Files
jiapuapp/docs/superpowers/plans/2026-07-21-a01-adaptive-structure-proof.md
T
2026-07-21 10:37:20 +08:00

369 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# A01 自适应结构证明 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 将 A01 从“整页合成背景 + 交互内容叠层定位”改为真正的纵向 Flex 文档流,并在当前 MuMu `720×1280 / 320dpi` 上证明默认密码态和验证码态无需滑动即可完整显示。
**Architecture:** A01 根容器只负责最小可用视口和自然溢出;固定比例品牌头图、独立宣纸内容区和登录内容形成真实布局层级。品牌印章可以在头图内部作为装饰定位,所有标题、输入、按钮和协议都在宣纸区正常流中,不再使用背景地标作为坐标。
**Tech Stack:** uni-app、Vue 3、SCSS、PowerShell 合同测试、Node.js CDP 辅助检查、HBuilderX Android、MuMu、ADB。
## Global Constraints
- 规格源:`docs/superpowers/specs/2026-07-21-project-mobile-viewport-adaptation-design.md`
- 本计划只覆盖 A01;用户确认 MuMu 画面前不迁移其他页面。
- 不改变登录业务、字段、校验、协议、反馈、路由和文案语义。
- 删除 A01 对整页合成背景、`scaleToFill``page-canvas``page-backdrop` 和整页网格叠层的依赖。
- 头图使用 `a01-vnext-header-v1.png`,保持原始 `824:340` 比例。
- 宣纸区使用 `auth-page-paper.jpg` 作可重复装饰背景,不承担内容坐标。
- MuMu 约 `360×640dp` 默认密码态和验证码态不滚动;`320×568`、错误、大字号或键盘空间不足时允许自然滚动但不得裁切。
- 交互目标最小高度 `44px`;禁止整页缩放。
- H5 只作结构辅助验证,最终视觉放行必须来自 MuMu 原生截图。
---
### Task 1: 撤销被否定的旧视口实验
**Files:**
- Revert: 当前工作区中上一版 viewport 实验修改的组件、页面、样式和测试
- Delete: `docs/superpowers/plans/2026-07-21-project-mobile-viewport-adaptation.md`
- Delete: `tests/mobile-viewport-page-contract.json`
- Delete: `tests/mobile-viewport-page-contract.ps1`
- Delete: `tests/mobile-viewport-runtime-smoke.js`
**Interfaces:**
- Consumes: 已提交的新设计规格 `2d33ee7`
- Produces: 无上一版实验残留的 A01 实施基线
- [ ] **Step 1: 核对待撤销集合**
Run: `git status --short``git diff --name-only`
Expected: 修改集合只包含上一版实验触及的组件、页面、样式、A 系列/共享测试和风险白名单。发现未知修改时停止整批恢复并逐文件保留。
- [ ] **Step 2: 精确恢复已确认属于旧实验的跟踪文件**
仅在 Step 1 的集合完全吻合后运行:
```powershell
$experimentFiles = git diff --name-only
foreach ($file in $experimentFiles) { git restore -- $file }
```
禁止运行 `git restore .`;不得恢复设计规格和本计划。
- [ ] **Step 3: 用 `apply_patch` 精确删除四个旧实验新增文件**
只删除本任务 Files 中列出的旧计划和三个 `mobile-viewport-*` 文件。
- [ ] **Step 4: 验证基线**
Run: `powershell -ExecutionPolicy Bypass -File tests/a01-a02-ui-contract.ps1`
Expected: `A01-LOGIN-MERGE-CONTRACT PASS`,且 `git status --short` 只显示本计划。
---
### Task 2: 用失败合同锁定新结构
**Files:**
- Modify: `tests/a01-a02-ui-contract.ps1`
- Test: `tests/a01-a02-ui-contract.ps1`
**Interfaces:**
- Produces: A01 头图、宣纸和正常流静态合同
- [ ] **Step 1: 替换旧坐标断言**
保留业务、文案、交互、按钮皮肤、Toast 和 Dialog 断言。删除要求整页背景、品牌印章网格对齐及 `--auth-paper-start` 的断言,加入:
```powershell
foreach ($required in @('class="auth-header"','class="auth-header__image"','a01-vnext-header-v1.png','mode="widthFix"','class="auth-paper"','auth-page-paper.jpg')) {
Assert-Contains -Content $entry -Expected $required -Message "A01 adaptive structure is missing: $required"
}
foreach ($forbidden in @('class="page-canvas"','class="page-backdrop"','a01-red-hall-ink-backdrop-v1.png','mode="scaleToFill"','--auth-paper-start','1665rpx')) {
Assert-NotContains -Content $entry -Unexpected $forbidden -Message "A01 still uses rejected page coordinates: $forbidden"
}
$pageRule = [regex]::Match($entry, '(?ms)^\.auth-page\s*\{(?<Body>.*?)^\}')
$paperRule = [regex]::Match($entry, '(?ms)^\.auth-paper\s*\{(?<Body>.*?)^\}')
$contentRule = [regex]::Match($entry, '(?ms)^\.login-content\s*\{(?<Body>.*?)^\}')
Assert-Contains $pageRule.Groups['Body'].Value 'display: flex;' 'A01 root must use flex flow.'
Assert-Contains $pageRule.Groups['Body'].Value 'min-height: var(--app-viewport-height);' 'A01 root must fill without locking content height.'
Assert-NotContains $pageRule.Groups['Body'].Value 'height: var(--app-viewport-height);' 'A01 root must not lock the viewport.'
Assert-Contains $paperRule.Groups['Body'].Value 'flex: 1;' 'A01 paper must receive remaining space.'
Assert-Contains $contentRule.Groups['Body'].Value 'justify-content: space-between;' 'A01 must distribute spare height in normal flow.'
Assert-NotContains $contentRule.Groups['Body'].Value 'grid-area:' 'A01 interactive content must not overlap page artwork.'
```
- [ ] **Step 2: 验证 RED**
Run: `powershell -ExecutionPolicy Bypass -File tests/a01-a02-ui-contract.ps1`
Expected: FAIL,提示缺少 `auth-header` 或仍存在 `page-canvas`
- [ ] **Step 3: 提交失败合同**
Run: `git add tests/a01-a02-ui-contract.ps1`,然后 `git commit -m "测试A01自适应页面结构"`
---
### Task 3: 建立最小全局视口原语
**Files:**
- Modify: `styles/global.scss`
**Interfaces:**
- Produces: `--app-viewport-height``--app-safe-top``--app-safe-bottom``--app-touch-min`
- Consumed by: `pages/auth/a01-entry.vue`
- [ ] **Step 1: 在现有 `page` 规则中加入变量**
```scss
page {
--app-viewport-height: 100vh;
--app-safe-top: env(safe-area-inset-top, 0px);
--app-safe-bottom: env(safe-area-inset-bottom, 0px);
--app-touch-min: 44px;
}
@supports (height: 100dvh) {
page { --app-viewport-height: 100dvh; }
}
```
本任务不增加全项目页面类,不修改共享组件或其他路由。
- [ ] **Step 2: 验证并提交**
Run: `git diff --check -- styles/global.scss`
Expected: exit 0,差异只有四个变量和 `100dvh` 能力覆盖。
Run: `git add styles/global.scss`,然后 `git commit -m "增加手机可用视口基础变量"`
---
### Task 4: 将 A01 重构为正常流
**Files:**
- Modify: `pages/auth/a01-entry.vue`
- Test: `tests/a01-a02-ui-contract.ps1`
**Interfaces:**
- Consumes: Task 3 的四个变量
- Produces: `.auth-header``.auth-header__image``.auth-paper`、正常流 `.login-content`
- [ ] **Step 1: 替换顶层模板**
```diff
- <view class="auth-page login-page">
- <view class="page-canvas">
- <image
- class="page-backdrop"
- src="/static/assets/modules/auth/opaque/a01-red-hall-ink-backdrop-v1.png"
- mode="scaleToFill"
- />
+ <view class="auth-page login-page">
+ <view class="auth-header">
+ <image
+ class="auth-header__image"
+ src="/static/assets/modules/auth/opaque/a01-vnext-header-v1.png"
+ mode="widthFix"
+ />
<image
class="brand-seal"
src="/static/assets/foundation/transparent/brand-seal.png"
mode="aspectFit"
/>
+ </view>
+ <view class="auth-paper">
<view class="login-content">
```
该局部替换后,现有 `.login-content` 的全部子节点及其紧随的两个闭合 `</view>` 不变:第一个仍关闭 `.login-content`,第二个改为关闭 `.auth-paper``verification-layer``feedback-toast` 继续保留在 `.auth-page` 根节点内。
- [ ] **Step 2: 写入页面骨架样式**
```scss
.auth-page {
display: flex;
flex-direction: column;
box-sizing: border-box;
width: 100%;
min-height: var(--app-viewport-height);
overflow-x: hidden;
background: #940400;
color: #493323;
}
.auth-header {
position: relative;
flex: 0 0 auto;
box-sizing: border-box;
width: 100%;
padding-top: var(--app-safe-top);
background: #940400;
}
.auth-header__image { display: block; width: 100%; height: auto; pointer-events: none; }
.brand-seal {
position: absolute;
top: calc(var(--app-safe-top) + clamp(8px, 2vw, 14px));
left: 50%;
width: clamp(60px, 19vw, 86px);
height: clamp(72px, 23vw, 104px);
transform: translateX(-50%);
pointer-events: none;
}
.auth-paper {
display: flex;
flex: 1;
box-sizing: border-box;
width: 100%;
padding-bottom: var(--app-safe-bottom);
background: #f7f0e5 url("/static/assets/foundation/opaque/auth-page-paper.jpg") center top / 100% auto repeat-y;
}
.login-content {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
box-sizing: border-box;
width: 100%;
max-width: 480px;
min-width: 0;
margin: 0 auto;
padding: clamp(10px, 2.2vh, 20px) clamp(24px, 8.5vw, 44px);
}
```
- [ ] **Step 3: 收敛结构高度而不建立页面坐标**
```scss
.login-heading { min-height: 56px; }
.login-tabs, .input-row, .form-secondary-row, .login-submit,
.wechat-login, .register-entry, .agreement-row { min-height: var(--app-touch-min); }
.login-submit, .wechat-login { height: var(--app-touch-min); }
.other-login-divider { min-height: 30px; }
```
删除旧视口固定 `height`、旧五个 `--auth-*height` 变量及对应 `@supports`。按钮内部皮肤与文案的局部网格叠放可以保留;Verification 和 Toast 等真实 Overlay 可以保留定位。
- [ ] **Step 4: 验证 GREEN**
Run:
```powershell
powershell -ExecutionPolicy Bypass -File tests/a01-a02-ui-contract.ps1
powershell -ExecutionPolicy Bypass -File tests/a01-asset-alpha-audit.ps1
git diff --check
```
Expected: 两个合同 PASSdiff check exit 0。
- [ ] **Step 5: 提交实现**
Run: `git add pages/auth/a01-entry.vue`,然后 `git commit -m "重构A01为自适应文档流"`
---
### Task 5: 修订多视口运行合同
**Files:**
- Modify: `tests/a01-responsive-runtime-smoke.js`
**Interfaces:**
- Consumes: `.auth-header__image``.auth-paper``.login-content`
- Produces: 六档视口结构、比例、首屏和可达性断言
- [ ] **Step 1: 采集新指标**
`320×568``360×616``360×640``360×800``412×915``480×1040` 读取 root/document scrollWidth/scrollHeight、头图运行尺寸和自然尺寸、header bottom、paper top、content top、agreement bottom。
- [ ] **Step 2: 写入准确断言**
```js
assert(metrics.scrollWidth <= size.width + 1)
assert.deepStrictEqual([metrics.headerNaturalWidth, metrics.headerNaturalHeight], [824, 340])
assert(Math.abs(metrics.headerImageHeight / metrics.headerImageWidth - 340 / 824) < 0.01)
assert(metrics.paperTop >= metrics.headerBottom - 1)
assert(metrics.contentTop >= metrics.paperTop)
if (size.width >= 360 && size.height >= 640) {
assert(metrics.rootScrollHeight <= size.height + 1)
assert(metrics.agreementBottom <= size.height + 1)
} else {
assert(metrics.agreementBottom <= metrics.documentScrollHeight + 1)
}
```
密码态和验证码态均执行首屏断言。保留图标、协议错误、Toast、Dialog 和登录方式切换测试。
- [ ] **Step 3: 运行辅助检查并提交**
前提:复用 HBuilderX 已运行的 `http://localhost:5173` 和 Chrome `9222`;不存在时报告阻塞,不打开浏览器冒充 Android。
Run: `node tests/a01-responsive-runtime-smoke.js`
Expected: `A01-RESPONSIVE-RUNTIME-SMOKE PASS`
Run: `git add tests/a01-responsive-runtime-smoke.js`,然后 `git commit -m "验证A01多视口自适应结构"`
---
### Task 6: MuMu 原生验收门
**Files:**
- Create ignored evidence: `%TEMP%\jiapuapp-audit\2026-07-21\A01-adaptive-*.png`
- Modify after user acceptance only: `docs/验收规划.md`
- Modify after user acceptance only: `docs/交接记录.md`
**Interfaces:**
- Consumes: HBuilderX Android 应用 `io.dcloud.HBuilder`
- Produces: 当前 MuMu 的密码、验证码、协议错误和键盘状态证据
- [ ] **Step 1: 确认设备**
```powershell
& 'C:\Users\Administrator\Desktop\HBuilderX\plugins\launcher-tools\tools\adbs\adb.exe' devices
& 'C:\Users\Administrator\Desktop\HBuilderX\plugins\launcher-tools\tools\adbs\adb.exe' -s emulator-5554 shell wm size
& 'C:\Users\Administrator\Desktop\HBuilderX\plugins\launcher-tools\tools\adbs\adb.exe' -s emulator-5554 shell wm density
```
Expected: `emulator-5554 device``720x1280``320`。按实际结果记录,不改变系统分辨率伪造验证。
- [ ] **Step 2: 截取密码态与验证码态**
确认 HBuilderX 热更新后重新进入 A01,随后运行:
```powershell
$evidence = Join-Path $env:TEMP 'jiapuapp-audit\2026-07-21'
New-Item -ItemType Directory -Force -Path $evidence | Out-Null
$adb = 'C:\Users\Administrator\Desktop\HBuilderX\plugins\launcher-tools\tools\adbs\adb.exe'
& $adb -s emulator-5554 shell screencap -p /sdcard/A01-adaptive-password.png
& $adb -s emulator-5554 pull /sdcard/A01-adaptive-password.png (Join-Path $evidence 'A01-adaptive-password.png')
```
切换验证码态后,将两处 `password` 明确替换为 `sms` 并再次执行。不得使用浏览器截图替代。
- [ ] **Step 3: 验证默认态不滑动**
密码态和验证码态分别记录滑动前截图,向上滑动后再截图;默认态内容位置不得移动。检查头图无拉伸、印章在头图内、标题完全位于宣纸、全部控件和协议完整、安全区无遮挡。
- [ ] **Step 4: 验证异常自然滚动**
触发未勾选协议错误并聚焦第二输入框。错误文案必须完整;键盘不得永久遮挡焦点字段和当前操作;需要时页面允许自然滚动,键盘收起后恢复合理位置。
- [ ] **Step 5: 用户视觉放行**
向用户展示 MuMu 原生截图。只有用户明确确认后才更新验收规划和交接记录;记录必须区分自动合同、当前 MuMu 已验证状态和其他真机未验证状态。未确认时不开始 A04/A05/A06。
- [ ] **Step 6: 最终回归**
```powershell
powershell -ExecutionPolicy Bypass -File tests/a01-a02-ui-contract.ps1
powershell -ExecutionPolicy Bypass -File tests/a01-asset-alpha-audit.ps1
node tests/a01-responsive-runtime-smoke.js
git diff --check
git status --short
```
Expected: 可运行项全部通过;只存在本阶段有意修改。用户确认后才提交验收记录,提交信息为 `记录A01安卓自适应验收`