Перейти к содержимому

Интеграция 1С и соцсети Пульс от Т-Инвестиции

Интеграция 1С и Пульс Т-Банк - пошаговый пример

Цель написания данной заметки, показать как можно получить публикации авторов из социальной сети для инвесторов и трейдеров «Пульс». В которой, произошли изменения в показе ленты социальной сети, в результате чего, помимо тех авторов на которых подписан, стали появляться публикации от сторонних авторов, которые мне совершено не интересны.

На мой запрос, по возникшей ситуации, получил ответ от технической поддержки:

Интеграция 1С и соцсети Пульс от Т-Инвестиции - Ответ технической поддержки
Интеграция 1С и соцсети Пульс от Т-Инвестиции — Ответ технической поддержки

Значит придется разработать конфигурацию, которая будет получать публикации, только интересующих нас авторов.

1. Создание конфигурации.

Создаем пустую конфигурацию, в которую добавляем библиотеку Коннектор: удобный HTTP-клиент для 1С:Предприятие 8, для этого заходим на страницу по адресу https://github.com/vbondarevsky/Connector/releases и скачиваем файл конфигурации, на момент написания заметки, текущая версия Connector_v2.6.0.cf. С помощью меню «Файл — Открыть», открываем файл скаченной конфигурации «Коннектора» и переносим в свою конфигурацию общий модуль «КоннекторHTTP»:

Перенос общего модуля Коннектор HTTP
Перенос общего модуля Коннектор HTTP

2. Константы адресов.

В состав конфигурации добавим несколько констант, которые будут хранить адреса сервисов (API).

  1. «АдресСервисаПубликаций», тип «Строка», длина «100», которая будет хранить адрес сервиса получения публикаций.
  2. «АдресКэшаФайлов», тип «Строка», длина «100», которая будет хранить адрес сервиса получения изображений.
  3. «АдресКэшаАватаров», тип «Строка», длина «100», которая будет хранить адрес сервиса получения аватаров.

Интеграция 1С и соцсети Пульс от Т-Инвестиции - Константы адресов
Интеграция 1С и соцсети Пульс от Т-Инвестиции — Константы адресов


После добавления констант, запускаем пользовательский режим и заполняем их, для этого открываем «Сервис и настройки», далее «Функции для технического специалиста», ветка «Константы»:

  • «Адрес сервиса публикаций», указываем https://www.tbank.ru/api/invest-gw/social/v1/
  • «Адрес кэша файлов», указываем https://www.tbank.ru/api/invest-gw/social/file/v1/cache/post/image/
  • «Адрес кэша аватаров», указываем https://www.tbank.ru/api/invest-gw/social/file/v1/cache/profile/avatar/

Установка адреса сервиса
Установка адреса сервиса

Для работы с константами и получения адресов сервисов, добавляем в состав конфигурации общий модуль «ПубликацииСерверПовтИсп» с установленным свойством «Повторное использование возвращаемых значений» в значение «На время сеанса», код модуля:

#Область ПрограммныйИнтерфейс

Функция АдресСервисаПубликаций() Экспорт
	Возврат Константы.АдресСервисаПубликаций.Получить();	
КонецФункции

Функция АдресКэшаФайлов() Экспорт
	Возврат Константы.АдресКэшаФайлов.Получить();	
КонецФункции

Функция АдресКэшаАватаров() Экспорт
	Возврат Константы.АдресКэшаАватаров.Получить();	
КонецФункции

#КонецОбласти

3. Справочник «Авторы».

Для хранения информации об авторах, будет использоваться справочник «Авторы», для этого добавляем справочник в состав конфигурации, устанавливаем длину наименования 150 символов и добавляем реквизиты:

  • «Идентификатор», тип «Строка», длина 36 символов — для хранения уникального идентификатора автора.
  • «Аватар», тип «ХранилищеЗначений» — для хранения данных изображения.
  • «Описание», тип «Строка», длина 1000 символов — для хранения информации об авторе.
  • «ПозицияКурсора», тип «Число», длина 32 цифры — для хранения значения курсора.

Необходимо объяснить, что такое «Курсор» — это позиция начала, полученной порции данных, в зависимости от лимита (количество публикаций возвращаемых в запросе). С помощью этого значения, можно пролистывать ленту «вниз» и получать предыдущие порции публикаций, схематично, это выглядит так:

Интеграция 1С и соцсети Пульс от Т-Инвестиции - Курсор
Интеграция 1С и соцсети Пульс от Т-Инвестиции — Курсор

При запросе публикаций, система (Пульс) возвращает значение следующего курсора. Для получения «новых» публикаций используется значение курсора = 0, если необходимы «предыдущие» публикации, тогда курсор устанавливаем в значение полученное ранее, тем самым «двигаясь влево», по временной оси.

В справочнике «Авторы», добавляем форму элемента, с настройками расположения элементов по умолчанию, как предлагает конструктор формы. Посмотреть результат настройки внешнего вида формы, можно в прикрепленной к заметке конфигурации, так как описание, займет много времени, укажу лишь основные моменты:

  1. Добавлен реквизит формы «АдресАватара», тип строка, который перетаскиваем на форму и в свойстве элемента «Вид» установлено значение «Поле картинки».
  2. Добавляем команду «Получить данные», располагаем ее в командной панели формы и добавляем обработчик действия, со следующим кодом:
&НаКлиенте
Процедура ПолучитьДанные(Команда)
	
	Если ПроверитьЗаполнение() Тогда
		ПолучитьДанныеНаСервере();
	КонецЕсли;
	
КонецПроцедуры

&НаСервере
Процедура ПолучитьДанныеНаСервере()
	
	// Формируем адрес сервиса получения публикаций и данных автора.
	АдресСервисаПубликаций = ПубликацииСерверПовтИсп.АдресСервисаПубликаций();
	Адрес = СтрШаблон("%1profile/nickname/%2", АдресСервисаПубликаций, Объект.Наименование);

	// Запрашиваем данные в формате JSON.
	Ответ = КоннекторHTTP.GetJson(Адрес);
	Если НРег(Ответ["status"]) = "error" Тогда
		ВызватьИсключение Ответ["payload"]["message"];
	КонецЕсли;
	
	// Получение данных автора.
	Объект.Идентификатор = Ответ["payload"]["id"];
	Объект.Описание = Ответ["payload"]["description"];
	
	ИдентификаторИзображения = Ответ["payload"]["image"];
	
	// Формируем адрес сервиса получения данных изображения автора.
	АдресКэшаАватаров = ПубликацииСерверПовтИсп.АдресКэшаАватаров();
	Адрес = СтрШаблон("%1%2?size=original", АдресКэшаАватаров, ИдентификаторИзображения);
	
	// Запрашиваем данные аватара.
	Ответ = КоннекторHTTP.Get(Адрес);
	Если Ответ.КодСостояния <> 200 Тогда
		ВызватьИсключение СтрШаблон("%1: %2", "Не удалось получить изображение аватара", Адрес);	
	КонецЕсли;

	// Помещаем двоичные данные аватара во временное хранилище.
	ДвоичныеДанныеАватара = Ответ.Тело; 
	АдресАватара = ПоместитьВоВременноеХранилище(ДвоичныеДанныеАватара, УникальныйИдентификатор);
	
	Модифицированность = Истина;
	
КонецПроцедуры

Для формы элемента справочника «Авторы», добавляем два события «ПриСозданииНаСервере» и «ПередЗаписьюНаСервере», со следующим кодом:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	АдресАватара = ПолучитьНавигационнуюСсылку(Объект.Ссылка, "Аватар");
	
КонецПроцедуры

&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
	
	Если ЭтоАдресВременногоХранилища(АдресАватара) Тогда
		
		Данные = ПолучитьИзВременногоХранилища(АдресАватара);
		ТекущийОбъект.Аватар = Новый ХранилищеЗначения(Данные, Новый СжатиеДанных(9));	
		
		УдалитьИзВременногоХранилища(АдресАватара);
		
	КонецЕсли;
	
КонецПроцедуры

Для начального получения данных автора, необходимо правильно указать его никнейм, в поле «Наименование» и нажать кнопку «Получить данные»:

Интеграция 1С и соцсети Пульс от Т-Инвестиции - Справочник Авторы
Интеграция 1С и соцсети Пульс от Т-Инвестиции — Справочник Авторы

4. Регистры сведений «Публикации» и «Изображения».

Для хранения и отображения списка публикаций (ленты) будет использоваться непериодический, независимый, регистр сведений «Публикации», со следующими данными:

Измерения:

  • «Идентификатор», тип «Строка», длина 36 символов, для хранения идентификатора публикации.
  • «Дата», тип «Дата», состав даты «Дата и время», для хранения даты публикации.
  • «Автор», тип «СправочникСсылка.Авторы», для хранения ссылки на автора публикации.

Ресурс:

  • «Текст», тип «Строка», включена опция «Строка неограниченной длины», для хранения текста публикации.

Для хранения изображений публикаций, будет использоваться непериодический, независимый, регистр сведений «Изображения», со следующими данными:

Измерения:

  • «ИдентификаторПубликации», тип «Строка», длина 36 символов, для хранения идентификатора публикации.
  • «ИдентификаторИзображения», тип «Строка», длина 36 символов, для хранения идентификатора изображения.

Ресурс:

  • «Изображение», тип «ХранилищеЗначений» — для хранения данных изображения.

Добавляем форму списка регистра сведений «Публикации», которую для удобства, размещаем в составе начальной страницы конфигурации, как это сделать описано в заметках «Сериализация данных с помощью файловых потоков 1С» и «График выплат купонов и дивидендов».

В форме списка регистра сведений «Публикации», добавляем реквизит формы «ИдентификаторыЗаданий», тип «СписокЗначений», для хранения идентификаторов фоновых заданий, в рамках которых будет производится получение новых публикаций. Этот список нужен для обработчика ожидания, в котором будут проверятся активные фоновые задания и когда они все завершаться, можно будет обновить динамический список.

В форме списка регистра сведений «Публикации», нужно добавить команду «ПолучитьПубликации» и разместить в командной панели формы, далее добавить к ней обработчик и следующий код:

&НаКлиенте
Процедура ПолучитьПубликации(Команда)
	
	ИдентификаторыЗаданий = ПолучитьПубликацииНаСервере(); 
	
	// Если имеются запущенные фоновые задания, тогда включаем обработчик ожидания.
	Если ИдентификаторыЗаданий.Количество() Тогда       
		Элементы.ФормаПолучитьПубликации.Доступность = Ложь;
		ПодключитьОбработчикОжидания("Подключаемый_ОжиданиеФоновыхЗаданий", 1);
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьПубликацииНаСервере()

	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	Авторы.Ссылка КАК Ссылка,
		|	Авторы.Идентификатор КАК Идентификатор,
		|	Авторы.ПозицияКурсора КАК ПозицияКурсора
		|ИЗ
		|	Справочник.Авторы КАК Авторы
		|ГДЕ
		|	НЕ Авторы.ПометкаУдаления";
	
	РезультатЗапроса = Запрос.Выполнить();
	Если РезультатЗапроса.Пустой() Тогда
		ВызватьИсключение "Отсутствуют элементы в справочнике ""Авторы.""";
	КонецЕсли;
	
	Выборка = РезультатЗапроса.Выбрать();
	
	// Параметры многопоточного получения данных.
	КоличествоПотоков = 6;
	КоличествоАвторов = Выборка.Количество(); 
	
	// Определяем размер порции данных для одного потока.
	РазмерПорции = Окр(КоличествоАвторов / КоличествоПотоков);
	РазмерПорции = РазмерПорции + ?(КоличествоАвторов % КоличествоПотоков, 1, 0);
	
	// Массив, элементами которого являются структуры данных автора.
	ПорцияДанных = Новый Массив;
	
	НомерПотока = 1; 
	ЭтоПоследнийПоток = Ложь;
	
	ИдентификаторыЗаданий = Новый СписокЗначений;
	
	Пока Выборка.Следующий() Цикл
		
		// Структура данных автора.
		ЭлементДанных = Новый Структура("Ссылка, Идентификатор, ПозицияКурсора");
		ЗаполнитьЗначенияСвойств(ЭлементДанных, Выборка);
		
		ПорцияДанных.Добавить(ЭлементДанных);
		
		// Определение запуска фонового задания, в зависимости от наполнения порции данных.
		Если ПорцияДанных.Количество() = РазмерПорции 
			ИЛИ ЭтоПоследнийПоток И ПорцияДанных.Количество() = (КоличествоАвторов - ((КоличествоПотоков - 1) * РазмерПорции)) Тогда
			
			ПараметрыЗадания = Новый Массив;
			ПараметрыЗадания.Добавить(ПорцияДанных);
			
			// Передаем порцию данных в фоновое задание и запускаем его.
			Задание = ФоновыеЗадания.Выполнить("ПубликацииСервер.ПолучитьДанные", ПараметрыЗадания);
			ИдентификаторыЗаданий.Добавить(Задание.УникальныйИдентификатор);
			
			ПорцияДанных.Очистить();
			
			НомерПотока = НомерПотока + 1;
			ЭтоПоследнийПоток = НомерПотока = КоличествоПотоков; 
		
		КонецЕсли;
		
	КонецЦикла;
	
	// Возвращаем список идентификаторов фоновых заданий.
	Возврат ИдентификаторыЗаданий;
	
КонецФункции

Код по работе с обработчиком ожидания:

&НаКлиенте
Процедура Подключаемый_ОжиданиеФоновыхЗаданий()
	
	Если ИдентификаторыЗаданий.Количество() = 0 Тогда
		
		// Активных заданий нет, обработчик можно отключить.
		ОтключитьОбработчикОжидания("Подключаемый_ОжиданиеФоновыхЗаданий");
		
		// После выполнения всех фоновых заданий обновляем список.
		Элементы.Список.Обновить();
		ПоказатьОповещениеПользователя("Получить публикации", , "Список обновлен", БиблиотекаКартинок.ДиалогИнформация);
		Элементы.ФормаПолучитьПубликации.Доступность = Истина;
		Возврат;
		
	КонецЕсли;
	
	СписокДляУдаления = Новый Массив;
	
	Для каждого ИдентификаторЗадания Из ИдентификаторыЗаданий Цикл
		
		// Проверяем активность заданий.
		Если НЕ ЗаданиеАктивно(ИдентификаторЗадания.Значение) Тогда
			СписокДляУдаления.Добавить(ИдентификаторЗадания);
		КонецЕсли;
		
	КонецЦикла;
	
	// Удаляем не активные задания.
	Если СписокДляУдаления.Количество() Тогда
		Для каждого ЗаданиеНаУдаление Из СписокДляУдаления Цикл
			ИдентификаторыЗаданий.Удалить(ЗаданиеНаУдаление);
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ЗаданиеАктивно(ИдентификаторЗадания) 
	
	НайденноеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
	Если НайденноеЗадание = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;
	
	Возврат НайденноеЗадание.Состояние = СостояниеФоновогоЗадания.Активно;
	
КонецФункции

Для выполнения фонового задания, добавляем общий модуль «ПубликацииСервер» и реализуем код фонового задания:

Процедура ПолучитьДанные(ПорцияДанных) Экспорт 
	
	АдресСервисаПубликаций = ПубликацииСерверПовтИсп.АдресСервисаПубликаций();
	АдресКэшаФайлов = ПубликацииСерверПовтИсп.АдресКэшаФайлов();
	
	Для каждого ЭлементДанных Из ПорцияДанных Цикл
		
		Автор = ЭлементДанных.Ссылка; 
		ИдентификаторАвтора = ЭлементДанных.Идентификатор;
		ПозицияКурсора = ЭлементДанных.ПозицияКурсора;
		
		АдресЗапросаПубликаций = СтрШаблон("%1profile/%2/post", АдресСервисаПубликаций, ИдентификаторАвтора); 
		
		ПараметрыЗапроса = Новый Структура;
		ПараметрыЗапроса.Вставить("limit", 30); 
		ПараметрыЗапроса.Вставить("cursor", Формат(0, "ЧГ=0"));
		
		ПараметрыПреобразованияJSON = Новый Структура;
		ПараметрыПреобразованияJSON.Вставить("ИменаСвойствСоЗначениямиДата", "inserted");
		
		ДополнительныеПараметры = Новый Структура("ПараметрыПреобразованияJSON", ПараметрыПреобразованияJSON);
		
		ОтветЗапросаПубликаций = КоннекторHTTP.GetJson(АдресЗапросаПубликаций, ПараметрыЗапроса, ДополнительныеПараметры);
		Если НРег(ОтветЗапросаПубликаций["status"]) = "error" Тогда
			ЗаписьЖурналаРегистрации("Пульс", УровеньЖурналаРегистрации.Ошибка, Метаданные.Справочники.Авторы, Автор, ОтветЗапросаПубликаций["payload"]["message"]);		
			Продолжить;
		КонецЕсли;  
		
		// Полученный курсор используется для определения наличия новых публикаций.
		СледующийКурсор = ОтветЗапросаПубликаций["payload"]["nextCursor"];
		Если ПозицияКурсора = СледующийКурсор Тогда
			ЗаписьЖурналаРегистрации("Пульс", УровеньЖурналаРегистрации.Информация, Метаданные.Справочники.Авторы, Автор, "Новых публикаций нет.");		
			Продолжить;
		КонецЕсли;
		
		ИдентификаторыПубликаций = Новый Массив;
		
		Публикации = ОтветЗапросаПубликаций["payload"]["items"];
		Для каждого Публикация Из Публикации Цикл
			ИдентификаторыПубликаций.Добавить(Публикация["id"]);
		КонецЦикла;    
		
		// Определяем "новые" публикации – это публикации которых нет в регистре.
		Запрос = Новый Запрос;
		Запрос.Текст = 
			"ВЫБРАТЬ
			|	Публикации.Идентификатор КАК Идентификатор
			|ИЗ
			|	РегистрСведений.Публикации КАК Публикации
			|ГДЕ
			|	Публикации.Идентификатор В(&ИдентификаторыПубликаций)";
		
		Запрос.УстановитьПараметр("ИдентификаторыПубликаций", ИдентификаторыПубликаций);
		
		РезультатЗапроса = Запрос.Выполнить(); 
		Если РезультатЗапроса.Пустой() Тогда
			// Если результат пустой, значит все публикации "новые".
		Иначе	
			
			Выборка = РезультатЗапроса.Выбрать();
			Пока Выборка.Следующий() Цикл 
				// Из массива удаляется ранее полученная публикация.
				УдалитьВсеВхожденияЗначенияИзМассива(ИдентификаторыПубликаций, Выборка.Идентификатор);
			КонецЦикла;
		
		КонецЕсли;
		
		НаборЗаписейПубликации = РегистрыСведений.Публикации.СоздатьНаборЗаписей();
		
		Для каждого Публикация Из Публикации Цикл
			
			ИдентификаторПубликации = Публикация["id"];
			
			// Массив ИдентификаторыПубликаций содержит только "новые" публикации. 
			Если ИдентификаторыПубликаций.Найти(ИдентификаторПубликации) = Неопределено Тогда
				// Если не нашли идентификатор, значит это ранее полученная публикация. 
				Продолжить;
			КонецЕсли;
			
			ЗаписьПубликации = НаборЗаписейПубликации.Добавить();
			ЗаписьПубликации.Идентификатор = ИдентификаторПубликации;
			ЗаписьПубликации.Дата = Публикация["inserted"];
			ЗаписьПубликации.Автор = Автор;
			ЗаписьПубликации.Текст = Публикация["text"];
			
			#Область ИзображенияПубликации
			
			// В зависимости от типа публикации, изображения хранятся по-разному.
			ТипПубликации = НРег(Публикация["content"]["type"]);
			Если ТипПубликации = "simple" Тогда
				
				Изображения = Публикация["content"]["images"];
			
			ИначеЕсли ТипПубликации = "news" Тогда	
				
				Изображения = Публикация["content"]["headerImage"];
				
			КонецЕсли;
			
			// Сохранение изображений публикации.
			Для каждого Изображение Из Изображения Цикл
				
				Если ТипПубликации = "simple" Тогда       
					
					ИдентификаторИзображения = Изображение["id"];
					АдресИзображения = СтрШаблон("%1%2?size=original", АдресКэшаФайлов, ИдентификаторИзображения);
					
				ИначеЕсли ТипПубликации = "news" Тогда	
					
					// Временное решение, использовать новый идентификатор.
					ИдентификаторИзображения = XMLСтрока(Новый УникальныйИдентификатор);
					АдресИзображения = Изображение.Значение;
				
				КонецЕсли;
				
				// Запрашиваем данные изображения.
				ОтветЗапросаИзображения = КоннекторHTTP.Get(АдресИзображения);
				Если ОтветЗапросаИзображения.КодСостояния <> 200 Тогда
					ТекстОшибки = СтрШаблон("%1: %2", "Не удалось получить изображение", АдресИзображения);
					ЗаписьЖурналаРегистрации("Пульс", УровеньЖурналаРегистрации.Ошибка, Метаданные.РегистрыСведений.Изображения, ИдентификаторИзображения, ТекстОшибки);
					Продолжить;
				КонецЕсли;
				
				// Помещаем двоичные данные изображения.
				ДвоичныеДанныеИзображения = ОтветЗапросаИзображения.Тело; 
				
				НаборЗаписейИзображения = РегистрыСведений.Изображения.СоздатьНаборЗаписей();
				
				ЗаписьИзображения = НаборЗаписейИзображения.Добавить();
				ЗаписьИзображения.ИдентификаторПубликации = ИдентификаторПубликации;
				ЗаписьИзображения.ИдентификаторИзображения = ИдентификаторИзображения;
				ЗаписьИзображения.Изображение = Новый ХранилищеЗначения(ДвоичныеДанныеИзображения, Новый СжатиеДанных(9));
				
				Попытка
					НаборЗаписейИзображения.Записать(Ложь);
				Исключение
					ЗаписьЖурналаРегистрации("Пульс", УровеньЖурналаРегистрации.Ошибка, Метаданные.РегистрыСведений.Изображения, ИдентификаторИзображения, ОписаниеОшибки());
				КонецПопытки;
				
			КонецЦикла;
			
			#КонецОбласти
			
		КонецЦикла;
		
		// Добавление новых публикаций в регистр сведений. 
		Попытка
			НаборЗаписейПубликации.Записать(Ложь);
		Исключение
			ЗаписьЖурналаРегистрации("Пульс", УровеньЖурналаРегистрации.Ошибка, Метаданные.РегистрыСведений.Публикации, Автор, ОписаниеОшибки());		
		КонецПопытки;
		
		// Сохранения полученной позиции курсора.
		ОбъектСправочникаАвтор = Автор.ПолучитьОбъект();
		ОбъектСправочникаАвтор.ПозицияКурсора = СледующийКурсор;
		Попытка
			ОбъектСправочникаАвтор.Записать();
		Исключение
			ЗаписьЖурналаРегистрации("Пульс", УровеньЖурналаРегистрации.Ошибка, Метаданные.Справочники.Авторы, Автор, ОписаниеОшибки());
		КонецПопытки;
		
	КонецЦикла;              
		
КонецПроцедуры

// Взято из БСП, модуль "ОбщегоНазначенияКлиентСервер".
//
// Удаляет все вхождения переданного значения из массива.
//
// Параметры:
//  Массив - Массив - массив, из которого необходимо удалить значение;
//  Значение - Произвольный - удаляемое значение из массива.
// 
Процедура УдалитьВсеВхожденияЗначенияИзМассива(Массив, Значение) Экспорт
	
	КоличествоЭлементовКоллекции = Массив.Количество();
	
	Для ОбратныйИндекс = 1 По КоличествоЭлементовКоллекции Цикл
		
		Индекс = КоличествоЭлементовКоллекции - ОбратныйИндекс;
		
		Если Массив[Индекс] = Значение Тогда
			
			Массив.Удалить(Индекс);
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецПроцедуры

Пояснение:
Когда нажимаем кнопку «ПолучитьПубликации», запросом выбираются авторы, в зависимости от их количества и установленного количества потоков, рассчитывается порция данных, то есть сколько авторов будут обрабатываться в одном фоновом задании. После расчета, создаются фоновые задания, в которые передаются данные авторов, при этом запускается обработчик ожидания, который раз в 1 секунду проверяет активность заданий, чтобы после их завершения выполнить обновление динамического списка.
В фоновом задании, для каждого автора, происходит получение публикаций, лимит равен 30. Полученные публикации проверяются на наличие новых, которых нет в регистре сведений «Публикации». Дополнительно, в зависимости от типа публикации происходит получение изображений и последующее их сохранение в регистр сведений «Изображения». Код не везде оптимальный и требует местами рефакторинга, но для ознакомительных целей заметки сгодится.

5. Показ публикаций.

Теперь необходимо сделать показ текста и изображений публикации, будет использоваться вывод в HTML. В форме списка регистра сведений «Публикации», добавить реквизит формы «Публикация», тип «Строка» и перенести на форму, в свойстве «Вид», элемента реквизита формы, изменить значение на «Поле HTML документа».

При клике на строке динамического списка, будет происходить показ выбранной публикации. Устанавливаем для поля «Идентификатор», реквизита «Список», опцию «Использовать всегда»:

Идентификатор - Использовать всегда
Идентификатор — Использовать всегда

Для списка формы добавляем обработчик события «ПриАктивизацииСтроки» и следующий код:

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
	
	ТекущиеДанные = Элементы.Список.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Текст = ТекущиеДанные.Текст;
	ИзображенияПубликации = ИзображенияПубликации(ТекущиеДанные.Идентификатор);
		
	КодСтраницы = 
		"<!DOCTYPE html>
		|<html lang=""ru"">
		|<head>
		|	<meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"">
		|	<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
		|	<title>Post</title>
		|</head>
		|<body>
		|	<main>%1</main>
		|	<footer>%2</footer>
		|</body>
		|</html>";
	
	Публикация = СтрШаблон(КодСтраницы, Текст, ИзображенияПубликации); 
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ИзображенияПубликации(ИдентификаторПубликации)

	ИзображенияПубликации = "";
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	Изображения.Изображение КАК Изображение
		|ИЗ
		|	РегистрСведений.Изображения КАК Изображения
		|ГДЕ
		|	Изображения.ИдентификаторПубликации = &ИдентификаторПубликации";
	
	Запрос.УстановитьПараметр("ИдентификаторПубликации", ИдентификаторПубликации);
	
	РезультатЗапроса = Запрос.Выполнить();
	Если РезультатЗапроса.Пустой() Тогда
		Возврат ИзображенияПубликации;
	КонецЕсли;
	
	Выборка = РезультатЗапроса.Выбрать();
	Пока Выборка.Следующий() Цикл
		
		ДвоичныеДанныеИзображения = Выборка.Изображение.Получить();
		Base64ДанныеИзображения = Base64Строка(ДвоичныеДанныеИзображения);
		
		ИзображенияПубликации = ИзображенияПубликации + "<img src='data:image/;base64," + Base64ДанныеИзображения + "' width=""99%"">";
		ИзображенияПубликации = ИзображенияПубликации + "<br />";
		
	КонецЦикла;
	
	Возврат ИзображенияПубликации;

КонецФункции

Пояснение:
При активизации строки, читаем идентификатор публикации, с помощью которого из регистра сведений «Изображения», получаем изображения и формируем HTML код для отображения страницы.

Итог.

Теперь базовый функционал конфигурации для чтения сообщений из социальной сети для инвесторов и трейдеров «Пульс» готов. Повторюсь, что местами код не оптимальный и необходим рефакторинг, но думаю, что для заинтересованного читателя не составит труда, доделать конфигурацию под свои нужды. Например, можно использовать оповещение клиента с сервера, а не обработчик ожидания, вынести код из модулей формы в общие модули или менеджеры объектов, так же, изменить код фонового задания, для более наглядной обработки публикации в зависимости от ее типа. Ну и конечно, продумать хранение изображений и добавить вывод информации о работе активных фоновых заданий, так как сейчас приходится смотреть журнал регистрации на наличие событий.

Дополнительная информация:

Метки:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *