Разработка интерактивного календаря для планирования записей — одна из наиболее частых задач при автоматизации медицинских центров, стоматологий, салонов красоты или автосервисов. Пользователям необходим удобный, быстрый и отзывчивый интерфейс, где можно буквально в один клик перетащить запись к другому врачу, изменить время приема или быстро оценить загрузку кабинетов. В этой статье мы подробно разберем, как решить эту задачу в среде 1С:Предприятие 8.3 (Управляемые формы), проанализируем штатные возможности платформы и альтернативные веб-технологии.
Начиная с версии платформы 8.3.5, разработчикам доступен готовый специализированный элемент управления — Планировщик. Это штатный объект, предназначенный специально для отображения и редактирования планов, графиков и расписаний в интерактивном режиме.
Рассмотрим по шагам, как настроить встроенный Планировщик на управляемой форме:
Планировщик. Перетащим его на панель элементов формы, чтобы он отобразился на экране.Проанализируем программный код инициализации и первоначальной настройки планировщика при создании формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Задаем интервал отображения (например, текущий рабочий день)
Элементы.КалендарьРасписания.ТекущийПериодОтображенияНачало = НачалоДня(ТекущаяДата());
Элементы.КалендарьРасписания.ТекущийПериодОтображенияКонец = КонецДня(ТекущаяДата());
// Настраиваем шкалу времени с шагом в 30 минут
Элементы.КалендарьРасписания.ШкалаВремени.Элементы.Очистить();
НовыйЭлементШкалы = Элементы.КалендарьРасписания.ШкалаВремени.Элементы.Добавить();
НовыйЭлементШкалы.ЕдиницаВремени = ЕдиницаВремени.Минута;
НовыйЭлементШкалы.Кратность = 30;
// Настраиваем рабочий интервал (например, с 08:00 до 20:00)
КалендарьРасписания.РабочееВремяНачало = '00010101080000';
КалендарьРасписания.РабочееВремяКонец = '00010101200000';
// Вызываем заполнение измерений (например, список врачей)
ЗаполнитьИзмеренияПланировщика();
// Загружаем записи из базы данных
ОбновитьРасписаниеНаСервере();
КонецПроцедуры
Теперь разберем, как добавить в планировщик колонки врачей. Измерения позволяют группировать календарную сетку вертикально или горизонтально:
&НаСервере
Процедура ЗаполнитьИзмеренияПланировщика()
// Очищаем старые измерения
КалендарьРасписания.Измерения.Очистить();
// Создаем новое измерение "Врачи"
ИзмерениеВрачи = КалендарьРасписания.Измерения.Добавить("Врач");
// Заполняем измерение элементами справочника "Сотрудники"
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Сотрудники.Ссылка КАК Ссылка,
| Сотрудники.Наименование КАК Наименование
|ИЗ
| Справочник.Сотрудники КАК Сотрудники
|ГДЕ
| НЕ Сотрудники.ПометкаУдаления";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
ЗначениеИзмерения = ИзмерениеВрачи.Значения.Добавить(Выборка.Ссылка, Выборка.Наименование);
КонецЦикла;
КонецПроцедуры
Для вывода самих записей на сетку календаря используется коллекция Элементы объекта Планировщик. Рассмотрим пример заполнения элементами:
&НаСервере
Процедура ОбновитьРасписаниеНаСервере()
КалендарьРасписания.Элементы.Очистить();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаписьНаПрием.Ссылка КАК Ссылка,
| ЗаписьНаПрием.Пациент.Наименование КАК ПациентНаименование,
| ЗаписьНаПрием.Врач КАК Врач,
| ЗаписьНаПрием.ДатаНачала КАК ДатаНачала,
| ЗаписьНаПрием.ДатаОкончания КАК ДатаОкончания
|ИЗ
| Документ.ЗаписьНаПрием КАК ЗаписьНаПрием
|ГДЕ
| ЗаписьНаПрием.Проведен";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Создаем элемент планировщика с указанием времени начала и окончания
НоваяЗапись = КалендарьРасписания.Элементы.Добавить(Выборка.ДатаНачала, Выборка.ДатаОкончания);
НоваяЗапись.Текст = Выборка.ПациентНаименование;
// Привязываем элемент к измерению "Врач"
НоваяЗапись.ЗначенияИзмерений.Вставить("Врач", Выборка.Врач);
// Сохраняем ссылку на документ для последующей интерактивной работы
НоваяЗапись.КлючСвязи = Выборка.Ссылка;
КонецЦикла;
КонецПроцедуры
Штатный планировщик полностью поддерживает технологию Drag-and-Drop. Пользователь может перетаскивать записи мышкой, менять их длительность, растягивая границы блоков. Чтобы обработать эти изменения и сохранить их в базе данных, нам нужно использовать интерактивные события элемента формы, такие как ПриИзмененииЭлемента.
Ограничения штатного планировщика: Несмотря на простоту внедрения, встроенный объект имеет ряд «подводных камней». В реальных медицинских центрах крайне важна детальная визуализация: индикаторы оплаты, статусы явки (опоздал, подтвердил, в кабинете), иконки типов приемов, группировки по кабинетам с контролем занятости оборудования. Настроить настолько сложный графический интерфейс средствами стандартного планировщика 1С бывает крайне сложно или вовсе невозможно из-за жестких ограничений платформенного рендеринга.
Если визуальные требования заказчика выходят за рамки возможностей стандартного планировщика, лучшим решением будет интеграция профессиональных JavaScript-календарей (например, FullCalendar.js или DHTMLX Scheduler) непосредственно в форму 1С.
Благодаря переходу современных версий платформы 1С 8.3 на современный движок рендеринга WebKit, мы получили полноценный доступ к современным стандартам веб-верстки. Схема взаимодействия строится на обмене данными между 1С и JavaScript через объект ПолеHTMLДокумента.
Рассмотрим по шагам архитектуру такого решения:
Проанализируем пример передачи данных в JS-библиотеку из 1С. Для сериализации данных в формат JSON воспользуемся встроенными средствами платформы:
&НаСервере
Функция ПолучитьДанныеЗаписейВФорматеJSON()
МассивЗаписей = Новый Массив;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Запись.Ссылка КАК ID,
| Запись.Пациент.Наименование КАК Title,
| Запись.ДатаНачала КАК StartDate,
| Запись.ДатаОкончания КАК EndDate,
| Запись.Врач КАК ResourceId
|ИЗ
| Документ.ЗаписьНаПрием КАК Запись";
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
СтруктураЗаписи = Новый Структура;
СтруктураЗаписи.Вставить("id", Строка(Выборка.ID.УникальныйИдентификатор()));
СтруктураЗаписи.Вставить("title", Выборка.Title);
// Форматируем даты в стандарт ISO для JavaScript
СтруктураЗаписи.Вставить("start", Формат(Выборка.StartDate, "ДФ=yyyy-MM-ddTHH:mm:ss"));
СтруктураЗаписи.Вставить("end", Формат(Выборка.EndDate, "ДФ=yyyy-MM-ddTHH:mm:ss"));
СтруктураЗаписи.Вставить("resourceId", Строка(Выборка.ResourceId.УникальныйИдентификатор()));
МассивЗаписей.Добавить(СтруктураЗаписи);
КонецЦикла;
// Сериализация в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, МассивЗаписей);
СтрокаJSON = ЗаписьJSON.Закрыть();
Возврат СтрокаJSON;
КонецФункции
Передадим полученную JSON-строку в наше поле HTML-документа на клиенте:
&НаКлиенте
Процедура ОбновитьКалендарьНаФорме()
ДанныеJSON = ПолучитьДанныеЗаписейВФорматеJSON();
// Вызов JavaScript-функции, определенной внутри нашего HTML-шаблона
Элементы.ПолеКалендаря.Документ.defaultView.loadAppointments(ДанныеJSON);
КонецПроцедуры
Для реализации обратной связи (из веб-интерфейса обратно в базу данных 1С) используется механизм обработки событий. В коде JavaScript при перетаскивании события (например, событие eventDrop в FullCalendar) вызывается специальный внутренний метод 1С:
// Пример JavaScript кода внутри HTML-макета
calendar.on('eventDrop', function(info) {
var eventData = {
id: info.event.id,
newStart: info.event.start.toISOString(),
newEnd: info.event.end.toISOString(),
newResource: info.event.getResources()[0] ? info.event.getResources()[0].id : ""
};
// Передаем данные в 1С
window.external.ВызватьСобытие1С("ИзменениеЗаписи", JSON.stringify(eventData));
});
В модуле управляемой формы 1С нам достаточно настроить событие ПриНажатии (или специализированный обработчик ожидания событий) для элемента ПолеHTMLДокумента, чтобы перехватить переданные параметры, выполнить необходимые проверки прав доступа и занятости оборудования на сервере, а затем перезаписать документ.
В старых конфигурациях 1С (особенно на обычных формах) расписания часто строили на базе обычного ТабличногоДокумента. Ячейки таблицы программно объединялись, раскрашивались, а текст выводился в области макета.
Рассмотрим, почему этот подход сегодня считается устаревшим:
Использовать ТабличныйДокумент для интерактивных календарей в современных конфигурациях крайне не рекомендуется. Его область применения сейчас — это исключительно печатные формы расписания врачей на день или неделю.
Выбор конкретного технического решения полностью зависит от требований вашего проекта:
Если перед вами стоит задача быстро (за 1-2 дня) внедрить базовую сетку расписания с возможностью интерактивного переноса записей, и при этом у заказчика нет жестких требований к уникальному дизайну интерфейса — смело используйте штатный платформенный Планировщик. Это надежное, быстрое решение, которое полностью поддерживается платформой из коробки и не требует от вас знания веб-технологий.
Если же вы разрабатываете тиражное решение для клиник, где интерфейс расписания является главным рабочим местом администратора (АРМ) и требует максимального удобства, интеграции с внешними сервисами, отображения сложных статусов и иконок — выбирайте связку Поле HTML-документа + FullCalendar.js. Этот подход потребует от вас базовых знаний HTML, CSS и JavaScript, но взамен предоставит неограниченные возможности по кастомизации интерфейса.