feat(cf-init): генерить Ext/ClientApplicationInterface.xml с ERP-дефолтом

Без этого файла веб-клиент 1С рендерит секции icon-only (без подписей),
а web-test их не видит. Дефолтная раскладка как в типовых ERP/БП ≥ 8.3.24:
панель открытых сверху, панель разделов слева; функций/избранного/истории
объявлены через panelDef но не размещены.

Расширил docs/1c-configuration-spec.md § 4.2 моделью раскладки и таблицей
UUID 5 платформенных панелей. Обновил снапшоты cf-init под новый файл.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-05-01 16:43:39 +03:00
parent d75b4d96ca
commit 3c3ed2ff46
13 changed files with 254 additions and 27 deletions
+35 -1
View File
@@ -1,4 +1,4 @@
# cf-init v1.1 — Create empty 1C configuration scaffold
# cf-init v1.2 — Create empty 1C configuration scaffold
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
param(
[Parameter(Mandatory)]
@@ -192,6 +192,33 @@ $langXml = @"
</MetaDataObject>
"@
# --- Ext/ClientApplicationInterface.xml (default ERP-style panel layout) ---
# Open panel on top, Sections panel on left; Functions/Favorites/History declared
# via panelDef but not placed by default. Without this file the web client renders
# section icons without labels (icon-only mode).
$openPanelInst = [guid]::NewGuid().ToString()
$sectionsPanelInst = [guid]::NewGuid().ToString()
$caiXml = @"
<?xml version="1.0" encoding="UTF-8"?>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
<top>
<panel id="$openPanelInst">
<uuid>cbab57f2-a0f3-4f0a-89ea-4cb19570ab75</uuid>
</panel>
</top>
<left>
<panel id="$sectionsPanelInst">
<uuid>b553047f-c9aa-4157-978d-448ecad24248</uuid>
</panel>
</left>
<panelDef id="b553047f-c9aa-4157-978d-448ecad24248"/>
<panelDef id="13322b22-3960-4d68-93a6-fe2dd7f28ca3"/>
<panelDef id="c933ac92-92cd-459d-81cc-e0c8a83ced99"/>
<panelDef id="cbab57f2-a0f3-4f0a-89ea-4cb19570ab75"/>
<panelDef id="b2735bd3-d822-4430-ba59-c9e869693b24"/>
</ClientApplicationInterface>
"@
# --- Create directories ---
if (-not (Test-Path $OutputDir)) {
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
@@ -200,6 +227,10 @@ $langDir = Join-Path $OutputDir "Languages"
if (-not (Test-Path $langDir)) {
New-Item -ItemType Directory -Path $langDir -Force | Out-Null
}
$extDir = Join-Path $OutputDir "Ext"
if (-not (Test-Path $extDir)) {
New-Item -ItemType Directory -Path $extDir -Force | Out-Null
}
# --- Write files with UTF-8 BOM ---
$enc = New-Object System.Text.UTF8Encoding($true)
@@ -207,9 +238,12 @@ $enc = New-Object System.Text.UTF8Encoding($true)
[System.IO.File]::WriteAllText($cfgFile, $cfgXml, $enc)
$langFile = Join-Path $langDir "Русский.xml"
[System.IO.File]::WriteAllText($langFile, $langXml, $enc)
$caiFile = Join-Path $extDir "ClientApplicationInterface.xml"
[System.IO.File]::WriteAllText($caiFile, $caiXml, $enc)
# --- Output ---
Write-Host "[OK] Создана конфигурация: $Name"
Write-Host " Каталог: $OutputDir"
Write-Host " Configuration.xml: $cfgFile"
Write-Host " Languages: $langFile"
Write-Host " Ext/CAI: $caiFile"
+31 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# cf-init v1.1 — Create empty 1C configuration scaffold
# cf-init v1.2 — Create empty 1C configuration scaffold
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
"""Generates minimal XML source files for a 1C configuration."""
import sys, os, argparse, uuid
@@ -184,20 +184,50 @@ def main():
\t</Language>
</MetaDataObject>'''
# --- Ext/ClientApplicationInterface.xml (default ERP-style panel layout) ---
# Open panel on top, Sections panel on left; Functions/Favorites/History declared
# via panelDef but not placed by default. Without this file the web client renders
# section icons without labels (icon-only mode).
open_panel_inst = new_uuid()
sections_panel_inst = new_uuid()
cai_xml = f'''<?xml version="1.0" encoding="UTF-8"?>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
\t<top>
\t\t<panel id="{open_panel_inst}">
\t\t\t<uuid>cbab57f2-a0f3-4f0a-89ea-4cb19570ab75</uuid>
\t\t</panel>
\t</top>
\t<left>
\t\t<panel id="{sections_panel_inst}">
\t\t\t<uuid>b553047f-c9aa-4157-978d-448ecad24248</uuid>
\t\t</panel>
\t</left>
\t<panelDef id="b553047f-c9aa-4157-978d-448ecad24248"/>
\t<panelDef id="13322b22-3960-4d68-93a6-fe2dd7f28ca3"/>
\t<panelDef id="c933ac92-92cd-459d-81cc-e0c8a83ced99"/>
\t<panelDef id="cbab57f2-a0f3-4f0a-89ea-4cb19570ab75"/>
\t<panelDef id="b2735bd3-d822-4430-ba59-c9e869693b24"/>
</ClientApplicationInterface>'''
# --- Create directories ---
os.makedirs(output_dir, exist_ok=True)
lang_dir = os.path.join(output_dir, "Languages")
os.makedirs(lang_dir, exist_ok=True)
ext_dir = os.path.join(output_dir, "Ext")
os.makedirs(ext_dir, exist_ok=True)
# --- Write files ---
write_utf8_bom(cfg_file, cfg_xml)
lang_file = os.path.join(lang_dir, "Русский.xml")
write_utf8_bom(lang_file, lang_xml)
cai_file = os.path.join(ext_dir, "ClientApplicationInterface.xml")
write_utf8_bom(cai_file, cai_xml)
print(f"[OK] Создана конфигурация: {name}")
print(f" Каталог: {output_dir}")
print(f" Configuration.xml: {cfg_file}")
print(f" Languages: {lang_file}")
print(f" Ext/CAI: {cai_file}")
if __name__ == '__main__':
main()
+39 -7
View File
@@ -381,20 +381,52 @@ ClassId — фиксированные идентификаторы классо
Подробнее: [1c-subsystem-spec.md § 4](1c-subsystem-spec.md#4-формат-командного-интерфейса-commandinterfacexml).
**ClientApplicationInterface.xml** — расположение панелей (top/left/bottom/right):
**ClientApplicationInterface.xml** — расположение панелей рабочего пространства Taxi.
Структура: четыре стороны (`top`, `left`, `right`, `bottom`), внутри каждой произвольная комбинация `<panel>` и `<group>`. Список объявленных панелей — `<panelDef>` на верхнем уровне.
```xml
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" ...>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" ... xsi:type="InterfaceLayouter">
<top>
<group id="...">
<group><panel id="..."><uuid>...</uuid></panel></group>
...
</group>
<panel id="<arbitrary-uuid>"><uuid>cbab57f2-a0f3-4f0a-89ea-4cb19570ab75</uuid></panel>
</top>
<left>...</left>
<left>
<panel id="<arbitrary-uuid>"><uuid>b553047f-c9aa-4157-978d-448ecad24248</uuid></panel>
</left>
<right>
<group id="<arbitrary-uuid>">
<group><panel id="..."><uuid>13322b22-...</uuid></panel></group>
<group><panel id="..."><uuid>c933ac92-...</uuid></panel></group>
</group>
</right>
<panelDef id="b553047f-c9aa-4157-978d-448ecad24248"/>
<panelDef id="cbab57f2-a0f3-4f0a-89ea-4cb19570ab75"/>
<panelDef id="13322b22-3960-4d68-93a6-fe2dd7f28ca3"/>
<panelDef id="c933ac92-92cd-459d-81cc-e0c8a83ced99"/>
<panelDef id="b2735bd3-d822-4430-ba59-c9e869693b24"/>
</ClientApplicationInterface>
```
**UUID платформенных панелей** (фиксированные константы во всех конфигурациях):
| UUID | Панель |
|------|--------|
| `cbab57f2-a0f3-4f0a-89ea-4cb19570ab75` | Панель открытых |
| `b553047f-c9aa-4157-978d-448ecad24248` | Панель разделов |
| `13322b22-3960-4d68-93a6-fe2dd7f28ca3` | Панель избранного |
| `c933ac92-92cd-459d-81cc-e0c8a83ced99` | Панель истории |
| `b2735bd3-d822-4430-ba59-c9e869693b24` | Панель функций текущего раздела |
**Семантика контейнеров:**
- Несколько прямых child-узлов внутри `<top>`/`<left>`/`<right>`/`<bottom>` располагаются **рядом** друг с другом (отдельные слоты на стороне).
- `<group id="...">` — контейнер-«ячейка»: вложенные `<panel>`/`<group>` располагаются **друг под другом** (стек).
- Атрибут `id` у `<group>` и `<panel>` — произвольный uuid экземпляра (Конфигуратор генерирует свой при сохранении). Привязка к платформенной панели — только через `<uuid>` внутри `<panel>`.
- `<panelDef id="...">` объявляет, что панель доступна пользователю. Если панель не размещена в `top/left/right/bottom`, она остаётся скрытой, но доступна через «Вид → Настройка панелей».
**Дефолтная раскладка** (как в типовых ERP/БП ≥ 8.3.24): «Панель открытых» в `top`, «Панель разделов» в `left`; «Функций», «Избранного», «История» — только в `panelDef`, по умолчанию не размещены.
> Замечание: в типовых конфигурациях встречается также `<panelDef id="8e10648b-...87de33778d95"/>` — наследие от старых версий платформы. В новых конфигурациях с нуля Конфигуратор её не создаёт; не закладывайте на неё логику.
### 4.3. Начальная страница
| Файл | Описание |
+9 -3
View File
@@ -1,7 +1,13 @@
{
"name": "Пустая конфигурация",
"params": { "name": "ТестоваяКонфигурация" },
"params": {
"name": "ТестоваяКонфигурация"
},
"expect": {
"files": ["Configuration.xml", "Languages/Русский.xml"]
"files": [
"Configuration.xml",
"Languages/Русский.xml",
"Ext/ClientApplicationInterface.xml"
]
}
}
}
+9 -3
View File
@@ -1,7 +1,13 @@
{
"name": "Минимальная конфигурация (только имя)",
"params": { "name": "МинКонф" },
"params": {
"name": "МинКонф"
},
"expect": {
"files": ["Configuration.xml", "Languages/Русский.xml"]
"files": [
"Configuration.xml",
"Languages/Русский.xml",
"Ext/ClientApplicationInterface.xml"
]
}
}
}
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
<top>
<panel id="UUID-001">
<uuid>UUID-002</uuid>
</panel>
</top>
<left>
<panel id="UUID-003">
<uuid>UUID-004</uuid>
</panel>
</left>
<panelDef id="UUID-004"/>
<panelDef id="UUID-005"/>
<panelDef id="UUID-006"/>
<panelDef id="UUID-002"/>
<panelDef id="UUID-007"/>
</ClientApplicationInterface>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
<top>
<panel id="UUID-001">
<uuid>UUID-002</uuid>
</panel>
</top>
<left>
<panel id="UUID-003">
<uuid>UUID-004</uuid>
</panel>
</left>
<panelDef id="UUID-004"/>
<panelDef id="UUID-005"/>
<panelDef id="UUID-006"/>
<panelDef id="UUID-002"/>
<panelDef id="UUID-007"/>
</ClientApplicationInterface>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
<top>
<panel id="UUID-001">
<uuid>UUID-002</uuid>
</panel>
</top>
<left>
<panel id="UUID-003">
<uuid>UUID-004</uuid>
</panel>
</left>
<panelDef id="UUID-004"/>
<panelDef id="UUID-005"/>
<panelDef id="UUID-006"/>
<panelDef id="UUID-002"/>
<panelDef id="UUID-007"/>
</ClientApplicationInterface>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
<top>
<panel id="UUID-001">
<uuid>UUID-002</uuid>
</panel>
</top>
<left>
<panel id="UUID-003">
<uuid>UUID-004</uuid>
</panel>
</left>
<panelDef id="UUID-004"/>
<panelDef id="UUID-005"/>
<panelDef id="UUID-006"/>
<panelDef id="UUID-002"/>
<panelDef id="UUID-007"/>
</ClientApplicationInterface>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<ClientApplicationInterface xmlns="http://v8.1c.ru/8.2/managed-application/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="InterfaceLayouter">
<top>
<panel id="UUID-001">
<uuid>UUID-002</uuid>
</panel>
</top>
<left>
<panel id="UUID-003">
<uuid>UUID-004</uuid>
</panel>
</left>
<panelDef id="UUID-004"/>
<panelDef id="UUID-005"/>
<panelDef id="UUID-006"/>
<panelDef id="UUID-002"/>
<panelDef id="UUID-007"/>
</ClientApplicationInterface>
@@ -1,8 +1,17 @@
{
"name": "Конфигурация с CompatibilityMode",
"params": { "name": "ТестСовместимость" },
"args_extra": ["-CompatibilityMode", "Version8_3_17"],
"params": {
"name": "ТестСовместимость"
},
"args_extra": [
"-CompatibilityMode",
"Version8_3_17"
],
"expect": {
"files": ["Configuration.xml", "Languages/Русский.xml"]
"files": [
"Configuration.xml",
"Languages/Русский.xml",
"Ext/ClientApplicationInterface.xml"
]
}
}
}
+13 -4
View File
@@ -1,9 +1,18 @@
{
"name": "Конфигурация с синонимом",
"params": { "name": "ТестСиноним" },
"args_extra": ["-Synonym", "Тестовый синоним конфигурации"],
"params": {
"name": "ТестСиноним"
},
"args_extra": [
"-Synonym",
"Тестовый синоним конфигурации"
],
"expect": {
"files": ["Configuration.xml", "Languages/Русский.xml"],
"files": [
"Configuration.xml",
"Languages/Русский.xml",
"Ext/ClientApplicationInterface.xml"
],
"stdoutContains": "ТестСиноним"
}
}
}
+15 -4
View File
@@ -1,9 +1,20 @@
{
"name": "Конфигурация с поставщиком и версией",
"params": { "name": "Бухгалтерия" },
"args_extra": ["-Vendor", "Тест", "-Version", "2.0.1"],
"params": {
"name": "Бухгалтерия"
},
"args_extra": [
"-Vendor",
"Тест",
"-Version",
"2.0.1"
],
"expect": {
"files": ["Configuration.xml", "Languages/Русский.xml"],
"files": [
"Configuration.xml",
"Languages/Русский.xml",
"Ext/ClientApplicationInterface.xml"
],
"stdoutContains": "Бухгалтерия"
}
}
}