refactor(ui): InspectionTaskWizardWindow 全量令牌化(107 处)

检测任务向导 9 阶段模板中全部裸 HEX 颜色和越界字号替换为 Nova 令牌引用,
残留归零。这是 P3 逐页迁移的第一个文件,也是单文件改动量最大的一个。

颜色映射
- #FFFFFF(根背景/容器白底)→ NovaSurfaceContainerBrush
- #F5F6F7(左侧步骤轨)/ #FAFAFA(卡片浅背景)→ NovaSurfaceContainerLowBrush
- #E0E0E0(分隔线/边框/待定态灰)→ NovaOutlineVariantBrush
- #1B1B1B(主要文字)→ NovaOnSurfaceBrush
- #5A5A5A(次要文字)→ NovaOnSurfaceVariantBrush
- #FFFFFF(白色前景)→ NovaOnPrimaryBrush
- #107C10(完成态/运行态绿)→ NovaSuccessBrush
- #D13438(失败红)→ NovaErrorBrush
- #B0B0B0(禁用态按钮)→ NovaOnBackgroundDisabledBrush
- #F0F5FF/#B0C4DE/#1B5E9A/#3A6A9A/#7A9ABA(信息提示卡片组)→
  NovaInfoContainerBrush / NovaInfoBrush / NovaPrimaryBrush / NovaOnSurfaceVariantBrush

字号收敛
- FontSize="13" → NovaFontSizeBody (14):全部替换
- FontSize="14" → NovaFontSizeBody (14):统一引用令牌
- FontSize="16" → NovaFontSizeBodyStrong (16):标题
- FontSize="12" → NovaFontSizeCaption (12):说明文字
- FontSize="20" → NovaFontSizeSubtitle (18):判定结果大标题
- FontSize="11" → 保留现状(步骤数字,密集面板例外)
This commit is contained in:
zhengxuan.zhang
2026-07-31 17:29:58 +08:00
parent 8a41af3e38
commit 59c1707393
2 changed files with 246 additions and 84 deletions
+162
View File
@@ -0,0 +1,162 @@
<#
.SYNOPSIS
NOVA UI 规范护栏:禁止新增裸 HEX 颜色值。
.DESCRIPTION
对应 .kiro/steering/ui-design.md 第 6 节「编码约束 · 禁止裸 HEX」。
颜色必须统一走 Themes/NovaColors.xaml 中的令牌(NovaXxxBrush /
NovaXxxColor),不允许在页面或代码里直接写十六进制色值。
仓库里历史遗留的裸 HEX 还有大量未迁移(P3 阶段尚在推进,详见
ui-design.md 第 7 节迁移顺序),因此本护栏默认是【增量模式】:
只检查相对于某个基准(默认与 origin 的合并基点)新增或修改的行,
不会因为历史存量而挡住无关的提交。要看全量现状用 -Mode Full。
范围限定为 XplorePlane 主项目(原生 WPF 面 + 代码侧),与
ui-design.md 第 4 节记录的范围边界一致:
- 排除 Themes/Nova*.xaml 本身(它是唯一允许出现裸 HEX 的地方)
- 排除 obj/bin 生成目录
- 不扫描跨模块项目(XP.Common、XP.Hardware.* 等)——那些明确
标注为「本次不做」,不应被这道护栏误挡
正则只匹配带引号的属性值形式 ="#RRGGBB(AA)",不匹配裸文本,
因此不会对「说明性注释里提到某个十六进制色值」产生误报
(例如 "原 #E3F0FF 浅蓝强调底,语义对应 NOVA secondaryContainer"
这类迁移记录注释)。
.PARAMETER Mode
Diff(默认):只检查增量(git diff 新增行)。
Full:扫描全部现存文件,用于生成现状报告,不建议作为提交门禁。
.PARAMETER Base
Diff 模式下的比较基准。默认自动探测 origin/主分支的合并基点;
在本地无网络/无远程的场景可显式传入一个 commit/分支名。
.PARAMETER Path
要扫描的项目根目录。默认是仓库中的 XplorePlane 主项目目录。
.EXAMPLE
pwsh tools/Check-NovaColorTokens.ps1
提交前跑:只检查本次改动是否新增了裸 HEX。
.EXAMPLE
pwsh tools/Check-NovaColorTokens.ps1 -Mode Full
生成全量现状报告(预期会有大量历史命中,仅供参考)。
.NOTES
退出码:0 = 未发现违规;1 = 发现违规。
没有现成 CI 配置时,建议接成 pre-commit(或 Kiro PreToolUse)钩子,
命令示例:
pwsh -NoProfile -File tools/Check-NovaColorTokens.ps1
一旦引入正式 CI 流水线,直接调用本脚本(Diff 模式)作为一个步骤即可。
#>
param(
[ValidateSet('Diff', 'Full')]
[string]$Mode = 'Diff',
[string]$Base,
[string]$Path = (Join-Path $PSScriptRoot '..\XplorePlane')
)
$ErrorActionPreference = 'Stop'
$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
$Path = (Resolve-Path $Path).Path
# 带引号的属性值形式:Background="#FFFFFF"、Value="#1A2B3C"、
# "#2E7D32"C# 字符串字面量)等。不匹配裸文本,避免命中注释里的说明文字。
$hexPattern = '="#[0-9A-Fa-f]{6,8}"'
function Test-IsExcluded {
param([string]$RelativePath)
if ($RelativePath -match '[\\/](obj|bin)[\\/]') { return $true }
if ($RelativePath -match '[\\/]Themes[\\/]Nova.*\.xaml$') { return $true }
return $false
}
$violations = @()
if ($Mode -eq 'Full') {
$files = Get-ChildItem -Recurse -Path $Path -Include *.xaml, *.cs -File |
Where-Object { -not (Test-IsExcluded $_.FullName.Substring($RepoRoot.Length + 1)) }
foreach ($file in $files) {
$matches = Select-String -Path $file.FullName -Pattern $hexPattern -AllMatches
foreach ($m in $matches) {
foreach ($hit in $m.Matches) {
$violations += [pscustomobject]@{
File = $file.FullName.Substring($Path.Length + 1)
Line = $m.LineNumber
Snippet = $m.Line.Trim()
Hex = $hit.Value
}
}
}
}
}
else {
# Diff 模式:只看 git diff 里新增的行(+ 开头,排除 +++ 文件头),
# 且限定在 XplorePlane 目录下的 .xaml/.cs 文件。
if (-not $Base) {
$Base = git -C $RepoRoot merge-base HEAD origin/HEAD 2>$null
if (-not $Base) { $Base = git -C $RepoRoot rev-parse HEAD~1 2>$null }
if (-not $Base) { $Base = 'HEAD' }
}
# 同时覆盖已提交的改动(Base..HEAD)与尚未提交的工作区改动,
# 这样在提交前本地跑一次就能拦住,不必依赖已经 commit。
$diffArgs = @('-C', $RepoRoot, 'diff', '--unified=0', "$Base", '--', 'XplorePlane/*.xaml', 'XplorePlane/*.cs')
$committedDiff = & git @diffArgs 2>$null
$workingDiff = & git -C $RepoRoot diff --unified=0 -- 'XplorePlane/*.xaml' 'XplorePlane/*.cs' 2>$null
$stagedDiff = & git -C $RepoRoot diff --unified=0 --cached -- 'XplorePlane/*.xaml' 'XplorePlane/*.cs' 2>$null
$currentFile = $null
$currentLine = 0
foreach ($line in ($committedDiff + $workingDiff + $stagedDiff)) {
if ($line -match '^\+\+\+ b/(.+)$') {
$currentFile = $matches[1]
continue
}
if ($line -match '^@@ -\d+(?:,\d+)? \+(\d+)') {
$currentLine = [int]$matches[1]
continue
}
if ($line -match '^\+(?!\+\+)(.*)$') {
$content = $matches[1]
if ($currentFile -and -not (Test-IsExcluded $currentFile)) {
if ($content -match $hexPattern) {
foreach ($hit in [regex]::Matches($content, $hexPattern)) {
$violations += [pscustomobject]@{
File = $currentFile
Line = $currentLine
Snippet = $content.Trim()
Hex = $hit.Value
}
}
}
}
$currentLine++
continue
}
if ($line -match '^-') { continue }
}
}
# 同一行可能被 committedDiff/workingDiff/stagedDiff 重复统计,按 文件+行+片段 去重。
$violations = $violations | Sort-Object File, Line, Snippet -Unique
if ($violations.Count -eq 0) {
$scope = if ($Mode -eq 'Full') { '全量扫描' } else { "增量扫描(基准 $Base" }
Write-Host "[NOVA] 未发现新增裸 HEX 颜色值($scope)。" -ForegroundColor Green
exit 0
}
Write-Host "[NOVA] 发现 $($violations.Count) 处裸 HEX 颜色值,须改为引用 Themes/NovaColors.xaml 中的令牌:" -ForegroundColor Red
Write-Host ""
foreach ($v in $violations) {
Write-Host (" {0}:{1}" -f $v.File, $v.Line) -ForegroundColor Yellow
Write-Host (" {0}" -f $v.Snippet)
}
Write-Host ""
Write-Host "参见 .kiro/steering/ui-design.md 第 6 节「禁止裸 HEX」。" -ForegroundColor DarkYellow
exit 1