feat: unify project responsive layouts

This commit is contained in:
rain
2026-07-21 20:59:10 +08:00
parent a0d19f4aab
commit 5d99bae3f2
94 changed files with 2324 additions and 404 deletions
@@ -0,0 +1,162 @@
# G09 Nine-Slice Application Cards Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 修复 G09“我的申请”列表卡片装饰边框被纵向拉伸的问题,并收紧卡片内部及卡片之间的间距。
**Architecture:** 保留现有 `list-slip-frame.png` 真实素材和卡片 DOM 结构,将 `.application-card` 从整图背景拉伸改为 CSS `border-image` 九宫格切片。视觉合同负责固定切片值、边框宽度和紧凑布局,并禁止旧的 `100% 100%` 背景方案回归。
**Tech Stack:** uni-app、Vue 3、SCSS、PowerShell 静态合同、MuMu Android 模拟器
## Global Constraints
- 仅修改 G09 列表卡片,不修改空数据、加载和错误状态卡片。
- 使用 `/static/assets/modules/genealogy/transparent/list-slip-frame.png`,切片为 `24 32`
- 卡片边框宽度为 `18rpx 24rpx`,卡片最小高度为 `210rpx`,卡片间距为 `12rpx`
- 正文最小高度为 `174rpx`,网格间距为 `8rpx 14rpx`,内距为 `26rpx 28rpx 22rpx 40rpx`
- 保留 `.application-card__action``white-space: nowrap`
- 不修改文案、业务状态、模拟数据、路由和交互。
- 视觉验收只使用 MuMu Android 原生画面,不使用浏览器。
- 不执行 Git 操作,不启用多代理。
---
### Task 1: 固定 G09 九宫格卡片视觉合同
**Files:**
- Modify: `tests/g09-all-states-visual-contract.ps1`
- Test: `tests/g09-all-states-visual-contract.ps1`
**Interfaces:**
- Consumes: `pages/genealogy/g09-my-applications.vue``<style scoped lang="scss">` 的卡片样式。
- Produces: 对九宫格素材、切片值、边框宽度、紧凑尺寸及旧拉伸背景禁用规则的静态合同。
- [ ] **Step 1: 写入九宫格和紧凑间距断言**
在现有 `$rules` 中加入以下规则:
```powershell
'(?s)\.application-card\s*\{[^}]*min-height:\s*210rpx;[^}]*margin-bottom:\s*12rpx;[^}]*border-width:\s*18rpx 24rpx;[^}]*border-style:\s*solid;[^}]*border-color:\s*transparent;[^}]*border-image-source:\s*url\("/static/assets/modules/genealogy/transparent/list-slip-frame\.png"\);[^}]*border-image-slice:\s*24 32;[^}]*border-image-width:\s*18rpx 24rpx;[^}]*border-image-repeat:\s*stretch;[^}]*box-sizing:\s*border-box;',
'(?s)\.application-card__body\s*\{[^}]*min-height:\s*174rpx;[^}]*gap:\s*8rpx 14rpx;[^}]*padding:\s*26rpx 28rpx 22rpx 40rpx;'
```
在循环前加入旧方案禁用断言:
```powershell
if ($page -match '(?s)\.application-card\s*\{[^}]*background:\s*url\("/static/assets/modules/genealogy/transparent/list-slip-frame\.png"\)[^}]*100%\s+100%') {
throw 'G09 application card must not stretch the complete frame asset to 100% 100%'
}
```
- [ ] **Step 2: 运行合同并确认先失败**
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g09-all-states-visual-contract.ps1
```
Expected: FAIL,错误指出缺少 `210rpx``border-image-source` 或相关九宫格规则。
### Task 2: 将列表卡片改为九宫格边框
**Files:**
- Modify: `pages/genealogy/g09-my-applications.vue`
- Test: `tests/g09-all-states-visual-contract.ps1`
- Test: `tests/g09-document-flow-contract.ps1`
**Interfaces:**
- Consumes: Task 1 固定的样式合同及现有 `list-slip-frame.png`
- Produces: 不拉伸四角、保持文档流并缩短内部间隔的 G09 列表卡片。
- [ ] **Step 1: 替换 `.application-card` 样式**
`.application-card` 精确改为:
```scss
.application-card {
display: grid;
width: 100%;
min-height: 210rpx;
margin-bottom: 12rpx;
border-width: 18rpx 24rpx;
border-style: solid;
border-color: transparent;
border-image-source: url("/static/assets/modules/genealogy/transparent/list-slip-frame.png");
border-image-slice: 24 32;
border-image-width: 18rpx 24rpx;
border-image-repeat: stretch;
box-sizing: border-box;
}
```
- [ ] **Step 2: 收紧 `.application-card__body` 布局**
保留现有网格列定义和 `box-sizing`,将尺寸精确改为:
```scss
min-height: 174rpx;
gap: 8rpx 14rpx;
padding: 26rpx 28rpx 22rpx 40rpx;
```
- [ ] **Step 3: 运行 G09 视觉和文档流合同**
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g09-all-states-visual-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g09-document-flow-contract.ps1
```
Expected:
```text
G09-ALL-STATES-VISUAL-CONTRACT PASS
G09-DOCUMENT-FLOW-CONTRACT PASS
```
如文档流合同仍只接受 `background` 素材引用,将该合同的 G09 列表素材要求改为接受 `border-image-source`;主操作按钮素材要求保持不变。
### Task 3: 回归验证与 MuMu 原生验收
**Files:**
- Verify: `pages/genealogy/g09-my-applications.vue`
- Verify: `tests/g09-all-states-visual-contract.ps1`
- Verify: `tests/g09-document-flow-contract.ps1`
- Verify: `tests/g09-g10-business-state-contract.ps1`
**Interfaces:**
- Consumes: Task 2 的最终样式。
- Produces: 合同输出与 MuMu 原生截图证据,供用户决定当前页面是否通过。
- [ ] **Step 1: 运行三项聚焦合同**
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g09-all-states-visual-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g09-document-flow-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g09-g10-business-state-contract.ps1
```
Expected: 三项均输出 `PASS`
- [ ] **Step 2: 在 MuMu 中刷新 G09 并截图**
使用当前已连接的 `emulator-5554`,刷新 `/pages/genealogy/g09-my-applications`,通过 Android `screencap` 保存新截图到 `tmp/G09-nine-slice-native.png`
Expected: 三张列表卡片四角比例正常,边线不显得纵向膨胀;卡片之间和卡片内部更紧凑;“修改后重新提交”保持单行且没有越界。
- [ ] **Step 3: 对照用户上一张截图检查**
只检查以下视觉差异:
```text
1. 金色装饰角不再纵向拉长。
2. 每张卡片的上下留白减少,但文字不压线。
3. 三张卡片之间的距离缩短。
4. 时间、状态、操作文字没有重叠或溢出。
```
若任一项失败,仅调整本计划中 `.application-card``.application-card__body` 的边框/间距值,再重复三项合同和 MuMu 截图;不改其他页面或业务逻辑。
@@ -0,0 +1,265 @@
# G10 All-States Responsive Visual Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 修复 G10 列表卡框、双操作按钮和审核弹窗在 MuMu 中的拉伸、细条及标题正文连行问题,并覆盖全部审核状态。
**Architecture:** `AppButton` 提供默认关闭的紧凑九宫格变体,`AppDialog` 只在显式请求且存在双操作时消费该变体。G10 使用共享变体替换页面内直接图片按钮,并把列表、结果及状态卡全部迁移到真实素材九宫格边框。
**Tech Stack:** uni-app、Vue 3、SCSS、PowerShell 静态合同、MuMu Android 模拟器
## Global Constraints
- `AppButton.compact``AppDialog.compactActions` 默认值均为 `false`
- 紧凑按钮切片固定为 `56 300 fill`,边框宽度固定为 `10rpx 26rpx`
- G10 卡框切片固定为 `24 32`,边框宽度固定为 `18rpx 24rpx`
- G10 双操作继续左右并排,按钮尺寸为 `148rpx × 68rpx`
- G10 结果条尺寸为 `308rpx × 68rpx`
- 不修改文案、模拟数据、路由、状态枚举、校验和审核逻辑。
- 视觉验收只使用 MuMu Android 原生画面。
- 不执行 Git 操作,不启用多代理。
---
### Task 1: AppButton 紧凑九宫格变体
**Files:**
- Create: `tests/app-button-compact-contract.ps1`
- Modify: `components/AppButton.vue`
- Test: `tests/shared-interaction-accessibility-contract.ps1`
- Test: `tests/shared-component-document-flow-contract.ps1`
**Interfaces:**
- Consumes: `type: "primary" | "secondary"`、现有点击和禁用接口。
- Produces: `compact: Boolean = false`;根类 `app-button--compact`
- [ ] **Step 1: 写入失败合同**
合同读取 `components/AppButton.vue` 并要求以下标记:
```powershell
foreach ($token in @(
'compact: { type: Boolean, default: false }',
"'app-button--compact': compact",
'border-image-slice: 56 300 fill;',
'border-width: 10rpx 26rpx;',
'a01-scroll-primary-v3.png',
'a01-scroll-secondary-v3.png'
)) {
if (-not $button.Contains($token)) { throw "AppButton compact contract missing: $token" }
}
```
并断言 `.app-button--compact .app-button__skin``display: none`
- [ ] **Step 2: 运行合同并确认失败**
Run: `powershell -NoProfile -ExecutionPolicy Bypass -File tests/app-button-compact-contract.ps1`
Expected: FAIL,指出缺少 `compact`
- [ ] **Step 3: 实现最小变体**
在属性中加入:
```js
compact: { type: Boolean, default: false },
```
在根类对象中加入:
```js
'app-button--compact': compact
```
为主/次紧凑按钮分别设置对应卷轴 `border-image-source`,共同使用:
```scss
border-width: 10rpx 26rpx;
border-style: solid;
border-color: transparent;
border-image-slice: 56 300 fill;
border-image-width: 10rpx 26rpx;
border-image-repeat: stretch;
```
隐藏紧凑模式中的原图片皮肤,保留标签和原有事件。
- [ ] **Step 4: 运行组件合同**
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File tests/app-button-compact-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/shared-interaction-accessibility-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/shared-component-document-flow-contract.ps1
```
Expected: 三项均输出 `PASS`
### Task 2: AppDialog 标题分行与显式紧凑双操作
**Files:**
- Create: `tests/app-dialog-responsive-content-contract.ps1`
- Modify: `components/AppDialog.vue`
**Interfaces:**
- Consumes: Task 1 的 `AppButton.compact`
- Produces: `compactActions: Boolean = false``.app-dialog__copy` 独立文本容器。
- [ ] **Step 1: 写入失败合同**
合同要求:
```powershell
foreach ($token in @(
'compactActions: { type: Boolean, default: false }',
'class="app-dialog__copy"',
':compact="compactActions && showCancel"'
)) {
if (-not $dialog.Contains($token)) { throw "AppDialog responsive contract missing: $token" }
}
```
并要求 `.app-dialog__copy` 为纵向 flex、宽度 `100%`,标题和说明为 `display: block; width: 100%`
- [ ] **Step 2: 运行合同并确认失败**
Run: `powershell -NoProfile -ExecutionPolicy Bypass -File tests/app-dialog-responsive-content-contract.ps1`
Expected: FAIL,指出缺少 `compactActions`
- [ ] **Step 3: 实现弹窗布局**
使用 `.app-dialog__copy` 包裹 eyebrow、title 和 message;在属性中加入:
```js
compactActions: { type: Boolean, default: false },
```
两个 `AppButton` 都传入:
```vue
:compact="compactActions && showCancel"
```
单按钮因 `showCancel === false` 保持默认宽卷轴。
- [ ] **Step 4: 运行弹窗及共享合同**
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File tests/app-dialog-responsive-content-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/shared-interaction-accessibility-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/shared-component-document-flow-contract.ps1
```
Expected: 三项均输出 `PASS`
### Task 3: G10 列表、结果与状态卡迁移
**Files:**
- Modify: `pages/genealogy/g10-application-review.vue`
- Modify: `tests/g10-all-states-visual-contract.ps1`
- Modify: `tests/g10-document-flow-contract.ps1`
- Test: `tests/g08-g10-application-flow-contract.ps1`
- Test: `tests/g09-g10-business-state-contract.ps1`
**Interfaces:**
- Consumes: `AppButton compact``AppDialog compact-actions`
- Produces: G10 九宫格卡框、左右紧凑操作、九宫格结果条和完整状态卡。
- [ ] **Step 1: 将 G10 合同切换到新契约**
删除 `g10-document-flow-contract.ps1` 对以下旧值的要求:
```text
background ... list-slip-frame.png ... 100% 100%
padding: 44rpx 52rpx 29rpx 64rpx
```
在视觉/文档流合同中要求:
```text
border-image-source: url("/static/assets/modules/genealogy/transparent/list-slip-frame.png")
border-image-slice: 24 32
border-width: 18rpx 24rpx
min-height: 218rpx
margin-bottom: 12rpx
body min-height: 182rpx
gap: 8rpx 0
padding: 28rpx 28rpx 22rpx 40rpx
<AppButton compact type="secondary"
<AppButton compact
<AppDialog compact-actions
```
并禁止 `.application-card``.review-state-card` 继续使用 `100% 100%` 的完整背景拉伸。
- [ ] **Step 2: 运行 G10 合同并确认失败**
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g10-all-states-visual-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g10-document-flow-contract.ps1
```
Expected: FAIL,指出缺少九宫格卡框或紧凑按钮。
- [ ] **Step 3: 修改 G10 模板和样式**
- 导入 `AppButton`
- 用两个 `AppButton compact` 替换 `.review-action` 内的直接图片。
-`AppDialog` 增加 `compact-actions`
- `.application-card` 使用 `24 32` 九宫格切片和规格中的 `218rpx` 尺寸。
- `.application-card__body` 使用 `182rpx``8rpx 0``28rpx 28rpx 22rpx 40rpx`
- `.review-result` 根据 approved/rejected 类使用对应卷轴九宫格并移除直接图片。
- `.review-state-card` 使用同一卡框九宫格,保留其文案布局。
- [ ] **Step 4: 运行页面合同**
Run:
```powershell
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g10-all-states-visual-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g10-document-flow-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g08-g10-application-flow-contract.ps1
powershell -NoProfile -ExecutionPolicy Bypass -File tests/g09-g10-business-state-contract.ps1
```
Expected: 四项均输出 `PASS`
### Task 4: MuMu 全状态验证
**Files:**
- Verify: `components/AppButton.vue`
- Verify: `components/AppDialog.vue`
- Verify: `pages/genealogy/g10-application-review.vue`
- Save screenshots: `tmp/G10-responsive-*.png`
**Interfaces:**
- Consumes: Task 13 的最终实现。
- Produces: 11 个 G10 状态的 MuMu 原生视觉证据。
- [ ] **Step 1: 运行全部聚焦合同**
运行 Task 1–3 的九项唯一合同,任何一项失败即停止视觉验收。
- [ ] **Step 2: 捕获 11 个 MuMu 状态**
依次捕获列表、说明、通过确认、通过完成、拒绝确认、拒绝空校验、拒绝完成、空、加载、错误、无权限。
- [ ] **Step 3: 逐项检查**
```text
1. 卡框四角不拉伸,卡片上下留白收紧。
2. 左右双按钮皮肤完整,文字居中,不重叠、不越界。
3. 标题和说明独立成行。
4. 结果条完整且不可点击。
5. 空/错/无权限卡框不变形。
6. 加载、重试、拒绝校验和审核业务行为不回退。
```
若任一状态不满足,只调整本规格定义的紧凑切片、G10 卡片间距或弹窗文本布局,并重新运行全部聚焦合同与对应 MuMu 状态。
@@ -0,0 +1,152 @@
# 全项目通用提示文案实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 清除全项目输入提示、示例和辅助说明中的具体人物或家族名称,同时完整保留页面模拟数据。
**Architecture:** 新增一个只扫描用户提示上下文的 PowerShell 合同,作为规则唯一验证入口。生产改动限定在 G03、G08 与共享 `TreeMemberForm` 的六处提示文案,不触碰任何 fixture、卡片或详情数据。
**Tech Stack:** uni-app、Vue 3、PowerShell 静态合同、现有页面合同、MuMu、ADB。
## Global Constraints
- 只检查 `placeholder`、带“例如/比如/如:”的示例和输入框附近辅助说明。
- 模拟数据、成员目录、详情卡、申请记录和测试输入值保持不变。
- G08 使用“某某某堂侄”表达关系格式;其他字段优先使用动作型提示。
- 不执行 Git 操作,不启用多代理。
- 最终视觉结论只依据 MuMu 原生画面。
---
### Task 1: 建立提示文案全项目合同
**Files:**
- Create: `tests/generic-guidance-copy-contract.ps1`
**Interfaces:**
- Consumes: `pages/**/*.vue``components/**/*.vue` 中的用户提示文案。
- Produces: 只针对提示上下文禁止具体姓名的项目级合同。
- [ ] **Step 1: 写入失败合同**
创建 `tests/generic-guidance-copy-contract.ps1`
```powershell
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent $PSScriptRoot
$vueFiles = @(
Get-ChildItem -LiteralPath (Join-Path $root 'pages') -Recurse -Filter '*.vue'
Get-ChildItem -LiteralPath (Join-Path $root 'components') -Recurse -Filter '*.vue'
)
$specificCopy = @('汤正华', '汤正国', '汤文远', '汤氏家谱', '如:汤')
foreach ($file in $vueFiles) {
$lineNumber = 0
foreach ($line in Get-Content -LiteralPath $file.FullName -Encoding utf8) {
$lineNumber += 1
if ($line -notmatch 'placeholder|例如|比如|如:') { continue }
foreach ($token in $specificCopy) {
if ($line.Contains($token)) {
throw "User guidance must not contain specific copy '$token': $($file.FullName):$lineNumber"
}
}
}
}
$g08 = Get-Content -LiteralPath (Join-Path $root 'pages/genealogy/g08-join-application.vue') -Raw -Encoding utf8
foreach ($required in @('placeholder="例如:某某某堂侄"', '请以家谱中一位已知长辈为参照,例如:某某某堂侄')) {
if (-not $g08.Contains($required)) { throw "G08 generic relationship guidance missing: $required" }
}
Write-Output 'GENERIC-GUIDANCE-COPY-CONTRACT PASS'
```
- [ ] **Step 2: 运行合同并确认 RED**
```powershell
& powershell -ExecutionPolicy Bypass -File tests/generic-guidance-copy-contract.ps1
```
Expected: FAIL,首先报告 G03、G08 或 `TreeMemberForm` 仍含具体提示文案。
### Task 2: 替换六处提示并回归
**Files:**
- Modify: `pages/genealogy/g03-create-genealogy.vue`
- Modify: `pages/genealogy/g08-join-application.vue`
- Modify: `components/tree/TreeMemberForm.vue`
**Interfaces:**
- Consumes: Task 1 的提示文案合同。
- Produces: 不含具体姓名的动作型提示与通用关系示例。
- [ ] **Step 1: 做六处精确替换**
`pages/genealogy/g03-create-genealogy.vue`
```vue
placeholder="请输入姓氏"
placeholder="请输入家谱名称"
```
`pages/genealogy/g08-join-application.vue`
```vue
placeholder="例如:某某某堂侄"
```
```text
请以家谱中一位已知长辈为参照,例如:某某某堂侄
```
`components/tree/TreeMemberForm.vue`
```js
{ key: "name", label: "姓名", placeholder: "请输入首位成员姓名" },
{ key: "source", label: "当前成员", placeholder: "请选择当前成员" },
```
- [ ] **Step 2: 运行静态合同**
```powershell
$tests = @(
'tests/generic-guidance-copy-contract.ps1',
'tests/g03-create-flow-contract.ps1',
'tests/g03-visual-states-contract.ps1',
'tests/g08-g10-application-flow-contract.ps1',
'tests/g08-document-flow-contract.ps1',
'tests/tree-member-form-document-flow-contract.ps1'
)
foreach ($test in $tests) { & powershell -ExecutionPolicy Bypass -File $test }
```
Expected: 六项全部输出各自 `PASS`
- [ ] **Step 3: 运行 G08 流程回归**
```powershell
node tests/g08-g10-application-flow-runtime-smoke.js http://localhost:5173
```
Expected: 输出 `G08-G10-APPLICATION-FLOW-RUNTIME-SMOKE PASS`。若 H5 服务未运行,记录为环境阻塞,不用浏览器截图代替 MuMu 视觉验收。
### Task 3: MuMu 原生复核
**Files:**
- Create: `tmp/G08-generic-guidance-native.png`
**Interfaces:**
- Consumes: 已同步到 MuMu 的 G08 最新页面。
- Produces: 通用关系提示的原生证据。
- [ ] **Step 1: 捕获 G08 当前画面**
```powershell
$adb = 'C:\Users\Administrator\Desktop\HBuilderX\plugins\launcher-tools\tools\adbs\adb.exe'
& $adb -s emulator-5554 shell screencap -p /sdcard/G08-generic-guidance-native.png
& $adb -s emulator-5554 pull /sdcard/G08-generic-guidance-native.png tmp/G08-generic-guidance-native.png
```
- [ ] **Step 2: 检查并交给用户确认**
使用 `view_image` 原图确认关系输入和下方辅助说明都显示“某某某堂侄”,页面不再出现具体人物姓名。只报告当前默认状态,不把未查看的校验或提交结果状态标记为通过。
@@ -0,0 +1,228 @@
# Responsive Foundation Phase 1 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 建立全项目响应式基础契约,并让 AppDialog、AppButton 与 ModulePage 使用统一九宫格素材档案和内容驱动高度。
**Architecture:** `styles/adaptive-frame-profiles.scss` 是九宫格切片的唯一所有者;组件只调用具名 mixin。`project-responsive-layout-contract.ps1` 根据覆盖清单扫描已迁移文件,根据唯一白名单放行结构性固定尺寸;第一阶段覆盖三个公共内容组件,后续阶段只增加覆盖范围。
**Tech Stack:** uni-app、Vue 3、SCSS、PowerShell、MuMu Android
## Global Constraints
- 内容容器不得使用固定高度表达内容容量。
- 可变内容背景不得使用 `100% 100%` 整图拉伸。
- 固定高度和固定装饰例外只能由 `tests/responsive-layout-allowlist.json` 所有。
- 第一阶段覆盖 `AppDialog.vue``AppButton.vue``ModulePage.vue`;已覆盖文件不得退出。
- AppDialog 短内容自然收紧、长内容自然增高、超过视口才滚动。
- 不修改业务逻辑、路由、文案和数据状态。
- 不执行 Git 操作,不启用多代理。
---
### Task 1: 唯一九宫格素材档案
**Files:**
- Create: `styles/adaptive-frame-profiles.scss`
- Create: `tests/adaptive-frame-profiles-contract.ps1`
**Interfaces:**
- Produces: `adaptive-auth-dialog``adaptive-scroll-button($type)``adaptive-module-content``adaptive-module-field` 四个 SCSS mixin。
- [ ] **Step 1: 写入失败合同**
合同要求档案存在并包含:
```powershell
foreach ($token in @(
'@mixin adaptive-auth-dialog',
'@mixin adaptive-scroll-button($type)',
'@mixin adaptive-module-content',
'@mixin adaptive-module-field',
'a01-scroll-dialog-v3.png',
'border-image-slice: 260 240 360 240 fill;',
'border-image-slice: 56 300 fill;',
'border-image-slice: 105 150;',
'border-image-slice: 70 100 fill;'
))
```
Run: `powershell -NoProfile -ExecutionPolicy Bypass -File tests/adaptive-frame-profiles-contract.ps1`
Expected: FAIL,素材档案不存在。
- [ ] **Step 2: 创建素材档案**
`adaptive-auth-dialog` 使用:
```scss
border-width: 48rpx 34rpx 72rpx;
border-image-slice: 260 240 360 240 fill;
border-image-width: 48rpx 34rpx 72rpx;
```
`adaptive-scroll-button` 使用现有主/次卷轴素材、`10rpx 26rpx` 边框和 `56 300 fill` 切片。
`adaptive-module-content` 使用动态 `var(--module-content-asset)``18rpx 20rpx` 边框和 `105 150` 切片。
`adaptive-module-field` 使用动态 `var(--module-field-asset)``12rpx 16rpx` 边框和 `70 100 fill` 切片。
所有 mixin 使用透明实体边框、`border-image-repeat: stretch``box-sizing: border-box`
- [ ] **Step 3: 验证档案合同**
Expected: `ADAPTIVE-FRAME-PROFILES-CONTRACT PASS`
### Task 2: 全局扫描合同、覆盖清单与例外白名单
**Files:**
- Create: `tests/project-responsive-layout-contract.ps1`
- Create: `tests/responsive-layout-coverage.json`
- Create: `tests/responsive-layout-allowlist.json`
**Interfaces:**
- Consumes: 覆盖文件列表与按文件/选择器/属性登记的例外。
- Produces: 已迁移文件中固定内容高度、可变背景整图拉伸和重复九宫格切片的失败门禁。
- [ ] **Step 1: 创建第一阶段覆盖清单**
```json
{
"covered": [
"components/AppButton.vue",
"components/AppDialog.vue",
"components/ModulePage.vue"
]
}
```
- [ ] **Step 2: 创建唯一白名单**
第一阶段只允许 `ModulePage.vue``.module-lead` 使用固定分隔线背景;不允许 AppDialog、AppButton 或 ModulePage 内容表面使用固定内容高度/整图拉伸。
- [ ] **Step 3: 创建扫描合同并确认失败**
合同解析覆盖文件的样式块,遇到以下情况失败:
```text
height: <数字>rpx(不含 min-height/max-height
background: ... 100% 100%
页面或组件直接出现 border-image-slice(素材档案本身除外)
```
白名单按规范化文件路径、选择器和属性精确匹配。覆盖清单中的路径不存在也失败。
Run: `powershell -NoProfile -ExecutionPolicy Bypass -File tests/project-responsive-layout-contract.ps1`
Expected: FAIL,指出 AppDialog 固定 `520rpx` 或 ModulePage 内容表面整图拉伸。
### Task 3: AppDialog 与 AppButton 消费统一档案
**Files:**
- Modify: `components/AppDialog.vue`
- Modify: `components/AppButton.vue`
- Modify: `tests/app-dialog-responsive-content-contract.ps1`
- Modify: `tests/app-button-compact-contract.ps1`
**Interfaces:**
- Consumes: Task 1 的 `adaptive-auth-dialog``adaptive-scroll-button`
- Produces: 内容驱动的全局弹窗和默认关闭的紧凑按钮。
- [ ] **Step 1: 更新失败合同**
AppDialog 合同禁止 `min-height: 520rpx`、旧 `background ... contain``margin-top: auto`,要求:
```text
@include adaptive-auth-dialog;
max-height: calc(var(--app-viewport-height, 100vh) - 160rpx)
margin-top: 26rpx
```
AppButton 合同要求调用 `adaptive-scroll-button(primary|secondary)`,不再在组件内重复切片值。
- [ ] **Step 2: 运行合同并确认失败**
Expected: AppDialog 因固定高度失败,AppButton 因本地切片重复失败。
- [ ] **Step 3: 修改 AppDialog**
在 scoped style 开头导入档案。`.app-dialog` 删除固定最小高度和旧背景,调用 `adaptive-auth-dialog``.app-dialog__content` 删除固定最小高度,使用:
```scss
max-height: calc(var(--app-viewport-height, 100vh) - 160rpx);
padding: 16rpx 20rpx 12rpx;
overflow-y: auto;
```
操作区改为 `margin-top: 26rpx`,不再使用 `auto`
- [ ] **Step 4: 修改 AppButton**
导入档案;主/次紧凑类分别调用 `@include adaptive-scroll-button(primary)``secondary`;删除组件内重复边框切片声明。
- [ ] **Step 5: 运行共享组件合同**
Run AppDialog、AppButton、共享无障碍、共享文档流和全局响应式合同,Expected: 全部 `PASS`
### Task 4: ModulePage 内容表面迁移
**Files:**
- Modify: `components/ModulePage.vue`
- Modify: `tests/module-page-visual-contract.ps1`
- Test: `tests/module-series-responsive-runtime-smoke.js`
**Interfaces:**
- Consumes: Task 1 的 module-content 与 module-field mixin。
- Produces: F/R/N/M 通用页面的内容驱动卡片和表单表面。
- [ ] **Step 1: 更新失败合同**
要求 ModulePage 导入档案,字段组调用 `adaptive-module-field`,内容组调用 `adaptive-module-content`;禁止内容表面 `100% 100%`
- [ ] **Step 2: 运行合同并确认失败**
Expected: FAIL,指出旧 `var(--module-*-asset) center / 100% 100%`
- [ ] **Step 3: 修改 ModulePage**
- `.form-row, .settings-row` 调用 `adaptive-module-field`
- `.list-card, .detail-card, .timeline-row, .status-card` 调用 `adaptive-module-content`
- `.module-lead` 自己承担 flex 居中,删除子文本的 `height: 100%`
- 保留现有 `min-height` 作为最低视觉基线,内容可继续增高。
- [ ] **Step 4: 验证 ModulePage**
运行视觉合同、响应式 runtime smoke 与全局响应式合同;若 H5 服务未运行,只记录 runtime 环境阻塞,不用浏览器代替 MuMu。
### Task 5: MuMu 三档基础验证
**Files:**
- Verify: `components/AppDialog.vue`
- Verify: `components/AppButton.vue`
- Verify: `components/ModulePage.vue`
- Save screenshots: `tmp/responsive-foundation-*.png`
**Interfaces:**
- Produces: G10 通过/拒绝弹窗和一个 ModulePage 页面在三档 Android 逻辑视口的原生证据。
- [ ] **Step 1: 运行全部聚焦合同**
必须包含素材档案、全局响应式、AppDialog、AppButton、ModulePage、共享无障碍和共享文档流合同。
- [ ] **Step 2: MuMu 验证 G10**
`360×640dp``360×800dp``412×915dp` 依次检查:
```text
通过确认:无固定大空白。
拒绝确认:输入框和按钮不压边。
拒绝错误:错误文字出现后仍可达按钮。
```
- [ ] **Step 3: MuMu 验证 ModulePage**
选择一个 ready 和一个 error 状态,确认内容卡随文字增高、边角不拉伸、按钮可达。
- [ ] **Step 4: 恢复 MuMu 原始尺寸**
每档验证后恢复用户当前 `720×1280` 物理尺寸和原密度,并把 G10 恢复到默认列表。