开始审核样式
This commit is contained in:
+74
-153
@@ -31,179 +31,100 @@ function Assert-NotContains {
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$entryPath = Join-Path $root 'pages/auth/a01-entry.vue'
|
||||
$loginPath = Join-Path $root 'pages/auth/a02-login.vue'
|
||||
$legacyLoginPath = Join-Path $root 'pages/auth/a02-login.vue'
|
||||
$pagesPath = Join-Path $root 'pages.json'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $entryPath)) {
|
||||
throw 'Missing A-01 entry page: pages/auth/a01-entry.vue'
|
||||
throw 'Missing the single A01 login page.'
|
||||
}
|
||||
if (Test-Path -LiteralPath $legacyLoginPath) {
|
||||
throw 'A02 was merged into A01, so the legacy page file must be removed.'
|
||||
}
|
||||
|
||||
$pages = Get-Content -LiteralPath $pagesPath -Raw -Encoding utf8 | ConvertFrom-Json
|
||||
if ($pages.pages[0].path -ne 'pages/auth/a01-entry') {
|
||||
throw 'A-01 entry page must be the first route in pages.json'
|
||||
throw 'A01 must remain the first application route.'
|
||||
}
|
||||
if ($pages.pages.path -contains 'pages/auth/a02-login') {
|
||||
throw 'pages.json must not retain the legacy A02 route.'
|
||||
}
|
||||
if ($pages.pages.Count -ne 53) {
|
||||
throw "Expected 53 final routes after the A02 merge, found $($pages.pages.Count)."
|
||||
}
|
||||
|
||||
$entry = Get-Content -LiteralPath $entryPath -Raw -Encoding utf8
|
||||
$login = Get-Content -LiteralPath $loginPath -Raw -Encoding utf8
|
||||
|
||||
$accountPasswordLogin = ConvertFrom-Utf8Base64 '6LSm5Y+35a+G56CB55m75b2V'
|
||||
$wechatLogin = ConvertFrom-Utf8Base64 '5b6u5L+h55m75b2V'
|
||||
$registerPrompt = ConvertFrom-Utf8Base64 '6L+Y5rKh5pyJ6LSm5Y+377yf'
|
||||
$registerEntry = ConvertFrom-Utf8Base64 '5rOo5YaM6LSm5Y+3'
|
||||
$loginEntry = ConvertFrom-Utf8Base64 '55m75b2V'
|
||||
$dividerGlyph = ConvertFrom-Utf8Base64 '4oyY'
|
||||
$agreementRequired = ConvertFrom-Utf8Base64 '6K+35YWI6ZiF6K+75bm25ZCM5oSP55u45YWz5Y2P6K6u'
|
||||
$wechatPending = ConvertFrom-Utf8Base64 '5b6u5L+h55m75b2V5Yqf6IO95YeG5aSH5Lit'
|
||||
$registerPending = ConvertFrom-Utf8Base64 '5rOo5YaM6aG16Z2i5YeG5aSH5Lit'
|
||||
$agreementPending = ConvertFrom-Utf8Base64 '5Y2P6K6u6aG16Z2i5YeG5aSH5Lit'
|
||||
$smsLogin = ConvertFrom-Utf8Base64 '5omL5py66aqM6K+B56CB55m75b2V'
|
||||
$forgotPassword = ConvertFrom-Utf8Base64 '5b+Y6K6w5a+G56CB'
|
||||
$getCode = ConvertFrom-Utf8Base64 '6I635Y+W6aqM6K+B56CB'
|
||||
$loginPending = ConvertFrom-Utf8Base64 '55m75b2V5o6l5Y+j5b6F5o6l5YWl'
|
||||
$forgotPasswordPending = ConvertFrom-Utf8Base64 '5b+Y6K6w5a+G56CB6aG16Z2i5YeG5aSH5Lit'
|
||||
$getCodePending = ConvertFrom-Utf8Base64 '6I635Y+W6aqM6K+B56CB5Yqf6IO95b6F5o6l5YWl'
|
||||
$implicitAgreement = ConvertFrom-Utf8Base64 '55m75b2V5Y2z6KGo56S65ZCM5oSP'
|
||||
$agreementConfirm = ConvertFrom-Utf8Base64 '5oiR5bey6ZiF6K+75bm25ZCM5oSP'
|
||||
$agreementGuard = ConvertFrom-Utf8Base64 '6K+35YWI6ZiF6K+75bm25ZCM5oSP55u45YWz5Y2P6K6u'
|
||||
$legacyAgreementReminder = ConvertFrom-Utf8Base64 '6K+35YWI5Zyo55m75b2V5byV5a+86aG16Z2i5YeG5aSH5Lit6ZiF6K+75bm25ZCM5oSP5Y2P6K6u'
|
||||
|
||||
foreach ($requiredEntryCopy in @($wechatLogin, $registerPrompt, $registerEntry, $agreementRequired, $wechatPending, $registerPending, $agreementPending)) {
|
||||
Assert-Contains -Content $entry -Expected $requiredEntryCopy -Message "Missing A-01 copy: $requiredEntryCopy"
|
||||
}
|
||||
|
||||
Assert-Contains -Content $entry -Expected "url: '/pages/auth/a02-login?agreed=1'" -Message 'A-01 account login must navigate with agreed=1'
|
||||
Assert-Contains -Content $entry -Expected "<text>$loginEntry</text>" -Message 'A-01 primary entry copy must be 登录'
|
||||
foreach ($requiredClass in @('auth-header', 'brand-intro', 'entry-actions', 'agreement-row')) {
|
||||
Assert-Contains -Content $entry -Expected $requiredClass -Message "Missing A-01 page structure: $requiredClass"
|
||||
}
|
||||
foreach ($requiredVisualAnchor in @(
|
||||
'brand-divider--top',
|
||||
'brand-divider--bottom',
|
||||
'entry-button--primary',
|
||||
'entry-button--secondary',
|
||||
'height: 253rpx',
|
||||
'padding: 150rpx 56rpx 0',
|
||||
'width: 426rpx',
|
||||
'margin: 95rpx 110rpx 0',
|
||||
'height: 118rpx',
|
||||
'margin-top: 51rpx',
|
||||
'margin-top: 98rpx',
|
||||
'margin-top: 141rpx',
|
||||
'top: 70rpx',
|
||||
'width: 64rpx',
|
||||
'entry-button__content',
|
||||
'translateX(-20rpx)',
|
||||
'auth-divider-knot.png',
|
||||
'auth-title-cloud.png',
|
||||
# Final decorative surfaces must come from real bitmap assets.
|
||||
foreach ($asset in @(
|
||||
'a01-login-header-v1.png',
|
||||
'a01-login-header-exact-v2.png',
|
||||
'auth-ink-scenery.png',
|
||||
'a01-login-scroll-frame-v1.png',
|
||||
'a01-title-divider-v2.png',
|
||||
'a01-primary-button.png',
|
||||
'a01-secondary-button.png',
|
||||
'entry-button__skin',
|
||||
'align-items: center',
|
||||
'white-space: nowrap',
|
||||
'font-size: 20rpx',
|
||||
'width: 30rpx',
|
||||
'height: 30rpx'
|
||||
)) {
|
||||
Assert-Contains -Content $entry -Expected $requiredVisualAnchor -Message "Missing A-01 calibrated visual anchor: $requiredVisualAnchor"
|
||||
}
|
||||
foreach ($rejectedVisualConstruction in @('link-line', 'button-corner--legacy', 'class="auth-button primary-button"', 'auth-button-corner.png', 'button-corner-asset', '.entry-button::after')) {
|
||||
Assert-NotContains -Content $entry -Unexpected $rejectedVisualConstruction -Message "A-01 retains rejected visual construction: $rejectedVisualConstruction"
|
||||
}
|
||||
foreach ($forbiddenClass in @('entryGuideVisual', 'guide-art', 'entry-hit', 'width: 750rpx', 'min-height: 1625rpx')) {
|
||||
Assert-NotContains -Content $entry -Unexpected $forbiddenClass -Message "A-01 must not render the whole design image with $forbiddenClass"
|
||||
}
|
||||
Assert-NotContains -Content $entry -Unexpected '/static/assets/icons/action/create-cloud-v2.png' -Message 'A-01 must not reuse the mismatched create-cloud asset for its title or divider ornaments'
|
||||
Assert-Contains -Content $entry -Expected 'filter: brightness(0) invert(1)' -Message 'A-01 primary login icon must render in white'
|
||||
Assert-NotContains -Content $entry -Unexpected $dividerGlyph -Message 'A-01 divider must not use a text glyph as ornament'
|
||||
if (([regex]::Matches($entry, 'class="entry-button__skin"')).Count -ne 2) {
|
||||
throw 'A-01 must render one complete opaque skin image for each entry button'
|
||||
}
|
||||
if (([regex]::Matches($entry, 'auth-divider-knot\.png')).Count -ne 2) {
|
||||
throw 'A-01 must render the dedicated divider-knot asset above and below the subtitle'
|
||||
}
|
||||
if ($entry -match '(?s)\.entry-button\s*\{[^}]*\bborder\s*:') {
|
||||
throw 'A-01 entry buttons must not draw their final border with CSS'
|
||||
}
|
||||
if ($entry -match '(?s)\.entry-button--(?:primary|secondary)\s*\{[^}]*\bbackground\s*:') {
|
||||
throw 'A-01 entry buttons must not draw their final surface with CSS'
|
||||
}
|
||||
if ($entry -notmatch '(?s)\.agreement-row\s*\{[^}]*align-items:\s*center') {
|
||||
throw 'A-01 agreement checkbox and copy must align on one horizontal center line'
|
||||
}
|
||||
if ($entry -notmatch '(?s)\.agreement-copy\s*\{[^}]*white-space:\s*nowrap') {
|
||||
throw 'A-01 agreement copy must remain on a single line'
|
||||
}
|
||||
if ($entry -match '(?s)\.auth-page\s*\{[^}]*overflow\s*:\s*hidden') {
|
||||
throw 'A-01 must allow vertical scrolling on small screens'
|
||||
}
|
||||
|
||||
foreach ($requiredLoginCopy in @($accountPasswordLogin, $smsLogin, $forgotPassword, $getCode, $loginPending, $agreementConfirm, $agreementGuard, $getCodePending)) {
|
||||
Assert-Contains -Content $login -Expected $requiredLoginCopy -Message "Missing A-02 copy: $requiredLoginCopy"
|
||||
}
|
||||
Assert-Contains -Content $login -Expected "url: '/pages/auth/a05-reset-password'" -Message 'A-02 forgot-password entry must navigate to A-05'
|
||||
|
||||
foreach ($requiredLoginVisualAnchor in @(
|
||||
'auth-title-cloud.png',
|
||||
'login-title-cloud',
|
||||
'a02-login-panel.png',
|
||||
'login-panel__skin',
|
||||
'a01-primary-button.png',
|
||||
'login-submit__skin',
|
||||
'login-submit__content',
|
||||
'agreement-row',
|
||||
'agreement-icon',
|
||||
'auth-wechat.png',
|
||||
'a01-icon-phone-v1.png',
|
||||
'a01-icon-lock-v1.png',
|
||||
'a01-icon-eye-open-v1.png',
|
||||
'a01-icon-eye-closed-pupil-v2.png',
|
||||
'a01-icon-sms-code-v2.png',
|
||||
'a02-agreement-unchecked.png',
|
||||
'a02-agreement-checked.png'
|
||||
)) {
|
||||
Assert-Contains -Content $login -Expected $requiredLoginVisualAnchor -Message "Missing A-02 calibrated visual anchor: $requiredLoginVisualAnchor"
|
||||
Assert-Contains -Content $entry -Expected $asset -Message "A01 is missing asset reference: $asset"
|
||||
}
|
||||
if (([regex]::Matches($login, 'class="login-submit__skin"')).Count -ne 1) {
|
||||
throw 'A-02 must render one complete opaque skin image for its login button'
|
||||
}
|
||||
if (([regex]::Matches($login, 'class="login-panel__skin"')).Count -ne 1) {
|
||||
throw 'A-02 must render one complete opaque skin image for its login panel'
|
||||
}
|
||||
if ($login -match '(?s)\.login-panel\s*\{[^}]*\bborder\s*:') {
|
||||
throw 'A-02 login panel must not draw its final frame with CSS'
|
||||
}
|
||||
if ($login -match '(?s)\.login-panel\s*\{[^}]*\bbackground\s*:') {
|
||||
throw 'A-02 login panel must not draw its final paper surface with CSS'
|
||||
}
|
||||
if ($login -match '(?s)\.login-submit\s*\{[^}]*\bborder\s*:') {
|
||||
throw 'A-02 login button must not draw its final border with CSS'
|
||||
}
|
||||
if ($login -match '(?s)\.login-submit\s*\{[^}]*\bbackground\s*:') {
|
||||
throw 'A-02 login button must not draw its final surface with CSS'
|
||||
}
|
||||
if ($login -notmatch '<view class="agreement-row" @click="toggleAgreement">') {
|
||||
throw 'A-02 must provide one directly clickable agreement row'
|
||||
}
|
||||
if (([regex]::Matches($login, '@click\.stop="prepareAgreement"')).Count -ne 2) {
|
||||
throw 'A-02 agreement row must retain two non-toggling agreement links'
|
||||
}
|
||||
foreach ($requiredAgreementState in @('const agreed = ref(false)', 'const isAgreedRoute = () =>', "if (typeof location !== 'undefined') {", "new URLSearchParams(location.hash.split('?')[1] || '')", 'const pages = getCurrentPages()', 'const currentPage = pages[pages.length - 1]', "return currentPage?.options?.agreed === '1'", 'const syncAgreementFromRoute = () =>', 'agreed.value = isAgreedRoute()', 'onShow(() => {', 'syncAgreementFromRoute()', 'const toggleAgreement = () =>', 'if (agreed.value) return true')) {
|
||||
Assert-Contains -Content $login -Expected $requiredAgreementState -Message "Missing A-02 agreement state: $requiredAgreementState"
|
||||
}
|
||||
Assert-NotContains -Content $login -Unexpected 'onLoad((options) =>' -Message 'A-02 must not leave agreement state initialized only on first load'
|
||||
Assert-NotContains -Content $login -Unexpected $legacyAgreementReminder -Message 'A-02 must not retain its passive return-to-entry agreement reminder'
|
||||
Assert-NotContains -Content $login -Unexpected 'agreedFromEntry' -Message 'A-02 must use its local agreed state as the submit gate'
|
||||
if ($login -match '(?s)\.agreement-icon\s*\{[^}]*\bborder\s*:') {
|
||||
throw 'A-02 agreement icon must not draw its final circle with CSS'
|
||||
}
|
||||
if ($login -match '(?s)\.agreement-icon\s*\{[^}]*\bbackground\s*:') {
|
||||
throw 'A-02 agreement icon must not draw its final state with CSS'
|
||||
}
|
||||
if ($login -match '\.agreement-icon::(?:before|after)') {
|
||||
throw 'A-02 agreement icon must not draw its final state with a pseudo element'
|
||||
foreach ($obsoleteHeaderAsset in @('auth-header.png', 'brand-seal.png', 'a01-paper-transition-v1.png')) {
|
||||
Assert-NotContains -Content $entry -Unexpected $obsoleteHeaderAsset -Message "A01 must use the selected design's single exact header bitmap instead of composing $obsoleteHeaderAsset."
|
||||
}
|
||||
|
||||
if ($login -match '(?s)\.auth-page\s*\{[^}]*overflow\s*:\s*hidden') {
|
||||
throw 'A-02 must allow vertical scrolling on small screens'
|
||||
$requiredCopy = @(
|
||||
'55m75b2V5a626LCx',
|
||||
'5a+G56CB55m75b2V',
|
||||
'6aqM6K+B56CB55m75b2V',
|
||||
'5omL5py65Y+3',
|
||||
'5a+G56CB',
|
||||
'6aqM6K+B56CB',
|
||||
'5b+Y6K6w5a+G56CB',
|
||||
'6I635Y+W6aqM6K+B56CB',
|
||||
'5b6u5L+h55m75b2V',
|
||||
'6L+Y5rKh5pyJ6LSm5Y+377yf',
|
||||
'5rOo5YaM6LSm5Y+3',
|
||||
'44CK55So5oi35Y2P6K6u44CL',
|
||||
'44CK6ZqQ56eB5pS/562W44CL'
|
||||
) | ForEach-Object { ConvertFrom-Utf8Base64 $_ }
|
||||
foreach ($copy in $requiredCopy) {
|
||||
Assert-Contains -Content $entry -Expected $copy -Message "A01 is missing required visible copy: $copy"
|
||||
}
|
||||
|
||||
foreach ($forbidden in @('appApi', 'calcMD5', 'loginWithPassword', 'uni.reLaunch', $implicitAgreement)) {
|
||||
Assert-NotContains -Content $entry -Unexpected $forbidden -Message "A-01 must not contain legacy auth behavior: $forbidden"
|
||||
Assert-NotContains -Content $login -Unexpected $forbidden -Message "A-02 must not contain legacy auth behavior: $forbidden"
|
||||
foreach ($contract in @(
|
||||
"const activeLoginMethod = ref('password')",
|
||||
'const passwordVisible = ref(false)',
|
||||
"const LOGIN_METHOD_STORAGE_KEY = 'a01:last-login-method'",
|
||||
'uni.getStorageSync(LOGIN_METHOD_STORAGE_KEY)',
|
||||
'uni.setStorageSync(LOGIN_METHOD_STORAGE_KEY, method)',
|
||||
'const switchLoginMethod = (method) =>',
|
||||
'const togglePasswordVisibility = () =>',
|
||||
"url: '/pages/auth/a04-register'",
|
||||
"url: '/pages/auth/a05-reset-password'",
|
||||
'class="feedback-toast"',
|
||||
'class="verification-layer"',
|
||||
'class="login-submit"'
|
||||
)) {
|
||||
Assert-Contains -Content $entry -Expected $contract -Message "A01 is missing state or interaction contract: $contract"
|
||||
}
|
||||
|
||||
Write-Output 'A01-A02-UI-CONTRACT PASS'
|
||||
foreach ($nativeUi in @('uni.showToast', 'uni.showModal', 'uni.showLoading', 'uni.showActionSheet')) {
|
||||
Assert-NotContains -Content $entry -Unexpected $nativeUi -Message "A01 must not use native UniApp feedback: $nativeUi"
|
||||
}
|
||||
Assert-NotContains -Content $entry -Unexpected "url: '/pages/auth/a02-login" -Message 'A01 must not navigate to A02.'
|
||||
Assert-NotContains -Content $entry -Unexpected 'brand-intro' -Message 'A01 must remove the legacy oversized brand introduction.'
|
||||
Assert-NotContains -Content $entry -Unexpected 'min-height: 100vh' -Message 'A01 must not depend on 100vh for its page shell.'
|
||||
Assert-NotContains -Content $entry -Unexpected 'exact-chrome-overlay' -Message 'A01 must not stack a second full-screen scroll perimeter over the complete scroll frame.'
|
||||
Assert-NotContains -Content $entry -Unexpected 'auth-design-scenery-v1.png' -Message 'A01 must not use the scenery bitmap that contains stray scroll handles.'
|
||||
Assert-NotContains -Content $entry -Unexpected 'a01-icon-eye-closed-v1.png' -Message 'A01 hidden-password icon must retain the center pupil instead of using the hollow crossed eye.'
|
||||
Assert-NotContains -Content $entry -Unexpected 'a01-icon-verification-v1.png' -Message 'A01 SMS field must use a message-code icon instead of a success-state checkmark.'
|
||||
Assert-NotContains -Content $entry -Unexpected 'a01-icon-sms-code-v1.svg' -Message 'A01 SMS field must use the custom generated icon instead of the temporary third-party SVG.'
|
||||
Assert-NotContains -Content $entry -Unexpected '@media (max-height:' -Message 'A01 must preserve the design ratio on short screens and scroll instead of compressing with pixel breakpoints.'
|
||||
|
||||
Write-Output 'A01-LOGIN-MERGE-CONTRACT PASS'
|
||||
|
||||
Reference in New Issue
Block a user