修改未完成

This commit is contained in:
rain
2026-07-13 17:31:05 +08:00
parent 965fff1621
commit 355f47976a
95 changed files with 1112 additions and 721 deletions
+9 -9
View File
@@ -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') {
+11 -11
View File
@@ -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." }
+10 -10
View File
@@ -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"
+36
View File
@@ -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'
+64
View File
@@ -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'
+6 -6
View File
@@ -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) {
+38 -39
View File
@@ -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
View File
@@ -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 }