修改未完成
This commit is contained in:
@@ -30,16 +30,16 @@ function Assert-NotContains {
|
||||
}
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$entryPath = Join-Path $root 'pages/auth/entry.vue'
|
||||
$loginPath = Join-Path $root 'pages/auth/login.vue'
|
||||
$entryPath = Join-Path $root 'pages/auth/a01-entry.vue'
|
||||
$loginPath = 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/entry.vue'
|
||||
throw 'Missing A-01 entry page: pages/auth/a01-entry.vue'
|
||||
}
|
||||
|
||||
$pages = Get-Content -LiteralPath $pagesPath -Raw -Encoding utf8 | ConvertFrom-Json
|
||||
if ($pages.pages[0].path -ne 'pages/auth/entry') {
|
||||
if ($pages.pages[0].path -ne 'pages/auth/a01-entry') {
|
||||
throw 'A-01 entry page must be the first route in pages.json'
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ foreach ($requiredEntryCopy in @($wechatLogin, $registerPrompt, $registerEntry,
|
||||
Assert-Contains -Content $entry -Expected $requiredEntryCopy -Message "Missing A-01 copy: $requiredEntryCopy"
|
||||
}
|
||||
|
||||
Assert-Contains -Content $entry -Expected "url: '/pages/auth/login?agreed=1'" -Message 'A-01 account login must navigate with agreed=1'
|
||||
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"
|
||||
@@ -92,9 +92,9 @@ foreach ($requiredVisualAnchor in @(
|
||||
'inset: 6rpx',
|
||||
'entry-button__content',
|
||||
'translateX(-20rpx)',
|
||||
'auth-button-corner-v1.png',
|
||||
'auth-divider-knot-v1.png',
|
||||
'auth-title-cloud-v1.png',
|
||||
'auth-button-corner.png',
|
||||
'auth-divider-knot.png',
|
||||
'auth-title-cloud.png',
|
||||
'button-corner-asset',
|
||||
'align-items: center',
|
||||
'white-space: nowrap',
|
||||
@@ -116,7 +116,7 @@ Assert-NotContains -Content $entry -Unexpected $dividerGlyph -Message 'A-01 divi
|
||||
if (([regex]::Matches($entry, 'button-corner-asset button-corner-asset--')).Count -ne 8) {
|
||||
throw 'A-01 must render the generated ornamental corner asset in all four corners of both entry buttons'
|
||||
}
|
||||
if (([regex]::Matches($entry, 'auth-divider-knot-v1\.png')).Count -ne 2) {
|
||||
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 -notmatch '(?s)\.agreement-row\s*\{[^}]*align-items:\s*center') {
|
||||
|
||||
@@ -4,16 +4,16 @@ $root = Split-Path -Parent $PSScriptRoot
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
$backgrounds = @(
|
||||
'static/assets/backgrounds/auth-ancestral-header-v1.png',
|
||||
'static/assets/backgrounds/auth-rice-paper-v1.jpg',
|
||||
'static/assets/backgrounds/auth-ink-scenery-v1.png'
|
||||
'static/assets/foundation/opaque/auth-header.png',
|
||||
'static/assets/foundation/opaque/auth-page-paper.jpg',
|
||||
'static/assets/foundation/transparent/auth-ink-scenery.png'
|
||||
)
|
||||
$icons = @(
|
||||
'static/assets/icons/auth/login-outline-v1.png',
|
||||
'static/assets/icons/auth/wechat-licensed-v1.png',
|
||||
'static/assets/icons/auth/auth-button-corner-v1.png',
|
||||
'static/assets/icons/auth/auth-divider-knot-v1.png',
|
||||
'static/assets/icons/auth/auth-title-cloud-v1.png'
|
||||
'static/assets/foundation/transparent/auth-login-outline.png',
|
||||
'static/assets/foundation/transparent/auth-wechat.png',
|
||||
'static/assets/foundation/transparent/auth-button-corner.png',
|
||||
'static/assets/foundation/transparent/auth-divider-knot.png',
|
||||
'static/assets/foundation/transparent/auth-title-cloud.png'
|
||||
)
|
||||
|
||||
foreach ($asset in $backgrounds + $icons) {
|
||||
@@ -41,9 +41,9 @@ foreach ($asset in $icons) {
|
||||
$bitmap.Dispose()
|
||||
|
||||
$expectedSize = switch ($asset) {
|
||||
'static/assets/icons/auth/auth-button-corner-v1.png' { @(160, 160) }
|
||||
'static/assets/icons/auth/auth-divider-knot-v1.png' { @(160, 96) }
|
||||
'static/assets/icons/auth/auth-title-cloud-v1.png' { @(200, 120) }
|
||||
'static/assets/foundation/transparent/auth-button-corner.png' { @(160, 160) }
|
||||
'static/assets/foundation/transparent/auth-divider-knot.png' { @(160, 96) }
|
||||
'static/assets/foundation/transparent/auth-title-cloud.png' { @(200, 120) }
|
||||
default { @(96, 96) }
|
||||
}
|
||||
if ($width -ne $expectedSize[0] -or $height -ne $expectedSize[1]) { throw "$asset must be $($expectedSize[0]) x $($expectedSize[1])px." }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$requiredFiles = @('utils/config.js', 'utils/session.js', 'utils/genealogy-context.js', 'utils/api.js', 'pages/lineage/first-person.vue', 'pages/content/list.vue', 'pages/content/editor.vue')
|
||||
$requiredFiles = @('utils/config.js', 'utils/session.js', 'utils/genealogy-context.js', 'utils/api.js', 'pages/genealogy/g04-first-ancestor.vue', 'pages/skeleton/content-list-skeleton.vue', 'pages/family/f02-publish-feed.vue')
|
||||
foreach ($file in $requiredFiles) {
|
||||
if (-not (Test-Path (Join-Path $root $file))) {
|
||||
throw "Missing core-flow file: $file"
|
||||
@@ -46,16 +46,16 @@ if ($api -notmatch 'getProfile') {
|
||||
}
|
||||
|
||||
$pages = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages.json')
|
||||
if ($pages -notmatch 'pages/lineage/first-person') {
|
||||
if ($pages -notmatch 'pages/genealogy/g04-first-ancestor') {
|
||||
throw 'Missing first-person page route'
|
||||
}
|
||||
foreach ($route in @('pages/content/list', 'pages/content/editor')) {
|
||||
foreach ($route in @('pages/skeleton/content-list-skeleton', 'pages/family/f02-publish-feed')) {
|
||||
if ($pages -notmatch [regex]::Escape($route)) {
|
||||
throw "Missing content page route: $route"
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($pageFile in @('pages/genealogy/detail.vue', 'pages/tree/index.vue', 'pages/member/detail.vue')) {
|
||||
foreach ($pageFile in @('pages/genealogy/g05-genealogy-overview.vue', 'pages/tree/t01-tree-overview.vue', 'pages/tree/t03-member-profile.vue')) {
|
||||
$page = Get-Content -Raw -Encoding UTF8 (Join-Path $root $pageFile)
|
||||
if ($page -match "id=1001|id=3") {
|
||||
throw "Hard-coded route ID remains in $pageFile"
|
||||
@@ -71,33 +71,33 @@ foreach ($method in @('markNotificationRead', 'markAllNotificationsRead')) {
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($pageFile in @('pages/genealogy/applications.vue', 'pages/notification/index.vue')) {
|
||||
foreach ($pageFile in @('pages/genealogy/g10-application-review.vue', 'pages/notification/n01-message-center.vue')) {
|
||||
$page = Get-Content -Raw -Encoding UTF8 (Join-Path $root $pageFile)
|
||||
if ($page -match '1001') {
|
||||
throw "Hard-coded genealogy ID remains in $pageFile"
|
||||
}
|
||||
}
|
||||
|
||||
$applications = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/genealogy/applications.vue')
|
||||
$applications = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/genealogy/g10-application-review.vue')
|
||||
if ($applications -notmatch 'genealogyContext') {
|
||||
throw 'Missing genealogy context in applications page'
|
||||
}
|
||||
|
||||
$notifications = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/notification/index.vue')
|
||||
$notifications = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/notification/n01-message-center.vue')
|
||||
foreach ($method in @('markNotificationRead', 'markAllNotificationsRead')) {
|
||||
if ($notifications -notmatch [regex]::Escape($method)) {
|
||||
throw "Notification page does not use $method"
|
||||
}
|
||||
}
|
||||
|
||||
$family = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/family/index.vue')
|
||||
foreach ($token in @('genealogyContext', 'openSection', 'pages/content/list', 'pages/content/editor')) {
|
||||
$family = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/family/f01-family-feed.vue')
|
||||
foreach ($token in @('genealogyContext', 'openSection', 'pages/skeleton/content-list-skeleton', 'pages/family/f02-publish-feed')) {
|
||||
if ($family -notmatch [regex]::Escape($token)) {
|
||||
throw "Missing family content flow: $token"
|
||||
}
|
||||
}
|
||||
|
||||
$profile = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/profile/index.vue')
|
||||
$profile = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/profile/m01-profile-home.vue')
|
||||
foreach ($token in @('appApi', 'getProfile', 'profile.name')) {
|
||||
if ($profile -notmatch [regex]::Escape($token)) {
|
||||
throw "Missing dynamic profile behavior: $token"
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$errors = [System.Collections.Generic.List[string]]::new()
|
||||
$sourceFiles = Get-ChildItem -LiteralPath (Join-Path $root 'pages'), (Join-Path $root 'components') -Recurse -File |
|
||||
Where-Object { $_.Extension -in '.vue', '.js', '.scss' }
|
||||
|
||||
foreach ($sourceFile in $sourceFiles) {
|
||||
$content = Get-Content -Raw -Encoding UTF8 $sourceFile.FullName
|
||||
$matches = [regex]::Matches($content, '/static/assets/[^"''\s<]+')
|
||||
|
||||
foreach ($match in $matches) {
|
||||
$assetUrl = $match.Value
|
||||
$assetPath = Join-Path $root $assetUrl.TrimStart('/')
|
||||
$relativeSource = $sourceFile.FullName.Substring($root.Length + 1)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $assetPath)) {
|
||||
$errors.Add("Missing asset $assetUrl referenced by $relativeSource")
|
||||
continue
|
||||
}
|
||||
|
||||
if ($assetUrl -notmatch '^/static/assets/(foundation|modules)/') {
|
||||
$errors.Add("Legacy asset path $assetUrl referenced by $relativeSource")
|
||||
}
|
||||
|
||||
if ($assetUrl -match '(-v[0-9]+|-source)\.') {
|
||||
$errors.Add("Temporary asset name $assetUrl referenced by $relativeSource")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors.Count -gt 0) {
|
||||
throw "Foundation asset audit failed:`n$($errors -join "`n")"
|
||||
}
|
||||
|
||||
Write-Output 'PASS foundation asset audit'
|
||||
@@ -0,0 +1,64 @@
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$errors = [System.Collections.Generic.List[string]]::new()
|
||||
$pageCommentPrefix = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('PCEtLSDpobXpnaLnvJblj7fvvJo='))
|
||||
|
||||
$pages = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages.json') | ConvertFrom-Json
|
||||
$registeredPaths = @($pages.pages | ForEach-Object { $_.path })
|
||||
|
||||
function Test-ExpectedPage {
|
||||
param(
|
||||
[string]$ExpectedPath,
|
||||
[string]$PageId
|
||||
)
|
||||
|
||||
$pageFile = Join-Path $root ($expectedPath + '.vue')
|
||||
if ($registeredPaths -notcontains $expectedPath) {
|
||||
$errors.Add("Missing final route: $expectedPath")
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $pageFile)) {
|
||||
$errors.Add("Missing final page file: $($expectedPath).vue")
|
||||
return
|
||||
}
|
||||
|
||||
$content = Get-Content -Raw -Encoding UTF8 $pageFile
|
||||
if (-not $content.StartsWith($pageCommentPrefix + $pageId)) {
|
||||
$errors.Add("Missing Chinese page header: $($expectedPath).vue")
|
||||
}
|
||||
}
|
||||
|
||||
function Test-AssetDirectory {
|
||||
param([string]$AssetDirectory)
|
||||
|
||||
if (-not (Test-Path -LiteralPath (Join-Path $root $assetDirectory))) {
|
||||
$errors.Add("Missing foundation asset directory: $assetDirectory")
|
||||
}
|
||||
}
|
||||
|
||||
# P-00 final routes: each file name identifies the page and its design ID.
|
||||
Test-ExpectedPage -ExpectedPath 'pages/auth/a01-entry' -PageId 'A-01'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/auth/a02-login' -PageId 'A-02'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/genealogy/g01-my-genealogies' -PageId 'G-01'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/genealogy/g03-create-genealogy' -PageId 'G-03'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/genealogy/g04-first-ancestor' -PageId 'G-04'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/genealogy/g05-genealogy-overview' -PageId 'G-05'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/genealogy/g06-search-genealogies' -PageId 'G-06'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/genealogy/g10-application-review' -PageId 'G-10'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/tree/t01-tree-overview' -PageId 'T-01'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/tree/t03-member-profile' -PageId 'T-03'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/family/f01-family-feed' -PageId 'F-01'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/family/f02-publish-feed' -PageId 'F-02'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/skeleton/content-list-skeleton' -PageId 'S-01'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/notification/n01-message-center' -PageId 'N-01'
|
||||
Test-ExpectedPage -ExpectedPath 'pages/profile/m01-profile-home' -PageId 'M-01'
|
||||
|
||||
# Both asset directories are required so opaque bases and transparent overlays stay separate.
|
||||
Test-AssetDirectory -AssetDirectory 'static/assets/foundation/opaque'
|
||||
Test-AssetDirectory -AssetDirectory 'static/assets/foundation/transparent'
|
||||
|
||||
if ($errors.Count -gt 0) {
|
||||
throw "P-00 foundation structure audit failed:`n$($errors -join "`n")"
|
||||
}
|
||||
|
||||
Write-Output 'PASS foundation structure audit'
|
||||
@@ -4,12 +4,12 @@ $root = Split-Path -Parent $PSScriptRoot
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
$assets = @(
|
||||
'static/assets/icons/common/location-v1.png',
|
||||
'static/assets/icons/common/member-meta-v1.png',
|
||||
'static/assets/icons/common/admin-v1.png',
|
||||
'static/assets/icons/genealogy/seal-current-frame-v1.png',
|
||||
'static/assets/icons/genealogy/seal-row-frame-v1.png',
|
||||
'static/assets/icons/action/create-cloud-v2.png'
|
||||
'static/assets/foundation/transparent/meta-location.png',
|
||||
'static/assets/foundation/transparent/meta-member.png',
|
||||
'static/assets/foundation/transparent/meta-admin.png',
|
||||
'static/assets/modules/genealogy/transparent/current-seal-frame.png',
|
||||
'static/assets/modules/genealogy/transparent/row-seal-frame.png',
|
||||
'static/assets/modules/genealogy/transparent/create-cloud.png'
|
||||
)
|
||||
|
||||
foreach ($asset in $assets) {
|
||||
|
||||
@@ -2,33 +2,32 @@ $ErrorActionPreference = 'Stop'
|
||||
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$requiredAssets = @(
|
||||
'static/assets/icons/brand/jiapu-seal-logo.png',
|
||||
'static/assets/icons/brand/jiapu-seal-logo-header.png',
|
||||
'static/assets/icons/common/notice-v3.png',
|
||||
'static/assets/icons/common/chevron-right-v2.png',
|
||||
'static/assets/icons/common/location-v1.png',
|
||||
'static/assets/icons/common/member-meta-v1.png',
|
||||
'static/assets/icons/common/admin-v1.png',
|
||||
'static/assets/icons/genealogy/tree-v2.png',
|
||||
'static/assets/icons/genealogy/members-v2.png',
|
||||
'static/assets/icons/genealogy/generation-poem-v2.png',
|
||||
'static/assets/icons/genealogy/application-v2.png',
|
||||
'static/assets/icons/genealogy/seal-current-frame-v1.png',
|
||||
'static/assets/icons/genealogy/seal-row-frame-v1.png',
|
||||
'static/assets/icons/action/add-v2.png',
|
||||
'static/assets/icons/action/create-cloud-v2.png',
|
||||
'static/assets/icons/tab/genealogy-v4.png',
|
||||
'static/assets/icons/tab/genealogy-active-v4.png',
|
||||
'static/assets/icons/tab/family-v4.png',
|
||||
'static/assets/icons/tab/family-active-v4.png',
|
||||
'static/assets/icons/tab/profile-v4.png',
|
||||
'static/assets/icons/tab/profile-active-v4.png',
|
||||
'static/assets/backgrounds/genealogy-current-slip-frame.png',
|
||||
'static/assets/backgrounds/genealogy-list-slip-frame.png',
|
||||
'static/assets/backgrounds/header-cinnabar-texture-v2.jpg',
|
||||
'static/assets/backgrounds/paper-rice-texture-v2.jpg',
|
||||
'static/assets/backgrounds/footer-mountain-bamboo.png',
|
||||
'static/assets/backgrounds/genealogy-section-divider-v2.png'
|
||||
'static/assets/foundation/transparent/brand-seal.png',
|
||||
'static/assets/foundation/transparent/notice.png',
|
||||
'static/assets/foundation/transparent/chevron-right.png',
|
||||
'static/assets/foundation/transparent/meta-location.png',
|
||||
'static/assets/foundation/transparent/meta-member.png',
|
||||
'static/assets/foundation/transparent/meta-admin.png',
|
||||
'static/assets/modules/genealogy/transparent/shortcut-tree.png',
|
||||
'static/assets/modules/genealogy/transparent/shortcut-members.png',
|
||||
'static/assets/modules/genealogy/transparent/shortcut-generation-poem.png',
|
||||
'static/assets/modules/genealogy/transparent/shortcut-application.png',
|
||||
'static/assets/modules/genealogy/transparent/current-seal-frame.png',
|
||||
'static/assets/modules/genealogy/transparent/row-seal-frame.png',
|
||||
'static/assets/modules/genealogy/transparent/add.png',
|
||||
'static/assets/modules/genealogy/transparent/create-cloud.png',
|
||||
'static/assets/foundation/transparent/tab-genealogy.png',
|
||||
'static/assets/foundation/transparent/tab-genealogy-active.png',
|
||||
'static/assets/foundation/transparent/tab-family.png',
|
||||
'static/assets/foundation/transparent/tab-family-active.png',
|
||||
'static/assets/foundation/transparent/tab-profile.png',
|
||||
'static/assets/foundation/transparent/tab-profile-active.png',
|
||||
'static/assets/modules/genealogy/transparent/current-slip-frame.png',
|
||||
'static/assets/modules/genealogy/transparent/list-slip-frame.png',
|
||||
'static/assets/foundation/opaque/root-header-cinnabar.jpg',
|
||||
'static/assets/foundation/opaque/page-paper.jpg',
|
||||
'static/assets/foundation/transparent/footer-mountain-bamboo.png',
|
||||
'static/assets/modules/genealogy/transparent/section-divider.png'
|
||||
)
|
||||
|
||||
foreach ($asset in $requiredAssets) {
|
||||
@@ -40,14 +39,14 @@ foreach ($asset in $requiredAssets) {
|
||||
$header = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'components/PageHeader.vue')
|
||||
$tabbar = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'components/AppTabbar.vue')
|
||||
|
||||
if ($header -notmatch 'jiapu-seal-logo-header\.png') { throw 'Header does not use the approved tight brand PNG.' }
|
||||
if ($header -notmatch 'jiapu-seal-logo-header\.png') { throw 'Header does not use the tight header Logo asset.' }
|
||||
if ($header -notmatch 'notice-v3\.png') { throw 'Header does not use the approved notice PNG.' }
|
||||
if ($header -notmatch 'brand-seal\.png') { throw 'Header does not use the approved tight brand PNG.' }
|
||||
if ($header -notmatch 'brand-seal\.png') { throw 'Header does not use the tight header Logo asset.' }
|
||||
if ($header -notmatch 'notice\.png') { throw 'Header does not use the approved notice PNG.' }
|
||||
if ($header -notmatch 'unreadCount\s*>\s*0') { throw 'Header badge is not conditional on unread count.' }
|
||||
if ($header -notmatch 'class="header-hall"') { throw 'Header does not isolate the hall line-art as a low-contrast background layer.' }
|
||||
if ($header -match 'background-image: url') { throw 'Header still applies hall line-art directly to the red header surface.' }
|
||||
if ($header -notmatch 'opacity:\s*\.29') { throw 'Header hall line-art is not visible enough for the approved eave layer.' }
|
||||
if ($header -notmatch 'header-cinnabar-texture-v2\.jpg') { throw 'Header does not use the approved cinnabar texture asset.' }
|
||||
if ($header -notmatch 'root-header-cinnabar\.jpg') { throw 'Header does not use the approved cinnabar texture asset.' }
|
||||
if ($header -notmatch 'height:\s*calc\(124rpx\s*\+\s*var\(--status-bar-height,\s*0px\)\)') { throw 'Header does not preserve the approved visual height above the system status bar.' }
|
||||
if ($header -notmatch 'padding-top:\s*var\(--status-bar-height,\s*0px\)') { throw 'Header does not reserve the real system status-bar height.' }
|
||||
if ($tabbar -match '/static/icons/tab-') { throw 'Tabbar still references rejected legacy tab assets.' }
|
||||
@@ -55,20 +54,20 @@ if ($tabbar -notmatch 'safe-area-inset-bottom') { throw 'Tabbar has no Android s
|
||||
if ($tabbar -notmatch 'font-size:\s*30rpx') { throw 'Tabbar label size does not match the approved visual weight.' }
|
||||
if ($tabbar -notmatch 'width:\s*64rpx') { throw 'Tabbar icon size does not match the approved visual weight.' }
|
||||
|
||||
$page = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/genealogy/index.vue')
|
||||
$page = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages/genealogy/g01-my-genealogies.vue')
|
||||
if ($page -match "from '@/utils/api\.js'") { throw 'G-01 visual phase must not call the remote API.' }
|
||||
foreach ($state in @('isLoading', 'hasGenealogies', 'createdGenealogies', 'joinedGenealogies')) {
|
||||
if ($page -notmatch $state) { throw "G-01 is missing presentation state: $state" }
|
||||
}
|
||||
foreach ($asset in @('tree-v2.png', 'members-v2.png', 'generation-poem-v2.png', 'application-v2.png', 'add-v2.png')) {
|
||||
foreach ($asset in @('shortcut-tree.png', 'shortcut-members.png', 'shortcut-generation-poem.png', 'shortcut-application.png', 'add.png')) {
|
||||
if ($page -notmatch [regex]::Escape($asset)) { throw "G-01 does not consume $asset" }
|
||||
}
|
||||
if ($page -notmatch 'genealogy-current-slip-frame\.png') { throw 'G-01 does not use the approved current genealogy frame asset.' }
|
||||
foreach ($token in @('current-summary', 'current-meta-item', 'current-seal-frame', 'location-v1.png', 'member-meta-v1.png', 'admin-v1.png', 'create-cloud-v2.png')) {
|
||||
if ($page -notmatch 'current-slip-frame\.png') { throw 'G-01 does not use the approved current genealogy frame asset.' }
|
||||
foreach ($token in @('current-summary', 'current-meta-item', 'current-seal-frame', 'meta-location.png', 'meta-member.png', 'meta-admin.png', 'create-cloud.png')) {
|
||||
if ($page -notmatch $token) { throw "G-01 current panel is missing $token" }
|
||||
}
|
||||
if ($page -notmatch 'width:\s*82rpx') { throw 'G-01 shortcut icons remain below the reference visual size.' }
|
||||
foreach ($asset in @('paper-rice-texture-v2.jpg', 'footer-mountain-bamboo.png', 'genealogy-section-divider-v2.png')) {
|
||||
foreach ($asset in @('page-paper.jpg', 'footer-mountain-bamboo.png', 'section-divider.png')) {
|
||||
if ($page -notmatch [regex]::Escape($asset)) { throw "G-01 does not consume the approved background asset: $asset" }
|
||||
}
|
||||
if ($page -match 'footer-mountain-bamboo-v2\.png') { throw 'G-01 still uses the solid mountain footer asset instead of the translucent watercolor landscape.' }
|
||||
@@ -77,13 +76,13 @@ if ($page -notmatch '(?s)\.page-footer-landscape\s*\{.*?opacity:\s*0\.5') { thro
|
||||
if ($page -match 'background:\s*rgba\(255,\s*249,\s*238,\s*\.88\)') { throw 'G-01 current genealogy card retains a rectangular pale backing behind its transparent corners.' }
|
||||
|
||||
$card = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'components/GenealogyCard.vue')
|
||||
if ($card -notmatch 'genealogy-list-slip-frame\.png') { throw 'G-01 list rows do not use the approved slip frame asset.' }
|
||||
if ($card -notmatch 'list-slip-frame\.png') { throw 'G-01 list rows do not use the approved slip frame asset.' }
|
||||
if ($card -match 'background:\s*rgba\(255,\s*249,\s*238,\s*\.(9|96)\)') { throw 'G-01 list cards retain a rectangular pale backing behind their transparent corners.' }
|
||||
foreach ($token in @('seal-row-frame-v1.png', 'card-main', 'card-title-row', 'card-detail-row', 'card-updated')) {
|
||||
foreach ($token in @('row-seal-frame.png', 'card-main', 'card-title-row', 'card-detail-row', 'card-updated')) {
|
||||
if ($card -notmatch $token) { throw "G-01 list card is missing $token" }
|
||||
}
|
||||
if ($card -match 'background:\s*#b93b2e') { throw 'G-01 list seal is still a plain CSS red block.' }
|
||||
foreach ($asset in @('location-v1.png', 'member-meta-v1.png', 'admin-v1.png', 'seal-current-frame-v1.png', 'seal-row-frame-v1.png', 'create-cloud-v2.png')) {
|
||||
foreach ($asset in @('meta-location.png', 'meta-member.png', 'meta-admin.png', 'current-seal-frame.png', 'row-seal-frame.png', 'create-cloud.png')) {
|
||||
if ($page -notmatch [regex]::Escape($asset) -and $card -notmatch [regex]::Escape($asset)) {
|
||||
throw "G-01 does not consume $asset"
|
||||
}
|
||||
|
||||
+30
-22
@@ -13,17 +13,21 @@ $requiredFiles = @(
|
||||
'utils/api.js',
|
||||
'components/AppTabbar.vue',
|
||||
'components/PageHeader.vue',
|
||||
'pages/auth/login.vue',
|
||||
'pages/genealogy/index.vue',
|
||||
'pages/genealogy/create.vue',
|
||||
'pages/genealogy/detail.vue',
|
||||
'pages/genealogy/search.vue',
|
||||
'pages/genealogy/applications.vue',
|
||||
'pages/tree/index.vue',
|
||||
'pages/member/detail.vue',
|
||||
'pages/family/index.vue',
|
||||
'pages/profile/index.vue',
|
||||
'pages/notification/index.vue',
|
||||
'pages/auth/a01-entry.vue',
|
||||
'pages/auth/a02-login.vue',
|
||||
'pages/genealogy/g01-my-genealogies.vue',
|
||||
'pages/genealogy/g03-create-genealogy.vue',
|
||||
'pages/genealogy/g04-first-ancestor.vue',
|
||||
'pages/genealogy/g05-genealogy-overview.vue',
|
||||
'pages/genealogy/g06-search-genealogies.vue',
|
||||
'pages/genealogy/g10-application-review.vue',
|
||||
'pages/tree/t01-tree-overview.vue',
|
||||
'pages/tree/t03-member-profile.vue',
|
||||
'pages/family/f01-family-feed.vue',
|
||||
'pages/family/f02-publish-feed.vue',
|
||||
'pages/skeleton/content-list-skeleton.vue',
|
||||
'pages/profile/m01-profile-home.vue',
|
||||
'pages/notification/n01-message-center.vue',
|
||||
'static/icons/tab-genealogy.png',
|
||||
'static/icons/tab-family.png',
|
||||
'static/icons/tab-profile.png'
|
||||
@@ -37,17 +41,21 @@ if ($missing) {
|
||||
$pages = Get-Content -Raw -Encoding UTF8 (Join-Path $root 'pages.json') | ConvertFrom-Json
|
||||
$paths = @($pages.pages | ForEach-Object { $_.path })
|
||||
$requiredRoutes = @(
|
||||
'pages/auth/login',
|
||||
'pages/genealogy/index',
|
||||
'pages/genealogy/create',
|
||||
'pages/genealogy/detail',
|
||||
'pages/genealogy/search',
|
||||
'pages/genealogy/applications',
|
||||
'pages/tree/index',
|
||||
'pages/member/detail',
|
||||
'pages/family/index',
|
||||
'pages/profile/index',
|
||||
'pages/notification/index'
|
||||
'pages/auth/a01-entry',
|
||||
'pages/auth/a02-login',
|
||||
'pages/genealogy/g01-my-genealogies',
|
||||
'pages/genealogy/g03-create-genealogy',
|
||||
'pages/genealogy/g04-first-ancestor',
|
||||
'pages/genealogy/g05-genealogy-overview',
|
||||
'pages/genealogy/g06-search-genealogies',
|
||||
'pages/genealogy/g10-application-review',
|
||||
'pages/tree/t01-tree-overview',
|
||||
'pages/tree/t03-member-profile',
|
||||
'pages/family/f01-family-feed',
|
||||
'pages/family/f02-publish-feed',
|
||||
'pages/skeleton/content-list-skeleton',
|
||||
'pages/profile/m01-profile-home',
|
||||
'pages/notification/n01-message-center'
|
||||
)
|
||||
|
||||
$missingRoutes = $requiredRoutes | Where-Object { $_ -notin $paths }
|
||||
|
||||
Reference in New Issue
Block a user