Files
no-whatever/REFACTOR_PLAN.md
T
kurihada ce76980fe5 refactor(P0): JWT 认证、并发安全、错误日志三项安全加固
- 新增 JWT httpOnly cookie 认证链路 (jose),登录/注册签发 token,
  所有用户和盲盒 API 改为从 cookie 提取 userId,不再信任客户端传值
- 新增 /api/auth/logout 端点清除认证 cookie
- GET /api/user 区分 owner/非 owner,非 owner 不暴露 email
- atomicUpdateRoom 新增 per-room 应用层互斥锁,防止 SQLite 下并发 lost update
- 修复 getRoomData 中 fire-and-forget delete 改为 await
- 37 个静默 catch 块跨 17 个文件添加 console.error 日志
- 新增 REFACTOR_PLAN.md 全景分析文档
2026-03-02 17:24:26 +08:00

210 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 项目代码质量全景分析 & 重构计划
> 生成时间: 2026-03-02 | 分析工具: Claude Code 7-agent 并行审查
## 模块评分总览
| # | 模块 | 评分 | 重构优先级 | 核心问题 |
|---|------|------|-----------|----------|
| 1 | 认证 & 用户 API | 7.5 | 高 | 无真正鉴权机制,userId 可伪造 |
| 2 | 房间投票 API | 7.0 | 中 | atomicUpdateRoom 并发 lost update |
| 3 | 盲盒系统 API | 7.0 | 中 | AI 错误静默吞掉,plan/route.ts 臃肿 |
| 4 | 位置服务 API | 6.5 | 中 | 高德 API 调用代码 4 处重复,无超时/缓存 |
| 5 | 前端页面 | 5.5 | 高 | blindbox/[code] 1300行 37个useState |
| 6 | 组件 & Hooks | 6.5 | 高 | ShareCard 三兄弟 60% 重复,BlindboxPlan 742行 |
| 7 | 基础设施 & Lib | 6.5 | 高 | Room JSON blob 模型、前后端代码边界模糊 |
**全局平均: 6.6 / 10**
---
## 跨模块共性问题 TOP 5
### 1. 无真正的认证机制 (影响: 全局)
所有 API 的 userId 由客户端 localStorage 传入,任何人可伪造身份操作他人数据。登录接口签发了用户信息但没有 JWT/Cookie,形同虚设。
### 2. AI/外部 API 错误被静默吞掉 (影响: 盲盒、位置、Lib)
ai.ts 所有函数的 catch 都是 return nullamap 调用无超时,blindboxPlanGen.ts 多处空 catch。生产环境问题排查极其困难。
### 3. 巨型组件/页面 (影响: 前端)
- blindbox/[code]/page.tsx: 1300行, 37个useState, 12个useEffect
- BlindboxPlan.tsx: 742行
- blindbox/page.tsx: 658行, 18个useState
- MatchResult.tsx: 513行
### 4. 代码重复 (影响: 组件、位置、盲盒)
- ShareCard 三个文件 ~1024行,重复率 ~60%
- 高德 transit API 调用在 4处 复制粘贴
- 标签更新映射代码 3处 重复
- generateRoomCode 函数 2处 相同实现
### 5. Room 数据模型: JSON Blob 反模式 (影响: 房间、Lib)
Room.data 用一个 JSON 字符串存储全部状态,无法利用数据库约束、索引和关联查询。同项目的 BlindBoxRoom 系列已证明团队有能力做好关系化建模。
---
## 重构路线图
### P0 -- 立即修复 (安全/数据完整性)
- [ ] **实现 JWT/httpOnly Cookie 认证链路** (2-3天)
- 登录签发 JWT,设置 httpOnly cookie
- 新增 getAuthUserId(req) 从 cookie 中提取用户
- 所有 /api/user/*, /api/blindbox/*, /api/room/* 改用服务端鉴权
- 前端移除 userId 参数传递,改为 cookie 自动携带
- [ ] **修复 atomicUpdateRoom 并发安全** (0.5天)
- SQLite 下使用 IMMEDIATE 事务或应用层锁
- 如迁移到 PostgreSQL,使用 SELECT ... FOR UPDATE
- [ ] **所有 catch 块至少加 console.error** (0.5天)
- ai.ts: tagIdea, suggestIdeas, generateSchedule, refinePlan, suggestAlternativeItems
- blindboxPlanGen.ts: 多处空 catch
- 前端组件: BlindboxPlan, MatchResult, SwipeDeck, RestaurantCard 等
- API routes: applyTags 的 fire-and-forget
### P1 -- 短期重构 (代码质量)
- [ ] 拆分 blindbox/[code]/page.tsx 为 5-6 个子模块 + hooks (2-3天)
- [ ] 抽取 ShareCardShell 消除三兄弟重复 (1天)
- [ ] 拆分 BlindboxPlan.tsx (1天)
- [ ] 完善 amap.ts 为完整 API 客户端 (1天)
- [ ] 统一数据获取层 SWR 替代裸 fetch+useState (1-2天)
### P2 -- 中期优化 (架构改善)
- [ ] Room JSON blob 拆为关系化模型 (3-5天)
- [ ] 引入 zod 做 AI 返回值 + request body 校验 (1-2天)
- [ ] blindboxPlanGen.ts 拆为 4 个子模块 (1天)
- [ ] ApiError 独立 + validation 纯函数化 (0.5天)
- [ ] plan/route.ts PATCH/GET 内部拆分 (0.5天)
### P3 -- 长期改善
- [ ] 部分页面引入 Server Component 混合渲染
- [ ] 补全 a11y (aria-label、键盘导航)
- [ ] SSE 重连策略 (指数退避)
- [ ] 文件重命名 (store.ts → roomRepository.ts)
---
## 各模块详细分析
### 模块1: 认证 & 用户 API (7.5/10)
**亮点:**
- 已有 apiHandler 统一错误处理框架
- validation.ts 提供输入校验工具
- P2002 唯一约束冲突有分层防御
**问题:**
1. [Critical] userId 由客户端传入可伪造,无 JWT/session
2. [Critical] 登录成功后无状态维持(不签发 token)
3. [Warning] JSON.parse 部分未做防御处理
4. [Warning] GET /api/user 无需鉴权即可查任意用户 email
5. [Warning] login 接口缺少暴力破解防护
6. [Suggestion] 用户序列化逻辑重复
7. [Suggestion] achievements 业务逻辑偏重可抽 service
### 模块2: 房间投票 API (7.0/10)
**亮点:**
- atomicUpdateRoom 原子操作封装
- buildRoomStatus 视图层分离
- roomEvents 发布/订阅模式
- 各 handler 职责单一 (10-30行)
**问题:**
1. [Critical] atomicUpdateRoom 事务隔离级别不足,并发 lost update
2. [Critical] Room.data JSON blob 反模式
3. [Warning] SSE 连接中被踢用户无实时通知
4. [Warning] 房间过期清理机制不可靠 (进程内变量)
5. [Warning] getRoomData 中 fire-and-forget delete
6. [Warning] buildRoomStatus 每次查 DB 获取 UserProfile,缺缓存
7. [Suggestion] 房间 ID 使用 Math.random() 非密码学安全
### 模块3: 盲盒系统 API (7.0/10)
**亮点:**
- Agent + Legacy 双路径容错设计
- requireMembership 公共权限检查
- IdeaTags 多维标签系统设计合理
- 路由数量合理,职责清晰
**问题:**
1. [Critical] applyTags 静默吞掉所有错误
2. [Critical] retag 端点串行处理无并发控制
3. [Critical] plan/route.ts 227行承担过多职责
4. [Warning] 标签更新映射代码 3处 重复
5. [Warning] roomId 验证方式不一致
6. [Warning] plan/stream 未使用 apiHandler
7. [Warning] plan GET 的 pending/history 有 N+1 查询
8. [Suggestion] blindboxPlanGen.ts 808行应拆分
### 模块4: 位置服务 API (6.5/10)
**亮点:**
- 三个 location 端点都有测试覆盖
- apiHandler 统一包装
**问题:**
1. [Critical] 高德 transit API 调用在 4处 复制粘贴
2. [Critical] fetch 调用缺少超时控制
3. [Critical] debug 端点未用 apiHandler 且缺 try-catch
4. [Warning] amap.ts 封装过于薄弱 (仅 7行)
5. [Warning] 缺少缓存策略
6. [Warning] fetch 响应未检查 HTTP 状态码
7. [Warning] 输入验证不够严格 (经纬度未校验范围)
8. [Suggestion] POI 类型定义散落多文件
### 模块5: 前端页面 (5.5/10)
**亮点:**
- 路由设计清晰语义明确
- Skeleton 骨架屏使用
**问题:**
1. [Critical] blindbox/[code]/page.tsx 1300行 37个useState "上帝组件"
2. [Critical] blindbox/page.tsx 658行表单代码重复
3. [Critical] profile/page.tsx 521行 18个useState
4. [Warning] 数据获取方式不一致 (裸fetch vs SWR)
5. [Warning] userId 通过 URL 参数传递
6. [Warning] 错误静默吞掉
7. [Warning] panic/page.tsx 598行位置搜索逻辑应抽取
8. [Suggestion] 所有页面都是 "use client" 未利用 SSR
9. [Suggestion] 重复的页面布局模式 (ambient glow + 返回按钮)
### 模块6: 组件 & Hooks (6.5/10)
**亮点:**
- Hooks 设计整体合理
- Toast 系统简洁
- useShare 正确处理 AbortError
**问题:**
1. [Critical] ShareCard 三兄弟 ~60% 代码重复
2. [Critical] BlindboxPlan.tsx 742行职责过多
3. [Warning] 多处错误被静默吞掉
4. [Warning] useRoomPolling SSE 重连策略不足
5. [Warning] MatchResult.tsx 513行职责偏重
6. [Warning] useEffect 依赖项不完整
7. [Suggestion] 可访问性(a11y)严重不足
8. [Suggestion] ShareCard inline style 缺注释说明原因
### 模块7: 基础设施 & Lib (6.5/10)
**亮点:**
- 前后端目前无实际交叉引用错误
- sceneConfig/avatars 等纯函数设计良好
**问题:**
1. [Critical] Room JSON blob + WeekendPlan/Decision JSON 存储
2. [Warning] store.ts 命名严重误导 (服务端代码叫 store)
3. [Warning] api.ts 混合两类职责
4. [Warning] blindboxPlanGen.ts 808行过大
5. [Warning] 两套房间模型 (Room vs BlindBoxRoom) 设计差异大
6. [Warning] ai.ts AI 返回值校验不统一
7. [Warning] userId.ts 基于 localStorage UUID 无安全性
8. [Suggestion] runAgentLoop 硬编码 finalize_plan 工具名
9. [Suggestion] roomEvents 进程内存级发布订阅