# Паттерны компоновки управляемых форм Рекомендации по дизайну форм, извлечённые из типовых конфигураций 1С. Используйте при создании форм через `/form-compile`, когда требования пользователя не детализируют расположение элементов. ## Архетипы форм ### Форма документа ``` Шапка (horizontal, 2 колонки) ├─ Левая (vertical): НомерДата (H: Номер + Дата "от"), Контрагент, Договор ├─ Правая (vertical): Организация, Подразделение, ЦеныИВалюта (надпись-ссылка) Страницы (pages) ├─ Товары: таблица Объект.Товары ├─ Услуги: таблица Объект.Услуги (опционально) └─ Дополнительно: прочие реквизиты Подвал (vertical) ├─ Итоги (horizontal): Всего, НДС, Скидка └─ КомментарийОтветственный (horizontal): Комментарий + Ответственный ``` **Типичные события:** OnCreateAtServer, OnReadAtServer, OnOpen, BeforeWriteAtServer, AfterWriteAtServer, AfterWrite, NotificationProcessing **Свойства:** autoTitle=false, командная панель со стандартными + глобальными командами ### Форма обработки (DataProcessor) ``` Параметры (vertical) ├─ Группа полей ввода (Организация, Период, режимы работы) ├─ Информационные надписи (label, hyperlink) Рабочая область ├─ Таблица данных или Pages с вкладками Кнопки действий ├─ Выполнить / Применить (defaultButton) ├─ Закрыть (stdCommand: Close) ``` **Типичные события:** OnCreateAtServer, OnOpen, NotificationProcessing **Свойства:** windowOpeningMode=LockOwnerWindow (если диалог), autoTitle=false ### Форма списка ``` Отборы (group: alwaysHorizontal) ├─ ГруппаОтбор[Поле] (H): Флажок + Поле ввода (для каждого фильтра) Список (table, DynamicList) ├─ Колонки: labelField (не input — данные только для чтения) ``` **Типичные события:** OnCreateAtServer, OnOpen, NotificationProcessing, OnLoadDataFromSettingsAtServer **Свойства:** autoSaveDataInSettings=Use (запомнить отборы) **Фильтры:** пара реквизитов на каждый фильтр — `Отбор[Поле]` (значение) + `Отбор[Поле]Использование` (boolean, флажок вкл/выкл) ### Форма элемента справочника **Простая:** ``` ГруппаРеквизитов (horizontal) ├─ Наименование -> Объект.Description └─ Код -> Объект.Code (если нужен) ``` **Сложная:** ``` Главное (vertical) ├─ Наименование -> Объект.Description ├─ Параметры (horizontal, 2 колонки) │ ├─ Левая: основные реквизиты │ └─ Правая: дополнительные реквизиты └─ КонтактныеДанные / Дополнительно (vertical) ``` **Типичные события:** OnCreateAtServer, OnReadAtServer, BeforeWriteAtServer, NotificationProcessing ### Мастер (Wizard) ``` Страницы (pages, OnCurrentPageChange) ├─ Шаг1: описание + параметры ├─ Шаг2: основная работа └─ Шаг3: результат Кнопки (horizontal) ├─ Назад (command), Далее (command, defaultButton), Выполнить (command) └─ Закрыть (stdCommand: Close) ``` **Свойства:** windowOpeningMode=LockOwnerWindow ## Конвенции именования ### Группы | Назначение | Имя | Тип | |-----------|-----|-----| | Шапка | `ГруппаШапка` | horizontal | | Левая колонка | `ГруппаШапкаЛевая` | vertical | | Правая колонка | `ГруппаШапкаПравая` | vertical | | Номер+Дата | `ГруппаНомерДата` | horizontal | | Подвал | `ГруппаПодвал` | vertical | | Итоги | `ГруппаИтоги` | horizontal | | Кнопки | `ГруппаКнопок` | horizontal | | Страницы | `ГруппаСтраницы` / `Страницы` | pages | | Предупреждение | `ГруппаПредупреждение` | horizontal, visible:false | | Доп. секция | `ГруппаДополнительно` / `ГруппаПрочее` | vertical, collapse | ### Элементы | Назначение | Имя | Суффикс | |-----------|-----|---------| | Поле в таблице | `[Таблица][Поле]` | — | | Итог | `Итоги[Поле]` | — | | Надпись-ссылка | `[Поле]Надпись` | — | | Фильтр | `Отбор[Поле]` | — | | Флажок фильтра | `Отбор[Поле]Использование` | — | | Кнопка команды | `[Команда]Кнопка` | — | | Баннер-картинка | `[Баннер]Картинка` | — | | Баннер-надпись | `[Баннер]Надпись` | — | | Подменю | `Подменю[Действие]` | — | ### Обработчики событий Имя обработчика = имя элемента + суффикс события на русском: | Событие | Суффикс | Пример | |---------|---------|--------| | OnChange | ПриИзменении | `ОрганизацияПриИзменении` | | StartChoice | НачалоВыбора | `КонтрагентНачалоВыбора` | | Click | Нажатие | `ЦеныИВалютаНажатие` | | OnEditEnd | ПриОкончанииРедактирования | `ТоварыПриОкончанииРедактирования` | | OnStartEdit | ПриНачалеРедактирования | `ТоварыПриНачалеРедактирования` | Обработчики формы — стандартные имена: `ПриСозданииНаСервере`, `ПриОткрытии`, `ПередЗакрытием`, `ОбработкаОповещения`. ## Принципы компоновки 1. **Порядок чтения.** Сверху вниз, слева направо. Самое важное — вверху. 2. **Двухколоночная шапка.** Основные реквизиты слева (контрагент, склад), организационные справа (организация, подразделение). 3. **Кнопки действий внизу.** Главная кнопка — `defaultButton: true`. Закрыть — всегда последняя. 4. **Таблицы — основная область.** Табличные части занимают большую часть формы, обычно на Pages. 5. **Итоги рядом с таблицей.** В подвале, горизонтальная группа, все поля readOnly. 6. **Фильтры — отдельная зона.** Над списком, горизонтальная группа (alwaysHorizontal), пара "флажок + поле" на каждый фильтр. 7. **Скрытые элементы для состояний.** Баннеры, предупреждения — `visible: false` по умолчанию, показываются программно. 8. **Надписи-ссылки для диалогов.** `labelField` с `hyperlink: true` и событием Click — для открытия подформ (ЦеныИВалюта, УчётнаяПолитика). ## Продвинутые паттерны (ERP) Извлечены из конфигурации «Управление предприятием» (ERP 8.3.24). Применяйте в сложных формах. ### Сворачиваемые группы (Collapsible) Для необязательных секций — «Подписи», «Дополнительно», «Прочее». Сворачиваются по умолчанию, экономят место. ``` ГруппаПодписи (vertical, collapse, collapsed) ├─ Руководитель -> Объект.Руководитель └─ ГлавныйБухгалтер -> Объект.ГлавныйБухгалтер ``` DSL: ```json { "group": "vertical", "name": "ГруппаПодписи", "title": "Подписи", "behavior": "Collapsible", "collapsed": true, "children": [ { "input": "Руководитель", "path": "Объект.Руководитель" }, { "input": "ГлавныйБухгалтер", "path": "Объект.ГлавныйБухгалтер" } ]} ``` ### Баннер-предупреждение (Status Banner) Группа «картинка + надпись» без заголовка, скрыта по умолчанию. Показывается программно при определённых условиях (просрочка, блокировка, информация). ``` ГруппаПредупреждение (horizontal, showTitle:false, visible:false) ├─ [Picture] ПредупреждениеКартинка -> StdPicture.Information └─ [Label] ПредупреждениеНадпись (maxWidth:76, textColor:style:ПоясняющийТекст) ``` DSL: ```json { "group": "horizontal", "name": "ГруппаПредупреждение", "showTitle": false, "visible": false, "children": [ { "picture": "ПредупреждениеКартинка" }, { "label": "ПредупреждениеНадпись", "title": "Текст предупреждения", "maxWidth": 76, "autoMaxWidth": false } ]} ``` ### Выпадающее меню в командной панели (Popup) Группировка связанных команд (печать, отправка, выгрузка) в одну кнопку-меню с иконкой. ``` [CmdBar] КоманднаяПанель ├─ [Popup] ПодменюПечать (picture: StdPicture.Print, representation: Picture) │ ├─ [Button] ПечатьНакладная -> Печать [cmd] │ └─ [Button] ПечатьСчёт -> ПечатьСчёт [cmd] └─ [Popup] ПодменюОтправить (picture: StdPicture.SendByEmail) └─ [Button] ОтправитьПоПочте -> Отправить [cmd] ``` DSL: ```json { "cmdBar": "КоманднаяПанель", "children": [ { "popup": "ПодменюПечать", "title": "Печать", "picture": "StdPicture.Print", "representation": "Picture", "children": [ { "button": "ПечатьНакладная", "command": "Печать" }, { "button": "ПечатьСчёт", "command": "ПечатьСчёт" } ]}, { "popup": "ПодменюОтправить", "title": "Отправить", "picture": "StdPicture.SendByEmail", "representation": "Picture", "children": [ { "button": "ОтправитьПоПочте", "command": "Отправить" } ]} ]} ``` ### Форма без стандартной командной панели Для модальных диалогов и мастеров — отключение стандартной командной панели, полностью ручное управление кнопками. ``` properties: commandBarLocation=None, windowOpeningMode=LockWholeInterface Содержимое (vertical) ├─ ... рабочая область ... ГруппаКнопок (horizontal) ├─ Назад (command), Далее (command, defaultButton) └─ Закрыть (stdCommand: Close) ``` DSL: ```json { "properties": { "commandBarLocation": "None", "windowOpeningMode": "LockWholeInterface" }, "elements": [ { "group": "vertical", "name": "Содержимое", "children": [ "..." ] }, { "group": "horizontal", "name": "ГруппаКнопок", "children": [ { "button": "Назад", "command": "Назад" }, { "button": "Далее", "command": "Далее", "defaultButton": true }, { "button": "Закрыть", "stdCommand": "Close" } ]} ] } ``` ### Надпись-гиперссылка для открытия подформ `labelField` с `hyperlink: true` и событием Click — вместо кнопки. Типичный приём для «ЦеныИВалюта», «УчётнаяПолитика» и подобных. ``` [LabelField] ЦеныИВалютаНадпись -> ЦеныИВалюта (hyperlink) {Click} ``` DSL: ```json { "labelField": "ЦеныИВалютаНадпись", "path": "ЦеныИВалюта", "hyperlink": true, "on": ["Click"] } ``` ## Примеры DSL ### Типичная форма обработки ```json { "title": "Загрузка данных из CSV", "properties": { "autoTitle": false, "windowOpeningMode": "LockOwnerWindow" }, "events": { "OnCreateAtServer": "ПриСозданииНаСервере" }, "elements": [ { "group": "vertical", "name": "ГруппаПараметры", "children": [ { "input": "ФайлЗагрузки", "path": "ФайлЗагрузки", "title": "Файл", "clearButton": true, "horizontalStretch": true, "on": ["StartChoice"] }, { "input": "Кодировка", "path": "Кодировка", "title": "Кодировка" }, { "input": "Разделитель", "path": "Разделитель", "title": "Разделитель колонок" } ]}, { "table": "Данные", "path": "Объект.Данные", "on": ["OnStartEdit"], "columns": [ { "input": "ДанныеНомерСтроки", "path": "Объект.Данные.LineNumber", "readOnly": true, "title": "№" }, { "input": "ДанныеНаименование", "path": "Объект.Данные.Наименование" }, { "input": "ДанныеКоличество", "path": "Объект.Данные.Количество", "on": ["OnChange"] }, { "input": "ДанныеСумма", "path": "Объект.Данные.Сумма", "readOnly": true } ]}, { "group": "horizontal", "name": "ГруппаКнопок", "children": [ { "button": "Загрузить", "command": "Загрузить", "title": "Загрузить из файла", "defaultButton": true }, { "button": "Очистить", "command": "Очистить", "title": "Очистить таблицу" }, { "button": "Закрыть", "stdCommand": "Close" } ]} ], "attributes": [ { "name": "Объект", "type": "ExternalDataProcessorObject.ЗагрузкаИзCSV", "main": true }, { "name": "ФайлЗагрузки", "type": "string" }, { "name": "Кодировка", "type": "string(20)" }, { "name": "Разделитель", "type": "string(5)" } ], "commands": [ { "name": "Загрузить", "action": "ЗагрузитьОбработка" }, { "name": "Очистить", "action": "ОчиститьОбработка" } ] } ``` ### Типичная форма со списком и фильтрами ```json { "properties": { "autoTitle": false, "autoSaveDataInSettings": "Use" }, "events": { "OnCreateAtServer": "ПриСозданииНаСервере", "NotificationProcessing": "ОбработкаОповещения" }, "elements": [ { "group": "alwaysHorizontal", "name": "ГруппаОтборы", "children": [ { "group": "horizontal", "name": "ГруппаОтборОрганизация", "children": [ { "check": "ОтборОрганизацияИспользование", "path": "ОтборОрганизацияИспользование", "titleLocation": "none", "on": ["OnChange"] }, { "input": "ОтборОрганизация", "path": "ОтборОрганизация", "title": "Организация", "on": ["OnChange"] } ]}, { "group": "horizontal", "name": "ГруппаОтборКонтрагент", "children": [ { "check": "ОтборКонтрагентИспользование", "path": "ОтборКонтрагентИспользование", "titleLocation": "none", "on": ["OnChange"] }, { "input": "ОтборКонтрагент", "path": "ОтборКонтрагент", "title": "Контрагент", "on": ["OnChange"] } ]} ]}, { "table": "Список", "path": "Список", "on": ["Selection", "OnActivateRow"], "columns": [ { "labelField": "СписокДата", "path": "Список.Дата", "title": "Дата" }, { "labelField": "СписокНомер", "path": "Список.Номер", "title": "Номер" }, { "labelField": "СписокКонтрагент", "path": "Список.Контрагент" }, { "labelField": "СписокСумма", "path": "Список.Сумма" } ]} ], "attributes": [ { "name": "Список", "type": "DynamicList", "mainTable": "Document.РеализацияТоваров" }, { "name": "ОтборОрганизация", "type": "CatalogRef.Организации" }, { "name": "ОтборОрганизацияИспользование", "type": "boolean" }, { "name": "ОтборКонтрагент", "type": "CatalogRef.Контрагенты" }, { "name": "ОтборКонтрагентИспользование", "type": "boolean" } ] } ```