97 lines
3.9 KiB
Markdown
97 lines
3.9 KiB
Markdown
|
|
# CompletionView Magic Card 版 — 审查报告(不应用)
|
|||
|
|
|
|||
|
|
**审查日期**:2025-01-29
|
|||
|
|
**范围**:Magic Card Edition(粒子庆祝 + 按钮卡片一体化 + 极光光晕)
|
|||
|
|
**结论**:仅审查、不修改仓库;逻辑继承正确,**ParticleModifier 存在两处需修复的实现问题**。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 需求落实情况
|
|||
|
|
|
|||
|
|
| 项目 | 要求 | 定稿实现 | 结论 |
|
|||
|
|
|------|------|----------|------|
|
|||
|
|
| **按钮卡片一体化** | 按钮在卡片内,点击后「献祭」化作彩带和数据 | IdleActionView 中按钮,切换后显示 ActiveDashboard + ConfettiExplosion | ✅ |
|
|||
|
|
| **粒子爆炸** | 蓝/紫/粉色粒子炸开 | ConfettiExplosion:Circle + Capsule,confettiColors | ✅ |
|
|||
|
|
| **呼吸光晕** | 激活后卡片背景极淡极光渐变 | AngularGradient + blur(20),isSystemOn 时显示 | ✅ |
|
|||
|
|
| **极简流程** | 点击上传 → 按钮消失 → 数据呈现,无「已同步」占位 | 符合 | ✅ |
|
|||
|
|
| **色彩规范** | 按钮 System Blue | brandBlue = Color.blue | ✅ |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 逻辑继承
|
|||
|
|
|
|||
|
|
| 项目 | 结论 |
|
|||
|
|
|------|------|
|
|||
|
|
| **持久化 Key** | ✅ `has_revealed_course_\(courseId)` |
|
|||
|
|
| **游客短路** | ✅ 0.5s 延迟,`performActivation(0, 0)`,不调网络 |
|
|||
|
|
| **登录用户** | ✅ 0.8s 延迟 → fetchUserProfile → performActivation |
|
|||
|
|
| **checkSystemStatus** | ✅ 已激活时恢复最终值 |
|
|||
|
|
| **数字滚动** | ✅ `withAnimation(.linear(1.5))` + RollingNumberText |
|
|||
|
|
| **ScaleButtonStyle** | 未使用,无重复定义风险 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. ⚠️ ParticleModifier 需修复项
|
|||
|
|
|
|||
|
|
### 3.1 角度单位错误(影响粒子方向)
|
|||
|
|
|
|||
|
|
**问题**:`angle` 为角度制 (0~360°),但 `cos(angle)`、`sin(angle)` 在 Swift 中接收弧度制。未做转换会导致粒子方向错误。
|
|||
|
|
|
|||
|
|
**修复**:先转换为弧度再计算:
|
|||
|
|
```swift
|
|||
|
|
let rad = angle * .pi / 180
|
|||
|
|
offset(x: time == 0 ? 0 : cos(rad) * distance,
|
|||
|
|
y: time == 0 ? 0 : sin(rad) * distance)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 angle / distance 每次重算导致动画抖动
|
|||
|
|
|
|||
|
|
**问题**:`var angle: Double { Double.random(in: 0...360) }` 和 `var distance: Double { ... }` 为计算属性,`body` 每次求值都会得到新随机数,粒子目标位置不断变化,动画会抖动。
|
|||
|
|
|
|||
|
|
**修复**:在 `init` 中一次性随机,并用 `@State` 保存,例如:
|
|||
|
|
```swift
|
|||
|
|
let index: Int
|
|||
|
|
@State private var time: Double = 0.0
|
|||
|
|
private let angle: Double
|
|||
|
|
private let distance: Double
|
|||
|
|
|
|||
|
|
init(index: Int) {
|
|||
|
|
self.index = index
|
|||
|
|
self.angle = Double.random(in: 0..<360)
|
|||
|
|
self.distance = Double.random(in: 80...150)
|
|||
|
|
// 如需在 init 中初始化 @State,可用 _time = State(initialValue: 0)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
并在 `body` 中用 `angle`、`distance` 计算 offset(配合上述弧度转换)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. ConfettiExplosion 可选优化
|
|||
|
|
|
|||
|
|
- **`confettiColors.randomElement()!`**:在 `body` 中每次重绘都会重新随机,粒子颜色可能闪变。可按 `index` 固定颜色,如 `confettiColors[i % confettiColors.count]`,以保持每个粒子颜色稳定。
|
|||
|
|
- **ForEach(0..<15)**:若 Swift 版本要求,可为 `ForEach` 增加 `id: \.self`。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 接口与影响范围
|
|||
|
|
|
|||
|
|
| 项目 | 结论 |
|
|||
|
|
|------|------|
|
|||
|
|
| **初始化参数** | 三参数不变 |
|
|||
|
|
| **替换方式** | 整文件替换 `CompletionView.swift` |
|
|||
|
|
| **新增类型** | `ParticleModifier` 仅在本文件使用,无符号冲突 |
|
|||
|
|
| **RollingNumberText** | 同前,保留在本文件 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 总结
|
|||
|
|
|
|||
|
|
| 维度 | 结论 |
|
|||
|
|
|------|------|
|
|||
|
|
| **需求落实** | ✅ 卡片一体化、粒子、光晕、流程、色彩均符合 |
|
|||
|
|
| **逻辑继承** | ✅ Key、游客、登录用户、数字滚动正确 |
|
|||
|
|
| **ParticleModifier** | ⚠️ **需修复**:弧度转换 + angle/distance 稳定化 |
|
|||
|
|
| **接口兼容** | ✅ 可直接替换 |
|
|||
|
|
|
|||
|
|
**审查结论**: Magic Card 版在设计与逻辑上正确,应用前需修复 ParticleModifier 的角度单位与随机值稳定性,否则粒子动画会出现方向错误和抖动。**本次未对仓库做任何修改。**
|