Add DCS template type, conditional appearance, filter/total enhancements

- epf-add-template: support DataCompositionSchema template type with
  minimal DCS scaffold (dataSource + Local)
- skd-compile: add conditionalAppearance with auto-detect value types
  (Color, LocalStringType, Boolean), selection, filter, presentation
- skd-compile: add @normal, @inaccessible viewMode shorthand flags
- skd-compile: add userSettingPresentation for filters and dataParameters
- skd-compile: support multiple group elements in totalField (array form)
- skd-compile SKILL.md: document all new features with examples

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-02-11 16:12:47 +03:00
parent 1382194201
commit 91d254b718
4 changed files with 195 additions and 6 deletions
+2 -1
View File
@@ -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-схема |
## Конвенция именования
@@ -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 = @"
<?xml version="1.0" encoding="UTF-8"?>
<DataCompositionSchema xmlns="http://v8.1c.ru/8.1/data-composition-system/schema"
xmlns:dcscom="http://v8.1c.ru/8.1/data-composition-system/common"
xmlns:dcscor="http://v8.1c.ru/8.1/data-composition-system/core"
xmlns:dcsset="http://v8.1c.ru/8.1/data-composition-system/settings"
xmlns:v8="http://v8.1c.ru/8.1/data/core"
xmlns:v8ui="http://v8.1c.ru/8.1/data/ui"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dataSource>
<name>ИсточникДанных1</name>
<dataSourceType>Local</dataSourceType>
</dataSource>
</DataCompositionSchema>
"@
[System.IO.File]::WriteAllText($templateFilePath, $content, $encBom)
}
}
# --- 3. Модификация корневого XML ---
+48 -1
View File
@@ -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 Иерархия", "ОбщийИтог"] }
]
```
## Примеры
### Минимальный
@@ -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<totalField>"
X "`t`t<dataPath>$(Esc-Xml $parsed.dataPath)</dataPath>"
X "`t`t<expression>$(Esc-Xml $parsed.expression)</expression>"
if ($parsed.group) {
X "`t`t<group>$(Esc-Xml $parsed.group)</group>"
if ($parsed.groups) {
foreach ($g in $parsed.groups) {
X "`t`t<group>$(Esc-Xml "$g")</group>"
}
}
X "`t</totalField>"
}
@@ -1021,6 +1031,15 @@ function Emit-FilterItem {
X "$indent`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
}
if ($item.userSettingPresentation) {
X "$indent`t<dcsset:userSettingPresentation xsi:type=`"v8:LocalStringType`">"
X "$indent`t`t<v8:item>"
X "$indent`t`t`t<v8:lang>ru</v8:lang>"
X "$indent`t`t`t<v8:content>$(Esc-Xml "$($item.userSettingPresentation)")</v8:content>"
X "$indent`t`t</v8:item>"
X "$indent`t</dcsset:userSettingPresentation>"
}
X "$indent</dcsset:item>"
}
@@ -1088,6 +1107,94 @@ function Emit-Order {
X "$indent</dcsset:order>"
}
function Emit-AppearanceValue {
param([string]$key, $val, [string]$indent)
X "$indent<dcscor:item xsi:type=`"dcsset:SettingsParameterValue`">"
if ($val -is [PSCustomObject] -and $val.use -ne $null -and $val.use -eq $false) {
X "$indent`t<dcscor:use>false</dcscor:use>"
X "$indent`t<dcscor:parameter>$(Esc-Xml $key)</dcscor:parameter>"
$actualVal = "$($val.value)"
} else {
X "$indent`t<dcscor:parameter>$(Esc-Xml $key)</dcscor:parameter>"
$actualVal = "$val"
}
# Auto-detect value type
if ($actualVal -match '^(style|web|win):') {
X "$indent`t<dcscor:value xsi:type=`"v8ui:Color`">$(Esc-Xml $actualVal)</dcscor:value>"
} elseif ($actualVal -eq "true" -or $actualVal -eq "false") {
X "$indent`t<dcscor:value xsi:type=`"xs:boolean`">$actualVal</dcscor:value>"
} elseif ($key -eq "Текст" -or $key -eq "Заголовок") {
X "$indent`t<dcscor:value xsi:type=`"v8:LocalStringType`">"
X "$indent`t`t<v8:item>"
X "$indent`t`t`t<v8:lang>ru</v8:lang>"
X "$indent`t`t`t<v8:content>$(Esc-Xml $actualVal)</v8:content>"
X "$indent`t`t</v8:item>"
X "$indent`t</dcscor:value>"
} else {
X "$indent`t<dcscor:value xsi:type=`"xs:string`">$(Esc-Xml $actualVal)</dcscor:value>"
}
X "$indent</dcscor:item>"
}
function Emit-ConditionalAppearance {
param($items, [string]$indent)
if (-not $items -or $items.Count -eq 0) { return }
X "$indent<dcsset:conditionalAppearance>"
foreach ($ca in $items) {
X "$indent`t<dcsset:item>"
# Selection (which fields to apply to; empty = all)
if ($ca.selection -and $ca.selection.Count -gt 0) {
X "$indent`t`t<dcsset:selection>"
foreach ($sel in $ca.selection) {
X "$indent`t`t`t<dcsset:item>"
X "$indent`t`t`t`t<dcsset:field>$(Esc-Xml "$sel")</dcsset:field>"
X "$indent`t`t`t</dcsset:item>"
}
X "$indent`t`t</dcsset:selection>"
} else {
X "$indent`t`t<dcsset:selection/>"
}
# 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<dcsset:appearance>"
foreach ($prop in $ca.appearance.PSObject.Properties) {
Emit-AppearanceValue -key $prop.Name -val $prop.Value -indent "$indent`t`t`t"
}
X "$indent`t`t</dcsset:appearance>"
}
# Presentation
if ($ca.presentation) {
X "$indent`t`t<dcsset:presentation xsi:type=`"xs:string`">$(Esc-Xml "$($ca.presentation)")</dcsset:presentation>"
}
# ViewMode
if ($ca.viewMode) {
X "$indent`t`t<dcsset:viewMode>$(Esc-Xml "$($ca.viewMode)")</dcsset:viewMode>"
}
# UserSettingID
if ($ca.userSettingID) {
$uid = if ("$($ca.userSettingID)" -eq "auto") { New-Guid-String } else { "$($ca.userSettingID)" }
X "$indent`t`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
}
X "$indent`t</dcsset:item>"
}
X "$indent</dcsset:conditionalAppearance>"
}
function Emit-OutputParameters {
param($params, [string]$indent)
@@ -1183,6 +1290,15 @@ function Emit-DataParameters {
X "$indent`t`t<dcsset:userSettingID>$(Esc-Xml $uid)</dcsset:userSettingID>"
}
if ($dp.userSettingPresentation) {
X "$indent`t`t<dcsset:userSettingPresentation xsi:type=`"v8:LocalStringType`">"
X "$indent`t`t`t<v8:item>"
X "$indent`t`t`t`t<v8:lang>ru</v8:lang>"
X "$indent`t`t`t`t<v8:content>$(Esc-Xml "$($dp.userSettingPresentation)")</v8:content>"
X "$indent`t`t`t</v8:item>"
X "$indent`t`t</dcsset:userSettingPresentation>"
}
X "$indent`t</dcscor:item>"
}
X "$indent</dcsset:dataParameters>"
@@ -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"