скрипт

This commit is contained in:
gorbenko.pavel
2026-08-17 13:19:43 +05:00
parent 364835eaf7
commit e2c7f96021
37 changed files with 377 additions and 198 deletions
+89 -3
View File
@@ -10,6 +10,17 @@
2) при необходимости переименовывает колонку Title;
3) обеспечивает колонки.
Имена списков НУМЕРОВАННЫЕ: «<Форма> <N> — данные» / «<Форма> <N> — согласование».
Номер собирает сам скрипт из имени в манифесте (см. Get-NumberedListTitle) — в
манифестах имена остаются без номера, чтобы номер не дублировался по 14 манифестам
и ссылкам lookupList. Нумерация нужна под архивацию: когда список данных упирается
в порог элементов, рядом создаётся следующая пара с номером N+1.
Перед основным проходом идёт разовая МИГРАЦИЯ имён (только при -ListNumber 1):
существующие списки со старым безномерным именем переименовываются в «… 1 — …».
Переименовывается только Title — server-relative URL списка при этом НЕ меняется,
поэтому ссылки на список (request_type.list_id в approval-route) остаются валидными.
Колонки — через СТОЛБЦЫ САЙТА (эталоны):
- не-Lookup колонка сначала создаётся как столбец сайта (группа «Портал заявок»),
один раз на весь сайт, затем ПОДКЛЮЧАЕТСЯ к списку по ссылке. Так одинаковые
@@ -40,17 +51,31 @@
.PARAMETER FormsRoot
Папка с формами. По умолчанию — src/webparts/requestPortal/forms.
.PARAMETER ListNumber
Номер пары списков. 1 — текущие (рабочие) списки; 2, 3 … — следующие пары под
архивацию. Миграция безномерных имён выполняется только при 1.
.PARAMETER SkipRename
Не выполнять миграцию имён существующих списков (только создание/колонки).
.EXAMPLE
./Provision-Lists.ps1 -SiteUrl "https://tnsukz.sharepoint.com/sites/requests" `
-ClientId "7459c965-5ed4-4673-8140-0ab8faf9db64" -Tenant "tnsukz.onmicrosoft.com" `
-Thumbprint "AABBCC...."
.EXAMPLE
# Следующая пара списков под архивацию, без миграции имён.
./Provision-Lists.ps1 -SiteUrl "..." -ClientId "..." -Tenant "..." -Thumbprint "..." `
-ListNumber 2
#>
param(
[Parameter(Mandatory = $true)][string]$SiteUrl,
[Parameter(Mandatory = $true)][string]$ClientId,
[Parameter(Mandatory = $true)][string]$Tenant,
[Parameter(Mandatory = $true)][string]$Thumbprint,
[string]$FormsRoot = "$PSScriptRoot/../src/webparts/requestPortal/forms"
[string]$FormsRoot = "$PSScriptRoot/../src/webparts/requestPortal/forms",
[ValidateRange(1, 999)][int]$ListNumber = 1,
[switch]$SkipRename
)
$ErrorActionPreference = 'Stop'
@@ -61,6 +86,30 @@ function ConvertTo-XmlSafe {
return $Value.Replace('&', '&amp;').Replace('<', '&lt;').Replace('>', '&gt;').Replace("'", '&apos;').Replace('"', '&quot;')
}
# Имя списка по конвенции: «<Форма> — данные» / «<Форма> — согласование».
$LIST_TITLE_PATTERN = '^(?<base>.+?)\s*—\s*(?<suffix>данные|согласование)\s*$'
# Имя в манифесте → нумерованное «<Форма> <N> — <суффикс>».
#
# Номер ставится ПЕРЕД суффиксом, и это не косметика: и портал
# (features/myRequests/myRequests.service.ts), и админка маршрутов
# (approval-route/frontend/.../requestManageService.ts) выводят имя списка
# согласования из имени списка данных регексом /\s*—\s*данные\s*$/, привязанным к
# КОНЦУ строки. «… — данные 1» этот регекс не матчит, и список согласования просто
# перестаёт находиться.
#
# Идемпотентно: уже нумерованное имя не получает второй номер, а перенумеровывается.
function Get-NumberedListTitle {
param([string]$Title, [int]$Number)
$m = [regex]::Match($Title, $LIST_TITLE_PATTERN)
if (-not $m.Success) {
throw "Имя списка «$Title» не по конвенции «<Форма> — данные|согласование» — номер поставить некуда"
}
$base = $m.Groups['base'].Value -replace '\s+\d+$', ''
return "$base $Number — $($m.Groups['suffix'].Value)"
}
# Есть ли колонка НА СПИСКЕ (list-scope).
function Test-FieldExists {
param([string]$List, [string]$InternalName)
@@ -175,7 +224,12 @@ function Add-ListColumn {
}
}
'Lookup' {
$src = Get-PnPList -Identity $Col.lookupList -ErrorAction Stop
# lookupList в манифесте — безномерное имя, целевой список тоже нумерован.
# Кросс-формные lookup'ы (WorkplaceSetup.SourceHire → «Прием на работу … — данные»)
# при этом предполагают ОДИН И ТОТ ЖЕ номер у обеих форм — при появлении
# реальных архивных пар это место придётся пересмотреть.
$lookupTitle = Get-NumberedListTitle -Title $Col.lookupList -Number $ListNumber
$src = Get-PnPList -Identity $lookupTitle -ErrorAction Stop
$guid = $src.Id.ToString()
$show = if ($Col.lookupShowField) { $Col.lookupShowField } else { 'Title' }
$xml = "<Field Type='Lookup' DisplayName='$(ConvertTo-XmlSafe $Col.title)' Name='$($Col.internalName)' ShowField='$show' List='{$guid}' />"
@@ -239,9 +293,41 @@ if (-not $manifests) {
return
}
# Проход 0: миграция безномерных имён на «… 1 — …». Отдельным проходом ДО основного —
# так порядок обхода манифестов не важен: к моменту разрешения Lookup'а (по имени
# списка-источника) все списки уже переименованы.
#
# Переименовывается только Title. URL списка при переименовании Title в SharePoint не
# меняется, поэтому request_type.list_id (server-relative URL) в approval-route
# трогать не нужно.
if ($ListNumber -eq 1 -and -not $SkipRename) {
Write-Host "`n=== Миграция имён списков на «… 1 — …» ===" -ForegroundColor Cyan
foreach ($manifest in $manifests) {
$def = Get-Content -Path $manifest.FullName -Raw -Encoding UTF8 | ConvertFrom-Json
$legacyTitle = $def.dataListTitle
$targetTitle = Get-NumberedListTitle -Title $legacyTitle -Number 1
if (Get-PnPList -Identity $targetTitle -ErrorAction SilentlyContinue) {
Write-Host " [=] уже нумерован: «$targetTitle»" -ForegroundColor DarkGray
continue
}
if (-not (Get-PnPList -Identity $legacyTitle -ErrorAction SilentlyContinue)) {
Write-Host " [ ] нет списка «$legacyTitle» — создастся ниже как «$targetTitle»" -ForegroundColor DarkGray
continue
}
try {
Set-PnPList -Identity $legacyTitle -Title $targetTitle | Out-Null
Write-Host " [~] «$legacyTitle» → «$targetTitle»" -ForegroundColor Yellow
}
catch {
Write-Warning " [!] не удалось переименовать «$legacyTitle»: $($_.Exception.Message)"
}
}
}
foreach ($manifest in $manifests) {
$def = Get-Content -Path $manifest.FullName -Raw -Encoding UTF8 | ConvertFrom-Json
$listTitle = $def.dataListTitle
$listTitle = Get-NumberedListTitle -Title $def.dataListTitle -Number $ListNumber
Write-Host "`n=== Форма: $($manifest.Directory.Name) → список «$listTitle» ===" -ForegroundColor Cyan
# 1) Список (идемпотентно)