Review changes batch 6 of 6
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
# AppLoading 必要加载动效实施计划
|
||||
|
||||
> **执行要求:** 使用 `superpowers:executing-plans` 在当前会话内逐步执行。用户明确禁止多代理、worktree、`git add`、commit、push、reset 和 checkout。
|
||||
|
||||
**目标:** 修复 G01 在 `prefers-reduced-motion: reduce` 下加载态完全静止的问题,使印牌和如意结保留清晰的透明度呼吸,同时不产生缩放、旋转或位移。
|
||||
|
||||
**架构:** 继续由 `components/AppLoading.vue` 单一维护加载动效,不在 G01 复制样式。正常模式保持现有动画;减少动态效果模式改用独立的透明度关键帧,并强制 `transform: none`。测试先锁定旧行为必须失败,再验证静态契约和当前 Chrome 运行时证据。
|
||||
|
||||
**技术栈:** Vue 3、uni-app、SCSS、PowerShell 契约测试、Chrome DevTools Protocol、Node.js。
|
||||
|
||||
## 全局约束
|
||||
|
||||
- 只修改 G01 加载态直接依赖的公共 `AppLoading`、聚焦测试和当轮内部证据。
|
||||
- 不改变 `variant`、`text`、`description` 组件契约。
|
||||
- 不改变 G01 状态逻辑、布局、背景、文案、标题栏或底部导航。
|
||||
- 不新增图片、CSS 图形、JavaScript 定时器或业务接口。
|
||||
- `prefers-reduced-motion: reduce` 下只允许透明度变化,`transform` 必须为 `none`。
|
||||
- H5 截图只是内部候选;Android/HBuilderX 仍未验证。
|
||||
- 不执行任何 Git 写操作。
|
||||
|
||||
---
|
||||
|
||||
### Task 1:修复并验证减少动态效果模式的必要加载反馈
|
||||
|
||||
**文件:**
|
||||
|
||||
- 修改:`tests/app-loading-contract.ps1`
|
||||
- 修改:`components/AppLoading.vue`
|
||||
- 验证:`tests/g01-loading-state-contract.ps1`
|
||||
- 验证:`tests/g-series-app-loading-contract.ps1`
|
||||
- 验证:`tests/module-app-loading-contract.ps1`
|
||||
- 内部证据:`docs/design/screens/runtime/2026-07-19/g01-approval/03-loading-essential-motion-412x915.png`
|
||||
|
||||
**接口:**
|
||||
|
||||
- 消费:`AppLoading` 现有 `variant`、`text`、`description` 属性。
|
||||
- 产出:正常模式继续使用 `app-loading-seal-breathe`/`app-loading-knot-breathe`;减少动态效果模式使用 `app-loading-seal-essential-pulse`/`app-loading-knot-essential-pulse`。
|
||||
- 不增加新的组件属性、事件或页面状态。
|
||||
|
||||
- [ ] **Step 1:先补充会失败的公共契约**
|
||||
|
||||
在 `tests/app-loading-contract.ps1` 的现有动画断言之后加入:
|
||||
|
||||
```powershell
|
||||
Assert-Match -Content $component -Pattern '@keyframes\s+app-loading-seal-essential-pulse' -Message 'Reduced-motion AppLoading must retain an essential seal opacity pulse'
|
||||
Assert-Match -Content $component -Pattern '@keyframes\s+app-loading-knot-essential-pulse' -Message 'Reduced-motion AppLoading must retain an essential knot opacity pulse'
|
||||
Assert-Match -Content $component -Pattern '(?s)@media\s*\(prefers-reduced-motion:\s*reduce\).*?\.app-loading__seal\s*\{[^}]*animation:\s*app-loading-seal-essential-pulse\s+1\.2s\s+ease-in-out\s+infinite;[^}]*transform:\s*none;' -Message 'Reduced-motion seal must pulse opacity without transform motion'
|
||||
Assert-Match -Content $component -Pattern '(?s)@media\s*\(prefers-reduced-motion:\s*reduce\).*?\.app-loading__knot\s*\{[^}]*animation:\s*app-loading-knot-essential-pulse\s+1\.2s\s+ease-in-out\s+\.2s\s+infinite;[^}]*transform:\s*none;' -Message 'Reduced-motion knot must pulse opacity without transform motion'
|
||||
if ($component -match '(?s)@media\s*\(prefers-reduced-motion:\s*reduce\).*?animation:\s*none') {
|
||||
throw 'Reduced-motion AppLoading must not become completely static'
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2:运行聚焦契约并确认 RED**
|
||||
|
||||
运行:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/app-loading-contract.ps1
|
||||
```
|
||||
|
||||
预期:退出码非 0,错误首先指向缺少 `app-loading-seal-essential-pulse`,证明测试捕获的是当前完全静止行为,而不是语法或路径错误。
|
||||
|
||||
- [ ] **Step 3:实现最小降动效透明度脉冲**
|
||||
|
||||
在 `components/AppLoading.vue` 中保留现有正常模式关键帧,并把当前媒体查询替换为:
|
||||
|
||||
```scss
|
||||
@keyframes app-loading-seal-essential-pulse {
|
||||
0%, 100% { opacity: .58; }
|
||||
50% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes app-loading-knot-essential-pulse {
|
||||
0%, 100% { opacity: .28; }
|
||||
50% { opacity: .86; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.app-loading__seal {
|
||||
animation: app-loading-seal-essential-pulse 1.2s ease-in-out infinite;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.app-loading__knot {
|
||||
animation: app-loading-knot-essential-pulse 1.2s ease-in-out .2s infinite;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
不得修改模板、属性、尺寸、文案或正常模式关键帧。
|
||||
|
||||
- [ ] **Step 4:运行聚焦契约并确认 GREEN**
|
||||
|
||||
运行:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/app-loading-contract.ps1
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g01-loading-state-contract.ps1
|
||||
```
|
||||
|
||||
预期:分别输出 `APP-LOADING-CONTRACT PASS` 和 `G01-LOADING-STATE-CONTRACT PASS`,退出码均为 0。
|
||||
|
||||
- [ ] **Step 5:在当前唯一 Chrome 标签页验证真实动画**
|
||||
|
||||
保持 G01 `state=loading` 和 412×915 视口。通过 9222 CDP 在同一次检查中读取:
|
||||
|
||||
```js
|
||||
const seal = document.querySelector('.app-loading__seal')
|
||||
const knot = document.querySelector('.app-loading__knot')
|
||||
const sealStyle = getComputedStyle(seal)
|
||||
const knotStyle = getComputedStyle(knot)
|
||||
({
|
||||
reduced: matchMedia('(prefers-reduced-motion: reduce)').matches,
|
||||
sealAnimation: sealStyle.animationName,
|
||||
sealTransform: sealStyle.transform,
|
||||
sealOpacity: sealStyle.opacity,
|
||||
sealAnimations: seal.getAnimations().length,
|
||||
knotAnimation: knotStyle.animationName,
|
||||
knotTransform: knotStyle.transform,
|
||||
knotOpacity: knotStyle.opacity,
|
||||
knotAnimations: knot.getAnimations().length
|
||||
})
|
||||
```
|
||||
|
||||
等待约 420ms 后再次读取。预期:
|
||||
|
||||
- `reduced` 为 `true`;
|
||||
- 两个 `animationName` 分别以新的 essential pulse 名称开头;Vue scoped CSS 可在运行时追加哈希后缀;
|
||||
- 两个 `getAnimations().length` 均大于 0;
|
||||
- 两次读取的透明度不同;
|
||||
- 两个 `transform` 均为 `none`;
|
||||
- 页面仍为 G01 加载态。
|
||||
|
||||
- [ ] **Step 6:捕获并人工检查当前候选帧**
|
||||
|
||||
使用当前唯一标签页保存:
|
||||
|
||||
```text
|
||||
docs/design/screens/runtime/2026-07-19/g01-approval/03-loading-essential-motion-412x915.png
|
||||
```
|
||||
|
||||
人工检查:标题栏、背景、印牌、如意结、两行文案和底部导航均完整;没有列表、失败态或原生 Loading 串入。静态截图不作为动画运行证明,动画结论以 Step 5 的多时点数据为准。
|
||||
|
||||
- [ ] **Step 7:运行受影响合同与空白检查**
|
||||
|
||||
运行:
|
||||
|
||||
```powershell
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/g-series-app-loading-contract.ps1
|
||||
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/module-app-loading-contract.ps1
|
||||
git diff --check -- components/AppLoading.vue tests/app-loading-contract.ps1 docs/superpowers/specs/2026-07-19-app-loading-essential-motion-design.md docs/superpowers/plans/2026-07-19-app-loading-essential-motion.md
|
||||
```
|
||||
|
||||
预期:两个合同均输出各自的 `PASS`,`git diff --check` 退出码为 0。不得把 Android/HBuilderX 写成已验证。
|
||||
|
||||
- [ ] **Step 8:回到同一加载态等待用户复核**
|
||||
|
||||
保持浏览器停留在修正后的 G01 加载态,不自动切换到失败态。只有用户明确说加载态“通过”后,才继续 G01 下一状态;在此之前 G01 保持 `[!]`。
|
||||
Reference in New Issue
Block a user