# 项目代码质量全景分析 & 重构计划

> 生成时间: 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 null，amap 调用无超时，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 进程内存级发布订阅
