Add /form-add skill for configuration objects

Create forms (metadata XML + Form.xml + Module.bsl) for Document,
Catalog, InformationRegister and other configuration object types.
Supports Object/List/Choice/Record purposes with automatic
ChildObjects registration and DefaultForm setup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-02-09 22:53:13 +03:00
parent 89f0788585
commit 6681758121
5 changed files with 707 additions and 2 deletions
+91
View File
@@ -0,0 +1,91 @@
---
name: form-add
description: Добавить управляемую форму к объекту конфигурации 1С
argument-hint: <ObjectPath> <FormName> [Purpose] [--set-default]
allowed-tools:
- Bash
- Read
- Write
- Edit
- Glob
- Grep
---
# /form-add — Добавление формы к объекту конфигурации
Создаёт управляемую форму (metadata XML + Form.xml + Module.bsl) и регистрирует её в корневом XML объекта конфигурации (Document, Catalog, InformationRegister и др.).
## Usage
```
/form-add <ObjectPath> <FormName> [Purpose] [Synonym] [--set-default]
```
| Параметр | Обязательный | По умолчанию | Описание |
|-------------|:------------:|--------------|----------------------------------------------|
| ObjectPath | да | — | Путь к XML-файлу объекта (Documents/Док.xml) |
| FormName | да | — | Имя формы (ФормаДокумента) |
| Purpose | нет | Object | Назначение: Object, List, Choice, Record |
| Synonym | нет | = FormName | Синоним формы |
| --set-default | нет | авто | Установить как форму по умолчанию |
## Команда
```powershell
powershell.exe -NoProfile -File .claude\skills\form-add\scripts\form-add.ps1 -ObjectPath "<ObjectPath>" -FormName "<FormName>" [-Purpose "<Purpose>"] [-Synonym "<Synonym>"] [-SetDefault]
```
## Purpose — назначение формы
| Purpose | Допустимые типы объектов | Основной реквизит | DefaultForm-свойство |
|---------|-------------------------|-------------------|---------------------|
| Object | Document, Catalog, DataProcessor, Report, ChartOf*, ExchangePlan, BusinessProcess, Task | Объект (тип: *Object.Имя) | DefaultObjectForm (DefaultForm для DataProcessor/Report) |
| List | Все кроме DataProcessor | Список (DynamicList) | DefaultListForm |
| Choice | Document, Catalog, ChartOf*, ExchangePlan, BusinessProcess, Task | Список (DynamicList) | DefaultChoiceForm |
| Record | InformationRegister | Запись (InformationRegisterRecordManager) | DefaultRecordForm |
## Что создаётся
```
<ObjectDir>/Forms/
├── <FormName>.xml # Метаданные формы (UUID)
└── <FormName>/
└── Ext/
├── Form.xml # Описание формы (logform namespace)
└── Form/
└── Module.bsl # BSL-модуль с 5 регионами + ПриСозданииНаСервере
```
## Что модифицируется
- `<ObjectPath>` — добавляется `<Form>` в `ChildObjects` (перед `<Template>` или `<TabularSection>`), обновляется Default*Form (автоматически если пустое, или явно при `--set-default`)
## Поддерживаемые типы объектов
Document, Catalog, DataProcessor, Report, InformationRegister, ChartOfAccounts, ChartOfCharacteristicTypes, ExchangePlan, BusinessProcess, Task
## Примеры
```
# Форма документа
/form-add Documents/АвансовыйОтчет.xml ФормаДокумента --purpose Object
# Форма списка каталога
/form-add Catalogs/Контрагенты.xml ФормаСписка --purpose List
# Форма записи регистра сведений
/form-add InformationRegisters/КурсыВалют.xml ФормаЗаписи --purpose Record
# Форма выбора с синонимом
/form-add Catalogs/Номенклатура.xml ФормаВыбора --purpose Choice --synonym "Выбор номенклатуры"
# Установить как форму по умолчанию
/form-add Documents/Заказ.xml ФормаДокументаНовая --purpose Object --set-default
```
## Workflow
1. `/form-add` — создать каркас формы
2. `/form-compile` или `/form-edit` — наполнить Form.xml элементами
3. `/form-validate` — проверить корректность
4. `/form-info` — проанализировать результат
@@ -0,0 +1,435 @@
param(
[Parameter(Mandatory)]
[string]$ObjectPath,
[Parameter(Mandatory)]
[string]$FormName,
[string]$Synonym = $FormName,
[string]$Purpose = "Object",
[switch]$SetDefault
)
$ErrorActionPreference = "Stop"
# --- Фаза 1: Определение типа объекта ---
if (-not (Test-Path $ObjectPath)) {
Write-Error "Файл объекта не найден: $ObjectPath"
exit 1
}
$objectXmlFull = Resolve-Path $ObjectPath
$xmlDoc = New-Object System.Xml.XmlDocument
$xmlDoc.PreserveWhitespace = $true
$xmlDoc.Load($objectXmlFull.Path)
$nsMgr = New-Object System.Xml.XmlNamespaceManager($xmlDoc.NameTable)
$nsMgr.AddNamespace("md", "http://v8.1c.ru/8.3/MDClasses")
$nsMgr.AddNamespace("v8", "http://v8.1c.ru/8.1/data/core")
# Определяем тип объекта по корневому тегу внутри MetaDataObject
$metaDataObject = $xmlDoc.SelectSingleNode("//md:MetaDataObject", $nsMgr)
if (-not $metaDataObject) {
# Пробуем без namespace (fallback)
$metaDataObject = $xmlDoc.DocumentElement
}
$supportedTypes = @(
"Document", "Catalog", "DataProcessor", "Report",
"InformationRegister", "ChartOfAccounts", "ChartOfCharacteristicTypes",
"ExchangePlan", "BusinessProcess", "Task"
)
$objectType = $null
$objectNode = $null
foreach ($t in $supportedTypes) {
$node = $xmlDoc.SelectSingleNode("//md:$t", $nsMgr)
if ($node) {
$objectType = $t
$objectNode = $node
break
}
}
if (-not $objectType) {
Write-Error "Не удалось определить тип объекта. Поддерживаемые типы: $($supportedTypes -join ', ')"
exit 1
}
# Имя объекта из Properties/Name
$objectName = $xmlDoc.SelectSingleNode("//md:${objectType}/md:Properties/md:Name", $nsMgr).InnerText
if (-not $objectName) {
Write-Error "Не удалось определить имя объекта из Properties/Name"
exit 1
}
Write-Host ""
Write-Host "=== form-add ==="
Write-Host ""
Write-Host "Object: $objectType.$objectName"
# --- Фаза 2: Валидация Purpose ---
$Purpose = $Purpose.Substring(0,1).ToUpper() + $Purpose.Substring(1).ToLower()
# Нормализация
switch ($Purpose) {
"Object" { }
"List" { }
"Choice" { }
"Record" { }
default {
Write-Error "Недопустимое назначение: $Purpose. Допустимые: Object, List, Choice, Record"
exit 1
}
}
$objectLikeTypes = @("Document", "Catalog", "ChartOfAccounts", "ChartOfCharacteristicTypes", "ExchangePlan", "BusinessProcess", "Task")
$processorLikeTypes = @("DataProcessor", "Report")
switch ($Purpose) {
"Object" {
# допустимо для всех типов
}
"List" {
if ($objectType -eq "DataProcessor") {
Write-Error "Purpose=List недопустим для DataProcessor"
exit 1
}
}
"Choice" {
if ($objectType -in $processorLikeTypes -or $objectType -eq "InformationRegister") {
Write-Error "Purpose=Choice недопустим для $objectType"
exit 1
}
}
"Record" {
if ($objectType -ne "InformationRegister") {
Write-Error "Purpose=Record допустим только для InformationRegister"
exit 1
}
}
}
# --- Фаза 3: Создание файлов ---
$objectDir = [System.IO.Path]::ChangeExtension($objectXmlFull.Path, $null).TrimEnd('.')
$formsDir = Join-Path $objectDir "Forms"
$formMetaPath = Join-Path $formsDir "$FormName.xml"
if (Test-Path $formMetaPath) {
Write-Error "Форма уже существует: $formMetaPath"
exit 1
}
$formDir = Join-Path $formsDir $FormName
$formExtDir = Join-Path $formDir "Ext"
$formModuleDir = Join-Path $formExtDir "Form"
New-Item -ItemType Directory -Path $formModuleDir -Force | Out-Null
$encBom = New-Object System.Text.UTF8Encoding($true)
# --- 3a. Метаданные формы ---
$formUuid = [guid]::NewGuid().ToString()
$formMetaXml = @"
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:cmi="http://v8.1c.ru/8.2/managed-application/cmi" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xen="http://v8.1c.ru/8.3/xcf/enums" xmlns:xpr="http://v8.1c.ru/8.3/xcf/predef" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.17">
<Form uuid="$formUuid">
<Properties>
<Name>$FormName</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>$Synonym</v8:content>
</v8:item>
</Synonym>
<Comment/>
<FormType>Managed</FormType>
<IncludeHelpInContents>false</IncludeHelpInContents>
<UsePurposes>
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
<v8:Value xsi:type="app:ApplicationUsePurpose">MobilePlatformApplication</v8:Value>
</UsePurposes>
<ExtendedPresentation/>
</Properties>
</Form>
</MetaDataObject>
"@
[System.IO.File]::WriteAllText($formMetaPath, $formMetaXml, $encBom)
# --- 3b. Form.xml ---
$formXmlPath = Join-Path $formExtDir "Form.xml"
$formNsDecl = 'xmlns="http://v8.1c.ru/8.3/xcf/logform" xmlns:app="http://v8.1c.ru/8.2/managed-application/core" xmlns:cfg="http://v8.1c.ru/8.1/data/enterprise/current-config" xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core" xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings" xmlns:ent="http://v8.1c.ru/8.1/data/enterprise" xmlns:lf="http://v8.1c.ru/8.2/managed-application/logform" xmlns:style="http://v8.1c.ru/8.1/data/ui/style" xmlns:sys="http://v8.1c.ru/8.1/data/ui/fonts/system" xmlns:v8="http://v8.1c.ru/8.1/data/core" xmlns:v8ui="http://v8.1c.ru/8.1/data/ui" xmlns:web="http://v8.1c.ru/8.1/data/ui/colors/web" xmlns:win="http://v8.1c.ru/8.1/data/ui/colors/windows" xmlns:xr="http://v8.1c.ru/8.3/xcf/readable" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"'
if ($Purpose -eq "List" -or $Purpose -eq "Choice") {
# Динамический список
# MainTable: тип.имя
$mainTable = "$objectType.$objectName"
$formXml = @"
<?xml version="1.0" encoding="UTF-8"?>
<Form $formNsDecl version="2.17">
<AutoCommandBar name="ФормаКоманднаяПанель" id="-1">
<Autofill>true</Autofill>
</AutoCommandBar>
<Events>
<Event name="OnCreateAtServer">ПриСозданииНаСервере</Event>
</Events>
<ChildItems/>
<Attributes>
<Attribute name="Список" id="1">
<Type>
<v8:Type>cfg:DynamicList</v8:Type>
</Type>
<MainAttribute>true</MainAttribute>
<Settings xsi:type="DynamicList">
<MainTable>$mainTable</MainTable>
</Settings>
</Attribute>
</Attributes>
</Form>
"@
} elseif ($Purpose -eq "Record") {
# Запись регистра сведений
$mainAttrName = "Запись"
$mainAttrType = "InformationRegisterRecordManager.$objectName"
$formXml = @"
<?xml version="1.0" encoding="UTF-8"?>
<Form $formNsDecl version="2.17">
<AutoCommandBar name="ФормаКоманднаяПанель" id="-1">
<Autofill>true</Autofill>
</AutoCommandBar>
<Events>
<Event name="OnCreateAtServer">ПриСозданииНаСервере</Event>
</Events>
<ChildItems/>
<Attributes>
<Attribute name="$mainAttrName" id="1">
<Type>
<v8:Type>cfg:$mainAttrType</v8:Type>
</Type>
<MainAttribute>true</MainAttribute>
<SavedData>true</SavedData>
</Attribute>
</Attributes>
</Form>
"@
} else {
# Object — форма объекта
$mainAttrName = "Объект"
# Маппинг типа объекта на тип реквизита
$attrTypeMap = @{
"Document" = "DocumentObject"
"Catalog" = "CatalogObject"
"DataProcessor" = "DataProcessorObject"
"Report" = "ReportObject"
"ChartOfAccounts" = "ChartOfAccountsObject"
"ChartOfCharacteristicTypes" = "ChartOfCharacteristicTypesObject"
"ExchangePlan" = "ExchangePlanObject"
"BusinessProcess" = "BusinessProcessObject"
"Task" = "TaskObject"
"InformationRegister" = "InformationRegisterRecordManager"
}
$mainAttrType = "$($attrTypeMap[$objectType]).$objectName"
$formXml = @"
<?xml version="1.0" encoding="UTF-8"?>
<Form $formNsDecl version="2.17">
<AutoCommandBar name="ФормаКоманднаяПанель" id="-1">
<Autofill>true</Autofill>
</AutoCommandBar>
<Events>
<Event name="OnCreateAtServer">ПриСозданииНаСервере</Event>
</Events>
<ChildItems/>
<Attributes>
<Attribute name="$mainAttrName" id="1">
<Type>
<v8:Type>cfg:$mainAttrType</v8:Type>
</Type>
<MainAttribute>true</MainAttribute>
<SavedData>true</SavedData>
</Attribute>
</Attributes>
</Form>
"@
}
[System.IO.File]::WriteAllText($formXmlPath, $formXml, $encBom)
# --- 3c. Module.bsl ---
$modulePath = Join-Path $formModuleDir "Module.bsl"
$moduleBsl = @"
#Область ОбработчикиСобытийФормы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовФормы
#КонецОбласти
#Область ОбработчикиКомандФормы
#КонецОбласти
#Область ОбработчикиОповещений
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
#КонецОбласти
"@
[System.IO.File]::WriteAllText($modulePath, $moduleBsl, $encBom)
# --- Фаза 4: Регистрация в родительском объекте ---
$childObjects = $xmlDoc.SelectSingleNode("//md:${objectType}/md:ChildObjects", $nsMgr)
if (-not $childObjects) {
Write-Error "Не найден элемент ChildObjects в $ObjectPath"
exit 1
}
# Добавить <Form>$FormName</Form>
$formElem = $xmlDoc.CreateElement("Form", "http://v8.1c.ru/8.3/MDClasses")
$formElem.InnerText = $FormName
# Ищем первый <Template> для вставки перед ним
$firstTemplate = $childObjects.SelectSingleNode("md:Template", $nsMgr)
# Ищем первую <TabularSection> для вставки перед ней (если нет Template)
$firstTabular = $childObjects.SelectSingleNode("md:TabularSection", $nsMgr)
# Определяем точку вставки: перед Template, перед TabularSection, или в конец
$insertBefore = $null
if ($firstTemplate) {
$insertBefore = $firstTemplate
} elseif ($firstTabular) {
$insertBefore = $firstTabular
}
if ($insertBefore) {
# Вставить перед найденным элементом, с переносом строки
$whitespace = $xmlDoc.CreateWhitespace("`n`t`t`t")
$childObjects.InsertBefore($formElem, $insertBefore) | Out-Null
$childObjects.InsertBefore($whitespace, $formElem) | Out-Null
# Переставляем: whitespace перед formElem — неправильный порядок
# Правильно: formElem, затем whitespace перед insertBefore
# InsertBefore возвращает вставленный узел, порядок: ... formElem whitespace insertBefore ...
# На самом деле нам нужно: ... \n\t\t\tformElem \n\t\t\tinsertBefore
# Удалим и вставим правильно
$childObjects.RemoveChild($whitespace) | Out-Null
$childObjects.RemoveChild($formElem) | Out-Null
$childObjects.InsertBefore($formElem, $insertBefore) | Out-Null
# Whitespace нужен ДО formElem (перенос строки + отступ)
# Но перед insertBefore уже должен быть whitespace от предыдущего элемента
# Нам нужно добавить whitespace ПОСЛЕ formElem (перед insertBefore)
$ws = $xmlDoc.CreateWhitespace("`n`t`t`t")
$childObjects.InsertBefore($ws, $insertBefore) | Out-Null
} else {
# Добавить в конец ChildObjects
if ($childObjects.ChildNodes.Count -eq 0) {
$childObjects.AppendChild($xmlDoc.CreateWhitespace("`n`t`t`t")) | Out-Null
$childObjects.AppendChild($formElem) | Out-Null
$childObjects.AppendChild($xmlDoc.CreateWhitespace("`n`t`t")) | Out-Null
} else {
$lastChild = $childObjects.LastChild
if ($lastChild.NodeType -eq [System.Xml.XmlNodeType]::Whitespace) {
$childObjects.InsertBefore($xmlDoc.CreateWhitespace("`n`t`t`t"), $lastChild) | Out-Null
$childObjects.InsertBefore($formElem, $lastChild) | Out-Null
} else {
$childObjects.AppendChild($xmlDoc.CreateWhitespace("`n`t`t`t")) | Out-Null
$childObjects.AppendChild($formElem) | Out-Null
$childObjects.AppendChild($xmlDoc.CreateWhitespace("`n`t`t")) | Out-Null
}
}
}
# --- SetDefault ---
$existingForms = $childObjects.SelectNodes("md:Form", $nsMgr)
$isFirstFormForPurpose = $false
$defaultPropName = $null
$defaultValue = "$objectType.$objectName.Form.$FormName"
# Определяем имя свойства для DefaultForm
switch ($Purpose) {
"Object" {
if ($objectType -in $processorLikeTypes) {
$defaultPropName = "DefaultForm"
} else {
$defaultPropName = "DefaultObjectForm"
}
}
"List" { $defaultPropName = "DefaultListForm" }
"Choice" { $defaultPropName = "DefaultChoiceForm" }
"Record" { $defaultPropName = "DefaultRecordForm" }
}
# Проверяем, установлено ли уже значение
$defaultNode = $xmlDoc.SelectSingleNode("//md:${objectType}/md:Properties/md:$defaultPropName", $nsMgr)
if ($defaultNode) {
$isFirstFormForPurpose = [string]::IsNullOrWhiteSpace($defaultNode.InnerText)
}
$defaultUpdated = $false
if ($SetDefault -or $isFirstFormForPurpose) {
if ($defaultNode) {
$defaultNode.InnerText = $defaultValue
$defaultUpdated = $true
}
}
# Сохранить с BOM
$settings = New-Object System.Xml.XmlWriterSettings
$settings.Encoding = $encBom
$settings.Indent = $false
$stream = New-Object System.IO.FileStream($objectXmlFull.Path, [System.IO.FileMode]::Create)
$writer = [System.Xml.XmlWriter]::Create($stream, $settings)
$xmlDoc.Save($writer)
$writer.Close()
$stream.Close()
# --- Фаза 5: Вывод ---
# Относительные пути для вывода
$basePath = Split-Path $objectXmlFull.Path -Parent
# Определяем корень (ищем родительский каталог типа Documents, Catalogs и т.д.)
$relFormMeta = $formMetaPath.Replace($basePath, "").TrimStart("\", "/")
$relFormXml = $formXmlPath.Replace($basePath, "").TrimStart("\", "/")
$relModule = $modulePath.Replace($basePath, "").TrimStart("\", "/")
$objFileName = [System.IO.Path]::GetFileName($ObjectPath)
$objDirName = Split-Path $ObjectPath -Parent
$objBaseName = [System.IO.Path]::GetFileNameWithoutExtension($ObjectPath)
Write-Host "Created:"
Write-Host " Metadata: $objDirName\$objBaseName\Forms\$FormName.xml"
Write-Host " Form: $objDirName\$objBaseName\Forms\$FormName\Ext\Form.xml"
Write-Host " Module: $objDirName\$objBaseName\Forms\$FormName\Ext\Form\Module.bsl"
Write-Host ""
Write-Host "Registered: <Form>$FormName</Form> in ChildObjects"
if ($defaultUpdated) {
Write-Host "${defaultPropName}: $defaultValue"
}
Write-Host ""
+2 -1
View File
@@ -21,7 +21,7 @@
|--------|--------|----------|------|
| Внешние обработки (EPF) | 10 навыков `/epf-*` | Создание, модификация, сборка обработок из XML-исходников | [Подробнее](docs/epf-guide.md) |
| Табличный документ (MXL) | 4 навыка `/mxl-*` | Анализ, создание, компиляция макетов печатных форм | [Подробнее](docs/mxl-guide.md) |
| Управляемые формы (Form) | 5 навыков `/form-*` | Анализ, генерация, модификация, валидация управляемых форм | [Подробнее](docs/form-guide.md) |
| Управляемые формы (Form) | 6 навыков `/form-*` | Создание, анализ, генерация, модификация, валидация управляемых форм | [Подробнее](docs/form-guide.md) |
| Роли (Role) | 2 навыка `/role-*` | Анализ прав роли, создание роли из описания | [Подробнее](docs/role-guide.md) |
| Утилиты | `/img-grid` | Наложение сетки на изображение для определения пропорций колонок | — |
@@ -59,6 +59,7 @@
├── mxl-validate/ # Валидация макета
├── mxl-compile/ # Компиляция макета из JSON
├── mxl-decompile/ # Декомпиляция макета в JSON
├── form-add/ # Добавление формы к объекту конфигурации
├── form-info/ # Анализ структуры управляемой формы
├── form-compile/ # Компиляция формы из JSON
├── form-validate/ # Валидация формы
+151
View File
@@ -5,6 +5,157 @@
---
## 0. Файловая структура и регистрация
### Файлы формы
Каждая форма объекта конфигурации состоит из 3 файлов:
```
<Объект>/Forms/
ИмяФормы.xml ← метаданные (UUID, имя, синоним, FormType)
ИмяФормы/
Ext/
Form.xml ← определение формы (описано в разделах 1–17)
Form/
Module.bsl ← модуль формы (1С-код)
```
Общие формы (CommonForm) — аналогично, но на верхнем уровне конфигурации:
```
CommonForms/
ИмяФормы.xml ← метаданные (тег <CommonForm>)
ИмяФормы/
Ext/
Form.xml
Form/
Module.bsl
```
### Метаданные формы — шаблон
#### Форма объекта (Document, Catalog, DataProcessor, Report, ...)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses"
xmlns:app="http://v8.1c.ru/8.2/managed-application/core"
xmlns:v8="http://v8.1c.ru/8.1/data/core"
xmlns:xr="http://v8.1c.ru/8.3/xcf/readable"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.17">
<Form uuid="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX">
<Properties>
<Name>ИмяФормы</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Отображаемое имя</v8:content>
</v8:item>
</Synonym>
<Comment/>
<FormType>Managed</FormType>
<IncludeHelpInContents>false</IncludeHelpInContents>
<UsePurposes>
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
<v8:Value xsi:type="app:ApplicationUsePurpose">MobilePlatformApplication</v8:Value>
</UsePurposes>
</Properties>
</Form>
</MetaDataObject>
```
#### CommonForm
```xml
<?xml version="1.0" encoding="UTF-8"?>
<MetaDataObject xmlns="http://v8.1c.ru/8.3/MDClasses"
xmlns:app="http://v8.1c.ru/8.2/managed-application/core"
xmlns:v8="http://v8.1c.ru/8.1/data/core"
xmlns:xr="http://v8.1c.ru/8.3/xcf/readable"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.17">
<CommonForm uuid="XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX">
<Properties>
<Name>ИмяФормы</Name>
<Synonym>
<v8:item>
<v8:lang>ru</v8:lang>
<v8:content>Отображаемое имя</v8:content>
</v8:item>
</Synonym>
<Comment/>
<FormType>Managed</FormType>
<IncludeHelpInContents>false</IncludeHelpInContents>
<UseStandardCommands>false</UseStandardCommands>
<ExtendedPresentation/>
<Explanation/>
<UsePurposes>
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
<v8:Value xsi:type="app:ApplicationUsePurpose">MobilePlatformApplication</v8:Value>
</UsePurposes>
</Properties>
</CommonForm>
</MetaDataObject>
```
### Регистрация формы
#### В ChildObjects родительского объекта
```xml
<!-- В файле Documents/АвансовыйОтчет.xml (или Catalogs/Контрагенты.xml и т.д.) -->
<ChildObjects>
<Form>ФормаДокумента</Form>
<Form>ФормаСписка</Form>
...
</ChildObjects>
```
CommonForms регистрируются в `Configuration.xml`:
```xml
<ChildObjects>
<CommonForm>ИмяФормы</CommonForm>
...
</ChildObjects>
```
#### DefaultForm в Properties родительского объекта
Формат значения: `ТипОбъекта.ИмяОбъекта.Form.ИмяФормы`
```xml
<Properties>
<DefaultObjectForm>Document.АвансовыйОтчет.Form.ФормаДокумента</DefaultObjectForm>
<DefaultListForm>Document.АвансовыйОтчет.Form.ФормаСписка</DefaultListForm>
<DefaultChoiceForm>Document.АвансовыйОтчет.Form.ФормаВыбора</DefaultChoiceForm>
</Properties>
```
#### Свойства DefaultForm по типам объектов
| Тип объекта | Свойства DefaultForm |
|-------------|---------------------|
| Document | DefaultObjectForm, DefaultListForm, DefaultChoiceForm |
| Catalog | DefaultObjectForm, DefaultFolderForm, DefaultListForm, DefaultChoiceForm, DefaultFolderChoiceForm |
| ChartOfCharacteristicTypes | DefaultObjectForm, DefaultFolderForm, DefaultListForm, DefaultChoiceForm, DefaultFolderChoiceForm |
| ChartOfAccounts | DefaultObjectForm, DefaultListForm, DefaultChoiceForm |
| DataProcessor | DefaultForm |
| Report | DefaultForm |
| InformationRegister | DefaultRecordForm, DefaultListForm |
| ExchangePlan | DefaultObjectForm, DefaultListForm, DefaultChoiceForm |
| BusinessProcess | DefaultObjectForm, DefaultListForm, DefaultChoiceForm |
| Task | DefaultObjectForm, DefaultListForm, DefaultChoiceForm |
| CommonForm | — (регистрируется в Configuration.xml, нет DefaultForm) |
> Report.DefaultForm может указывать на общую форму: `CommonForm.ФормаОтчета`.
---
## 1. Корневой элемент
```xml
+28 -1
View File
@@ -6,6 +6,7 @@
| Навык | Параметры | Описание |
|-------|-----------|----------|
| `/form-add` | `<ObjectPath> <FormName> [Purpose]` | Добавление формы к объекту конфигурации (Document, Catalog и др.) |
| `/form-info` | `<FormPath>` | Компактная сводка: дерево элементов, реквизиты, команды, события |
| `/form-compile` | `<JsonPath> <OutputPath>` | Генерация Form.xml из компактного JSON-определения |
| `/form-validate` | `<FormPath>` | Валидация: уникальность ID, companions, DataPath, команды |
@@ -14,6 +15,23 @@
## Сценарии использования
### Добавление новой формы к объекту конфигурации
`/form-add` создаёт каркас управляемой формы (metadata XML + Form.xml + Module.bsl) и регистрирует её в объекте конфигурации. Поддерживает Document, Catalog, DataProcessor, Report, InformationRegister и другие типы.
```
> Добавь форму документа к Documents/АвансовыйОтчет.xml
```
Claude вызовет `/form-add` с нужными параметрами. Назначение формы (Purpose) определяет структуру: Object — форма объекта с реквизитом «Объект», List/Choice — форма списка с DynamicList, Record — форма записи регистра.
Типичный workflow:
1. `/form-add` — создать каркас (metadata + Form.xml + Module.bsl)
2. `/form-compile` или `/form-edit` — наполнить Form.xml элементами
3. `/form-validate` — проверить корректность
4. `/form-info` — проанализировать результат
### Анализ формы перед модификацией
Файлы Form.xml содержат от сотен до десятков тысяч строк XML. 80% объёма — визуальный шум (цвета, шрифты, размеры, автогенерированные подсказки). `/form-info` извлекает суть.
@@ -199,7 +217,16 @@ Claude создаст JSON-определение и вызовет `/form-compi
## Связь с EPF-навыками
Навыки `/form-*` работают с формами из любых источников — конфигурации и внешних обработок. При работе с обработками:
Навыки `/form-*` работают с формами из любых источников — конфигурации и внешних обработок.
При работе с объектами конфигурации:
1. `/form-add` — создать форму (каркас + регистрация в объекте)
2. `/form-compile` или `/form-edit` — наполнить Form.xml элементами
3. `/form-validate` — проверить корректность
4. `/form-info` — проанализировать результат
При работе с внешними обработками:
1. `/epf-add-form` — создать форму (каркас)
2. `/form-compile` — сгенерировать Form.xml из JSON-определения