mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-12 00:44:57 +03:00
feat(skd): form C drilldown + per-cell drilldown override + fieldTemplates
Расширение DSL для area-templates под отчёты с расшифровкой через
data-параметр (типа АнализВыполненияМаршрутныхЛистов в ERP).
Раньше шорткат `drilldown: "X"` всегда генерировал
`Расшифровка_X` + `ИмяРесурса`/`DrillDown`. Появилось три формы:
- A: { name, expression } — без drilldown
- B: { name, expression, drilldown: "X" } — текущий shortcut (без изменений)
- C: { name, drilldown: { field, expression, action } } — самостоятельный
DetailsAreaTemplateParameter
Per-cell override: ячейка может быть object `{ value, drilldown }` —
тогда appearance ссылается на указанный параметр расшифровки (без
префикса `Расшифровка_`). Используется когда несколько ячеек должны
указывать на один details-параметр (МаршрутныйЛист).
Новая корневая секция:
"fieldTemplates": [{ "field": "X", "template": "Макет1" }]
— XML <fieldTemplate><field/><template/></fieldTemplate>.
compile (PS+Py): новый helper Emit-AreaTemplateParameter, ветка form C
в Emit-AreaTemplateDSL/Emit-Templates raw-mode, Emit-FieldTemplates.
Cell rendering: проверка cell.drilldown override перед drilldownMap.
decompile (PS): Build-Template переписан — собирает все
DetailsAreaTemplateParameter в map; распознаёт shortcut form B по
canonical shape (Расшифровка_<Y>/ИмяРесурса/"<Y>"/DrillDown) И наличию
cell appearance ref на этот target; не-shortcut → form C entry.
Cell wrapping: если drilldownTarget ≠ shortcut Расшифровка_Y, ячейка
оборачивается в { value, drilldown }. Plus Build-FieldTemplates.
Размер diff на sample30: 1045 → 809 строк (-22.5% за сессию).
This commit is contained in:
@@ -344,8 +344,9 @@ Raw XML (`"template": "<...>"`) остаётся как fallback. Детект:
|
||||
|
||||
### Расшифровка (drilldown) в параметрах шаблона
|
||||
|
||||
Ключ `drilldown` в параметре шаблона автоматически генерирует `DetailsAreaTemplateParameter` и привязку `Расшифровка` в appearance ячеек:
|
||||
Ключ `drilldown` в параметре шаблона управляет генерацией `DetailsAreaTemplateParameter` и привязкой `Расшифровка` в appearance ячеек. Различает три формы по типу значения.
|
||||
|
||||
**Форма B (shortcut, строка) — расшифровка через `ИмяРесурса`/`DrillDown`:**
|
||||
```json
|
||||
"parameters": [
|
||||
{ "name": "Сырье", "expression": "ПоступлениеСырья", "drilldown": "ПоступлениеСырья" }
|
||||
@@ -354,6 +355,38 @@ Raw XML (`"template": "<...>"`) остаётся как fallback. Детект:
|
||||
|
||||
Генерирует: `ExpressionAreaTemplateParameter` (обычный) + `DetailsAreaTemplateParameter` с именем `Расшифровка_ПоступлениеСырья`, `fieldExpression` по полю `ИмяРесурса`, `mainAction=DrillDown`. Ячейки `{Сырье}` автоматически получают appearance `Расшифровка = Расшифровка_ПоступлениеСырья`.
|
||||
|
||||
**Форма C (объект) — произвольный `DetailsAreaTemplateParameter`:**
|
||||
```json
|
||||
"parameters": [
|
||||
{ "name": "Номер", "expression": "МаршрутныйЛист.Номер" },
|
||||
{ "name": "Дата", "expression": "МаршрутныйЛист.Дата" },
|
||||
{ "name": "МаршрутныйЛист",
|
||||
"drilldown": { "field": "МаршрутныйЛист", "expression": "МаршрутныйЛист", "action": "OpenValue" } }
|
||||
]
|
||||
```
|
||||
|
||||
Параметр без `expression` и с `drilldown` в виде объекта — это самостоятельный `DetailsAreaTemplateParameter` с именем `name`, `fieldExpression={field, expression}`, `mainAction=action` (по умолчанию `DrillDown`). Используется когда `mainAction=OpenValue` (открытие ссылки на data-параметр), либо когда расшифровка не привязана к `ИмяРесурса`.
|
||||
|
||||
**Override расшифровки на уровне ячейки:**
|
||||
```json
|
||||
"rows": [
|
||||
[ { "value": "{Номер}", "drilldown": "МаршрутныйЛист" },
|
||||
{ "value": "{Дата}", "drilldown": "МаршрутныйЛист" } ]
|
||||
]
|
||||
```
|
||||
|
||||
Object-форма ячейки `{ value, drilldown }`: appearance ячейки получит `Расшифровка → <drilldown>` (без префикса `Расшифровка_`). Используется когда несколько ячеек должны указывать на один и тот же параметр расшифровки, объявленный через форму C. Если в ячейке-строке `{X}` есть param X со shortcut form B — appearance подставляется автоматически, override не нужен.
|
||||
|
||||
### Привязка макета к полю — `fieldTemplates`
|
||||
|
||||
```json
|
||||
"fieldTemplates": [
|
||||
{ "field": "МаршрутныйЛист", "template": "Макет1" }
|
||||
]
|
||||
```
|
||||
|
||||
Эквивалент XML-секции `<fieldTemplate><field>X</field><template>Y</template></fieldTemplate>` — при выводе значения поля `X` используется именованный area-template `Y`.
|
||||
|
||||
### Привязки макетов к группировкам
|
||||
|
||||
```json
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# skd-compile v1.91 — Compile 1C DCS from JSON
|
||||
# skd-compile v1.92 — Compile 1C DCS from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$DefinitionFile,
|
||||
@@ -1800,11 +1800,14 @@ function Emit-AreaTemplateDSL {
|
||||
}
|
||||
}
|
||||
|
||||
# Build drilldown map: param_name -> drilldown_value
|
||||
# Build drilldown map: param_name -> drilldown_value (только для shortcut-формы — drilldown:string).
|
||||
# Форма C (drilldown:object) — DetailsAreaTemplateParameter с произвольным именем, в map не идёт.
|
||||
$drilldownMap = @{}
|
||||
if ($t.parameters) {
|
||||
foreach ($tp in $t.parameters) {
|
||||
if ($tp.drilldown) { $drilldownMap["$($tp.name)"] = "$($tp.drilldown)" }
|
||||
if ($tp.drilldown -and ($tp.drilldown -is [string])) {
|
||||
$drilldownMap["$($tp.name)"] = "$($tp.drilldown)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1848,13 +1851,25 @@ function Emit-AreaTemplateDSL {
|
||||
X "`t`t`t`t`t<dcsat:item xsi:type=`"dcsat:Field`">"
|
||||
X "`t`t`t`t`t`t<dcsat:value xsi:type=`"dcscor:Parameter`">$(Esc-Xml $paramName)</dcsat:value>"
|
||||
X "`t`t`t`t`t</dcsat:item>"
|
||||
# Build drilldown appearance extra items
|
||||
# Build drilldown appearance extra items.
|
||||
# Приоритет: per-cell override (cell={value, drilldown}) → drilldownMap (shortcut form B).
|
||||
$cellExtraItems = @()
|
||||
if ($drilldownMap.ContainsKey($paramName)) {
|
||||
$ddVal = $drilldownMap[$paramName]
|
||||
$cellDrillOverride = $null
|
||||
if ($cellRaw -is [PSCustomObject] -and $cellRaw.PSObject.Properties['drilldown']) {
|
||||
$cellDrillOverride = "$($cellRaw.drilldown)"
|
||||
} elseif (($cellRaw -is [hashtable] -or $cellRaw -is [System.Collections.IDictionary]) -and $cellRaw.Contains('drilldown')) {
|
||||
$cellDrillOverride = "$($cellRaw['drilldown'])"
|
||||
}
|
||||
$ddTarget = $null
|
||||
if ($cellDrillOverride) {
|
||||
$ddTarget = $cellDrillOverride
|
||||
} elseif ($drilldownMap.ContainsKey($paramName)) {
|
||||
$ddTarget = "Расшифровка_$($drilldownMap[$paramName])"
|
||||
}
|
||||
if ($ddTarget) {
|
||||
$cellExtraItems += "`t`t`t`t`t`t<dcscor:item>"
|
||||
$cellExtraItems += "`t`t`t`t`t`t`t<dcscor:parameter>Расшифровка</dcscor:parameter>"
|
||||
$cellExtraItems += "`t`t`t`t`t`t`t<dcscor:value xsi:type=`"dcscor:Parameter`">Расшифровка_$ddVal</dcscor:value>"
|
||||
$cellExtraItems += "`t`t`t`t`t`t`t<dcscor:value xsi:type=`"dcscor:Parameter`">$(Esc-Xml $ddTarget)</dcscor:value>"
|
||||
$cellExtraItems += "`t`t`t`t`t`t</dcscor:item>"
|
||||
}
|
||||
} else {
|
||||
@@ -1879,27 +1894,62 @@ function Emit-AreaTemplateDSL {
|
||||
# Parameters (reuse existing logic)
|
||||
if ($t.parameters) {
|
||||
foreach ($tp in $t.parameters) {
|
||||
X "`t`t<parameter xmlns:dcsat=`"http://v8.1c.ru/8.1/data-composition-system/area-template`" xsi:type=`"dcsat:ExpressionAreaTemplateParameter`">"
|
||||
X "`t`t`t<dcsat:name>$(Esc-Xml "$($tp.name)")</dcsat:name>"
|
||||
X "`t`t`t<dcsat:expression>$(Esc-Xml "$($tp.expression)")</dcsat:expression>"
|
||||
X "`t`t</parameter>"
|
||||
# Drilldown parameter
|
||||
if ($tp.drilldown) {
|
||||
$ddVal = "$($tp.drilldown)"
|
||||
X "`t`t<parameter xmlns:dcsat=`"http://v8.1c.ru/8.1/data-composition-system/area-template`" xsi:type=`"dcsat:DetailsAreaTemplateParameter`">"
|
||||
X "`t`t`t<dcsat:name>Расшифровка_$(Esc-Xml $ddVal)</dcsat:name>"
|
||||
X "`t`t`t<dcsat:fieldExpression>"
|
||||
X "`t`t`t`t<dcsat:field>ИмяРесурса</dcsat:field>"
|
||||
X "`t`t`t`t<dcsat:expression>`"$(Esc-Xml $ddVal)`"</dcsat:expression>"
|
||||
X "`t`t`t</dcsat:fieldExpression>"
|
||||
X "`t`t`t<dcsat:mainAction>DrillDown</dcsat:mainAction>"
|
||||
X "`t`t</parameter>"
|
||||
}
|
||||
Emit-AreaTemplateParameter -tp $tp -indent "`t`t"
|
||||
}
|
||||
}
|
||||
X "`t</template>"
|
||||
}
|
||||
|
||||
# Эмиссия одного параметра шаблона. Различает три формы:
|
||||
# A. { name, expression } → ExpressionAreaTemplateParameter
|
||||
# B. { name, expression, drilldown: "X" } → Expression + Details(Расшифровка_X, ИмяРесурса, DrillDown) [shortcut]
|
||||
# C. { name, drilldown: { field, expression, action? } } → DetailsAreaTemplateParameter с произвольным name
|
||||
function Emit-AreaTemplateParameter {
|
||||
param($tp, [string]$indent)
|
||||
# Определяем форму C: drilldown — объект с полем field или expression.
|
||||
$dd = $tp.drilldown
|
||||
$ddIsObject = $false
|
||||
if ($null -ne $dd) {
|
||||
if ($dd -is [hashtable] -or $dd -is [System.Collections.IDictionary]) { $ddIsObject = $true }
|
||||
elseif ($dd -is [PSCustomObject]) { $ddIsObject = $true }
|
||||
}
|
||||
if ($ddIsObject) {
|
||||
# Форма C
|
||||
$ddField = if ($dd -is [PSCustomObject]) { "$($dd.field)" } else { "$($dd['field'])" }
|
||||
$ddExpr = if ($dd -is [PSCustomObject]) { "$($dd.expression)" } else { "$($dd['expression'])" }
|
||||
$ddActV = $null
|
||||
if ($dd -is [PSCustomObject] -and $dd.PSObject.Properties['action']) { $ddActV = "$($dd.action)" }
|
||||
elseif (($dd -is [hashtable] -or $dd -is [System.Collections.IDictionary]) -and $dd.Contains('action')) { $ddActV = "$($dd['action'])" }
|
||||
$ddAct = if ($ddActV) { $ddActV } else { 'DrillDown' }
|
||||
X "$indent<parameter xmlns:dcsat=`"http://v8.1c.ru/8.1/data-composition-system/area-template`" xsi:type=`"dcsat:DetailsAreaTemplateParameter`">"
|
||||
X "$indent`t<dcsat:name>$(Esc-Xml "$($tp.name)")</dcsat:name>"
|
||||
X "$indent`t<dcsat:fieldExpression>"
|
||||
X "$indent`t`t<dcsat:field>$(Esc-Xml $ddField)</dcsat:field>"
|
||||
X "$indent`t`t<dcsat:expression>$(Esc-Xml $ddExpr)</dcsat:expression>"
|
||||
X "$indent`t</dcsat:fieldExpression>"
|
||||
X "$indent`t<dcsat:mainAction>$(Esc-Xml $ddAct)</dcsat:mainAction>"
|
||||
X "$indent</parameter>"
|
||||
return
|
||||
}
|
||||
# Форма A или B
|
||||
X "$indent<parameter xmlns:dcsat=`"http://v8.1c.ru/8.1/data-composition-system/area-template`" xsi:type=`"dcsat:ExpressionAreaTemplateParameter`">"
|
||||
X "$indent`t<dcsat:name>$(Esc-Xml "$($tp.name)")</dcsat:name>"
|
||||
X "$indent`t<dcsat:expression>$(Esc-Xml "$($tp.expression)")</dcsat:expression>"
|
||||
X "$indent</parameter>"
|
||||
if ($dd -and ($dd -is [string])) {
|
||||
# Форма B: shortcut Расшифровка_<X> + ИмяРесурса + DrillDown
|
||||
$ddVal = "$dd"
|
||||
X "$indent<parameter xmlns:dcsat=`"http://v8.1c.ru/8.1/data-composition-system/area-template`" xsi:type=`"dcsat:DetailsAreaTemplateParameter`">"
|
||||
X "$indent`t<dcsat:name>Расшифровка_$(Esc-Xml $ddVal)</dcsat:name>"
|
||||
X "$indent`t<dcsat:fieldExpression>"
|
||||
X "$indent`t`t<dcsat:field>ИмяРесурса</dcsat:field>"
|
||||
X "$indent`t`t<dcsat:expression>`"$(Esc-Xml $ddVal)`"</dcsat:expression>"
|
||||
X "$indent`t</dcsat:fieldExpression>"
|
||||
X "$indent`t<dcsat:mainAction>DrillDown</dcsat:mainAction>"
|
||||
X "$indent</parameter>"
|
||||
}
|
||||
}
|
||||
|
||||
# === Templates ===
|
||||
function Emit-Templates {
|
||||
if (-not $def.templates) { return }
|
||||
@@ -1916,22 +1966,7 @@ function Emit-Templates {
|
||||
}
|
||||
if ($t.parameters) {
|
||||
foreach ($tp in $t.parameters) {
|
||||
X "`t`t<parameter xmlns:dcsat=`"http://v8.1c.ru/8.1/data-composition-system/area-template`" xsi:type=`"dcsat:ExpressionAreaTemplateParameter`">"
|
||||
X "`t`t`t<dcsat:name>$(Esc-Xml "$($tp.name)")</dcsat:name>"
|
||||
X "`t`t`t<dcsat:expression>$(Esc-Xml "$($tp.expression)")</dcsat:expression>"
|
||||
X "`t`t</parameter>"
|
||||
# Drilldown parameter
|
||||
if ($tp.drilldown) {
|
||||
$ddVal = "$($tp.drilldown)"
|
||||
X "`t`t<parameter xmlns:dcsat=`"http://v8.1c.ru/8.1/data-composition-system/area-template`" xsi:type=`"dcsat:DetailsAreaTemplateParameter`">"
|
||||
X "`t`t`t<dcsat:name>Расшифровка_$(Esc-Xml $ddVal)</dcsat:name>"
|
||||
X "`t`t`t<dcsat:fieldExpression>"
|
||||
X "`t`t`t`t<dcsat:field>ИмяРесурса</dcsat:field>"
|
||||
X "`t`t`t`t<dcsat:expression>`"$(Esc-Xml $ddVal)`"</dcsat:expression>"
|
||||
X "`t`t`t</dcsat:fieldExpression>"
|
||||
X "`t`t`t<dcsat:mainAction>DrillDown</dcsat:mainAction>"
|
||||
X "`t`t</parameter>"
|
||||
}
|
||||
Emit-AreaTemplateParameter -tp $tp -indent "`t`t"
|
||||
}
|
||||
}
|
||||
X "`t</template>"
|
||||
@@ -1939,6 +1974,19 @@ function Emit-Templates {
|
||||
}
|
||||
}
|
||||
|
||||
# === FieldTemplates ===
|
||||
# Привязка <fieldTemplate><field/><template/></fieldTemplate> поля к именованному area-template.
|
||||
# DSL: "fieldTemplates": [{ "field": "X", "template": "Макет1" }, ...]
|
||||
function Emit-FieldTemplates {
|
||||
if (-not $def.fieldTemplates) { return }
|
||||
foreach ($ft in $def.fieldTemplates) {
|
||||
X "`t<fieldTemplate>"
|
||||
X "`t`t<field>$(Esc-Xml "$($ft.field)")</field>"
|
||||
X "`t`t<template>$(Esc-Xml "$($ft.template)")</template>"
|
||||
X "`t</fieldTemplate>"
|
||||
}
|
||||
}
|
||||
|
||||
# === GroupTemplates ===
|
||||
function Emit-GroupTemplates {
|
||||
if (-not $def.groupTemplates) { return }
|
||||
@@ -3268,6 +3316,7 @@ Emit-CalcFields
|
||||
Emit-TotalFields
|
||||
Emit-Parameters
|
||||
Emit-Templates
|
||||
Emit-FieldTemplates
|
||||
Emit-GroupTemplates
|
||||
Emit-SettingsVariants
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# skd-compile v1.91 — Compile 1C DCS from JSON
|
||||
# skd-compile v1.92 — Compile 1C DCS from JSON
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import json
|
||||
@@ -1484,12 +1484,14 @@ def _emit_area_template_dsl(lines, t):
|
||||
if cell_val == '>':
|
||||
h_merge[r][c] = True
|
||||
|
||||
# Build drilldown map: param_name -> drilldown_value
|
||||
# Build drilldown map: param_name -> drilldown_value (только shortcut-форма: drilldown — строка).
|
||||
# Форма C (drilldown — объект) — DetailsAreaTemplateParameter с произвольным именем, в map не идёт.
|
||||
drilldown_map = {}
|
||||
if t.get('parameters'):
|
||||
for tp in t['parameters']:
|
||||
if tp.get('drilldown'):
|
||||
drilldown_map[str(tp['name'])] = str(tp['drilldown'])
|
||||
dd = tp.get('drilldown')
|
||||
if dd and isinstance(dd, str):
|
||||
drilldown_map[str(tp['name'])] = dd
|
||||
|
||||
lines.append('\t<template>')
|
||||
lines.append(f'\t\t<name>{esc_xml(str(t["name"]))}</name>')
|
||||
@@ -1529,12 +1531,20 @@ def _emit_area_template_dsl(lines, t):
|
||||
lines.append('\t\t\t\t\t<dcsat:item xsi:type="dcsat:Field">')
|
||||
lines.append(f'\t\t\t\t\t\t<dcsat:value xsi:type="dcscor:Parameter">{esc_xml(param_name)}</dcsat:value>')
|
||||
lines.append('\t\t\t\t\t</dcsat:item>')
|
||||
# Build drilldown appearance extra items
|
||||
if param_name in drilldown_map:
|
||||
dd_val = drilldown_map[param_name]
|
||||
# Build drilldown appearance extra items.
|
||||
# \u041f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442: per-cell override (cell={value, drilldown}) \u2192 drilldownMap (shortcut form B).
|
||||
cell_drill_override = None
|
||||
if isinstance(cell_raw, dict) and 'drilldown' in cell_raw:
|
||||
cell_drill_override = str(cell_raw['drilldown'])
|
||||
dd_target = None
|
||||
if cell_drill_override:
|
||||
dd_target = cell_drill_override
|
||||
elif param_name in drilldown_map:
|
||||
dd_target = f'\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_{drilldown_map[param_name]}'
|
||||
if dd_target:
|
||||
cell_extra_items.append('\t\t\t\t\t\t<dcscor:item>')
|
||||
cell_extra_items.append(f'\t\t\t\t\t\t\t<dcscor:parameter>\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430</dcscor:parameter>')
|
||||
cell_extra_items.append(f'\t\t\t\t\t\t\t<dcscor:value xsi:type="dcscor:Parameter">\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_{dd_val}</dcscor:value>')
|
||||
cell_extra_items.append(f'\t\t\t\t\t\t\t<dcscor:value xsi:type="dcscor:Parameter">{esc_xml(dd_target)}</dcscor:value>')
|
||||
cell_extra_items.append('\t\t\t\t\t\t</dcscor:item>')
|
||||
else:
|
||||
lines.append('\t\t\t\t\t<dcsat:item xsi:type="dcsat:Field">')
|
||||
@@ -1548,24 +1558,48 @@ def _emit_area_template_dsl(lines, t):
|
||||
lines.append('\t\t</template>')
|
||||
if t.get('parameters'):
|
||||
for tp in t['parameters']:
|
||||
lines.append('\t\t<parameter xmlns:dcsat="http://v8.1c.ru/8.1/data-composition-system/area-template" xsi:type="dcsat:ExpressionAreaTemplateParameter">')
|
||||
lines.append(f'\t\t\t<dcsat:name>{esc_xml(str(tp["name"]))}</dcsat:name>')
|
||||
lines.append(f'\t\t\t<dcsat:expression>{esc_xml(str(tp["expression"]))}</dcsat:expression>')
|
||||
lines.append('\t\t</parameter>')
|
||||
# Drilldown parameter
|
||||
if tp.get('drilldown'):
|
||||
dd_val = str(tp['drilldown'])
|
||||
lines.append('\t\t<parameter xmlns:dcsat="http://v8.1c.ru/8.1/data-composition-system/area-template" xsi:type="dcsat:DetailsAreaTemplateParameter">')
|
||||
lines.append(f'\t\t\t<dcsat:name>\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_{esc_xml(dd_val)}</dcsat:name>')
|
||||
lines.append('\t\t\t<dcsat:fieldExpression>')
|
||||
lines.append('\t\t\t\t<dcsat:field>\u0418\u043c\u044f\u0420\u0435\u0441\u0443\u0440\u0441\u0430</dcsat:field>')
|
||||
lines.append(f'\t\t\t\t<dcsat:expression>"{esc_xml(dd_val)}"</dcsat:expression>')
|
||||
lines.append('\t\t\t</dcsat:fieldExpression>')
|
||||
lines.append('\t\t\t<dcsat:mainAction>DrillDown</dcsat:mainAction>')
|
||||
lines.append('\t\t</parameter>')
|
||||
_emit_area_template_parameter(lines, tp, '\t\t')
|
||||
lines.append('\t</template>')
|
||||
|
||||
|
||||
# \u042d\u043c\u0438\u0441\u0441\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u0430. \u0420\u0430\u0437\u043b\u0438\u0447\u0430\u0435\u0442 \u0442\u0440\u0438 \u0444\u043e\u0440\u043c\u044b:
|
||||
# A. {name, expression} \u2192 ExpressionAreaTemplateParameter
|
||||
# B. {name, expression, drilldown: "X"} \u2192 Expression + Details(\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_X, \u0418\u043c\u044f\u0420\u0435\u0441\u0443\u0440\u0441\u0430, DrillDown)
|
||||
# C. {name, drilldown: {field, expression, action?}} \u2192 DetailsAreaTemplateParameter \u0441 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u043c \u0438\u043c\u0435\u043d\u0435\u043c
|
||||
def _emit_area_template_parameter(lines, tp, indent):
|
||||
dd = tp.get('drilldown')
|
||||
if isinstance(dd, dict):
|
||||
# \u0424\u043e\u0440\u043c\u0430 C
|
||||
dd_field = str(dd.get('field', ''))
|
||||
dd_expr = str(dd.get('expression', ''))
|
||||
dd_act = str(dd.get('action') or 'DrillDown')
|
||||
lines.append(f'{indent}<parameter xmlns:dcsat="http://v8.1c.ru/8.1/data-composition-system/area-template" xsi:type="dcsat:DetailsAreaTemplateParameter">')
|
||||
lines.append(f'{indent}\t<dcsat:name>{esc_xml(str(tp["name"]))}</dcsat:name>')
|
||||
lines.append(f'{indent}\t<dcsat:fieldExpression>')
|
||||
lines.append(f'{indent}\t\t<dcsat:field>{esc_xml(dd_field)}</dcsat:field>')
|
||||
lines.append(f'{indent}\t\t<dcsat:expression>{esc_xml(dd_expr)}</dcsat:expression>')
|
||||
lines.append(f'{indent}\t</dcsat:fieldExpression>')
|
||||
lines.append(f'{indent}\t<dcsat:mainAction>{esc_xml(dd_act)}</dcsat:mainAction>')
|
||||
lines.append(f'{indent}</parameter>')
|
||||
return
|
||||
# \u0424\u043e\u0440\u043c\u0430 A \u0438\u043b\u0438 B
|
||||
lines.append(f'{indent}<parameter xmlns:dcsat="http://v8.1c.ru/8.1/data-composition-system/area-template" xsi:type="dcsat:ExpressionAreaTemplateParameter">')
|
||||
lines.append(f'{indent}\t<dcsat:name>{esc_xml(str(tp["name"]))}</dcsat:name>')
|
||||
lines.append(f'{indent}\t<dcsat:expression>{esc_xml(str(tp.get("expression", "")))}</dcsat:expression>')
|
||||
lines.append(f'{indent}</parameter>')
|
||||
if dd and isinstance(dd, str):
|
||||
# \u0424\u043e\u0440\u043c\u0430 B: shortcut \u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_<X> + \u0418\u043c\u044f\u0420\u0435\u0441\u0443\u0440\u0441\u0430 + DrillDown
|
||||
dd_val = dd
|
||||
lines.append(f'{indent}<parameter xmlns:dcsat="http://v8.1c.ru/8.1/data-composition-system/area-template" xsi:type="dcsat:DetailsAreaTemplateParameter">')
|
||||
lines.append(f'{indent}\t<dcsat:name>\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_{esc_xml(dd_val)}</dcsat:name>')
|
||||
lines.append(f'{indent}\t<dcsat:fieldExpression>')
|
||||
lines.append(f'{indent}\t\t<dcsat:field>\u0418\u043c\u044f\u0420\u0435\u0441\u0443\u0440\u0441\u0430</dcsat:field>')
|
||||
lines.append(f'{indent}\t\t<dcsat:expression>"{esc_xml(dd_val)}"</dcsat:expression>')
|
||||
lines.append(f'{indent}\t</dcsat:fieldExpression>')
|
||||
lines.append(f'{indent}\t<dcsat:mainAction>DrillDown</dcsat:mainAction>')
|
||||
lines.append(f'{indent}</parameter>')
|
||||
|
||||
|
||||
# === Templates ===
|
||||
|
||||
def emit_templates(lines, defn):
|
||||
@@ -1581,24 +1615,23 @@ def emit_templates(lines, defn):
|
||||
lines.append(f'\t\t{t["template"]}')
|
||||
if t.get('parameters'):
|
||||
for tp in t['parameters']:
|
||||
lines.append('\t\t<parameter xmlns:dcsat="http://v8.1c.ru/8.1/data-composition-system/area-template" xsi:type="dcsat:ExpressionAreaTemplateParameter">')
|
||||
lines.append(f'\t\t\t<dcsat:name>{esc_xml(str(tp["name"]))}</dcsat:name>')
|
||||
lines.append(f'\t\t\t<dcsat:expression>{esc_xml(str(tp["expression"]))}</dcsat:expression>')
|
||||
lines.append('\t\t</parameter>')
|
||||
# Drilldown parameter
|
||||
if tp.get('drilldown'):
|
||||
dd_val = str(tp['drilldown'])
|
||||
lines.append('\t\t<parameter xmlns:dcsat="http://v8.1c.ru/8.1/data-composition-system/area-template" xsi:type="dcsat:DetailsAreaTemplateParameter">')
|
||||
lines.append(f'\t\t\t<dcsat:name>\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_{esc_xml(dd_val)}</dcsat:name>')
|
||||
lines.append('\t\t\t<dcsat:fieldExpression>')
|
||||
lines.append('\t\t\t\t<dcsat:field>\u0418\u043c\u044f\u0420\u0435\u0441\u0443\u0440\u0441\u0430</dcsat:field>')
|
||||
lines.append(f'\t\t\t\t<dcsat:expression>"{esc_xml(dd_val)}"</dcsat:expression>')
|
||||
lines.append('\t\t\t</dcsat:fieldExpression>')
|
||||
lines.append('\t\t\t<dcsat:mainAction>DrillDown</dcsat:mainAction>')
|
||||
lines.append('\t\t</parameter>')
|
||||
_emit_area_template_parameter(lines, tp, '\t\t')
|
||||
lines.append('\t</template>')
|
||||
|
||||
|
||||
# === FieldTemplates ===
|
||||
# Привязка <fieldTemplate><field/><template/></fieldTemplate> поля к именованному area-template.
|
||||
# DSL: "fieldTemplates": [{ "field": "X", "template": "Макет1" }, ...]
|
||||
def emit_field_templates(lines, defn):
|
||||
if not defn.get('fieldTemplates'):
|
||||
return
|
||||
for ft in defn['fieldTemplates']:
|
||||
lines.append('\t<fieldTemplate>')
|
||||
lines.append(f'\t\t<field>{esc_xml(str(ft["field"]))}</field>')
|
||||
lines.append(f'\t\t<template>{esc_xml(str(ft["template"]))}</template>')
|
||||
lines.append('\t</fieldTemplate>')
|
||||
|
||||
|
||||
# === GroupTemplates ===
|
||||
|
||||
def emit_group_templates(lines, defn):
|
||||
@@ -2680,6 +2713,7 @@ def main():
|
||||
emit_total_fields(lines, defn)
|
||||
emit_parameters(lines, defn)
|
||||
emit_templates(lines, defn)
|
||||
emit_field_templates(lines, defn)
|
||||
emit_group_templates(lines, defn)
|
||||
emit_settings_variants(lines, defn)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# skd-decompile v0.74 — Decompile 1C DCS Template.xml to JSON DSL (draft)
|
||||
# skd-decompile v0.75 — Decompile 1C DCS Template.xml to JSON DSL (draft)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -1132,7 +1132,9 @@ function Save-UserStyles {
|
||||
# Extract per-cell width/minHeight/merge from appearance.
|
||||
function Get-CellPerCellAttrs {
|
||||
param($appNode)
|
||||
$attrs = @{ width = $null; height = $null; mergeV = $false; mergeH = $false; drilldown = $null }
|
||||
# drilldown — суффикс X из имени Расшифровка_X (только shortcut form B).
|
||||
# drilldownTarget — полное имя target-параметра как есть (любая форма).
|
||||
$attrs = @{ width = $null; height = $null; mergeV = $false; mergeH = $false; drilldown = $null; drilldownTarget = $null }
|
||||
if (-not $appNode) { return $attrs }
|
||||
foreach ($it in $appNode.SelectNodes("dcscor:item", $ns)) {
|
||||
$pName = Get-Text $it "dcscor:parameter"
|
||||
@@ -1144,9 +1146,10 @@ function Get-CellPerCellAttrs {
|
||||
'ОбъединятьПоВертикали' { if ($val -and $val.InnerText -eq 'true') { $attrs.mergeV = $true } }
|
||||
'ОбъединятьПоГоризонтали' { if ($val -and $val.InnerText -eq 'true') { $attrs.mergeH = $true } }
|
||||
'Расшифровка' {
|
||||
# value xsi:type=dcscor:Parameter pointing to Расшифровка_X
|
||||
# value xsi:type=dcscor:Parameter pointing to <X> или Расшифровка_<X>
|
||||
if ($val) {
|
||||
$paramRef = $val.InnerText
|
||||
$attrs.drilldownTarget = $paramRef
|
||||
if ($paramRef -match '^Расшифровка_(.+)$') { $attrs.drilldown = $matches[1] }
|
||||
}
|
||||
}
|
||||
@@ -1219,9 +1222,10 @@ function Build-Template {
|
||||
$rows = @()
|
||||
$widths = $null
|
||||
$minHeight = $null
|
||||
$cellStyleMap = @{} # "r,c" → имя стиля для конкретной ячейки (null для merge/no-style)
|
||||
$cellStyleMap = @{} # "r,c" → имя стиля для конкретной ячейки (null для merge/no-style)
|
||||
$cellDrilldownMap = @{} # "r,c" → полное имя drilldown-target (для cell wrap в object-form)
|
||||
$hasAnyStyledCell = $false
|
||||
$drilldownByParam = @{} # param name → field name (X from Расшифровка_X)
|
||||
$drilldownByParam = @{} # param name → field name (X from Расшифровка_X) — для form B fold
|
||||
|
||||
$rowIdx = 0
|
||||
foreach ($rowNode in $rowNodes) {
|
||||
@@ -1248,10 +1252,16 @@ function Build-Template {
|
||||
}
|
||||
}
|
||||
|
||||
# Drilldown attachment
|
||||
# Drilldown attachment — для shortcut form B (Расшифровка_X) кладём в drilldownByParam.
|
||||
# Полное имя target сохраняем в cellDrilldownMap для последующего разрешения:
|
||||
# если target = "Расшифровка_X" и X совпадает с именем параметра ячейки {X} —
|
||||
# это shortcut и cell остаётся строкой; иначе cell wrap в {value, drilldown}.
|
||||
if ($content -match '^\{(.+)\}$' -and $perCell.drilldown) {
|
||||
$drilldownByParam[$matches[1]] = $perCell.drilldown
|
||||
}
|
||||
if ($perCell.drilldownTarget) {
|
||||
$cellDrilldownMap["$rowIdx,$colIdx"] = $perCell.drilldownTarget
|
||||
}
|
||||
|
||||
# First row collects widths from any non-merge cell
|
||||
if ($rowIdx -eq 0 -and $perCell.width) { $rowWidths += $perCell.width }
|
||||
@@ -1305,16 +1315,34 @@ function Build-Template {
|
||||
# Template parameters (and drilldown folding)
|
||||
$paramNodes = $templateNode.SelectNodes("r:parameter", $ns)
|
||||
$exprParams = [ordered]@{}
|
||||
$detailParams = @{}
|
||||
$detailsByName = [ordered]@{} # name → @{ field, expression, action }
|
||||
foreach ($pn in $paramNodes) {
|
||||
$pType = Get-LocalXsiType $pn
|
||||
$pName = Get-Text $pn "dcsat:name"
|
||||
if ($pType -eq 'ExpressionAreaTemplateParameter') {
|
||||
$exprParams[$pName] = Get-Text $pn "dcsat:expression"
|
||||
} elseif ($pType -eq 'DetailsAreaTemplateParameter') {
|
||||
# Name format: Расшифровка_<X>
|
||||
if ($pName -match '^Расшифровка_(.+)$') {
|
||||
$detailParams[$matches[1]] = $true
|
||||
$feNode = $pn.SelectSingleNode("dcsat:fieldExpression", $ns)
|
||||
$detailsByName[$pName] = @{
|
||||
field = if ($feNode) { Get-Text $feNode "dcsat:field" } else { '' }
|
||||
expression = if ($feNode) { Get-Text $feNode "dcsat:expression" } else { '' }
|
||||
action = Get-Text $pn "dcsat:mainAction"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Сворачиваем shortcut form B: каждый exprParam X с drilldownByParam[X]=Y проверяем —
|
||||
# если detailsByName["Расшифровка_Y"] существует и имеет canonical shape
|
||||
# (field=ИмяРесурса, expression="Y", action=DrillDown) → fold X.drilldown="Y" и mark detail folded.
|
||||
$foldedDetailNames = @{}
|
||||
foreach ($pname in @($drilldownByParam.Keys)) {
|
||||
$yVal = $drilldownByParam[$pname]
|
||||
$detailName = "Расшифровка_$yVal"
|
||||
if ($detailsByName.Contains($detailName)) {
|
||||
$d = $detailsByName[$detailName]
|
||||
$expectedExpr = "`"$yVal`""
|
||||
if ($d.field -eq 'ИмяРесурса' -and $d.expression -eq $expectedExpr -and $d.action -eq 'DrillDown') {
|
||||
$foldedDetailNames[$detailName] = $true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1327,6 +1355,60 @@ function Build-Template {
|
||||
}
|
||||
$templateParams += $entry
|
||||
}
|
||||
# Form C: details-параметры, не свёрнутые как shortcut → отдельная запись.
|
||||
foreach ($dname in $detailsByName.Keys) {
|
||||
if ($foldedDetailNames.ContainsKey($dname)) { continue }
|
||||
$d = $detailsByName[$dname]
|
||||
$entry = [ordered]@{ name = $dname }
|
||||
$ddObj = [ordered]@{ field = $d.field; expression = $d.expression }
|
||||
if ($d.action -and $d.action -ne 'DrillDown') { $ddObj['action'] = $d.action }
|
||||
$entry['drilldown'] = $ddObj
|
||||
$templateParams += $entry
|
||||
}
|
||||
|
||||
# Cell wrapping: для ячеек, у которых drilldownTarget НЕ соответствует shortcut form B
|
||||
# (то есть target ≠ "Расшифровка_X" с X = имя параметра ячейки), оборачиваем в {value, drilldown}.
|
||||
# Уже обёрнутые style-ом ячейки получают drilldown как дополнительное поле.
|
||||
if ($cellDrilldownMap.Count -gt 0) {
|
||||
for ($r = 0; $r -lt $rows.Count; $r++) {
|
||||
$newRow = @()
|
||||
for ($c = 0; $c -lt $rows[$r].Count; $c++) {
|
||||
$cellVal = $rows[$r][$c]
|
||||
$key = "$r,$c"
|
||||
$target = $cellDrilldownMap[$key]
|
||||
# Распаковка inner value если cell уже обёрнута style-ом
|
||||
$innerVal = $cellVal
|
||||
$isWrapped = $false
|
||||
if ($cellVal -is [System.Collections.IDictionary] -or $cellVal -is [hashtable]) {
|
||||
if ($cellVal.Contains('value')) {
|
||||
$innerVal = $cellVal['value']
|
||||
$isWrapped = $true
|
||||
}
|
||||
}
|
||||
$needsWrap = $false
|
||||
if ($target -and ($innerVal -is [string]) -and ($innerVal -match '^\{(.+)\}$')) {
|
||||
$cellParam = $matches[1]
|
||||
# Shortcut form B: cell param имеет drilldown "Y", target == "Расшифровка_Y".
|
||||
$expectedShortcut = $null
|
||||
if ($drilldownByParam.ContainsKey($cellParam)) {
|
||||
$expectedShortcut = "Расшифровка_$($drilldownByParam[$cellParam])"
|
||||
}
|
||||
if ($target -ne $expectedShortcut) { $needsWrap = $true }
|
||||
}
|
||||
if ($needsWrap) {
|
||||
if ($isWrapped) {
|
||||
$cellVal['drilldown'] = $target
|
||||
$newRow += $cellVal
|
||||
} else {
|
||||
$newRow += [ordered]@{ value = $innerVal; drilldown = $target }
|
||||
}
|
||||
} else {
|
||||
$newRow += $cellVal
|
||||
}
|
||||
}
|
||||
$rows[$r] = $newRow
|
||||
}
|
||||
}
|
||||
|
||||
# Decide output form
|
||||
if ($templateDefault) {
|
||||
@@ -2488,6 +2570,17 @@ foreach ($tn in $tNodes) {
|
||||
}
|
||||
if ($templates.Count -gt 0) { $out['templates'] = $templates }
|
||||
|
||||
# --- 5e2. fieldTemplates ---
|
||||
# Привязка <fieldTemplate><field/><template/></fieldTemplate> поля к именованному area-template.
|
||||
|
||||
$fieldTemplates = @()
|
||||
foreach ($ftn in $root.SelectNodes("r:fieldTemplate", $ns)) {
|
||||
$ftField = Get-Text $ftn "r:field"
|
||||
$ftTempl = Get-Text $ftn "r:template"
|
||||
$fieldTemplates += [ordered]@{ field = $ftField; template = $ftTempl }
|
||||
}
|
||||
if ($fieldTemplates.Count -gt 0) { $out['fieldTemplates'] = $fieldTemplates }
|
||||
|
||||
# --- 5f. groupTemplates ---
|
||||
|
||||
$groupTemplates = @()
|
||||
|
||||
Reference in New Issue
Block a user