# 知习后端:当前状态 & 需要你处理的决策和任务 > 基于代码审计生成。**2026-05-16 已确认所有决策,执行中。** --- # 一、当前代码状态总览 ## 已完成(真实可用的) | 模块 | 状态 | 说明 | |------|------|------| | Auth 控制器 + 服务 | 真实 | dev-login / apple / refresh / logout 全部写好了 | | TokenService | 真实 | JWT accessToken + crypto refreshToken + hash 入库 | | JwtAuthGuard | 真实 | 可正常验证 Bearer token | | CurrentUser 装饰器 | 真实 | 从 request.user 提取当前用户 | | AppleAuthService | 真实+兜底 | BUNDLE_ID 有值就走真实 JWKS 验证,没值走 mock | | UsersRepository | 真实 | **唯一接 Prisma 的 repository** | | PrismaService | 真实 | 连接 MySQL | | Prisma Schema | 完整 | 所有表都定义了(User, KnowledgeBase, KnowledgeItem, 等 30+ 个 model) | | AppModule | 完整 | 所有模块都注册了 | | 基础设施骨架 | 有 | Redis/Storage/Logger/Queue 模块都创建了 | | 全局异常过滤器 | 有 | | | 统一响应拦截器 | 有 | | | DTO 校验管道 | 有 | | | Apple 登录配置 | 有 | 但缺 `APPLE_BUNDLE_ID` | ## 仍在使用内存 Map(没有接数据库) | 模块 | 存储方式 | 严重程度 | |------|----------|----------| | KnowledgeBaseRepository | `new Map()` | 高 | | KnowledgeItemsRepository | `new Map()` | 高 | | ActiveRecallRepository | `new Map()` × 2 | 高 | | AiAnalysisRepository | `new Map()` × 2 | 高 | | FocusItemsRepository | `new Map()` | 高 | | ReviewRepository | `new Map()` × 2 | 高 | | LearningSessionRepository | `new Map()` | 高 | | LearningActivityRepository | `new Map()` | 中 | | DocumentImportRepository | `new Map()` | 中 | | QueueService | `new Map()` | 中 | ## AI 模块 ✅ 已升级为三层架构 | 组件 | 状态 | |------|------| | AiProvider 接口 | ✅ 统一 generate() + signal | | MockAiProvider | ✅ 永久保留 | | DeepSeekProvider | ✅ OpenAI 兼容协议 | | MiniMaxProvider | ✅ OpenAI 兼容协议(Coding Plan) | | ModelRouter | ✅ cheap / primary / strong 三档 | | AiGatewayService | ✅ 统一入口 + JSON容错 + 超时重试 | | PromptTemplateService | ✅ key + version 注册 | | ActiveRecallAnalysisWorkflow | ✅ 第一个 Workflow | | AiUsageLog + CostCalculator | ✅ 已加入 schema | | 旧 infrastructure/ai | ❌ 已删除 | | 新 AiModule | ✅ `src/modules/ai/` 14 个文件 | 详见 `startup-plan/技术设计/api-server/[已完成]-AI架构决策清单.md` --- # 二、需要你决策的事项 这些都是我无法替你决定的问题,每一个都会影响后续开发方向。 ## 决策 1:MySQL 数据库 —— 当前什么状态? `.env` 里配置了: ``` DATABASE_URL="mysql://zhixi_user:Zhixi@2026!App@localhost:3306/zhixi" ``` 需要确认: - [ ] MySQL 服务是否在运行? - [ ] 数据库 `zhixi` 是否已创建? - [ ] 数据库里是否已有数据?(如果之前跑过可能会有旧表) - [ ] Prisma schema 和实际数据库是否一致? **为什么重要**:Prisma schema 已定义 30+ 张表,但没有 migrations 目录。第一次 `prisma migrate dev` 会生成初始 migration。如果数据库已有表结构(非 Prisma 迁移创建的),需要额外处理。 **建议方案**: - 如果是空库 → 直接 `prisma migrate dev` 生成初始迁移 - 如果已有 Prisma 创建的表 → 先 `prisma db pull` 拉取现有结构,再 `prisma migrate dev` - 如果 MySQL 没启动 → 先解决 MySQL 启动问题 --- ## 决策 2:BigInt ID 问题 —— 现在不改,后面全是雷 Prisma schema 所有主键都是 `BigInt @default(autoincrement())`。 但是: - JavaScript/JSON 不支持 64 位整数 - Auth 模块里已经出现大量 `BigInt(userId)` / `String(user.id)` 的转换 - KnowledgeBase 的 in-memory 版本用的是 `string` ID - JWT payload 里的 `sub` 是 `String(user.id)` - 这意味着:**内存版本和数据库版本的 ID 类型不统一** **问题场景**: ``` 数据库返回: user.id = 9007199254740993n (BigInt, 超出 JS 安全范围) JSON.stringify → "9007199254740992" (精度丢失!) ``` **选项**: - A) 换 `String @id @default(cuid())` —— 最安全,推荐,但需要改 schema 和所有关联代码 - B) 换 `Int @default(autoincrement())` —— 简单但有上限(21 亿),够用但不够好看 - C) 保持 `BigInt` —— 不改,但要全局统一序列化(`JSON.stringify` 不能直接用),所有 repository 都要转 string --- ## 决策 3:AI Provider —— 第一个接哪个? 目前 AI 是纯 mock,返回固定 JSON。 **选项**: - A) **DeepSeek** —— 便宜,中文强,适合预算有限的独立开发者 - B) **OpenAI (GPT-4o)** —— 贵但生态好,SDK 成熟 - C) **Anthropic Claude** —— 长上下文优秀,适合大段知识分析 - D) **MiniMax / 豆包 / 通义千问** —— 国内合规,需要 ICP 备案才能用 **连锁影响**: - 决定了 AIGateway 第一个 provider 实现 - 决定了 Prompt 模板的调试环境 - 决定了成本(需要 API key 和充值) --- ## 决策 4:Redis 状态 —— 需要现在启动吗? `.env` 里配置了 Redis 连接,`AiAnalysisService` 里用了 Redis(限流、任务状态、锁)。 但是这些功能**不启动 Redis 也能绕过去**——限流可以先去掉,任务状态可以先放内存。 **建议**:先不管 Redis,集中精力把数据库层搞定。限流等功能后面补。 --- ## 决策 5:Prisma Schema 需要调整吗? 现在 schema 非常完整(30+ 张表),但很多是远期才用的表: | 近期需要的表 | 远期才用的表 | |-------------|-------------| | users | UserProfile | | auth_accounts | UserPreference | | refresh_tokens | UserConsent | | knowledge_bases | KnowledgeItemRelation | | knowledge_items | Tag (如果第一版不做标签) | | active_recall_questions | KnowledgeItemTag | | active_recall_answers | UploadedFile | | ai_analysis_jobs | DocumentImport | | ai_analysis_results | LearningRecord | | focus_items | ReviewPlan | | review_cards | AppChangelog | | review_logs | DailyLearningActivity | | learning_sessions | Notification | | feedback | ... | **选项**: - A) 保持全部 schema,一次迁移创建所有表(简单但有大量空表) - B) 先只迁移近期需要的表(干净但需要改 schema 文件) --- ## 决策 6:Apple 登录什么时候接? 代码已写好,AppleAuthService 带了 mock 兜底。 问题: - `APPLE_BUNDLE_ID` 为空 → Apple 登录走 mock - 真正的 Apple ID token 验证需要 Apple Developer 账号 - 这取决于你的 Apple Developer 审核进度 **当前行为**:即使 APPLE_BUNDLE_ID 为空,Apple 登录接口也能用,只是不走真实验证。这对开发阶段来说够了。 --- # 三、当前无法处理的事情 这些事情需要外部条件满足才能推进: | 阻塞项 | 原因 | 谁来解决 | 预计时间 | |--------|------|----------|----------| | 11 个 Repository 接 Prisma | 待逐一迁移 | 开发 | — | | AiUsageLog 表建到服务器 | SSH 隧道未连通 | 你 | — | | Apple 登录真实验证 | 需要 APPLE_BUNDLE_ID | Apple 审核 | 不确定 | | BullMQ 队列 | 需要 Redis | 可推迟 | — | | 文件上传 (COS/S3) | 需要选存储服务 | 可推迟 | — | | iOS Keychain / AppSession | 前端配合 | iOS 开发时 | — | ## ✅ 已解决的阻塞项 | 阻塞项 | 状态 | |--------|------| | Prisma 首次迁移 | ✅ db push 完成,所有表已建 | | 真实 AI 分析 | ✅ 三层架构已落地,Mock/DeepSeek/MiniMax 三 Provider | | BigInt ID 方案 | ✅ 全部改为 String cuid() | --- # 四、分阶段可执行任务清单 ## 阶段 1:地基打通(现在就要做) 这些是最紧迫的,必须在写新功能之前完成。 ### 任务 1.1:确认数据库连接 + 跑通首次迁移 **前置条件**:决策 1 ```text 1. 确认 MySQL 服务已启动 2. 确认 zhixi 数据库已创建(不存在则 CREATE DATABASE zhixi) 3. 根据决策 2 调整 Prisma schema 的 ID 类型 4. 运行 prisma migrate dev --name init 5. 验证生成的 migration SQL 无误 6. 运行 prisma generate 7. 启动服务,调 dev-login 验证 auth 模块正常工作 ``` ### 任务 1.2:解决 BigInt ID 方案 **前置条件**:决策 2 如果是方案 A(cuid),需要改: - `schema.prisma` 所有 `BigInt @default(autoincrement())` → `String @id @default(cuid())` - `AuthService` 里的 `BigInt(userId)` 转换去掉 - `UsersRepository` 里的 `BigInt(userId)` 转换去掉 - `JwtAuthGuard` 的 `request.user` 类型 ### 任务 1.3:把所有 Repository 从 Map 迁到 Prisma **前置条件**:任务 1.1 + 1.2 按优先级迁: ```text 第一批(核心业务): KnowledgeBaseRepository → prisma KnowledgeItemsRepository → prisma ActiveRecallRepository → prisma 第二批(学习闭环): LearningSessionRepository → prisma AiAnalysisRepository → prisma FocusItemsRepository → prisma ReviewRepository → prisma 第三批(辅助): LearningActivityRepository → prisma DocumentImportRepository → prisma ``` 每个 repository 改造模板: ```text 1. 注入 PrismaService 2. create → prisma.xxx.create() 3. findById → prisma.xxx.findUnique() 4. findAllByUserId → prisma.xxx.findMany({ where: { userId } }) 5. update → prisma.xxx.update() 6. softDelete → prisma.xxx.update({ data: { deletedAt: new Date() } }) 7. 删除 Map 相关代码 ``` ### 任务 1.4:给所有 Controller 统一加 JwtAuthGuard 当前问题: - `KnowledgeBaseController` 的 `@CurrentUser()` 标记了 `| undefined`,实际允许未登录访问 - 部分 Controller 根本没加 guard ```text 1. KnowledgeBaseController 加 @UseGuards(JwtAuthGuard) 2. KnowledgeItemsController 加 @UseGuards(JwtAuthGuard) 3. ActiveRecallController 加 @UseGuards(JwtAuthGuard) 4. AiAnalysisController 加 @UseGuards(JwtAuthGuard) 5. FocusItemsController 加 @UseGuards(JwtAuthGuard) 6. ReviewController 加 @UseGuards(JwtAuthGuard) 7. LearningSessionController 加 @UseGuards(JwtAuthGuard) 8. LearningActivityController 加 @UseGuards(JwtAuthGuard) ``` --- ## 阶段 2:第一个真实 AI Provider ### 任务 2.1:选 provider + 获取 API Key **前置条件**:决策 3 ### 任务 2.2:实现第一个真实 AI Provider ```text 1. 创建 DeepSeekProvider(或你选的 provider) 2. 实现 AiProvider 接口 3. 对接真实 API 4. 处理超时、重试、JSON 解析 5. 更新 AiModule 根据配置切换 provider ``` ### 任务 2.3:实现第一个真实 Prompt 模板 硬编码在 MockAiProvider 里的静态 JSON 不能用了,需要: ```text 1. 编写主动回忆分析的 System Prompt 2. 设计输出 JSON Schema 3. 处理 AI 返回格式不稳定的情况(JSON 解析错误兜底) ``` --- ## 阶段 3:学习闭环联调 ### 任务 3.1:验证端到端流程 ```text 用户登录 → 创建知识库 → 创建知识点 → 开始学习会话 → 提交主动回忆 → AI 分析 → 生成 FocusItem → 生成复习卡 → 完成复习 ``` --- # 五、决策汇总表(已确认) | 编号 | 问题 | 决策 | 状态 | |------|------|------|------| | 决策 1 | MySQL 数据库当前状态? | URL-encode 密码 `@→%40, !→%21`,确认连接后 migrate | 已修复 DATABASE_URL | | 决策 2 | BigInt vs cuid vs Int,用哪个 ID 方案? | **全部 String cuid()**,不用 BigInt | 已完成 | | 决策 3 | 第一个 AI Provider 选谁? | DeepSeek,但先不接,等核心闭环跑通 | 已决策 | | 决策 4 | Redis 现在启动还是先绕过? | 先绕过,不阻塞主线 | 已决策 | | 决策 5 | Prisma Schema 全部迁移还是分批? | 保留完整 schema,一次迁移 | 已决策 | | 决策 6 | Apple 登录什么时候接? | **现在接**,BUNDLE_ID=cloud.longde.AIStudyApp | 已配置 | ## 已完成的改动 - [x] `schema.prisma`:全部 27 个 model 的 BigInt → String cuid() - [x] `auth.service.ts`:删除 BigInt() 转换、bigint 类型 → string - [x] `token.service.ts`:bigint → string,删除 String(user.id) 转换 - [x] `users.repository.ts`:删除所有 BigInt() 转换 - [x] `security.util.ts`:number|bigint → string - [x] `.env`:DATABASE_URL 密码 URL-encode,补 APPLE_BUNDLE_ID - [x] `.env.example`:同步更新 ## 待完成(需要 MySQL 环境) - [ ] `prisma migrate dev --name init` - [ ] `prisma generate` - [ ] 启动服务,验证 dev-login、refresh、logout、users/me - [ ] KnowledgeBaseRepository 接 Prisma(第一个业务 repository 迁移) - [ ] KnowledgeItemsRepository 接 Prisma - [ ] ActiveRecallRepository 接 Prisma - [ ] 所有 Controller 加 JwtAuthGuard