$ErrorActionPreference = 'Stop' function Assert-Contains { param([string]$Content, [string]$Expected, [string]$Message) if ($Content -notmatch [regex]::Escape($Expected)) { throw $Message } } $root = Split-Path -Parent $PSScriptRoot $global = Get-Content -LiteralPath (Join-Path $root 'styles/global.scss') -Raw -Encoding utf8 Assert-Contains $global '.auth-page.auth-page .auth-plain-button[disabled]' '认证页禁用按钮必须由全局认证样式覆盖原生默认底色' Assert-Contains $global 'background: transparent !important;' '认证页禁用按钮必须保持透明背景' foreach ($relativePath in @( 'pages/auth/a01-entry.vue', 'pages/auth/a04-register.vue', 'pages/auth/a05-reset-password.vue' )) { $page = Get-Content -LiteralPath (Join-Path $root $relativePath) -Raw -Encoding utf8 foreach ($required in @( 'class="auth-plain-button get-code"', 'class="{ ''get-code--disabled'': sendingCode || cooldownSeconds > 0 }"', 'createAuthSmsCooldown({', 'const sentPhone = ref("");', 'isSmsDeliveryOutcomeUnknown', 'flex: 0 0 176rpx;', 'white-space: nowrap;', 'background: transparent !important;' )) { Assert-Contains $page $required "$relativePath 的验证码操作缺少视觉合同:$required" } if ($page.Contains('cooldownSeconds.value -= 1')) { throw "$relativePath still uses a decrementing cooldown that freezes in background" } if (-not $page.Contains('cooldownSeconds > 0 && phone.length > 0')) { throw "$relativePath must preserve an editable empty phone field when a scene cooldown is restored" } } Write-Output 'AUTH-CODE-ACTION-VISUAL-CONTRACT PASS'