$ErrorActionPreference = 'Stop' $htmlPath = Join-Path $PSScriptRoot '..\assets\app.js' $html = [System.IO.File]::ReadAllText($htmlPath, [System.Text.Encoding]::UTF8) $required = @( 'relabelMode:', 'relabel-box', 'relabel-sku', 'setRelabelMode(mode)', '贴箱唛', '贴SKU标', '开始作业', 'function relabelBoxView()', 'function relabelSkuView()', 'window.print()', 'handleRelabelScan()' ) $missing = $required | Where-Object { -not $html.Contains($_) } if ($missing) { throw "Missing relabel workflow contract: $($missing -join ', ')" } $renderStart = $html.LastIndexOf('function relabelView()') $renderEnd = $html.IndexOf('function relabelDetailView', $renderStart) if ($renderStart -lt 0 -or $renderEnd -lt 0) { throw 'Current relabel list view not found' } $render = $html.Substring($renderStart, $renderEnd - $renderStart) if (-not $render.Contains('setRelabelMode(')) { throw 'Relabel list does not expose mode tabs' } if (-not $render.Contains("t('relabelStart')")) { throw 'Relabel list does not use the start-work action' } $detailView = [regex]::Match($html, '(?s)function relabelDetailView\(mode\).*?(?=function relabelBoxView)').Value foreach ($token in @('relabel-scan','relabel-box-preview','relabel-sku-preview','printRelabelLabel')) { if (-not $detailView.Contains($token)) { throw "Relabel detail page is missing $token" } } $boxView = [regex]::Match($html, 'function relabelBoxView\(\)\{[^}]+\}').Value if (-not $boxView.Contains("relabelDetailView('box')")) { throw 'Carton-mark page does not use the shared detail view' } $skuView = [regex]::Match($html, 'function relabelSkuView\(\)\{[^}]+\}').Value if (-not $skuView.Contains("relabelDetailView('sku')")) { throw 'SKU-label page does not use the shared detail view' } Write-Output 'PASS: relabel workflow source contract'