Files
no-whatever/REFACTOR_PLAN.md
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

7.9 KiB
Raw Permalink Blame History

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

生成时间: 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 进程内存级发布订阅