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

Страница «Редакции конфигурации» — План реализации

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Реализовать красивую HTML-страницу с матрицей возможностей редакций СТАНДАРТ/ПРОФ/КОРП, которая открывается программно с подсветкой конкретной фичи, когда пользователь пытается использовать недоступную функциональность.

Architecture: Markdown-макет (единый источник правды) → парсер в модуле СЛС → HTML-генератор через РаботаСВебСервер (поток в памяти + ЗаписьТекста, без конкатенации) → ПолеHTMLДокумента на общей форме. Клиентский фасад СЛСКлиент.ПроверитьДоступностьРедакции(КодФункции) — одна строка в месте вызова.

Tech Stack::EDT, BSL, MCP EDT (read_module_source, write_module_source, get_project_errors), прямое редактирование .mdo/.form/.txt файлов через Read/Edit/Write.

Spec: docs/superpowers/specs/2026-04-10-editions-page-design.md


Текущее состояние репозитория (до задач)

В ветке uit4 уже есть незакоммиченные изменения, создающие каркас:

  • Создана директория it/src/CommonForms/РедакцииКонфигурации/ с пустыми Form.form и РедакцииКонфигурации.mdo
  • it/src/CommonTemplates/РедакцииКонфигурации/РедакцииКонфигурации.mdo изменён (тип TextDocument)
  • it/src/CommonTemplates/РедакцииКонфигурации/Template.mxlx удалён (старый табличный макет)
  • it/src/CommonTemplates/РедакцииКонфигурации/Template.txt создан (пустой)
  • it/src/Configuration/Configuration.mdo изменён — добавлена регистрация CommonForm.РедакцииКонфигурации и перемещён CommonTemplate.РедакцииКонфигурации
  • it/src/Roles/БазовыеПраваУФ/Rights.rights уже содержит View на CommonForm.РедакцииКонфигурации

Эти изменения — каркас, на котором базируется план. Они не коммитятся отдельно — первый же Task добавляет к ним новый файл и всё коммитится единым атомарным изменением.

Порядок задач

Task 1: Создать CommonTemplate.css_editions (метаданные + CSS + регистрация)
Task 2: Заполнить Template.txt макета РедакцииКонфигурации Markdown-контентом
Task 3: СЛС.ФункциональностьДоступна — серверная проверка
Task 4: СЛС.ПрочитатьМакетРедакций — парсер
Task 5: СЛС.СформироватьHTMLРедакций + вспомогательные (+ HTMLОшибкиМакетаРедакций)
Task 6: СЛСКлиент.ПроверитьДоступностьРедакции — клиентский фасад
Task 7: Реквизиты формы РедакцииКонфигурации (ТекстHTML, КодФункции)
Task 8: Элемент ПолеHTMLДокумента на форме РедакцииКонфигурации
Task 9: Модуль формы РедакцииКонфигурации (обработчики)
Task 10: Ручное тестирование по чек-листу спецификации

Порядок важен: Tasks 3–6 создают API, который использует форма в Tasks 7–9. Ручное тестирование — только после всех BSL-изменений.


Task 1: Создать CommonTemplate.css_editions

Files:

  • Create: it/src/CommonTemplates/css_editions/css_editions.mdo

  • Create: it/src/CommonTemplates/css_editions/Template.txt

  • Modify: it/src/Configuration/Configuration.mdo (добавить регистрацию в алфавитном порядке между css_docsinum_static и css_hack_font)

  • Step 1: Создать css_editions.mdo

Записать в it/src/CommonTemplates/css_editions/css_editions.mdo:

<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonTemplate xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="a02b55eb-9f48-4fff-b25c-bc892f55e388">
<name>css_editions</name>
<synonym>
<key>ru</key>
<value>css_editions</value>
</synonym>
<templateType>TextDocument</templateType>
</mdclass:CommonTemplate>
  • Step 2: Создать Template.txt с CSS

Записать в it/src/CommonTemplates/css_editions/Template.txt (~180 строк):

/* === Страница Редакции конфигурации === */
/* Правила окружения: старый webkit 2015+, без @media, без CSS-переменных. */

.editions-panel {
display: -webkit-box;
display: -webkit-flex;
display: flex;
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
flex-direction: column;
max-width: 960px;
margin: 0 auto;
padding: 20px;
font-family: "Segoe UI", "Open Sans", Tahoma, Arial, sans-serif;
font-size: 14px;
color: #212529;
line-height: 1.5;
}

/* === Шапка === */

.editions-hero {
margin-bottom: 24px;
padding: 20px 24px;
background: -webkit-linear-gradient(left, #f8f9fa, #e9ecef);
background: linear-gradient(90deg, #f8f9fa, #e9ecef);
border-radius: 6px;
border-left: 4px solid #0066cc;
}

.editions-hero h1 {
margin: 0 0 12px 0;
font-size: 22px;
font-weight: 600;
color: #212529;
}

.current-edition-badge {
display: inline-block;
padding: 6px 14px;
border-radius: 20px;
font-weight: 600;
font-size: 13px;
color: #ffffff;
}

.current-edition-badge.edition-standart {
background-color: #6c757d;
}

.current-edition-badge.edition-prof {
background-color: #0066cc;
}

.current-edition-badge.edition-corp {
background-color: #d4a017;
}

.current-edition-badge.edition-unknown {
background-color: #adb5bd;
}

/* === Введение === */

.editions-intro {
margin-bottom: 24px;
padding: 0 4px;
}

/* Стили markdown для введения идут из css_markdown_content */

/* === Матрица возможностей === */

.editions-matrix {
width: 100%;
border-collapse: collapse;
border: 1px solid #dee2e6;
margin-bottom: 16px;
background-color: #ffffff;
}

.editions-matrix th,
.editions-matrix td {
padding: 8px 12px;
border: 1px solid #dee2e6;
vertical-align: top;
text-align: left;
}

.editions-matrix thead th {
background-color: #343a40;
color: #ffffff;
font-weight: 600;
text-align: center;
position: relative;
}

.editions-matrix thead th.col-feature {
text-align: left;
width: 60%;
}

.editions-matrix thead th.col-edition {
width: 13%;
}

.editions-matrix thead th.col-current {
background-color: #0066cc;
}

.editions-matrix tbody td.col-current {
background-color: #e7f1ff;
}

/* Строка раздела */

.row-section td {
background-color: #343a40;
color: #ffffff;
font-weight: 700;
font-size: 15px;
padding: 10px 12px;
border-top: 2px solid #212529;
}

/* Строка подраздела */

.row-subsection td {
background-color: #e9ecef;
color: #495057;
font-weight: 600;
font-style: italic;
padding: 6px 12px;
}

/* Строка фичи */

.row-feature td {
font-size: 13px;
}

.row-feature td.check {
text-align: center;
font-size: 16px;
color: #28a745;
font-weight: 700;
}

.row-feature td.dash {
text-align: center;
font-size: 16px;
color: #adb5bd;
}

/* Примечание под названием фичи */

.feature-note {
display: block;
margin-top: 4px;
font-size: 12px;
font-style: italic;
color: #6c757d;
}

/* === Подсветка целевой фичи === */

.row-highlighted td {
background-color: #fff3cd;
border-left: 3px solid #dc3545;
}

.row-highlighted td.col-current {
background-color: #ffe8b3;
}

.feature-unavailable-badge {
display: block;
margin-top: 6px;
padding: 6px 10px;
background-color: #dc3545;
color: #ffffff;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
}

/* === Блок ошибки макета === */

.editions-error {
margin: 24px;
padding: 16px 20px;
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c2c7;
border-radius: 4px;
font-family: "Consolas", "Courier New", monospace;
font-size: 12px;
white-space: pre-wrap;
word-wrap: break-word;
}
  • Step 3: Зарегистрировать в Configuration.mdo

Найти блок <commonTemplates> с CSS-макетами (строки ~2443–2455). Вставить новый элемент после css_docsinum_static и перед css_hack_font. Используй Edit для точной вставки:

Найти:

  <commonTemplates>CommonTemplate.css_docsinum_static</commonTemplates>
<commonTemplates>CommonTemplate.css_hack_font</commonTemplates>

Заменить на:

  <commonTemplates>CommonTemplate.css_docsinum_static</commonTemplates>
<commonTemplates>CommonTemplate.css_editions</commonTemplates>
<commonTemplates>CommonTemplate.css_hack_font</commonTemplates>
  • Step 4: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors.

  • Step 5: Commit
git add it/src/CommonTemplates/css_editions/ it/src/Configuration/Configuration.mdo
git commit -m "feat: Новый макет CSS css_editions для страницы редакций"

Task 2: Заполнить Template.txt макета РедакцииКонфигурации Markdown-контентом

Files:

  • Modify: it/src/CommonTemplates/РедакцииКонфигурации/Template.txt (из пустого → полный макет)

Этот макет — единый источник правды о матрице возможностей. Заполняется однократно на основе Возможности УИТ 4.xlsx и СЛС.УстановитьФункционал() Module.bsl:5321. Для строк с code= маска должна совпадать с ФО-реальностью (параметры СтандАРТ, ПРОФ, КОРП в УстановитьДоступностьФункционала). Для строк без кода — маска берётся из xlsx.

  • Step 1: Записать содержимое макета

Записать в it/src/CommonTemplates/РедакцииКонфигурации/Template.txt:

# Возможности "Управление IT-отделом 8"

В программе **"Управление IT-отделом 8"** существует три редакции:
**Стандарт**, **Проф** и **Корп**. Редакции отличаются набором
доступных возможностей. Ниже — полная матрица функционала.

Если вы видите эту страницу, значит функция, к которой вы обратились,
недоступна в вашей редакции. Обратитесь к поставщику для перехода
на редакцию с нужной функциональностью.

## 1. Service Desk (управление инцидентами)

### 1.1. Документ "Задание"

- Создание, редактирование, выполнение заданий | СПК
- Шаблоны заданий/комментариев | СПК
note: Планируется убрать из Стандарта.
- Оценка заданий и лояльность пользователей | СПК

### 1.2. Мастер регистрации

- Функционал Мастера регистрации | СПК
note: Планируется убрать из Стандарта.

### 1.3. SLA (Service Level Agreement)

- Функционал SLA | -ПК | code=SLAСервисыРаботы
note: Сам функционал виден везде, в Стандарте скрыты только услуги.

### 1.4. CRM-подсистема

- Потенциальные клиенты | --К | code=ИспользоватьCRM

### 1.5. Управление проблемами

- Регистрация и отслеживание проблем | --К | code=ИспользоватьПроблемы

### 1.6. Отчёты Service Desk

- Отчёты Service Desk | СПК
note: Планируется дифференцировать набор отчётов по редакциям.

## 2. База знаний

### 2.1. Статьи и каталоги

- Создание статей и каталогов | СПК
- Схемы Mermaid | СПК
note: Планируется убрать из Стандарта.

## 3. Управление проектами

### 3.1. Планирование проекта

- Создание и ведение проектов | СПК
- Канбан-доска | СПК
- Спринты | СПК

### 3.2. Подсистема Agile

- Покер планирования | --К | code=ИспользоватьПокерПланирование
- Ежедневный стендап | --К | code=ИспользоватьЕжедневныйСтендап
- Ретроспектива | --К | code=ИспользоватьРетроспективу

## 4. Сотрудники

### 4.1. Управление сотрудниками

- Справочник сотрудников | СПК
- Закрепление сотрудников за местами хранения | СПК

### 4.2. Анкетирование

- Создание анкет и опросов | --К | code=ИспользоватьАнкетирование
note: Планируется добавить в Проф.

### 4.3. Управление доступом к информационным ресурсам

- Просмотр доступных ресурсов | --К | code=ИспользоватьДоступКИнформационнымРесурсам

### 4.4. Заработная плата

- Назначения начислений и удержаний | -ПК
- Начисления заработной платы | -ПК

## 5. Учёт рабочего времени

### 5.1. Ежедневный отчёт

- Документ "Ежедневный отчёт" | --К

### 5.2. Работы

- Учёт трудозатрат сотрудников | СПК
- Наряды на работы | -ПК
- Листы учёта рабочего времени | -ПК

### 5.3. Причины отклонений от графика

- Отслеживание отклонений | СПК

## 6. Логины и пароли

### 6.1. Хранилище

- Хранение логинов и паролей | СПК
- Удалённое подключение к рабочим местам | --К | code=ИспользоватьУдаленноеУправление
note: Удалённое подключение можно настроить вне зависимости от редакции. Выделенный функционал только в КОРП.

## 7. Взаимодействия

### 7.1. Электронная почта

- Входящие/исходящие письма | СПК
- Шаблоны писем | СПК
note: Планируется убрать из Стандарта (требует обсуждения — всё-таки почта).

### 7.2. SMS-сообщения

- Отправка и получение SMS | -ПК | code=ИспользоватьОповещенияПоSMS

### 7.3. Телефония

- Звонки и работа с телефонией | --К
- Журнал звонков | --К

### 7.4. Встречи

- Планирование и проведение встреч | СПК

## 8. Автоматизация

### 8.1. Правила событий

- Правила событий | СПК
note: Планируется дифференцировать набор правил по редакциям.
- Действия правил событий | СПК

## 9. Управление IT-активами

### 9.1. Номенклатура

- Номенклатуры и карточки номенклатуры | СПК
- Комплекты и комплектующие | СПК

### 9.2. Складской учёт

- Места хранения | СПК
- Местоположение | СПК
- Закрепление сотрудников за местами хранения | СПК
- Складской учёт клиентов | --К | code=СкладскойУчетКлиентов
note: Константу можно включить в любой момент, функционал только в КОРП.

### 9.3. Складские документы

- Заказы клиентов и заказы поставщику | СПК
- Поступление, Перемещение, Списание, Инвентаризация | СПК
- Продажа | СПК
- Сборка и разбиение комплектации | СПК

### 9.4. Терминал сбора данных

- Выгрузка данных в и из ТСД | СПК
- Инвентаризация на основании мобильного ТСД | -ПК | code=ИспользоватьМобильныйТСД

### 9.5. Ремонты и обслуживание

- Документ "Начало обслуживания" | -ПК | code=ИспользоватьРемонтыИОбслуживание
- Документ "Окончание обслуживания" | -ПК
- Изменение показателей оборудования | -ПК

### 9.6. Импорт данных

- Загрузка номенклатуры из файла Excel | СПК
- Загрузка из AIDA64 и WMI | СПК
note: Планируется убрать из Стандарта и Проф.

### 9.7. Отчёты складского учёта

- Отчёты складского учёта | СПК
note: Планируется дифференцировать набор отчётов по редакциям.

## 10. Денежные средства

### 10.1. Учёт и взаиморасчёты

- Учёт денежных средств | СПК
- Взаиморасчёты с контрагентами | СПК
- Бюджетирование | --К | code=ИспользоватьБюджетирование

## 11. Первичные документы

### 11.1. Учёт первичных документов

- Учёт первичных документов | СПК

## 12. Интеграция со сторонними сервисами

### 12.1. Каналы взаимодействия

- Личный кабинет | СПК
- Telegram-bot | -ПК | code=ИспользоватьTelegram
- Мобильное приложение | --К

## 13. Администрирование

### 13.1. Обмен и миграция

- Обмен с конфигурациями 1С (справочной информацией) | СПК
note: Планируется убрать из Стандарта.
- Импорт данных из Active Directory | СПК
note: Планируется убрать из Стандарта и Проф.
- Свёртка информационной базы | СПК
note: Планируется убрать из Стандарта.

### 13.2. Настройка и API

- Изменение макетов печатных форм | СПК
note: Обсуждается вариант максимальной настраиваемости только в КОРП.
- Настройка рабочего стола | СПК
note: Планируется убрать из Стандарта.
- REST API | СПК
  • Step 2: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors (Template.txt — просто текстовый файл, EDT не должен ругаться).

  • Step 3: Commit
git add it/src/CommonTemplates/РедакцииКонфигурации/
git commit -m "feat: Макет редакций конфигурации — матрица возможностей в формате Markdown"

Task 3: СЛС.ФункциональностьДоступна — серверная проверка

Files:

  • Modify: it/src/CommonModules/СЛС/Module.bsl (добавить в область ПрограммныйИнтерфейс рядом с другими функциями о редакциях — около Module.bsl:534, после ЭтоРедакцияКОРП())

  • Step 1: Прочитать контекст вставки

MCP: read_method_source для метода ЭтоРедакцияКОРП в модуле СЛС — убедиться, что вставка будет после этой функции.

  • Step 2: Добавить функцию ФункциональностьДоступна

Вставить после функции ЭтоРедакцияКОРП:

// Возвращает Истина, если функция доступна в текущей редакции конфигурации.
// Проверка делается через значение константы функциональной опции, которую
// устанавливает СЛС.УстановитьФункционал() согласно редакции.
//
// Параметры:
// КодФункции - Строка - Имя константы функциональной опции
// (например, "ИспользоватьCRM").
// Если пустая строка - возврат Истина.
//
// Возвращаемое значение:
// Булево - Истина, если функция доступна.
//
Функция ФункциональностьДоступна(Знач КодФункции) Экспорт

Если НЕ ЗначениеЗаполнено(КодФункции) Тогда
Возврат Истина;
КонецЕсли;

МетаданныеКонстанты = Метаданные.Константы.Найти(КодФункции);
Если МетаданныеКонстанты = Неопределено Тогда
Возврат Истина;
КонецЕсли;

УстановитьПривилегированныйРежим(Истина);
Значение = Константы[КодФункции].Получить();
УстановитьПривилегированныйРежим(Ложь);

Возврат Значение = Истина;

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

Используй MCP write_module_source для вставки — не трогай Read/Edit напрямую для .bsl файлов (правило CLAUDE.md → Инструменты по типам файлов 1С).

  • Step 3: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors.

  • Step 4: Commit
git add it/src/CommonModules/СЛС/Module.bsl
git commit -m "feat: СЛС.ФункциональностьДоступна — проверка доступности функции по коду"

Task 4: СЛС.ПрочитатьМакетРедакций — парсер макета

Files:

  • Modify: it/src/CommonModules/СЛС/Module.bsl (добавить публичную функцию в ПрограммныйИнтерфейс, служебные — в СлужебныеПроцедурыИФункции)

  • Step 1: Добавить публичную функцию ПрочитатьМакетРедакций

Через MCP write_module_source вставить в область ПрограммныйИнтерфейс (после ФункциональностьДоступна):

// Читает макет "РедакцииКонфигурации" и разбирает его в структуру данных
// с разделами, подразделами и фичами.
//
// Возвращаемое значение:
// Структура - Разобранные данные макета:
// * Введение - Строка - Markdown-текст введения до первого "## ".
// * Разделы - Массив из Структура - Список разделов:
// ** Название - Строка - Название раздела.
// ** Подразделы - Массив из Структура - Список подразделов:
// *** Название - Строка - Название подраздела.
// *** Фичи - Массив из Структура - Список фич:
// **** Название - Строка - Название фичи.
// **** Маска - Строка - Маска доступности (например, "СПК", "-ПК", "--К").
// **** Код - Строка - Имя константы функциональной опции (или пустая строка).
// **** Примечание - Строка - Примечание к фиче (или пустая строка).
//
Функция ПрочитатьМакетРедакций() Экспорт

МакетОбъект = ПолучитьОбщийМакет("РедакцииКонфигурации");
Текст = МакетОбъект.ПолучитьТекст();

Строки = СтрРазделить(Текст, Символы.ПС, Истина);

Результат = Новый Структура("Введение, Разделы", "", Новый Массив);

ТекущийРаздел = Неопределено;
ТекущийПодраздел = Неопределено;
ПоследняяФича = Неопределено;
ВведениеНакапливаем = Истина;
БуферВведения = Новый Массив;
ЗаголовокПройден = Ложь;

Для НомерСтроки = 1 По Строки.Количество() Цикл

Строка = Строки[НомерСтроки - 1];

Если НЕ ЗаголовокПройден И СтрНачинаетсяС(Строка, "# ") Тогда
ЗаголовокПройден = Истина;
Продолжить;
КонецЕсли;

Если СтрНачинаетсяС(Строка, "## ") Тогда
ВведениеНакапливаем = Ложь;
ТекущийРаздел = НовыйЭлементРаздела(СокрЛП(Сред(Строка, 4)));
Результат.Разделы.Добавить(ТекущийРаздел);
ТекущийПодраздел = Неопределено;
ПоследняяФича = Неопределено;
Продолжить;
КонецЕсли;

Если СтрНачинаетсяС(Строка, "### ") Тогда
Если ТекущийРаздел = Неопределено Тогда
ВызватьИсключение СтрШаблон(
НСтр("ru = 'Макет редакций: подраздел вне раздела, строка %1'"),
НомерСтроки);
КонецЕсли;
ТекущийПодраздел = НовыйЭлементПодраздела(СокрЛП(Сред(Строка, 5)));
ТекущийРаздел.Подразделы.Добавить(ТекущийПодраздел);
ПоследняяФича = Неопределено;
Продолжить;
КонецЕсли;

Если СтрНачинаетсяС(Строка, "- ") Тогда
Если ТекущийПодраздел = Неопределено Тогда
ВызватьИсключение СтрШаблон(
НСтр("ru = 'Макет редакций: фича вне подраздела, строка %1'"),
НомерСтроки);
КонецЕсли;
Фича = РазобратьСтрокуФичиМакетаРедакций(Строка, НомерСтроки);
ТекущийПодраздел.Фичи.Добавить(Фича);
ПоследняяФича = Фича;
Продолжить;
КонецЕсли;

СтрокаБезОтступа = СокрЛ(Строка);
Если СтрНачинаетсяС(СтрокаБезОтступа, "note: ") Тогда
Если ПоследняяФича = Неопределено Тогда
ВызватьИсключение СтрШаблон(
НСтр("ru = 'Макет редакций: note без фичи, строка %1'"),
НомерСтроки);
КонецЕсли;
ПоследняяФича.Примечание = СокрЛП(Сред(СтрокаБезОтступа, 7));
Продолжить;
КонецЕсли;

Если ВведениеНакапливаем Тогда
БуферВведения.Добавить(Строка);
КонецЕсли;

КонецЦикла;

Результат.Введение = СокрЛП(СтрСоединить(БуферВведения, Символы.ПС));

Возврат Результат;

КонецФункции
  • Step 2: Добавить служебные функции парсера

Через MCP write_module_source вставить в область СлужебныеПроцедурыИФункции (в конце модуля перед закрывающим #КонецОбласти):

// Создает структуру нового раздела макета редакций.
Функция НовыйЭлементРаздела(Знач Название)

Раздел = Новый Структура;
Раздел.Вставить("Название", Название);
Раздел.Вставить("Подразделы", Новый Массив);
Возврат Раздел;

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

// Создает структуру нового подраздела макета редакций.
Функция НовыйЭлементПодраздела(Знач Название)

Подраздел = Новый Структура;
Подраздел.Вставить("Название", Название);
Подраздел.Вставить("Фичи", Новый Массив);
Возврат Подраздел;

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

// Разбирает одну строку фичи макета редакций вида
// "- Название | Маска | атрибут1 | атрибут2"
Функция РазобратьСтрокуФичиМакетаРедакций(Знач Строка, Знач НомерСтроки)

ТелоСтроки = СокрЛ(Сред(Строка, 3));
Части = СтрРазделить(ТелоСтроки, "|", Ложь);

Если Части.Количество() < 2 Тогда
ВызватьИсключение СтрШаблон(
НСтр("ru = 'Макет редакций: ожидается ""- Название | Маска"", строка %1'"),
НомерСтроки);
КонецЕсли;

Фича = Новый Структура("Название, Маска, Код, Примечание", "", "---", "", "");
Фича.Название = СокрЛП(Части[0]);
Фича.Маска = ВалидироватьМаскуРедакций(СокрЛП(Части[1]), НомерСтроки);

Для Индекс = 2 По Части.ВГраница() Цикл
Атрибут = СокрЛП(Части[Индекс]);
Если СтрНачинаетсяС(Атрибут, "code=") Тогда
Фича.Код = СокрЛП(Сред(Атрибут, 6));
КонецЕсли;
КонецЦикла;

Возврат Фича;

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

// Проверяет маску редакций: ровно 3 символа из набора { "С", "П", "К", "-" }.
Функция ВалидироватьМаскуРедакций(Знач Маска, Знач НомерСтроки)

Если СтрДлина(Маска) <> 3 Тогда
ВызватьИсключение СтрШаблон(
НСтр("ru = 'Макет редакций: маска должна быть ровно 3 символа, строка %1, получено: ""%2""'"),
НомерСтроки, Маска);
КонецЕсли;

РазрешенныеСимволы = "СПК-";
Для Позиция = 1 По 3 Цикл
Символ = Сред(Маска, Позиция, 1);
Если СтрНайти(РазрешенныеСимволы, Символ) = 0 Тогда
ВызватьИсключение СтрШаблон(
НСтр("ru = 'Макет редакций: недопустимый символ ""%1"" в маске, строка %2'"),
Символ, НомерСтроки);
КонецЕсли;
КонецЦикла;

Возврат Маска;

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

Используй MCP write_module_source для вставки.

  • Step 3: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors.

  • Step 4: Commit
git add it/src/CommonModules/СЛС/Module.bsl
git commit -m "feat: СЛС.ПрочитатьМакетРедакций — парсер Markdown-макета матрицы возможностей"

Task 5: СЛС.СформироватьHTMLРедакций и СЛС.HTMLОшибкиМакетаРедакций

Files:

  • Modify: it/src/CommonModules/СЛС/Module.bsl

Этот Task содержит самый большой объём BSL-кода. Разделён на два шага: публичные функции в ПрограммныйИнтерфейс, служебные — в СлужебныеПроцедурыИФункции.

  • Step 1: Добавить публичные функции СформироватьHTMLРедакций и HTMLОшибкиМакетаРедакций

Через MCP write_module_source вставить после функции ПрочитатьМакетРедакций в область ПрограммныйИнтерфейс:

// Формирует полный HTML-документ страницы "Редакции конфигурации".
//
// Параметры:
// ДанныеМакета - Структура - Результат СЛС.ПрочитатьМакетРедакций().
// ТекущаяРедакция - Число, Неопределено - Номер текущей редакции (1, 2, 3 или Неопределено).
// ВыделеннаяФича - Строка - Код функциональной опции для подсветки (может быть пустой).
//
// Возвращаемое значение:
// Строка - Полный HTML-документ.
//
Функция СформироватьHTMLРедакций(ДанныеМакета, Знач ТекущаяРедакция, Знач ВыделеннаяФича = "") Экспорт

Стили = Новый Массив;
Стили.Добавить(РаботаСВебСервер.ПолучитьТекстОбщегоМакета("css_markdown_content"));
Стили.Добавить(РаботаСВебСервер.ПолучитьТекстОбщегоМакета("css_editions"));

ПотокДанных = Новый ПотокВПамяти;
Запись = Новый ЗаписьТекста(ПотокДанных, КодировкаТекста.UTF8);

Заголовок = НСтр("ru = 'Редакции конфигурации'");
РаботаСВебСервер.ОткрытьДокумент(Запись, Заголовок, Стили);

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "div", "editions-panel");
РаботаСВебСервер.ДобавитьСвойствоЗначениеТега(Запись,
"data-current-edition",
?(ТекущаяРедакция = Неопределено, "0", Формат(ТекущаяРедакция, "ЧН=0; ЧГ=0")));
Если ЗначениеЗаполнено(ВыделеннаяФича) Тогда
РаботаСВебСервер.ДобавитьСвойствоЗначениеТега(Запись,
"data-highlighted-feature", ВыделеннаяФича);
КонецЕсли;
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

СобратьШапкуРедакций(Запись, ТекущаяРедакция);
СобратьВведениеРедакций(Запись, ДанныеМакета.Введение);
СобратьТаблицуРедакций(Запись, ДанныеМакета, ТекущаяРедакция, ВыделеннаяФича);

РаботаСВебСервер.ЗакрытьDiv(Запись);
РаботаСВебСервер.ЗакрытьДокумент(Запись);

Запись.Закрыть();
ПотокДанных.Позиция = 0;
Чтение = Новый ЧтениеТекста(ПотокДанных, КодировкаТекста.UTF8);
РезультатHTML = Чтение.Прочитать();
Чтение.Закрыть();

Возврат РезультатHTML;

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

// Формирует HTML-страницу для отображения ошибки загрузки/парсинга макета редакций.
//
// Параметры:
// ИнформацияОбОшибке - ИнформацияОбОшибке - Объект с описанием ошибки.
//
// Возвращаемое значение:
// Строка - HTML-документ с сообщением об ошибке.
//
Функция HTMLОшибкиМакетаРедакций(ИнформацияОбОшибке) Экспорт

ПотокДанных = Новый ПотокВПамяти;
Запись = Новый ЗаписьТекста(ПотокДанных, КодировкаТекста.UTF8);

Заголовок = НСтр("ru = 'Редакции конфигурации - ошибка макета'");
РаботаСВебСервер.ОткрытьДокумент(Запись, Заголовок, РаботаСВебСервер.ПолучитьТекстОбщегоМакета("css_editions"));

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "div", "editions-error");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

ТекстОшибки = НСтр("ru = 'Не удалось загрузить матрицу возможностей редакций.'")
+ Символы.ПС + Символы.ПС
+ ПодробноеПредставлениеОшибки(ИнформацияОбОшибке);
РаботаСВебСервер.ДобавитьHTML(Запись, РаботаСВебСервер.ЗаменитьСпецСимволыHTML(ТекстОшибки));

РаботаСВебСервер.ЗакрытьDiv(Запись);
РаботаСВебСервер.ЗакрытьДокумент(Запись);

Запись.Закрыть();
ПотокДанных.Позиция = 0;
Чтение = Новый ЧтениеТекста(ПотокДанных, КодировкаТекста.UTF8);
РезультатHTML = Чтение.Прочитать();
Чтение.Закрыть();

Возврат РезультатHTML;

КонецФункции
  • Step 2: Добавить служебные процедуры HTML-сборки

Через MCP write_module_source вставить в конец области СлужебныеПроцедурыИФункции (после ВалидироватьМаскуРедакций из Task 4):

// Собирает hero-блок: заголовок + бейдж текущей редакции.
Процедура СобратьШапкуРедакций(Запись, Знач ТекущаяРедакция)

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "header", "editions-hero");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "h1");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
Запись.ЗаписатьСтроку(НСтр("ru = 'Возможности ""Управление IT-отделом 8""'"));
РаботаСВебСервер.ЗакрытьТег(Запись, "h1");

КлассБейджа = "current-edition-badge " + КлассБейджаТекущейРедакции(ТекущаяРедакция);
РаботаСВебСервер.НачатьОткрытиеТега(Запись, "div", КлассБейджа);
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
ТекстБейджа = СтрШаблон(НСтр("ru = 'Ваша редакция: %1'"),
НазваниеРедакцииДляБейджа(ТекущаяРедакция));
РаботаСВебСервер.ДобавитьHTML(Запись, РаботаСВебСервер.ЗаменитьСпецСимволыHTML(ТекстБейджа));
РаботаСВебСервер.ЗакрытьDiv(Запись);

РаботаСВебСервер.ЗакрытьТег(Запись, "header");

КонецПроцедуры

// Собирает секцию с введением (рендерит Markdown через ДоксинумПарсер).
Процедура СобратьВведениеРедакций(Запись, Знач ТекстВведения)

Если НЕ ЗначениеЗаполнено(ТекстВведения) Тогда
Возврат;
КонецЕсли;

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "section", "editions-intro markdown-content");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

ПараметрыMD = ДоксинумПарсер.ПараметрыMD(ДоксинумПарсер, ДоксинумШаблоны);
HTMLВведения = ДоксинумПарсер.ОбработатьТекстMD(ПараметрыMD, ТекстВведения);
РаботаСВебСервер.ДобавитьHTML(Запись, HTMLВведения);

РаботаСВебСервер.ЗакрытьТег(Запись, "section");

КонецПроцедуры

// Собирает основную таблицу матрицы возможностей.
Процедура СобратьТаблицуРедакций(Запись, ДанныеМакета, Знач ТекущаяРедакция, Знач ВыделеннаяФича)

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "table", "editions-matrix");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

СобратьЗаголовокТаблицыРедакций(Запись, ТекущаяРедакция);

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "tbody");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

Для Каждого Раздел Из ДанныеМакета.Разделы Цикл
СобратьСтрокуРазделаРедакций(Запись, Раздел.Название);
Для Каждого Подраздел Из Раздел.Подразделы Цикл
СобратьСтрокуПодразделаРедакций(Запись, Подраздел.Название);
Для Каждого Фича Из Подраздел.Фичи Цикл
СобратьСтрокуФичиРедакций(Запись, Фича, ТекущаяРедакция, ВыделеннаяФича);
КонецЦикла;
КонецЦикла;
КонецЦикла;

РаботаСВебСервер.ЗакрытьТег(Запись, "tbody");
РаботаСВебСервер.ЗакрытьТег(Запись, "table");

КонецПроцедуры

// Собирает thead с заголовками колонок: Возможность + 3 редакции.
Процедура СобратьЗаголовокТаблицыРедакций(Запись, Знач ТекущаяРедакция)

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "thead");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "tr");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "th", "col-feature");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
Запись.ЗаписатьСтроку(НСтр("ru = 'Возможность'"));
РаботаСВебСервер.ЗакрытьТег(Запись, "th");

ЗаголовкиРедакций = Новый Массив;
ЗаголовкиРедакций.Добавить(НСтр("ru = 'Стандарт'"));
ЗаголовкиРедакций.Добавить(НСтр("ru = 'Проф'"));
ЗаголовкиРедакций.Добавить(НСтр("ru = 'Корп'"));

Для НомерРедакции = 1 По 3 Цикл
КлассКолонки = "col-edition";
Если НомерРедакции = ТекущаяРедакция Тогда
КлассКолонки = КлассКолонки + " col-current";
КонецЕсли;
РаботаСВебСервер.НачатьОткрытиеТега(Запись, "th", КлассКолонки);
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
Запись.ЗаписатьСтроку(ЗаголовкиРедакций[НомерРедакции - 1]);
РаботаСВебСервер.ЗакрытьТег(Запись, "th");
КонецЦикла;

РаботаСВебСервер.ЗакрытьТег(Запись, "tr");
РаботаСВебСервер.ЗакрытьТег(Запись, "thead");

КонецПроцедуры

// Собирает строку раздела (tr class="row-section" с colspan).
Процедура СобратьСтрокуРазделаРедакций(Запись, Знач Название)

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "tr", "row-section");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "td");
РаботаСВебСервер.ДобавитьСвойствоЗначениеТега(Запись, "colspan", "4");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
Запись.ЗаписатьСтроку(РаботаСВебСервер.ЗаменитьСпецСимволыHTML(Название));
РаботаСВебСервер.ЗакрытьТег(Запись, "td");

РаботаСВебСервер.ЗакрытьТег(Запись, "tr");

КонецПроцедуры

// Собирает строку подраздела.
Процедура СобратьСтрокуПодразделаРедакций(Запись, Знач Название)

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "tr", "row-subsection");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "td");
РаботаСВебСервер.ДобавитьСвойствоЗначениеТега(Запись, "colspan", "4");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
Запись.ЗаписатьСтроку(РаботаСВебСервер.ЗаменитьСпецСимволыHTML(Название));
РаботаСВебСервер.ЗакрытьТег(Запись, "td");

РаботаСВебСервер.ЗакрытьТег(Запись, "tr");

КонецПроцедуры

// Собирает строку фичи с 4 колонками и опциональной подсветкой.
Процедура СобратьСтрокуФичиРедакций(Запись, Фича, Знач ТекущаяРедакция, Знач ВыделеннаяФича)

ЭтоВыделеннаяСтрока = ЗначениеЗаполнено(Фича.Код) И Фича.Код = ВыделеннаяФича;
КлассСтроки = "row-feature";
Если ЭтоВыделеннаяСтрока Тогда
КлассСтроки = КлассСтроки + " row-highlighted";
КонецЕсли;

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "tr", КлассСтроки);
Если ЗначениеЗаполнено(Фича.Код) Тогда
РаботаСВебСервер.ДобавитьСвойствоЗначениеТега(Запись, "id", "feature-" + Фича.Код);
КонецЕсли;
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);

// Колонка с названием + опциональными note и unavailable-badge.
РаботаСВебСервер.НачатьОткрытиеТега(Запись, "td");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
Запись.ЗаписатьСтроку(РаботаСВебСервер.ЗаменитьСпецСимволыHTML(Фича.Название));

Если ЗначениеЗаполнено(Фича.Примечание) Тогда
РаботаСВебСервер.НачатьОткрытиеТега(Запись, "span", "feature-note");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
Запись.ЗаписатьСтроку(РаботаСВебСервер.ЗаменитьСпецСимволыHTML(Фича.Примечание));
РаботаСВебСервер.ЗакрытьТег(Запись, "span");
КонецЕсли;

Если ЭтоВыделеннаяСтрока Тогда
ТребуемаяРедакция = МинимальнаяДоступнаяРедакцияИзМаски(Фича.Маска);
РаботаСВебСервер.НачатьОткрытиеТега(Запись, "div", "feature-unavailable-badge");
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
ТекстБейджа = СтрШаблон(
НСтр("ru = 'Недоступно в вашей редакции, требуется %1'"), ТребуемаяРедакция);
РаботаСВебСервер.ДобавитьHTML(Запись,
РаботаСВебСервер.ЗаменитьСпецСимволыHTML(ТекстБейджа));
РаботаСВебСервер.ЗакрытьDiv(Запись);
КонецЕсли;

РаботаСВебСервер.ЗакрытьТег(Запись, "td");

// 3 колонки редакций - галочка или прочерк.
Для НомерРедакции = 1 По 3 Цикл
ЕстьГалочка = МаскаРедакцийСодержит(Фича.Маска, НомерРедакции);
КлассЯчейки = ?(ЕстьГалочка, "check", "dash");
Если НомерРедакции = ТекущаяРедакция Тогда
КлассЯчейки = КлассЯчейки + " col-current";
КонецЕсли;

РаботаСВебСервер.НачатьОткрытиеТега(Запись, "td", КлассЯчейки);
РаботаСВебСервер.ЗакрытьОткрытиеТега(Запись);
Запись.ЗаписатьСтроку(?(ЕстьГалочка, "✓", "&mdash;"));
РаботаСВебСервер.ЗакрытьТег(Запись, "td");
КонецЦикла;

РаботаСВебСервер.ЗакрытьТег(Запись, "tr");

КонецПроцедуры

// Возвращает CSS-класс бейджа по номеру редакции.
Функция КлассБейджаТекущейРедакции(Знач ТекущаяРедакция)

Если ТекущаяРедакция = 1 Тогда
Возврат "edition-standart";
ИначеЕсли ТекущаяРедакция = 2 Тогда
Возврат "edition-prof";
ИначеЕсли ТекущаяРедакция = 3 Тогда
Возврат "edition-corp";
КонецЕсли;

Возврат "edition-unknown";

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

// Возвращает локализованное название редакции для бейджа.
Функция НазваниеРедакцииДляБейджа(Знач ТекущаяРедакция)

Если ТекущаяРедакция = 1 Тогда
Возврат НСтр("ru = 'СТАНДАРТ'");
ИначеЕсли ТекущаяРедакция = 2 Тогда
Возврат НСтр("ru = 'ПРОФ'");
ИначеЕсли ТекущаяРедакция = 3 Тогда
Возврат НСтр("ru = 'КОРП'");
КонецЕсли;

Возврат НСтр("ru = 'не определена'");

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

// Проверяет, содержит ли маска указанную редакцию (позиция 1-3).
Функция МаскаРедакцийСодержит(Знач Маска, Знач НомерРедакции)

Символ = Сред(Маска, НомерРедакции, 1);
Возврат Символ <> "-";

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

// Возвращает строковое представление минимальной редакции, в которой
// доступна фича согласно маске. Используется для бейджа "требуется ...".
Функция МинимальнаяДоступнаяРедакцияИзМаски(Знач Маска)

Если МаскаРедакцийСодержит(Маска, 2) Тогда
Возврат НСтр("ru = 'ПРОФ'");
ИначеЕсли МаскаРедакцийСодержит(Маска, 3) Тогда
Возврат НСтр("ru = 'КОРП'");
КонецЕсли;

Возврат НСтр("ru = 'СТАНДАРТ'");

КонецФункции
  • Step 3: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors. Возможные предупреждения про ДоксинумПарсер / ДоксинумШаблоны — проверить, что имена общих модулей верны (ДоксинумШаблоны может называться иначе — уточнить через list_modules).

Если ДоксинумШаблоны не найден — заменить сигнатуру вызова ДоксинумПарсер.ПараметрыMD(ДоксинумПарсер, ДоксинумШаблоны) на корректный по факту контекст: посмотреть, как ДоксинумПарсер.ПараметрыMD вызывается в существующем коде (например, через search_in_code MCP EDT или через Grep по .bsl файлам).

  • Step 4: Commit
git add it/src/CommonModules/СЛС/Module.bsl
git commit -m "feat: СЛС.СформироватьHTMLРедакций — генератор страницы матрицы возможностей"

Task 6: СЛСКлиент.ПроверитьДоступностьРедакции — клиентский фасад

Files:

  • Modify: it/src/CommonModules/СЛСКлиент/Module.bsl (добавить в область ПрограммныйИнтерфейс в конец существующих экспортных функций)

  • Step 1: Определить точку вставки

MCP: list_modules или read_module_source — найти последнюю экспортную функцию в СЛСКлиент и область ПрограммныйИнтерфейс. Существующие функции: Старт, СтартЗавершение, ПроверитьЗащитуЗавершение — по структуре Module.bsl:9–98.

  • Step 2: Добавить функцию ПроверитьДоступностьРедакции

Через MCP write_module_source вставить в область ПрограммныйИнтерфейс после существующих экспортных процедур:

// Проверяет доступность функции в текущей редакции конфигурации. Если функция
// недоступна, открывает форму "Редакции конфигурации" с подсветкой этой функции.
//
// Типичный паттерн использования в коде вызова:
//
// Если НЕ СЛСКлиент.ПроверитьДоступностьРедакции("ИспользоватьCRM") Тогда
// Возврат;
// КонецЕсли;
//
// Параметры:
// КодФункции - Строка - Имя константы функциональной опции
// (например, "ИспользоватьCRM").
//
// Возвращаемое значение:
// Булево - Истина, если функция доступна (вызывающий код продолжает работу).
//
Функция ПроверитьДоступностьРедакции(Знач КодФункции) Экспорт

Если СЛС.ФункциональностьДоступна(КодФункции) Тогда
Возврат Истина;
КонецЕсли;

ПараметрыФормы = Новый Структура("КодФункции", КодФункции);
ОткрытьФорму("ОбщаяФорма.РедакцииКонфигурации", ПараметрыФормы);

Возврат Ложь;

КонецФункции
  • Step 3: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors. Вызов СЛС.ФункциональностьДоступна() с клиента работает напрямую, потому что СЛС имеет флаг serverCall=true.

  • Step 4: Commit
git add it/src/CommonModules/СЛСКлиент/Module.bsl
git commit -m "feat: СЛСКлиент.ПроверитьДоступностьРедакции — фасад gating для клиента"

Task 7: Реквизиты формы РедакцииКонфигурации

Files:

  • Modify: it/src/CommonForms/РедакцииКонфигурации/Form.form

Текущая форма содержит только базовую структуру без реквизитов и элементов. Нужно добавить реквизиты ТекстHTML (Строка, основной) и КодФункции (Строка).

  • Step 1: Сгенерировать UUID-ы для реквизитов

Использовать заранее сгенерированные UUID:

  • ТекстHTML (attribute): 5d61196a-d76e-4abf-abb7-f3a5ac34aab9

  • КодФункции (attribute): 51f1a60d-6d5d-420d-aa90-0579d3fcb05f

  • Step 2: Добавить реквизиты в Form.form

Текущее содержимое Form.form:

<?xml version="1.0" encoding="UTF-8"?>
<form:Form xmlns:form="http://g5.1c.ru/v8/dt/form">
<autoCommandBar>
<name>ФормаКоманднаяПанель</name>
<id>-1</id>
<horizontalAlign>Left</horizontalAlign>
<autoFill>true</autoFill>
</autoCommandBar>
<saveWindowSettings>true</saveWindowSettings>
<autoTitle>true</autoTitle>
<autoUrl>true</autoUrl>
<group>Vertical</group>
<autoFillCheck>true</autoFillCheck>
<allowFormCustomize>true</allowFormCustomize>
<enabled>true</enabled>
<showTitle>true</showTitle>
<showCloseButton>true</showCloseButton>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
</form:Form>

Заменить на версию с реквизитами (вставка блока <attributes> перед <commandInterface>):

<?xml version="1.0" encoding="UTF-8"?>
<form:Form xmlns:form="http://g5.1c.ru/v8/dt/form">
<autoCommandBar>
<name>ФормаКоманднаяПанель</name>
<id>-1</id>
<horizontalAlign>Left</horizontalAlign>
<autoFill>true</autoFill>
</autoCommandBar>
<saveWindowSettings>true</saveWindowSettings>
<autoTitle>true</autoTitle>
<autoUrl>true</autoUrl>
<group>Vertical</group>
<autoFillCheck>true</autoFillCheck>
<allowFormCustomize>true</allowFormCustomize>
<enabled>true</enabled>
<showTitle>true</showTitle>
<showCloseButton>true</showCloseButton>
<attributes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="form:FormAttribute">
<name>ТекстHTML</name>
<title>
<key>ru</key>
<value>Текст HTML</value>
</title>
<id>1</id>
<valueType>
<types>String</types>
<stringQualifiers>
<length>0</length>
</stringQualifiers>
</valueType>
<view>
<common>true</common>
</view>
<edit>
<common>true</common>
</edit>
</attributes>
<attributes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="form:FormAttribute">
<name>КодФункции</name>
<title>
<key>ru</key>
<value>Код функции</value>
</title>
<id>2</id>
<valueType>
<types>String</types>
<stringQualifiers>
<length>100</length>
</stringQualifiers>
</valueType>
<view>
<common>true</common>
</view>
<edit>
<common>true</common>
</edit>
</attributes>
<commandInterface>
<navigationPanel/>
<commandBar/>
</commandInterface>
</form:Form>
  • Step 3: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors. EDT должен увидеть новые реквизиты формы.

  • Step 4: Commit
git add it/src/CommonForms/РедакцииКонфигурации/Form.form
git commit -m "feat: Реквизиты формы РедакцииКонфигурации (ТекстHTML, КодФункции)"

Task 8: Элемент ПолеHTMLДокумента на форме

Files:

  • Modify: it/src/CommonForms/РедакцииКонфигурации/Form.form

  • Step 1: Добавить элемент ПолеHTMLДокумента

Вставить блок <items> после блока <attributes> с КодФункции (т.е. перед <commandInterface>):

  <items xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="form:FormField">
<name>ПолеHTMLДокумента</name>
<id>1</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<type>HTMLDocumentField</type>
<dataPath xmlns:d5p1="http://g5.1c.ru/v8/dt/data-composition-system" xsi:type="d5p1:DataCompositionField">ТекстHTML</dataPath>
<titleLocation>None</titleLocation>
<horizontalStretch>true</horizontalStretch>
<verticalStretch>true</verticalStretch>
<extendedTooltip>
<name>ПолеHTMLДокументаРасширеннаяПодсказка</name>
<id>2</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<type>Label</type>
<autoMaxWidth>true</autoMaxWidth>
<autoMaxHeight>true</autoMaxHeight>
<extInfo xsi:type="form:LabelDecorationExtInfo">
<horizontalAlign>Left</horizontalAlign>
</extInfo>
</extendedTooltip>
<contextMenu>
<name>ПолеHTMLДокументаКонтекстноеМеню</name>
<id>3</id>
<visible>true</visible>
<enabled>true</enabled>
<userVisible>
<common>true</common>
</userVisible>
<autoFill>true</autoFill>
</contextMenu>
</items>
  • Step 2: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors. Элемент ПолеHTMLДокумента должен подхватить привязку к реквизиту ТекстHTML.

  • Step 3: Commit
git add it/src/CommonForms/РедакцииКонфигурации/Form.form
git commit -m "feat: Элемент ПолеHTMLДокумента на форме РедакцииКонфигурации"

Task 9: Модуль формы РедакцииКонфигурации

Files:

  • Create: it/src/CommonForms/РедакцииКонфигурации/Module.bsl

  • Step 1: Создать Module.bsl формы

Через MCP write_module_source создать файл с обработчиками:

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

Если Параметры.Свойство("КодФункции") Тогда
КодФункции = Параметры.КодФункции;
КонецЕсли;

Попытка
ДанныеМакета = СЛС.ПрочитатьМакетРедакций();
ТекстHTML = СЛС.СформироватьHTMLРедакций(
ДанныеМакета,
СЛС.РедакцияКонфигурации(),
КодФункции);
Исключение
ТекстHTML = СЛС.HTMLОшибкиМакетаРедакций(ИнформацияОбОшибке());
КонецПопытки;

КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)

Если ЗначениеЗаполнено(КодФункции) Тогда
ВыполнитьСкроллККодуФункции();
КонецЕсли;

КонецПроцедуры

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

#Область СлужебныеПроцедурыИФункции

&НаКлиенте
Процедура ВыполнитьСкроллККодуФункции()

Если Элементы.ПолеHTMLДокумента.Документ = Неопределено Тогда
Возврат;
КонецЕсли;

Элемент = Элементы.ПолеHTMLДокумента.Документ.getElementById(
"feature-" + КодФункции);

Если Элемент <> Неопределено Тогда
Элемент.scrollIntoView();
КонецЕсли;

КонецПроцедуры

#КонецОбласти
  • Step 2: Проверить ошибки EDT

MCP: get_project_errors Expected: no new errors. Все вызываемые функции СЛС.* уже определены в Tasks 3–5.

  • Step 3: Commit
git add it/src/CommonForms/РедакцииКонфигурации/Module.bsl
git commit -m "feat: Модуль формы РедакцииКонфигурации — рендер HTML и скролл к фиче"

Task 10: Ручное тестирование по чек-листу спецификации

Files: нет — только визуальная проверка в EDT/конфигураторе.

Эти проверки не автоматизируются (нет YaXUnit-инфраструктуры в проекте), но обязательны перед завершением работы. Если любой пункт провален — возврат к соответствующему Task для исправления.

  • Тест 1 (матрица без параметра)

В EDT или конфигураторе:

  1. Открыть конфигурацию в режиме 1С:Предприятие
  2. Открыть форму через:
    &НаКлиенте
    Процедура ТестОткрытьФорму(Команда)
    ОткрытьФорму("ОбщаяФорма.РедакцииКонфигурации");
    КонецПроцедуры
    (временно добавить в любую доступную форму, либо открыть через e1cib/command/CommonForm.РедакцииКонфигурации)

Ожидаемо: страница отрисовалась полностью; hero-блок с названием и бейджем текущей редакции (цвет соответствует СТАНДАРТ/ПРОФ/КОРП); введение отображается как markdown с жирным шрифтом; таблица содержит все разделы, подразделы и фичи; колонка текущей редакции выделена (более тёмный фон в thead, голубой фон в tbody); строки фич без подсветки.

  • Тест 2 (подсветка фичи)

Вызвать (в тестовой команде):

ПараметрыФормы = Новый Структура("КодФункции", "ИспользоватьCRM");
ОткрытьФорму("ОбщаяФорма.РедакцииКонфигурации", ПараметрыФормы);

Ожидаемо: форма открылась, страница автоматически проскроллилась к строке «Потенциальные клиенты»; строка подсвечена жёлтым фоном с красной левой границей; под названием фичи — красный бейдж «Недоступно в вашей редакции — требуется КОРП».

  • Тест 3 (доступная фича — gating)

Если текущая редакция КОРП (СЛС.РедакцияКонфигурации() = 3) — вызвать:

Результат = СЛСКлиент.ПроверитьДоступностьРедакции("ИспользоватьCRM");
Сообщить("Результат: " + Результат);

Ожидаемо: Результат = Истина, форма не открылась, сообщение «Результат: Да».

Если текущая редакция НЕ КОРП — временно изменить условия для проверки: вызвать с заведомо недоступной фичей и убедиться, что Результат = Ложь и форма открылась.

  • Тест 4 (невалидный макет)
  1. Временно сломать макет: открыть it/src/CommonTemplates/РедакцииКонфигурации/Template.txt, в любой строке фичи убрать символ |, сохранить
  2. Обновить конфигурацию БД
  3. Открыть форму

Ожидаемо: вместо пустой страницы/краша — страница ошибки с текстом типа Макет редакций: ожидается "- Название | Маска", строка N; форма сама не упала, обработчик поймал исключение.

  1. Вернуть макет в исходное состояние
  • Тест 5 (несуществующий код)

Вызвать:

ПараметрыФормы = Новый Структура("КодФункции", "НеСуществующаяКонстанта");
ОткрытьФорму("ОбщаяФорма.РедакцииКонфигурации", ПараметрыФормы);

Ожидаемо: форма отрисовывается как обычно, без подсветки какой-либо строки, без ошибок. СЛС.ФункциональностьДоступна("НеСуществующаяКонстанта") возвращает Истина (см. Task 3) — т.е. клиентский фасад даже не открывает форму при прямом вызове ПроверитьДоступностьРедакции("НеСуществующаяКонстанта").

  • Тест 6 (пустой параметр)
ПараметрыФормы = Новый Структура("КодФункции", "");
ОткрытьФорму("ОбщаяФорма.РедакцииКонфигурации", ПараметрыФормы);

Ожидаемо: форма открывается нормально, без подсветки, без ошибок.

  • Тест 7 (визуальный осмотр)

Пройтись глазами по странице:

  • Все 13 разделов видны, не обрезаны

  • Столбец текущей редакции чётко выделен

  • Примечания (note:) отображаются серым мелким текстом под названием фичи

  • Введение отрендерилось с жирным текстом

  • Нет «ломаных» символов (артефакты от неверной кодировки)

  • На большом экране страница не растянута на всю ширину (max-width работает)

  • Финальный commit (если были правки по тестированию)

Если в ходе тестирования обнаружены и исправлены баги, сделать финальный коммит:

git add -u
git commit -m "fix: Правки по результатам ручного тестирования страницы редакций"

Если багов не было — этот шаг пропускается.


Примечания по реализации

Работа с BSL-файлами

Правило CLAUDE.md запрещает редактировать .bsl файлы через Read/Edit/Write напрямую — только через MCP EDT (read_module_source, write_module_source). Это критично для Tasks 3–6, 9.

Имя модуля ДоксинумШаблоны

В Task 5, Step 2, в процедуре СобратьВведениеРедакций используется вызов:

ПараметрыMD = ДоксинумПарсер.ПараметрыMD(ДоксинумПарсер, ДоксинумШаблоны);

Имя модуля шаблонов (ДоксинумШаблоны) — это предположение. Если get_project_errors в Step 3 сообщит, что такого модуля нет, нужно:

  1. Вызвать MCP list_modules с паттерном Доксинум*
  2. Найти корректное имя модуля шаблонов
  3. Заменить в коде

Альтернатива: найти существующий вызов ДоксинумПарсер.ПараметрыMD( через Grep по .bsl файлам — первый же match покажет правильную сигнатуру.

Использование ПолучитьОбщийМакет

В Task 4 (ПрочитатьМакетРедакций) используется глобальная функция ПолучитьОбщийМакет("РедакцииКонфигурации"). Если платформа или БСП требует других способов получения общего макета — уточнить по существующим вызовам в СЛС или других модулях.

Расширяемость на будущее

Парсер из Task 4 игнорирует неизвестные атрибуты (version=, deprecated= и т.п.) — задел на будущее без изменения кода. Если будет нужно добавлять новые редакции, потребуется:

  1. Расширить маску в ВалидироватьМаскуРедакций (сейчас жёстко СтрДлина(Маска) <> 3)
  2. Добавить колонку в СобратьЗаголовокТаблицыРедакций и цикл в СобратьСтрокуФичиРедакций
  3. Обновить все строки макета: добавить 4-й символ маски
  4. Добавить запись в СЛС.ВариантыРедакцийКонфигурации()

Самоконтроль: покрытие спецификации

Требование спецификацииTask
Markdown-макет с матрицей возможностейTask 2
Грамматика разделов/подразделов/фичTask 4 (парсер)
Маска СПК/-ПК/--КTask 4 (валидация) + Task 5 (отображение)
Атрибут code=Task 4 (парсинг) + Task 5 (id, скролл)
Атрибут note:Task 4 (парсинг) + Task 5 (рендер как .feature-note)
HTML hero-блок с бейджем редакцииTask 5 (СобратьШапкуРедакций)
Введение через ДоксинумПарсерTask 5 (СобратьВведениеРедакций)
Матрица с подсветкой колонки текущей редакцииTask 5 (СобратьЗаголовокТаблицыРедакций, col-current)
Подсветка строки выделенной фичиTask 5 (row-highlighted, feature-unavailable-badge)
CSS-макет css_editionsTask 1
Переиспользование css_markdown_contentTask 5 (СформироватьHTMLРедакций)
Серверная проверка ФункциональностьДоступнаTask 3
Клиентский фасад ПроверитьДоступностьРедакцииTask 6
Обработчик ПриСозданииНаСервере формыTask 9
Обработчик ПриОткрытии со скролломTask 9
HTML ошибки при невалидном макетеTask 5 (HTMLОшибкиМакетаРедакций) + Task 9 (ловит Исключение)
Реквизиты ТекстHTML, КодФункцииTask 7
Элемент ПолеHTMLДокументаTask 8
7 сценариев тестированияTask 10