diff --git a/.claude/skills/skd-compile/SKILL.md b/.claude/skills/skd-compile/SKILL.md index 9c5791a8..96be9b30 100644 --- a/.claude/skills/skd-compile/SKILL.md +++ b/.claude/skills/skd-compile/SKILL.md @@ -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 ячейки получит `Расшифровка → ` (без префикса `Расшифровка_`). Используется когда несколько ячеек должны указывать на один и тот же параметр расшифровки, объявленный через форму C. Если в ячейке-строке `{X}` есть param X со shortcut form B — appearance подставляется автоматически, override не нужен. + +### Привязка макета к полю — `fieldTemplates` + +```json +"fieldTemplates": [ + { "field": "МаршрутныйЛист", "template": "Макет1" } +] +``` + +Эквивалент XML-секции `X` — при выводе значения поля `X` используется именованный area-template `Y`. + ### Привязки макетов к группировкам ```json diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index 2d3aab0a..0f35d537 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.ps1 +++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1 @@ -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" X "`t`t`t`t`t`t$(Esc-Xml $paramName)" X "`t`t`t`t`t" - # 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" $cellExtraItems += "`t`t`t`t`t`t`tРасшифровка" - $cellExtraItems += "`t`t`t`t`t`t`tРасшифровка_$ddVal" + $cellExtraItems += "`t`t`t`t`t`t`t$(Esc-Xml $ddTarget)" $cellExtraItems += "`t`t`t`t`t`t" } } else { @@ -1879,27 +1894,62 @@ function Emit-AreaTemplateDSL { # Parameters (reuse existing logic) if ($t.parameters) { foreach ($tp in $t.parameters) { - X "`t`t" - X "`t`t`t$(Esc-Xml "$($tp.name)")" - X "`t`t`t$(Esc-Xml "$($tp.expression)")" - X "`t`t" - # Drilldown parameter - if ($tp.drilldown) { - $ddVal = "$($tp.drilldown)" - X "`t`t" - X "`t`t`tРасшифровка_$(Esc-Xml $ddVal)" - X "`t`t`t" - X "`t`t`t`tИмяРесурса" - X "`t`t`t`t`"$(Esc-Xml $ddVal)`"" - X "`t`t`t" - X "`t`t`tDrillDown" - X "`t`t" - } + Emit-AreaTemplateParameter -tp $tp -indent "`t`t" } } X "`t" } +# Эмиссия одного параметра шаблона. Различает три формы: +# 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" + X "$indent`t$(Esc-Xml "$($tp.name)")" + X "$indent`t" + X "$indent`t`t$(Esc-Xml $ddField)" + X "$indent`t`t$(Esc-Xml $ddExpr)" + X "$indent`t" + X "$indent`t$(Esc-Xml $ddAct)" + X "$indent" + return + } + # Форма A или B + X "$indent" + X "$indent`t$(Esc-Xml "$($tp.name)")" + X "$indent`t$(Esc-Xml "$($tp.expression)")" + X "$indent" + if ($dd -and ($dd -is [string])) { + # Форма B: shortcut Расшифровка_ + ИмяРесурса + DrillDown + $ddVal = "$dd" + X "$indent" + X "$indent`tРасшифровка_$(Esc-Xml $ddVal)" + X "$indent`t" + X "$indent`t`tИмяРесурса" + X "$indent`t`t`"$(Esc-Xml $ddVal)`"" + X "$indent`t" + X "$indent`tDrillDown" + X "$indent" + } +} + # === 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" - X "`t`t`t$(Esc-Xml "$($tp.name)")" - X "`t`t`t$(Esc-Xml "$($tp.expression)")" - X "`t`t" - # Drilldown parameter - if ($tp.drilldown) { - $ddVal = "$($tp.drilldown)" - X "`t`t" - X "`t`t`tРасшифровка_$(Esc-Xml $ddVal)" - X "`t`t`t" - X "`t`t`t`tИмяРесурса" - X "`t`t`t`t`"$(Esc-Xml $ddVal)`"" - X "`t`t`t" - X "`t`t`tDrillDown" - X "`t`t" - } + Emit-AreaTemplateParameter -tp $tp -indent "`t`t" } } X "`t" @@ -1939,6 +1974,19 @@ function Emit-Templates { } } +# === FieldTemplates === +# Привязка ') +# \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}') + lines.append(f'{indent}\t{esc_xml(str(tp["name"]))}') + lines.append(f'{indent}\t') + lines.append(f'{indent}\t\t{esc_xml(dd_field)}') + lines.append(f'{indent}\t\t{esc_xml(dd_expr)}') + lines.append(f'{indent}\t') + lines.append(f'{indent}\t{esc_xml(dd_act)}') + lines.append(f'{indent}') + return + # \u0424\u043e\u0440\u043c\u0430 A \u0438\u043b\u0438 B + lines.append(f'{indent}') + lines.append(f'{indent}\t{esc_xml(str(tp["name"]))}') + lines.append(f'{indent}\t{esc_xml(str(tp.get("expression", "")))}') + lines.append(f'{indent}') + if dd and isinstance(dd, str): + # \u0424\u043e\u0440\u043c\u0430 B: shortcut \u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_ + \u0418\u043c\u044f\u0420\u0435\u0441\u0443\u0440\u0441\u0430 + DrillDown + dd_val = dd + lines.append(f'{indent}') + lines.append(f'{indent}\t\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_{esc_xml(dd_val)}') + lines.append(f'{indent}\t') + lines.append(f'{indent}\t\t\u0418\u043c\u044f\u0420\u0435\u0441\u0443\u0440\u0441\u0430') + lines.append(f'{indent}\t\t"{esc_xml(dd_val)}"') + lines.append(f'{indent}\t') + lines.append(f'{indent}\tDrillDown') + lines.append(f'{indent}') + + # === 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') - lines.append(f'\t\t\t{esc_xml(str(tp["name"]))}') - lines.append(f'\t\t\t{esc_xml(str(tp["expression"]))}') - lines.append('\t\t') - # Drilldown parameter - if tp.get('drilldown'): - dd_val = str(tp['drilldown']) - lines.append('\t\t') - lines.append(f'\t\t\t\u0420\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0430_{esc_xml(dd_val)}') - lines.append('\t\t\t') - lines.append('\t\t\t\t\u0418\u043c\u044f\u0420\u0435\u0441\u0443\u0440\u0441\u0430') - lines.append(f'\t\t\t\t"{esc_xml(dd_val)}"') - lines.append('\t\t\t') - lines.append('\t\t\tDrillDown') - lines.append('\t\t') + _emit_area_template_parameter(lines, tp, '\t\t') lines.append('\t') +# === FieldTemplates === +# Привязка