diff --git a/.claude/skills/epf-add-template/SKILL.md b/.claude/skills/epf-add-template/SKILL.md index 55100184..d005dfc4 100644 --- a/.claude/skills/epf-add-template/SKILL.md +++ b/.claude/skills/epf-add-template/SKILL.md @@ -25,7 +25,7 @@ allowed-tools: |---------------|:------------:|-----------------|--------------------------------------------------| | ProcessorName | да | — | Имя обработки | | TemplateName | да | — | Имя макета | -| TemplateType | да | — | Тип: HTML, Text, SpreadsheetDocument, BinaryData | +| TemplateType | да | — | Тип: HTML, Text, SpreadsheetDocument, BinaryData, DataCompositionSchema | | Synonym | нет | = TemplateName | Синоним макета | | SrcDir | нет | `src` | Каталог исходников | @@ -45,6 +45,7 @@ pwsh -NoProfile -File .claude/skills/epf-add-template/scripts/add-template.ps1 - | Text, текстовый документ, текст | TextDocument | `.txt` | Пустой файл | | SpreadsheetDocument, табличный документ, MXL | SpreadsheetDocument | `.xml` | Минимальный spreadsheet | | BinaryData, двоичные данные | BinaryData | `.bin` | Пустой файл | +| DataCompositionSchema, СКД, схема компоновки | DataCompositionSchema | `.xml` | Минимальная DCS-схема | ## Конвенция именования diff --git a/.claude/skills/epf-add-template/scripts/add-template.ps1 b/.claude/skills/epf-add-template/scripts/add-template.ps1 index a63ac008..456d3444 100644 --- a/.claude/skills/epf-add-template/scripts/add-template.ps1 +++ b/.claude/skills/epf-add-template/scripts/add-template.ps1 @@ -6,7 +6,7 @@ [string]$TemplateName, [Parameter(Mandatory)] - [ValidateSet("HTML", "Text", "SpreadsheetDocument", "BinaryData")] + [ValidateSet("HTML", "Text", "SpreadsheetDocument", "BinaryData", "DataCompositionSchema")] [string]$TemplateType, [string]$Synonym = $TemplateName, @@ -23,6 +23,7 @@ $typeMap = @{ "Text" = @{ TemplateType = "TextDocument"; Ext = ".txt" } "SpreadsheetDocument" = @{ TemplateType = "SpreadsheetDocument"; Ext = ".xml" } "BinaryData" = @{ TemplateType = "BinaryData"; Ext = ".bin" } + "DataCompositionSchema" = @{ TemplateType = "DataCompositionSchema"; Ext = ".xml" } } $tmpl = $typeMap[$TemplateType] @@ -111,6 +112,25 @@ switch ($TemplateType) { "BinaryData" { [System.IO.File]::WriteAllBytes($templateFilePath, @()) } + "DataCompositionSchema" { + $content = @" + + + + ИсточникДанных1 + Local + + +"@ + [System.IO.File]::WriteAllText($templateFilePath, $content, $encBom) + } } # --- 3. Модификация корневого XML --- diff --git a/.claude/skills/skd-compile/SKILL.md b/.claude/skills/skd-compile/SKILL.md index 93fc6350..d4d7f191 100644 --- a/.claude/skills/skd-compile/SKILL.md +++ b/.claude/skills/skd-compile/SKILL.md @@ -94,7 +94,20 @@ powershell.exe -NoProfile -File .claude\skills\skd-compile\scripts\skd-compile.p ] ``` -Формат: `"Поле оператор значение @флаги"`. Значение `_` = пустое (placeholder). Флаги: `@off` (use=false), `@user` (userSettingID=auto), `@quickAccess`. +Формат: `"Поле оператор значение @флаги"`. Значение `_` = пустое (placeholder). Флаги: `@off` (use=false), `@user` (userSettingID=auto), `@quickAccess`, `@normal`, `@inaccessible`. + +В объектной форме доступны: `viewMode`, `userSettingID`, `userSettingPresentation`. + +Группы фильтров (Or/And/Not): +```json +{ "group": "Or", "items": [ + { "group": "And", "items": [ + { "field": "Статус", "op": "=", "value": "Активен" }, + { "field": "Сумма", "op": ">", "value": 1000 } + ]}, + { "field": "Количество", "op": "filled" } +]} +``` ### Параметры данных — shorthand @@ -127,6 +140,15 @@ powershell.exe -NoProfile -File .claude\skills\skd-compile\scripts\skd-compile.p "selection": ["Номенклатура", "Количество", "Auto"], "filter": ["Организация = _ @off @user"], "order": ["Количество desc", "Auto"], + "conditionalAppearance": [ + { + "filter": ["Просрочено = true"], + "appearance": { "ЦветТекста": "style:ПросроченныеДанныеЦвет" }, + "presentation": "Выделять просроченные", + "viewMode": "Normal", + "userSettingID": "auto" + } + ], "outputParameters": { "Заголовок": "Мой отчёт" }, "dataParameters": ["Период = LastMonth @user"], "structure": "Организация > details" @@ -134,6 +156,31 @@ powershell.exe -NoProfile -File .claude\skills\skd-compile\scripts\skd-compile.p }] ``` +### Условное оформление (conditionalAppearance) + +```json +"conditionalAppearance": [ + { + "selection": ["Поле1"], + "filter": ["Поле1 notFilled"], + "appearance": { "Текст": "Не указано", "ЦветТекста": "style:XXX" }, + "presentation": "Описание", + "viewMode": "Normal", + "userSettingID": "auto" + } +] +``` + +Типы значений appearance: `style:XXX`/`web:XXX`/`win:XXX` → Color, `true`/`false` → Boolean, параметр `Текст` → LocalStringType, прочее → String. + +### Итоги с привязкой к группировкам + +```json +"totalFields": [ + { "dataPath": "Кол", "expression": "Сумма(Кол)", "group": ["Группа1", "Группа1 Иерархия", "ОбщийИтог"] } +] +``` + ## Примеры ### Минимальный diff --git a/.claude/skills/skd-compile/scripts/skd-compile.ps1 b/.claude/skills/skd-compile/scripts/skd-compile.ps1 index 8ba7a00d..934986d2 100644 --- a/.claude/skills/skd-compile/scripts/skd-compile.ps1 +++ b/.claude/skills/skd-compile/scripts/skd-compile.ps1 @@ -381,6 +381,14 @@ function Parse-FilterShorthand { $result.viewMode = "QuickAccess" $s = $s -replace '\s*@quickAccess', '' } + if ($s -match '@normal') { + $result.viewMode = "Normal" + $s = $s -replace '\s*@normal', '' + } + if ($s -match '@inaccessible') { + $result.viewMode = "Inaccessible" + $s = $s -replace '\s*@inaccessible', '' + } $s = $s.Trim() @@ -751,14 +759,16 @@ function Emit-TotalFields { dataPath = "$($tf.dataPath)" expression = "$($tf.expression)" } - if ($tf.group) { $parsed.group = "$($tf.group)" } + if ($tf.group) { $parsed.groups = @($tf.group) } } X "`t" X "`t`t$(Esc-Xml $parsed.dataPath)" X "`t`t$(Esc-Xml $parsed.expression)" - if ($parsed.group) { - X "`t`t$(Esc-Xml $parsed.group)" + if ($parsed.groups) { + foreach ($g in $parsed.groups) { + X "`t`t$(Esc-Xml "$g")" + } } X "`t" } @@ -1021,6 +1031,15 @@ function Emit-FilterItem { X "$indent`t$(Esc-Xml $uid)" } + if ($item.userSettingPresentation) { + X "$indent`t" + X "$indent`t`t" + X "$indent`t`t`tru" + X "$indent`t`t`t$(Esc-Xml "$($item.userSettingPresentation)")" + X "$indent`t`t" + X "$indent`t" + } + X "$indent" } @@ -1088,6 +1107,94 @@ function Emit-Order { X "$indent" } +function Emit-AppearanceValue { + param([string]$key, $val, [string]$indent) + + X "$indent" + if ($val -is [PSCustomObject] -and $val.use -ne $null -and $val.use -eq $false) { + X "$indent`tfalse" + X "$indent`t$(Esc-Xml $key)" + $actualVal = "$($val.value)" + } else { + X "$indent`t$(Esc-Xml $key)" + $actualVal = "$val" + } + + # Auto-detect value type + if ($actualVal -match '^(style|web|win):') { + X "$indent`t$(Esc-Xml $actualVal)" + } elseif ($actualVal -eq "true" -or $actualVal -eq "false") { + X "$indent`t$actualVal" + } elseif ($key -eq "Текст" -or $key -eq "Заголовок") { + X "$indent`t" + X "$indent`t`t" + X "$indent`t`t`tru" + X "$indent`t`t`t$(Esc-Xml $actualVal)" + X "$indent`t`t" + X "$indent`t" + } else { + X "$indent`t$(Esc-Xml $actualVal)" + } + X "$indent" +} + +function Emit-ConditionalAppearance { + param($items, [string]$indent) + + if (-not $items -or $items.Count -eq 0) { return } + + X "$indent" + foreach ($ca in $items) { + X "$indent`t" + + # Selection (which fields to apply to; empty = all) + if ($ca.selection -and $ca.selection.Count -gt 0) { + X "$indent`t`t" + foreach ($sel in $ca.selection) { + X "$indent`t`t`t" + X "$indent`t`t`t`t$(Esc-Xml "$sel")" + X "$indent`t`t`t" + } + X "$indent`t`t" + } else { + X "$indent`t`t" + } + + # Filter (reuse existing Emit-Filter logic) + if ($ca.filter) { + Emit-Filter -items $ca.filter -indent "$indent`t`t" + } + + # Appearance (parameter-value pairs) + if ($ca.appearance) { + X "$indent`t`t" + foreach ($prop in $ca.appearance.PSObject.Properties) { + Emit-AppearanceValue -key $prop.Name -val $prop.Value -indent "$indent`t`t`t" + } + X "$indent`t`t" + } + + # Presentation + if ($ca.presentation) { + X "$indent`t`t$(Esc-Xml "$($ca.presentation)")" + } + + # ViewMode + if ($ca.viewMode) { + X "$indent`t`t$(Esc-Xml "$($ca.viewMode)")" + } + + # UserSettingID + if ($ca.userSettingID) { + $uid = if ("$($ca.userSettingID)" -eq "auto") { New-Guid-String } else { "$($ca.userSettingID)" } + X "$indent`t`t$(Esc-Xml $uid)" + } + + X "$indent`t" + } + X "$indent" +} + function Emit-OutputParameters { param($params, [string]$indent) @@ -1183,6 +1290,15 @@ function Emit-DataParameters { X "$indent`t`t$(Esc-Xml $uid)" } + if ($dp.userSettingPresentation) { + X "$indent`t`t" + X "$indent`t`t`t" + X "$indent`t`t`t`tru" + X "$indent`t`t`t`t$(Esc-Xml "$($dp.userSettingPresentation)")" + X "$indent`t`t`t" + X "$indent`t`t" + } + X "$indent`t" } X "$indent" @@ -1434,6 +1550,11 @@ function Emit-SettingsVariants { Emit-Order -items $s.order -indent "`t`t`t" -skipAuto } + # ConditionalAppearance + if ($s.conditionalAppearance) { + Emit-ConditionalAppearance -items $s.conditionalAppearance -indent "`t`t`t" + } + # OutputParameters if ($s.outputParameters) { Emit-OutputParameters -params $s.outputParameters -indent "`t`t`t"