restructure doc repo: new directory layout with status prefixes, archive completed docs
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
8841c4188b
commit
00b7b3613c
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
.claude/
|
||||
.DS_Store
|
||||
凭据配置/
|
||||
|
||||
168
README.md
Normal file
168
README.md
Normal file
@ -0,0 +1,168 @@
|
||||
# 知习 ZhiXi 文档中心
|
||||
|
||||
> 所有技术设计和项目规划文档的总索引。
|
||||
|
||||
---
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
├── 技术设计/ 系统怎么建(按项目分文件夹)
|
||||
├── 开发计划/ 先做什么后做什么(按项目分文件夹)
|
||||
├── 长期规划/ 为什么做、给谁做
|
||||
├── 凭据配置/ 服务器密码和密钥(已 gitignore)
|
||||
└── 图片资源/ 产品图片
|
||||
```
|
||||
|
||||
### 状态标识说明
|
||||
|
||||
| 前缀 | 含义 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| `[已完成]` | 设计已落实到代码,功能可运行 | 技术设计文档 |
|
||||
| `[进行中]` | 部分实现/持续更新中 | 技术设计 + 开发计划 |
|
||||
| `[设计中]` | 纯设计文档,尚未开始实现 | 技术设计文档 |
|
||||
| `[参考]` | 静态参考文档,内容不再变动 | 需求基线等 |
|
||||
| `[快照]` | 一次性审计快照,记录某个时间点的状态 | 差距分析等 |
|
||||
|
||||
---
|
||||
|
||||
## 技术设计
|
||||
|
||||
### api-server(后端)
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [进行中-架构总览](技术设计/api-server/[进行中]-架构总览.md) | 模块化单体架构、技术栈、目录结构、14个业务模块、API路由规划、数据模型(模块骨架存在,队列/AI异步未完成) |
|
||||
| [进行中-Redis缓存设计](技术设计/api-server/[进行中]-Redis缓存设计.md) | 缓存/队列/限流设计,Redis 已连接,BullMQ 队列待替换内存队列 |
|
||||
| [设计中-AI架构设计](技术设计/api-server/[设计中]-AI架构设计.md) | AI Provider 抽象、四层模型策略、Agent 演进路线 V0-V3 |
|
||||
|
||||
#### 已完成
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [数据库设计](技术设计/api-server/已完成/[已完成]-数据库设计.md) | 27 张表完整设计,Prisma schema 已落地,MySQL 运行中 |
|
||||
| [安全规范](技术设计/api-server/已完成/[已完成]-安全规范.md) | 安全基线:Helmet、CORS、JWT Guard、参数校验、限流、Swagger保护 |
|
||||
| [登录流程-总览](技术设计/api-server/已完成/[已完成]-登录流程/总览.md) | 登录系统整体设计:前后端职责、Token 策略、5 个 API 接口规划 |
|
||||
| [登录流程-Apple登录集成](技术设计/api-server/已完成/[已完成]-登录流程/Apple登录集成.md) | Sign in with Apple 后端实现:jose 验签、JWKS、字段信任模型 |
|
||||
| [登录流程-后端接口](技术设计/api-server/已完成/[已完成]-登录流程/后端接口.md) | dev-login / refresh / logout / /users/me 四个接口的详细实现 |
|
||||
| [登录流程-数据库设计](技术设计/api-server/已完成/[已完成]-登录流程/数据库设计.md) | users / auth_accounts / refresh_tokens 三表 Prisma Schema |
|
||||
|
||||
### ios-projects(iOS 客户端)
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [进行中-架构设计](技术设计/ios-projects/[进行中]-架构设计.md) | 当前项目文件结构、导航架构、与计划架构的差异表(28项未实现),UI 层完成但无 MVVM |
|
||||
| [设计中-登录集成](技术设计/ios-projects/[设计中]-登录集成.md) | iOS 端登录设计:AuthService、Keychain 存储、Token 自动刷新、401 重试,均未实现 |
|
||||
| [样式规范](技术设计/ios-projects/已完成/[已完成]-样式规范.md) | 完整设计系统:颜色、渐变、圆角、间距、字体、29 个共享组件、页面模板 |
|
||||
| [页面规划](技术设计/ios-projects/已完成/[已完成]-页面规划.md) | 22 个页面完整清单,UI 层全部实现(Onboarding 5页 + 主Tab 5页 + 子页12页) |
|
||||
|
||||
### web-projects(官网)
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [设计中-设计文档](技术设计/web-projects/[设计中]-设计文档.md) | 官网视觉设计系统:"Luminous Clarity" 玻璃拟态浅色主题 |
|
||||
|
||||
### miniapp-projects(微信小程序)
|
||||
|
||||
> 暂无文档,预留目录。
|
||||
|
||||
### harmonyos-projects(鸿蒙)
|
||||
|
||||
> 暂无文档,预留目录。
|
||||
|
||||
### admin-projects(后台管理)
|
||||
|
||||
> 暂无文档,预留目录。
|
||||
|
||||
### android-projects / webApp-projects
|
||||
|
||||
> 暂无文档,预留目录。
|
||||
|
||||
---
|
||||
|
||||
## 开发计划
|
||||
|
||||
### 跨项目
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [进行中-阶段路线图](开发计划/[进行中]-阶段路线图.md) | 产品 9 阶段整体路线。阶段0官网部分已完成,阶段1方向选择进行中 |
|
||||
| [进行中-潜在问题清单](开发计划/[进行中]-潜在问题清单.md) | 代码和策略中已发现问题,按🔴严重/🟠高危/🟡中危分级,持续更新(最新:2026-05-15) |
|
||||
|
||||
### api-server
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [进行中-后端开发优先级](开发计划/api-server/[进行中]-后端开发优先级.md) | 51 模块 14 层级总表 + 8 阶段开发路线 + 每个模块接口/表结构/流程详案 |
|
||||
|
||||
### ios-projects
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [参考-功能需求清单](开发计划/ios-projects/[参考]-功能需求清单.md) | 从 v0.1 创业计划提取的 iOS 功能需求基线 |
|
||||
| [进行中-缺失项与待补全方向](开发计划/ios-projects/[进行中]-缺失项与待补全方向.md) | iOS 架构/页面/功能/设计缺失项梳理,含 P0/P1/P2 优先级 |
|
||||
| [差距分析](开发计划/ios-projects/已完成/[已完成]-差距分析.md) | 两轮审计快照合并:现有资源盘点 + P0 任务分解 |
|
||||
|
||||
### web-projects / android-projects / webApp-projects
|
||||
|
||||
> 暂无开发计划文档,预留目录。
|
||||
|
||||
---
|
||||
|
||||
## 长期规划
|
||||
|
||||
### 产品方向
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [进行中-个人开发者创业计划](长期规划/[进行中]-个人开发者创业计划.md) | 整体创业策略:Apple-first、验证优先级、长期架构 |
|
||||
| [参考-产品与用户模块](长期规划/[参考]-产品与用户模块.md) | 产品定位、目标用户、核心价值主张 |
|
||||
| [参考-产品方向深度评估](长期规划/[参考]-产品方向深度评估.md) | 知识库方向选择评估维度和候选方案 |
|
||||
| [参考-技术与交付模块](长期规划/[参考]-技术与交付模块.md) | 技术选型决策、开发流程、交付标准 |
|
||||
|
||||
### 商业化
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [进行中-商业化与支付模块](长期规划/[进行中]-商业化与支付模块.md) | 订阅定价、Apple IAP、会员权益体系 |
|
||||
|
||||
### 营销与增长
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [进行中-营销与增长模块](长期规划/营销与增长/[进行中]-营销与增长模块.md) | 营销策略总纲 |
|
||||
| [参考-营销冷启动调研方案](长期规划/营销与增长/[参考]-营销冷启动调研方案.md) | 冷启动阶段获客调研方案 |
|
||||
| [参考-冷启动与增长深度调研](长期规划/营销与增长/[参考]-冷启动与增长深度调研.md) | 增长策略深度调研 |
|
||||
|
||||
### 运营与客服
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [进行中-运营与客服模块](长期规划/运营与客服/[进行中]-运营与客服模块.md) | 运营策略总纲 |
|
||||
| [参考-客服设计详案](长期规划/运营与客服/[参考]-客服设计详案.md) | 客服流程和工单系统设计 |
|
||||
|
||||
### 合规与数据
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [设计中-数据反馈与迭代模块](长期规划/[设计中]-数据反馈与迭代模块.md) | 数据埋点、用户反馈收集、迭代流程 |
|
||||
| [设计中-合规与公司化模块](长期规划/[设计中]-合规与公司化模块.md) | 公司注册、ICP备案、隐私合规、Apple审核要求 |
|
||||
|
||||
---
|
||||
|
||||
## 快速定位
|
||||
|
||||
| 我想知道... | 看这个 |
|
||||
|-------------|--------|
|
||||
| 后端整体怎么设计? | [技术设计/api-server/架构总览](技术设计/api-server/[进行中]-架构总览.md) |
|
||||
| 数据库有哪些表? | [技术设计/api-server/数据库设计](技术设计/api-server/已完成/[已完成]-数据库设计.md) |
|
||||
| 登录怎么做? | [技术设计/api-server/登录流程/总览](技术设计/api-server/已完成/[已完成]-登录流程/总览.md) |
|
||||
| iOS App 架构? | [技术设计/ios-projects/架构设计](技术设计/ios-projects/[进行中]-架构设计.md) |
|
||||
| 接下来做什么? | [开发计划/阶段路线图](开发计划/[进行中]-阶段路线图.md) |
|
||||
| 后端先开发哪些? | [开发计划/api-server/后端开发优先级](开发计划/api-server/[进行中]-后端开发优先级.md) |
|
||||
| iOS 还差什么? | [开发计划/ios-projects/缺失项与待补全方向](开发计划/ios-projects/[进行中]-缺失项与待补全方向.md) |
|
||||
| 有哪些已知问题? | [开发计划/潜在问题清单](开发计划/[进行中]-潜在问题清单.md) |
|
||||
| 产品方向怎么定的? | [长期规划/产品方向深度评估](长期规划/[参考]-产品方向深度评估.md) |
|
||||
| 怎么收费? | [长期规划/商业化与支付模块](长期规划/[进行中]-商业化与支付模块.md) |
|
||||
| 怎么获客? | [长期规划/营销与增长/营销冷启动调研方案](长期规划/营销与增长/[参考]-营销冷启动调研方案.md) |
|
||||
| 服务器密码、SSH密钥? | [凭据配置/服务器凭据](凭据配置/服务器凭据.md) |
|
||||
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 842 KiB After Width: | Height: | Size: 842 KiB |
@ -15,9 +15,9 @@
|
||||
| 2 | 后端 `infrastructure/queue/queue.service.ts` | 队列是内存数组 `push/shift`,不是 BullMQ,没接 Redis | 队列任务重启丢失,无可靠异步处理 |
|
||||
| 3 | 后端 3 个 Worker 文件 | 全是空壳(只有 `console.log` + `setInterval`),没有真正消费队列 | 异步任务(AI分析/导入/通知)全部未生效 |
|
||||
| 4 | 后端 `.gitea/workflows/deploy.yml` | 数据库密码、Redis 密码、JWT Secret、Swagger 密码全部明文硬编码 | 任何人拿到仓库就能访问生产环境 |
|
||||
| 5 | 后端 `服务器密钥/WangDL.pem` | SSH 密钥已提交到 Git,`.gitignore` 没排除 | 密钥泄露风险 |
|
||||
| 5 | 后端 `服务器密钥/WangDL.pem` | ~~SSH 密钥已提交到 Git~~ ✅ 已从工作目录删除,移至 `startup-plan/凭据配置/` 并已 gitignore | 密钥泄露风险已消除 |
|
||||
| 6 | iOS 全部 View 文件 | 自定义 `NavigationLink(destination:label:)` 没有定义,SwiftUI 原生签名不同 | **项目无法编译** |
|
||||
| 7 | iOS `Core/Network/APIConfig.swift` + `Info.plist` | `baseURL` 使用 `http://` 明文,`NSAllowsArbitraryLoads = true` | **App Store 审核必然被拒** |
|
||||
| 7 | iOS `Core/Network/APIConfig.swift` + `Info.plist` | ✅ `baseURL` 已改为 `https://api.longde.cloud`,`NSAllowsArbitraryLoads` 已移除 | App Store 审核合规 |
|
||||
|
||||
---
|
||||
|
||||
@ -86,10 +86,10 @@ Web C 端 / B 端
|
||||
- [ ] 项目总纲
|
||||
- [ ] 产品定位与假设
|
||||
- [ ] 第一版知识库候选方向
|
||||
- [ ] 官网基础页面
|
||||
- [ ] 隐私政策初版
|
||||
- [ ] 用户协议初版
|
||||
- [ ] 等待名单页面
|
||||
- [x] 官网基础页面
|
||||
- [x] 隐私政策初版
|
||||
- [x] 用户协议初版
|
||||
- [x] 等待名单页面
|
||||
|
||||
***
|
||||
|
||||
@ -285,7 +285,7 @@ AI 分析页
|
||||
### 阶段产出
|
||||
|
||||
- [ ] iPhone MVP v0.1
|
||||
- [ ] 官网 v0.1
|
||||
- [x] 官网 v0.1
|
||||
- [ ] 可在自己手机上测试
|
||||
- [ ] 基础学习闭环跑通
|
||||
|
||||
0
开发计划/admin-projects/.gitkeep
Normal file
0
开发计划/admin-projects/.gitkeep
Normal file
0
开发计划/android-projects/.gitkeep
Normal file
0
开发计划/android-projects/.gitkeep
Normal file
@ -1,3 +1,81 @@
|
||||
# 后端开发优先级
|
||||
|
||||
> 知习后端完整模块清单(51 个模块,14 个层级)及分 8 阶段开发路线图。
|
||||
> 详案见:[后端完全体优先级详案](./后端完全体优先级详案.md)
|
||||
|
||||
---
|
||||
|
||||
## 总优先级总表
|
||||
|
||||
| 优先级 | 层级 | 核心模块 |
|
||||
|--------|------|----------|
|
||||
| P0 | 后端地基 | 安全配置、数据库(Prisma+MySQL)、统一工程规范(响应/错误/DTO/Guard) |
|
||||
| P1 | 身份权限 | Auth(Apple/Refresh/Logout)、Users、Role、Resource Permission |
|
||||
| P2 | 知识系统 | KnowledgeBase、KnowledgeItem、Tag、Search |
|
||||
| P3 | 学习闭环 | LearningSession、ActiveRecall、AIAnalysis、FocusItem、Review、LearningActivity |
|
||||
| P4 | AI 基础设施 | AIGateway、PromptTemplate、AIUsageLog、AIQuota、AIWorkflow |
|
||||
| P5 | 文件导入 | File/Storage、DocumentImport、KnowledgeGeneration |
|
||||
| P6 | 商业化 | Plans、Membership、Subscription(Apple IAP)、Payment、Refund |
|
||||
| P7 | 用户 Web 后台 | Web Console、批量上传/导入/导出 |
|
||||
| P8 | 管理员后台 | Admin Users、Admin Knowledge、AI Cost、Feedback、Audit Log |
|
||||
| P9 | 客服反馈 | Feedback、SupportTicket、Dify 智能客服、HelpCenter |
|
||||
| P10 | 通知任务 | Notifications、Push(APNs)、BullMQ Worker、Scheduler |
|
||||
| P11 | 学习画像 | LearningAnalytics、UserLearningProfile、LearningReport |
|
||||
| P12 | 公开分享 | Visibility、ShareLink、Public Knowledge |
|
||||
| P13 | 合规配置 | SystemConfig、Privacy、Delete Account、Data Export |
|
||||
| P14 | 增长归因 | Attribution、ProductAnalytics、Campaign Tracking |
|
||||
|
||||
---
|
||||
|
||||
## 8 阶段开发路线
|
||||
|
||||
### 第一阶段:能真实使用
|
||||
安全、数据库、登录、用户、权限、知识库、知识点
|
||||
> 目标:用户可以登录并创建自己的知识库。
|
||||
|
||||
### 第二阶段:形成学习闭环
|
||||
学习会话、主动回忆、AI 分析、待巩固项、复习卡片、学习活跃、AI Usage Log
|
||||
> 目标:从输入知识走到主动输出、AI 反馈、复习。
|
||||
|
||||
### 第三阶段:支持真实内容导入
|
||||
文件上传、文档导入、AI 切分知识点、导入队列、Worker
|
||||
> 目标:用户可以上传资料并转成知识库。
|
||||
|
||||
### 第四阶段:商业化
|
||||
会员权益、AI 额度、套餐、Apple IAP、订阅通知、退款处理
|
||||
> 目标:用户可以付费,系统可以控制成本。
|
||||
|
||||
### 第五阶段:运营后台
|
||||
管理员后台、用户管理、知识库元数据、反馈管理、AI 成本看板、审计日志
|
||||
> 目标:可以运营这个产品。
|
||||
|
||||
### 第六阶段:客服和支持
|
||||
反馈、工单、Dify 智能客服、帮助中心
|
||||
> 目标:基础问题自动回答,复杂问题进工单。
|
||||
|
||||
### 第七阶段:学习画像和 Agent
|
||||
用户学习画像、长期趋势、周报月报、AI 工作流、Learning Agent
|
||||
> 目标:系统开始越来越懂用户。
|
||||
|
||||
### 第八阶段:公开知识库和社区
|
||||
公开知识库、分享链接、官方模板库、举报审核
|
||||
> 目标:从个人学习工具扩展到内容和社区。
|
||||
|
||||
---
|
||||
|
||||
## 最终形态
|
||||
|
||||
```
|
||||
用户系统 + 权限系统 + 知识库系统 + 学习闭环系统 + AI 工作流系统
|
||||
+ 复习系统 + 成本控制系统 + 订阅系统 + 文件导入系统
|
||||
+ 后台管理系统 + 客服工单系统 + 学习画像系统 + 合规系统 + 增长归因系统
|
||||
```
|
||||
|
||||
核心开发顺序:**身份权限 → 知识系统 → 学习闭环 → AI 基础设施 → 文件导入 → 商业化 → 后台 → 客服 → 学习画像 → 公开分享 → 增长归因**
|
||||
|
||||
|
||||
---
|
||||
|
||||
明白,你要的不是“现在别做什么”,而是:
|
||||
|
||||
```text
|
||||
0
开发计划/harmonyos-projects/.gitkeep
Normal file
0
开发计划/harmonyos-projects/.gitkeep
Normal file
339
开发计划/ios-projects/[参考]-功能需求清单.md
Normal file
339
开发计划/ios-projects/[参考]-功能需求清单.md
Normal file
@ -0,0 +1,339 @@
|
||||
# 个人开发者创业 v0.1 — iOS 相关需求整理
|
||||
|
||||
> 来源:`startup-plan/个人开发者创业 v0.1/` 各文档
|
||||
> 整理时间:2026-05-10
|
||||
|
||||
本文档从 v0.1 创业计划中提取所有与 iOS 客户端直接相关的内容,作为 iOS 开发的参考基线。
|
||||
|
||||
---
|
||||
|
||||
## 一、产品定位(来源:`0-项目总纲/项目总纲.md`)
|
||||
|
||||
- 产品长期方向:AI 驱动的系统化学习产品(知识库 + 笔记 + AI 学习教练 + 复习计划)
|
||||
- 当前只做三件事:确定方向 → 做 14 天验证 Demo → 找第一批真实反馈
|
||||
- 平台策略:**只做 iPhone**,不做 Android/iPad/Mac/Web 学习端
|
||||
- 不做:完整平台、泛学习大而全、复杂后端、支付
|
||||
|
||||
### 三个候选方向
|
||||
|
||||
1. 公考申论 AI 学习教练
|
||||
2. AI 工具学习知识库
|
||||
3. 程序员/前端面试学习助手
|
||||
|
||||
---
|
||||
|
||||
## 二、第一版产品形态(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
```
|
||||
iPhone App + 官网基础页面 + 最小后端 + AI API
|
||||
```
|
||||
|
||||
### MVP 核心学习闭环
|
||||
|
||||
```
|
||||
注册/登录 → 选择学习方向 → 进入学习路径 → 阅读知识内容
|
||||
→ 主动回忆/写笔记/写答案 → AI 分析 → 生成学习状态
|
||||
→ 给出复习和下一步建议 → 进入下一次学习
|
||||
```
|
||||
|
||||
### 第一版页面列表(计划 14 页)
|
||||
|
||||
| 优先级 | 页面 | 当前 iOS 实现 |
|
||||
|--------|------|---------------|
|
||||
| **P0** | 登录页 | `LoginPage` ✅ |
|
||||
| **P0** | 学习方向选择页 | `GoalSetupPage` ✅ (部分) |
|
||||
| **P0** | 学习路径页 | `LibraryHomeView` + `LibraryDetailPage` ✅ |
|
||||
| **P0** | 今日学习任务页 | `StudyHomeView` ✅ |
|
||||
| **P0** | 内容阅读页 | `KnowledgeDetailPage` ✅ |
|
||||
| **P0** | 主动回忆/笔记输入页 | `DailyThinkingPage` + `RecallTestPage` ✅ |
|
||||
| **P0** | AI 分析结果页 | `AIFeedbackPage` ✅ |
|
||||
| **P0** | AI 对话页 | `AIChatPage` ✅ |
|
||||
| **P0** | 复习计划页 | 未独立实现 ⚠️ (部分在 StudyHomeView) |
|
||||
| **P1** | 学习进度页 | `AnalysisHomeView` ✅ |
|
||||
| **P1** | 设置页 | `ProfileView` ✅ |
|
||||
| **P1** | 反馈页 | 未实现 ❌ |
|
||||
| **P1** | 启动页/欢迎页 | `SplashPage` + `WelcomePage` ✅ |
|
||||
| **P1** | 语言与基础偏好页 | 未实现 ❌ |
|
||||
|
||||
### 底部 Tab 设计(计划)
|
||||
|
||||
```
|
||||
学习 | 知识库 | AI助手 | 我的
|
||||
```
|
||||
|
||||
当前 iOS 实现为 5 个 Tab:`AI | 知识库 | 学习 | 分析 | 我的`(多了"分析"Tab,将计划的 AI 助手拆分为独立的分析页)
|
||||
|
||||
---
|
||||
|
||||
## 三、账号体系(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
- **第一版登录方式**:Sign in with Apple
|
||||
- **暂不做**:微信登录、手机号登录、邮箱密码登录、Google 登录
|
||||
|
||||
> ⚠️ 当前 iOS `LoginPage` 包含了手机号/邮箱登录 + 微信/Apple 登录 UI,与计划"A Sign in with Apple"的要求不完全一致。计划强调极简,实际 UI 做了更多登录方式入口。
|
||||
|
||||
### 用户身份模型(计划)
|
||||
|
||||
```
|
||||
User
|
||||
├── id
|
||||
├── appleUserId
|
||||
├── displayName
|
||||
├── email
|
||||
├── preferredLanguage
|
||||
├── createdAt
|
||||
├── lastLoginAt
|
||||
└── status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、知识库设计(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
### 数据结构
|
||||
|
||||
```
|
||||
KnowledgeBase → LearningPath → Module → Lesson
|
||||
├── 正文内容
|
||||
├── 学习目标
|
||||
├── 重点概念
|
||||
├── 主动回忆问题
|
||||
├── 练习输入
|
||||
└── AI 分析规则
|
||||
```
|
||||
|
||||
### 第一版内容范围
|
||||
|
||||
只做一个小路径,例如"AI 工具入门 7 天路径",而不是大而全的知识库市场。
|
||||
|
||||
---
|
||||
|
||||
## 五、AI 能力需求(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
### AI 三大核心职责
|
||||
|
||||
1. 分析用户输入
|
||||
2. 判断用户当前学习状态
|
||||
3. 给出下一步学习建议
|
||||
|
||||
### AI 分析维度
|
||||
|
||||
```
|
||||
理解程度、要点覆盖、逻辑结构、表达清晰度、错误理解、遗漏内容、下一步建议
|
||||
```
|
||||
|
||||
### AI 输出结构(计划 JSON Schema)
|
||||
|
||||
```json
|
||||
{
|
||||
"masteryScore": 3,
|
||||
"understandingLevel": "基本理解",
|
||||
"summary": "用户能说出核心意思,但要点不够完整。",
|
||||
"strengths": ["能识别主要问题", "表达比较清楚"],
|
||||
"weakPoints": ["遗漏关键要点", "逻辑层次不够清晰"],
|
||||
"suggestions": ["补充材料中的第二个要点", "回答时先概括问题,再展开原因"],
|
||||
"reviewNeeded": true,
|
||||
"nextAction": "建议明天复习本节,并重新回答主动回忆问题。"
|
||||
}
|
||||
```
|
||||
|
||||
### 掌握度评分(0-5)
|
||||
|
||||
```
|
||||
0 = 没有作答/无法判断
|
||||
1 = 基本没理解
|
||||
2 = 理解较弱
|
||||
3 = 基本理解
|
||||
4 = 理解较好
|
||||
5 = 掌握很好
|
||||
```
|
||||
|
||||
### AI 对话页定位
|
||||
|
||||
只能围绕当前知识库和学习内容,不能做泛聊天。快捷问题预设:
|
||||
- 帮我解释这一节
|
||||
- 用更简单的话讲
|
||||
- 给我举个例子
|
||||
- 我哪里理解错了
|
||||
- 帮我总结重点
|
||||
- 生成一个复习问题
|
||||
|
||||
---
|
||||
|
||||
## 六、学习状态模型(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
### 用户学习画像
|
||||
|
||||
```
|
||||
UserLearningProfile
|
||||
├── userId
|
||||
├── currentKnowledgeBaseId
|
||||
├── currentPathId
|
||||
├── currentLessonId
|
||||
├── overallLevel
|
||||
├── weakPoints
|
||||
├── strengths
|
||||
├── recentMistakes
|
||||
├── reviewQueue
|
||||
├── learningStreak
|
||||
└── updatedAt
|
||||
```
|
||||
|
||||
### 单次学习记录
|
||||
|
||||
```
|
||||
LearningSession
|
||||
├── id
|
||||
├── userId
|
||||
├── lessonId
|
||||
├── startedAt
|
||||
├── endedAt
|
||||
├── userInput
|
||||
├── aiAnalysis
|
||||
├── masteryScore
|
||||
├── weakPoints
|
||||
├── nextSuggestion
|
||||
└── reviewAt
|
||||
```
|
||||
|
||||
### 复习任务
|
||||
|
||||
```
|
||||
ReviewTask
|
||||
├── id
|
||||
├── userId
|
||||
├── lessonId
|
||||
├── sourceSessionId
|
||||
├── reviewType
|
||||
├── scheduledAt
|
||||
├── completedAt
|
||||
└── status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、UI 设计原则(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
```
|
||||
安静、清晰、克制、学习感、低干扰、Apple原生感、卡片式结构、适合长时间阅读
|
||||
```
|
||||
|
||||
- 不做花哨视觉
|
||||
- 不做复杂动画
|
||||
- 不做社交信息流
|
||||
- 不做游戏化过重设计
|
||||
- 优先保证阅读体验
|
||||
- 优先保证学习任务清晰
|
||||
- 优先保证 AI 分析结果可理解
|
||||
|
||||
---
|
||||
|
||||
## 八、技术选型(来源:`3-官网与技术基础/官网与技术基础.md`)
|
||||
|
||||
| 项目 | 计划选型 | 当前实现 |
|
||||
|------|----------|----------|
|
||||
| UI 框架 | SwiftUI | SwiftUI ✅ |
|
||||
| 架构模式 | MVVM + Service + Repository | 无分层(View 内聚)⚠️ |
|
||||
| 设计规范 | Apple HIG | 深色主题 + 自定义 DesignTokens ✅ |
|
||||
| 动效策略 | 轻量、有意义、服务学习体验 | 最小动效(仅基础过渡)⚠️ |
|
||||
| 多语言 | 预留架构,中文默认 | 未实现 ❌ |
|
||||
| 部署 | 4 核 4G 轻量云 + Nginx + Docker | 未接入 ❌ |
|
||||
|
||||
### 目录结构(计划 vs 实际)
|
||||
|
||||
计划定义了完整的分层目录(App/Core/Features/Shared/Resources),当前实现仅有 Features 和 DesignSystem,缺少 Network、Auth、Storage、Localization、ViewModel、Model 等层。
|
||||
|
||||
### 第一版 iOS 不做(来自计划)
|
||||
|
||||
- 复杂动画系统
|
||||
- iPad 专门布局 / Mac Catalyst / Watch App / Widget
|
||||
- 离线完整知识库
|
||||
- 复杂搜索
|
||||
- 文件导入
|
||||
- 推送通知
|
||||
- 支付订阅
|
||||
- 复杂自定义控件
|
||||
|
||||
---
|
||||
|
||||
## 九、数据实体汇总(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
```
|
||||
User
|
||||
KnowledgeBase
|
||||
LearningPath
|
||||
Lesson
|
||||
LearningSession
|
||||
AIAnalysis
|
||||
ReviewTask
|
||||
Feedback
|
||||
WaitlistEntry
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、核心 API 接口(来源:`3-官网与技术基础/官网与技术基础.md`)
|
||||
|
||||
### POST /ai/analyze-learning-input
|
||||
|
||||
分析用户学习输入,返回掌握度评估。
|
||||
|
||||
### POST /ai/chat
|
||||
|
||||
AI 对话接口,限于当前知识库上下文。
|
||||
|
||||
### 后端模块(P0)
|
||||
|
||||
Auth → User → Knowledge → Learning → AI → Review → Feedback → Waitlist
|
||||
|
||||
---
|
||||
|
||||
## 十一、成功标准(来源:`2-Demo与MVP/Demo与MVP.md`)
|
||||
|
||||
### 产品可用标准
|
||||
|
||||
- 用户能登录
|
||||
- 用户能选择学习路径
|
||||
- 用户能完成一节学习
|
||||
- 用户能输入内容
|
||||
- AI 能返回分析
|
||||
- 系统能生成复习建议
|
||||
- 用户知道下一步该干什么
|
||||
|
||||
### 验证成功标准
|
||||
|
||||
- 至少 10 个用户愿意试用
|
||||
- 至少 3 个用户完整走完学习闭环
|
||||
- 至少 3 条有效反馈
|
||||
- 至少 1 个用户表示愿意继续用
|
||||
- 至少 1 个用户表示未来愿意付费
|
||||
|
||||
---
|
||||
|
||||
## 十二、暂缓事项(来源:`99-暂缓事项/暂缓事项.md`)
|
||||
|
||||
以下为 v0.1 明确不做、后续解冻的事项:
|
||||
|
||||
| 类别 | 暂缓内容 | 解冻条件 |
|
||||
|------|----------|----------|
|
||||
| 商业化 | Apple IAP、订阅、免费试用 | TestFlight 有真实用户 + 有人愿意付费 |
|
||||
| 运营 | 社群、客服机器人、打卡活动 | 10+ 内测用户持续反馈 |
|
||||
| 数据 | 完整埋点、留存分析、付费转化 | App Store MVP 准备上线 |
|
||||
| 合规 | 公司注册、微信/支付宝、备案 | Apple 端稳定收入 |
|
||||
| 多端 | iPad、Mac、Android、Web | iPhone 核心稳定 + 用户多端需求 |
|
||||
|
||||
---
|
||||
|
||||
## 十三、当前 iOS 实现与计划的差距
|
||||
|
||||
| 维度 | 计划要求 | 当前状态 | 差距 |
|
||||
|------|----------|----------|------|
|
||||
| 登录 | Sign in with Apple | 多种登录 UI | 需简化或实现 Apple 登录 |
|
||||
| 架构 | MVVM + Service | View 内聚 | 需重构分层 |
|
||||
| 多语言 | 架构预留 | 未实现 | 需添加本地化 |
|
||||
| 后端对接 | REST API | 无 | 需接入 |
|
||||
| AI 集成 | 真实 AI 分析 | 静态 Mock | 需接入 AI API |
|
||||
| 数据持久化 | 本地缓存 + Keychain | 无 | 需实现 |
|
||||
| Tab 设计 | 4 个 Tab | 5 个 Tab | 多了"分析"Tab |
|
||||
| 反馈页 | P1 优先级 | 未实现 | 需添加 |
|
||||
| 复习计划页 | P0 优先级 | 部分实现 | 需独立设计 |
|
||||
1042
开发计划/ios-projects/[进行中]-缺失项与待补全方向.md
Normal file
1042
开发计划/ios-projects/[进行中]-缺失项与待补全方向.md
Normal file
File diff suppressed because it is too large
Load Diff
435
开发计划/ios-projects/已完成/[已完成]-差距分析.md
Normal file
435
开发计划/ios-projects/已完成/[已完成]-差距分析.md
Normal file
@ -0,0 +1,435 @@
|
||||
# iOS 差距分析
|
||||
|
||||
---
|
||||
|
||||
## 第一轮分析
|
||||
|
||||
# AIStudyApp 现状与缺口分析 - 第一篇:现有资源盘点
|
||||
|
||||
> 生成日期:2026-05-11
|
||||
> 后端地址:http://81.70.187.179:3001
|
||||
|
||||
---
|
||||
|
||||
## 一、项目文件结构
|
||||
|
||||
```
|
||||
AIStudyApp/
|
||||
├── AIStudyAppApp.swift # 应用入口,含 5 步 Onboarding 流程
|
||||
├── ContentView.swift # 主 Tab 框架(5 个 Tab + 自定义底部栏)
|
||||
│
|
||||
├── Core/
|
||||
│ ├── DesignSystem/DesignTokens.swift # 颜色/渐变/间距/字体全局设计令牌
|
||||
│ ├── Models/APIModels.swift # 20+ DTO 数据模型
|
||||
│ ├── Network/
|
||||
│ │ ├── APIClient.swift # 通用 HTTP 客户端(actor, async/await)
|
||||
│ │ ├── APIConfig.swift # baseURL 配置
|
||||
│ │ └── APIError.swift # 错误枚举(网络/服务端/解码/认证)
|
||||
│ └── Services/APIService.swift # 8 个服务类,15 个公开方法
|
||||
│
|
||||
├── Features/
|
||||
│ ├── AI/
|
||||
│ │ ├── AIHomeView.swift # AI 首页 + ZXQuickAction + ZXAIInteractionRow 组件
|
||||
│ │ └── DailyThinkingPage.swift # 每日思考题 + RecallTestPage / WeakPointsPage /
|
||||
│ │ # AIFeedbackPageView / AIChatPage 子页面
|
||||
│ ├── Analysis/
|
||||
│ │ └── AnalysisHomeView.swift # 学习分析页 + ZXChartView 折线图 + ZXWeakRow 薄弱点
|
||||
│ ├── Library/
|
||||
│ │ ├── LibraryHomeView.swift # 知识库列表首页
|
||||
│ │ └── LibrarySubpages.swift # CreateLibraryPage / LibraryDetailPage /
|
||||
│ │ # AddKnowledgePage / KnowledgeDetailPage /
|
||||
│ │ # ImportPage / EditKnowledgePage
|
||||
│ ├── Profile/
|
||||
│ │ └── ProfileView.swift # 个人中心页
|
||||
│ └── Study/
|
||||
│ └── StudyHomeView.swift # 学习工作台 + 今日任务 + 周活跃柱状图
|
||||
│
|
||||
└── Info.plist # 手动管理(ATS例外 / Bundle元数据等)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、5 个 Tab 页面清单
|
||||
|
||||
| Tab | 标签 | SF Symbol | View |
|
||||
|-----|------|-----------|------|
|
||||
| 1 | AI | `brain.head.profile` | AIHomeView |
|
||||
| 2 | 知识库 | `books.vertical.fill` | LibraryHomeView |
|
||||
| 3 | 学习 | `bolt.fill` | StudyHomeView |
|
||||
| 4 | 分析 | `chart.bar.fill` | AnalysisHomeView |
|
||||
| 5 | 我的 | `person.fill` | ProfileView |
|
||||
|
||||
---
|
||||
|
||||
## 三、所有页面/子页面总览(共 21 个)
|
||||
|
||||
### AI 模块(1 主 + 4 子)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| AIHomeView | 🔴硬编码 | API 状态检测、思考题卡片、快捷操作、互动记录、提问输入栏 |
|
||||
| DailyThinkingPage | 🔴硬编码 | AI 思考题展示 + 回答提交 |
|
||||
| RecallTestPage | 🔴硬编码 | 回忆测试输入 |
|
||||
| WeakPointsPage | 🔴硬编码 | 薄弱知识点静态列表 |
|
||||
| AIFeedbackPageView | 🔴硬编码 | AI 反馈评分 + 操作入口 |
|
||||
| AIChatPage | 🔴硬编码 | AI 对话气泡界面 |
|
||||
|
||||
### 知识库模块(1 主 + 6 子)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| LibraryHomeView | 🔴硬编码 | 知识库列表 + 搜索框 + 创建入口 |
|
||||
| CreateLibraryPage | 🔴静态 | 创建表单(名称+描述) |
|
||||
| LibraryDetailPage | 🔴硬编码 | 知识点静态列表 |
|
||||
| AddKnowledgePage | 🔴静态 | 添加知识点表单 |
|
||||
| KnowledgeDetailPage | 🔴硬编码 | 知识点详情+标签+复习/费曼入口 |
|
||||
| ImportPage | 🔴静态 | 导入方式选择(拍照/文件/链接/相册) |
|
||||
| EditKnowledgePage | 🔴静态 | 编辑知识点表单 |
|
||||
|
||||
### 学习模块(1 主)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| StudyHomeView | 🔴硬编码 | 今日进度环、任务列表(5个任务)、本周活跃柱状图 |
|
||||
|
||||
### 分析模块(1 主)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| AnalysisHomeView | 🔴硬编码 | 4项统计徽章、掌握度7日折线图、薄弱知识点列表 |
|
||||
|
||||
### 个人中心(1 主)
|
||||
|
||||
| 页面 | 数据来源 | 核心功能 |
|
||||
|------|---------|---------|
|
||||
| ProfileView | 🔴硬编码 | 个人卡片、菜单列表、成就徽章 |
|
||||
|
||||
### 启动流程(5 步 Onboarding)
|
||||
|
||||
| 步骤 | 页面 | 功能 |
|
||||
|------|------|------|
|
||||
| Step 0 | SplashPage | 品牌开屏,2 秒自动跳转 |
|
||||
| Step 1 | WelcomePage | 3 大功能介绍 |
|
||||
| Step 2 | LoginPage | 手机号/邮箱 + 密码表单 + 微信/Apple 登录入口 |
|
||||
| Step 3 | OnboardingPage | 4 步功能轮播 |
|
||||
| Step 4 | GoalSetupPage | 学习目标/方法/每日时长选择 |
|
||||
|
||||
---
|
||||
|
||||
## 四、APIService 已封装方法(15 个)
|
||||
|
||||
| 服务类 | 方法 | 接口 |
|
||||
|--------|------|------|
|
||||
| WaitlistService | `join(...)` | POST /waitlist |
|
||||
| | `stats()` | GET /waitlist/stats |
|
||||
| AuthService | `appleLogin(...)` | POST /auth/apple |
|
||||
| | `logout()` | POST /auth/logout |
|
||||
| UserService | `myProfile()` | GET /users/me |
|
||||
| | `updateProfile(...)` | PATCH /users/me |
|
||||
| KnowledgeBaseService | `list()` | GET /knowledge-bases |
|
||||
| | `create(...)` | POST /knowledge-bases |
|
||||
| | `detail(id:)` | GET /knowledge-bases/:id |
|
||||
| KnowledgeItemService | `list(baseId:)` | GET /knowledge-items |
|
||||
| | `detail(id:)` | GET /knowledge-items/:id |
|
||||
| | `create(...)` | POST /knowledge-items |
|
||||
| AIAnalysisService | `analyze(...)` | POST /ai-analysis |
|
||||
| ActivityService | `summary()` | GET /activity/summary |
|
||||
| ReviewService | `due()` | GET /reviews/due |
|
||||
| FocusItemService | `list()` | GET /focus-items |
|
||||
| FeedbackService | `submit(...)` | POST /feedback |
|
||||
|
||||
---
|
||||
|
||||
## 五、后端接口 vs App 覆盖对照表
|
||||
|
||||
| 后端模块 | 接口数 | App 覆盖 | 状态 |
|
||||
|----------|--------|---------|------|
|
||||
| System | 3 | 0 | ❌ 无 |
|
||||
| Auth | 3 | 2(Service 有,View 未接) | 🔶 |
|
||||
| Users | 3 | 2(Service 有,View 未接) | 🔶 |
|
||||
| KnowledgeBase | 5 | 3(Service 有,View 未接) | 🔶 |
|
||||
| KnowledgeItems | 4 | 3(Service 有,View 未接) | 🔶 |
|
||||
| DocumentImport | 2 | 0 | ❌ 无 |
|
||||
| LearningSession | 3 | 0 | ❌ 无 |
|
||||
| ActiveRecall | 2 | 0 | ❌ 无 |
|
||||
| AIAnalysis | 3 | 1(Service 有,View 未接) | 🔶 |
|
||||
| FocusItems | 4 | 1(Service 有,View 未接) | 🔶 |
|
||||
| Review | 2 | 1(Service 有,View 未接) | 🔶 |
|
||||
| LearningActivity | 2 | 1(Service 有,View 未接) | 🔶 |
|
||||
| Notifications | 2 | 0 | ❌ 无 |
|
||||
| Feedback | 4 | 1(Service 有,View 未接) | 🔶 |
|
||||
| Waitlist | 3 | 2(Service 有,View 未接) | 🔶 |
|
||||
|
||||
> 覆盖率:Service 层 15/48 = 31%,View 层实际接入 0/48 = 0%
|
||||
|
||||
---
|
||||
|
||||
## 第二轮分析
|
||||
|
||||
# AIStudyApp 现状与缺口分析 - 第二篇:缺失功能与实施路线
|
||||
|
||||
> 接第一篇《现有资源盘点》
|
||||
> 生成日期:2026-05-11
|
||||
|
||||
---
|
||||
|
||||
## 一、优先级总览
|
||||
|
||||
```
|
||||
P0(核心闭环,本周必须) 4 项
|
||||
P1(数据接入,下周) 5 项
|
||||
P2(新页面/功能,后续) 5 项
|
||||
P3(体验增强,优化期) 5 项
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、P0 —— 核心学习闭环(4 项)
|
||||
|
||||
### P0-1:真实 Apple 登录流程
|
||||
|
||||
**现状:** LoginPage 是静态表单,没有调 API,Token 没有持久化。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| 集成 `AuthenticationServices`,添加 `ASAuthorizationAppleIDButton` | LoginPage(内嵌在 AIStudyAppApp.swift) |
|
||||
| 拿到 `identityToken` 后调用 `AuthService.appleLogin(...)` | LoginPage |
|
||||
| 登录成功后用 `@AppStorage` 或 Keychain 存储 Token | APIClient |
|
||||
| `@main` 启动时检查已有 Token,跳过 Onboarding | AIStudyAppApp.swift |
|
||||
| 处理登录失败/网络错误的 UI 提示 | LoginPage |
|
||||
| 接入 `POST /auth/refresh` Token 自动刷新 | APIClient |
|
||||
|
||||
涉及接口:`POST /auth/apple`、`POST /auth/refresh`、`POST /auth/logout`
|
||||
|
||||
---
|
||||
|
||||
### P0-2:知识库 + 知识点接入真实 API
|
||||
|
||||
**现状:** LibraryHomeView 硬编码 4 个知识库,子页面表单没有提交。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| `LibraryHomeView` 的 `.task {}` 中调 `KnowledgeBaseService.list()` | LibraryHomeView.swift |
|
||||
| 替换硬编码卡片为 `ForEach(bases)` 真实数据 | LibraryHomeView.swift |
|
||||
| `CreateLibraryPage` 表单提交调 `KnowledgeBaseService.create(...)` | LibrarySubpages.swift |
|
||||
| `LibraryDetailPage` 加载真实知识点列表 `KnowledgeItemService.list(baseId:)` | LibrarySubpages.swift |
|
||||
| `AddKnowledgePage` 表单提交调 `KnowledgeItemService.create(...)` | LibrarySubpages.swift |
|
||||
| `EditKnowledgePage` 提交调 `PATCH /knowledge-items/:id`(APIService 需新增 update 方法) | LibrarySubpages.swift + APIService.swift |
|
||||
| 增加 loading / empty / error 三种状态处理 | 各 Library 页面 |
|
||||
|
||||
涉及接口:`GET/POST /knowledge-bases`、`GET/POST/PATCH /knowledge-items`
|
||||
|
||||
---
|
||||
|
||||
### P0-3:学习会话追踪
|
||||
|
||||
**现状:** StudyHomeView 的"今日任务"是静态列表,没有学习计时,没有调任何接口。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 / 新建文件 |
|
||||
|--------|-------------------|
|
||||
| 新建 `LearningSessionView.swift`:含计时器(`Timer.publish`)+ 暂停/结束按钮 | **新文件** Features/Study/LearningSessionView.swift |
|
||||
| 点击 StudyHomeView 任务 → push 到 LearningSessionView | StudyHomeView.swift |
|
||||
| 入场调 `POST /learning-sessions`(传入 knowledgeBaseId) | LearningSessionView.swift |
|
||||
| 结束/暂停时调 `POST /learning-sessions/:id/end` | LearningSessionView.swift |
|
||||
| APIService 新增 `LearningSessionService` | APIService.swift |
|
||||
| APIModels 新增 `LearningSessionCreateRequest` / `LearningSessionResponse` | APIModels.swift |
|
||||
|
||||
涉及接口:`POST /learning-sessions`、`POST /learning-sessions/:id/end`、`GET /learning-sessions`
|
||||
|
||||
---
|
||||
|
||||
### P0-4:间隔复习卡片
|
||||
|
||||
**现状:** 没有复习页面。后端 `GET /reviews/due` + `POST /reviews/:id/submit` 已就绪。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 新建文件 |
|
||||
|--------|---------|
|
||||
| 新建 `ReviewCardView.swift`:正面问题 → 点击翻转 → 显示答案 → 评分按钮 | **新文件** Features/Study/ReviewCardView.swift |
|
||||
| 评分按钮:Again(1) / Hard(2) / Good(3) / Easy(4),调 `POST /reviews/:id/submit` | ReviewCardView.swift |
|
||||
| 复习入口放在 StudyHomeView "今日任务"区域顶部 | StudyHomeView.swift |
|
||||
| 复习入口放在 AIHomeView 快捷操作中 | AIHomeView.swift |
|
||||
| 到期卡片数为 0 时显示空状态"🎉 都复习完啦" | ReviewCardView.swift |
|
||||
|
||||
涉及接口:`GET /reviews/due`、`POST /reviews/:id/submit`
|
||||
|
||||
---
|
||||
|
||||
## 三、P1 —— 数据接入(5 项)
|
||||
|
||||
### P1-1:薄弱点 / AI 分析接真实数据
|
||||
|
||||
**现状:** AnalysisHomeView / WeakPointsPage 硬编码 3 条数据。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| AnalysisHomeView `.task {}` 中调 `FocusItemService.list()` | AnalysisHomeView.swift |
|
||||
| 替换硬编码 ZXWeakRow 为 `ForEach(focusItems)` | AnalysisHomeView.swift |
|
||||
| RecallTestPage 提交回答时调 `AIAnalysisService.analyze(...)` | DailyThinkingPage.swift |
|
||||
| AIFeedbackPageView 展示真实分析结果 | DailyThinkingPage.swift |
|
||||
| APIModels 增补 FocusItem 字段对齐后端 | APIModels.swift |
|
||||
|
||||
涉及接口:`GET /focus-items`、`POST /ai-analysis`、`GET /ai-analysis/:id`
|
||||
|
||||
---
|
||||
|
||||
### P1-2:StudyHomeView 数据真实化
|
||||
|
||||
**现状:** 进度环、任务列表、周活跃柱状图全是硬编码。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| 调 `ActivityService.summary()` 获取真实统计数据 | StudyHomeView.swift |
|
||||
| 进度环用真实 `totalMinutes` / `streakDays` | StudyHomeView.swift |
|
||||
| 周活跃图调 `GET /activity/heatmap`(APIService 需新增 heatmap 方法) | StudyHomeView.swift + APIService.swift |
|
||||
| 今日任务从 `GET /reviews/due` + `GET /focus-items` 拼接 | StudyHomeView.swift |
|
||||
|
||||
涉及接口:`GET /activity/summary`、`GET /activity/heatmap`
|
||||
|
||||
---
|
||||
|
||||
### P1-3:ProfileView 接入用户资料
|
||||
|
||||
**现状:** ProfileView 全部静态假数据(昵称"学习者"、假统计)。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| `.task {}` 调 `UserService.myProfile()` | ProfileView.swift |
|
||||
| 替换头像(emoji → 真实 avatar URL / 默认头像) | ProfileView.swift |
|
||||
| 替换昵称、邮箱、统计数字 | ProfileView.swift |
|
||||
| 菜单项"学习目标设置"跳设置表单页 → `PATCH /users/me/preferences` | ProfileView.swift + 新 SettingsView |
|
||||
|
||||
涉及接口:`GET /users/me`、`PATCH /users/me`、`PATCH /users/me/preferences`
|
||||
|
||||
---
|
||||
|
||||
### P1-4:通知中心页面
|
||||
|
||||
**现状:** 完全没有通知页面。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 新建/涉及文件 |
|
||||
|--------|-------------|
|
||||
| 新建 `NotificationListView.swift` | **新文件** Features/Profile/NotificationListView.swift |
|
||||
| `.task {}` 调 `GET /notifications` | NotificationListView.swift |
|
||||
| 列表项点击标记已读 `POST /notifications/:id/read` | NotificationListView.swift |
|
||||
| ProfileView 右上角铃铛 badge 显示未读数 | ProfileView.swift |
|
||||
| APIService 新增 `NotificationService` | APIService.swift |
|
||||
|
||||
涉及接口:`GET /notifications`、`POST /notifications/:id/read`
|
||||
|
||||
---
|
||||
|
||||
### P1-5:反馈提交
|
||||
|
||||
**现状:** 没有反馈提交入口。
|
||||
|
||||
**需要做:**
|
||||
|
||||
| 子任务 | 涉及文件 |
|
||||
|--------|---------|
|
||||
| ProfileView 菜单加"帮助与反馈" → 跳反馈表单 | ProfileView.swift + 新 FeedbackView |
|
||||
| 调 `FeedbackService.submit(...)` | 新 FeedbackView |
|
||||
| 提交后显示"感谢反馈"提示 | 新 FeedbackView |
|
||||
|
||||
涉及接口:`POST /feedback`
|
||||
|
||||
---
|
||||
|
||||
## 四、P2 —— 新页面/功能(5 项)
|
||||
|
||||
### P2-1:文件导入真实接入
|
||||
|
||||
**现状:** ImportPage 只有 4 个静态按钮。
|
||||
|
||||
**需要做:** 接入 `PHPickerViewController`(相册选图)、`UIDocumentPickerViewController`(文件选择)、AVCaptureSession(拍照),上传后调 `POST /imports`,轮询 `GET /imports/:id/status`。APIService 新增 `DocumentImportService`。
|
||||
|
||||
---
|
||||
|
||||
### P2-2:全局搜索
|
||||
|
||||
**现状:** LibraryHomeView 有搜索框但无效。
|
||||
|
||||
**需要做:** 新建 `SearchView.swift`,调 `GET /knowledge-items?keyword=xxx`,支持搜索知识点/知识库/标签,展示搜索结果列表。
|
||||
|
||||
---
|
||||
|
||||
### P2-3:设置页面完善
|
||||
|
||||
**现状:** ProfileView 5 个菜单项全是假的。
|
||||
|
||||
**需要做:** 每个菜单项对应一个设置表单页:学习目标、复习提醒时间、学习报告邮件、学习方法偏好(费曼/回忆/间隔/综合)、数据同步状态。
|
||||
|
||||
---
|
||||
|
||||
### P2-4:主动回忆(Active Recall)流程
|
||||
|
||||
**现状:** RecallTestPage 只提交假的 AI 分析,没有调 `GET /active-recalls`。
|
||||
|
||||
**需要做:** 新建 ActiveRecallView,展示问题卡片 → 输入回答 → 调 `POST /active-recalls/:id/submit`。
|
||||
|
||||
---
|
||||
|
||||
### P2-5:Token 自动刷新与登录态管理
|
||||
|
||||
**现状:** Token 没有持久化,没有 refresh 逻辑。
|
||||
|
||||
**需要做:** Keychain 存储 accessToken + refreshToken;APIClient 拦截 401 → 自动调 `POST /auth/refresh` → 重试原请求;refresh 也失败 → 清 Token → 跳登录页。
|
||||
|
||||
---
|
||||
|
||||
## 五、P3 —— 体验增强(5 项)
|
||||
|
||||
| # | 项目 | 说明 |
|
||||
|---|------|------|
|
||||
| P3-1 | 下拉刷新 | 所有列表页 `.refreshable {}` + 页码分页 |
|
||||
| P3-2 | 加载/空/错误三态 | 每个数据加载页加 ProgressView / 空状态插图+文案 / 错误重试按钮 |
|
||||
| P3-3 | 离线缓存 | 用 UserDefaults 或本地 JSON 缓存最近数据,断网可展示 |
|
||||
| P3-4 | 深色模式 | 当前强制 `.dark`,需支持跟随系统 |
|
||||
| P3-5 | 无障碍 | VoiceOver labels、Dynamic Type 适配、高对比度 |
|
||||
|
||||
---
|
||||
|
||||
## 六、实施建议顺序
|
||||
|
||||
```
|
||||
第 1 周 ─ P0-1 登录 → P0-2 知识库CRUD → P0-3 学习会话
|
||||
第 2 周 ─ P0-4 复习卡片 → P1-1 薄弱点/AI分析 → P1-2 StudyHomeView 真实化
|
||||
第 3 周 ─ P1-3 ProfileView → P1-4 通知中心 → P1-5 反馈
|
||||
第 4 周 ─ P2-1 文件导入 → P2-2 搜索 → P2-3 设置页
|
||||
第 5 周 ─ P2-4 主动回忆 → P2-5 Token刷新
|
||||
第 6 周 ─ P3 体验增强
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、后端接口未封装清单(需新增 Service 方法)
|
||||
|
||||
| 模块 | 后端口 | 未封装接口 |
|
||||
|------|--------|----------|
|
||||
| KnowledgeBase | PATCH/DELETE | update / delete |
|
||||
| KnowledgeItems | PATCH/DELETE | update / delete |
|
||||
| LearningSession | POST/GET | start / end / list |
|
||||
| ActiveRecall | GET/POST | list / submit |
|
||||
| AIAnalysis | GET | result / job status |
|
||||
| Activity | GET | heatmap |
|
||||
| Notifications | GET/POST | list / markRead |
|
||||
| DocumentImport | POST/GET | create / status |
|
||||
| Review | POST | submit |
|
||||
| FocusItems | POST/PATCH | create / update / complete |
|
||||
|
||||
> 需新增约 15 个 Service 方法 + 对应 Request/Response DTO
|
||||
0
开发计划/miniapp-projects/.gitkeep
Normal file
0
开发计划/miniapp-projects/.gitkeep
Normal file
0
开发计划/web-projects/.gitkeep
Normal file
0
开发计划/web-projects/.gitkeep
Normal file
0
开发计划/webApp-projects/.gitkeep
Normal file
0
开发计划/webApp-projects/.gitkeep
Normal file
0
技术设计/admin-projects/.gitkeep
Normal file
0
技术设计/admin-projects/.gitkeep
Normal file
0
技术设计/android-projects/.gitkeep
Normal file
0
技术设计/android-projects/.gitkeep
Normal file
262
技术设计/api-server/[进行中]-Redis缓存设计.md
Normal file
262
技术设计/api-server/[进行中]-Redis缓存设计.md
Normal file
@ -0,0 +1,262 @@
|
||||
---
|
||||
source: AI回答.md
|
||||
updated: 2026-05-09
|
||||
---
|
||||
|
||||
# 知习 Redis 设计
|
||||
|
||||
> Redis 在知习里不是"另一个 MySQL",它是系统的**加速器和调度器**。MySQL 存结果,Redis 管过程。
|
||||
|
||||
---
|
||||
|
||||
## 1. Redis 定位
|
||||
|
||||
Redis 不作为主数据库,只负责:
|
||||
|
||||
1. 缓存
|
||||
2. 限流
|
||||
3. 队列(BullMQ)
|
||||
4. 临时任务状态
|
||||
5. 分布式锁
|
||||
6. 防重复提交
|
||||
7. AI 调用次数统计
|
||||
8. 短期 Token / 黑名单
|
||||
9. 通知任务调度
|
||||
10. 学习会话草稿
|
||||
|
||||
---
|
||||
|
||||
## 2. Key 命名规范
|
||||
|
||||
统一格式:
|
||||
|
||||
```text
|
||||
业务域:对象类型:对象ID:字段
|
||||
```
|
||||
|
||||
示例:
|
||||
|
||||
```text
|
||||
cache:user:123:profile
|
||||
rate:user:123:ai:daily:2026-05-09
|
||||
lock:ai-analysis:session:987
|
||||
job:ai-analysis:abc123:status
|
||||
```
|
||||
|
||||
规则:
|
||||
|
||||
1. 全部小写
|
||||
2. 用冒号 `:` 分隔
|
||||
3. 从大范围到小范围
|
||||
4. userId、jobId、sessionId 明确写在 key 里
|
||||
5. 带日期的 key 用 `YYYY-MM-DD`
|
||||
6. 所有临时 key 必须设置 TTL
|
||||
|
||||
---
|
||||
|
||||
## 3. Key 总表
|
||||
|
||||
### 缓存类
|
||||
|
||||
| Key | 用途 | TTL |
|
||||
|-----|------|-----|
|
||||
| `cache:user:{userId}:profile` | 用户资料 | 5-10 分钟 |
|
||||
| `cache:user:{userId}:preferences` | 用户偏好设置 | 10 分钟 |
|
||||
| `cache:user:{userId}:knowledge-bases` | 用户知识库列表 | 3-5 分钟 |
|
||||
| `cache:knowledge-base:{kbId}:summary` | 知识库摘要 | 5 分钟 |
|
||||
| `cache:review:user:{userId}:due-count` | 到期复习数量 | 1-3 分钟 |
|
||||
|
||||
### 限流类
|
||||
|
||||
| Key | 用途 | TTL |
|
||||
|-----|------|-----|
|
||||
| `rate:user:{userId}:ai:daily:{date}` | 用户每日 AI 调用次数 | 到当天结束或 24h |
|
||||
| `rate:user:{userId}:feedback:hourly` | 用户每小时反馈次数 | 1 小时 |
|
||||
| `rate:ip:{ip}:request:{minute}` | IP 每分钟请求频率 | 60-120 秒 |
|
||||
| `rate:ip:{ip}:login:{date}` | IP 每日登录尝试 | 10-30 分钟 |
|
||||
|
||||
### 分布式锁类
|
||||
|
||||
| Key | 用途 | TTL |
|
||||
|-----|------|-----|
|
||||
| `lock:ai-analysis:session:{sessionId}` | 防止重复提交 AI 分析 | 60-300 秒 |
|
||||
| `lock:ai-analysis:answer:{answerId}` | 防止同回答重复分析 | 60-300 秒 |
|
||||
| `lock:document-import:{importId}` | 防止重复处理导入 | 5-30 分钟 |
|
||||
| `lock:review-plan:user:{userId}:item:{itemId}` | 防止重复生成复习计划 | 60-300 秒 |
|
||||
| `lock:feedback:ip:{ip}` | 防止 IP 刷反馈 | 60-300 秒 |
|
||||
|
||||
### 任务状态类
|
||||
|
||||
| Key | Value 示例 | TTL |
|
||||
|-----|-----------|-----|
|
||||
| `job:ai-analysis:{jobId}:status` | `pending / processing / completed / failed` | 24h |
|
||||
| `job:ai-analysis:{jobId}:progress` | `0-100` | 24h |
|
||||
| `job:ai-analysis:{jobId}:error` | 错误信息字符串 | 24h |
|
||||
| `job:document-import:{importId}:status` | `pending / parsing / chunking / generating / completed / failed` | 24h |
|
||||
| `job:document-import:{importId}:progress` | `0-100` | 24h |
|
||||
| `job:document-import:{importId}:message` | `"正在提取关键知识点"` | 24h |
|
||||
| `job:document-import:{importId}:error` | 错误信息字符串 | 24h |
|
||||
|
||||
### 会话临时状态类
|
||||
|
||||
| Key | 用途 | TTL |
|
||||
|-----|------|-----|
|
||||
| `session:learning:{sessionId}:heartbeat` | 学习会话心跳 | 30 分钟 |
|
||||
| `session:learning:{sessionId}:current-step` | 当前学习步骤 | 2 小时 |
|
||||
| `session:active-recall:{sessionId}:draft` | 回答草稿暂存 | 1-24 小时 |
|
||||
|
||||
### Token / 黑名单
|
||||
|
||||
| Key | 用途 | TTL |
|
||||
|-----|------|-----|
|
||||
| `auth:refresh-token:blacklist:{tokenId}` | 注销后刷新 Token 失效 | 到 token 过期 |
|
||||
| `auth:access-token:blacklist:{jwtId}` | 注销后 JWT 失效 | 到 token 过期 |
|
||||
|
||||
### Set 类(可选)
|
||||
|
||||
| Key | 用途 |
|
||||
|-----|------|
|
||||
| `set:user:{userId}:reviewed-items:{date}` | 当天已复习项去重 |
|
||||
|
||||
---
|
||||
|
||||
## 4. Redis 数据类型选择
|
||||
|
||||
| 类型 | 用途 | 示例 |
|
||||
|------|------|------|
|
||||
| **String** | 最常用:缓存 JSON、计数器、状态、锁 | `rate:user:123:ai:daily:2026-05-09 = 8` |
|
||||
| **Hash** | 可选,任务多字段频繁更新的场景 | `job:ai-analysis:1001 → status=processing, progress=40` |
|
||||
| **List/Stream** | 队列,BullMQ 自动管理,不需要手动操作 | - |
|
||||
| **Set** | 去重,如当天已复习项集合 | `set:user:123:reviewed-items:2026-05-09` |
|
||||
| **Sorted Set** | 后期按时间排序的复习调度,v0.1 先不做 | - |
|
||||
|
||||
---
|
||||
|
||||
## 5. 核心流程中 Redis 与 MySQL 的配合
|
||||
|
||||
### 5.1 AI 分析流程
|
||||
|
||||
```text
|
||||
1. MySQL 创建 ai_analysis_jobs
|
||||
2. Redis 加入 ai-analysis 队列(BullMQ)
|
||||
3. Redis 存 job:xxx:status = processing
|
||||
4. Worker 调用 AI
|
||||
5. MySQL 写 ai_analysis_results
|
||||
6. MySQL 写 focus_items
|
||||
7. MySQL 写 review_cards
|
||||
8. Redis 存 job:xxx:status = completed
|
||||
9. MySQL 写 notifications
|
||||
```
|
||||
|
||||
### 5.2 资料导入流程
|
||||
|
||||
```text
|
||||
1. MySQL 创建 document_imports
|
||||
2. Redis 加入 document-import 队列(BullMQ)
|
||||
3. Redis 存导入进度
|
||||
4. Worker 解析文件
|
||||
5. MySQL 写 knowledge_items
|
||||
6. MySQL 更新 document_imports 为 success
|
||||
7. Redis 存状态 completed
|
||||
```
|
||||
|
||||
### 5.3 学习活跃图流程
|
||||
|
||||
```text
|
||||
1. 用户完成学习动作
|
||||
2. MySQL 写 learning_records
|
||||
3. MySQL 更新 daily_learning_activities
|
||||
4. Redis 可短期缓存今日活跃统计
|
||||
5. App 查询活跃图优先查 MySQL,必要时加缓存
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. BullMQ 队列
|
||||
|
||||
BullMQ 自动管理 Redis key,不需要手动建。建议预留 3 个队列:
|
||||
|
||||
| 队列名 | 任务数据 | 处理逻辑 |
|
||||
|--------|---------|---------|
|
||||
| `ai-analysis` | `{ jobId, userId, sessionId, answerId, jobType }` | 读取回答 → 调 AI → 写结果 → 生成待巩固项 → 生成复习卡片 → 发通知 |
|
||||
| `document-import` | `{ importId, userId, knowledgeBaseId, sourceType }` | 解析文件 → 提取文本 → 分段 → 生成知识点 → 写 knowledge_items → 更新状态 |
|
||||
| `notification` | `{ userId, type, title, data }` | 写 notifications 表,后续可扩展 APNs 推送 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 哪些绝对不能只放 Redis
|
||||
|
||||
以下全部必须写 MySQL,Redis 只能做缓存,不是唯一来源:
|
||||
|
||||
```text
|
||||
用户资料 → users, user_profiles
|
||||
知识库内容 → knowledge_bases
|
||||
知识点内容 → knowledge_items
|
||||
学习记录 → learning_records
|
||||
主动回忆回答 → active_recall_answers
|
||||
AI 分析结果 → ai_analysis_results
|
||||
待巩固项 → focus_items
|
||||
复习卡片 → review_cards
|
||||
复习记录 → review_logs
|
||||
学习活跃记录 → daily_learning_activities
|
||||
通知记录 → notifications
|
||||
用户设置 → user_preferences
|
||||
协议同意记录 → user_consents
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. v0.1 Redis 最小落地范围
|
||||
|
||||
### 必须做
|
||||
|
||||
```text
|
||||
1. Redis 连接
|
||||
2. /health 检查 Redis
|
||||
3. RedisModule + RedisService(get/set/del/exists/expire/ttl/incr/setNx/lock/unlock)
|
||||
4. AI 每日调用限流(rate:user:{userId}:ai:daily:{date})
|
||||
5. AI 分析队列(BullMQ ai-analysis)
|
||||
6. AI 分析任务状态(job:ai-analysis:{jobId}:status/progress/error)
|
||||
7. 防重复提交锁(lock:ai-analysis:session:{sessionId})
|
||||
8. document-import 队列预留(BullMQ document-import)
|
||||
9. notification 队列预留(BullMQ notification)
|
||||
```
|
||||
|
||||
### 暂时不做
|
||||
|
||||
```text
|
||||
复杂缓存策略
|
||||
Sorted Set 复习调度
|
||||
复杂分布式任务调度
|
||||
全量通知推送(APNs)
|
||||
复杂排行榜
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. RedisService 方法清单
|
||||
|
||||
```text
|
||||
get(key) — 读取
|
||||
set(key, value) — 写入
|
||||
del(key) — 删除
|
||||
exists(key) — 判断存在
|
||||
expire(key, ttl) — 设置过期
|
||||
ttl(key) — 查看剩余时间
|
||||
incr(key) — 自增(限流计数)
|
||||
setNx(key, value) — 不存在才写入(锁)
|
||||
lock(key, ttl) — 获取分布式锁,返回 token
|
||||
unlock(key, token) — 释放锁,校验 token,防止误删
|
||||
```
|
||||
|
||||
锁的实现注意:
|
||||
|
||||
- 锁必须设置 TTL
|
||||
- 解锁时必须校验 value/token,不能误删别人的锁
|
||||
- 锁的 value 用随机 token,解锁时比对
|
||||
|
||||
---
|
||||
|
||||
## 10. 一句话总结
|
||||
|
||||
> **Redis 在知习里不是"另一个 MySQL",它是系统的加速器和调度器。MySQL 存结果,Redis 管过程。**
|
||||
1185
技术设计/api-server/[进行中]-架构总览.md
Normal file
1185
技术设计/api-server/[进行中]-架构总览.md
Normal file
File diff suppressed because it is too large
Load Diff
169
技术设计/api-server/已完成/[已完成]-安全规范.md
Normal file
169
技术设计/api-server/已完成/[已完成]-安全规范.md
Normal file
@ -0,0 +1,169 @@
|
||||
# 知习 api-server 安全基线
|
||||
|
||||
> v0.1 安全设计文档。本后端存储用户资料、知识库、上传文件、主动回忆回答、AI 分析结果和学习记录,第一版必须建立基础安全边界。
|
||||
|
||||
---
|
||||
|
||||
## 1. 全局安全中间件
|
||||
|
||||
| 措施 | 实现 | 文件 |
|
||||
|------|------|------|
|
||||
| helmet | `app.use(helmet())` 设置安全 HTTP 头 | `src/main.ts` |
|
||||
| CORS | 仅允许配置域名。生产环境仅允许 `longde.cloud` | `src/main.ts` |
|
||||
| body size limit | JSON 请求体最大 10MB | `src/main.ts` |
|
||||
| 异常过滤 | 生产环境不返回 stack trace | `src/common/filters/global-exception.filter.ts` |
|
||||
|
||||
---
|
||||
|
||||
## 2. 认证与 Token
|
||||
|
||||
### JWT
|
||||
|
||||
- `accessToken`: JWT,1 小时过期
|
||||
- `refreshToken`: 128 位随机 hex,入库只存 SHA-256 hash
|
||||
- logout 时 `revokedAt = now()` 撤销所有 refresh token
|
||||
- `/users/me` 及其所有子路由强制 `@UseGuards(JwtAuthGuard)`
|
||||
|
||||
```
|
||||
POST /auth/apple → 返回 accessToken + refreshToken
|
||||
POST /auth/refresh → 消耗旧 refreshToken,发放新 token pair(rotation)
|
||||
POST /auth/logout → 撤销该用户所有 refresh token
|
||||
```
|
||||
|
||||
### 存储安全
|
||||
|
||||
```
|
||||
refresh_tokens.tokenHash = SHA-256(实际 token)
|
||||
数据库中永远不存明文 refreshToken
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 权限与越权防护
|
||||
|
||||
### 资源归属校验
|
||||
|
||||
所有用户资源操作必须校验 `userId` 归属:
|
||||
|
||||
```ts
|
||||
// src/common/utils/security.util.ts
|
||||
export async function findByIdAndUserId(delegate, id, userId, resourceName)
|
||||
export function ensureOwnership(record, userId, resourceName)
|
||||
```
|
||||
|
||||
### 需校验的资源
|
||||
|
||||
| 资源 | 校验字段 |
|
||||
|------|---------|
|
||||
| KnowledgeBase | `userId` |
|
||||
| KnowledgeItem | `userId` |
|
||||
| LearningSession | `userId` |
|
||||
| ActiveRecallAnswer | `userId` |
|
||||
| AiAnalysisJob | `userId` |
|
||||
| AiAnalysisResult | `userId` |
|
||||
| FocusItem | `userId` |
|
||||
| ReviewCard | `userId` |
|
||||
| ReviewLog | `userId` |
|
||||
| DocumentImport | `userId` |
|
||||
|
||||
---
|
||||
|
||||
## 4. 参数校验
|
||||
|
||||
- 全局 `StrictValidationPipe`:
|
||||
- `whitelist: true` — 自动剥离未声明字段
|
||||
- `forbidNonWhitelisted: true` — 未知字段返回 400
|
||||
- 字符串字段最大长度 5000 字符
|
||||
- 分页 DTO: page≥1, limit 1-100
|
||||
|
||||
---
|
||||
|
||||
## 5. 限流(Redis)
|
||||
|
||||
| 场景 | Key | 限制 |
|
||||
|------|-----|------|
|
||||
| 登录 | `rate:ip:{ip}:login:{date}` | 20次/IP/天 |
|
||||
| 反馈 | `rate:ip:{ip}:feedback:hourly` | 5次/IP/时 |
|
||||
| AI 分析 | `rate:user:{userId}:ai:daily:{date}` | 50次/用户/天 |
|
||||
| 文件上传 | `rate:user:{userId}:upload:hourly` | 10次/用户/时 |
|
||||
|
||||
实现: `src/common/utils/rate-limit.service.ts`
|
||||
|
||||
---
|
||||
|
||||
## 6. 文件上传安全
|
||||
|
||||
| 措施 | 说明 |
|
||||
|------|------|
|
||||
| 类型白名单 | PDF, Word, Excel, 纯文本, Markdown, CSV, PNG, JPEG, WebP |
|
||||
| 大小限制 | 最大 20MB |
|
||||
| 随机文件名 | `sanitizeFilename()` 生成随机 key,不信任用户原始文件名 |
|
||||
| 默认私有 | 所有文件默认私有访问 |
|
||||
| 路径隔离 | `users/{userId}/...` |
|
||||
|
||||
---
|
||||
|
||||
## 7. Redis 安全使用
|
||||
|
||||
- 不存核心业务结果(用户资料/知识点/AI分析结果等必须在 MySQL)
|
||||
- 队列任务只存 `jobId`/`userId` 等引用 ID
|
||||
- 所有临时 key 必须设置 TTL
|
||||
- 防重复提交锁必须有 TTL,解锁校验 token
|
||||
- 不在 Redis 中存 token 明文
|
||||
|
||||
---
|
||||
|
||||
## 8. COS 安全使用
|
||||
|
||||
- Bucket 默认私有读写
|
||||
- 后端不向前端暴露 SecretId/SecretKey
|
||||
- 下载私有文件通过签名 URL
|
||||
- 上传路径按 `users/{userId}/{randomKey}` 组织
|
||||
- 预留临时上传 URL(STS)机制
|
||||
|
||||
---
|
||||
|
||||
## 9. Swagger 安全
|
||||
|
||||
- 开发环境默认开启
|
||||
- 生产环境默认关闭
|
||||
- 生产环境如需开启,必须配置 Basic Auth(`SWAGGER_USER`/`SWAGGER_PASSWORD`)
|
||||
- 生产环境手动设置 `ENABLE_SWAGGER=true`
|
||||
|
||||
---
|
||||
|
||||
## 10. 数据库安全
|
||||
|
||||
- 不使用 root 连接业务
|
||||
- 业务账号 `zhixi_user` 仅需 SELECT/INSERT/UPDATE/DELETE
|
||||
- 迁移账号和业务账号分离(`prisma db push` 与运行时连接帐号可不同)
|
||||
- 数据库自动备份建议: `mysqldump zhixi | gzip > backup-$(date +%Y%m%d).sql.gz`
|
||||
|
||||
### 日志中禁止打印
|
||||
|
||||
```
|
||||
DATABASE_URL(含密码)
|
||||
JWT_SECRET
|
||||
AI_API_KEY
|
||||
COS SecretKey
|
||||
用户完整 refreshToken
|
||||
用户上传文件的完整内容
|
||||
Authorization header
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 11. 安全检查清单
|
||||
|
||||
- [x] helmet 已启用
|
||||
- [x] CORS 仅允许白名单域名
|
||||
- [x] JWT + refresh token rotation + hash 存储
|
||||
- [x] logout 撤销 refresh token
|
||||
- [x] 所有用户数据接口需要认证
|
||||
- [x] 资源所有权校验工具已就绪
|
||||
- [x] StrictValidationPipe 全局启用(whitelist + forbidNonWhitelisted)
|
||||
- [x] Redis 限流已实现
|
||||
- [x] 文件类型/大小白名单
|
||||
- [x] 全局异常过滤器生产环境不暴露 stack trace
|
||||
- [x] Swagger 生产环境默认关闭
|
||||
- [x] 敏感信息不在日志中打印原则已确立
|
||||
814
技术设计/api-server/已完成/[已完成]-数据库设计.md
Normal file
814
技术设计/api-server/已完成/[已完成]-数据库设计.md
Normal file
@ -0,0 +1,814 @@
|
||||
---
|
||||
source: AI回答.md
|
||||
updated: 2026-05-09
|
||||
---
|
||||
|
||||
# 知习 MySQL 数据库表结构设计
|
||||
|
||||
> 共 27 张表,v0.1 先建 24 张核心表。
|
||||
|
||||
---
|
||||
|
||||
## 通用字段规范
|
||||
|
||||
每张核心表统一使用:
|
||||
|
||||
```sql
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted_at DATETIME NULL
|
||||
```
|
||||
|
||||
- `id`:内部主键
|
||||
- `created_at`:创建时间
|
||||
- `updated_at`:更新时间
|
||||
- `deleted_at`:软删除
|
||||
|
||||
状态字段统一用 `VARCHAR(32)`,不用 MySQL ENUM。
|
||||
|
||||
---
|
||||
|
||||
## 一、用户与认证表(5 张)
|
||||
|
||||
### 1. users 用户表
|
||||
|
||||
```sql
|
||||
users
|
||||
- id BIGINT UNSIGNED PK
|
||||
- email VARCHAR(255) NULL
|
||||
- nickname VARCHAR(100) NULL
|
||||
- avatar_url VARCHAR(500) NULL
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'active'
|
||||
- onboarding_completed TINYINT(1) NOT NULL DEFAULT 0
|
||||
- last_login_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
- deleted_at DATETIME NULL
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_users_email (email)
|
||||
INDEX idx_users_status (status)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. auth_accounts 第三方登录账号表
|
||||
|
||||
```sql
|
||||
auth_accounts
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- provider VARCHAR(32) NOT NULL -- apple
|
||||
- provider_user_id VARCHAR(255) NOT NULL -- Apple userIdentifier / sub
|
||||
- email VARCHAR(255) NULL
|
||||
- raw_profile_json JSON NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
UNIQUE KEY uk_provider_user (provider, provider_user_id)
|
||||
INDEX idx_auth_accounts_user_id (user_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. refresh_tokens 刷新 Token 表
|
||||
|
||||
```sql
|
||||
refresh_tokens
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- token_hash VARCHAR(255) NOT NULL
|
||||
- device_id VARCHAR(255) NULL
|
||||
- device_name VARCHAR(255) NULL
|
||||
- expires_at DATETIME NOT NULL
|
||||
- revoked_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_refresh_tokens_user_id (user_id)
|
||||
INDEX idx_refresh_tokens_token_hash (token_hash)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. user_profiles 用户资料扩展表
|
||||
|
||||
```sql
|
||||
user_profiles
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- learning_identity VARCHAR(100) NULL -- 系统学习者 / 备考用户 / 知识工作者
|
||||
- learning_direction VARCHAR(255) NULL -- 认知科学 / AIGC / 产品设计
|
||||
- bio TEXT NULL
|
||||
- current_goal VARCHAR(255) NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
UNIQUE KEY uk_user_profiles_user_id (user_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. user_preferences 用户学习偏好表
|
||||
|
||||
```sql
|
||||
user_preferences
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- preferred_methods JSON NULL
|
||||
-- ["active_recall", "spaced_repetition", "feynman", "retrieval_practice"]
|
||||
- default_focus_minutes INT NOT NULL DEFAULT 25
|
||||
- ai_suggestion_level VARCHAR(32) NOT NULL DEFAULT 'normal'
|
||||
-- low / normal / high
|
||||
- language VARCHAR(32) NOT NULL DEFAULT 'zh-CN'
|
||||
- appearance VARCHAR(32) NOT NULL DEFAULT 'system'
|
||||
- notification_enabled TINYINT(1) NOT NULL DEFAULT 1
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
UNIQUE KEY uk_user_preferences_user_id (user_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、知识库相关表(5 张)
|
||||
|
||||
### 6. knowledge_bases 知识库表
|
||||
|
||||
```sql
|
||||
knowledge_bases
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- title VARCHAR(255) NOT NULL
|
||||
- description TEXT NULL
|
||||
- cover_key VARCHAR(100) NULL
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'active'
|
||||
-- active / archived / deleted
|
||||
- item_count INT NOT NULL DEFAULT 0
|
||||
- last_studied_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
- deleted_at DATETIME NULL
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_knowledge_bases_user_id (user_id)
|
||||
INDEX idx_knowledge_bases_status (status)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. knowledge_items 知识点/内容表
|
||||
|
||||
```sql
|
||||
knowledge_items
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- knowledge_base_id BIGINT UNSIGNED NOT NULL
|
||||
- parent_id BIGINT UNSIGNED NULL
|
||||
- item_type VARCHAR(32) NOT NULL
|
||||
-- chapter / lesson / concept / note / imported_doc
|
||||
- title VARCHAR(255) NOT NULL
|
||||
- content LONGTEXT NULL
|
||||
- summary TEXT NULL
|
||||
- source_type VARCHAR(32) NULL
|
||||
-- manual / file / url / ai_generated
|
||||
- source_ref VARCHAR(500) NULL
|
||||
- order_index INT NOT NULL DEFAULT 0
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'active'
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
- deleted_at DATETIME NULL
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_knowledge_items_user_id (user_id)
|
||||
INDEX idx_knowledge_items_kb_id (knowledge_base_id)
|
||||
INDEX idx_knowledge_items_parent_id (parent_id)
|
||||
INDEX idx_knowledge_items_type (item_type)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 8. knowledge_item_relations 知识点关联表
|
||||
|
||||
```sql
|
||||
knowledge_item_relations
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- source_item_id BIGINT UNSIGNED NOT NULL
|
||||
- target_item_id BIGINT UNSIGNED NOT NULL
|
||||
- relation_type VARCHAR(32) NOT NULL
|
||||
-- related / prerequisite / similar / conflict / extension
|
||||
- confidence DECIMAL(5,2) NULL
|
||||
- reason TEXT NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_relations_source (source_item_id)
|
||||
INDEX idx_relations_target (target_item_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 9. tags 标签表
|
||||
|
||||
```sql
|
||||
tags
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- name VARCHAR(100) NOT NULL
|
||||
- color VARCHAR(32) NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
UNIQUE KEY uk_user_tag_name (user_id, name)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 10. knowledge_item_tags 知识点标签关联表
|
||||
|
||||
```sql
|
||||
knowledge_item_tags
|
||||
- id BIGINT UNSIGNED PK
|
||||
- knowledge_item_id BIGINT UNSIGNED NOT NULL
|
||||
- tag_id BIGINT UNSIGNED NOT NULL
|
||||
- created_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
UNIQUE KEY uk_item_tag (knowledge_item_id, tag_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、资料导入相关表(2 张)
|
||||
|
||||
### 11. uploaded_files 上传文件表
|
||||
|
||||
```sql
|
||||
uploaded_files
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- filename VARCHAR(255) NOT NULL
|
||||
- mime_type VARCHAR(100) NULL
|
||||
- storage_path VARCHAR(500) NOT NULL
|
||||
- size_bytes BIGINT UNSIGNED NOT NULL DEFAULT 0
|
||||
- checksum VARCHAR(255) NULL
|
||||
- created_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_uploaded_files_user_id (user_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 12. document_imports 资料导入任务表
|
||||
|
||||
```sql
|
||||
document_imports
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- knowledge_base_id BIGINT UNSIGNED NULL
|
||||
- file_id BIGINT UNSIGNED NULL
|
||||
- source_type VARCHAR(32) NOT NULL
|
||||
-- file / text / url
|
||||
- source_name VARCHAR(255) NULL
|
||||
- source_url VARCHAR(500) NULL
|
||||
- raw_text LONGTEXT NULL
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'pending'
|
||||
-- pending / processing / success / failed
|
||||
- progress INT NOT NULL DEFAULT 0
|
||||
- error_message TEXT NULL
|
||||
- result_json JSON NULL
|
||||
- started_at DATETIME NULL
|
||||
- completed_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_document_imports_user_id (user_id)
|
||||
INDEX idx_document_imports_status (status)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、学习过程相关表(2 张)
|
||||
|
||||
### 13. learning_sessions 学习会话表
|
||||
|
||||
```sql
|
||||
learning_sessions
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- knowledge_base_id BIGINT UNSIGNED NULL
|
||||
- knowledge_item_id BIGINT UNSIGNED NULL
|
||||
- mode VARCHAR(32) NOT NULL
|
||||
-- reading / active_recall / review / feynman / free_learning
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'active'
|
||||
-- active / completed / cancelled
|
||||
- started_at DATETIME NOT NULL
|
||||
- ended_at DATETIME NULL
|
||||
- duration_seconds INT NOT NULL DEFAULT 0
|
||||
- focus_minutes INT NULL
|
||||
- metadata JSON NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_learning_sessions_user_id (user_id)
|
||||
INDEX idx_learning_sessions_item_id (knowledge_item_id)
|
||||
INDEX idx_learning_sessions_started_at (started_at)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 14. learning_records 学习记录表
|
||||
|
||||
类似 GitHub commit log,语义是学习记录。
|
||||
|
||||
```sql
|
||||
learning_records
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- session_id BIGINT UNSIGNED NULL
|
||||
- record_type VARCHAR(32) NOT NULL
|
||||
-- read / active_recall / review / ai_analysis / focus_item_completed
|
||||
- title VARCHAR(255) NOT NULL
|
||||
- description TEXT NULL
|
||||
- duration_seconds INT NOT NULL DEFAULT 0
|
||||
- occurred_at DATETIME NOT NULL
|
||||
- metadata JSON NULL
|
||||
- created_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_learning_records_user_id (user_id)
|
||||
INDEX idx_learning_records_occurred_at (occurred_at)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、主动回忆相关表(2 张)
|
||||
|
||||
### 15. active_recall_questions 主动回忆问题表
|
||||
|
||||
```sql
|
||||
active_recall_questions
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- knowledge_item_id BIGINT UNSIGNED NULL
|
||||
- question_text TEXT NOT NULL
|
||||
- difficulty VARCHAR(32) NULL
|
||||
-- easy / normal / hard
|
||||
- created_by VARCHAR(32) NOT NULL DEFAULT 'ai'
|
||||
-- ai / user / system
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_recall_questions_user_id (user_id)
|
||||
INDEX idx_recall_questions_item_id (knowledge_item_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 16. active_recall_answers 主动回忆回答表
|
||||
|
||||
```sql
|
||||
active_recall_answers
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- question_id BIGINT UNSIGNED NULL
|
||||
- session_id BIGINT UNSIGNED NULL
|
||||
- answer_type VARCHAR(32) NOT NULL DEFAULT 'text'
|
||||
-- text / voice
|
||||
- answer_text LONGTEXT NULL
|
||||
- audio_file_id BIGINT UNSIGNED NULL
|
||||
- submitted_at DATETIME NOT NULL
|
||||
- created_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_recall_answers_user_id (user_id)
|
||||
INDEX idx_recall_answers_question_id (question_id)
|
||||
INDEX idx_recall_answers_session_id (session_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、AI 分析相关表(2 张)
|
||||
|
||||
### 17. ai_analysis_jobs AI 分析任务表
|
||||
|
||||
```sql
|
||||
ai_analysis_jobs
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- session_id BIGINT UNSIGNED NULL
|
||||
- answer_id BIGINT UNSIGNED NULL
|
||||
- job_type VARCHAR(32) NOT NULL
|
||||
-- active_recall_analysis / weak_point_detection / review_generation
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'pending'
|
||||
-- pending / processing / success / failed
|
||||
- progress INT NOT NULL DEFAULT 0
|
||||
- error_message TEXT NULL
|
||||
- queued_at DATETIME NULL
|
||||
- started_at DATETIME NULL
|
||||
- completed_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_ai_jobs_user_id (user_id)
|
||||
INDEX idx_ai_jobs_status (status)
|
||||
INDEX idx_ai_jobs_session_id (session_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 18. ai_analysis_results AI 分析结果表
|
||||
|
||||
```sql
|
||||
ai_analysis_results
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- job_id BIGINT UNSIGNED NOT NULL
|
||||
- session_id BIGINT UNSIGNED NULL
|
||||
- answer_id BIGINT UNSIGNED NULL
|
||||
- summary TEXT NULL
|
||||
- mastery_score INT NULL -- 0-100
|
||||
- strengths JSON NULL
|
||||
- weaknesses JSON NULL
|
||||
- suggestions JSON NULL
|
||||
- next_actions JSON NULL
|
||||
- raw_result JSON NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_ai_results_user_id (user_id)
|
||||
INDEX idx_ai_results_job_id (job_id)
|
||||
INDEX idx_ai_results_session_id (session_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、待巩固项表(1 张)
|
||||
|
||||
### 19. focus_items 待巩固项表
|
||||
|
||||
类似 GitHub issue,学习语义叫「待巩固项」。
|
||||
|
||||
```sql
|
||||
focus_items
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- knowledge_base_id BIGINT UNSIGNED NULL
|
||||
- knowledge_item_id BIGINT UNSIGNED NULL
|
||||
- analysis_result_id BIGINT UNSIGNED NULL
|
||||
- title VARCHAR(255) NOT NULL
|
||||
- reason TEXT NULL
|
||||
- suggestion TEXT NULL
|
||||
- priority VARCHAR(32) NOT NULL DEFAULT 'normal'
|
||||
-- low / normal / high
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'open'
|
||||
-- open / in_review / completed / ignored
|
||||
- mastery_score INT NULL
|
||||
- due_at DATETIME NULL
|
||||
- completed_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
- deleted_at DATETIME NULL
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_focus_items_user_id (user_id)
|
||||
INDEX idx_focus_items_status (status)
|
||||
INDEX idx_focus_items_due_at (due_at)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、复习相关表(3 张)
|
||||
|
||||
### 20. review_cards 复习卡片表
|
||||
|
||||
```sql
|
||||
review_cards
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- knowledge_item_id BIGINT UNSIGNED NULL
|
||||
- focus_item_id BIGINT UNSIGNED NULL
|
||||
- front_text TEXT NOT NULL
|
||||
- back_text TEXT NULL
|
||||
- difficulty VARCHAR(32) NULL
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'active'
|
||||
-- active / suspended / completed
|
||||
- next_review_at DATETIME NULL
|
||||
- interval_days INT NOT NULL DEFAULT 1
|
||||
- ease_factor DECIMAL(4,2) NOT NULL DEFAULT 2.50
|
||||
- repetition_count INT NOT NULL DEFAULT 0
|
||||
- lapse_count INT NOT NULL DEFAULT 0
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
- deleted_at DATETIME NULL
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_review_cards_user_id (user_id)
|
||||
INDEX idx_review_cards_next_review_at (next_review_at)
|
||||
INDEX idx_review_cards_focus_item_id (focus_item_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 21. review_logs 复习记录表
|
||||
|
||||
```sql
|
||||
review_logs
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- review_card_id BIGINT UNSIGNED NOT NULL
|
||||
- session_id BIGINT UNSIGNED NULL
|
||||
- rating VARCHAR(32) NOT NULL
|
||||
-- again / hard / good / easy
|
||||
- response_text TEXT NULL
|
||||
- reviewed_at DATETIME NOT NULL
|
||||
- next_review_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_review_logs_user_id (user_id)
|
||||
INDEX idx_review_logs_card_id (review_card_id)
|
||||
INDEX idx_review_logs_reviewed_at (reviewed_at)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 22. review_plans 复习计划表
|
||||
|
||||
```sql
|
||||
review_plans
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- title VARCHAR(255) NOT NULL
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'active'
|
||||
-- active / completed / cancelled
|
||||
- scheduled_at DATETIME NULL
|
||||
- completed_at DATETIME NULL
|
||||
- card_count INT NOT NULL DEFAULT 0
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_review_plans_user_id (user_id)
|
||||
INDEX idx_review_plans_scheduled_at (scheduled_at)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、学习活跃记录表(1 张)
|
||||
|
||||
### 23. daily_learning_activities 每日学习活跃表
|
||||
|
||||
用于个人中心的蓝色学习活跃图。
|
||||
|
||||
```sql
|
||||
daily_learning_activities
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- activity_date DATE NOT NULL
|
||||
- duration_seconds INT NOT NULL DEFAULT 0
|
||||
- sessions_count INT NOT NULL DEFAULT 0
|
||||
- active_recall_count INT NOT NULL DEFAULT 0
|
||||
- review_count INT NOT NULL DEFAULT 0
|
||||
- ai_analysis_count INT NOT NULL DEFAULT 0
|
||||
- completed_loop_count INT NOT NULL DEFAULT 0
|
||||
- activity_level INT NOT NULL DEFAULT 0 -- 0-4,颜色深浅
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
UNIQUE KEY uk_user_activity_date (user_id, activity_date)
|
||||
INDEX idx_daily_activity_user_id (user_id)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、通知与反馈表(2 张)
|
||||
|
||||
### 24. notifications 消息通知表
|
||||
|
||||
```sql
|
||||
notifications
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- type VARCHAR(32) NOT NULL
|
||||
-- review_due / ai_analysis_done / learning_suggestion / system
|
||||
- title VARCHAR(255) NOT NULL
|
||||
- content TEXT NULL
|
||||
- data JSON NULL
|
||||
- read_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_notifications_user_id (user_id)
|
||||
INDEX idx_notifications_read_at (read_at)
|
||||
INDEX idx_notifications_type (type)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 25. feedbacks 用户反馈表
|
||||
|
||||
```sql
|
||||
feedbacks
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NULL
|
||||
- email VARCHAR(255) NULL
|
||||
- category VARCHAR(64) NOT NULL
|
||||
-- feature / bug / experience / privacy / other
|
||||
- content TEXT NOT NULL
|
||||
- device_info JSON NULL
|
||||
- status VARCHAR(32) NOT NULL DEFAULT 'open'
|
||||
-- open / processing / resolved / ignored
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_feedbacks_user_id (user_id)
|
||||
INDEX idx_feedbacks_status (status)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十一、合规与系统表(2 张)
|
||||
|
||||
### 26. user_consents 用户协议同意记录表
|
||||
|
||||
```sql
|
||||
user_consents
|
||||
- id BIGINT UNSIGNED PK
|
||||
- user_id BIGINT UNSIGNED NOT NULL
|
||||
- consent_type VARCHAR(32) NOT NULL
|
||||
-- privacy_policy / terms_of_service
|
||||
- version VARCHAR(50) NOT NULL
|
||||
- accepted_at DATETIME NOT NULL
|
||||
- ip_address VARCHAR(100) NULL
|
||||
- user_agent VARCHAR(500) NULL
|
||||
- created_at DATETIME
|
||||
```
|
||||
|
||||
索引:
|
||||
```sql
|
||||
INDEX idx_user_consents_user_id (user_id)
|
||||
INDEX idx_user_consents_type (consent_type)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 27. app_changelogs 更新记录表(可选)
|
||||
|
||||
```sql
|
||||
app_changelogs
|
||||
- id BIGINT UNSIGNED PK
|
||||
- version VARCHAR(50) NOT NULL
|
||||
- title VARCHAR(255) NOT NULL
|
||||
- content TEXT NOT NULL
|
||||
- platform VARCHAR(32) NOT NULL DEFAULT 'ios'
|
||||
- published_at DATETIME NULL
|
||||
- created_at DATETIME
|
||||
- updated_at DATETIME
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## v0.1 建表优先级
|
||||
|
||||
### 第一批(24 张,必须)
|
||||
|
||||
```text
|
||||
users
|
||||
auth_accounts
|
||||
refresh_tokens
|
||||
user_profiles
|
||||
user_preferences
|
||||
|
||||
knowledge_bases
|
||||
knowledge_items
|
||||
tags
|
||||
knowledge_item_tags
|
||||
document_imports
|
||||
uploaded_files
|
||||
|
||||
learning_sessions
|
||||
learning_records
|
||||
active_recall_questions
|
||||
active_recall_answers
|
||||
|
||||
ai_analysis_jobs
|
||||
ai_analysis_results
|
||||
focus_items
|
||||
|
||||
review_cards
|
||||
review_logs
|
||||
|
||||
daily_learning_activities
|
||||
|
||||
notifications
|
||||
feedbacks
|
||||
user_consents
|
||||
```
|
||||
|
||||
### 第二批(3 张,可稍后)
|
||||
|
||||
```text
|
||||
knowledge_item_relations
|
||||
review_plans
|
||||
app_changelogs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 模块与表对应关系
|
||||
|
||||
```text
|
||||
auth → users, auth_accounts, refresh_tokens
|
||||
users → user_profiles, user_preferences, user_consents
|
||||
knowledge-base → knowledge_bases
|
||||
knowledge-items → knowledge_items, knowledge_item_relations, tags, knowledge_item_tags
|
||||
document-import → uploaded_files, document_imports
|
||||
learning-session → learning_sessions, learning_records
|
||||
active-recall → active_recall_questions, active_recall_answers
|
||||
ai-analysis → ai_analysis_jobs, ai_analysis_results
|
||||
focus-items → focus_items
|
||||
review → review_cards, review_logs, review_plans
|
||||
learning-activity → daily_learning_activities
|
||||
notifications → notifications
|
||||
feedback → feedbacks
|
||||
system → app_changelogs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Prisma 生成规范
|
||||
|
||||
```text
|
||||
所有表使用 BIGINT UNSIGNED AUTO_INCREMENT 主键
|
||||
状态字段使用 VARCHAR,不使用 ENUM
|
||||
JSON 字段用于存储 AI 分析结构化结果、用户偏好、元数据
|
||||
核心表添加 created_at、updated_at、deleted_at
|
||||
为 user_id、status、created_at、外键字段添加合理索引
|
||||
```
|
||||
254
技术设计/api-server/已完成/[已完成]-登录流程/Apple登录集成.md
Normal file
254
技术设计/api-server/已完成/[已完成]-登录流程/Apple登录集成.md
Normal file
@ -0,0 +1,254 @@
|
||||
# iOS 登录流程 —— Apple 登录详解
|
||||
|
||||
---
|
||||
|
||||
## 一、Apple 登录核心理解
|
||||
|
||||
**后端不需要 Apple 开发证书。** Apple 登录的公钥是 Apple 公开提供的 JWKS 地址,后端运行时获取即可。
|
||||
|
||||
```
|
||||
iOS 真机运行: 需要 Apple 开发证书 + Provisioning Profile
|
||||
后端验证 Apple 登录: 不需要证书,只需要 Apple JWKS 公钥 + Bundle ID
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、环境变量配置
|
||||
|
||||
```env
|
||||
JWT_ACCESS_SECRET=你自己的随机强密钥
|
||||
JWT_REFRESH_SECRET=你自己的随机强密钥
|
||||
APPLE_BUNDLE_ID=cloud.longde.AIStudyApp
|
||||
APPLE_ISSUER=https://appleid.apple.com
|
||||
APPLE_JWKS_URL=https://appleid.apple.com/auth/keys
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、Apple 登录流程
|
||||
|
||||
### iOS 端
|
||||
|
||||
iOS 通过 Sign in with Apple 拿到以下数据:
|
||||
|
||||
```
|
||||
identityToken ← JWT,唯一必须的值
|
||||
authorizationCode ← 可选,后面可能用于完整校验/撤销
|
||||
userIdentifier ← 可选,辅助识别,但后端不要完全信任
|
||||
email ← 可选,注意:仅首次授权时返回
|
||||
fullName ← 可选,注意:仅首次授权时返回
|
||||
```
|
||||
|
||||
### 发给后端
|
||||
|
||||
```http
|
||||
POST /api/auth/apple
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"identityToken": "eyJ...",
|
||||
"authorizationCode": "c123...",
|
||||
"userIdentifier": "000123.xxxxx",
|
||||
"email": "xxx@privaterelay.appleid.com",
|
||||
"fullName": {
|
||||
"givenName": "Long",
|
||||
"familyName": "De"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
最小必填字段只有:
|
||||
|
||||
```json
|
||||
{
|
||||
"identityToken": "eyJ..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、Apple Token 校验(核心)
|
||||
|
||||
使用 `jose` 库,不要手写公钥解析:
|
||||
|
||||
```bash
|
||||
npm install jose
|
||||
```
|
||||
|
||||
### AppleAuthService 实现
|
||||
|
||||
```ts
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
||||
|
||||
@Injectable()
|
||||
export class AppleAuthService {
|
||||
private readonly appleIssuer = 'https://appleid.apple.com';
|
||||
private readonly appleBundleId = process.env.APPLE_BUNDLE_ID!;
|
||||
private readonly jwks = createRemoteJWKSet(
|
||||
new URL('https://appleid.apple.com/auth/keys'),
|
||||
);
|
||||
|
||||
async verifyIdentityToken(identityToken: string) {
|
||||
try {
|
||||
const { payload } = await jwtVerify(identityToken, this.jwks, {
|
||||
issuer: this.appleIssuer,
|
||||
audience: this.appleBundleId,
|
||||
});
|
||||
|
||||
return {
|
||||
appleUserId: payload.sub, // ← Apple 用户唯一 ID,后端核心信任字段
|
||||
email: typeof payload.email === 'string' ? payload.email : undefined,
|
||||
emailVerified: payload.email_verified,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new UnauthorizedException('Invalid Apple identity token');
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### jose 自动完成的工作
|
||||
|
||||
```
|
||||
1. 读取 JWT header 里的 kid
|
||||
2. 请求 Apple JWKS 地址,找到 kid 对应的公钥
|
||||
3. 验证 JWT 签名(RSA)
|
||||
4. 校验 issuer === https://appleid.apple.com
|
||||
5. 校验 audience === cloud.longde.AIStudyApp
|
||||
6. 校验 exp 过期时间
|
||||
```
|
||||
|
||||
你不需要手动把 `n`、`e` 转成 RSA 公钥。
|
||||
|
||||
---
|
||||
|
||||
## 五、Apple Login 接口实现
|
||||
|
||||
### Controller
|
||||
|
||||
```ts
|
||||
@Post('apple')
|
||||
async loginWithApple(@Body() dto: AppleLoginDto) {
|
||||
const appleUser = await this.appleAuthService.verifyIdentityToken(
|
||||
dto.identityToken,
|
||||
);
|
||||
|
||||
return this.authService.loginWithProvider({
|
||||
provider: 'APPLE',
|
||||
providerUserId: appleUser.appleUserId, // ← 即 identityToken.sub
|
||||
email: appleUser.email ?? dto.email,
|
||||
nickname: dto.fullName?.givenName
|
||||
? `${dto.fullName.givenName} ${dto.fullName.familyName ?? ''}`
|
||||
: undefined,
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### DTO
|
||||
|
||||
```ts
|
||||
export class AppleLoginDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
identityToken: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
authorizationCode?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
userIdentifier?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsEmail()
|
||||
email?: string;
|
||||
|
||||
@IsOptional()
|
||||
fullName?: {
|
||||
givenName?: string;
|
||||
familyName?: string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、后端信任模型
|
||||
|
||||
| 字段 | 信任级别 | 说明 |
|
||||
|------|----------|------|
|
||||
| `identityToken.sub` | ✅ 信任 | Apple 签名验证通过后的用户唯一 ID |
|
||||
| `identityToken.aud` | ✅ 信任 | 必须等于你的 Bundle ID |
|
||||
| `identityToken.iss` | ✅ 信任 | 必须等于 `https://appleid.apple.com` |
|
||||
| `identityToken.email` | ⚠️ 参考 | Apple 侧校验过的邮箱,但可能为空 |
|
||||
| `userIdentifier`(请求体) | ❌ 不信任 | iOS 侧传的,可能被篡改 |
|
||||
| `email`(请求体) | ❌ 不信任 | iOS 侧传的,可能被篡改 |
|
||||
| `userId`(请求体) | ❌ 绝对不能信 | 用户 ID 只能从后端 JWT 获取 |
|
||||
|
||||
**核心规则**:
|
||||
|
||||
```
|
||||
1. 后端只信 identityToken 里校验出来的 sub
|
||||
2. 用 sub 去 auth_accounts(provider=APPLE, providerUserId=sub) 查找/创建用户
|
||||
3. 不要信前端传的 userIdentifier / email / name 作为唯一标识
|
||||
4. 绝对不要让前端传 userId
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、Apple 登录的特别注意事项
|
||||
|
||||
### 1. 电子邮件和姓名仅首次返回
|
||||
|
||||
```
|
||||
email / fullName 只在用户第一次授权时返回
|
||||
第二次及以后登录,Apple 不会返回这两个字段
|
||||
```
|
||||
|
||||
所以首次登录时需要将 email 和姓名保存到 `auth_accounts` 和 `users` 表中。
|
||||
|
||||
### 2. Apple 私密邮箱
|
||||
|
||||
Apple 可能返回 `xxx@privaterelay.appleid.com` 格式的私密中继邮箱,这是正常的。如果用户选择隐藏邮箱,Apple 会生成一个中转邮箱,发到该邮箱的邮件会自动转发到用户真实邮箱。
|
||||
|
||||
### 3. 什么时候后端才需要 Apple Key?
|
||||
|
||||
只有在后端要主动调用 Apple 服务时才需要 `.p8` 私钥:
|
||||
|
||||
- App Store Server API
|
||||
- App Store Connect API
|
||||
- 订阅状态查询
|
||||
- IAP 交易验证
|
||||
- APNs 推送
|
||||
|
||||
**登录不需要这些,这些都是后面的事情。**
|
||||
|
||||
---
|
||||
|
||||
## 八、完整后端校验小结
|
||||
|
||||
```text
|
||||
POST /api/auth/apple
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ 1. 拿到 identityToken │
|
||||
│ 2. 解析 header 里的 kid │
|
||||
│ 3. 请求 Apple JWKS → https://appleid.apple.com/auth/keys
|
||||
│ 4. 找到 kid 对应的公钥 │
|
||||
│ 5. 验证 JWT 签名 │
|
||||
│ 6. 校验 iss === https://appleid.apple.com │
|
||||
│ 7. 校验 aud === cloud.longde.AIStudyApp │
|
||||
│ 8. 校验 exp 未过期 │
|
||||
│ 9. 取 sub 作为 Apple 用户唯一 ID │
|
||||
│ 10. 查 auth_accounts(provider=APPLE, providerUserId=sub)│
|
||||
│ 11. 不存在→创建 User + AuthAccount │
|
||||
│ 12. 存在→找到对应 User │
|
||||
│ 13. 生成 accessToken + refreshToken │
|
||||
│ 14. refreshToken hash 入库 │
|
||||
│ 15. 返回 { accessToken, refreshToken, user } │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
268
技术设计/api-server/已完成/[已完成]-登录流程/后端接口.md
Normal file
268
技术设计/api-server/已完成/[已完成]-登录流程/后端接口.md
Normal file
@ -0,0 +1,268 @@
|
||||
# iOS 登录流程 —— 后端接口实现
|
||||
|
||||
本文覆盖后端的 `dev-login`、`refresh`、`logout`、`/users/me` 四个核心接口的实现要点。Apple 登录单独见 [ios登录流程-Apple登录.md](./ios登录流程-Apple登录.md)。
|
||||
|
||||
---
|
||||
|
||||
## 一、dev-login 接口
|
||||
|
||||
开发阶段用的快速登录接口,**生产环境必须禁止**。
|
||||
|
||||
### 请求
|
||||
|
||||
```http
|
||||
POST /api/auth/dev-login
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"email": "test@zhixi.app",
|
||||
"nickname": "测试用户",
|
||||
"devSecret": "你的开发密钥"
|
||||
}
|
||||
```
|
||||
|
||||
### DTO
|
||||
|
||||
```ts
|
||||
export class DevLoginDto {
|
||||
@IsEmail()
|
||||
email: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
nickname?: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
devSecret: string;
|
||||
}
|
||||
```
|
||||
|
||||
### 后端逻辑
|
||||
|
||||
```
|
||||
1. 判断 NODE_ENV 不是 production
|
||||
2. 校验 devSecret
|
||||
3. 根据 provider=DEV + providerUserId=email 查 AuthAccount
|
||||
4. 如果没有,创建 User + AuthAccount(provider=DEV, providerUserId=email)
|
||||
5. 生成 accessToken
|
||||
6. 生成 refreshToken
|
||||
7. refreshToken hash 入库
|
||||
8. 返回 token + user
|
||||
```
|
||||
|
||||
### 生产环境保护
|
||||
|
||||
```ts
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
throw new ForbiddenException('dev-login is disabled in production');
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、refresh 接口
|
||||
|
||||
用于 accessToken 过期后刷新登录态。
|
||||
|
||||
### 请求
|
||||
|
||||
```http
|
||||
POST /api/auth/refresh
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"refreshToken": "eyJ..."
|
||||
}
|
||||
```
|
||||
|
||||
### 后端逻辑
|
||||
|
||||
```
|
||||
1. 校验 refreshToken JWT 签名
|
||||
2. 解析出 userId / tokenId
|
||||
3. 查 refresh_tokens 表,找到 tokenId 对应记录
|
||||
4. 对比 tokenHash(SHA-256)
|
||||
5. 确认 revokedAt 为 null(未撤销)
|
||||
6. 确认 expiresAt 未过期
|
||||
7. 生成新的 accessToken
|
||||
8. 可选:轮换新的 refreshToken(旧记录 revoke,新记录入库)
|
||||
9. 返回新 token
|
||||
```
|
||||
|
||||
### 响应(第一版可简单)
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "new_access_token",
|
||||
"refreshToken": "new_refresh_token"
|
||||
}
|
||||
```
|
||||
|
||||
**建议做 refreshToken 轮换**:每次都生成新的 refreshToken,旧 token 标记 revoked,这样即使 refreshToken 泄露也能被检测到。
|
||||
|
||||
---
|
||||
|
||||
## 三、logout 接口
|
||||
|
||||
### 请求
|
||||
|
||||
```http
|
||||
POST /api/auth/logout
|
||||
Authorization: Bearer accessToken
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"refreshToken": "eyJ..."
|
||||
}
|
||||
```
|
||||
|
||||
### 后端逻辑
|
||||
|
||||
```
|
||||
1. 通过 accessToken 拿到 currentUser
|
||||
2. 解析 refreshToken,拿到 tokenId
|
||||
3. 查 refresh_tokens 表找到对应记录
|
||||
4. 校验该记录属于当前用户(userId 匹配)
|
||||
5. 设置 revokedAt = now()
|
||||
6. 返回成功
|
||||
```
|
||||
|
||||
### iOS 侧配合操作
|
||||
|
||||
```
|
||||
清除 Keychain 中的 refreshToken
|
||||
清除内存中的 accessToken + user
|
||||
跳转到登录页
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、/users/me 接口
|
||||
|
||||
App 启动后判断登录态的核心接口。
|
||||
|
||||
### 请求
|
||||
|
||||
```http
|
||||
GET /api/users/me
|
||||
Authorization: Bearer accessToken
|
||||
```
|
||||
|
||||
### 响应
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "user_xxx",
|
||||
"email": "test@zhixi.app",
|
||||
"nickname": "测试用户",
|
||||
"avatarUrl": null,
|
||||
"role": "USER",
|
||||
"status": "ACTIVE",
|
||||
"onboardingCompleted": false
|
||||
}
|
||||
```
|
||||
|
||||
### 后端逻辑
|
||||
|
||||
```
|
||||
1. JwtAuthGuard 校验 accessToken
|
||||
2. 从 JWT payload 取 currentUser.id
|
||||
3. 查 users 表返回用户信息
|
||||
```
|
||||
|
||||
**注意**:不要返回敏感字段(如密码哈希、token 等),只返回前端需要的用户展示信息。
|
||||
|
||||
---
|
||||
|
||||
## 五、JwtAuthGuard
|
||||
|
||||
全局认证守卫,保护需要登录的接口。
|
||||
|
||||
```ts
|
||||
@Injectable()
|
||||
export class JwtAuthGuard extends AuthGuard('jwt') {}
|
||||
```
|
||||
|
||||
配合 `jwt.strategy.ts` 从 Authorization Header 解析 JWT,注入 `currentUser`。
|
||||
|
||||
### CurrentUser 装饰器
|
||||
|
||||
```ts
|
||||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
||||
|
||||
export const CurrentUser = createParamDecorator(
|
||||
(data: keyof User | undefined, ctx: ExecutionContext) => {
|
||||
const request = ctx.switchToHttp().getRequest();
|
||||
const user = request.user;
|
||||
return data ? user?.[data] : user;
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 使用示例
|
||||
|
||||
```ts
|
||||
@Get('knowledge-bases')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
async list(@CurrentUser('id') userId: string) {
|
||||
return this.service.findByUser(userId);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、通用 Provider 登录方法
|
||||
|
||||
`auth.service.ts` 中的通用方法,被 dev-login 和 Apple 登录复用:
|
||||
|
||||
```ts
|
||||
async loginWithProvider(params: {
|
||||
provider: AuthProvider;
|
||||
providerUserId: string;
|
||||
email?: string;
|
||||
nickname?: string;
|
||||
}) {
|
||||
// 1. 查 auth_account
|
||||
let authAccount = await this.prisma.authAccount.findUnique({
|
||||
where: {
|
||||
provider_providerUserId: {
|
||||
provider: params.provider,
|
||||
providerUserId: params.providerUserId,
|
||||
},
|
||||
},
|
||||
include: { user: true },
|
||||
});
|
||||
|
||||
// 2. 没有就创建
|
||||
if (!authAccount) {
|
||||
const user = await this.prisma.user.create({
|
||||
data: {
|
||||
email: params.email,
|
||||
nickname: params.nickname,
|
||||
authAccounts: {
|
||||
create: {
|
||||
provider: params.provider,
|
||||
providerUserId: params.providerUserId,
|
||||
email: params.email,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
authAccount = { user, /* ... */ };
|
||||
}
|
||||
|
||||
// 3. 签发 token
|
||||
const accessToken = this.tokenService.generateAccessToken(authAccount.user);
|
||||
const refreshToken = this.tokenService.generateRefreshToken(authAccount.user);
|
||||
|
||||
// 4. refreshToken hash 入库
|
||||
await this.tokenService.saveRefreshToken(authAccount.user.id, refreshToken);
|
||||
|
||||
// 5. 返回
|
||||
return { accessToken, refreshToken, user: authAccount.user };
|
||||
}
|
||||
```
|
||||
179
技术设计/api-server/已完成/[已完成]-登录流程/总览.md
Normal file
179
技术设计/api-server/已完成/[已完成]-登录流程/总览.md
Normal file
@ -0,0 +1,179 @@
|
||||
# iOS 登录流程 —— 总体设计
|
||||
|
||||
---
|
||||
|
||||
## 一、核心理解
|
||||
|
||||
```
|
||||
Apple 登录不是你的 App 登录系统本身。
|
||||
Apple 只是帮你证明"这个人是谁"。
|
||||
真正的登录态,要由你的后端发 accessToken / refreshToken。
|
||||
```
|
||||
|
||||
最终流程:
|
||||
|
||||
```
|
||||
iOS 调 Apple 登录
|
||||
→ 拿到 Apple identityToken
|
||||
→ 发给你的 NestJS 后端
|
||||
→ 后端校验 Apple token
|
||||
→ 后端创建 / 查找用户
|
||||
→ 后端生成自己的 accessToken + refreshToken
|
||||
→ iOS 存 Keychain
|
||||
→ 以后所有接口带 Authorization: Bearer accessToken
|
||||
```
|
||||
|
||||
**开发建议**:先做 `dev-login → /users/me → Keychain → 知识库接口`,Apple 登录随后再接,不要让 Apple 流程卡住后端开发。
|
||||
|
||||
---
|
||||
|
||||
## 二、认证系统核心模型
|
||||
|
||||
后端登录系统的本质是建立自己的认证体系:
|
||||
|
||||
```
|
||||
users
|
||||
+ auth_accounts (支持多 provider:DEV、APPLE)
|
||||
+ refresh_tokens (只存 hash,不存明文)
|
||||
+ accessToken (短期令牌,JWT)
|
||||
+ refreshToken (长期令牌,JWT,可轮换/撤销)
|
||||
+ JwtAuthGuard (全局守卫)
|
||||
+ /users/me (启动态判定核心接口)
|
||||
```
|
||||
|
||||
Apple 登录只是其中一个 provider。核心是通过 `auth_accounts` 表关联第三方身份与本地用户。
|
||||
|
||||
---
|
||||
|
||||
## 三、接口清单
|
||||
|
||||
第一版 5 个接口:
|
||||
|
||||
| 接口 | 用途 | 优先级 |
|
||||
|------|------|--------|
|
||||
| `POST /api/auth/dev-login` | 开发调试登录 | ⭐ 先做 |
|
||||
| `POST /api/auth/refresh` | 刷新登录态 | ⭐ 先做 |
|
||||
| `GET /api/users/me` | 获取当前用户 | ⭐ 先做 |
|
||||
| `POST /api/auth/apple` | Apple 正式登录 | 随后接 |
|
||||
| `POST /api/auth/logout` | 退出登录 | 最后做 |
|
||||
|
||||
---
|
||||
|
||||
## 四、统一返回格式
|
||||
|
||||
登录成功后后端统一返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"accessToken": "eyJ...",
|
||||
"refreshToken": "eyJ...",
|
||||
"user": {
|
||||
"id": "user_xxx",
|
||||
"email": "test@zhixi.app",
|
||||
"nickname": "测试用户",
|
||||
"avatarUrl": null,
|
||||
"role": "USER",
|
||||
"status": "ACTIVE",
|
||||
"onboardingCompleted": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
iOS 拿到后:
|
||||
|
||||
| 数据 | 存储位置 | 用途 |
|
||||
|------|---------|------|
|
||||
| `accessToken` | 内存 | 接口请求 Authorization Header |
|
||||
| `refreshToken` | Keychain | 恢复登录 |
|
||||
| `user` | AppSession / UserStore | 用户信息展示 |
|
||||
|
||||
---
|
||||
|
||||
## 五、后端模块结构
|
||||
|
||||
```
|
||||
src/modules/auth/
|
||||
├── auth.controller.ts # 登录/刷新/登出接口
|
||||
├── auth.service.ts # 通用登录逻辑(provider 调度)
|
||||
├── apple-auth.service.ts # Apple identityToken 校验
|
||||
├── token.service.ts # JWT 生成/校验
|
||||
├── dto/
|
||||
│ ├── dev-login.dto.ts
|
||||
│ ├── apple-login.dto.ts
|
||||
│ └── refresh-token.dto.ts
|
||||
├── guards/
|
||||
│ └── jwt-auth.guard.ts # 全局认证守卫
|
||||
├── decorators/
|
||||
│ └── current-user.decorator.ts # 从 JWT 取用户
|
||||
└── strategies/
|
||||
└── jwt.strategy.ts
|
||||
|
||||
src/modules/users/
|
||||
├── users.controller.ts # /users/me
|
||||
├── users.service.ts
|
||||
└── dto/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、业务接口安全规则
|
||||
|
||||
所有业务接口依赖登录体系。**核心规则:不要相信前端传的 `userId`。**
|
||||
|
||||
```http
|
||||
GET /api/knowledge-bases
|
||||
Authorization: Bearer accessToken
|
||||
```
|
||||
|
||||
后端应从 JWT 拿当前用户:
|
||||
|
||||
```ts
|
||||
// ✅ 正确:从 token 里取 currentUser.id
|
||||
where: {
|
||||
userId: currentUser.id,
|
||||
deletedAt: null
|
||||
}
|
||||
|
||||
// ❌ 错误:从请求体取 userId
|
||||
where: {
|
||||
userId: body.userId
|
||||
}
|
||||
```
|
||||
|
||||
用户资源接口,只相信 JWT 里的 `currentUser.id`,不允许前端传递 `userId` 参数。
|
||||
|
||||
---
|
||||
|
||||
## 七、推荐开发顺序
|
||||
|
||||
```
|
||||
1. Prisma 建 users / auth_accounts / refresh_tokens
|
||||
2. TokenService:生成 accessToken / refreshToken
|
||||
3. dev-login 接口
|
||||
4. JwtAuthGuard
|
||||
5. CurrentUser 装饰器
|
||||
6. /users/me 接口
|
||||
7. iOS 接 dev-login + Keychain + AppSession
|
||||
8. 知识库接口全部加 JwtAuthGuard
|
||||
9. Apple 登录接口
|
||||
10. refresh 接口
|
||||
11. logout 接口
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 八、环境变量最小配置
|
||||
|
||||
```env
|
||||
JWT_ACCESS_SECRET=你自己的随机强密钥
|
||||
JWT_REFRESH_SECRET=你自己的随机强密钥
|
||||
APPLE_BUNDLE_ID=cloud.longde.AIStudyApp
|
||||
APPLE_ISSUER=https://appleid.apple.com
|
||||
APPLE_JWKS_URL=https://appleid.apple.com/auth/keys
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、总结
|
||||
|
||||
最终一句话:后端登录对接的核心不是"接 Apple 登录按钮",而是先建立自己的认证系统。Apple 登录只是其中一个 provider。先把 `dev-login → token → /users/me → iOS Keychain` 跑通,知识库和学习闭环就不会卡住。
|
||||
153
技术设计/api-server/已完成/[已完成]-登录流程/数据库设计.md
Normal file
153
技术设计/api-server/已完成/[已完成]-登录流程/数据库设计.md
Normal file
@ -0,0 +1,153 @@
|
||||
# iOS 登录流程 —— 数据库设计
|
||||
|
||||
---
|
||||
|
||||
## 一、users 表
|
||||
|
||||
用户主表,存储用户基础信息。
|
||||
|
||||
```prisma
|
||||
model User {
|
||||
id String @id @default(cuid())
|
||||
email String?
|
||||
nickname String?
|
||||
avatarUrl String?
|
||||
role UserRole @default(USER)
|
||||
status UserStatus @default(ACTIVE)
|
||||
onboardingCompleted Boolean @default(false)
|
||||
|
||||
authAccounts AuthAccount[]
|
||||
refreshTokens RefreshToken[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
enum UserRole {
|
||||
USER
|
||||
ADMIN
|
||||
SUPER_ADMIN
|
||||
}
|
||||
|
||||
enum UserStatus {
|
||||
ACTIVE
|
||||
DISABLED
|
||||
DELETED
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | String (cuid) | 主键 |
|
||||
| `email` | String? | 邮箱,可选(Apple 登录首次可能提供) |
|
||||
| `nickname` | String? | 昵称 |
|
||||
| `avatarUrl` | String? | 头像 URL |
|
||||
| `role` | UserRole | 角色,默认 USER |
|
||||
| `status` | UserStatus | 状态,默认 ACTIVE |
|
||||
| `onboardingCompleted` | Boolean | 是否完成引导,默认 false |
|
||||
| `authAccounts` | 关联 | 一对多关联 auth_accounts |
|
||||
| `refreshTokens` | 关联 | 一对多关联 refresh_tokens |
|
||||
|
||||
---
|
||||
|
||||
## 二、auth_accounts 表
|
||||
|
||||
记录用户通过什么方式(provider)登录,支持一个用户绑定多个登录方式。
|
||||
|
||||
```prisma
|
||||
model AuthAccount {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
provider AuthProvider
|
||||
providerUserId String
|
||||
email String?
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([provider, providerUserId])
|
||||
@@index([userId])
|
||||
}
|
||||
|
||||
enum AuthProvider {
|
||||
DEV
|
||||
APPLE
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | String (cuid) | 主键 |
|
||||
| `userId` | String | 关联 users 表 |
|
||||
| `provider` | AuthProvider | 登录提供商(DEV / APPLE) |
|
||||
| `providerUserId` | String | 提供商侧的用户唯一 ID |
|
||||
| `email` | String? | 提供商侧邮箱 |
|
||||
| `@@unique([provider, providerUserId])` | 约束 | 同一个提供商的用户唯一 |
|
||||
|
||||
**查找逻辑**:
|
||||
|
||||
```
|
||||
Apple 登录时:
|
||||
provider = APPLE
|
||||
providerUserId = identityToken 里校验出来的 sub
|
||||
→ 如果不存在,创建 User + AuthAccount
|
||||
→ 如果存在,直接找到对应 User
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、refresh_tokens 表
|
||||
|
||||
**重要:refreshToken 不要明文存数据库,只存 hash。**
|
||||
|
||||
```prisma
|
||||
model RefreshToken {
|
||||
id String @id @default(cuid())
|
||||
userId String
|
||||
tokenHash String
|
||||
expiresAt DateTime
|
||||
revokedAt DateTime?
|
||||
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([userId])
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `id` | String (cuid) | 主键,同时写入 JWT payload 作为 `tokenId` |
|
||||
| `userId` | String | 关联 users 表 |
|
||||
| `tokenHash` | String | refreshToken 的 hash 值(SHA-256) |
|
||||
| `expiresAt` | DateTime | 过期时间 |
|
||||
| `revokedAt` | DateTime? | 撤销时间(登出时设置) |
|
||||
|
||||
**刷新时的校验链**:
|
||||
|
||||
```
|
||||
1. 解析 refreshToken JWT,拿到 userId + tokenId
|
||||
2. 查 refresh_tokens 表,找到对应记录
|
||||
3. 对比 tokenHash
|
||||
4. 确认 revokedAt 为 null(未撤销)
|
||||
5. 确认 expiresAt 未过期
|
||||
6. 签发新的 accessToken(可选轮换新的 refreshToken)
|
||||
```
|
||||
|
||||
**登出时**:将对应记录的 `revokedAt` 设为当前时间。
|
||||
|
||||
---
|
||||
|
||||
## 四、ER 关系总结
|
||||
|
||||
```
|
||||
User (1) ──── (N) AuthAccount 一个用户可有多种登录方式
|
||||
User (1) ──── (N) RefreshToken 一个用户可有多个活跃 refreshToken(多设备)
|
||||
```
|
||||
|
||||
- 用户与登录方式是解耦的:用户是一个独立实体,通过 `auth_accounts` 关联到具体的第三方身份。
|
||||
- 这种设计天然支持未来扩展更多登录方式(如 Google、微信等),只需在 `AuthProvider` 枚举中添加即可。
|
||||
0
技术设计/harmonyos-projects/.gitkeep
Normal file
0
技术设计/harmonyos-projects/.gitkeep
Normal file
172
技术设计/ios-projects/[设计中]-登录集成.md
Normal file
172
技术设计/ios-projects/[设计中]-登录集成.md
Normal file
@ -0,0 +1,172 @@
|
||||
# iOS 登录流程 —— iOS 端集成
|
||||
|
||||
---
|
||||
|
||||
## 一、iOS 需要的核心组件
|
||||
|
||||
```
|
||||
AuthService ← 调后端登录接口
|
||||
UserService ← 用户信息管理
|
||||
TokenStore ← token 存储协议
|
||||
KeychainTokenStore ← 基于 Keychain 的安全存储实现
|
||||
AppSession ← 管理当前登录态
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、数据存储策略
|
||||
|
||||
| 数据 | 存储位置 | 生命周期 | 原因 |
|
||||
|------|---------|---------|------|
|
||||
| `accessToken` | 内存 | App 运行期间 | 短期使用,不需要持久化 |
|
||||
| `refreshToken` | Keychain | 长期持久化 | 敏感凭证,需安全存储,卸载后也保留 |
|
||||
| `user` | AppSession / UserStore | App 运行期间 | 用户展示信息 |
|
||||
|
||||
---
|
||||
|
||||
## 三、App 启动流程
|
||||
|
||||
```
|
||||
App 启动
|
||||
→ AppSession.checkSession()
|
||||
→ 从 Keychain 读取 refreshToken
|
||||
→ 如果没有 refreshToken
|
||||
→ 进入登录页
|
||||
→ 如果有 refreshToken
|
||||
→ 调用 POST /api/auth/refresh
|
||||
→ 成功
|
||||
→ 存储新的 accessToken + refreshToken
|
||||
→ 调用 GET /api/users/me
|
||||
→ 存储 user 信息
|
||||
→ 进入主界面
|
||||
→ 失败
|
||||
→ 清空 Keychain + 内存 token
|
||||
→ 进入登录页
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、登录流程
|
||||
|
||||
### 开发登录(dev-login)
|
||||
|
||||
```
|
||||
用户在登录页输入邮箱/昵称
|
||||
→ AuthService.devLogin(email, nickname)
|
||||
→ POST /api/auth/dev-login
|
||||
→ 后端返回 { accessToken, refreshToken, user }
|
||||
→ refreshToken 存 Keychain
|
||||
→ accessToken 放内存
|
||||
→ user 放 AppSession
|
||||
→ 进入主界面
|
||||
```
|
||||
|
||||
### Apple 登录
|
||||
|
||||
```
|
||||
用户点击 Sign in with Apple
|
||||
→ iOS 系统弹出 Apple 授权界面
|
||||
→ 用户授权成功
|
||||
→ 拿到 identityToken + authorizationCode 等
|
||||
→ AuthService.appleLogin(identityToken, ...)
|
||||
→ POST /api/auth/apple
|
||||
→ 后端验证 Apple token,返回 { accessToken, refreshToken, user }
|
||||
→ refreshToken 存 Keychain
|
||||
→ accessToken 放内存
|
||||
→ user 放 AppSession
|
||||
→ 进入主界面
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、接口请求拦截
|
||||
|
||||
所有需要登录的接口都必须携带:
|
||||
|
||||
```http
|
||||
Authorization: Bearer {accessToken}
|
||||
```
|
||||
|
||||
### HTTP Client 封装建议
|
||||
|
||||
```
|
||||
所有请求自动注入 Authorization Header
|
||||
→ 从 AuthService 获取当前 accessToken
|
||||
→ 自动添加到请求头
|
||||
```
|
||||
|
||||
### 401 自动处理
|
||||
|
||||
```
|
||||
接口返回 401
|
||||
→ 调用 POST /api/auth/refresh
|
||||
→ 成功
|
||||
→ 更新 accessToken
|
||||
→ 自动重试原请求
|
||||
→ 失败
|
||||
→ 清空 Keychain + 内存数据
|
||||
→ 跳转登录页
|
||||
```
|
||||
|
||||
**重要**:重试原请求时注意避免无限循环,设置最多重试 1 次。
|
||||
|
||||
---
|
||||
|
||||
## 六、退出登录
|
||||
|
||||
```
|
||||
用户点击退出登录
|
||||
→ AuthService.logout()
|
||||
→ POST /api/auth/logout
|
||||
Body: { refreshToken: 从 Keychain 取的 refreshToken }
|
||||
Header: Authorization: Bearer accessToken
|
||||
→ 后端标记 refreshToken revoked
|
||||
→ iOS 端:
|
||||
→ 清除 Keychain 中的 refreshToken
|
||||
→ 清除内存中的 accessToken
|
||||
→ 清除 AppSession 中的 user
|
||||
→ 跳转登录页
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 七、Token 存储对比:UserDefaults vs Keychain
|
||||
|
||||
| | UserDefaults | Keychain |
|
||||
|------|------------|----------|
|
||||
| 安全性 | 低(明文存储) | 高(系统级加密) |
|
||||
| 应用卸载后 | 数据被清除 | 可选保留(推荐保留) |
|
||||
| 备份 | 包含在 iTunes/iCloud 备份中 | 仅加密备份 |
|
||||
| 适用数据 | 非敏感偏好设置 | 密码、Token 等敏感凭据 |
|
||||
|
||||
**结论:refreshToken 一定要用 Keychain 存储。**
|
||||
|
||||
---
|
||||
|
||||
## 八、Session 状态机
|
||||
|
||||
```
|
||||
App 启动
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ 检查 Keychain │
|
||||
│ 有 refreshToken? │
|
||||
└───────┬─────────┘
|
||||
│
|
||||
┌───────┴───────┐
|
||||
│ 有 │ 无
|
||||
▼ ▼
|
||||
┌─────────┐ ┌──────────┐
|
||||
│ 调 refresh │ │ 进入登录页 │
|
||||
│ 接口 │ └──────────┘
|
||||
└─────┬─────┘
|
||||
│
|
||||
┌────┴────┐
|
||||
│ 成功 │ 失败
|
||||
▼ ▼
|
||||
┌────────┐ ┌──────────┐
|
||||
│ 调 /me │ │ 清空数据 │
|
||||
│ 进主页 │ │ 进登录页 │
|
||||
└────────┘ └──────────┘
|
||||
```
|
||||
139
技术设计/ios-projects/[进行中]-架构设计.md
Normal file
139
技术设计/ios-projects/[进行中]-架构设计.md
Normal file
@ -0,0 +1,139 @@
|
||||
# 知习 ZhiXi — 项目架构
|
||||
|
||||
> 更新时间:2026-05-10
|
||||
|
||||
## 一、项目结构
|
||||
|
||||
```
|
||||
AIStudyApp/
|
||||
├── AIStudyAppApp.swift # 应用入口 + 引导流程路由
|
||||
│ ├── OnboardingFlowView # Splash → Welcome → Login → Onboarding → GoalSetup
|
||||
│ ├── SplashPage # 启动页
|
||||
│ ├── WelcomePage # 欢迎页
|
||||
│ ├── LoginPage # 登录页
|
||||
│ ├── OnboardingPage # 功能引导
|
||||
│ └── GoalSetupPage # 学习目标设置
|
||||
│
|
||||
├── ContentView.swift # 5-Tab 主界面
|
||||
│ ├── ZXTabBar # 自定义底部 Tab 栏
|
||||
│ ├── ZXAIInputBar # AI 输入栏
|
||||
│ ├── ZXScoreBox # 评分组件
|
||||
│ └── ZXIconBtn # 图标按钮
|
||||
│
|
||||
├── Core/
|
||||
│ └── DesignSystem/
|
||||
│ └── DesignTokens.swift # 颜色/渐变/圆角/间距/字号/排版
|
||||
│
|
||||
├── Features/
|
||||
│ ├── AI/
|
||||
│ │ ├── AIHomeView.swift # AI 首页(Tab 1)
|
||||
│ │ └── DailyThinkingPage.swift # 今日思考 + AIChat + RecallTest + WeakPoints + AIFeedback
|
||||
│ │
|
||||
│ ├── Library/
|
||||
│ │ ├── LibraryHomeView.swift # 知识库首页(Tab 2)
|
||||
│ │ └── LibrarySubpages.swift # Create/Detail/Add/Import/KnowledgeDetail/Edit
|
||||
│ │
|
||||
│ ├── Study/
|
||||
│ │ └── StudyHomeView.swift # 学习工作台(Tab 3)
|
||||
│ │
|
||||
│ ├── Analysis/
|
||||
│ │ └── AnalysisHomeView.swift # 学习分析(Tab 4)
|
||||
│ │
|
||||
│ └── Profile/
|
||||
│ └── ProfileView.swift # 我的(Tab 5)
|
||||
│
|
||||
└── Assets.xcassets/ # 资源文件
|
||||
```
|
||||
|
||||
## 二、导航架构
|
||||
|
||||
```
|
||||
@main AIStudyAppApp
|
||||
├── hasCompletedOnboarding == false
|
||||
│ └── OnboardingFlowView
|
||||
│ ├── step 0: SplashPage ──(2s)──→ step 1
|
||||
│ ├── step 1: WelcomePage ──"开始使用"──→ step 2
|
||||
│ │ ──"已有账号"──→ hasCompletedOnboarding = true
|
||||
│ ├── step 2: LoginPage ──"登录"──→ step 3
|
||||
│ │ ──"跳过"──→ hasCompletedOnboarding = true
|
||||
│ ├── step 3: OnboardingPage ──"下一步"──→ step 4
|
||||
│ └── step 4: GoalSetupPage ──"开始学习"──→ hasCompletedOnboarding = true
|
||||
│
|
||||
└── hasCompletedOnboarding == true
|
||||
└── ContentView (5-Tab)
|
||||
├── Tab "AI" → NavigationStack { AIHomeView }
|
||||
│ ├── → DailyThinkingPage → AIFeedbackPageView
|
||||
│ ├── → RecallTestPage
|
||||
│ ├── → WeakPointsPage
|
||||
│ └── → AIChatPage
|
||||
│
|
||||
├── Tab "知识库" → NavigationStack { LibraryHomeView }
|
||||
│ ├── → LibraryDetailPage → KnowledgeDetailPage
|
||||
│ ├── → CreateLibraryPage
|
||||
│ ├── → AddKnowledgePage
|
||||
│ ├── → ImportPage
|
||||
│ └── → EditKnowledgePage
|
||||
│
|
||||
├── Tab "学习" → NavigationStack { StudyHomeView }
|
||||
├── Tab "分析" → NavigationStack { AnalysisHomeView }
|
||||
└── Tab "我的" → NavigationStack { ProfileView }
|
||||
```
|
||||
|
||||
## 三、数据流(当前均为静态 Mock)
|
||||
|
||||
所有页面目前使用 `@State` 管理的本地假数据,尚未接入真实后端:
|
||||
|
||||
| 数据 | 当前状态 |
|
||||
|------|----------|
|
||||
| 用户信息 | ProfileView 中硬编码 |
|
||||
| 知识库列表 | LibraryHomeView 中硬编码 4 个 |
|
||||
| 学习任务 | StudyHomeView 中硬编码 5 个 |
|
||||
| AI 分析结果 | 各 AI 页面静态文本 |
|
||||
| 学习统计 | AnalysisHomeView 中硬编码 |
|
||||
| 登录状态 | @AppStorage 布尔值控制 |
|
||||
|
||||
## 四、技术栈
|
||||
|
||||
| 层 | 技术 | 备注 |
|
||||
|----|------|------|
|
||||
| 语言 | Swift | — |
|
||||
| UI 框架 | SwiftUI | iOS 17+ |
|
||||
| 架构模式 | 当前未分层(View 内聚) | 计划 MVVM + Service + Repository |
|
||||
| 设计系统 | 自定义 DesignTokens | 从 React 原型 1:1 提取 |
|
||||
| 构建工具 | Xcode | — |
|
||||
| 目标平台 | iPhone (iOS 17+) | 未做 iPad/Mac 适配 |
|
||||
|
||||
## 五、与计划架构的差异
|
||||
|
||||
计划文档(`官网与技术基础.md`)中定义的 iOS 目录结构:
|
||||
|
||||
```
|
||||
计划架构 当前实现
|
||||
───────────────────────────────── ─────────────────
|
||||
App/AIStudyApp.swift AIStudyAppApp.swift ✅
|
||||
App/AppConfig.swift 未实现 ❌
|
||||
App/AppRouter.swift 未实现 ❌
|
||||
Core/Network/ 未实现 ❌
|
||||
Core/Auth/ 未实现 ❌
|
||||
Core/Storage/ 未实现 ❌
|
||||
Core/Localization/ 未实现 ❌
|
||||
Core/DesignSystem/ DesignTokens.swift ✅ (部分)
|
||||
Features/*/Views/ Features/*/ ✅
|
||||
Features/*/ViewModels/ 未实现 ❌ (View 内聚状态)
|
||||
Features/*/Models/ 未实现 ❌ (无独立 Model)
|
||||
Shared/Components/ 分散在各 View 文件中 ⚠️
|
||||
Shared/Extensions/ 仅 Color hex 扩展 ✅
|
||||
Shared/Utils/ 未实现 ❌
|
||||
Shared/Constants/ 未实现 ❌
|
||||
Resources/Localizable.xcstrings 未实现 ❌
|
||||
Resources/PreviewData/ 未实现 ❌
|
||||
```
|
||||
|
||||
## 六、待重构项
|
||||
|
||||
1. **View 文件过大**:`AIStudyAppApp.swift` 包含 5 个独立页面,应拆分到各自文件
|
||||
2. **无 ViewModel 层**:所有状态和数据逻辑写在 View 中,需要抽离
|
||||
3. **无 Model 层**:数据结构(如学习任务、知识库卡片)分散在 View 中用局部变量定义
|
||||
4. **共享组件未集中**:`ZXTabBar`、`ZXBackHeader` 等组件散落在不同文件中
|
||||
5. **无网络层**:无 API Client、无 Auth Service、无 Storage 层
|
||||
6. **无本地化**:所有文案硬编码,未使用 `LocalizedStringKey`
|
||||
550
技术设计/ios-projects/已完成/[已完成]-样式规范.md
Normal file
550
技术设计/ios-projects/已完成/[已完成]-样式规范.md
Normal file
@ -0,0 +1,550 @@
|
||||
# 知习 iOS 样式规范
|
||||
|
||||
> 基于现有 DesignTokens 与实际页面中反复出现的 UI 模式,归纳形成本规范。
|
||||
> 后续创建新页面时,优先从本文档引用的 token 和组件中选择,保持一致的设计语言。
|
||||
|
||||
---
|
||||
|
||||
## 一、色彩系统
|
||||
|
||||
所有颜色定义在 `Core/DesignSystem/DesignTokens.swift`,命名前缀 `zx`(知习)。
|
||||
|
||||
### 1.1 背景
|
||||
|
||||
| Token | 色值 | 用途 |
|
||||
|---|---|---|
|
||||
| `zxBg0` | `#0F0F1A` | 页面基底(与 zxBg1 组成 page 渐变) |
|
||||
| `zxBg1` | `#12122A` | page 渐变的第二色 |
|
||||
| `zxBg2` | `#0A0A14` | 手机外壳装饰用,极少使用 |
|
||||
| `zxBgSplash` | `#0D0D20` | 启动页专用 |
|
||||
|
||||
### 1.2 文字
|
||||
|
||||
所有文字色基于 `#F0F0FF`(近白紫调)变化透明度:
|
||||
|
||||
| Token | 透明度 | 用途 |
|
||||
|---|---|---|
|
||||
| `zxF0` | 100% | 标题、正文高亮 |
|
||||
| `zxF007` | 70% | 次重要正文 |
|
||||
| `zxF006` | 60% | — |
|
||||
| `zxF05` | 50% | 次要信息 |
|
||||
| `zxF0045` | 45% | — |
|
||||
| `zxF04` | 40% | 辅助描述 |
|
||||
| `zxF035` | 35% | 弱标签、灰色字段名 |
|
||||
| `zxF03` | 30% | 占位符级别 |
|
||||
| `zxF02` | 20% | 极弱(如未选中图标边框) |
|
||||
|
||||
### 1.3 品牌/语义色
|
||||
|
||||
| Token | 色值 | 含义 |
|
||||
|---|---|---|
|
||||
| `zxPurple` | `#7C6EFA` | 主品牌,选中态、标签、进度 |
|
||||
| `zxAccent` | `#A78BFA` | 次要品牌,AI 相关 |
|
||||
| `zxOrange` | `#F97316` | 热度/连续天数/回忆 |
|
||||
| `zxTeal` | `#2DD4BF` | 语言/词汇 |
|
||||
| `zxCyan` | `#4ECDC4` | 进度条渐变 |
|
||||
| `zxGreen` | `#34D399` | 已掌握、成功 |
|
||||
| `zxYellow` | `#F59E0B` | 薄弱/警告/待复习 |
|
||||
| `zxRed` | `#EF4444` | 错误/高优先级 |
|
||||
|
||||
**彩色半透明背景**(用于标签、badge 底衬):
|
||||
|
||||
```swift
|
||||
zxPurpleBG(0.12) // 紫色 12% 透明
|
||||
zxOrangeBG(0.10) // 橙色 10% 透明
|
||||
zxGreenBG(0.15) // 绿色 15% 透明
|
||||
zxYellowBG(0.15) // 黄色 15% 透明
|
||||
zxTealBG(0.10) // 青色 10% 透明
|
||||
zxRedBG(0.15) // 红色 15% 透明
|
||||
```
|
||||
|
||||
### 1.4 边框/分割线
|
||||
|
||||
| Token | 透明度 | 用途 |
|
||||
|---|---|---|
|
||||
| `zxBorder015` | 15% | 较明显边框 |
|
||||
| `zxBorder01` | 10% | 标准边框、虚线框 |
|
||||
| `zxBorder008` | 8% | 通用卡片边框 |
|
||||
| `zxBorder006` | 6% | 弱边框、卡片分隔 |
|
||||
| `zxBorder004` | 4% | 极弱边框 |
|
||||
|
||||
### 1.5 填充(半透明叠层)
|
||||
|
||||
| Token | 透明度 | 用途 |
|
||||
|---|---|---|
|
||||
| `zxFill01` | 10% | 图表柱状 |
|
||||
| `zxFill008` | 8% | 进度条底色 |
|
||||
| `zxFill006` | 6% | 列表图标底衬 |
|
||||
| `zxFill005` | 5% | 按钮/选中行底衬 |
|
||||
| `zxFill004` | 4% | 输入框/面板底色 |
|
||||
| `zxFill003` | 3% | 卡片底色 |
|
||||
|
||||
---
|
||||
|
||||
## 二、渐变
|
||||
|
||||
所有渐变定义在 `ZXGradient` enum。
|
||||
|
||||
| 渐变 | 颜色 | 方向 | 用途 |
|
||||
|---|---|---|---|
|
||||
| `page` | `#0F0F1A → #12122A` | top→bottom | 所有主页面背景 |
|
||||
| `splash` | `#0D0D20 → #0F0F1A → #130D20` | top→bottom | 启动页背景 |
|
||||
| `brand` | `#7C6EFA → #F97316` | topLeading→bottomTrailing | CTA 按钮、播放按钮 |
|
||||
| `brandPurple` | `#7C6EFA → #9B8BFF` | leading→trailing | 发送按钮、AI 气泡 |
|
||||
| `ctaButton` | `#7C6EFA → #F97316` | topLeading→bottomTrailing | 同 brand,CTA 语义 |
|
||||
| `ctaPurple` | `#7C6EFA → #9B8BFF` | topLeading→bottomTrailing | 紫色 CTA(创建/保存/提交) |
|
||||
| `progressBar` | `#7C6EFA → #4ECDC4` | leading→trailing | 进度条 |
|
||||
| `thinkingCard` | `#7C6EFA 8% → #F97316 4%` | topLeading→bottomTrailing | 思考卡片 |
|
||||
| `progressCard` | `#7C6EFA 10% → #F97316 5%` | topLeading→bottomTrailing | 进度卡片 |
|
||||
| `feedbackScore` | `#7C6EFA 12% → #34D399 6%` | topLeading→bottomTrailing | 反馈评分卡片 |
|
||||
| `profileCard` | `#7C6EFA 15% → #F97316 8%` | topLeading→bottomTrailing | 个人页卡片 |
|
||||
|
||||
---
|
||||
|
||||
## 三、圆角
|
||||
|
||||
```swift
|
||||
ZXRadius.xs = 2 // 进度指示器小圆点
|
||||
ZXRadius.sm = 8 // 小图标
|
||||
ZXRadius.md = 10 // 标准图标按钮
|
||||
ZXRadius.lg = 12 // 标签/徽章
|
||||
ZXRadius.xl = 14 // 卡片/输入框/行
|
||||
ZXRadius.xl2 = 16 // 大卡片/对话框
|
||||
ZXRadius.xl3 = 20 // 主要面板
|
||||
|
||||
ZXRadius.button = 12 // 标准按钮
|
||||
ZXRadius.buttonLg = 18 // 大按钮(CTA)
|
||||
ZXRadius.icon = 10 // 小图标
|
||||
ZXRadius.iconLg = 12 // 中图标
|
||||
ZXRadius.avatar = 13 // 头像/emoji 图标
|
||||
```
|
||||
|
||||
**使用原则**:
|
||||
- 卡片统一 `14`–`20`
|
||||
- 按钮统 `12`–`18`
|
||||
- 输入框 `14`
|
||||
- 标签 `Capsule()`(自动全圆角)
|
||||
|
||||
---
|
||||
|
||||
## 四、间距
|
||||
|
||||
```swift
|
||||
ZXSpacing.ss = 2 // 字间距/tracking 用
|
||||
ZXSpacing.xs = 4
|
||||
ZXSpacing.sm = 6
|
||||
ZXSpacing.md = 8 // 卡片内元素间距
|
||||
ZXSpacing.lg = 10
|
||||
ZXSpacing.xl = 12 // 行内元素间距
|
||||
ZXSpacing.xl2 = 14
|
||||
ZXSpacing.xl3 = 16 // 卡片间距
|
||||
ZXSpacing.xl4 = 20 // 页面水平内边距
|
||||
ZXSpacing.xl5 = 24
|
||||
ZXSpacing.xl6 = 28
|
||||
|
||||
// 专用
|
||||
ZXSpacing.pageHPadding = 20 // 所有页面两侧统一留白
|
||||
ZXSpacing.statusBarH = 44 // 状态栏 + Dynamic Island
|
||||
ZXSpacing.tabBarH = 83 // 底部 TabBar 总高
|
||||
ZXSpacing.homeIndicatorH = 34 // Home Indicator
|
||||
```
|
||||
|
||||
**页面结构公式**:
|
||||
```
|
||||
header top padding = statusBarH + 16
|
||||
每个 section 间距 = 12–20
|
||||
ScrollView bottom = 120(有 TabBar)/ 80–100(子页面)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、尺寸
|
||||
|
||||
```swift
|
||||
// 按钮
|
||||
ZXSize.iconBtn = 36 // 图标按钮(ZXIconBtn 默认)
|
||||
ZXSize.buttonH = 42 // 标准按钮高
|
||||
ZXSize.buttonLgH = 52 // 大按钮高
|
||||
ZXSize.buttonXlH = 56 // CTA 按钮高
|
||||
ZXSize.sendBtn = 30 // 发送按钮
|
||||
|
||||
// 图标
|
||||
ZXSize.iconSm = 14
|
||||
ZXSize.iconMd = 16
|
||||
ZXSize.iconLg = 18
|
||||
ZXSize.tabIcon = 22 // TabBar 图标
|
||||
ZXSize.listIcon = 40 // 列表图标
|
||||
ZXSize.libraryIcon = 44 // 知识库卡片图标
|
||||
|
||||
// 头像
|
||||
ZXSize.avatarSm = 36
|
||||
ZXSize.avatarMd = 64
|
||||
ZXSize.avatarLg = 80
|
||||
|
||||
// 其他
|
||||
ZXSize.quickActionH = 72 // 快捷操作高度
|
||||
ZXSize.inputH = 44 // 输入框高度
|
||||
ZXSize.progressH = 5 // 进度条高度
|
||||
ZXSize.scoreBox = 36 // 分数方块
|
||||
ZXSize.weakBox = 40 // 薄弱点分数方块
|
||||
ZXSize.topBar = 3 // 顶部装饰条
|
||||
ZXSize.searchIconBtn = 36 // 搜索图标按钮
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、字体层级
|
||||
|
||||
```swift
|
||||
// 使用方式: .font(.system(size: ZXFont.xxx.size, weight: ZXFont.xxx.weight))
|
||||
|
||||
titleLarge // 22pt, heavy, -0.5 → 页面主标题
|
||||
titleMedium // 20pt, heavy, -0.4 → 二级标题
|
||||
sectionTitle // 15pt, bold → 区域标题
|
||||
subsectionTitle // 14pt, bold → 子标题
|
||||
body // 13pt, semibold, 1.4 → 正文
|
||||
bodySmall // 12pt, medium → 辅助信息
|
||||
caption // 10pt, bold → 标签加粗
|
||||
captionSmall // 10pt, regular → 标签常规
|
||||
labelXs // 9pt, regular → 最小标签
|
||||
score // 12pt, heavy → 分数
|
||||
scoreLarge // 22pt, heavy, 1 → 大分数
|
||||
date // 12pt, medium → 日期
|
||||
description // 12pt, regular, 0.4 → 描述文字
|
||||
```
|
||||
|
||||
**实际页面中常用的内联声明**(可直接使用,也可用 ZXFont 引用):
|
||||
- 页面大标题:`.font(.system(size: 22, weight: .heavy)).tracking(-0.5)` `.foregroundColor(.zxF0)`
|
||||
- 区域标题:`.font(.system(size: 15, weight: .bold)).foregroundColor(.zxF0)`
|
||||
- 卡片标题:`.font(.system(size: 13, weight: .semibold)).foregroundColor(.zxF0)`
|
||||
- 辅助文字:`.font(.system(size: 12)).foregroundColor(.zxF04)`
|
||||
- 标签文字:`.font(.system(size: 10, weight: .semibold))`
|
||||
- 大数值:`.font(.system(size: 26, weight: .black))`
|
||||
|
||||
---
|
||||
|
||||
## 七、共享组件目录
|
||||
|
||||
以下组件散落在各页面文件中,新页面应直接复用,禁止重复实现。
|
||||
|
||||
### 7.1 导航/布局
|
||||
|
||||
**ZXTabBar**(`ContentView.swift:58`)
|
||||
5 个 tab(AI / 知识库 / 学习 / 分析 / 我的),选中态紫色高亮 + 圆形背景扩散。
|
||||
```swift
|
||||
ZXTabBar(active: $selectedTab)
|
||||
```
|
||||
|
||||
**ZXBackHeader**(`DailyThinkingPage.swift:52`)
|
||||
子页面顶部返回栏,含标题、副标题、可选的右侧按钮。
|
||||
```swift
|
||||
ZXBackHeader(title: "标题", subtitle: "副标题") { trailingView }
|
||||
ZXBackHeader(title: "标题", subtitle: nil, onBack: customBackAction) { ... }
|
||||
```
|
||||
|
||||
### 7.2 按钮
|
||||
|
||||
**ZXIconBtn**(`ContentView.swift:100`)
|
||||
标准 36pt 圆形图标按钮,可切换品牌渐变样式。
|
||||
```swift
|
||||
ZXIconBtn(icon: "bell", size: 36) { action }
|
||||
ZXIconBtn(icon: "plus", size: 36, branded: true) { action } // 品牌渐变底
|
||||
```
|
||||
|
||||
**ZXOutlineBtn**(`DailyThinkingPage.swift:167`)
|
||||
44pt 高描边文字按钮。
|
||||
```swift
|
||||
ZXOutlineBtn(text: "深入提问")
|
||||
```
|
||||
|
||||
### 7.3 列表/卡片行
|
||||
|
||||
**ZXCardRow**(`LibrarySubpages.swift:40`)
|
||||
带 emoji 图标、标题、描述、状态标签的标准列表行。
|
||||
```swift
|
||||
ZXCardRow(emoji: "📝", title: "标题", desc: "描述", status: "已掌握", c: .zxGreen)
|
||||
```
|
||||
|
||||
**ZXImportOption**(`LibrarySubpages.swift:93`)
|
||||
带大图标 + 标题描述的导入选项行。
|
||||
|
||||
**ZXProfileMenuRow**(`ProfileView.swift:58`)
|
||||
Profile 页菜单行,emoji + 标题 + 描述 + 箭头。
|
||||
|
||||
**ReviewTaskRow**(`ReviewPlanView.swift:82`)
|
||||
复习任务行,含完成勾选 + 复习类型标签 + 播放按钮。
|
||||
|
||||
**ZXAIInteractionRow**(`AIHomeView.swift:138`)
|
||||
AI 互动记录行,含标签 + 时间 + 分数。
|
||||
|
||||
### 7.4 数据展示
|
||||
|
||||
**ZXScoreBox**(`ContentView.swift:50`)
|
||||
36pt 方形分数格。
|
||||
```swift
|
||||
ZXScoreBox(score: 82, bg: .zxGreenBG(0.15), fg: .zxGreen)
|
||||
```
|
||||
|
||||
**ZXStatBadge**(`AnalysisHomeView.swift:74`)
|
||||
统计徽章,图标 + 数值 + 标签 + 趋势。
|
||||
|
||||
**ZXWeakRow**(`AnalysisHomeView.swift:91`)
|
||||
薄弱知识点行,分数 + 标题 + 库名 + 优先级。
|
||||
|
||||
**ZXAchievementBadge**(`ProfileView.swift:61`)
|
||||
成就徽章,emoji + 标签。
|
||||
|
||||
**ZXProfileStat**(`ProfileView.swift:55`)
|
||||
Profile 页三栏统计数字。
|
||||
|
||||
**ZXChartView**(`AnalysisHomeView.swift:117`)
|
||||
折线图(掌握度趋势)。
|
||||
|
||||
### 7.5 输入
|
||||
|
||||
**ZXAIInputBar**(`ContentView.swift:26`)
|
||||
AI 对话输入栏,含 sparkles 图标 + 文本框 + 麦克风 + 发送按钮。
|
||||
|
||||
### 7.6 标签
|
||||
|
||||
**ZXChip**(`LibrarySubpages.swift:74`)
|
||||
Capsule 标签,彩色文字 + 半透明底色。
|
||||
|
||||
**复习类型标签**(`ReviewTaskRow.swift:129`)
|
||||
4 种:间隔重复(紫) / 费曼(accent) / 回忆(橙) / 薄弱(黄)。
|
||||
|
||||
### 7.7 卡片装饰
|
||||
|
||||
**ZXQuickAction**(`AIHomeView.swift:132`)
|
||||
72pt 高快捷操作按钮,emoji + 文字。
|
||||
|
||||
**ZLibraryCard**(`LibraryHomeView.swift:32`)
|
||||
知识库卡片,顶部渐变色条 + emoji + 名称 + 进度 + 标签。
|
||||
|
||||
### 7.8 状态组件
|
||||
|
||||
**ZXLoadingView**(`Shared/Components/ZXLoadingView.swift`)
|
||||
全屏加载指示器,紫色 ProgressView + "加载中…" 文字。
|
||||
|
||||
**ZXShimmerList**(`Shared/Components/ZXLoadingView.swift`)
|
||||
骨架屏列表,传入 `count` 生成占位卡片。
|
||||
|
||||
**ZXErrorView**(`Shared/Components/ZXErrorView.swift`)
|
||||
全屏错误状态,黄色三角图标 + 消息 + 可选重试按钮。
|
||||
|
||||
**ZXErrorBanner**(`Shared/Components/ZXErrorView.swift`)
|
||||
内联错误横幅,黄色背景 + 消息 + 关闭按钮。
|
||||
|
||||
**ZXEmptyView**(`Shared/Components/ZXEmptyView.swift`)
|
||||
空状态视图,支持图标 + 标题 + 副标题 + 可选操作按钮。
|
||||
|
||||
### 7.9 其他
|
||||
|
||||
**FeatureRow**(`Shared/Components/FeatureRow.swift`)
|
||||
Welcome 页功能介绍行。
|
||||
|
||||
---
|
||||
|
||||
## 八、页面布局模式
|
||||
|
||||
### 8.1 主 Tab 页(有底部 TabBar)
|
||||
|
||||
```swift
|
||||
struct SomeHomeView: View {
|
||||
var body: some View {
|
||||
ZStack {
|
||||
ZXGradient.page.ignoresSafeArea() // ① 背景
|
||||
|
||||
VStack(spacing: 0) {
|
||||
// ② Header
|
||||
HStack {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("副标题").font(.system(size: 12)).foregroundColor(.zxF04)
|
||||
Text("主标题").font(.system(size: 22, weight: .heavy))
|
||||
.foregroundColor(.zxF0).tracking(-0.5)
|
||||
}
|
||||
Spacer()
|
||||
// 右侧按钮/状态
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.top, ZXSpacing.statusBarH + 16)
|
||||
.padding(.bottom, 12)
|
||||
|
||||
// ③ 可滚动内容
|
||||
ScrollView {
|
||||
VStack(spacing: 16) {
|
||||
// 卡片/列表...
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.bottom, 120) // 为 TabBar 留空间
|
||||
}
|
||||
.scrollIndicators(.hidden)
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
.preferredColorScheme(.dark)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.2 子页面(有返回按钮,无 TabBar)
|
||||
|
||||
```swift
|
||||
struct SomeDetailPage: View {
|
||||
var body: some View {
|
||||
ZStack {
|
||||
Color.zxBg0.ignoresSafeArea() // 纯色(非渐变)
|
||||
|
||||
VStack(spacing: 0) {
|
||||
ZXBackHeader(title: "标题", subtitle: "副标题") {
|
||||
// 右侧按钮
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
VStack(spacing: 16) {
|
||||
// 内容
|
||||
}
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.bottom, 80)
|
||||
}
|
||||
.scrollIndicators(.hidden)
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8.3 卡片通用写法
|
||||
|
||||
```swift
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
// 卡片内容
|
||||
}
|
||||
.padding(16)
|
||||
.background(Color.zxFill003) // 底色
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 16)
|
||||
.stroke(Color.zxBorder006, lineWidth: 1) // 边框
|
||||
)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16)) // 裁剪
|
||||
```
|
||||
|
||||
渐变背景卡片把 `.background(Color.zxFill003)` 换成对应的 `ZXGradient.xxx`。
|
||||
|
||||
### 8.4 输入框通用写法
|
||||
|
||||
```swift
|
||||
TextField("占位文字", text: $text)
|
||||
.font(.system(size: 14))
|
||||
.tint(.zxPurple)
|
||||
.padding(.horizontal, 16)
|
||||
.frame(height: 52)
|
||||
.background(Color.zxFill004)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 14))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 14)
|
||||
.stroke(Color.zxBorder008, lineWidth: 1)
|
||||
)
|
||||
```
|
||||
|
||||
### 8.5 状态标签(Capsule 形)
|
||||
|
||||
```swift
|
||||
Text("标签文字")
|
||||
.font(.system(size: 10, weight: .semibold))
|
||||
.foregroundColor(semanticColor)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 2)
|
||||
.background(semanticColor.opacity(0.12))
|
||||
.clipShape(Capsule())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 九、设计决策与约束
|
||||
|
||||
### 9.1 全局
|
||||
|
||||
- 强制深色模式:`.preferredColorScheme(.dark)`
|
||||
- 所有页面 `navigationBarHidden(true)`,使用自建导航
|
||||
- 禁止使用系统默认蓝色、默认圆角、默认间距
|
||||
|
||||
### 9.2 颜色
|
||||
|
||||
- 文字统一用 `#F0F0FF` 加透明度,不要用 `Color.white`
|
||||
- 不要直接写 `Color(hex: ...)` 内联,优先用现有 token;确需新色值先加 token
|
||||
- 语义色不要混用——紫色是品牌/AI,橙色是热度/连续,绿色是完成,黄色是警告
|
||||
|
||||
### 9.3 字体
|
||||
|
||||
- 不使用系统默认字体大小(如 `.title`、`.headline`),一律显式 `.system(size:weight:)`
|
||||
- 标题统一 tracking 负值(`-0.5` 或 `-0.4`)
|
||||
- 中文内容避免使用 `.bold` 以下的极细字体
|
||||
|
||||
### 9.4 布局
|
||||
|
||||
- 页面水平留白统一 `20pt`
|
||||
- 卡片间距 `12–20pt`
|
||||
- 内容区底部留白至少 `80pt`(子页面)或 `120pt`(有 TabBar)
|
||||
- 所有 ScrollView 隐藏指示器:`.scrollIndicators(.hidden)`
|
||||
|
||||
### 9.5 组件
|
||||
|
||||
- 优先复用第七节的共享组件,不要内联重复 UI
|
||||
- 新组件如通用性足够,应抽到 `Shared/` 目录
|
||||
|
||||
---
|
||||
|
||||
## 十、文件引用索引
|
||||
|
||||
| 规范项 | 定义文件 |
|
||||
|---|---|
|
||||
| 颜色/渐变/圆角/间距/尺寸/字体 | `Core/DesignSystem/DesignTokens.swift` |
|
||||
| ZXTabBar | `Shared/Components/ZXTabBar.swift` |
|
||||
| ZXIconBtn | `Shared/Components/ZXIconBtn.swift` |
|
||||
| ZXScoreBox | `Shared/Components/ZXScoreBox.swift` |
|
||||
| ZXAIInputBar | `Shared/Components/ZXAIInputBar.swift` |
|
||||
| ZXBackHeader | `Shared/Components/ZXBackHeader.swift` |
|
||||
| ZXOutlineBtn | `Shared/Components/ZXOutlineBtn.swift` |
|
||||
| ZXQuickAction | `Shared/Components/ZXQuickAction.swift` |
|
||||
| ZXAIInteractionRow | `Shared/Components/ZXAIInteractionRow.swift` |
|
||||
| ZXCardRow | `Shared/Components/ZXCardRow.swift` |
|
||||
| ZXChip | `Shared/Components/ZXChip.swift` |
|
||||
| ZXImportOption | `Shared/Components/ZXImportOption.swift` |
|
||||
| ZXWeakRow | `Shared/Components/ZXWeakRow.swift` |
|
||||
| ZXStatBadge | `Shared/Components/ZXStatBadge.swift` |
|
||||
| ZXProfileMenuRow | `Shared/Components/ZXProfileMenuRow.swift` |
|
||||
| ZXProfileStat | `Shared/Components/ZXProfileStat.swift` |
|
||||
| ZXAchievementBadge | `Shared/Components/ZXAchievementBadge.swift` |
|
||||
| ZXChartView | `Shared/Components/ZXChartView.swift` |
|
||||
| ZXSTaskRow + ZXSTask | `Shared/Components/ZXSTaskRow.swift` |
|
||||
| FeatureRow | `Shared/Components/FeatureRow.swift` |
|
||||
| ReviewTaskRow | `Shared/Components/ReviewTaskRow.swift` |
|
||||
| ZXLoadingView / ZXShimmerList | `Shared/Components/ZXLoadingView.swift` |
|
||||
| ZXErrorView / ZXErrorBanner | `Shared/Components/ZXErrorView.swift` |
|
||||
| ZXEmptyView | `Shared/Components/ZXEmptyView.swift` |
|
||||
| ZXLibraryCard | `Features/Library/LibraryHomeView.swift` |
|
||||
| AIHomeView | `Features/AI/AIHomeView.swift` |
|
||||
| DailyThinkingPage | `Features/AI/DailyThinkingPage.swift` |
|
||||
| RecallTestPage | `Features/AI/RecallTestPage.swift` |
|
||||
| WeakPointsPage | `Features/AI/WeakPointsPage.swift` |
|
||||
| AIFeedbackPageView | `Features/AI/AIFeedbackPage.swift` |
|
||||
| AIChatPage | `Features/AI/AIChatPage.swift` |
|
||||
| LibraryHomeView | `Features/Library/LibraryHomeView.swift` |
|
||||
| CreateLibraryPage | `Features/Library/CreateLibraryPage.swift` |
|
||||
| LibraryDetailPage | `Features/Library/LibraryDetailPage.swift` |
|
||||
| AddKnowledgePage | `Features/Library/AddKnowledgePage.swift` |
|
||||
| KnowledgeDetailPage | `Features/Library/KnowledgeDetailPage.swift` |
|
||||
| ImportPage | `Features/Library/ImportPage.swift` |
|
||||
| EditKnowledgePage | `Features/Library/EditKnowledgePage.swift` |
|
||||
| AnalysisHomeView | `Features/Analysis/AnalysisHomeView.swift` |
|
||||
| ProfileView | `Features/Profile/ProfileView.swift` |
|
||||
| ReviewPlanView | `Features/Review/ReviewPlanView.swift` |
|
||||
| StudyHomeView | `Features/Study/StudyHomeView.swift` |
|
||||
| SplashPage | `Features/Onboarding/SplashPage.swift` |
|
||||
| WelcomePage | `Features/Onboarding/WelcomePage.swift` |
|
||||
| OnboardingPage | `Features/Onboarding/OnboardingPage.swift` |
|
||||
| GoalSetupPage | `Features/Onboarding/GoalSetupPage.swift` |
|
||||
| AppRootView / OnboardingFlowView | `AIStudyAppApp.swift` |
|
||||
| LoginView | `Features/Auth/Views/LoginView.swift` |
|
||||
235
技术设计/ios-projects/已完成/[已完成]-页面规划.md
Normal file
235
技术设计/ios-projects/已完成/[已完成]-页面规划.md
Normal file
@ -0,0 +1,235 @@
|
||||
# 知习 ZhiXi — 页面清单与功能说明
|
||||
|
||||
> 更新时间:2026-05-10
|
||||
|
||||
## 项目概述
|
||||
|
||||
**知习 (ZhiXi)** 是一个 AI-first 系统化学习 iOS App,使用 SwiftUI 构建,深色主题。当前已完成 22 个页面的 UI 层实现,覆盖从引导流程到主界面 5 个 Tab 的完整交互链路。
|
||||
|
||||
---
|
||||
|
||||
## 一、引导流程(5 页)
|
||||
|
||||
所有引导页面定义在 `AIStudyAppApp.swift` 的 `OnboardingFlowView` 中,通过 `@AppStorage("hasCompletedOnboarding")` 控制显示。
|
||||
|
||||
### 1. SplashPage — 启动页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 0
|
||||
- **功能**:展示品牌 Logo、App 名称"知习"、副标题"AI-first 系统化学习",底部显示加载进度条,2 秒后自动跳转 Welcome
|
||||
- **视觉**:深色渐变背景 + 紫色/橙色光晕 + 品牌渐变图标
|
||||
|
||||
### 2. WelcomePage — 欢迎页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 1
|
||||
- **功能**:展示产品三大核心功能(主动回忆、费曼解释、AI 分析);提供"开始使用"和"已有账号?立即登录"两个入口
|
||||
- **UI 组件**:`FeatureRow`(emoji + 标题 + 描述卡片)
|
||||
|
||||
### 3. LoginPage — 登录页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 2
|
||||
- **功能**:支持手机号(+86)和邮箱两种登录方式切换;密码输入可切换明文/密文;底部提供微信登录和 Apple 登录入口;包含"忘记密码"链接
|
||||
- **UI 组件**:`ZXInputField`、`SocialLoginBtn`
|
||||
|
||||
### 4. OnboardingPage — 功能引导页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 3
|
||||
- **功能**:4 步滑动引导(输入知识 → 主动输出 → AI 分析 → 掌握知识),底部进度指示器,支持跳过
|
||||
- **UI 组件**:步进圆点指示器
|
||||
|
||||
### 5. GoalSetupPage — 学习目标设置页
|
||||
|
||||
- **路由**:`OnboardingFlowView` step 4
|
||||
- **功能**:设置学习目标(备考考试/职业技能/通识学习/自定义)、选择学习方法(间隔回忆/费曼技巧/AI 分析)、选择每日学习时间(15 分钟 ~ 不限制)
|
||||
- **UI 组件**:目标选项卡片(emoji + 标题 + 描述 + 单选圆点)、方法标签组、时间选择组
|
||||
|
||||
---
|
||||
|
||||
## 二、主界面 — 5 Tab 结构
|
||||
|
||||
`ContentView.swift` 实现底部 5 个 Tab 的导航:AI、知识库、学习、分析、我的。
|
||||
|
||||
### Tab 栏组件
|
||||
|
||||
- **ZXTabBar**:自定义底部 TabBar,包含选中态光晕动画、品牌紫色高亮
|
||||
- **ZXAIInputBar**:复用的 AI 输入栏(sparkles 图标 + 输入框 + 麦克风 + 发送按钮)
|
||||
- **ZXIconBtn**:通用图标按钮(支持 branded 紫色渐变样式)
|
||||
- **ZXScoreBox**:评分展示组件(分数 + 背景色 + 前景色,根据分数区间变色)
|
||||
|
||||
---
|
||||
|
||||
### Tab 1:AI 助手 — AIHomeView
|
||||
|
||||
- **文件**:`Features/AI/AIHomeView.swift`
|
||||
- **功能**:
|
||||
- 今日思考题卡片(展示 AI 生成的思考题,点击进入回答)
|
||||
- 快捷操作区(生成回忆测试、分析薄弱点、费曼解释练习、今日复习计划)
|
||||
- 最近 AI 互动列表(费曼复习、薄弱点分析、回忆测试记录,含评分)
|
||||
- AI 提问建议区(预设问题模板,点击可发送)
|
||||
- 底部 AI 输入栏
|
||||
- **子页面**:
|
||||
- `DailyThinkingPage` — 今日思考详情(见下方)
|
||||
- `RecallTestPage` — 回忆测试
|
||||
- `WeakPointsPage` — 薄弱点分析
|
||||
- `AIChatPage` — AI 对话
|
||||
- **UI 组件**:`ZXQuickAction`(emoji + 标签)、`ZXAIInteractionRow`(标签 + 标题 + 时间 + 评分)
|
||||
|
||||
#### AI 子页面(定义在 `Features/AI/DailyThinkingPage.swift`)
|
||||
|
||||
| 页面 | 功能 |
|
||||
|------|------|
|
||||
| **DailyThinkingPage** | 展示思考题 + 文本输入框,用户写下回答后提交给 AI 评估 |
|
||||
| **AIChatPage** | AI 对话页面,围绕当前知识库进行学习问答 |
|
||||
| **RecallTestPage** | 回忆测试:展示题目,用户回忆并写下理解,提交验证 |
|
||||
| **WeakPointsPage** | 薄弱知识点列表,每个知识点显示掌握分数、所属知识库、优先级 |
|
||||
| **AIFeedbackPage** | AI 反馈页,展示 AI 对用户回答的评分、优缺点分析、改进建议 |
|
||||
|
||||
**共享 UI 组件**:`ZXBackHeader` — 带返回按钮、标题、副标题、右侧操作区的通用导航头
|
||||
|
||||
---
|
||||
|
||||
### Tab 2:知识库 — LibraryHomeView
|
||||
|
||||
- **文件**:`Features/Library/LibraryHomeView.swift`
|
||||
- **功能**:
|
||||
- 知识库列表(机器学习、高等数学、英语词汇、产品设计等),每个卡片展示 emoji、名称、描述、知识点数量、掌握度百分比、标签、最近学习时间
|
||||
- 顶部搜索栏
|
||||
- 右上角搜索和创建按钮
|
||||
- 创建新知识库入口(虚线边框卡片)
|
||||
- **UI 组件**:`ZLibraryCard`(emoji + 名称 + 描述 + 进度条 + 标签 + 统计)
|
||||
|
||||
#### 知识库子页面(定义在 `Features/Library/LibrarySubpages.swift`)
|
||||
|
||||
| 页面 | 功能 |
|
||||
|------|------|
|
||||
| **CreateLibraryPage** | 创建新知识库:填写名称、描述 |
|
||||
| **LibraryDetailPage** | 知识库详情:展示该知识库下所有知识点列表,每个知识点显示标题、描述、掌握状态(已掌握/学习中/待复习) |
|
||||
| **AddKnowledgePage** | 添加知识点:填写标题、内容 |
|
||||
| **KnowledgeDetailPage** | 知识点详情:展示完整内容、标签、复习/费曼解释按钮 |
|
||||
| **ImportPage** | 导入资料 |
|
||||
| **EditKnowledgePage** | 编辑知识点 |
|
||||
|
||||
**知识库卡片组件**:`ZXCardRow` — emoji + 标题 + 描述 + 状态标签
|
||||
|
||||
---
|
||||
|
||||
### Tab 3:学习工作台 — StudyHomeView
|
||||
|
||||
- **文件**:`Features/Study/StudyHomeView.swift`
|
||||
- **功能**:
|
||||
- 日期和问候语("周四,1月16日")
|
||||
- 连续学习天数徽章(🔥)
|
||||
- 今日进度卡片:完成任务数/总任务数、进度百分比环形图、进度条、已学时间/剩余时间/掌握积分
|
||||
- 今日任务列表(机器学习回忆测试、高数间隔复习、英语词汇复习等),每个任务可勾选完成,显示任务类型标签和预计时长
|
||||
- 本周学习活跃柱状图(周一~周日,高亮当天)
|
||||
- 总计学习时长和日均统计
|
||||
- **数据模型**:`ZXSTask`(标题、类型、颜色、时长、完成状态)
|
||||
- **UI 组件**:`ZXSTaskRow`(勾选框 + 任务信息 + 类型标签 + 时长 + 播放按钮)
|
||||
|
||||
---
|
||||
|
||||
### Tab 4:学习分析 — AnalysisHomeView
|
||||
|
||||
- **文件**:`Features/Analysis/AnalysisHomeView.swift`
|
||||
- **功能**:
|
||||
- 顶部统计卡片行:综合掌握度(65%,+8%)、本周积分(1,240)、待巩固知识点数(23)、连续学习天数(14)
|
||||
- 掌握度趋势折线图(近 7 天数据)
|
||||
- 薄弱知识点列表(可导航至 WeakPointsPage)
|
||||
- AI 学习建议卡片
|
||||
- 知识库掌握分布(各知识库掌握度进度条)
|
||||
- **UI 组件**:`ZXStatBadge`(图标 + 标签 + 数值 + 变化趋势)、`ZXChartView`、`ZXWeakRow`
|
||||
|
||||
---
|
||||
|
||||
### Tab 5:我的 — ProfileView
|
||||
|
||||
- **文件**:`Features/Profile/ProfileView.swift`
|
||||
- **功能**:
|
||||
- 顶部导航栏(标题"我的" + 通知铃铛 + 设置齿轮)
|
||||
- 个人信息卡片:头像(emoji)、昵称"学习者"、邮箱、连续天数/知识点数/积分统计
|
||||
- 设置菜单:学习目标设置、复习提醒、学习报告、学习方法偏好、数据同步与备份
|
||||
- 成就展示区(连续 14 天、费曼达人、知识收藏家、速学者)
|
||||
- **UI 组件**:`ZXProfileStat`、`ZXProfileMenuRow`(emoji + 标题 + 描述 + 箭头)、`ZXAchievementBadge`
|
||||
|
||||
---
|
||||
|
||||
## 三、设计系统
|
||||
|
||||
文件:`Core/DesignSystem/DesignTokens.swift`
|
||||
|
||||
### 颜色系统
|
||||
| 类别 | Token | 值 |
|
||||
|------|-------|-----|
|
||||
| 主背景 | `Color.zxBg0` | `#0F0F1A` |
|
||||
| 品牌紫 | `Color.zxPurple` | `#7C6EFA` |
|
||||
| 品牌橙 | `Color.zxOrange` | `#F97316` |
|
||||
| 文字主色 | `Color.zxF0` | `#F0F0FF` |
|
||||
|
||||
### 渐变系统 (`ZXGradient`)
|
||||
- `page` — 页面背景渐变
|
||||
- `brand` — 品牌紫橙渐变
|
||||
- `brandPurple` — 紫色渐变
|
||||
- `thinkingCard` — 思考卡片渐变
|
||||
- `progressCard` — 进度卡片渐变
|
||||
- `feedbackScore` — 反馈评分渐变
|
||||
- `profileCard` — 个人信息卡片渐变
|
||||
- `ctaButton` / `ctaPurple` — CTA 按钮渐变
|
||||
|
||||
### 间距系统 (`ZXSpacing`)
|
||||
- `pageHPadding`: 20
|
||||
- `statusBarH`: 44
|
||||
- `tabBarH`: 83
|
||||
|
||||
### 尺寸系统 (`ZXSize`)
|
||||
- 图标按钮: 36, 头像: 36/64/80
|
||||
- 按钮高度: 42/52/56, 快捷操作: 72
|
||||
|
||||
### 排版系统 (`ZXFont`)
|
||||
- `titleLarge`: 22pt heavy, -0.5 tracking
|
||||
- `titleMedium`: 20pt heavy, -0.4 tracking
|
||||
- `sectionTitle`: 15pt bold
|
||||
- `body`: 13pt semibold
|
||||
- `bodySmall`: 12pt medium
|
||||
- `caption`: 10pt bold
|
||||
|
||||
---
|
||||
|
||||
## 四、页面状态总览
|
||||
|
||||
| # | 页面 | Tab | 文件 | 导航方式 | 状态 |
|
||||
|---|------|-----|------|----------|------|
|
||||
| 1 | Splash 启动页 | — | AIStudyAppApp.swift | 自动跳转 | ✅ |
|
||||
| 2 | Welcome 欢迎页 | — | AIStudyAppApp.swift | 按钮跳转 | ✅ |
|
||||
| 3 | Login 登录页 | — | AIStudyAppApp.swift | 按钮跳转 | ✅ |
|
||||
| 4 | Onboarding 引导 | — | AIStudyAppApp.swift | 步进/跳过 | ✅ |
|
||||
| 5 | GoalSetup 目标 | — | AIStudyAppApp.swift | 完成进入主界面 | ✅ |
|
||||
| 6 | AIHome AI 首页 | AI | AIHomeView.swift | Tab 1 | ✅ |
|
||||
| 7 | LibraryHome 知识库 | 知识库 | LibraryHomeView.swift | Tab 2 | ✅ |
|
||||
| 8 | StudyHome 学习 | 学习 | StudyHomeView.swift | Tab 3 | ✅ |
|
||||
| 9 | AnalysisHome 分析 | 分析 | AnalysisHomeView.swift | Tab 4 | ✅ |
|
||||
| 10 | Profile 我的 | 我的 | ProfileView.swift | Tab 5 | ✅ |
|
||||
| 11 | AIChat AI 对话 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 12 | DailyThinking 今日思考 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 13 | RecallTest 回忆测试 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 14 | WeakPoints 薄弱点 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 15 | AIFeedback AI 反馈 | AI | DailyThinkingPage.swift | NavigationLink | ✅ |
|
||||
| 16 | CreateLibrary 创建知识库 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 17 | LibraryDetail 知识库详情 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 18 | AddKnowledge 添加知识点 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 19 | Import 导入资料 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 20 | KnowledgeDetail 知识点详情 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
| 21 | EditKnowledge 编辑知识点 | 知识库 | LibrarySubpages.swift | NavigationLink | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 五、当前未实现的功能
|
||||
|
||||
以下为产品计划中但当前 iOS 项目尚未实现的能力:
|
||||
|
||||
- Sign in with Apple(UI 已做,实际认证逻辑未接入)
|
||||
- 后端 API 对接(当前为纯本地 UI)
|
||||
- 真实 AI 分析(当前为静态展示)
|
||||
- 数据持久化(无本地存储/云端同步)
|
||||
- 多语言本地化架构
|
||||
- Apple IAP 支付
|
||||
- 推送通知
|
||||
- 崩溃监控/数据埋点
|
||||
0
技术设计/miniapp-projects/.gitkeep
Normal file
0
技术设计/miniapp-projects/.gitkeep
Normal file
137
技术设计/web-projects/[设计中]-设计文档.md
Normal file
137
技术设计/web-projects/[设计中]-设计文档.md
Normal file
@ -0,0 +1,137 @@
|
||||
---
|
||||
name: Luminous Clarity
|
||||
colors:
|
||||
surface: '#faf9ff'
|
||||
surface-dim: '#d2daf1'
|
||||
surface-bright: '#faf9ff'
|
||||
surface-container-lowest: '#ffffff'
|
||||
surface-container-low: '#f1f3ff'
|
||||
surface-container: '#e9edff'
|
||||
surface-container-high: '#e1e8ff'
|
||||
surface-container-highest: '#dbe2fa'
|
||||
on-surface: '#131b2c'
|
||||
on-surface-variant: '#434654'
|
||||
inverse-surface: '#283042'
|
||||
inverse-on-surface: '#edf0ff'
|
||||
outline: '#737686'
|
||||
outline-variant: '#c3c5d7'
|
||||
surface-tint: '#1a53d6'
|
||||
primary: '#1550d3'
|
||||
on-primary: '#ffffff'
|
||||
primary-container: '#3c6bed'
|
||||
on-primary-container: '#fffbff'
|
||||
inverse-primary: '#b5c4ff'
|
||||
secondary: '#583dde'
|
||||
on-secondary: '#ffffff'
|
||||
secondary-container: '#715af8'
|
||||
on-secondary-container: '#fffbff'
|
||||
tertiary: '#595c60'
|
||||
on-tertiary: '#ffffff'
|
||||
tertiary-container: '#727578'
|
||||
on-tertiary-container: '#fcfcff'
|
||||
error: '#ba1a1a'
|
||||
on-error: '#ffffff'
|
||||
error-container: '#ffdad6'
|
||||
on-error-container: '#93000a'
|
||||
primary-fixed: '#dce1ff'
|
||||
primary-fixed-dim: '#b5c4ff'
|
||||
on-primary-fixed: '#00164d'
|
||||
on-primary-fixed-variant: '#003cad'
|
||||
secondary-fixed: '#e5deff'
|
||||
secondary-fixed-dim: '#c8bfff'
|
||||
on-secondary-fixed: '#190064'
|
||||
on-secondary-fixed-variant: '#421dc9'
|
||||
tertiary-fixed: '#e0e3e6'
|
||||
tertiary-fixed-dim: '#c4c7ca'
|
||||
on-tertiary-fixed: '#181c1f'
|
||||
on-tertiary-fixed-variant: '#44474a'
|
||||
background: '#faf9ff'
|
||||
on-background: '#131b2c'
|
||||
surface-variant: '#dbe2fa'
|
||||
typography:
|
||||
display-xl:
|
||||
fontFamily: Manrope
|
||||
fontSize: 64px
|
||||
fontWeight: '800'
|
||||
lineHeight: '1.1'
|
||||
letterSpacing: -0.02em
|
||||
headline-lg:
|
||||
fontFamily: Manrope
|
||||
fontSize: 40px
|
||||
fontWeight: '700'
|
||||
lineHeight: '1.2'
|
||||
letterSpacing: -0.01em
|
||||
headline-md:
|
||||
fontFamily: Manrope
|
||||
fontSize: 28px
|
||||
fontWeight: '600'
|
||||
lineHeight: '1.3'
|
||||
body-lg:
|
||||
fontFamily: Manrope
|
||||
fontSize: 18px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.6'
|
||||
body-base:
|
||||
fontFamily: Manrope
|
||||
fontSize: 16px
|
||||
fontWeight: '400'
|
||||
lineHeight: '1.6'
|
||||
label-sm:
|
||||
fontFamily: Inter
|
||||
fontSize: 13px
|
||||
fontWeight: '600'
|
||||
lineHeight: '1'
|
||||
letterSpacing: 0.05em
|
||||
rounded:
|
||||
sm: 0.25rem
|
||||
DEFAULT: 0.5rem
|
||||
md: 0.75rem
|
||||
lg: 1rem
|
||||
xl: 1.5rem
|
||||
full: 9999px
|
||||
spacing:
|
||||
unit: 8px
|
||||
container-max: 1200px
|
||||
gutter: 24px
|
||||
section-padding: 120px
|
||||
card-padding: 32px
|
||||
---
|
||||
|
||||
## Brand & Style
|
||||
The design system is anchored in the concept of "Intellectual Serenity." It aims to evoke the feeling of a focused, high-end study environment—quiet, organized, and filled with natural light. The target audience consists of lifelong learners and professionals who value structured knowledge over chaotic information.
|
||||
|
||||
The visual style is a fusion of **Apple-inspired Minimalism** and **Glassmorphism**. It prioritizes extreme legibility and breathability, using negative space not just as a gap, but as a structural element that reduces cognitive load. The aesthetic avoids the "aggressive" tropes of AI (heavy glows and dark modes) in favor of a "Calm Tech" approach that feels like a premium productivity tool rather than a futuristic novelty.
|
||||
|
||||
## Colors
|
||||
The color palette uses a "High-Key" approach. The primary **Calm Technology Blue** serves as the anchor for interactive elements, while the **Subtle Blue-Purple** accent is reserved for AI-assisted features and high-value highlights.
|
||||
|
||||
Backgrounds transition between pure white and a soft blue-white to define different content zones without needing heavy borders. Text utilizes a Deep Navy rather than pure black to maintain a softer, more premium contrast ratio that is easier on the eyes during long learning sessions.
|
||||
|
||||
## Typography
|
||||
This design system employs **Manrope** for its geometric yet warm characteristics, echoing the polished look of high-end consumer tech landing pages. For Chinese typesetting, pair this with a high-quality, weighted Sans-Serif (like PingFang SC) using optical kerning.
|
||||
|
||||
The hierarchy is dramatic; large display headings create an editorial feel, while body text maintains generous line-heights to ensure the "structured learning" content remains approachable and digestible.
|
||||
|
||||
## Layout & Spacing
|
||||
The layout follows a **Fixed Grid** philosophy for desktop (12 columns) to maintain the "launch page" precision, transitioning to a fluid model for mobile.
|
||||
|
||||
Spacing is intentionally oversized. Sections should be separated by significant vertical gaps (120px+) to allow the user's mind to reset between concepts. Within components, use a consistent 8px base grid. Content should be centered with wide margins, creating a "gallery" feel where every piece of information feels curated and important.
|
||||
|
||||
## Elevation & Depth
|
||||
Depth is created through **Glassmorphism** and **Ambient Shadows** rather than traditional layers.
|
||||
- **Surface Level 0:** The soft blue-white canvas (#F6F8FC).
|
||||
- **Surface Level 1 (Floating Cards):** Pure white background with a very soft, high-blur shadow (0px 20px 40px rgba(18, 26, 43, 0.04)).
|
||||
- **Surface Level 2 (Glass Overlays):** Semi-transparent white (rgba(255, 255, 255, 0.7)) with a 20px backdrop-blur and a subtle 1px white border.
|
||||
|
||||
Incorporate a subtle geometric dot-grid pattern in the background of Level 0 to provide a "blueprint" or "structured" feel to the learning environment.
|
||||
|
||||
## Shapes
|
||||
The shape language is strictly "iOS-style" squircle-adjacent. Use a base radius of 16px (1rem) for standard components and 24px-32px for large containers. This high level of roundedness removes "visual sharpness," reinforcing the calm and friendly nature of the AI assistant. Interactive elements like buttons should feel tactile and "pill-like" when small, or softly rectangular when large.
|
||||
|
||||
## Components
|
||||
- **Primary Buttons:** Use the accent gradient with white text. Apply a subtle lift effect (shadow increases) on hover.
|
||||
- **Glass Cards:** Used for "Learning Modules." Feature a 1px white inner stroke to catch the light, mimicking physical glass.
|
||||
- **AI Input Field:** A floating, pill-shaped bar with a soft inner shadow and a subtle blue-purple glow when focused, signaling "AI Activity."
|
||||
- **Progress Indicators:** Use thin, elegant lines with rounded caps. The "filled" state should use the primary blue.
|
||||
- **Micro-interactions:** Elements should fade and slide upward 10px when appearing, mimicking the smooth motion of a premium OS.
|
||||
- **Chips/Tags:** Small, semi-transparent blue fills with Deep Navy text, used for categorizing learning topics.
|
||||
0
技术设计/webApp-projects/.gitkeep
Normal file
0
技术设计/webApp-projects/.gitkeep
Normal file
@ -94,6 +94,6 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [阶段路线图](../0-阶段路线图/阶段路线图.md)
|
||||
- [技术与交付模块](../2-技术与交付模块/技术与交付模块.md)
|
||||
- [商业化与支付模块](../3-商业化与支付模块/商业化与支付模块.md)
|
||||
- [阶段路线图](../../开发计划/[进行中]-阶段路线图.md)
|
||||
- [技术与交付模块](./[参考]-技术与交付模块.md)
|
||||
- [商业化与支付模块](./[进行中]-商业化与支付模块.md)
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
## AI 架构
|
||||
|
||||
> 详见:[AI架构设计](./AI架构设计.md)
|
||||
> 详见:[AI架构设计](../../技术设计/api-server/[设计中]-AI架构设计.md)
|
||||
|
||||
核心原则:从"业务分级工作流"开始,暂不做完全自治 Agent。后期通过用户学习画像、长期记忆和受控 Skill 系统逐步演进。
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
|
||||
## 后端开发路线
|
||||
|
||||
> 详见:[后端开发优先级](./后端开发优先级.md) / [后端完全体优先级详案](./后端完全体优先级详案.md)
|
||||
> 详见:[后端开发优先级](../../开发计划/api-server/[进行中]-后端开发优先级.md)
|
||||
|
||||
核心开发顺序:**身份权限 → 知识系统 → 学习闭环 → AI 基础设施 → 文件导入 → 商业化 → 后台 → 客服 → 学习画像 → 公开分享 → 增长归因**
|
||||
|
||||
@ -71,8 +71,7 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [阶段路线图](../0-阶段路线图/阶段路线图.md)
|
||||
- [产品与用户模块](../1-产品与用户模块/产品与用户模块.md)
|
||||
- [AI架构设计](./AI架构设计.md)
|
||||
- [后端开发优先级](./后端开发优先级.md)
|
||||
- [后端完全体优先级详案](./后端完全体优先级详案.md)
|
||||
- [阶段路线图](../../开发计划/[进行中]-阶段路线图.md)
|
||||
- [产品与用户模块](./[参考]-产品与用户模块.md)
|
||||
- [AI架构设计](../../技术设计/api-server/[设计中]-AI架构设计.md)
|
||||
- [后端开发优先级](../../开发计划/api-server/[进行中]-后端开发优先级.md)
|
||||
@ -44,8 +44,8 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [阶段路线图](../0-阶段路线图/阶段路线图.md)
|
||||
- [商业化与支付模块](../3-商业化与支付模块/商业化与支付模块.md)
|
||||
- [阶段路线图](../../开发计划/[进行中]-阶段路线图.md)
|
||||
- [商业化与支付模块](./[进行中]-商业化与支付模块.md)
|
||||
|
||||
## 负责人
|
||||
|
||||
@ -42,8 +42,8 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [阶段路线图](../0-阶段路线图/阶段路线图.md)
|
||||
- [运营与客服模块](../5-运营与客服模块/运营与客服模块.md)
|
||||
- [阶段路线图](../../开发计划/[进行中]-阶段路线图.md)
|
||||
- [运营与客服模块](./运营与客服/[进行中]-运营与客服模块.md)
|
||||
|
||||
## 负责人
|
||||
|
||||
@ -62,7 +62,7 @@
|
||||
| 7 | iPad / Mac 扩展 | 🔲 |
|
||||
| 8 | 公司化与安卓扩展 | 🔲 |
|
||||
|
||||
> 详见:[阶段路线图](./0-阶段路线图/阶段路线图.md)
|
||||
> 详见:[阶段路线图](../开发计划/[进行中]-阶段路线图.md)
|
||||
|
||||
---
|
||||
|
||||
@ -76,7 +76,7 @@
|
||||
| 数据库 | MySQL + Redis 已部署 | 代码未走 Prisma |
|
||||
| 方向验证 | 3 个候选方向 | 未打分选定,未准备知识库内容 |
|
||||
|
||||
> 详见:[潜在问题清单](../潜在问题清单.md)
|
||||
> 详见:[潜在问题清单](../开发计划/[进行中]-潜在问题清单.md)
|
||||
|
||||
---
|
||||
|
||||
@ -84,13 +84,13 @@
|
||||
|
||||
| 模块 | 主文档 | 子文档 |
|
||||
|------|--------|--------|
|
||||
| 1. 产品与用户 | [产品与用户模块](./1-产品与用户模块/产品与用户模块.md) | [产品方向深度评估](./1-产品与用户模块/产品方向深度评估.md) |
|
||||
| 2. 技术与交付 | [技术与交付模块](./2-技术与交付模块/技术与交付模块.md) | [AI架构设计](./2-技术与交付模块/AI架构设计.md) / [后端开发优先级](./2-技术与交付模块/后端开发优先级.md) |
|
||||
| 3. 商业化与支付 | [商业化与支付模块](./3-商业化与支付模块/商业化与支付模块.md) | — |
|
||||
| 4. 营销与增长 | [营销与增长模块](./4-营销与增长模块/营销与增长模块.md) | [营销冷启动调研方案](./4-营销与增长模块/营销冷启动调研方案.md) / [冷启动与增长深度调研](./4-营销与增长模块/冷启动与增长深度调研.md) |
|
||||
| 5. 运营与客服 | [运营与客服模块](./5-运营与客服模块/运营与客服模块.md) | [客服设计详案](./5-运营与客服模块/客服设计详案.md) |
|
||||
| 6. 数据反馈与迭代 | [数据反馈与迭代模块](./6-数据反馈与迭代模块/数据反馈与迭代模块.md) | — |
|
||||
| 7. 合规与公司化 | [合规与公司化模块](./7-合规与公司化模块/合规与公司化模块.md) | — |
|
||||
| 1. 产品与用户 | [产品与用户模块](./[参考]-产品与用户模块.md) | [产品方向深度评估](./[参考]-产品方向深度评估.md) |
|
||||
| 2. 技术与交付 | [技术与交付模块](./[参考]-技术与交付模块.md) | [AI架构设计](../技术设计/api-server/[设计中]-AI架构设计.md) / [后端开发优先级](../开发计划/api-server/[进行中]-后端开发优先级.md) |
|
||||
| 3. 商业化与支付 | [商业化与支付模块](./[进行中]-商业化与支付模块.md) | — |
|
||||
| 4. 营销与增长 | [营销与增长模块](./营销与增长/[进行中]-营销与增长模块.md) | [营销冷启动调研方案](./营销与增长/[参考]-营销冷启动调研方案.md) / [冷启动与增长深度调研](./营销与增长/[参考]-冷启动与增长深度调研.md) |
|
||||
| 5. 运营与客服 | [运营与客服模块](./运营与客服/[进行中]-运营与客服模块.md) | [客服设计详案](./运营与客服/[参考]-客服设计详案.md) |
|
||||
| 6. 数据反馈与迭代 | [数据反馈与迭代模块](./[设计中]-数据反馈与迭代模块.md) | — |
|
||||
| 7. 合规与公司化 | [合规与公司化模块](./[设计中]-合规与公司化模块.md) | — |
|
||||
|
||||
---
|
||||
|
||||
@ -85,5 +85,5 @@
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [阶段路线图](../0-阶段路线图/阶段路线图.md)
|
||||
- [合规与公司化模块](../7-合规与公司化模块/合规与公司化模块.md)
|
||||
- [阶段路线图](../../开发计划/[进行中]-阶段路线图.md)
|
||||
- [合规与公司化模块](./[设计中]-合规与公司化模块.md)
|
||||
@ -77,5 +77,5 @@ AI 生成内容草稿 → 人审核修改 → 人手动发布 → AI 辅助分
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [阶段路线图](../0-阶段路线图/阶段路线图.md)
|
||||
- [营销冷启动调研方案](./营销冷启动调研方案.md)
|
||||
- [阶段路线图](../../../开发计划/[进行中]-阶段路线图.md)
|
||||
- [营销冷启动调研方案](./[参考]-营销冷启动调研方案.md)
|
||||
@ -86,6 +86,6 @@ iOS App → NestJS 后端 → Dify API → Dify 知识库
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [阶段路线图](../0-阶段路线图/阶段路线图.md)
|
||||
- [数据反馈与迭代模块](../6-数据反馈与迭代模块/数据反馈与迭代模块.md)
|
||||
- [客服设计详案](./客服设计详案.md)
|
||||
- [阶段路线图](../../../开发计划/[进行中]-阶段路线图.md)
|
||||
- [数据反馈与迭代模块](../[设计中]-数据反馈与迭代模块.md)
|
||||
- [客服设计详案](./[参考]-客服设计详案.md)
|
||||
@ -1,79 +0,0 @@
|
||||
# 后端开发优先级
|
||||
|
||||
> 知习后端完整模块清单(51 个模块,14 个层级)及分 8 阶段开发路线图。
|
||||
> 详案见:[后端完全体优先级详案](./后端完全体优先级详案.md)
|
||||
|
||||
---
|
||||
|
||||
## 总优先级总表
|
||||
|
||||
| 优先级 | 层级 | 核心模块 |
|
||||
|--------|------|----------|
|
||||
| P0 | 后端地基 | 安全配置、数据库(Prisma+MySQL)、统一工程规范(响应/错误/DTO/Guard) |
|
||||
| P1 | 身份权限 | Auth(Apple/Refresh/Logout)、Users、Role、Resource Permission |
|
||||
| P2 | 知识系统 | KnowledgeBase、KnowledgeItem、Tag、Search |
|
||||
| P3 | 学习闭环 | LearningSession、ActiveRecall、AIAnalysis、FocusItem、Review、LearningActivity |
|
||||
| P4 | AI 基础设施 | AIGateway、PromptTemplate、AIUsageLog、AIQuota、AIWorkflow |
|
||||
| P5 | 文件导入 | File/Storage、DocumentImport、KnowledgeGeneration |
|
||||
| P6 | 商业化 | Plans、Membership、Subscription(Apple IAP)、Payment、Refund |
|
||||
| P7 | 用户 Web 后台 | Web Console、批量上传/导入/导出 |
|
||||
| P8 | 管理员后台 | Admin Users、Admin Knowledge、AI Cost、Feedback、Audit Log |
|
||||
| P9 | 客服反馈 | Feedback、SupportTicket、Dify 智能客服、HelpCenter |
|
||||
| P10 | 通知任务 | Notifications、Push(APNs)、BullMQ Worker、Scheduler |
|
||||
| P11 | 学习画像 | LearningAnalytics、UserLearningProfile、LearningReport |
|
||||
| P12 | 公开分享 | Visibility、ShareLink、Public Knowledge |
|
||||
| P13 | 合规配置 | SystemConfig、Privacy、Delete Account、Data Export |
|
||||
| P14 | 增长归因 | Attribution、ProductAnalytics、Campaign Tracking |
|
||||
|
||||
---
|
||||
|
||||
## 8 阶段开发路线
|
||||
|
||||
### 第一阶段:能真实使用
|
||||
安全、数据库、登录、用户、权限、知识库、知识点
|
||||
> 目标:用户可以登录并创建自己的知识库。
|
||||
|
||||
### 第二阶段:形成学习闭环
|
||||
学习会话、主动回忆、AI 分析、待巩固项、复习卡片、学习活跃、AI Usage Log
|
||||
> 目标:从输入知识走到主动输出、AI 反馈、复习。
|
||||
|
||||
### 第三阶段:支持真实内容导入
|
||||
文件上传、文档导入、AI 切分知识点、导入队列、Worker
|
||||
> 目标:用户可以上传资料并转成知识库。
|
||||
|
||||
### 第四阶段:商业化
|
||||
会员权益、AI 额度、套餐、Apple IAP、订阅通知、退款处理
|
||||
> 目标:用户可以付费,系统可以控制成本。
|
||||
|
||||
### 第五阶段:运营后台
|
||||
管理员后台、用户管理、知识库元数据、反馈管理、AI 成本看板、审计日志
|
||||
> 目标:可以运营这个产品。
|
||||
|
||||
### 第六阶段:客服和支持
|
||||
反馈、工单、Dify 智能客服、帮助中心
|
||||
> 目标:基础问题自动回答,复杂问题进工单。
|
||||
|
||||
### 第七阶段:学习画像和 Agent
|
||||
用户学习画像、长期趋势、周报月报、AI 工作流、Learning Agent
|
||||
> 目标:系统开始越来越懂用户。
|
||||
|
||||
### 第八阶段:公开知识库和社区
|
||||
公开知识库、分享链接、官方模板库、举报审核
|
||||
> 目标:从个人学习工具扩展到内容和社区。
|
||||
|
||||
---
|
||||
|
||||
## 最终形态
|
||||
|
||||
```
|
||||
用户系统 + 权限系统 + 知识库系统 + 学习闭环系统 + AI 工作流系统
|
||||
+ 复习系统 + 成本控制系统 + 订阅系统 + 文件导入系统
|
||||
+ 后台管理系统 + 客服工单系统 + 学习画像系统 + 合规系统 + 增长归因系统
|
||||
```
|
||||
|
||||
核心开发顺序:**身份权限 → 知识系统 → 学习闭环 → AI 基础设施 → 文件导入 → 商业化 → 后台 → 客服 → 学习画像 → 公开分享 → 增长归因**
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [技术与交付模块](./技术与交付模块.md)
|
||||
- [后端完全体优先级详案](./后端完全体优先级详案.md)
|
||||
Loading…
x
Reference in New Issue
Block a user