diff --git a/design-qa.md b/design-qa.md index 01717f9..9f82a44 100644 --- a/design-qa.md +++ b/design-qa.md @@ -3,17 +3,17 @@ - Source visual truth: `docs/design/screens/A01-启动登录引导-栅格验收-412x915.png` - Target state: `412 × 915`, agreement unchecked. - Static contract: passed on 2026-07-13. -- Runtime screenshot: first capture reviewed on 2026-07-13; second capture pending. +- Runtime screenshot: first capture reviewed on 2026-07-13; second capture pending after the ornamental-asset calibration. ## Evidence - The first `412 × 915` runtime capture confirms that the red-header height, divider width, both button frames and registration-entry height are close to the reference. - The same capture shows the seal too high, title clouds too wide, both button content groups too far right, and an agreement row that is too wide and high. -- The second calibration adds sub-element anchors for those differences; the whole-image layer, registration side lines and four-corner button brackets remain forbidden. +- The second calibration replaces the incorrect shared cloud artwork with three dedicated transparent assets: button corner flourish, divider center knot and title-side cloud. It also aligns the agreement checkbox and copy on one non-wrapping center line. ## Remaining runtime evidence -- [P1] Capture the unchecked A-01 page at `412 × 915` in HBuilderX or Android, without browser chrome, after the second calibration and compare it against the source at the same scale. +- [P1] Capture the unchecked A-01 page at `412 × 915` in HBuilderX or Android, without browser chrome, after the ornamental-asset calibration and compare it against the source at the same scale. - [P1] Capture `320 × 568` after scrolling to confirm the agreement row and safe area are not clipped. - Confirm that selecting the agreement enables only the existing A-02 login route; the other entries remain local prepared-state prompts. diff --git a/docs/design/A01_启动登录引导_设计记录.md b/docs/design/A01_启动登录引导_设计记录.md index be96f74..a118c18 100644 --- a/docs/design/A01_启动登录引导_设计记录.md +++ b/docs/design/A01_启动登录引导_设计记录.md @@ -36,13 +36,13 @@ | 朱砂家祠头图 | 高 139px | 高 253rpx | | 红头谱印 | 比头图顶边低约 38px | `top: 70rpx` | | 标题区起点 | 红头后约 82px | `padding-top: 150rpx` | -| 标题两侧云纹 | 紧贴标题两侧,不扩张标题组宽度 | `56rpx × 34rpx`,标题左右各 12rpx | -| 标题分隔饰线 | 宽约 234px | 宽 426rpx;上、下间距独立 | +| 标题两侧云纹 | 紧贴标题两侧,不扩张标题组宽度 | 独立透明素材 `auth-title-cloud-v1.png`,`64rpx × 40rpx`,标题左右各 12rpx | +| 标题分隔饰线 | 宽约 234px,中心为对称小结 | 宽 426rpx;中结使用独立透明素材 `auth-divider-knot-v1.png`,上、下间距独立 | | 两个按钮 | x=60px,宽约 291px,高约 65px | `margin: 95rpx 110rpx 0`,高 118rpx | | 两按钮间距 | 约 28px | `margin-top: 51rpx` | -| 按钮内框与内容组 | 内框距外边约 3px;图标与文字整体偏左 | `inset: 6rpx`,内容组 `translateX(-20rpx)` | +| 按钮内框与内容组 | 内框距外边约 3px,四角有卷草角花;图标与文字整体偏左 | `inset: 6rpx`;四角使用同一张 `auth-button-corner-v1.png` 镜像;内容组 `translateX(-20rpx)` | | 注册入口 | 微信按钮后约 56px;无左右短线 | `margin-top: 98rpx` | -| 协议行 | 注册入口后约 77px;文案不应撑宽整行 | `margin-top: 141rpx`,字号 20rpx,复选框 30rpx,加安全区 | +| 协议行 | 注册入口后约 77px;复选框与全部文案同一水平线 | `margin-top: 141rpx`,字号与行高均为 20rpx / 30rpx,复选框 30rpx,`align-items: center`、`white-space: nowrap`,加安全区 | - 上表是 A-01 运行时布局数值的唯一所有者。320 × 568 时页面允许纵向滚动,根容器不得以 `overflow: hidden` 截断协议行或系统安全区;底部内边距包含 `env(safe-area-inset-bottom)`。 - 仅作静态设计验证,不代表 uni-app 运行时验收;页面实现后仍须在 Android 320 × 568、360 × 640、360 × 800、412 × 915 上重新验收。 @@ -62,6 +62,9 @@ | `docs/design/screens/A01-启动登录引导-效果稿-v3-文字注册入口.png` | A-01 视觉比对依据 | 已归档并由用户确认的 v3 效果稿 | `852 × 1846px` PNG;仅作真实 DOM 页面还原和运行时验收对照,不直接作为页面内容 | | `static/assets/backgrounds/auth-ancestral-header-v1.png`、`auth-rice-paper-v1.jpg`、`auth-ink-scenery-v1.png` | A-01 分层页面背景 | 2026-07-13 内置图像生成 | 当前 A-01 使用;不得复用 G-01 背景 | | `static/assets/icons/auth/login-outline-v1.png`、`static/assets/icons/auth/wechat-licensed-v1.png` | A-01 两个按钮图标 | 登录图标复用项目既有资产;微信图标来源与许可见旧记录 | 当前 A-01 使用;微信图标免费使用须在应用“关于/设置”及应用商店描述中保留 Icons8 署名链接 | +| `static/assets/icons/auth/auth-button-corner-v1.png` | 两个入口按钮的四角卷草装饰 | 2026-07-13 根据 412 × 915 视觉基准生成,去绿幕后保存 | `160 × 160px` 透明 PNG;同一张素材镜像至四角 | +| `static/assets/icons/auth/auth-divider-knot-v1.png` | 标题上下金线的中心对称中结 | 2026-07-13 根据 412 × 915 视觉基准生成,去绿幕后保存 | `160 × 96px` 透明 PNG;不得改用长祥云 | +| `static/assets/icons/auth/auth-title-cloud-v1.png` | “家谱”标题左右祥云 | 2026-07-13 根据 412 × 915 视觉基准生成,去绿幕后保存 | `200 × 120px` 透明 PNG;右侧只允许镜像该素材 | ## 4. 静态设计验收与剩余缺口 @@ -70,7 +73,7 @@ - 此结论只验证设计稿与固定栅格,不替代 uni-app 页面实现后的 Android 运行时验收。 - 仍未确定《家谱用户协议》与《隐私政策》的最终页面去向及返回路径;在这两页完成设计前,A-01 不得标记为完整设计完成。 - 页面实现阶段仍须按本记录在 Android 实机或同等运行环境复核四个尺寸的安全区、滚动与文字折行。 -- 2026-07-13 已按 412 × 915 参考图完成第一轮真实 DOM 校准;运行时截图显示容器位置已接近基准,但红头谱印、标题云纹、按钮内容组和协议行仍有子元素偏差,已进入第二轮校准。未取得第二轮同尺寸截图确认前不得标记 A-01 完成。 +- 2026-07-13 已按 412 × 915 参考图完成第二轮子元素校准:已补齐按钮四角透明角花、分隔线中心中结、标题独立祥云,并将协议复选框与文案改为单行居中对齐。未取得第二轮同尺寸运行时截图确认前不得标记 A-01 完成。 ## 5. 推进约束 diff --git a/pages/auth/entry.vue b/pages/auth/entry.vue index 0e4166d..b32b4c7 100644 --- a/pages/auth/entry.vue +++ b/pages/auth/entry.vue @@ -11,25 +11,29 @@ - + 家谱 - + - + 为家族留存可传承的记忆 - + + + + + 登录 @@ -37,6 +41,10 @@ + + + + 微信登录 @@ -170,10 +178,7 @@ const prepareAgreement = () => { line-height: 1; } -.title-cloud { - width: 56rpx; - height: 34rpx; -} +.title-cloud { width: 64rpx; height: 40rpx; } .title-cloud-left { margin-right: 0; } .title-cloud-right { margin-left: 0; transform: scaleX(-1); } @@ -233,8 +238,22 @@ const prepareAgreement = () => { border-radius: 2rpx; content: ''; pointer-events: none; + z-index: 1; } +.button-corner-asset { + position: absolute; + z-index: 2; + width: 54rpx; + height: 54rpx; + pointer-events: none; +} + +.button-corner-asset--top-left { top: 4rpx; left: 4rpx; } +.button-corner-asset--top-right { top: 4rpx; right: 4rpx; transform: scaleX(-1); } +.button-corner-asset--bottom-left { bottom: 4rpx; left: 4rpx; transform: scaleY(-1); } +.button-corner-asset--bottom-right { right: 4rpx; bottom: 4rpx; transform: scale(-1); } + .entry-button--primary { border-color: #9e170e; background: #b7170d; @@ -259,7 +278,7 @@ const prepareAgreement = () => { .entry-button--primary .entry-button__icon { filter: brightness(0) invert(1); } .entry-button__content { position: relative; - z-index: 1; + z-index: 3; display: flex; align-items: center; transform: translateX(-20rpx); @@ -284,13 +303,13 @@ const prepareAgreement = () => { .agreement-row { display: flex; - align-items: flex-start; + align-items: center; justify-content: center; margin-top: 141rpx; padding: 0 44rpx calc(32rpx + env(safe-area-inset-bottom)); color: #6b5a4a; font-size: 20rpx; - line-height: 1.7; + line-height: 30rpx; } .agreement-check { @@ -301,7 +320,7 @@ const prepareAgreement = () => { box-sizing: border-box; width: 30rpx; height: 30rpx; - margin: 7rpx 12rpx 0 0; + margin: 0 12rpx 0 0; border: 2rpx solid #b88d4b; border-radius: 50%; color: #fffaf0; @@ -310,6 +329,12 @@ const prepareAgreement = () => { } .agreement-check.checked { background: #b7170d; border-color: #b7170d; } -.agreement-copy { text-align: center; } +.agreement-copy { + display: flex; + align-items: center; + line-height: 30rpx; + text-align: center; + white-space: nowrap; +} .agreement-link { color: #b7170d; } diff --git a/static/assets/icons/auth/auth-button-corner-v1.png b/static/assets/icons/auth/auth-button-corner-v1.png new file mode 100644 index 0000000..e302088 Binary files /dev/null and b/static/assets/icons/auth/auth-button-corner-v1.png differ diff --git a/static/assets/icons/auth/auth-divider-knot-v1.png b/static/assets/icons/auth/auth-divider-knot-v1.png new file mode 100644 index 0000000..8c7774e Binary files /dev/null and b/static/assets/icons/auth/auth-divider-knot-v1.png differ diff --git a/static/assets/icons/auth/auth-title-cloud-v1.png b/static/assets/icons/auth/auth-title-cloud-v1.png new file mode 100644 index 0000000..a93f82e Binary files /dev/null and b/static/assets/icons/auth/auth-title-cloud-v1.png differ diff --git a/tests/a01-a02-ui-contract.ps1 b/tests/a01-a02-ui-contract.ps1 index b787331..825850c 100644 --- a/tests/a01-a02-ui-contract.ps1 +++ b/tests/a01-a02-ui-contract.ps1 @@ -88,25 +88,43 @@ foreach ($requiredVisualAnchor in @( 'margin-top: 98rpx', 'margin-top: 141rpx', 'top: 70rpx', - 'width: 56rpx', + 'width: 64rpx', 'inset: 6rpx', 'entry-button__content', 'translateX(-20rpx)', + 'auth-button-corner-v1.png', + 'auth-divider-knot-v1.png', + 'auth-title-cloud-v1.png', + 'button-corner-asset', + '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', 'class="auth-button primary-button"')) { +foreach ($rejectedVisualConstruction in @('link-line', 'button-corner--legacy', 'class="auth-button primary-button"')) { 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-Contains -Content $entry -Expected '/static/assets/icons/action/create-cloud-v2.png' -Message 'A-01 title and divider must use the local auspicious-cloud asset' +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, '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) { + 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') { + 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' } diff --git a/tests/a01-asset-alpha-audit.ps1 b/tests/a01-asset-alpha-audit.ps1 index d872d6d..6e710d6 100644 --- a/tests/a01-asset-alpha-audit.ps1 +++ b/tests/a01-asset-alpha-audit.ps1 @@ -10,7 +10,10 @@ $backgrounds = @( ) $icons = @( 'static/assets/icons/auth/login-outline-v1.png', - 'static/assets/icons/auth/wechat-licensed-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' ) foreach ($asset in $backgrounds + $icons) { @@ -37,7 +40,13 @@ foreach ($asset in $icons) { } $bitmap.Dispose() - if ($width -ne 96 -or $height -ne 96) { throw "$asset must be 96 x 96px." } + $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) } + default { @(96, 96) } + } + if ($width -ne $expectedSize[0] -or $height -ne $expectedSize[1]) { throw "$asset must be $($expectedSize[0]) x $($expectedSize[1])px." } if (($corners | Where-Object { $_ -ne 0 }).Count -ne 0) { throw "$asset has opaque outer corners." } if ($visiblePixels -lt 80) { throw "$asset has no usable visible artwork." } Write-Output "PASS $asset transparent corners and visible artwork"