150 lines
7.2 KiB
Markdown
150 lines
7.2 KiB
Markdown
# AppLoading 红金印牌重设计 Implementation Plan
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to implement this plan task-by-task. 本项目明确禁止多代理、worktree、`git add`、`commit`、`push`、`reset` 和 `checkout`。
|
||
|
||
**Goal:** 将公共 `AppLoading` 的临时细线方框替换为已批准的红金家谱印牌加载视觉,并保持页面级、区域级调用契约不变。
|
||
|
||
**Architecture:** `components/AppLoading.vue` 继续作为唯一加载视觉所有者,页面只传入 `variant`、`text` 和 `description`。组件复用 foundation 中的 `brand-seal.png` 与 `auth-divider-knot.png`,不让各业务页面重复定义加载资产或动画。
|
||
|
||
**Tech Stack:** uni-app、Vue 3 `<script setup>`、SCSS、PowerShell 契约测试、Chrome DevTools Protocol 截图脚本。
|
||
|
||
## Global Constraints
|
||
|
||
- 当前只做浅色国风主题,不接接口。
|
||
- 不修改 G01 状态判断、文案、背景、头部或底部导航。
|
||
- 不使用 CSS 绘制印章、SVG、emoji 或占位图形;只使用仓库内真实资产。
|
||
- 不使用多代理或 worktree,不执行任何 Git 写操作。
|
||
- 复用现有资产,不生成重复资产。
|
||
- H5 截图仅为内部候选证据;Android/HBuilderX 仍需复核。
|
||
|
||
---
|
||
|
||
### Task 1: 收紧公共加载视觉契约
|
||
|
||
**Files:**
|
||
- Modify: `tests/app-loading-contract.ps1`
|
||
- Test: `tests/app-loading-contract.ps1`
|
||
|
||
**Interfaces:**
|
||
- Consumes: `components/AppLoading.vue` 的模板与 scoped SCSS。
|
||
- Produces: 红金印牌、如意结、双尺寸和减弱动效的稳定契约。
|
||
|
||
- [ ] **Step 1: 写入失败契约**
|
||
|
||
在 `tests/app-loading-contract.ps1` 中将旧方框尺寸与 `1.35s` 断言替换为以下要求:
|
||
|
||
```powershell
|
||
Assert-Match -Content $component -Pattern 'class="app-loading__seal"\s+src="/static/assets/foundation/transparent/brand-seal\.png"' -Message 'AppLoading must render the approved real red-gold seal asset'
|
||
Assert-Match -Content $component -Pattern 'class="app-loading__knot"\s+src="/static/assets/foundation/transparent/auth-divider-knot\.png"' -Message 'AppLoading must render the approved real gold knot asset'
|
||
Assert-Match -Content $component -Pattern '(?s)\.app-loading--page\s+\.app-loading__seal\s*\{[^}]*width:\s*132rpx;[^}]*height:\s*136rpx;' -Message 'AppLoading page seal must use the approved size'
|
||
Assert-Match -Content $component -Pattern '(?s)\.app-loading--section\s+\.app-loading__seal\s*\{[^}]*width:\s*88rpx;[^}]*height:\s*90rpx;' -Message 'AppLoading section seal must use the approved size'
|
||
Assert-Match -Content $component -Pattern 'app-loading-seal-breathe\s+1\.6s' -Message 'AppLoading seal must use the approved restrained breathing rhythm'
|
||
Assert-Match -Content $component -Pattern '@media\s*\(prefers-reduced-motion:\s*reduce\)' -Message 'AppLoading must respect reduced-motion preferences'
|
||
if ($component -match 'app-loading__mark|border:\s*4rpx\s+double') { throw 'AppLoading must not retain the legacy CSS box mark' }
|
||
```
|
||
|
||
- [ ] **Step 2: 运行失败测试**
|
||
|
||
Run: `powershell -ExecutionPolicy Bypass -File tests/app-loading-contract.ps1`
|
||
|
||
Expected: FAIL,首个错误为缺少 `brand-seal.png` 真实印牌。
|
||
|
||
### Task 2: 实现红金印牌公共加载组件
|
||
|
||
**Files:**
|
||
- Modify: `components/AppLoading.vue`
|
||
- Test: `tests/app-loading-contract.ps1`
|
||
|
||
**Interfaces:**
|
||
- Consumes: `/static/assets/foundation/transparent/brand-seal.png`、`/static/assets/foundation/transparent/auth-divider-knot.png`。
|
||
- Produces: 调用方式不变的 `AppLoading` 页面级与区域级视觉。
|
||
|
||
- [ ] **Step 1: 替换模板主体**
|
||
|
||
将旧 `.app-loading__mark` 替换为:
|
||
|
||
```vue
|
||
<view class="app-loading__emblem" aria-hidden="true">
|
||
<image class="app-loading__seal" src="/static/assets/foundation/transparent/brand-seal.png" mode="aspectFit" />
|
||
<image class="app-loading__knot" src="/static/assets/foundation/transparent/auth-divider-knot.png" mode="aspectFit" />
|
||
</view>
|
||
```
|
||
|
||
- [ ] **Step 2: 写入最小视觉实现**
|
||
|
||
使用以下边界实现,不改变 props:
|
||
|
||
```scss
|
||
.app-loading__emblem { display: flex; flex-direction: column; align-items: center; }
|
||
.app-loading__seal { animation: app-loading-seal-breathe 1.6s ease-in-out infinite; }
|
||
.app-loading__knot { margin-top: 8rpx; opacity: .72; animation: app-loading-knot-breathe 1.6s ease-in-out infinite; }
|
||
.app-loading--page .app-loading__seal { width: 132rpx; height: 136rpx; }
|
||
.app-loading--page .app-loading__knot { width: 56rpx; height: 18rpx; }
|
||
.app-loading--section .app-loading__seal { width: 88rpx; height: 90rpx; }
|
||
.app-loading--section .app-loading__knot { width: 42rpx; height: 14rpx; margin-top: 5rpx; }
|
||
@keyframes app-loading-seal-breathe { 0%, 100% { opacity: .82; transform: scale(.96); } 50% { opacity: 1; transform: scale(1); } }
|
||
@keyframes app-loading-knot-breathe { 0%, 100% { opacity: .44; } 50% { opacity: .76; } }
|
||
@media (prefers-reduced-motion: reduce) { .app-loading__seal, .app-loading__knot { animation: none; opacity: 1; transform: none; } }
|
||
```
|
||
|
||
- [ ] **Step 3: 调整文字间距**
|
||
|
||
页面级主文案从印牌组合下方 `22rpx` 开始,区域级从 `14rpx` 开始;保留页面级 `30rpx/24rpx` 与区域级 `24rpx/22rpx` 字号。
|
||
|
||
- [ ] **Step 4: 运行契约测试**
|
||
|
||
Run: `powershell -ExecutionPolicy Bypass -File tests/app-loading-contract.ps1`
|
||
|
||
Expected: `APP-LOADING-CONTRACT PASS`。
|
||
|
||
### Task 3: 回归所有接入页面并完成视觉证据
|
||
|
||
**Files:**
|
||
- Verify: `pages/genealogy/g01-my-genealogies.vue`
|
||
- Verify: `pages/genealogy/g06-search-genealogies.vue`
|
||
- Verify: `tests/g01-loading-state-contract.ps1`
|
||
- Verify: `tests/g-series-app-loading-contract.ps1`
|
||
- Verify: `tests/module-app-loading-contract.ps1`
|
||
- Create: `docs/design/screens/runtime/2026-07-17/03-g01-loading-red-seal-412x900.png`
|
||
|
||
**Interfaces:**
|
||
- Consumes: 更新后的 `AppLoading` 公共视觉。
|
||
- Produces: 同一浏览器中的 G01 页面级与 G06 区域级回归证据。
|
||
|
||
- [ ] **Step 1: 运行加载契约和编译审计**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
powershell -ExecutionPolicy Bypass -File tests/g01-loading-state-contract.ps1
|
||
powershell -ExecutionPolicy Bypass -File tests/g-series-app-loading-contract.ps1
|
||
powershell -ExecutionPolicy Bypass -File tests/module-app-loading-contract.ps1
|
||
powershell -ExecutionPolicy Bypass -File tests/compile-audit.ps1
|
||
```
|
||
|
||
Expected: 四项均输出 `PASS`。
|
||
|
||
- [ ] **Step 2: 在同一个可控 Chrome 标签页截图 G01**
|
||
|
||
Run:
|
||
|
||
```powershell
|
||
node scripts/capture-chrome-page.js "http://localhost:5173/#/pages/genealogy/g01-my-genealogies?state=loading" ".state-panel--loading" "docs/design/screens/runtime/2026-07-17/03-g01-loading-red-seal-412x900.png" 412 900
|
||
```
|
||
|
||
Expected: 输出 `CAPTURED`,页面只有一个 Chrome 标签并显示红金印牌加载状态。
|
||
|
||
- [ ] **Step 3: 检查四档响应式尺寸**
|
||
|
||
分别使用 `320×568`、`360×640`、`360×800`、`412×915` 运行同一截图命令,确认印牌、文字和底栏无裁切、无横向滚动。
|
||
|
||
- [ ] **Step 4: 运行差异检查**
|
||
|
||
Run: `git diff --check -- components/AppLoading.vue tests/app-loading-contract.ps1`
|
||
|
||
Expected: 退出码 `0`;允许 Git 报告现有 LF/CRLF 提示,不允许空白错误。
|
||
|
||
## Execution Choice
|
||
|
||
按用户最新授权选择 **Inline Execution**:在当前会话使用 `superpowers:executing-plans` 顺序执行。由于用户明确禁止,不创建 worktree、不使用子代理、不执行提交。
|