mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-15 07:15:17 +03:00
feat(cf-*): set-home-page + drill-down -Section home-page + form-ref валидация
- cf-edit: новая операция set-home-page перезаписывает Ext/HomePageWorkArea.xml. DSL принимает template (OneColumn/TwoColumnsEqualWidth/TwoColumnsVariableWidth), left/right с записями форм (строка или объект form/height/visibility/roles). Тихая нормализация ссылок: русские типы, 3-сегмент → авто-Form, файловые пути - cf-info: краткая HP-сводка (template + счётчики) в overview/full, детальный вид через -Section home-page (alias -Name) с раскладкой и переопределениями ролей - cf-validate: Check 9 — валидация ссылок на формы из HomePageWorkArea и Default*Form свойств; битая ссылка → error - reference.md: убран реализационный шум (canonical sort, авто-нормализация форм, panelDef detail, секция авто-валидации); путь src/ в примерах вместо репо-специфичных 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: cf-edit
|
name: cf-edit
|
||||||
description: Точечное редактирование конфигурации 1С. Используй когда нужно изменить свойства конфигурации, добавить или удалить объект из состава, настроить роли по умолчанию, поменять раскладку панелей
|
description: Точечное редактирование конфигурации 1С. Используй когда нужно изменить свойства конфигурации, добавить или удалить объект из состава, настроить роли по умолчанию, поменять раскладку панелей, настроить начальную страницу
|
||||||
argument-hint: -ConfigPath <path> -Operation <op> -Value <value>
|
argument-hint: -ConfigPath <path> -Operation <op> -Value <value>
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
@@ -38,6 +38,7 @@ powershell.exe -NoProfile -File .claude/skills/cf-edit/scripts/cf-edit.ps1 -Conf
|
|||||||
| `remove-defaultRole` | `Role.Name` или `Name` | Удалить роль по умолчанию |
|
| `remove-defaultRole` | `Role.Name` или `Name` | Удалить роль по умолчанию |
|
||||||
| `set-defaultRoles` | Имена через `;;` | Заменить список ролей по умолчанию |
|
| `set-defaultRoles` | Имена через `;;` | Заменить список ролей по умолчанию |
|
||||||
| `set-panels` | JSON-объект (см. [reference.md](reference.md)) | Перезаписать `Ext/ClientApplicationInterface.xml` (раскладка панелей) |
|
| `set-panels` | JSON-объект (см. [reference.md](reference.md)) | Перезаписать `Ext/ClientApplicationInterface.xml` (раскладка панелей) |
|
||||||
|
| `set-home-page` | JSON-объект (см. [reference.md](reference.md)) | Перезаписать `Ext/HomePageWorkArea.xml` (начальная страница) |
|
||||||
|
|
||||||
Допустимые значения свойств, формат DefinitionFile (JSON), каноничный порядок: [reference.md](reference.md)
|
Допустимые значения свойств, формат DefinitionFile (JSON), каноничный порядок: [reference.md](reference.md)
|
||||||
|
|
||||||
@@ -45,15 +46,15 @@ powershell.exe -NoProfile -File .claude/skills/cf-edit/scripts/cf-edit.ps1 -Conf
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Изменить версию и поставщика
|
# Изменить версию и поставщика
|
||||||
... -ConfigPath test-tmp/cf -Operation modify-property -Value "Version=1.0.0.1 ;; Vendor=Фирма 1С"
|
... -ConfigPath src -Operation modify-property -Value "Version=1.0.0.1 ;; Vendor=Фирма 1С"
|
||||||
|
|
||||||
# Добавить объекты
|
# Добавить объекты
|
||||||
... -ConfigPath test-tmp/cf -Operation add-childObject -Value "Catalog.Товары ;; Document.Заказ"
|
... -ConfigPath src -Operation add-childObject -Value "Catalog.Товары ;; Document.Заказ"
|
||||||
|
|
||||||
# Удалить объект
|
# Удалить объект
|
||||||
... -ConfigPath test-tmp/cf -Operation remove-childObject -Value "Catalog.Устаревший"
|
... -ConfigPath src -Operation remove-childObject -Value "Catalog.Устаревший"
|
||||||
|
|
||||||
# Роли по умолчанию
|
# Роли по умолчанию
|
||||||
... -ConfigPath test-tmp/cf -Operation add-defaultRole -Value "ПолныеПрава"
|
... -ConfigPath src -Operation add-defaultRole -Value "ПолныеПрава"
|
||||||
... -ConfigPath test-tmp/cf -Operation set-defaultRoles -Value "ПолныеПрава ;; Администратор"
|
... -ConfigPath src -Operation set-defaultRoles -Value "ПолныеПрава ;; Администратор"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -35,14 +35,7 @@
|
|||||||
|
|
||||||
Формат: `Type.Name` — XML-тип и имя объекта через точку.
|
Формат: `Type.Name` — XML-тип и имя объекта через точку.
|
||||||
|
|
||||||
**Важно про `add-childObject`**: операция регистрирует в `<ChildObjects>` Configuration.xml только объект, **файл которого уже существует на диске** (например `Catalogs/Товары.xml`). Если файла нет — скрипт падает с exit 1 и подсказкой. Для создания нового объекта используй профильный навык — `/meta-compile` (Catalog, Document, Enum, Report, регистры и т.д.), `/role-compile` (Role), `/subsystem-compile` (Subsystem). Они создают файл И регистрируют его в Configuration.xml за один вызов.
|
**Важно про `add-childObject`**: регистрирует в `<ChildObjects>` объект, **файл которого уже существует на диске**. Если файла нет — exit 1. Для создания нового объекта используй профильный навык — `/meta-compile` (Catalog, Document, Enum, Report, регистры и т.д.), `/role-compile` (Role), `/subsystem-compile` (Subsystem). Они создают файл И регистрируют его за один вызов.
|
||||||
|
|
||||||
Когда `add-childObject` всё-таки нужен: откатили Configuration.xml (или перезаписали из выгрузки БД), а файлы объектов остались — нужно восстановить ссылки в `<ChildObjects>`.
|
|
||||||
|
|
||||||
При добавлении объект вставляется в каноническую позицию:
|
|
||||||
1. Находит последний элемент того же типа → вставляет после
|
|
||||||
2. Если тип отсутствует → находит последний элемент предшествующего типа → вставляет после
|
|
||||||
3. Внутри одного типа — алфавитный порядок
|
|
||||||
|
|
||||||
Batch: `"Catalog.Товары ;; Document.Заказ ;; Enum.ВидыОплат"`
|
Batch: `"Catalog.Товары ;; Document.Заказ ;; Enum.ВидыОплат"`
|
||||||
|
|
||||||
@@ -91,12 +84,59 @@ Batch: `"Catalog.Товары ;; Document.Заказ ;; Enum.ВидыОплат"
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
**Через `-Value`** (CLI): передавай тот же объект как JSON-строку:
|
Через `-Value` (CLI): передай объект как JSON-строку — `... -Operation set-panels -Value '{"top":["open"]}'`.
|
||||||
```powershell
|
|
||||||
... -Operation set-panels -Value '{"top":["open"],"left":["sections"]}'
|
|
||||||
```
|
|
||||||
|
|
||||||
`<panelDef>` для всех 5 панелей пишется автоматически — они всегда доступны пользователю через «Вид → Настройка панелей», даже если не размещены по умолчанию.
|
## set-home-page
|
||||||
|
|
||||||
|
Перезаписывает `Ext/HomePageWorkArea.xml` — раскладка форм на начальной странице (рабочая область). Файл создаётся с нуля; то, что не упомянуто в `value`, отсутствует.
|
||||||
|
|
||||||
|
`value` — объект:
|
||||||
|
|
||||||
|
| Ключ | Канонич. (XML) | Описание |
|
||||||
|
|------|----------------|----------|
|
||||||
|
| `template` | `WorkingAreaTemplate` | `OneColumn` / `TwoColumnsEqualWidth` (дефолт) / `TwoColumnsVariableWidth` |
|
||||||
|
| `left` | `LeftColumn` | массив записей форм |
|
||||||
|
| `right` | `RightColumn` | массив записей форм (запрещён при `OneColumn`) |
|
||||||
|
|
||||||
|
Принимаются и короткие и канонич. ключи (XML-имена) — оба работают.
|
||||||
|
|
||||||
|
**Запись формы** — одна из:
|
||||||
|
- Строка `"<form>"` — только имя формы, дефолты `height=10`, `visibility=true`
|
||||||
|
- Объект `{form, height?, visibility?, roles?}`
|
||||||
|
|
||||||
|
| Поле | Канонич. | Дефолт | Описание |
|
||||||
|
|------|----------|--------|----------|
|
||||||
|
| `form` | `Form` | — | `CommonForm.X` или `Type.Object.Form.Name` (или UUID) |
|
||||||
|
| `height` | `Height` | `10` | Высота |
|
||||||
|
| `visibility` | `Visibility` | `true` | Общая видимость (`<xr:Common>`) |
|
||||||
|
| `roles` | — | — | `{"Role.Имя": true|false, ...}` — переопределения по ролям |
|
||||||
|
|
||||||
|
**Семантика visibility:** `visibility` = общее правило, `roles` — точечные исключения. Скрыть для всех кроме одной роли: `{"visibility": false, "roles": {"Role.Опер": true}}`.
|
||||||
|
|
||||||
|
**Пример:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"operation": "set-home-page",
|
||||||
|
"value": {
|
||||||
|
"template": "TwoColumnsVariableWidth",
|
||||||
|
"left": [
|
||||||
|
"CommonForm.НачалоРаботы",
|
||||||
|
{ "form": "CommonForm.СписокЗадач", "height": 100, "visibility": false },
|
||||||
|
{ "form": "Catalog.Контрагенты.Form.ФормаСписка", "height": 50 },
|
||||||
|
{
|
||||||
|
"form": "CommonForm.РабочийСтолОператора",
|
||||||
|
"visibility": false,
|
||||||
|
"roles": { "Role.Оператор": true, "Role.ПолныеПрава": false }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"right": [
|
||||||
|
{ "form": "DataProcessor.Поиск.Form.ФормаПоиска", "height": 30 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
## DefinitionFile (JSON)
|
## DefinitionFile (JSON)
|
||||||
|
|
||||||
@@ -108,6 +148,3 @@ Batch: `"Catalog.Товары ;; Document.Заказ ;; Enum.ВидыОплат"
|
|||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Авто-валидация
|
|
||||||
|
|
||||||
После сохранения автоматически запускается `cf-validate` (если не указан `-NoValidate`).
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
# cf-edit v1.3 — Edit 1C configuration root (Configuration.xml)
|
# cf-edit v1.4 — Edit 1C configuration root (Configuration.xml)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)][Alias('Path')][string]$ConfigPath,
|
[Parameter(Mandatory)][Alias('Path')][string]$ConfigPath,
|
||||||
[string]$DefinitionFile,
|
[string]$DefinitionFile,
|
||||||
[ValidateSet("modify-property","add-childObject","remove-childObject","add-defaultRole","remove-defaultRole","set-defaultRoles","set-panels")]
|
[ValidateSet("modify-property","add-childObject","remove-childObject","add-defaultRole","remove-defaultRole","set-defaultRoles","set-panels","set-home-page")]
|
||||||
[string]$Operation,
|
[string]$Operation,
|
||||||
[string]$Value,
|
[string]$Value,
|
||||||
[switch]$NoValidate
|
[switch]$NoValidate
|
||||||
@@ -558,6 +558,194 @@ $bodyBlock$declarations
|
|||||||
Info "Wrote panel layout: $caiPath"
|
Info "Wrote panel layout: $caiPath"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- Operation: set-home-page ---
|
||||||
|
# Russian → English type aliases for form-ref normalization
|
||||||
|
$script:ruTypeMap = @{
|
||||||
|
"справочник" = "Catalog"
|
||||||
|
"документ" = "Document"
|
||||||
|
"перечисление" = "Enum"
|
||||||
|
"отчёт" = "Report"
|
||||||
|
"отчет" = "Report"
|
||||||
|
"обработка" = "DataProcessor"
|
||||||
|
"общаяформа" = "CommonForm"
|
||||||
|
"журналдокументов" = "DocumentJournal"
|
||||||
|
"планвидовхарактеристик" = "ChartOfCharacteristicTypes"
|
||||||
|
"плансчетов" = "ChartOfAccounts"
|
||||||
|
"планвидоврасчета" = "ChartOfCalculationTypes"
|
||||||
|
"планвидоврасчёта" = "ChartOfCalculationTypes"
|
||||||
|
"регистрсведений" = "InformationRegister"
|
||||||
|
"регистрнакопления" = "AccumulationRegister"
|
||||||
|
"регистрбухгалтерии" = "AccountingRegister"
|
||||||
|
"регистррасчета" = "CalculationRegister"
|
||||||
|
"регистррасчёта" = "CalculationRegister"
|
||||||
|
"бизнеспроцесс" = "BusinessProcess"
|
||||||
|
"задача" = "Task"
|
||||||
|
"планобмена" = "ExchangePlan"
|
||||||
|
"хранилищенастроек" = "SettingsStorage"
|
||||||
|
}
|
||||||
|
# plural folder → singular type
|
||||||
|
$script:dirToType = @{}
|
||||||
|
foreach ($k in $script:typeToDir.Keys) { $script:dirToType[$script:typeToDir[$k].ToLowerInvariant()] = $k }
|
||||||
|
|
||||||
|
function Normalize-FormRef([string]$s) {
|
||||||
|
$s = $s.Trim()
|
||||||
|
if (-not $s) { return $s }
|
||||||
|
# UUID — leave as-is
|
||||||
|
if ($s -match '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$') { return $s }
|
||||||
|
# Path form?
|
||||||
|
if ($s.Contains("/") -or $s.Contains("\")) {
|
||||||
|
$parts = $s.Replace("\","/").Split("/") | Where-Object { $_ -ne "" -and $_.ToLowerInvariant() -ne "ext" }
|
||||||
|
# Strip trailing Form.xml
|
||||||
|
if ($parts.Count -gt 0 -and $parts[-1].ToLowerInvariant() -eq "form.xml") {
|
||||||
|
$parts = @($parts[0..($parts.Count - 2)])
|
||||||
|
}
|
||||||
|
if ($parts.Count -ge 2) {
|
||||||
|
$typeDir = $parts[0]
|
||||||
|
$typeSingular = $script:dirToType[$typeDir.ToLowerInvariant()]
|
||||||
|
if ($typeSingular) {
|
||||||
|
if ($typeSingular -eq "CommonForm" -and $parts.Count -ge 2) {
|
||||||
|
return "CommonForm.$($parts[1])"
|
||||||
|
}
|
||||||
|
if ($parts.Count -ge 4 -and $parts[2].ToLowerInvariant() -eq "forms") {
|
||||||
|
return "$typeSingular.$($parts[1]).Form.$($parts[3])"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $s
|
||||||
|
}
|
||||||
|
# Dot form — translate Russian head and 'Форма' segment, auto-insert 'Form'
|
||||||
|
$segs = $s.Split(".")
|
||||||
|
if ($segs.Count -ge 1) {
|
||||||
|
$head = $segs[0].ToLowerInvariant()
|
||||||
|
if ($script:ruTypeMap.ContainsKey($head)) { $segs[0] = $script:ruTypeMap[$head] }
|
||||||
|
for ($i = 1; $i -lt $segs.Count; $i++) {
|
||||||
|
if ($segs[$i] -eq "Форма") { $segs[$i] = "Form" }
|
||||||
|
}
|
||||||
|
# Auto-insert Form: for object types with 3 segments (Type.Object.FormName)
|
||||||
|
if ($segs.Count -eq 3 -and $script:typeOrder -contains $segs[0] -and $segs[0] -ne "CommonForm") {
|
||||||
|
$segs = @($segs[0], $segs[1], "Form", $segs[2])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ($segs -join ".")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Accept short DSL or canonical XML keys (silently)
|
||||||
|
function Get-FieldValue($obj, [string[]]$keys) {
|
||||||
|
foreach ($k in $keys) {
|
||||||
|
if ($obj.PSObject.Properties[$k]) { return $obj.PSObject.Properties[$k].Value }
|
||||||
|
}
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-HomePageItemXml($entry, [string]$indent) {
|
||||||
|
# Resolve fields
|
||||||
|
if ($entry -is [string]) {
|
||||||
|
$formRef = Normalize-FormRef $entry
|
||||||
|
$height = 10
|
||||||
|
$common = $true
|
||||||
|
$roles = $null
|
||||||
|
} else {
|
||||||
|
$formRaw = Get-FieldValue $entry @("form","Form")
|
||||||
|
if (-not $formRaw) { Write-Error "Home page item: 'form' is required, got: $($entry | ConvertTo-Json -Compress)"; exit 1 }
|
||||||
|
$formRef = Normalize-FormRef ([string]$formRaw)
|
||||||
|
$h = Get-FieldValue $entry @("height","Height")
|
||||||
|
$height = if ($null -ne $h) { [int]$h } else { 10 }
|
||||||
|
$vis = Get-FieldValue $entry @("visibility","Visibility")
|
||||||
|
$common = if ($null -ne $vis) { [bool]$vis } else { $true }
|
||||||
|
$roles = Get-FieldValue $entry @("roles")
|
||||||
|
}
|
||||||
|
|
||||||
|
$visParts = @()
|
||||||
|
$visParts += "$indent`t`t<xr:Common>$($common.ToString().ToLower())</xr:Common>"
|
||||||
|
if ($roles) {
|
||||||
|
# roles is PSCustomObject {Role.X: bool, ...}
|
||||||
|
foreach ($prop in $roles.PSObject.Properties) {
|
||||||
|
$rname = $prop.Name
|
||||||
|
if (-not $rname.StartsWith("Role.") -and -not ($rname -match '^[0-9a-fA-F]{8}-')) { $rname = "Role.$rname" }
|
||||||
|
$rval = ([bool]$prop.Value).ToString().ToLower()
|
||||||
|
$escName = [System.Security.SecurityElement]::Escape($rname)
|
||||||
|
$visParts += "$indent`t`t<xr:Value name=`"$escName`">$rval</xr:Value>"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$visBlock = $visParts -join "`r`n"
|
||||||
|
$escForm = [System.Security.SecurityElement]::Escape($formRef)
|
||||||
|
return @"
|
||||||
|
$indent<Item>
|
||||||
|
$indent`t<Form>$escForm</Form>
|
||||||
|
$indent`t<Height>$height</Height>
|
||||||
|
$indent`t<Visibility>
|
||||||
|
$visBlock
|
||||||
|
$indent`t</Visibility>
|
||||||
|
$indent</Item>
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
function Do-SetHomePage($valArg) {
|
||||||
|
$layout = $valArg
|
||||||
|
if ($layout -is [string]) {
|
||||||
|
try { $layout = $layout | ConvertFrom-Json } catch {
|
||||||
|
Write-Error "set-home-page value must be valid JSON object"; exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $layout) { Write-Error "set-home-page value is empty"; exit 1 }
|
||||||
|
|
||||||
|
$allowedTemplates = @("OneColumn","TwoColumnsEqualWidth","TwoColumnsVariableWidth")
|
||||||
|
$tmpl = Get-FieldValue $layout @("template","WorkingAreaTemplate")
|
||||||
|
if (-not $tmpl) { $tmpl = "TwoColumnsEqualWidth" }
|
||||||
|
if ($allowedTemplates -notcontains $tmpl) {
|
||||||
|
Write-Error "Unknown template '$tmpl'. Allowed: $($allowedTemplates -join ', ')"; exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$leftItems = Get-FieldValue $layout @("left","LeftColumn")
|
||||||
|
$rightItems = Get-FieldValue $layout @("right","RightColumn")
|
||||||
|
|
||||||
|
# Reject unknown keys
|
||||||
|
$known = @("template","WorkingAreaTemplate","left","LeftColumn","right","RightColumn")
|
||||||
|
foreach ($prop in $layout.PSObject.Properties) {
|
||||||
|
if ($known -notcontains $prop.Name) {
|
||||||
|
Write-Error "Unknown key '$($prop.Name)'. Allowed: template, left, right"; exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($tmpl -eq "OneColumn" -and $rightItems) {
|
||||||
|
Write-Error "Template 'OneColumn' cannot have items in 'right' column"; exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-Column([string]$tag, $items) {
|
||||||
|
if (-not $items) { return "`t<$tag/>" }
|
||||||
|
if ($items -isnot [System.Array] -and $items -isnot [System.Collections.IList]) {
|
||||||
|
$items = @($items)
|
||||||
|
}
|
||||||
|
if ($items.Count -eq 0) { return "`t<$tag/>" }
|
||||||
|
$itemBlocks = @()
|
||||||
|
foreach ($it in $items) {
|
||||||
|
$itemBlocks += Build-HomePageItemXml $it "`t`t"
|
||||||
|
}
|
||||||
|
$body = $itemBlocks -join "`r`n"
|
||||||
|
return "`t<$tag>`r`n$body`r`n`t</$tag>"
|
||||||
|
}
|
||||||
|
|
||||||
|
$leftXml = Build-Column "LeftColumn" $leftItems
|
||||||
|
$rightXml = Build-Column "RightColumn" $rightItems
|
||||||
|
|
||||||
|
$hpXml = @"
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<HomePageWorkArea xmlns="http://v8.1c.ru/8.3/xcf/extrnprops" 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">
|
||||||
|
<WorkingAreaTemplate>$tmpl</WorkingAreaTemplate>
|
||||||
|
$leftXml
|
||||||
|
$rightXml
|
||||||
|
</HomePageWorkArea>
|
||||||
|
"@
|
||||||
|
|
||||||
|
$extDir = Join-Path $script:configDir "Ext"
|
||||||
|
if (-not (Test-Path $extDir)) { New-Item -ItemType Directory -Path $extDir -Force | Out-Null }
|
||||||
|
$hpPath = Join-Path $extDir "HomePageWorkArea.xml"
|
||||||
|
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||||
|
[System.IO.File]::WriteAllText($hpPath, $hpXml, $utf8Bom)
|
||||||
|
$script:modifyCount++
|
||||||
|
Info "Wrote home page layout: $hpPath"
|
||||||
|
}
|
||||||
|
|
||||||
# --- Operation: set-defaultRoles ---
|
# --- Operation: set-defaultRoles ---
|
||||||
function Do-SetDefaultRoles([string]$batchVal) {
|
function Do-SetDefaultRoles([string]$batchVal) {
|
||||||
$items = Parse-BatchValue $batchVal
|
$items = Parse-BatchValue $batchVal
|
||||||
@@ -634,6 +822,7 @@ foreach ($op in $operations) {
|
|||||||
"remove-defaultRole" { Do-RemoveDefaultRole $opValueStr }
|
"remove-defaultRole" { Do-RemoveDefaultRole $opValueStr }
|
||||||
"set-defaultRoles" { Do-SetDefaultRoles $opValueStr }
|
"set-defaultRoles" { Do-SetDefaultRoles $opValueStr }
|
||||||
"set-panels" { Do-SetPanels $opValue }
|
"set-panels" { Do-SetPanels $opValue }
|
||||||
|
"set-home-page" { Do-SetHomePage $opValue }
|
||||||
default { Write-Error "Unknown operation: $opName"; exit 1 }
|
default { Write-Error "Unknown operation: $opName"; exit 1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cf-edit v1.3 — Edit 1C configuration root (Configuration.xml)
|
# cf-edit v1.4 — Edit 1C configuration root (Configuration.xml)
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -162,7 +162,7 @@ def main():
|
|||||||
parser = argparse.ArgumentParser(description="Edit 1C configuration root (Configuration.xml)", allow_abbrev=False)
|
parser = argparse.ArgumentParser(description="Edit 1C configuration root (Configuration.xml)", allow_abbrev=False)
|
||||||
parser.add_argument("-ConfigPath", "-Path", required=True)
|
parser.add_argument("-ConfigPath", "-Path", required=True)
|
||||||
parser.add_argument("-DefinitionFile", default=None)
|
parser.add_argument("-DefinitionFile", default=None)
|
||||||
parser.add_argument("-Operation", default=None, choices=["modify-property", "add-childObject", "remove-childObject", "add-defaultRole", "remove-defaultRole", "set-defaultRoles", "set-panels"])
|
parser.add_argument("-Operation", default=None, choices=["modify-property", "add-childObject", "remove-childObject", "add-defaultRole", "remove-defaultRole", "set-defaultRoles", "set-panels", "set-home-page"])
|
||||||
parser.add_argument("-Value", default=None)
|
parser.add_argument("-Value", default=None)
|
||||||
parser.add_argument("-NoValidate", action="store_true")
|
parser.add_argument("-NoValidate", action="store_true")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
@@ -593,6 +593,170 @@ def main():
|
|||||||
modify_count += 1
|
modify_count += 1
|
||||||
info(f"Wrote panel layout: {cai_path}")
|
info(f"Wrote panel layout: {cai_path}")
|
||||||
|
|
||||||
|
# --- set-home-page (writes Ext/HomePageWorkArea.xml from scratch) ---
|
||||||
|
RU_TYPE_MAP = {
|
||||||
|
"справочник": "Catalog", "документ": "Document", "перечисление": "Enum",
|
||||||
|
"отчёт": "Report", "отчет": "Report", "обработка": "DataProcessor",
|
||||||
|
"общаяформа": "CommonForm", "журналдокументов": "DocumentJournal",
|
||||||
|
"планвидовхарактеристик": "ChartOfCharacteristicTypes",
|
||||||
|
"плансчетов": "ChartOfAccounts",
|
||||||
|
"планвидоврасчета": "ChartOfCalculationTypes",
|
||||||
|
"планвидоврасчёта": "ChartOfCalculationTypes",
|
||||||
|
"регистрсведений": "InformationRegister",
|
||||||
|
"регистрнакопления": "AccumulationRegister",
|
||||||
|
"регистрбухгалтерии": "AccountingRegister",
|
||||||
|
"регистррасчета": "CalculationRegister",
|
||||||
|
"регистррасчёта": "CalculationRegister",
|
||||||
|
"бизнеспроцесс": "BusinessProcess",
|
||||||
|
"задача": "Task", "планобмена": "ExchangePlan",
|
||||||
|
"хранилищенастроек": "SettingsStorage",
|
||||||
|
}
|
||||||
|
DIR_TO_TYPE = {v.lower(): k for k, v in TYPE_TO_DIR.items()}
|
||||||
|
UUID_RE = __import__("re").compile(r"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
|
||||||
|
|
||||||
|
def normalize_form_ref(s):
|
||||||
|
s = (s or "").strip()
|
||||||
|
if not s:
|
||||||
|
return s
|
||||||
|
if UUID_RE.match(s):
|
||||||
|
return s
|
||||||
|
if "/" in s or "\\" in s:
|
||||||
|
parts = [p for p in s.replace("\\", "/").split("/") if p and p.lower() != "ext"]
|
||||||
|
if parts and parts[-1].lower() == "form.xml":
|
||||||
|
parts = parts[:-1]
|
||||||
|
if len(parts) >= 2:
|
||||||
|
type_dir = parts[0]
|
||||||
|
type_singular = DIR_TO_TYPE.get(type_dir.lower())
|
||||||
|
if type_singular:
|
||||||
|
if type_singular == "CommonForm" and len(parts) >= 2:
|
||||||
|
return f"CommonForm.{parts[1]}"
|
||||||
|
if len(parts) >= 4 and parts[2].lower() == "forms":
|
||||||
|
return f"{type_singular}.{parts[1]}.Form.{parts[3]}"
|
||||||
|
return s
|
||||||
|
segs = s.split(".")
|
||||||
|
if segs:
|
||||||
|
head = segs[0].lower()
|
||||||
|
if head in RU_TYPE_MAP:
|
||||||
|
segs[0] = RU_TYPE_MAP[head]
|
||||||
|
for i in range(1, len(segs)):
|
||||||
|
if segs[i] == "Форма":
|
||||||
|
segs[i] = "Form"
|
||||||
|
if len(segs) == 3 and segs[0] in TYPE_ORDER and segs[0] != "CommonForm":
|
||||||
|
segs = [segs[0], segs[1], "Form", segs[2]]
|
||||||
|
return ".".join(segs)
|
||||||
|
|
||||||
|
def get_field(obj, keys):
|
||||||
|
for k in keys:
|
||||||
|
if isinstance(obj, dict) and k in obj:
|
||||||
|
return obj[k]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def build_home_page_item_xml(entry, indent):
|
||||||
|
if isinstance(entry, str):
|
||||||
|
form_ref = normalize_form_ref(entry)
|
||||||
|
height = 10
|
||||||
|
common = True
|
||||||
|
roles = None
|
||||||
|
elif isinstance(entry, dict):
|
||||||
|
form_raw = get_field(entry, ["form", "Form"])
|
||||||
|
if not form_raw:
|
||||||
|
print(f"Home page item: 'form' is required, got: {entry!r}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
form_ref = normalize_form_ref(str(form_raw))
|
||||||
|
h = get_field(entry, ["height", "Height"])
|
||||||
|
height = int(h) if h is not None else 10
|
||||||
|
vis = get_field(entry, ["visibility", "Visibility"])
|
||||||
|
common = bool(vis) if vis is not None else True
|
||||||
|
roles = get_field(entry, ["roles"])
|
||||||
|
else:
|
||||||
|
print(f"Home page item must be string or object, got: {entry!r}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
vis_parts = [f"{indent}\t\t<xr:Common>{str(common).lower()}</xr:Common>"]
|
||||||
|
if roles and isinstance(roles, dict):
|
||||||
|
for rname, rval in roles.items():
|
||||||
|
if not rname.startswith("Role.") and not UUID_RE.match(rname):
|
||||||
|
rname = f"Role.{rname}"
|
||||||
|
rval_s = str(bool(rval)).lower()
|
||||||
|
vis_parts.append(f'{indent}\t\t<xr:Value name="{html_escape(rname, quote=True)}">{rval_s}</xr:Value>')
|
||||||
|
vis_block = "\r\n".join(vis_parts)
|
||||||
|
esc_form = html_escape(form_ref, quote=True)
|
||||||
|
return (
|
||||||
|
f"{indent}<Item>\r\n"
|
||||||
|
f"{indent}\t<Form>{esc_form}</Form>\r\n"
|
||||||
|
f"{indent}\t<Height>{height}</Height>\r\n"
|
||||||
|
f"{indent}\t<Visibility>\r\n"
|
||||||
|
f"{vis_block}\r\n"
|
||||||
|
f"{indent}\t</Visibility>\r\n"
|
||||||
|
f"{indent}</Item>"
|
||||||
|
)
|
||||||
|
|
||||||
|
def do_set_home_page(value):
|
||||||
|
nonlocal modify_count
|
||||||
|
layout = value
|
||||||
|
if isinstance(layout, str):
|
||||||
|
try:
|
||||||
|
layout = json.loads(layout)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print("set-home-page value must be valid JSON object", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
if not isinstance(layout, dict) or not layout:
|
||||||
|
print("set-home-page value must be non-empty object", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
allowed_templates = ("OneColumn", "TwoColumnsEqualWidth", "TwoColumnsVariableWidth")
|
||||||
|
tmpl = get_field(layout, ["template", "WorkingAreaTemplate"]) or "TwoColumnsEqualWidth"
|
||||||
|
if tmpl not in allowed_templates:
|
||||||
|
print(f"Unknown template '{tmpl}'. Allowed: {', '.join(allowed_templates)}", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
left_items = get_field(layout, ["left", "LeftColumn"])
|
||||||
|
right_items = get_field(layout, ["right", "RightColumn"])
|
||||||
|
|
||||||
|
known = {"template", "WorkingAreaTemplate", "left", "LeftColumn", "right", "RightColumn"}
|
||||||
|
for k in layout.keys():
|
||||||
|
if k not in known:
|
||||||
|
print(f"Unknown key '{k}'. Allowed: template, left, right", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if tmpl == "OneColumn" and right_items:
|
||||||
|
print("Template 'OneColumn' cannot have items in 'right' column", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
def build_column(tag, items):
|
||||||
|
if not items:
|
||||||
|
return f"\t<{tag}/>"
|
||||||
|
if not isinstance(items, list):
|
||||||
|
items = [items]
|
||||||
|
if not items:
|
||||||
|
return f"\t<{tag}/>"
|
||||||
|
blocks = [build_home_page_item_xml(it, "\t\t") for it in items]
|
||||||
|
body = "\r\n".join(blocks)
|
||||||
|
return f"\t<{tag}>\r\n{body}\r\n\t</{tag}>"
|
||||||
|
|
||||||
|
left_xml = build_column("LeftColumn", left_items)
|
||||||
|
right_xml = build_column("RightColumn", right_items)
|
||||||
|
|
||||||
|
hp_xml = (
|
||||||
|
'<?xml version="1.0" encoding="UTF-8"?>\r\n'
|
||||||
|
'<HomePageWorkArea xmlns="http://v8.1c.ru/8.3/xcf/extrnprops" '
|
||||||
|
'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">\r\n'
|
||||||
|
f'\t<WorkingAreaTemplate>{tmpl}</WorkingAreaTemplate>\r\n'
|
||||||
|
f'{left_xml}\r\n'
|
||||||
|
f'{right_xml}\r\n'
|
||||||
|
'</HomePageWorkArea>'
|
||||||
|
)
|
||||||
|
|
||||||
|
ext_dir = os.path.join(config_dir, "Ext")
|
||||||
|
os.makedirs(ext_dir, exist_ok=True)
|
||||||
|
hp_path = os.path.join(ext_dir, "HomePageWorkArea.xml")
|
||||||
|
with open(hp_path, "w", encoding="utf-8-sig", newline="") as fh:
|
||||||
|
fh.write(hp_xml)
|
||||||
|
modify_count += 1
|
||||||
|
info(f"Wrote home page layout: {hp_path}")
|
||||||
|
|
||||||
# --- Execute operations ---
|
# --- Execute operations ---
|
||||||
operations = []
|
operations = []
|
||||||
if args.DefinitionFile:
|
if args.DefinitionFile:
|
||||||
@@ -626,6 +790,8 @@ def main():
|
|||||||
do_set_default_roles(op_value if isinstance(op_value, str) else str(op_value))
|
do_set_default_roles(op_value if isinstance(op_value, str) else str(op_value))
|
||||||
elif op_name == "set-panels":
|
elif op_name == "set-panels":
|
||||||
do_set_panels(op_value)
|
do_set_panels(op_value)
|
||||||
|
elif op_name == "set-home-page":
|
||||||
|
do_set_home_page(op_value)
|
||||||
else:
|
else:
|
||||||
print(f"Unknown operation: {op_name}", file=sys.stderr)
|
print(f"Unknown operation: {op_name}", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
name: cf-info
|
name: cf-info
|
||||||
description: Анализ структуры конфигурации 1С — свойства, состав, счётчики объектов. Используй для обзора конфигурации — какие объекты есть, сколько их, какие настройки
|
description: Анализ структуры конфигурации 1С — свойства, состав, счётчики объектов. Используй для обзора конфигурации — какие объекты есть, сколько их, какие настройки
|
||||||
argument-hint: <ConfigPath> [-Mode overview|brief|full]
|
argument-hint: <ConfigPath> [-Mode overview|brief|full] [-Section home-page]
|
||||||
allowed-tools:
|
allowed-tools:
|
||||||
- Bash
|
- Bash
|
||||||
- Read
|
- Read
|
||||||
@@ -18,6 +18,7 @@ allowed-tools:
|
|||||||
|----------|----------|
|
|----------|----------|
|
||||||
| `ConfigPath` | Путь к Configuration.xml или каталогу выгрузки |
|
| `ConfigPath` | Путь к Configuration.xml или каталогу выгрузки |
|
||||||
| `Mode` | Режим: `overview` (default), `brief`, `full` |
|
| `Mode` | Режим: `overview` (default), `brief`, `full` |
|
||||||
|
| `Section` | Drill-down по разделу (alias: `Name`). Сейчас: `home-page` |
|
||||||
| `Limit` / `Offset` | Пагинация (по умолчанию 150 строк) |
|
| `Limit` / `Offset` | Пагинация (по умолчанию 150 строк) |
|
||||||
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
| `OutFile` | Записать результат в файл (UTF-8 BOM) |
|
||||||
|
|
||||||
@@ -37,14 +38,17 @@ powershell.exe -NoProfile -File .claude/skills/cf-info/scripts/cf-info.ps1 -Conf
|
|||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
# Обзор пустой конфигурации
|
# Обзор пустой конфигурации
|
||||||
... -ConfigPath upload/cfempty
|
... -ConfigPath src
|
||||||
|
|
||||||
# Краткая сводка реальной конфигурации
|
# Краткая сводка реальной конфигурации
|
||||||
... -ConfigPath upload/acc_8.3.24 -Mode brief
|
... -ConfigPath src -Mode brief
|
||||||
|
|
||||||
# Полная информация
|
# Полная информация
|
||||||
... -ConfigPath upload/acc_8.3.24 -Mode full
|
... -ConfigPath src -Mode full
|
||||||
|
|
||||||
# С пагинацией
|
# С пагинацией
|
||||||
... -ConfigPath upload/acc_8.3.24 -Mode full -Limit 50 -Offset 100
|
... -ConfigPath src -Mode full -Limit 50 -Offset 100
|
||||||
|
|
||||||
|
# Drill-down: только начальная страница (раскладка форм с ролями)
|
||||||
|
... -ConfigPath src -Section home-page
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
# cf-info v1.1 — Compact summary of 1C configuration root
|
# cf-info v1.2 — Compact summary of 1C configuration root
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory=$true)][Alias('Path')][string]$ConfigPath,
|
[Parameter(Mandatory=$true)][Alias('Path')][string]$ConfigPath,
|
||||||
[ValidateSet("overview","brief","full")]
|
[ValidateSet("overview","brief","full")]
|
||||||
[string]$Mode = "overview",
|
[string]$Mode = "overview",
|
||||||
|
[Alias('Name')]
|
||||||
|
[ValidateSet("home-page")]
|
||||||
|
[string]$Section,
|
||||||
[int]$Limit = 150,
|
[int]$Limit = 150,
|
||||||
[int]$Offset = 0,
|
[int]$Offset = 0,
|
||||||
[string]$OutFile
|
[string]$OutFile
|
||||||
@@ -171,6 +174,62 @@ function Format-LayoutSlots($slots) {
|
|||||||
|
|
||||||
$script:panelLayout = Get-PanelsLayout
|
$script:panelLayout = Get-PanelsLayout
|
||||||
|
|
||||||
|
# --- Read home page layout (Ext/HomePageWorkArea.xml) ---
|
||||||
|
function Get-HomePageLayout {
|
||||||
|
$configDir = [System.IO.Path]::GetDirectoryName($ConfigPath)
|
||||||
|
$hpPath = Join-Path (Join-Path $configDir "Ext") "HomePageWorkArea.xml"
|
||||||
|
if (-not (Test-Path $hpPath)) { return $null }
|
||||||
|
try { [xml]$hpDoc = Get-Content -Path $hpPath -Encoding UTF8 } catch { return $null }
|
||||||
|
if (-not $hpDoc.DocumentElement) { return $null }
|
||||||
|
$hpNs = New-Object System.Xml.XmlNamespaceManager($hpDoc.NameTable)
|
||||||
|
$hpNs.AddNamespace("hp", "http://v8.1c.ru/8.3/xcf/extrnprops")
|
||||||
|
$hpNs.AddNamespace("xr", "http://v8.1c.ru/8.3/xcf/readable")
|
||||||
|
$result = [ordered]@{ template = ""; left = @(); right = @() }
|
||||||
|
$tmplNode = $hpDoc.DocumentElement.SelectSingleNode("hp:WorkingAreaTemplate", $hpNs)
|
||||||
|
if ($tmplNode) { $result.template = $tmplNode.InnerText.Trim() }
|
||||||
|
foreach ($colName in @("LeftColumn","RightColumn")) {
|
||||||
|
$colNode = $hpDoc.DocumentElement.SelectSingleNode("hp:$colName", $hpNs)
|
||||||
|
if (-not $colNode) { continue }
|
||||||
|
$items = @()
|
||||||
|
foreach ($item in $colNode.SelectNodes("hp:Item", $hpNs)) {
|
||||||
|
$f = $item.SelectSingleNode("hp:Form", $hpNs)
|
||||||
|
$h = $item.SelectSingleNode("hp:Height", $hpNs)
|
||||||
|
$visNode = $item.SelectSingleNode("hp:Visibility", $hpNs)
|
||||||
|
$common = $true
|
||||||
|
$roles = @()
|
||||||
|
if ($visNode) {
|
||||||
|
$cn = $visNode.SelectSingleNode("xr:Common", $hpNs)
|
||||||
|
if ($cn) { $common = ($cn.InnerText.Trim() -eq "true") }
|
||||||
|
foreach ($v in $visNode.SelectNodes("xr:Value", $hpNs)) {
|
||||||
|
$roles += @{ name = $v.GetAttribute("name"); value = ($v.InnerText.Trim() -eq "true") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$items += [ordered]@{
|
||||||
|
form = if ($f) { $f.InnerText.Trim() } else { "" }
|
||||||
|
height = if ($h) { [int]$h.InnerText.Trim() } else { 10 }
|
||||||
|
common = $common
|
||||||
|
roles = $roles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($colName -eq "LeftColumn") { $result.left = $items } else { $result.right = $items }
|
||||||
|
}
|
||||||
|
return $result
|
||||||
|
}
|
||||||
|
|
||||||
|
$script:homePage = Get-HomePageLayout
|
||||||
|
|
||||||
|
function Format-HomePageItem($it, [bool]$detailed) {
|
||||||
|
$badges = @()
|
||||||
|
$badges += "h=$($it.height)"
|
||||||
|
if (-not $it.common) { $badges += "скрыта" }
|
||||||
|
if ($it.roles.Count -gt 0) {
|
||||||
|
if ($detailed) { $badges += "роли: $($it.roles.Count)" }
|
||||||
|
else { $badges += "+$($it.roles.Count) ролей" }
|
||||||
|
}
|
||||||
|
$tail = if ($badges.Count -gt 0) { " (" + ($badges -join ", ") + ")" } else { "" }
|
||||||
|
return " $($it.form)$tail"
|
||||||
|
}
|
||||||
|
|
||||||
# --- Count objects in ChildObjects ---
|
# --- Count objects in ChildObjects ---
|
||||||
$objectCounts = [ordered]@{}
|
$objectCounts = [ordered]@{}
|
||||||
$totalObjects = 0
|
$totalObjects = 0
|
||||||
@@ -207,7 +266,7 @@ $cfgDbSpaces = Get-PropText "DatabaseTablespacesUseMode"
|
|||||||
$cfgWindowMode = Get-PropText "MainClientApplicationWindowMode"
|
$cfgWindowMode = Get-PropText "MainClientApplicationWindowMode"
|
||||||
|
|
||||||
# --- BRIEF mode ---
|
# --- BRIEF mode ---
|
||||||
if ($Mode -eq "brief") {
|
if ($Mode -eq "brief" -and -not $Section) {
|
||||||
$synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" }
|
$synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" }
|
||||||
$verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" }
|
$verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" }
|
||||||
$compatPart = if ($cfgCompat) { " | $cfgCompat" } else { "" }
|
$compatPart = if ($cfgCompat) { " | $cfgCompat" } else { "" }
|
||||||
@@ -215,7 +274,7 @@ if ($Mode -eq "brief") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --- OVERVIEW mode ---
|
# --- OVERVIEW mode ---
|
||||||
if ($Mode -eq "overview") {
|
if ($Mode -eq "overview" -and -not $Section) {
|
||||||
$synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" }
|
$synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" }
|
||||||
$verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" }
|
$verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" }
|
||||||
Out "=== Конфигурация: ${cfgName}${synPart}${verPart} ==="
|
Out "=== Конфигурация: ${cfgName}${synPart}${verPart} ==="
|
||||||
@@ -251,6 +310,16 @@ if ($Mode -eq "overview") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Home page layout (brief summary)
|
||||||
|
if ($script:homePage) {
|
||||||
|
$ln = $script:homePage.left.Count
|
||||||
|
$rn = $script:homePage.right.Count
|
||||||
|
Out "--- Начальная страница ---"
|
||||||
|
Out " Шаблон: $($script:homePage.template)"
|
||||||
|
Out " LeftColumn: $ln, RightColumn: $rn (детали: -Section home-page)"
|
||||||
|
Out ""
|
||||||
|
}
|
||||||
|
|
||||||
# Object counts table
|
# Object counts table
|
||||||
Out "--- Состав ($totalObjects объектов) ---"
|
Out "--- Состав ($totalObjects объектов) ---"
|
||||||
Out ""
|
Out ""
|
||||||
@@ -273,8 +342,34 @@ if ($Mode -eq "overview") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- Drill-down: -Section home-page ---
|
||||||
|
if ($Section -eq "home-page") {
|
||||||
|
if (-not $script:homePage) {
|
||||||
|
Out "Файл Ext/HomePageWorkArea.xml не найден"
|
||||||
|
} else {
|
||||||
|
Out "=== Начальная страница: $cfgName ==="
|
||||||
|
Out ""
|
||||||
|
Out "Шаблон: $($script:homePage.template)"
|
||||||
|
Out ""
|
||||||
|
foreach ($side in @(@("LeftColumn","left"), @("RightColumn","right"))) {
|
||||||
|
$items = $script:homePage[$side[1]]
|
||||||
|
$lbl = $side[0]
|
||||||
|
if ($items.Count -eq 0) { Out "${lbl}: —"; Out ""; continue }
|
||||||
|
Out "${lbl} ($($items.Count)):"
|
||||||
|
foreach ($it in $items) {
|
||||||
|
Out (Format-HomePageItem $it $true)
|
||||||
|
foreach ($r in $it.roles) {
|
||||||
|
$rval = if ($r.value) { "true" } else { "false" }
|
||||||
|
Out " $($r.name): $rval"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Out ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# --- FULL mode ---
|
# --- FULL mode ---
|
||||||
if ($Mode -eq "full") {
|
if ($Mode -eq "full" -and -not $Section) {
|
||||||
$synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" }
|
$synPart = if ($cfgSynonym) { " $dash `"$cfgSynonym`"" } else { "" }
|
||||||
$verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" }
|
$verPart = if ($cfgVersion) { " v$cfgVersion" } else { "" }
|
||||||
Out "=== Конфигурация: ${cfgName}${synPart}${verPart} ==="
|
Out "=== Конфигурация: ${cfgName}${synPart}${verPart} ==="
|
||||||
@@ -362,6 +457,16 @@ if ($Mode -eq "full") {
|
|||||||
Out ""
|
Out ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- Section: Home page (brief summary) ---
|
||||||
|
if ($script:homePage) {
|
||||||
|
$ln = $script:homePage.left.Count
|
||||||
|
$rn = $script:homePage.right.Count
|
||||||
|
Out "--- Начальная страница ---"
|
||||||
|
Out " Шаблон: $($script:homePage.template)"
|
||||||
|
Out " LeftColumn: $ln, RightColumn: $rn (детали: -Section home-page)"
|
||||||
|
Out ""
|
||||||
|
}
|
||||||
|
|
||||||
# --- Section: Storages & default forms ---
|
# --- Section: Storages & default forms ---
|
||||||
Out "--- Хранилища и формы по умолчанию ---"
|
Out "--- Хранилища и формы по умолчанию ---"
|
||||||
$storageProps = @("CommonSettingsStorage","ReportsUserSettingsStorage","ReportsVariantsStorage","FormDataSettingsStorage","DynamicListsUserSettingsStorage","URLExternalDataStorage")
|
$storageProps = @("CommonSettingsStorage","ReportsUserSettingsStorage","ReportsVariantsStorage","FormDataSettingsStorage","DynamicListsUserSettingsStorage","URLExternalDataStorage")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cf-info v1.1 — Compact summary of 1C configuration root
|
# cf-info v1.2 — Compact summary of 1C configuration root
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
@@ -15,6 +15,7 @@ sys.stderr.reconfigure(encoding="utf-8")
|
|||||||
parser = argparse.ArgumentParser(description="Analyze 1C configuration structure", allow_abbrev=False)
|
parser = argparse.ArgumentParser(description="Analyze 1C configuration structure", allow_abbrev=False)
|
||||||
parser.add_argument("-ConfigPath", "-Path", required=True, help="Path to Configuration.xml or directory")
|
parser.add_argument("-ConfigPath", "-Path", required=True, help="Path to Configuration.xml or directory")
|
||||||
parser.add_argument("-Mode", choices=["overview", "brief", "full"], default="overview", help="Output mode")
|
parser.add_argument("-Mode", choices=["overview", "brief", "full"], default="overview", help="Output mode")
|
||||||
|
parser.add_argument("-Section", "-Name", choices=["home-page"], default=None, help="Drill-down section (alias: -Name)")
|
||||||
parser.add_argument("-Limit", type=int, default=150, help="Max lines to show")
|
parser.add_argument("-Limit", type=int, default=150, help="Max lines to show")
|
||||||
parser.add_argument("-Offset", type=int, default=0, help="Lines to skip")
|
parser.add_argument("-Offset", type=int, default=0, help="Lines to skip")
|
||||||
parser.add_argument("-OutFile", default="", help="Write output to file")
|
parser.add_argument("-OutFile", default="", help="Write output to file")
|
||||||
@@ -172,6 +173,61 @@ def format_layout_slots(slots):
|
|||||||
|
|
||||||
panel_layout = get_panels_layout()
|
panel_layout = get_panels_layout()
|
||||||
|
|
||||||
|
# --- Read home page layout (Ext/HomePageWorkArea.xml) ---
|
||||||
|
HP_NS = "http://v8.1c.ru/8.3/xcf/extrnprops"
|
||||||
|
XR_NS_HP = "http://v8.1c.ru/8.3/xcf/readable"
|
||||||
|
|
||||||
|
def get_home_page_layout():
|
||||||
|
cfg_dir = os.path.dirname(config_path)
|
||||||
|
hp_path = os.path.join(cfg_dir, "Ext", "HomePageWorkArea.xml")
|
||||||
|
if not os.path.isfile(hp_path):
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
hp_tree = etree.parse(hp_path)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
hp_root = hp_tree.getroot()
|
||||||
|
result = {"template": "", "left": [], "right": []}
|
||||||
|
tn = hp_root.find(f"{{{HP_NS}}}WorkingAreaTemplate")
|
||||||
|
if tn is not None and tn.text:
|
||||||
|
result["template"] = tn.text.strip()
|
||||||
|
for col_name, key in (("LeftColumn", "left"), ("RightColumn", "right")):
|
||||||
|
col = hp_root.find(f"{{{HP_NS}}}{col_name}")
|
||||||
|
if col is None:
|
||||||
|
continue
|
||||||
|
items = []
|
||||||
|
for it in col.findall(f"{{{HP_NS}}}Item"):
|
||||||
|
f = it.find(f"{{{HP_NS}}}Form")
|
||||||
|
h = it.find(f"{{{HP_NS}}}Height")
|
||||||
|
vis = it.find(f"{{{HP_NS}}}Visibility")
|
||||||
|
common = True
|
||||||
|
roles = []
|
||||||
|
if vis is not None:
|
||||||
|
cn = vis.find(f"{{{XR_NS_HP}}}Common")
|
||||||
|
if cn is not None and cn.text:
|
||||||
|
common = cn.text.strip() == "true"
|
||||||
|
for v in vis.findall(f"{{{XR_NS_HP}}}Value"):
|
||||||
|
roles.append({"name": v.get("name", ""), "value": (v.text or "").strip() == "true"})
|
||||||
|
items.append({
|
||||||
|
"form": (f.text or "").strip() if f is not None else "",
|
||||||
|
"height": int((h.text or "10").strip()) if h is not None else 10,
|
||||||
|
"common": common,
|
||||||
|
"roles": roles,
|
||||||
|
})
|
||||||
|
result[key] = items
|
||||||
|
return result
|
||||||
|
|
||||||
|
home_page = get_home_page_layout()
|
||||||
|
|
||||||
|
def format_home_page_item(it, detailed):
|
||||||
|
badges = [f"h={it['height']}"]
|
||||||
|
if not it["common"]:
|
||||||
|
badges.append("скрыта")
|
||||||
|
if it["roles"]:
|
||||||
|
badges.append(f"роли: {len(it['roles'])}" if detailed else f"+{len(it['roles'])} ролей")
|
||||||
|
tail = f" ({', '.join(badges)})" if badges else ""
|
||||||
|
return f" {it['form']}{tail}"
|
||||||
|
|
||||||
# --- Count objects in ChildObjects ---
|
# --- Count objects in ChildObjects ---
|
||||||
object_counts = OrderedDict()
|
object_counts = OrderedDict()
|
||||||
total_objects = 0
|
total_objects = 0
|
||||||
@@ -206,14 +262,14 @@ cfg_db_spaces = get_prop_text("DatabaseTablespacesUseMode")
|
|||||||
cfg_window_mode = get_prop_text("MainClientApplicationWindowMode")
|
cfg_window_mode = get_prop_text("MainClientApplicationWindowMode")
|
||||||
|
|
||||||
# --- BRIEF mode ---
|
# --- BRIEF mode ---
|
||||||
if args.Mode == "brief":
|
if args.Mode == "brief" and not args.Section:
|
||||||
syn_part = f' {dash} "{cfg_synonym}"' if cfg_synonym else ""
|
syn_part = f' {dash} "{cfg_synonym}"' if cfg_synonym else ""
|
||||||
ver_part = f" v{cfg_version}" if cfg_version else ""
|
ver_part = f" v{cfg_version}" if cfg_version else ""
|
||||||
compat_part = f" | {cfg_compat}" if cfg_compat else ""
|
compat_part = f" | {cfg_compat}" if cfg_compat else ""
|
||||||
out(f"Конфигурация: {cfg_name}{syn_part}{ver_part} | {total_objects} объектов{compat_part}")
|
out(f"Конфигурация: {cfg_name}{syn_part}{ver_part} | {total_objects} объектов{compat_part}")
|
||||||
|
|
||||||
# --- OVERVIEW mode ---
|
# --- OVERVIEW mode ---
|
||||||
if args.Mode == "overview":
|
if args.Mode == "overview" and not args.Section:
|
||||||
syn_part = f' {dash} "{cfg_synonym}"' if cfg_synonym else ""
|
syn_part = f' {dash} "{cfg_synonym}"' if cfg_synonym else ""
|
||||||
ver_part = f" v{cfg_version}" if cfg_version else ""
|
ver_part = f" v{cfg_version}" if cfg_version else ""
|
||||||
out(f"=== Конфигурация: {cfg_name}{syn_part}{ver_part} ===")
|
out(f"=== Конфигурация: {cfg_name}{syn_part}{ver_part} ===")
|
||||||
@@ -241,6 +297,13 @@ if args.Mode == "overview":
|
|||||||
out(f" {s.ljust(7)} {format_layout_slots(panel_layout[s])}")
|
out(f" {s.ljust(7)} {format_layout_slots(panel_layout[s])}")
|
||||||
out()
|
out()
|
||||||
|
|
||||||
|
# Home page (brief summary)
|
||||||
|
if home_page:
|
||||||
|
out("--- Начальная страница ---")
|
||||||
|
out(f" Шаблон: {home_page['template']}")
|
||||||
|
out(f" LeftColumn: {len(home_page['left'])}, RightColumn: {len(home_page['right'])} (детали: -Section home-page)")
|
||||||
|
out()
|
||||||
|
|
||||||
# Object counts table
|
# Object counts table
|
||||||
out(f"--- Состав ({total_objects} объектов) ---")
|
out(f"--- Состав ({total_objects} объектов) ---")
|
||||||
out()
|
out()
|
||||||
@@ -261,7 +324,30 @@ if args.Mode == "overview":
|
|||||||
out(f" {padded} {count}")
|
out(f" {padded} {count}")
|
||||||
|
|
||||||
# --- FULL mode ---
|
# --- FULL mode ---
|
||||||
if args.Mode == "full":
|
# --- Drill-down: -Section home-page ---
|
||||||
|
if args.Section == "home-page":
|
||||||
|
if not home_page:
|
||||||
|
out("Файл Ext/HomePageWorkArea.xml не найден")
|
||||||
|
else:
|
||||||
|
out(f"=== Начальная страница: {cfg_name} ===")
|
||||||
|
out()
|
||||||
|
out(f"Шаблон: {home_page['template']}")
|
||||||
|
out()
|
||||||
|
for col_lbl, col_key in (("LeftColumn", "left"), ("RightColumn", "right")):
|
||||||
|
items = home_page[col_key]
|
||||||
|
if not items:
|
||||||
|
out(f"{col_lbl}: —")
|
||||||
|
out()
|
||||||
|
continue
|
||||||
|
out(f"{col_lbl} ({len(items)}):")
|
||||||
|
for it in items:
|
||||||
|
out(format_home_page_item(it, True))
|
||||||
|
for r in it["roles"]:
|
||||||
|
rval = "true" if r["value"] else "false"
|
||||||
|
out(f" {r['name']}: {rval}")
|
||||||
|
out()
|
||||||
|
|
||||||
|
if args.Mode == "full" and not args.Section:
|
||||||
syn_part = f' {dash} "{cfg_synonym}"' if cfg_synonym else ""
|
syn_part = f' {dash} "{cfg_synonym}"' if cfg_synonym else ""
|
||||||
ver_part = f" v{cfg_version}" if cfg_version else ""
|
ver_part = f" v{cfg_version}" if cfg_version else ""
|
||||||
out(f"=== Конфигурация: {cfg_name}{syn_part}{ver_part} ===")
|
out(f"=== Конфигурация: {cfg_name}{syn_part}{ver_part} ===")
|
||||||
@@ -350,6 +436,13 @@ if args.Mode == "full":
|
|||||||
out(f" объявлено: {', '.join(panel_layout['declared'])}")
|
out(f" объявлено: {', '.join(panel_layout['declared'])}")
|
||||||
out()
|
out()
|
||||||
|
|
||||||
|
# --- Section: Home page (brief summary) ---
|
||||||
|
if home_page:
|
||||||
|
out("--- Начальная страница ---")
|
||||||
|
out(f" Шаблон: {home_page['template']}")
|
||||||
|
out(f" LeftColumn: {len(home_page['left'])}, RightColumn: {len(home_page['right'])} (детали: -Section home-page)")
|
||||||
|
out()
|
||||||
|
|
||||||
# --- Section: Storages & default forms ---
|
# --- Section: Storages & default forms ---
|
||||||
out("--- Хранилища и формы по умолчанию ---")
|
out("--- Хранилища и формы по умолчанию ---")
|
||||||
storage_props = [
|
storage_props = [
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# cf-validate v1.2 — Validate 1C configuration root structure
|
# cf-validate v1.3 — Validate 1C configuration root structure
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -536,6 +536,72 @@ if ($childObjNode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# --- Check 9: Form references (HomePageWorkArea + Properties) ---
|
||||||
|
function Test-FormRef([string]$ref) {
|
||||||
|
if (-not $ref) { return $true }
|
||||||
|
# UUID — cannot verify without scanning all forms; skip
|
||||||
|
if ($ref -match $guidPattern) { return $true }
|
||||||
|
$parts = $ref.Split(".")
|
||||||
|
if ($parts.Count -eq 2 -and $parts[0] -eq "CommonForm") {
|
||||||
|
$p = Join-Path (Join-Path (Join-Path $configDir "CommonForms") $parts[1]) "Form.xml"
|
||||||
|
$pExt = Join-Path (Join-Path (Join-Path (Join-Path $configDir "CommonForms") $parts[1]) "Ext") "Form.xml"
|
||||||
|
return (Test-Path $p) -or (Test-Path $pExt)
|
||||||
|
}
|
||||||
|
if ($parts.Count -eq 4 -and $parts[2] -eq "Form" -and $childTypeDirMap.ContainsKey($parts[0])) {
|
||||||
|
$dir = $childTypeDirMap[$parts[0]]
|
||||||
|
$p = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $configDir $dir) $parts[1]) "Forms") $parts[3]) "Form.xml"
|
||||||
|
$pExt = Join-Path (Join-Path (Join-Path (Join-Path (Join-Path (Join-Path $configDir $dir) $parts[1]) "Forms") $parts[3]) "Ext") "Form.xml"
|
||||||
|
return (Test-Path $p) -or (Test-Path $pExt)
|
||||||
|
}
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
$formRefsChecked = 0
|
||||||
|
$formRefErrors = @()
|
||||||
|
|
||||||
|
# HomePageWorkArea
|
||||||
|
$hpPath = Join-Path (Join-Path $configDir "Ext") "HomePageWorkArea.xml"
|
||||||
|
if (Test-Path $hpPath) {
|
||||||
|
try {
|
||||||
|
[xml]$hpDoc = Get-Content -Path $hpPath -Encoding UTF8
|
||||||
|
$hpNs = New-Object System.Xml.XmlNamespaceManager($hpDoc.NameTable)
|
||||||
|
$hpNs.AddNamespace("hp", "http://v8.1c.ru/8.3/xcf/extrnprops")
|
||||||
|
foreach ($f in $hpDoc.DocumentElement.SelectNodes("//hp:Item/hp:Form", $hpNs)) {
|
||||||
|
$ref = $f.InnerText.Trim()
|
||||||
|
if (-not $ref) { continue }
|
||||||
|
$formRefsChecked++
|
||||||
|
if (-not (Test-FormRef $ref)) {
|
||||||
|
$formRefErrors += "HomePageWorkArea.Form '$ref' — file not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$formRefErrors += "HomePageWorkArea.xml: parse error — $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Properties: DefaultXxxForm refs
|
||||||
|
if ($propsNode) {
|
||||||
|
$formProps = @("DefaultReportForm","DefaultReportVariantForm","DefaultReportSettingsForm","DefaultDynamicListSettingsForm","DefaultSearchForm","DefaultDataHistoryChangeHistoryForm","DefaultDataHistoryVersionDataForm","DefaultDataHistoryVersionDifferencesForm","DefaultCollaborationSystemUsersChoiceForm","DefaultConstantsForm")
|
||||||
|
foreach ($pn in $formProps) {
|
||||||
|
$node = $propsNode.SelectSingleNode("md:$pn", $ns)
|
||||||
|
if ($node -and $node.InnerText.Trim()) {
|
||||||
|
$ref = $node.InnerText.Trim()
|
||||||
|
$formRefsChecked++
|
||||||
|
if (-not (Test-FormRef $ref)) {
|
||||||
|
$formRefErrors += "Properties.$pn '$ref' — form not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($formRefsChecked -eq 0) {
|
||||||
|
Report-OK "9. Form references: none to check"
|
||||||
|
} elseif ($formRefErrors.Count -eq 0) {
|
||||||
|
Report-OK "9. Form references: $formRefsChecked verified"
|
||||||
|
} else {
|
||||||
|
foreach ($err in $formRefErrors) { Report-Error "9. $err" }
|
||||||
|
}
|
||||||
|
|
||||||
# --- Final output ---
|
# --- Final output ---
|
||||||
& $finalize
|
& $finalize
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# cf-validate v1.2 — Validate 1C configuration XML structure
|
# cf-validate v1.3 — Validate 1C configuration XML structure
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
"""Validates Configuration.xml: root structure, InternalInfo, properties, ChildObjects, languages."""
|
"""Validates Configuration.xml: root structure, InternalInfo, properties, ChildObjects, languages."""
|
||||||
import sys, os, argparse, re
|
import sys, os, argparse, re
|
||||||
@@ -537,6 +537,60 @@ def main():
|
|||||||
else:
|
else:
|
||||||
pass # no ChildObjects
|
pass # no ChildObjects
|
||||||
|
|
||||||
|
# --- Check 9: Form references (HomePageWorkArea + Properties) ---
|
||||||
|
def test_form_ref(ref):
|
||||||
|
if not ref:
|
||||||
|
return True
|
||||||
|
if GUID_PATTERN.match(ref):
|
||||||
|
return True
|
||||||
|
parts = ref.split('.')
|
||||||
|
if len(parts) == 2 and parts[0] == 'CommonForm':
|
||||||
|
p = os.path.join(config_dir, 'CommonForms', parts[1], 'Form.xml')
|
||||||
|
p_ext = os.path.join(config_dir, 'CommonForms', parts[1], 'Ext', 'Form.xml')
|
||||||
|
return os.path.isfile(p) or os.path.isfile(p_ext)
|
||||||
|
if len(parts) == 4 and parts[2] == 'Form' and parts[0] in CHILD_TYPE_DIR_MAP:
|
||||||
|
d = CHILD_TYPE_DIR_MAP[parts[0]]
|
||||||
|
p = os.path.join(config_dir, d, parts[1], 'Forms', parts[3], 'Form.xml')
|
||||||
|
p_ext = os.path.join(config_dir, d, parts[1], 'Forms', parts[3], 'Ext', 'Form.xml')
|
||||||
|
return os.path.isfile(p) or os.path.isfile(p_ext)
|
||||||
|
return False
|
||||||
|
|
||||||
|
form_refs_checked = 0
|
||||||
|
form_ref_errors = []
|
||||||
|
|
||||||
|
hp_path = os.path.join(config_dir, 'Ext', 'HomePageWorkArea.xml')
|
||||||
|
if os.path.isfile(hp_path):
|
||||||
|
try:
|
||||||
|
hp_tree = etree.parse(hp_path)
|
||||||
|
HP_NS = 'http://v8.1c.ru/8.3/xcf/extrnprops'
|
||||||
|
for f in hp_tree.getroot().iter(f'{{{HP_NS}}}Form'):
|
||||||
|
ref = (f.text or '').strip()
|
||||||
|
if not ref:
|
||||||
|
continue
|
||||||
|
form_refs_checked += 1
|
||||||
|
if not test_form_ref(ref):
|
||||||
|
form_ref_errors.append(f"HomePageWorkArea.Form '{ref}' — file not found")
|
||||||
|
except Exception as e:
|
||||||
|
form_ref_errors.append(f'HomePageWorkArea.xml: parse error — {e}')
|
||||||
|
|
||||||
|
if props_node is not None:
|
||||||
|
form_props = ['DefaultReportForm','DefaultReportVariantForm','DefaultReportSettingsForm','DefaultDynamicListSettingsForm','DefaultSearchForm','DefaultDataHistoryChangeHistoryForm','DefaultDataHistoryVersionDataForm','DefaultDataHistoryVersionDifferencesForm','DefaultCollaborationSystemUsersChoiceForm','DefaultConstantsForm']
|
||||||
|
for pn in form_props:
|
||||||
|
node = props_node.find(f'md:{pn}', NS)
|
||||||
|
if node is not None and node.text and node.text.strip():
|
||||||
|
ref = node.text.strip()
|
||||||
|
form_refs_checked += 1
|
||||||
|
if not test_form_ref(ref):
|
||||||
|
form_ref_errors.append(f"Properties.{pn} '{ref}' — form not found")
|
||||||
|
|
||||||
|
if form_refs_checked == 0:
|
||||||
|
r.ok('9. Form references: none to check')
|
||||||
|
elif not form_ref_errors:
|
||||||
|
r.ok(f'9. Form references: {form_refs_checked} verified')
|
||||||
|
else:
|
||||||
|
for err in form_ref_errors:
|
||||||
|
r.error(f'9. {err}')
|
||||||
|
|
||||||
# --- Final output ---
|
# --- Final output ---
|
||||||
r.finalize(out_file)
|
r.finalize(out_file)
|
||||||
sys.exit(1 if r.errors > 0 else 0)
|
sys.exit(1 if r.errors > 0 else 0)
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "Установить начальную страницу (template + left/right + visibility/roles)",
|
||||||
|
"input": [
|
||||||
|
{
|
||||||
|
"operation": "set-home-page",
|
||||||
|
"value": {
|
||||||
|
"template": "TwoColumnsVariableWidth",
|
||||||
|
"left": [
|
||||||
|
"CommonForm.НачалоРаботы",
|
||||||
|
{ "form": "CommonForm.СписокЗадач", "height": 100, "visibility": false },
|
||||||
|
{ "form": "Справочник.Контрагенты.ФормаСписка", "height": 50 },
|
||||||
|
{
|
||||||
|
"form": "CommonForm.РабочийСтолОператора",
|
||||||
|
"visibility": false,
|
||||||
|
"roles": { "Role.Оператор": true, "ПолныеПрава": false }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"right": [
|
||||||
|
{ "form": "DataProcessor.Поиск.Form.ФормаПоиска", "height": 30 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+18
@@ -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>
|
||||||
+18
@@ -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>
|
||||||
+18
@@ -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,251 @@
|
|||||||
|
<?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">
|
||||||
|
<Configuration uuid="UUID-001">
|
||||||
|
<InternalInfo>
|
||||||
|
<xr:ContainedObject>
|
||||||
|
<xr:ClassId>UUID-002</xr:ClassId>
|
||||||
|
<xr:ObjectId>UUID-003</xr:ObjectId>
|
||||||
|
</xr:ContainedObject>
|
||||||
|
<xr:ContainedObject>
|
||||||
|
<xr:ClassId>UUID-004</xr:ClassId>
|
||||||
|
<xr:ObjectId>UUID-005</xr:ObjectId>
|
||||||
|
</xr:ContainedObject>
|
||||||
|
<xr:ContainedObject>
|
||||||
|
<xr:ClassId>UUID-006</xr:ClassId>
|
||||||
|
<xr:ObjectId>UUID-007</xr:ObjectId>
|
||||||
|
</xr:ContainedObject>
|
||||||
|
<xr:ContainedObject>
|
||||||
|
<xr:ClassId>UUID-008</xr:ClassId>
|
||||||
|
<xr:ObjectId>UUID-009</xr:ObjectId>
|
||||||
|
</xr:ContainedObject>
|
||||||
|
<xr:ContainedObject>
|
||||||
|
<xr:ClassId>UUID-010</xr:ClassId>
|
||||||
|
<xr:ObjectId>UUID-011</xr:ObjectId>
|
||||||
|
</xr:ContainedObject>
|
||||||
|
<xr:ContainedObject>
|
||||||
|
<xr:ClassId>UUID-012</xr:ClassId>
|
||||||
|
<xr:ObjectId>UUID-013</xr:ObjectId>
|
||||||
|
</xr:ContainedObject>
|
||||||
|
<xr:ContainedObject>
|
||||||
|
<xr:ClassId>UUID-014</xr:ClassId>
|
||||||
|
<xr:ObjectId>UUID-015</xr:ObjectId>
|
||||||
|
</xr:ContainedObject>
|
||||||
|
</InternalInfo>
|
||||||
|
<Properties>
|
||||||
|
<Name>TestConfig</Name>
|
||||||
|
<Synonym>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>TestConfig</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</Synonym>
|
||||||
|
<Comment />
|
||||||
|
<NamePrefix />
|
||||||
|
<ConfigurationExtensionCompatibilityMode>Version8_3_24</ConfigurationExtensionCompatibilityMode>
|
||||||
|
<DefaultRunMode>ManagedApplication</DefaultRunMode>
|
||||||
|
<UsePurposes>
|
||||||
|
<v8:Value xsi:type="app:ApplicationUsePurpose">PlatformApplication</v8:Value>
|
||||||
|
</UsePurposes>
|
||||||
|
<ScriptVariant>Russian</ScriptVariant>
|
||||||
|
<DefaultRoles />
|
||||||
|
<Vendor></Vendor>
|
||||||
|
<Version></Version>
|
||||||
|
<UpdateCatalogAddress />
|
||||||
|
<IncludeHelpInContents>false</IncludeHelpInContents>
|
||||||
|
<UseManagedFormInOrdinaryApplication>false</UseManagedFormInOrdinaryApplication>
|
||||||
|
<UseOrdinaryFormInManagedApplication>false</UseOrdinaryFormInManagedApplication>
|
||||||
|
<AdditionalFullTextSearchDictionaries />
|
||||||
|
<CommonSettingsStorage />
|
||||||
|
<ReportsUserSettingsStorage />
|
||||||
|
<ReportsVariantsStorage />
|
||||||
|
<FormDataSettingsStorage />
|
||||||
|
<DynamicListsUserSettingsStorage />
|
||||||
|
<URLExternalDataStorage />
|
||||||
|
<Content />
|
||||||
|
<DefaultReportForm />
|
||||||
|
<DefaultReportVariantForm />
|
||||||
|
<DefaultReportSettingsForm />
|
||||||
|
<DefaultReportAppearanceTemplate />
|
||||||
|
<DefaultDynamicListSettingsForm />
|
||||||
|
<DefaultSearchForm />
|
||||||
|
<DefaultDataHistoryChangeHistoryForm />
|
||||||
|
<DefaultDataHistoryVersionDataForm />
|
||||||
|
<DefaultDataHistoryVersionDifferencesForm />
|
||||||
|
<DefaultCollaborationSystemUsersChoiceForm />
|
||||||
|
<RequiredMobileApplicationPermissions />
|
||||||
|
<UsedMobileApplicationFunctionalities>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Biometrics</app:functionality>
|
||||||
|
<app:use>true</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Location</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>BackgroundLocation</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>BluetoothPrinters</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>WiFiPrinters</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Contacts</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Calendars</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>PushNotifications</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>LocalNotifications</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>InAppPurchases</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>PersonalComputerFileExchange</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Ads</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>NumberDialing</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>CallProcessing</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>CallLog</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>AutoSendSMS</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>ReceiveSMS</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>SMSLog</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Camera</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Microphone</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>MusicLibrary</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>PictureAndVideoLibraries</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>AudioPlaybackAndVibration</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>BackgroundAudioPlaybackAndVibration</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>InstallPackages</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>OSBackup</app:functionality>
|
||||||
|
<app:use>true</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>ApplicationUsageStatistics</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>BarcodeScanning</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>BackgroundAudioRecording</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>AllFilesAccess</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Videoconferences</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>NFC</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>DocumentScanning</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>SpeechToText</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>Geofences</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>IncomingShareRequests</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
<app:functionality>
|
||||||
|
<app:functionality>AllIncomingShareRequestsTypesProcessing</app:functionality>
|
||||||
|
<app:use>false</app:use>
|
||||||
|
</app:functionality>
|
||||||
|
</UsedMobileApplicationFunctionalities>
|
||||||
|
<StandaloneConfigurationRestrictionRoles />
|
||||||
|
<MobileApplicationURLs />
|
||||||
|
<AllowedIncomingShareRequestTypes />
|
||||||
|
<MainClientApplicationWindowMode>Normal</MainClientApplicationWindowMode>
|
||||||
|
<DefaultInterface />
|
||||||
|
<DefaultStyle />
|
||||||
|
<DefaultLanguage>Language.Русский</DefaultLanguage>
|
||||||
|
<BriefInformation />
|
||||||
|
<DetailedInformation />
|
||||||
|
<Copyright />
|
||||||
|
<VendorInformationAddress />
|
||||||
|
<ConfigurationInformationAddress />
|
||||||
|
<DataLockControlMode>Managed</DataLockControlMode>
|
||||||
|
<ObjectAutonumerationMode>NotAutoFree</ObjectAutonumerationMode>
|
||||||
|
<ModalityUseMode>DontUse</ModalityUseMode>
|
||||||
|
<SynchronousPlatformExtensionAndAddInCallUseMode>DontUse</SynchronousPlatformExtensionAndAddInCallUseMode>
|
||||||
|
<InterfaceCompatibilityMode>TaxiEnableVersion8_2</InterfaceCompatibilityMode>
|
||||||
|
<DatabaseTablespacesUseMode>DontUse</DatabaseTablespacesUseMode>
|
||||||
|
<CompatibilityMode>Version8_3_24</CompatibilityMode>
|
||||||
|
<DefaultConstantsForm />
|
||||||
|
</Properties>
|
||||||
|
<ChildObjects>
|
||||||
|
<Language>Русский</Language>
|
||||||
|
</ChildObjects>
|
||||||
|
</Configuration>
|
||||||
|
</MetaDataObject>
|
||||||
@@ -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,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<HomePageWorkArea xmlns="http://v8.1c.ru/8.3/xcf/extrnprops" 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">
|
||||||
|
<WorkingAreaTemplate>TwoColumnsVariableWidth</WorkingAreaTemplate>
|
||||||
|
<LeftColumn>
|
||||||
|
<Item>
|
||||||
|
<Form>CommonForm.НачалоРаботы</Form>
|
||||||
|
<Height>10</Height>
|
||||||
|
<Visibility>
|
||||||
|
<xr:Common>true</xr:Common>
|
||||||
|
</Visibility>
|
||||||
|
</Item>
|
||||||
|
<Item>
|
||||||
|
<Form>CommonForm.СписокЗадач</Form>
|
||||||
|
<Height>100</Height>
|
||||||
|
<Visibility>
|
||||||
|
<xr:Common>false</xr:Common>
|
||||||
|
</Visibility>
|
||||||
|
</Item>
|
||||||
|
<Item>
|
||||||
|
<Form>Catalog.Контрагенты.Form.ФормаСписка</Form>
|
||||||
|
<Height>50</Height>
|
||||||
|
<Visibility>
|
||||||
|
<xr:Common>true</xr:Common>
|
||||||
|
</Visibility>
|
||||||
|
</Item>
|
||||||
|
<Item>
|
||||||
|
<Form>CommonForm.РабочийСтолОператора</Form>
|
||||||
|
<Height>10</Height>
|
||||||
|
<Visibility>
|
||||||
|
<xr:Common>false</xr:Common>
|
||||||
|
<xr:Value name="Role.Оператор">true</xr:Value>
|
||||||
|
<xr:Value name="Role.ПолныеПрава">false</xr:Value>
|
||||||
|
</Visibility>
|
||||||
|
</Item>
|
||||||
|
</LeftColumn>
|
||||||
|
<RightColumn>
|
||||||
|
<Item>
|
||||||
|
<Form>DataProcessor.Поиск.Form.ФормаПоиска</Form>
|
||||||
|
<Height>30</Height>
|
||||||
|
<Visibility>
|
||||||
|
<xr:Common>true</xr:Common>
|
||||||
|
</Visibility>
|
||||||
|
</Item>
|
||||||
|
</RightColumn>
|
||||||
|
</HomePageWorkArea>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<?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">
|
||||||
|
<Language uuid="UUID-001">
|
||||||
|
<Properties>
|
||||||
|
<Name>Русский</Name>
|
||||||
|
<Synonym>
|
||||||
|
<v8:item>
|
||||||
|
<v8:lang>ru</v8:lang>
|
||||||
|
<v8:content>Русский</v8:content>
|
||||||
|
</v8:item>
|
||||||
|
</Synonym>
|
||||||
|
<Comment/>
|
||||||
|
<LanguageCode>ru</LanguageCode>
|
||||||
|
</Properties>
|
||||||
|
</Language>
|
||||||
|
</MetaDataObject>
|
||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user