fix: rebuild A01 as responsive page
This commit is contained in:
+8
-8
@@ -7,24 +7,24 @@
|
|||||||
## Evidence
|
## Evidence
|
||||||
|
|
||||||
- The selected source image was opened and measured at `852 × 1846px`; it corresponds exactly to the supplied target screen proportions.
|
- The selected source image was opened and measured at `852 × 1846px`; it corresponds exactly to the supplied target screen proportions.
|
||||||
- `pages/auth/entry.vue` now imports that source image directly, scales it by width, and overlays only local interaction regions.
|
- `pages/auth/entry.vue` 已恢复为真实 DOM、分层背景与独立按钮;整图视觉层方案已撤销。
|
||||||
- The supplied current-page screenshot predates this change, so it cannot serve as implementation evidence for the corrected page.
|
- 现有截图分别对应整图方案之前和整图方案本身,均不能作为当前真实 DOM 版本的实现证据。
|
||||||
|
|
||||||
## Findings
|
## Findings
|
||||||
|
|
||||||
- [P1] Runtime comparison blocked.
|
- [P1] Runtime comparison blocked.
|
||||||
- Location: `pages/auth/entry.vue` at `430 × 932`.
|
- Location: `pages/auth/entry.vue` at `430 × 932`.
|
||||||
- Evidence: no post-change HBuilderX or Android screenshot is available.
|
- Evidence: no post-change HBuilderX or Android screenshot is available.
|
||||||
- Impact: the image import, viewport scaling, hit-region placement, and checked-agreement state cannot be visually confirmed in the target runtime.
|
- Impact: the真实 DOM 的宽度、间距、按钮比例和已勾选协议状态无法在目标运行时确认。
|
||||||
- Fix: refresh the A-01 page in HBuilderX at `430 × 932`, capture the unchecked state, then compare it with the source visual above.
|
- Fix: refresh the A-01 page in HBuilderX at `430 × 932`, capture the unchecked state, then compare it with the source visual above.
|
||||||
|
|
||||||
## Required fidelity surfaces
|
## Required fidelity surfaces
|
||||||
|
|
||||||
- Fonts and typography: supplied by the v3 source image; runtime rendering not yet captured.
|
- Fonts and typography: 真实 DOM 已实现;运行时渲染尚未截图。
|
||||||
- Spacing and layout rhythm: supplied by the v3 source image; runtime scaling not yet captured.
|
- Spacing and layout rhythm: 真实 DOM 已实现;运行时尺寸尚未截图。
|
||||||
- Colors and visual tokens: supplied by the v3 source image; runtime rendering not yet captured.
|
- Colors and visual tokens: 分层背景和红金按钮已实现;运行时尚未截图。
|
||||||
- Image quality and asset fidelity: source is imported directly; runtime sharpness and crop not yet captured.
|
- Image quality and asset fidelity: 分层本地资产已使用;运行时清晰度和裁切尚未截图。
|
||||||
- Copy and content: source includes the approved `登录` primary label; runtime rendering not yet captured.
|
- Copy and content: 主入口为 `登录`;运行时渲染尚未截图。
|
||||||
|
|
||||||
## Implementation Checklist
|
## Implementation Checklist
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
- 文件:[`screens/A01-启动登录引导-效果稿-v1-显式协议.png`](screens/A01-启动登录引导-效果稿-v1-显式协议.png)
|
- 文件:[`screens/A01-启动登录引导-效果稿-v1-显式协议.png`](screens/A01-启动登录引导-效果稿-v1-显式协议.png)
|
||||||
- 效果稿 v2:[`screens/A01-启动登录引导-效果稿-v2-独立注册.png`](screens/A01-启动登录引导-效果稿-v2-独立注册.png),记录此前“四个独立按钮”的尝试;该入口结构已失效,不作当前方案依据。
|
- 效果稿 v2:[`screens/A01-启动登录引导-效果稿-v2-独立注册.png`](screens/A01-启动登录引导-效果稿-v2-独立注册.png),记录此前“四个独立按钮”的尝试;该入口结构已失效,不作当前方案依据。
|
||||||
- 当前效果稿 v3:[`screens/A01-启动登录引导-效果稿-v3-文字注册入口.png`](screens/A01-启动登录引导-效果稿-v3-文字注册入口.png),体现本记录第 2 节的当前入口层级,也是 `pages/auth/entry.vue` 的运行时视觉源;不得再用 CSS 重画其中的家祠、云纹、标题、按钮框与山水。
|
- 当前效果稿 v3:[`screens/A01-启动登录引导-效果稿-v3-文字注册入口.png`](screens/A01-启动登录引导-效果稿-v3-文字注册入口.png),体现本记录第 2 节的当前入口层级;效果稿 v3 仅作视觉比对依据,`pages/auth/entry.vue` 必须使用真实页面结构还原,不得将整张效果图作为页面内容。
|
||||||
- 用途:保留本轮已确认的“家祠卷轴”欢迎页美术方向,不作为可直接还原的代码布局图,也不作为功能图标资产。
|
- 用途:保留本轮已确认的“家祠卷轴”欢迎页美术方向,不作为可直接还原的代码布局图,也不作为功能图标资产。
|
||||||
- 画面方向:朱砂家祠红头、暖宣纸主体、古金细线与云纹、墨褐标题、两侧淡墨建筑/竹影与底部山水。登录欢迎页后续必须使用独立的红头/宣纸背景组合,不复用 G01 的列表页大山水底图。
|
- 画面方向:朱砂家祠红头、暖宣纸主体、古金细线与云纹、墨褐标题、两侧淡墨建筑/竹影与底部山水。登录欢迎页后续必须使用独立的红头/宣纸背景组合,不复用 G01 的列表页大山水底图。
|
||||||
|
|
||||||
@@ -27,9 +27,9 @@
|
|||||||
- A-01 的登录与微信功能图标均需采用独立本地透明 PNG;微信标志只使用官方或许可来源的原色透明 PNG,不自行重绘或改色。账号密码与手机号验证码的表单图标归 A-02 设计时确定。
|
- A-01 的登录与微信功能图标均需采用独立本地透明 PNG;微信标志只使用官方或许可来源的原色透明 PNG,不自行重绘或改色。账号密码与手机号验证码的表单图标归 A-02 设计时确定。
|
||||||
- A-01 只设计欢迎、入口与协议未勾选提示。账号密码与手机号验证码表单均归 `A-02`,微信授权结果归 `A-03`,注册归 `A-04`,忘记密码归 `A-05`。
|
- A-01 只设计欢迎、入口与协议未勾选提示。账号密码与手机号验证码表单均归 `A-02`,微信授权结果归 `A-03`,注册归 `A-04`,忘记密码归 `A-05`。
|
||||||
- A-01 正常态必须展示两个按钮、注册文字入口和未勾选协议;点击任一需要授权的入口但未勾选协议时,仅提示“请先阅读并同意相关协议”,不视为用户已同意。
|
- A-01 正常态必须展示两个按钮、注册文字入口和未勾选协议;点击任一需要授权的入口但未勾选协议时,仅提示“请先阅读并同意相关协议”,不视为用户已同意。
|
||||||
- 固定设计画布为 `750rpx` 宽。v3 原图尺寸为 `852 × 1846px`,运行时按宽度等比显示为 `750 × 1625rpx`;原图中的朱砂家祠、标题、按钮、注册文字、协议行和山水留白均为不可拆分的可见视觉层。
|
- 页面根容器宽度必须为 100%,不可写死为 `750rpx` 或使用整张效果图。固定设计画布仍以 `750rpx` 为测量基准,运行时由真实 DOM 按当前屏宽响应式还原。
|
||||||
- 运行时只在 v3 对应位置叠加不可见热区:登录、微信登录、注册文字、协议勾选和协议文字。主按钮文案固定为“登录”,不得再替换为“账号密码登录”。
|
- 朱砂家祠头图高 244rpx;标题区在头图下方保留 196rpx 起始留白。操作区左右内边距 100rpx,主按钮高度 124rpx,微信按钮与主按钮间距 32rpx,主按钮文案固定为“登录”。
|
||||||
- 320 × 568 时页面允许纵向滚动;不可使用根容器 `overflow: hidden` 截断 v3 底部协议行或系统安全区。
|
- 注册文字在微信按钮下方 70rpx;协议行在注册入口下方 160rpx,底部内边距包含 `env(safe-area-inset-bottom)`。320 × 568 时页面允许纵向滚动,根容器不得以 `overflow: hidden` 截断协议行或系统安全区。
|
||||||
- 仅作静态设计验证,不代表 uni-app 运行时验收;页面实现后仍须在 Android 320 × 568、360 × 640、360 × 800、412 × 915 上重新验收。
|
- 仅作静态设计验证,不代表 uni-app 运行时验收;页面实现后仍须在 Android 320 × 568、360 × 640、360 × 800、412 × 915 上重新验收。
|
||||||
|
|
||||||
| 状态 | 触发 | A-01 可见结果 | 去向 |
|
| 状态 | 触发 | A-01 可见结果 | 去向 |
|
||||||
@@ -44,13 +44,13 @@
|
|||||||
|
|
||||||
| 资产 | 用途 | 来源或生成提示 | 尺寸与验收 |
|
| 资产 | 用途 | 来源或生成提示 | 尺寸与验收 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| `docs/design/screens/A01-启动登录引导-效果稿-v3-文字注册入口.png` | A-01 当前完整可见视觉源 | 已归档并由用户确认的 v3 效果稿;页面通过本地导入按宽度等比显示 | `852 × 1846px` PNG;当前 A-01 必须直接使用,不重绘拆分元素 |
|
| `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` | 先前手工分层方案的保留资产 | 2026-07-13 内置图像生成 | 不删除;当前 A-01 不消费,后续页面若使用须另行设计确认 |
|
| `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 的图标已包含在 v3 视觉源内;若后续单独使用微信图标,仍须保留 Icons8 署名链接 |
|
| `static/assets/icons/auth/login-outline-v1.png`、`static/assets/icons/auth/wechat-licensed-v1.png` | A-01 两个按钮图标 | 登录图标复用项目既有资产;微信图标来源与许可见旧记录 | 当前 A-01 使用;微信图标免费使用须在应用“关于/设置”及应用商店描述中保留 Icons8 署名链接 |
|
||||||
|
|
||||||
## 4. 静态设计验收与剩余缺口
|
## 4. 静态设计验收与剩余缺口
|
||||||
|
|
||||||
- 静态设计验收已覆盖 320 × 568、360 × 640、360 × 800、412 × 915;四个尺寸均保持两个大按钮与单行文字注册入口。A-01 本地页的可见层以当前效果稿 v3 直接显示,防止运行时重新拼装后偏离该验收画面。
|
- 静态设计验收已覆盖 320 × 568、360 × 640、360 × 800、412 × 915;四个尺寸均保持两个大按钮与单行文字注册入口。A-01 本地页以真实 DOM 还原 v3 的层级和比例,运行时仍须截图对比,不得以整图页面替代。
|
||||||
- 归档文件:[320 × 568](screens/A01-启动登录引导-栅格验收-320x568.png)、[360 × 640](screens/A01-启动登录引导-栅格验收-360x640.png)、[360 × 800](screens/A01-启动登录引导-栅格验收-360x800.png)、[412 × 915](screens/A01-启动登录引导-栅格验收-412x915.png)。
|
- 归档文件:[320 × 568](screens/A01-启动登录引导-栅格验收-320x568.png)、[360 × 640](screens/A01-启动登录引导-栅格验收-360x640.png)、[360 × 800](screens/A01-启动登录引导-栅格验收-360x800.png)、[412 × 915](screens/A01-启动登录引导-栅格验收-412x915.png)。
|
||||||
- 此结论只验证设计稿与固定栅格,不替代 uni-app 页面实现后的 Android 运行时验收。
|
- 此结论只验证设计稿与固定栅格,不替代 uni-app 页面实现后的 Android 运行时验收。
|
||||||
- 仍未确定《家谱用户协议》与《隐私政策》的最终页面去向及返回路径;在这两页完成设计前,A-01 不得标记为完整设计完成。
|
- 仍未确定《家谱用户协议》与《隐私政策》的最终页面去向及返回路径;在这两页完成设计前,A-01 不得标记为完整设计完成。
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# A-01 V3 Visual Fidelity Implementation Plan
|
# A-01 V3 Visual Fidelity Implementation Plan
|
||||||
|
|
||||||
|
> 状态:已失效。用户否决“整张效果图作为页面视觉层”的方案;当前 A-01 必须以真实 DOM 还原 v3,见 `docs/design/A01_启动登录引导_设计记录.md`。
|
||||||
|
|
||||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
**Goal:** Make the running A-01 page reproduce the selected `A01-启动登录引导-效果稿-v3-文字注册入口.png` at mobile width while preserving its existing local-only interactions.
|
**Goal:** Make the running A-01 page reproduce the selected `A01-启动登录引导-效果稿-v3-文字注册入口.png` at mobile width while preserving its existing local-only interactions.
|
||||||
|
|||||||
+1
-1
@@ -107,4 +107,4 @@ powershell -ExecutionPolicy Bypass -File tests\vue3-entry.ps1
|
|||||||
- 所有后续页面效果图必须先保存到 `docs/design/screens/`,并在对应页面设计记录写明用途、状态和验收缺口;未完成归档不得展示为可推进的设计成果。
|
- 所有后续页面效果图必须先保存到 `docs/design/screens/`,并在对应页面设计记录写明用途、状态和验收缺口;未完成归档不得展示为可推进的设计成果。
|
||||||
- G-01 已于 2026-07-13 经用户确认结项;当前进入 D2 / A-01 的设计工作,接口、真实登录和 Android 打包仍暂停。
|
- G-01 已于 2026-07-13 经用户确认结项;当前进入 D2 / A-01 的设计工作,接口、真实登录和 Android 打包仍暂停。
|
||||||
- A-01 入口页与 A-02 双标签登录页已于 2026-07-13 落地本地 UI:路由入口为 `pages/auth/entry`;只有在 A-01 显式勾选协议后才可进入 A-02。页面不调用接口、不写登录态、不跳转家谱;微信、注册、协议、忘记密码和验证码仅提示待相应页面或能力完成。A-01/A-02 运行时四尺寸验收仍待执行。
|
- A-01 入口页与 A-02 双标签登录页已于 2026-07-13 落地本地 UI:路由入口为 `pages/auth/entry`;只有在 A-01 显式勾选协议后才可进入 A-02。页面不调用接口、不写登录态、不跳转家谱;微信、注册、协议、忘记密码和验证码仅提示待相应页面或能力完成。A-01/A-02 运行时四尺寸验收仍待执行。
|
||||||
- A-01 首次本地预览与 v3 效果稿存在红头高度、按钮宽度和垂直节奏偏差。现已改为直接使用 `docs/design/screens/A01-启动登录引导-效果稿-v3-文字注册入口.png` 作为可见视觉层,并仅保留透明交互热区;下一次 Android 预览必须以该 v3 截图作同尺寸对比。
|
- A-01 首次本地预览与 v3 效果稿存在红头高度、按钮宽度和垂直节奏偏差。整图视觉层方案已被用户否决并撤销;现以真实 DOM、分层背景和按钮图标重建页面,下一次 Android 预览必须以 v3 截图作同尺寸对比。
|
||||||
|
|||||||
+252
-59
@@ -1,19 +1,60 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="entry-page">
|
<view class="auth-page entry-page">
|
||||||
<image class="guide-art" :src="entryGuideVisual" mode="widthFix" />
|
<image class="paper-background" src="/static/assets/backgrounds/auth-rice-paper-v1.jpg" mode="aspectFill" />
|
||||||
|
<image class="scenery-background" src="/static/assets/backgrounds/auth-ink-scenery-v1.png" mode="aspectFill" />
|
||||||
|
|
||||||
<view class="entry-hit entry-login-hit" @click="openLogin" />
|
<view class="auth-content">
|
||||||
<view class="entry-hit entry-wechat-hit" @click="prepareWechatLogin" />
|
<view class="auth-header">
|
||||||
<view class="entry-hit entry-register-hit" @click="prepareRegister" />
|
<image class="header-background" src="/static/assets/backgrounds/auth-ancestral-header-v1.png" mode="aspectFill" />
|
||||||
<view class="entry-hit entry-agreement-hit" @click="toggleAgreement" />
|
<image class="header-seal" src="/static/assets/icons/brand/jiapu-seal-logo-header.png" mode="aspectFit" />
|
||||||
<view class="entry-hit entry-agreement-copy-hit" @click.stop="prepareAgreement" />
|
</view>
|
||||||
<view v-if="agreed" class="agreement-confirmed">✓</view>
|
|
||||||
|
<view class="brand-intro">
|
||||||
|
<view class="title-decoration">
|
||||||
|
<view class="cloud cloud-left" />
|
||||||
|
<text class="brand-title">家谱</text>
|
||||||
|
<view class="cloud cloud-right" />
|
||||||
|
</view>
|
||||||
|
<view class="gold-divider"><view class="divider-knot">⌘</view></view>
|
||||||
|
<text class="brand-subtitle">为家族留存可传承的记忆</text>
|
||||||
|
<view class="gold-divider"><view class="divider-knot">⌘</view></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="entry-actions">
|
||||||
|
<view class="auth-button primary-button" hover-class="button-hover" @click="openLogin">
|
||||||
|
<image class="button-icon" src="/static/assets/icons/auth/login-outline-v1.png" mode="aspectFit" />
|
||||||
|
<text>登录</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="auth-button secondary-button" hover-class="button-hover" @click="prepareWechatLogin">
|
||||||
|
<image class="button-icon wechat-icon" src="/static/assets/icons/auth/wechat-licensed-v1.png" mode="aspectFit" />
|
||||||
|
<text>微信登录</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="register-link" hover-class="link-hover" @click="prepareRegister">
|
||||||
|
<view class="link-line" />
|
||||||
|
<text>还没有账号?<text class="register-emphasis">注册账号</text></text>
|
||||||
|
<view class="link-line" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="agreement-row" @click="toggleAgreement">
|
||||||
|
<view class="agreement-check" :class="{ checked: agreed }">
|
||||||
|
<text v-if="agreed">✓</text>
|
||||||
|
</view>
|
||||||
|
<view class="agreement-copy">
|
||||||
|
<text>我已阅读并同意</text>
|
||||||
|
<text class="agreement-link" @click.stop="prepareAgreement">《用户协议》</text>
|
||||||
|
<text>与</text>
|
||||||
|
<text class="agreement-link" @click.stop="prepareAgreement">《隐私政策》</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import entryGuideVisual from '@/docs/design/screens/A01-启动登录引导-效果稿-v3-文字注册入口.png'
|
|
||||||
|
|
||||||
const agreed = ref(false)
|
const agreed = ref(false)
|
||||||
|
|
||||||
@@ -48,67 +89,219 @@ const prepareAgreement = () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.entry-page {
|
.auth-page {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 750rpx;
|
min-height: 100vh;
|
||||||
min-height: 1625rpx;
|
background: #f7f1e6;
|
||||||
background: #f9f5ed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.guide-art {
|
.paper-background,
|
||||||
display: block;
|
.scenery-background {
|
||||||
width: 750rpx;
|
|
||||||
height: 1625rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-hit {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paper-background { opacity: 0.96; }
|
||||||
|
.scenery-background { opacity: 0.82; }
|
||||||
|
|
||||||
|
.auth-content {
|
||||||
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
min-height: 100vh;
|
||||||
|
padding-bottom: calc(44rpx + env(safe-area-inset-bottom));
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-login-hit {
|
.auth-header {
|
||||||
top: 799rpx;
|
position: relative;
|
||||||
left: 99rpx;
|
height: 244rpx;
|
||||||
width: 552rpx;
|
overflow: hidden;
|
||||||
height: 126rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-wechat-hit {
|
.header-background {
|
||||||
top: 960rpx;
|
width: 100%;
|
||||||
left: 99rpx;
|
height: 100%;
|
||||||
width: 552rpx;
|
|
||||||
height: 126rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.entry-register-hit {
|
.header-seal {
|
||||||
top: 1155rpx;
|
|
||||||
left: 200rpx;
|
|
||||||
width: 350rpx;
|
|
||||||
height: 72rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-agreement-hit {
|
|
||||||
top: 1362rpx;
|
|
||||||
left: 126rpx;
|
|
||||||
width: 60rpx;
|
|
||||||
height: 60rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entry-agreement-copy-hit {
|
|
||||||
top: 1362rpx;
|
|
||||||
left: 190rpx;
|
|
||||||
width: 450rpx;
|
|
||||||
height: 60rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.agreement-confirmed {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2;
|
top: 44rpx;
|
||||||
top: 1365rpx;
|
left: 50%;
|
||||||
left: 134rpx;
|
width: 136rpx;
|
||||||
color: #b7170d;
|
height: 136rpx;
|
||||||
font-size: 38rpx;
|
transform: translateX(-50%);
|
||||||
font-weight: 700;
|
|
||||||
line-height: 52rpx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.brand-intro {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 196rpx 56rpx 0;
|
||||||
|
color: #3f2c1d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-decoration {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-title {
|
||||||
|
margin: 0 24rpx;
|
||||||
|
font-family: STKaiti, KaiTi, serif;
|
||||||
|
font-size: 112rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: 12rpx;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cloud {
|
||||||
|
position: relative;
|
||||||
|
width: 54rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
border: 3rpx solid #dca34d;
|
||||||
|
border-top: 0;
|
||||||
|
border-radius: 0 0 26rpx 26rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cloud::before,
|
||||||
|
.cloud::after {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -3rpx;
|
||||||
|
width: 22rpx;
|
||||||
|
height: 22rpx;
|
||||||
|
border: 3rpx solid #dca34d;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-radius: 50% 50% 0 0;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
.cloud::before { left: 5rpx; }
|
||||||
|
.cloud::after { right: 5rpx; }
|
||||||
|
.cloud-right { transform: scaleX(-1); }
|
||||||
|
|
||||||
|
.gold-divider {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 430rpx;
|
||||||
|
height: 1rpx;
|
||||||
|
margin: 30rpx 0;
|
||||||
|
background: #d5a34f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider-knot {
|
||||||
|
padding: 0 14rpx;
|
||||||
|
color: #d5a34f;
|
||||||
|
background: #f8f2e9;
|
||||||
|
font-size: 32rpx;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-subtitle {
|
||||||
|
color: #624631;
|
||||||
|
font-family: STKaiti, KaiTi, serif;
|
||||||
|
font-size: 36rpx;
|
||||||
|
letter-spacing: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry-actions {
|
||||||
|
margin: 130rpx 100rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-button {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
height: 124rpx;
|
||||||
|
border: 2rpx solid #d8ad63;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
font-family: STKaiti, KaiTi, serif;
|
||||||
|
font-size: 42rpx;
|
||||||
|
letter-spacing: 5rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.primary-button {
|
||||||
|
border-color: #9e170e;
|
||||||
|
background: #b7170d;
|
||||||
|
box-shadow: inset 0 0 0 4rpx #d69b5f;
|
||||||
|
color: #fffaf0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary-button {
|
||||||
|
margin-top: 32rpx;
|
||||||
|
background: rgba(255, 252, 245, 0.82);
|
||||||
|
box-shadow: inset 0 0 0 3rpx rgba(229, 190, 133, 0.45);
|
||||||
|
color: #60442f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon {
|
||||||
|
width: 52rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wechat-icon { width: 56rpx; }
|
||||||
|
.button-hover { opacity: 0.84; }
|
||||||
|
|
||||||
|
.register-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 70rpx;
|
||||||
|
color: #60442f;
|
||||||
|
font-family: STKaiti, KaiTi, serif;
|
||||||
|
font-size: 30rpx;
|
||||||
|
letter-spacing: 2rpx;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-emphasis { color: #b7170d; }
|
||||||
|
|
||||||
|
.link-line {
|
||||||
|
width: 58rpx;
|
||||||
|
height: 1rpx;
|
||||||
|
margin: 0 18rpx;
|
||||||
|
background: #d5a34f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-hover { opacity: 0.65; }
|
||||||
|
|
||||||
|
.agreement-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 160rpx;
|
||||||
|
padding: 0 44rpx calc(32rpx + env(safe-area-inset-bottom));
|
||||||
|
color: #6b5a4a;
|
||||||
|
font-size: 24rpx;
|
||||||
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agreement-check {
|
||||||
|
display: flex;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 28rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
margin: 7rpx 12rpx 0 0;
|
||||||
|
border: 2rpx solid #b88d4b;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #fffaf0;
|
||||||
|
font-size: 20rpx;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agreement-check.checked { background: #b7170d; border-color: #b7170d; }
|
||||||
|
.agreement-copy { text-align: center; }
|
||||||
|
.agreement-link { color: #b7170d; }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -48,12 +48,13 @@ $login = Get-Content -LiteralPath $loginPath -Raw -Encoding utf8
|
|||||||
|
|
||||||
$accountPasswordLogin = ConvertFrom-Utf8Base64 '6LSm5Y+35a+G56CB55m75b2V'
|
$accountPasswordLogin = ConvertFrom-Utf8Base64 '6LSm5Y+35a+G56CB55m75b2V'
|
||||||
$wechatLogin = ConvertFrom-Utf8Base64 '5b6u5L+h55m75b2V'
|
$wechatLogin = ConvertFrom-Utf8Base64 '5b6u5L+h55m75b2V'
|
||||||
$registerLink = ConvertFrom-Utf8Base64 '6L+Y5rKh5pyJ6LSm5Y+377yf5rOo5YaM6LSm5Y+3'
|
$registerPrompt = ConvertFrom-Utf8Base64 '6L+Y5rKh5pyJ6LSm5Y+377yf'
|
||||||
|
$registerEntry = ConvertFrom-Utf8Base64 '5rOo5YaM6LSm5Y+3'
|
||||||
|
$loginEntry = ConvertFrom-Utf8Base64 '55m75b2V'
|
||||||
$agreementRequired = ConvertFrom-Utf8Base64 '6K+35YWI6ZiF6K+75bm25ZCM5oSP55u45YWz5Y2P6K6u'
|
$agreementRequired = ConvertFrom-Utf8Base64 '6K+35YWI6ZiF6K+75bm25ZCM5oSP55u45YWz5Y2P6K6u'
|
||||||
$wechatPending = ConvertFrom-Utf8Base64 '5b6u5L+h55m75b2V5Yqf6IO95YeG5aSH5Lit'
|
$wechatPending = ConvertFrom-Utf8Base64 '5b6u5L+h55m75b2V5Yqf6IO95YeG5aSH5Lit'
|
||||||
$registerPending = ConvertFrom-Utf8Base64 '5rOo5YaM6aG16Z2i5YeG5aSH5Lit'
|
$registerPending = ConvertFrom-Utf8Base64 '5rOo5YaM6aG16Z2i5YeG5aSH5Lit'
|
||||||
$agreementPending = ConvertFrom-Utf8Base64 '5Y2P6K6u6aG16Z2i5YeG5aSH5Lit'
|
$agreementPending = ConvertFrom-Utf8Base64 '5Y2P6K6u6aG16Z2i5YeG5aSH5Lit'
|
||||||
$entryVisualSource = ConvertFrom-Utf8Base64 'QC9kb2NzL2Rlc2lnbi9zY3JlZW5zL0EwMS3lkK/liqjnmbvlvZXlvJXlr7wt5pWI5p6c56i/LXYzLeaWh+Wtl+azqOWGjOWFpeWPoy5wbmc='
|
|
||||||
$smsLogin = ConvertFrom-Utf8Base64 '5omL5py66aqM6K+B56CB55m75b2V'
|
$smsLogin = ConvertFrom-Utf8Base64 '5omL5py66aqM6K+B56CB55m75b2V'
|
||||||
$forgotPassword = ConvertFrom-Utf8Base64 '5b+Y6K6w5a+G56CB'
|
$forgotPassword = ConvertFrom-Utf8Base64 '5b+Y6K6w5a+G56CB'
|
||||||
$getCode = ConvertFrom-Utf8Base64 '6I635Y+W6aqM6K+B56CB'
|
$getCode = ConvertFrom-Utf8Base64 '6I635Y+W6aqM6K+B56CB'
|
||||||
@@ -63,17 +64,17 @@ $forgotPasswordPending = ConvertFrom-Utf8Base64 '5b+Y6K6w5a+G56CB6aG16Z2i5YeG5aS
|
|||||||
$getCodePending = ConvertFrom-Utf8Base64 '6I635Y+W6aqM6K+B56CB5Yqf6IO95b6F5o6l5YWl'
|
$getCodePending = ConvertFrom-Utf8Base64 '6I635Y+W6aqM6K+B56CB5Yqf6IO95b6F5o6l5YWl'
|
||||||
$implicitAgreement = ConvertFrom-Utf8Base64 '55m75b2V5Y2z6KGo56S65ZCM5oSP'
|
$implicitAgreement = ConvertFrom-Utf8Base64 '55m75b2V5Y2z6KGo56S65ZCM5oSP'
|
||||||
|
|
||||||
foreach ($requiredEntryCopy in @($wechatLogin, $agreementRequired, $wechatPending, $registerPending, $agreementPending)) {
|
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 $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/login?agreed=1'" -Message 'A-01 account login must navigate with agreed=1'
|
||||||
Assert-Contains -Content $entry -Expected "import entryGuideVisual from '$entryVisualSource'" -Message 'A-01 must import the selected v3 visual source'
|
Assert-Contains -Content $entry -Expected "<text>$loginEntry</text>" -Message 'A-01 primary entry copy must be 登录'
|
||||||
foreach ($requiredClass in @('guide-art', 'entry-login-hit', 'entry-wechat-hit', 'entry-register-hit', 'entry-agreement-hit')) {
|
foreach ($requiredClass in @('auth-header', 'brand-intro', 'entry-actions', 'agreement-row')) {
|
||||||
Assert-Contains -Content $entry -Expected $requiredClass -Message "Missing A-01 interaction region: $requiredClass"
|
Assert-Contains -Content $entry -Expected $requiredClass -Message "Missing A-01 page structure: $requiredClass"
|
||||||
}
|
}
|
||||||
foreach ($forbiddenClass in @('auth-header', 'brand-intro', 'entry-actions', 'cloud')) {
|
foreach ($forbiddenClass in @('entryGuideVisual', 'guide-art', 'entry-hit', 'width: 750rpx', 'min-height: 1625rpx')) {
|
||||||
Assert-NotContains -Content $entry -Unexpected $forbiddenClass -Message "A-01 must not redraw the v3 visual with $forbiddenClass"
|
Assert-NotContains -Content $entry -Unexpected $forbiddenClass -Message "A-01 must not render the whole design image with $forbiddenClass"
|
||||||
}
|
}
|
||||||
if ($entry -match '(?s)\.auth-page\s*\{[^}]*overflow\s*:\s*hidden') {
|
if ($entry -match '(?s)\.auth-page\s*\{[^}]*overflow\s*:\s*hidden') {
|
||||||
throw 'A-01 must allow vertical scrolling on small screens'
|
throw 'A-01 must allow vertical scrolling on small screens'
|
||||||
|
|||||||
@@ -23,12 +23,13 @@ foreach ($rule in $rules) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$layoutRules = @(
|
$layoutRules = @(
|
||||||
(ConvertFrom-Utf8Base64 '5Zu65a6a6K6+6K6h55S75biD5Li6IGA3NTBycHhgIOWuvQ=='),
|
(ConvertFrom-Utf8Base64 '6aG16Z2i5qC55a655Zmo5a695bqm5b+F6aG75Li6IDEwMCU='),
|
||||||
(ConvertFrom-Utf8Base64 'ODUyIMOXIDE4NDZweA=='),
|
(ConvertFrom-Utf8Base64 '5pyx56CC5a6256Wg5aS05Zu+6auYIDI0NHJweA=='),
|
||||||
(ConvertFrom-Utf8Base64 'NzUwIMOXIDE2MjVycHg='),
|
(ConvertFrom-Utf8Base64 '5pON5L2c5Yy65bem5Y+z5YaF6L656LedIDEwMHJweA=='),
|
||||||
(ConvertFrom-Utf8Base64 '6L+Q6KGM5pe26KeG6KeJ5rqQ'),
|
(ConvertFrom-Utf8Base64 '5Li75oyJ6ZKu6auY5bqmIDEyNHJweA=='),
|
||||||
(ConvertFrom-Utf8Base64 '5Li75oyJ6ZKu5paH5qGI5Zu65a6a5Li64oCc55m75b2V4oCd'),
|
(ConvertFrom-Utf8Base64 '5Y2P6K6u6KGM5Zyo5rOo5YaM5YWl5Y+j5LiL5pa5IDE2MHJweA=='),
|
||||||
(ConvertFrom-Utf8Base64 'b3ZlcmZsb3c6IGhpZGRlbg==')
|
(ConvertFrom-Utf8Base64 'ZW52KHNhZmUtYXJlYS1pbnNldC1ib3R0b20p'),
|
||||||
|
(ConvertFrom-Utf8Base64 '5pWI5p6c56i/IHYzIOS7heS9nOinhuinieavlOWvueS+neaNrg==')
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($rule in $layoutRules) {
|
foreach ($rule in $layoutRules) {
|
||||||
@@ -37,9 +38,9 @@ foreach ($rule in $layoutRules) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$legacyLayoutRule = ConvertFrom-Utf8Base64 '5YaF5a655a695bqmIDYzOHJweA=='
|
$forbiddenLayoutRule = ConvertFrom-Utf8Base64 '6L+Q6KGM5pe26KeG6KeJ5rqQ'
|
||||||
if ($record -match [regex]::Escape($legacyLayoutRule)) {
|
if ($record -match [regex]::Escape($forbiddenLayoutRule)) {
|
||||||
throw "Legacy A01 layout rule remains: $legacyLayoutRule"
|
throw "Whole-image A01 layout rule remains: $forbiddenLayoutRule"
|
||||||
}
|
}
|
||||||
|
|
||||||
$currentStructure = [regex]::Match($record, '(?s)## 2\..*?(?=## 3\.)').Value
|
$currentStructure = [regex]::Match($record, '(?s)## 2\..*?(?=## 3\.)').Value
|
||||||
|
|||||||
Reference in New Issue
Block a user