diff --git a/docs/superpowers/specs/2026-06-08-s1-scan-findings.md b/docs/superpowers/specs/2026-06-08-s1-scan-findings.md new file mode 100644 index 0000000..061b842 --- /dev/null +++ b/docs/superpowers/specs/2026-06-08-s1-scan-findings.md @@ -0,0 +1,107 @@ +# S1 全面扫描 — 汇总报告 + +日期: 2026-06-08 + +## 统计总览 + +| 优先级 | 数量 | 说明 | +|--------|------|------| +| P0 | 0 | 无数据丢失/安全漏洞/崩溃风险 | +| P1 | 1 | 功能问题 | +| P2 | 4 | 体验/规范问题 | +| P3 | 7 | 建议改进 | +| **合计** | **12** | | + +--- + +## P1 — 高优先级(1 项) + +### 1. notifications 页面使用 emoji 违反设计规范 + +| 文件 | 行号 | 问题 | 影响 | +|------|------|------|------| +| [notifications/index.vue](client/src/pages/notifications/index.vue) | 43 | `📌` 使用 emoji 作为图钉图标 | 设计规范明确禁止 emoji,必须使用 Icon 组件 | + +**修复方向**:将 `📌` 替换为 `` + +--- + +## P2 — 中优先级(4 项) + +### 2. stats 趋势条动画缺少 prefers-reduced-motion + +| 文件 | 行号 | 问题 | 影响 | +|------|------|------|------| +| [stats/index.vue](client/src/pages/stats/index.vue) | 550 | `.trend-bar { transition: width 0.6s ease-out; }` 无 `prefers-reduced-motion` 处理 | 对动画敏感用户不友好 | + +**修复方向**:添加 `@media (prefers-reduced-motion: reduce) { .trend-bar { transition: none; } }` + +### 3. admin/logs 页面日期选择触发双重请求 + +| 文件 | 行号 | 问题 | 影响 | +|------|------|------|------| +| [admin/logs.vue](client/src/pages/admin/logs.vue) | 181-185, 206-209 | `selectDate()` 直接调用 `loadLogs()`,同时 `watch([filterLevel, selectedDate])` 也触发 `loadLogs()`,导致日期变更时请求发两次 | 浪费带宽,可能导致竞态 | + +**修复方向**:`selectDate()` 只设置 `selectedDate.value`,删除手动 `loadLogs()` 调用,由 watcher 统一触发。 + +### 4. bills 页面列表参数使用 any 类型 + +| 文件 | 行号 | 问题 | 影响 | +|------|------|------|------| +| [bills/index.vue](client/src/pages/bills/index.vue) | 109, 165 | `txList: any[]` 和 `params: any` 丢失类型安全 | 重构时易引入 bug | + +**修复方向**:使用 `Transaction[]` 和 `TransactionParams` 类型。 + +### 5. bills 空状态缺少图标 + +| 文件 | 行号 | 问题 | 影响 | +|------|------|------|------| +| [bills/index.vue](client/src/pages/bills/index.vue) | 82-84 | 空状态只显示文字「暂无账单记录」,无图标 | 与其他页面空状态不一致(其他页面都有 Icon) | + +**修复方向**:添加 `` + +--- + +## P3 — 建议改进(7 项) + +### 6. 多处使用 `any` 类型 + +| 文件 | 行号 | 问题 | +|------|------|------| +| [index/index.vue](client/src/pages/index/index.vue) | 168 | `recentTx` 类型 `any[]`,应为 `Transaction[]` | +| [add/index.vue](client/src/pages/add/index.vue) | 139 | `getCurrentPages()` 结果 cast `as any` | +| [budget/index.vue](client/src/pages/budget/index.vue) | 93 | `budget` 类型 `any`,应为 `Budget \| null` | +| [profile/index.vue](client/src/pages/profile/index.vue) | 329 | `allList` 类型 `any[]`,应为 `Transaction[]` | +| [admin/users.vue](client/src/pages/admin/users.vue) | 99 | `params` 类型 `any`,应为具名类型 | +| [admin/feedback.vue](client/src/pages/admin/feedback.vue) | 105 | `list` 类型 `any[]`,应使用 Feedback 类型 | + +### 7. stats 页面 loadData / loadTabData 代码重复 + +| 文件 | 行号 | 问题 | +|------|------|------| +| [stats/index.vue](client/src/pages/stats/index.vue) | 245-281 | `loadData` 和 `loadTabData` 有大量重复代码(loadSeq、错误处理),可抽取公共函数 | + +--- + +## 总体评价 + +代码质量整体良好,主要体现在: + +- ✅ **认证机制完善**:HMAC-SHA256 token + timingSafeEqual,30天过期 +- ✅ **竞态保护**:bills、stats、notifications 页面均使用 `loadSeq` 防止并发覆盖 +- ✅ **401 队列重试**:`request.ts` 自动重登录 + 队列重试,设计精良 +- ✅ **统一设计系统**:SCSS 变量、mixin 复用度高,Claymorphism 风格统一 +- ✅ **响应格式统一**:后端 API 返回 `{ code, data/message }` 标准格式 +- ✅ **输入校验**:前后端均有校验(金额范围、必填字段、类型白名单) +- ✅ **参数化查询**:后端 SQL 使用 `?` 占位符,无 SQL 注入风险 +- ✅ **空状态/加载态/错误态**:大部分页面三态齐全 +- ✅ **小程序适配**:胶囊按钮避让 `capsuleRight` 使用正确 +- ✅ **数据加载模式**:`waitForReady()` + `initialLoaded` 守卫模式统一 +- ✅ **动画可访问性**:大部分页面有 `prefers-reduced-motion` 处理 + +主要改进方向集中在: +1. 消除 emoji(1 处) +2. 补全 `prefers-reduced-motion`(1 处) +3. 修复重复请求(1 处) +4. 统一空状态样式(1 处) +5. 减少 `any` 类型使用(6 处)