mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-07-24 13:41:01 +03:00
Expand /skd-edit to 25 operations with add-dataSet, add-variant, add-conditionalAppearance
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
28b8061d64
commit
acb7a4eadc
@@ -36,7 +36,7 @@ powershell.exe -NoProfile -File .claude\skills\skd-edit\scripts\skd-edit.ps1 -Te
|
|||||||
-Operation add-field -Value "Цена: decimal(15,2) ;; Количество: decimal(15,3) ;; Сумма: decimal(15,2)"
|
-Operation add-field -Value "Цена: decimal(15,2) ;; Количество: decimal(15,3) ;; Сумма: decimal(15,2)"
|
||||||
```
|
```
|
||||||
|
|
||||||
Работает для всех операций кроме `set-query` и `set-structure`.
|
Работает для всех операций кроме `set-query`, `set-structure` и `add-dataSet`.
|
||||||
|
|
||||||
## Операции
|
## Операции
|
||||||
|
|
||||||
@@ -123,6 +123,41 @@ Shorthand: `"Источник > Приёмник on ВырИсточника =
|
|||||||
"Набор1 > Набор2 on Поле1 = Поле2 [param Связь]"
|
"Набор1 > Набор2 on Поле1 = Поле2 [param Связь]"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### add-dataSet — добавить набор данных
|
||||||
|
|
||||||
|
Shorthand: `"Имя: ТЕКСТ_ЗАПРОСА"` или `"ТЕКСТ_ЗАПРОСА"` (авто-имя `НаборДанныхN`).
|
||||||
|
|
||||||
|
```
|
||||||
|
"Доп: ВЫБРАТЬ 1 КАК Тест"
|
||||||
|
"ВЫБРАТЬ Ссылка ИЗ Справочник.Номенклатура"
|
||||||
|
```
|
||||||
|
|
||||||
|
`dataSource` берётся из первого существующего. Дубликат имени — предупреждение, пропуск. Не поддерживает пакетный режим (запрос может содержать `;;`).
|
||||||
|
|
||||||
|
### add-variant — добавить вариант настроек
|
||||||
|
|
||||||
|
Shorthand: `"Имя [Представление]"`. Представление опционально, по умолчанию = имя.
|
||||||
|
|
||||||
|
```
|
||||||
|
"Детальный"
|
||||||
|
"Детальный [Детальный отчёт]"
|
||||||
|
```
|
||||||
|
|
||||||
|
Создаёт вариант с Auto selection + detail group. Дубликат имени — предупреждение, пропуск.
|
||||||
|
|
||||||
|
### add-conditionalAppearance — добавить условное оформление
|
||||||
|
|
||||||
|
Shorthand: `"Параметр = значение [when Поле оп правое] [for Поле1, Поле2]"`.
|
||||||
|
|
||||||
|
```
|
||||||
|
"ЦветТекста = web:Red when Сумма < 0"
|
||||||
|
"ЦветФона = web:LightGreen when Статус = Одобрен for Статус"
|
||||||
|
"МинимальнаяШирина = 50 for Организация"
|
||||||
|
"Формат = ЧДЦ=2 for Цена, Сумма"
|
||||||
|
```
|
||||||
|
|
||||||
|
Типы значений (автодетект): `web:*`/`style:*`/`win:*` → цвет, `true`/`false` → boolean, иначе строка.
|
||||||
|
|
||||||
### set-query — заменить текст запроса
|
### set-query — заменить текст запроса
|
||||||
|
|
||||||
Не поддерживает пакетный режим. Value — полный текст запроса.
|
Не поддерживает пакетный режим. Value — полный текст запроса.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# skd-edit v1.0 — Atomic 1C DCS editor
|
# skd-edit v1.1 — Atomic 1C DCS editor
|
||||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||||
param(
|
param(
|
||||||
[Parameter(Mandatory)]
|
[Parameter(Mandatory)]
|
||||||
@@ -8,6 +8,7 @@ param(
|
|||||||
[ValidateSet(
|
[ValidateSet(
|
||||||
"add-field","add-total","add-calculated-field","add-parameter","add-filter",
|
"add-field","add-total","add-calculated-field","add-parameter","add-filter",
|
||||||
"add-dataParameter","add-order","add-selection","add-dataSetLink",
|
"add-dataParameter","add-order","add-selection","add-dataSetLink",
|
||||||
|
"add-dataSet","add-variant","add-conditionalAppearance",
|
||||||
"set-query","set-outputParameter","set-structure",
|
"set-query","set-outputParameter","set-structure",
|
||||||
"modify-field","modify-filter","modify-dataParameter",
|
"modify-field","modify-filter","modify-dataParameter",
|
||||||
"clear-selection","clear-order","clear-filter",
|
"clear-selection","clear-order","clear-filter",
|
||||||
@@ -428,6 +429,78 @@ function Parse-DataSetLinkShorthand {
|
|||||||
return $result
|
return $result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Parse-DataSetShorthand {
|
||||||
|
param([string]$s)
|
||||||
|
|
||||||
|
$s = $s.Trim()
|
||||||
|
# "Name: QUERY" — split on first ": " only if prefix is a single word (no spaces)
|
||||||
|
if ($s -match '^(\S+):\s(.+)$') {
|
||||||
|
return @{ name = $Matches[1]; query = $Matches[2] }
|
||||||
|
}
|
||||||
|
return @{ name = ""; query = $s }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Parse-VariantShorthand {
|
||||||
|
param([string]$s)
|
||||||
|
|
||||||
|
$presentation = ""
|
||||||
|
if ($s -match '\[([^\]]+)\]') {
|
||||||
|
$presentation = $Matches[1]
|
||||||
|
$s = $s -replace '\s*\[[^\]]+\]', ''
|
||||||
|
}
|
||||||
|
$name = $s.Trim()
|
||||||
|
if (-not $presentation) { $presentation = $name }
|
||||||
|
return @{ name = $name; presentation = $presentation }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Parse-ConditionalAppearanceShorthand {
|
||||||
|
param([string]$s)
|
||||||
|
|
||||||
|
$result = @{ param = ""; value = ""; filter = $null; fields = @() }
|
||||||
|
|
||||||
|
# Extract " when ..." — condition part
|
||||||
|
$whenIdx = $s.IndexOf(' when ')
|
||||||
|
$forIdx = $s.IndexOf(' for ')
|
||||||
|
|
||||||
|
# Determine boundaries
|
||||||
|
$mainEnd = $s.Length
|
||||||
|
if ($whenIdx -ge 0 -and $forIdx -ge 0) {
|
||||||
|
$mainEnd = [Math]::Min($whenIdx, $forIdx)
|
||||||
|
} elseif ($whenIdx -ge 0) {
|
||||||
|
$mainEnd = $whenIdx
|
||||||
|
} elseif ($forIdx -ge 0) {
|
||||||
|
$mainEnd = $forIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse "for" fields
|
||||||
|
if ($forIdx -ge 0) {
|
||||||
|
$forEnd = $s.Length
|
||||||
|
if ($whenIdx -gt $forIdx) { $forEnd = $whenIdx }
|
||||||
|
$forPart = $s.Substring($forIdx + 5, $forEnd - $forIdx - 5).Trim()
|
||||||
|
$result.fields = @($forPart -split '\s*,\s*' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse "when" filter
|
||||||
|
if ($whenIdx -ge 0) {
|
||||||
|
$whenEnd = $s.Length
|
||||||
|
if ($forIdx -gt $whenIdx) { $whenEnd = $forIdx }
|
||||||
|
$whenPart = $s.Substring($whenIdx + 6, $whenEnd - $whenIdx - 6).Trim()
|
||||||
|
$result.filter = Parse-FilterShorthand $whenPart
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse main part: "Param = Value"
|
||||||
|
$mainPart = $s.Substring(0, $mainEnd).Trim()
|
||||||
|
$eqIdx = $mainPart.IndexOf('=')
|
||||||
|
if ($eqIdx -gt 0) {
|
||||||
|
$result.param = $mainPart.Substring(0, $eqIdx).Trim()
|
||||||
|
$result.value = $mainPart.Substring($eqIdx + 1).Trim()
|
||||||
|
} else {
|
||||||
|
$result.param = $mainPart
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result
|
||||||
|
}
|
||||||
|
|
||||||
function Parse-StructureShorthand {
|
function Parse-StructureShorthand {
|
||||||
param([string]$s)
|
param([string]$s)
|
||||||
|
|
||||||
@@ -838,6 +911,104 @@ function Build-DataSetLinkFragment {
|
|||||||
return $lines -join "`r`n"
|
return $lines -join "`r`n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Build-DataSetQueryFragment {
|
||||||
|
param($parsed, [string]$indent)
|
||||||
|
|
||||||
|
$i = $indent
|
||||||
|
$lines = @()
|
||||||
|
$lines += "$i<dataSet xsi:type=`"DataSetQuery`">"
|
||||||
|
$lines += "$i`t<name>$(Esc-Xml $parsed.name)</name>"
|
||||||
|
$lines += "$i`t<dataSource>$(Esc-Xml $parsed.dataSource)</dataSource>"
|
||||||
|
$lines += "$i`t<query>$(Esc-Xml $parsed.query)</query>"
|
||||||
|
$lines += "$i</dataSet>"
|
||||||
|
return $lines -join "`r`n"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-VariantFragment {
|
||||||
|
param($parsed, [string]$indent)
|
||||||
|
|
||||||
|
$i = $indent
|
||||||
|
$lines = @()
|
||||||
|
$lines += "$i<settingsVariant>"
|
||||||
|
$lines += "$i`t<dcsset:name>$(Esc-Xml $parsed.name)</dcsset:name>"
|
||||||
|
$lines += (Build-MLTextXml -tag "dcsset:presentation" -text $parsed.presentation -indent "$i`t")
|
||||||
|
$lines += "$i`t<dcsset:settings xmlns:style=`"http://v8.1c.ru/8.1/data/ui/style`" xmlns:sys=`"http://v8.1c.ru/8.1/data/ui/fonts/system`" xmlns:web=`"http://v8.1c.ru/8.1/data/ui/colors/web`" xmlns:win=`"http://v8.1c.ru/8.1/data/ui/colors/windows`">"
|
||||||
|
$lines += "$i`t`t<dcsset:selection>"
|
||||||
|
$lines += "$i`t`t`t<dcsset:item xsi:type=`"dcsset:SelectedItemAuto`"/>"
|
||||||
|
$lines += "$i`t`t</dcsset:selection>"
|
||||||
|
$lines += "$i`t`t<dcsset:item xsi:type=`"dcsset:StructureItemGroup`">"
|
||||||
|
$lines += "$i`t`t`t<dcsset:groupItems/>"
|
||||||
|
$lines += "$i`t`t`t<dcsset:order>"
|
||||||
|
$lines += "$i`t`t`t`t<dcsset:item xsi:type=`"dcsset:OrderItemAuto`"/>"
|
||||||
|
$lines += "$i`t`t`t</dcsset:order>"
|
||||||
|
$lines += "$i`t`t`t<dcsset:selection>"
|
||||||
|
$lines += "$i`t`t`t`t<dcsset:item xsi:type=`"dcsset:SelectedItemAuto`"/>"
|
||||||
|
$lines += "$i`t`t`t</dcsset:selection>"
|
||||||
|
$lines += "$i`t`t</dcsset:item>"
|
||||||
|
$lines += "$i`t</dcsset:settings>"
|
||||||
|
$lines += "$i</settingsVariant>"
|
||||||
|
return $lines -join "`r`n"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Build-ConditionalAppearanceItemFragment {
|
||||||
|
param($parsed, [string]$indent)
|
||||||
|
|
||||||
|
$i = $indent
|
||||||
|
$lines = @()
|
||||||
|
$lines += "$i<dcsset:item>"
|
||||||
|
|
||||||
|
# selection
|
||||||
|
if ($parsed.fields -and $parsed.fields.Count -gt 0) {
|
||||||
|
$lines += "$i`t<dcsset:selection>"
|
||||||
|
foreach ($fld in $parsed.fields) {
|
||||||
|
$lines += "$i`t`t<dcsset:item>"
|
||||||
|
$lines += "$i`t`t`t<dcsset:field>$(Esc-Xml $fld)</dcsset:field>"
|
||||||
|
$lines += "$i`t`t</dcsset:item>"
|
||||||
|
}
|
||||||
|
$lines += "$i`t</dcsset:selection>"
|
||||||
|
} else {
|
||||||
|
$lines += "$i`t<dcsset:selection/>"
|
||||||
|
}
|
||||||
|
|
||||||
|
# filter
|
||||||
|
if ($parsed.filter) {
|
||||||
|
$lines += "$i`t<dcsset:filter>"
|
||||||
|
$f = $parsed.filter
|
||||||
|
$lines += "$i`t`t<dcsset:item xsi:type=`"dcsset:FilterItemComparison`">"
|
||||||
|
$lines += "$i`t`t`t<dcsset:left xsi:type=`"dcscor:Field`">$(Esc-Xml $f.field)</dcsset:left>"
|
||||||
|
$lines += "$i`t`t`t<dcsset:comparisonType>$(Esc-Xml $f.op)</dcsset:comparisonType>"
|
||||||
|
if ($null -ne $f.value) {
|
||||||
|
$vt = if ($f["valueType"]) { $f["valueType"] } else { "xs:string" }
|
||||||
|
$lines += "$i`t`t`t<dcsset:right xsi:type=`"$vt`">$(Esc-Xml "$($f.value)")</dcsset:right>"
|
||||||
|
}
|
||||||
|
$lines += "$i`t`t</dcsset:item>"
|
||||||
|
$lines += "$i`t</dcsset:filter>"
|
||||||
|
} else {
|
||||||
|
$lines += "$i`t<dcsset:filter/>"
|
||||||
|
}
|
||||||
|
|
||||||
|
# appearance
|
||||||
|
$lines += "$i`t<dcsset:appearance>"
|
||||||
|
|
||||||
|
# Auto-detect value type
|
||||||
|
$val = $parsed.value
|
||||||
|
$valType = "xs:string"
|
||||||
|
if ($val -match '^(web|style|win):') {
|
||||||
|
$valType = "v8ui:Color"
|
||||||
|
} elseif ($val -eq "true" -or $val -eq "false") {
|
||||||
|
$valType = "xs:boolean"
|
||||||
|
}
|
||||||
|
|
||||||
|
$lines += "$i`t`t<dcscor:item xsi:type=`"dcsset:SettingsParameterValue`">"
|
||||||
|
$lines += "$i`t`t`t<dcscor:parameter>$(Esc-Xml $parsed.param)</dcscor:parameter>"
|
||||||
|
$lines += "$i`t`t`t<dcscor:value xsi:type=`"$valType`">$(Esc-Xml $val)</dcscor:value>"
|
||||||
|
$lines += "$i`t`t</dcscor:item>"
|
||||||
|
$lines += "$i`t</dcsset:appearance>"
|
||||||
|
|
||||||
|
$lines += "$i</dcsset:item>"
|
||||||
|
return $lines -join "`r`n"
|
||||||
|
}
|
||||||
|
|
||||||
function Build-StructureItemFragment {
|
function Build-StructureItemFragment {
|
||||||
param($item, [string]$indent)
|
param($item, [string]$indent)
|
||||||
|
|
||||||
@@ -1249,7 +1420,7 @@ $corNs = "http://v8.1c.ru/8.1/data-composition-system/core"
|
|||||||
|
|
||||||
# --- 7. Batch value splitting ---
|
# --- 7. Batch value splitting ---
|
||||||
|
|
||||||
if ($Operation -eq "set-query" -or $Operation -eq "set-structure") {
|
if ($Operation -eq "set-query" -or $Operation -eq "set-structure" -or $Operation -eq "add-dataSet") {
|
||||||
$values = @($Value)
|
$values = @($Value)
|
||||||
} else {
|
} else {
|
||||||
$values = @($Value -split ';;' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
$values = @($Value -split ';;' | ForEach-Object { $_.Trim() } | Where-Object { $_ })
|
||||||
@@ -1637,6 +1808,126 @@ switch ($Operation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"add-dataSet" {
|
||||||
|
$root = $xmlDoc.DocumentElement
|
||||||
|
$childIndent = Get-ChildIndent $root
|
||||||
|
|
||||||
|
$parsed = Parse-DataSetShorthand $Value
|
||||||
|
|
||||||
|
# Auto-name if empty
|
||||||
|
if (-not $parsed.name) {
|
||||||
|
$count = 0
|
||||||
|
foreach ($ch in $root.ChildNodes) {
|
||||||
|
if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'dataSet' -and $ch.NamespaceURI -eq $schNs) { $count++ }
|
||||||
|
}
|
||||||
|
$parsed.name = "НаборДанных$($count + 1)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Duplicate check
|
||||||
|
$existing = Find-ElementByChildValue $root "dataSet" "name" $parsed.name $schNs
|
||||||
|
if ($existing) {
|
||||||
|
Write-Host "[WARN] DataSet `"$($parsed.name)`" already exists — skipped"
|
||||||
|
} else {
|
||||||
|
# Get dataSource name from first existing <dataSource>
|
||||||
|
$dsSourceEl = Find-FirstElement $root @("dataSource") $schNs
|
||||||
|
$dsSourceName = "ИсточникДанных1"
|
||||||
|
if ($dsSourceEl) {
|
||||||
|
$nameEl = Find-FirstElement $dsSourceEl @("name") $schNs
|
||||||
|
if ($nameEl) { $dsSourceName = $nameEl.InnerText.Trim() }
|
||||||
|
}
|
||||||
|
$parsed["dataSource"] = $dsSourceName
|
||||||
|
|
||||||
|
$fragXml = Build-DataSetQueryFragment -parsed $parsed -indent $childIndent
|
||||||
|
$nodes = Import-Fragment $xmlDoc $fragXml
|
||||||
|
|
||||||
|
# Insert after last <dataSet>, or after <dataSource> if none
|
||||||
|
$lastDS = Find-LastElement $root "dataSet" $schNs
|
||||||
|
if ($lastDS) {
|
||||||
|
$refNode = $lastDS.NextSibling
|
||||||
|
while ($refNode -and ($refNode.NodeType -eq 'Whitespace' -or $refNode.NodeType -eq 'SignificantWhitespace')) {
|
||||||
|
$refNode = $refNode.NextSibling
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$refNode = Find-FirstElement $root @("dataSetLink","calculatedField","totalField","parameter","template","groupTemplate","settingsVariant") $schNs
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($node in $nodes) {
|
||||||
|
Insert-BeforeElement $root $node $refNode $childIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "[OK] DataSet `"$($parsed.name)`" added (dataSource=$dsSourceName)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"add-variant" {
|
||||||
|
$root = $xmlDoc.DocumentElement
|
||||||
|
$childIndent = Get-ChildIndent $root
|
||||||
|
|
||||||
|
foreach ($val in $values) {
|
||||||
|
$parsed = Parse-VariantShorthand $val
|
||||||
|
|
||||||
|
# Duplicate check — search for settingsVariant with matching dcsset:name
|
||||||
|
$isDup = $false
|
||||||
|
foreach ($ch in $root.ChildNodes) {
|
||||||
|
if ($ch.NodeType -eq 'Element' -and $ch.LocalName -eq 'settingsVariant' -and $ch.NamespaceURI -eq $schNs) {
|
||||||
|
foreach ($gc in $ch.ChildNodes) {
|
||||||
|
if ($gc.NodeType -eq 'Element' -and $gc.LocalName -eq 'name' -and $gc.NamespaceURI -eq $setNs -and $gc.InnerText -eq $parsed.name) {
|
||||||
|
$isDup = $true; break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($isDup) { break }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($isDup) {
|
||||||
|
Write-Host "[WARN] Variant `"$($parsed.name)`" already exists — skipped"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
$fragXml = Build-VariantFragment -parsed $parsed -indent $childIndent
|
||||||
|
$nodes = Import-Fragment $xmlDoc $fragXml
|
||||||
|
|
||||||
|
# Insert after last <settingsVariant>
|
||||||
|
$lastSV = Find-LastElement $root "settingsVariant" $schNs
|
||||||
|
if ($lastSV) {
|
||||||
|
$refNode = $lastSV.NextSibling
|
||||||
|
while ($refNode -and ($refNode.NodeType -eq 'Whitespace' -or $refNode.NodeType -eq 'SignificantWhitespace')) {
|
||||||
|
$refNode = $refNode.NextSibling
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$refNode = $null
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($node in $nodes) {
|
||||||
|
Insert-BeforeElement $root $node $refNode $childIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "[OK] Variant `"$($parsed.name)`" [`"$($parsed.presentation)`"] added"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"add-conditionalAppearance" {
|
||||||
|
$settings = Resolve-VariantSettings
|
||||||
|
$varName = Get-VariantName
|
||||||
|
|
||||||
|
foreach ($val in $values) {
|
||||||
|
$parsed = Parse-ConditionalAppearanceShorthand $val
|
||||||
|
|
||||||
|
$caEl = Ensure-SettingsChild $settings "conditionalAppearance" @("outputParameters","order","filter","selection")
|
||||||
|
$caIndent = Get-ContainerChildIndent $caEl
|
||||||
|
|
||||||
|
$fragXml = Build-ConditionalAppearanceItemFragment -parsed $parsed -indent $caIndent
|
||||||
|
$nodes = Import-Fragment $xmlDoc $fragXml
|
||||||
|
foreach ($node in $nodes) {
|
||||||
|
Insert-BeforeElement $caEl $node $null $caIndent
|
||||||
|
}
|
||||||
|
|
||||||
|
$desc = "$($parsed.param) = $($parsed.value)"
|
||||||
|
if ($parsed.filter) { $desc += " when $($parsed.filter.field) $($parsed.filter.op)" }
|
||||||
|
if ($parsed.fields -and $parsed.fields.Count -gt 0) { $desc += " for $($parsed.fields -join ', ')" }
|
||||||
|
Write-Host "[OK] ConditionalAppearance `"$desc`" added to variant `"$varName`""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
"clear-selection" {
|
"clear-selection" {
|
||||||
$settings = Resolve-VariantSettings
|
$settings = Resolve-VariantSettings
|
||||||
$varName = Get-VariantName
|
$varName = Get-VariantName
|
||||||
|
|||||||
Reference in New Issue
Block a user