e3f4af9c0c
- 总体架构:新增打印/图像预处理/双飞轮/三环境部署 - 技术选型:调整决策理由(Coze沙盒自动化测试),新增Sharp+PDFKit - 数据模型:新增code/role/question_type+print_tasks+audit_logs,ID+code并存 - 模块设计:新增Image/Print模块,推荐两阶段匹配(关键词粗筛→AI精排) - PRD:目标用户扩展为学生+家长,新增PDF打印,年级聚焦小初,图像预处理流程 - ADR-010:题库抽象层Adapter Pattern Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
404 lines
14 KiB
Markdown
404 lines
14 KiB
Markdown
# 模块设计
|
||
|
||
> 版本: v0.4.0 | 作者: Arch AI | 基于 PRD v0.4.0 + 旧架构合并
|
||
|
||
---
|
||
|
||
## 1. 模块总览
|
||
|
||
```
|
||
ErrLens
|
||
├── P01_errlens_app (小程序 + 后端)
|
||
│ ├── 小程序端 (Taro + React)
|
||
│ │ ├── pages/auth # 登录/注册
|
||
│ │ ├── pages/home # 首页(错题概览)
|
||
│ │ ├── pages/capture # 拍照录入
|
||
│ │ ├── pages/error-detail # 错题详情+分析
|
||
│ │ ├── pages/error-list # 错题列表
|
||
│ │ ├── pages/weak-points # 薄弱点分析
|
||
│ │ ├── pages/practice # 练习推荐 (P1)
|
||
│ │ ├── pages/print # PDF 输出 (P0)
|
||
│ │ └── pages/profile # 个人中心
|
||
│ │
|
||
│ └── 后端 (NestJS)
|
||
│ ├── modules/auth # 鉴权模块
|
||
│ ├── modules/user # 用户模块(含邀请链)
|
||
│ ├── modules/invitation # 邀请模块
|
||
│ ├── modules/error-item # 错题模块
|
||
│ ├── modules/ai # AI 分析模块
|
||
│ ├── modules/image # 图像预处理模块
|
||
│ ├── modules/subject # 学科模块
|
||
│ ├── modules/question-bank # 题库模块
|
||
│ ├── modules/recommend # 推荐模块 (P1)
|
||
│ ├── modules/print # 打印/PDF 输出模块 (P0)
|
||
│ └── modules/upload # 文件上传
|
||
│
|
||
├── P02_errlens_training (Phase 3)
|
||
│ └── AI 模型训练管线
|
||
│
|
||
└── P03_errlens_web (Phase 3)
|
||
└── Web 管理后台
|
||
```
|
||
|
||
## 2. 小程序页面路由
|
||
|
||
| 路由 | 页面 | 说明 | MVP |
|
||
|------|------|------|-----|
|
||
| `/pages/index/index` | 首页 | 错题统计概览 + 快捷入口 | ✅ |
|
||
| `/pages/auth/login` | 登录 | 微信授权登录 | ✅ |
|
||
| `/pages/capture/index` | 拍照录入 | 拍照 → AI 识别 → 确认 | ✅ |
|
||
| `/pages/error-list/index` | 错题列表 | 筛选 + 搜索 | ✅ |
|
||
| `/pages/error-detail/index` | 错题详情 | 题目 + AI 分析 | ✅ |
|
||
| `/pages/weak-points/index` | 薄弱点 | 知识点薄弱项汇总 | ✅ |
|
||
| `/pages/practice/index` | 练习推荐 | 智能组题 | P1 |
|
||
| `/pages/practice/result` | 练习结果 | 对错反馈 | P1 |
|
||
| `/pages/print/index` | 错题选择 | 选题→生成 PDF | ✅ |
|
||
| `/pages/print/preview` | 打印预览 | PDF 预览+下载 | ✅ |
|
||
| `/pages/profile/index` | 个人中心 | 资料 + 设置 | ✅ |
|
||
|
||
## 3. 后端模块设计
|
||
|
||
### 3.1 Auth 模块
|
||
|
||
```
|
||
modules/auth/
|
||
├── auth.module.ts
|
||
├── auth.controller.ts # POST /auth/login (微信 code → JWT)
|
||
├── auth.service.ts # 微信 code2session + JWT 签发
|
||
├── auth.guard.ts # JWT 鉴权守卫
|
||
└── dto/
|
||
└── login.dto.ts
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /auth/login | 微信 code 换取 JWT token |
|
||
| POST | /auth/refresh | 刷新 token |
|
||
|
||
### 3.2 User 模块
|
||
|
||
```
|
||
modules/user/
|
||
├── user.module.ts
|
||
├── user.controller.ts # GET/PATCH /user/profile
|
||
├── user.service.ts
|
||
├── user.entity.ts # Drizzle schema
|
||
└── dto/
|
||
└── update-profile.dto.ts
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | /user/profile | 获取个人信息 |
|
||
| PATCH | /user/profile | 更新年级、学科 |
|
||
| GET | /user/invitation-code | 获取个人邀请码和二维码 |
|
||
| GET | /user/tree | 获取邀请树(直接下级列表) |
|
||
|
||
### 3.3 Invitation 模块
|
||
|
||
```
|
||
modules/invitation/
|
||
├── invitation.module.ts
|
||
├── invitation.controller.ts # POST /invitation/register
|
||
├── invitation.service.ts # 邀请码生成 + 邀请链管理
|
||
├── user-relation.entity.ts # Drizzle schema
|
||
└── dto/
|
||
├── register-by-invite.dto.ts
|
||
└── tree-query.dto.ts
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /invitation/register | 通过邀请码注册(携带 inviter_code) |
|
||
| GET | /invitation/tree | 获取当前用户的邀请树(一级+递归) |
|
||
| GET | /invitation/tree/:userId | 获取指定用户的邀请统计(子节点数、活跃用户数) |
|
||
|
||
**邀请码生成规则**:
|
||
- 用户注册时自动生成 6 位字母数字邀请码
|
||
- 格式: `[A-Z0-9]{6}`,排除易混淆字符 (0/O, 1/I/L)
|
||
- 唯一约束,冲突时重试生成
|
||
|
||
**注册流程**:
|
||
```
|
||
1. 老用户 A 分享小程序 → 携带邀请码参数 (pages/auth/login?invite=ABC123)
|
||
2. 新用户 B 打开 → 微信授权登录
|
||
3. 后端创建 B 用户 → 生成 B 的邀请码
|
||
4. 创建 user_relation (inviter=A, invitee=B)
|
||
5. B 进入首页 → 关系建立完成
|
||
```
|
||
|
||
### 3.4 ErrorItem 模块(核心)
|
||
|
||
```
|
||
modules/error-item/
|
||
├── error-item.module.ts
|
||
├── error-item.controller.ts # CRUD /error-items
|
||
├── error-item.service.ts # 错题业务逻辑 + 校验状态管理
|
||
├── error-item.entity.ts # Drizzle schema
|
||
├── correction-log.service.ts # 修正记录管理
|
||
└── dto/
|
||
├── create-error.dto.ts
|
||
├── update-error.dto.ts
|
||
├── query-error.dto.ts # 筛选参数(含 verification_status)
|
||
└── batch-confirm.dto.ts # 批量确认
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /error-items | 创建错题(AI 识别结果,状态=raw) |
|
||
| GET | /error-items | 列表查询(分页+筛选,含 verification_status 筛选) |
|
||
| GET | /error-items/:id | 错题详情(含 AI 分析 + 置信度) |
|
||
| PATCH | /error-items/:id | 修正错题信息(字段修正时记录 CorrectionLog) |
|
||
| POST | /error-items/batch-confirm | 批量确认(raw → reviewed) |
|
||
| DELETE | /error-items/:id | 删除错题 |
|
||
|
||
**校验状态机**:
|
||
```
|
||
raw → (用户查看+确认) → reviewed → (用户修正字段) → corrected
|
||
↓
|
||
stale (30天未确认,系统标记,可恢复为 raw)
|
||
```
|
||
|
||
**AnalysisReport 数据过滤**: 查询时加 `WHERE verification_status != 'raw'`,确保分析只使用已确认数据。
|
||
|
||
### 3.5 AI 模块
|
||
|
||
```
|
||
modules/ai/
|
||
├── ai.module.ts
|
||
├── ai.controller.ts # POST /ai/analyze
|
||
├── ai.service.ts # Coze SDK 调用封装
|
||
├── strategies/
|
||
│ ├── ocr.strategy.ts # OCR 识别策略
|
||
│ ├── classify.strategy.ts # 学科/知识点分类策略
|
||
│ └── diagnose.strategy.ts # 错误原因诊断策略
|
||
└── dto/
|
||
├── analyze-request.dto.ts
|
||
└── analyze-response.dto.ts
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /ai/analyze | 分析错题图片 → 返回结构化结果 |
|
||
| GET | /ai/report | 获取薄弱点分析报告 |
|
||
|
||
**AI 分析流程**:
|
||
|
||
```
|
||
图片 URL → OCR 文字提取 ──→ question_text (confidence: 0.5-0.95)
|
||
├─ 学科分类 ──────────→ subject_id (confidence: 0.7-0.95)
|
||
├─ 知识点标注 ────────→ knowledge_points[] (confidence 各 0.5-0.9)
|
||
├─ 题目结构提取 ──────→ wrong_answer/correct_answer (confidence 各 0.5-0.9)
|
||
└─ 错误原因诊断 ──────→ error_type + diagnosis (confidence: 0.5-0.9)
|
||
→ 每个字段附带 confidence 分数
|
||
→ 低置信(<0.7)字段标记 requires_review=true,前端红色高亮
|
||
→ 汇总返回 { result, confidences, requires_review_fields[] }
|
||
```
|
||
|
||
### 3.6 Image 模块(图像预处理)
|
||
|
||
```
|
||
modules/image/
|
||
├── image.module.ts
|
||
├── image.service.ts # 图像预处理编排
|
||
├── pipelines/
|
||
│ ├── perspective.service.ts # 透视校正(手动框 4 角)
|
||
│ ├── enhance.service.ts # CLAHE + Gamma + 对比度增强
|
||
│ └── pen-removal.service.ts # 笔迹去除(红/蓝 HSV 自动,黑笔手动圈选)
|
||
├── sharp.config.ts # Sharp 图像处理参数配置
|
||
└── dto/
|
||
└── preprocess.dto.ts
|
||
```
|
||
|
||
**处理管线**:
|
||
```
|
||
原始图片 → 透视校正 → CLAHE 增强 → 笔迹去除 → 输出增强图片 URL
|
||
↓ ↓ ↓ ↓
|
||
原图保留 手动框角 光照归一化 红/蓝自动去除
|
||
黑笔可选手动圈选
|
||
```
|
||
|
||
**降级策略**: 任何模块失败不阻塞整体流程。校正失败 → 用原图;增强失败 → 跳过增强;笔迹去除失败 → 保留原图。始终保证图片能进入 AI 识别。
|
||
|
||
**Spike 验证结论**(来自旧架构,Coze 沙盒中重新调优):
|
||
- 自动透视校正不可用(整页裁成碎片),以手动框 4 角为主方案
|
||
- CLAHE 增强 10/10 达到清晰度标准
|
||
- 红笔批改可靠去除、蓝笔可用、黑笔无法自动去除(需用户圈选)
|
||
|
||
### 3.8 Subject 模块
|
||
|
||
```
|
||
modules/subject/
|
||
├── subject.module.ts
|
||
├── subject.controller.ts # GET /subjects
|
||
├── subject.service.ts
|
||
└── subject.entity.ts
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | /subjects | 获取学科列表 |
|
||
| GET | /subjects/:id/knowledge-points | 获取学科下知识点树 |
|
||
|
||
### 3.7 Print 模块(PDF 输出)[P0]
|
||
|
||
```
|
||
modules/print/
|
||
├── print.module.ts
|
||
├── print.controller.ts # POST /print/generate, GET /print/download/:id
|
||
├── print.service.ts # PDF 生成 + S3 存储 + 过期清理
|
||
├── pdf-layout.service.ts # PDFKit A4/300DPI 排版
|
||
└── dto/
|
||
├── generate-print.dto.ts
|
||
└── print-task.dto.ts
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /print/generate | 提交错题 ID 列表,生成 PDF 任务 |
|
||
| GET | /print/task/:id | 查询生成进度 |
|
||
| GET | /print/download/:id | 下载 PDF 文件(24h 有效) |
|
||
|
||
**排版优先级**: 题库匹配的结构化内容 > 经图像预处理的增强图片 > 原始图片
|
||
|
||
**清理策略**: 定时任务每天清理 expires_at < NOW() 的临时文件。
|
||
|
||
### 3.9 Upload 模块
|
||
|
||
```
|
||
modules/upload/
|
||
├── upload.module.ts
|
||
├── upload.controller.ts # POST /upload/image
|
||
├── upload.service.ts # S3 上传 + 缩略图
|
||
└── upload.config.ts # S3/MinIO 配置
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| POST | /upload/image | 上传图片 → 返回 URL |
|
||
|
||
### 3.10 Recommend 模块 (P1)
|
||
|
||
```
|
||
modules/recommend/
|
||
├── recommend.module.ts
|
||
├── recommend.controller.ts # GET /recommend
|
||
├── recommend.service.ts # 推荐编排
|
||
└── strategies/
|
||
├── coarse-recall.strategy.ts # 粗筛:关键词搜索 + Jaccard 相似度(本地,免费)
|
||
├── ai-rerank.strategy.ts # 精排:AI 语义匹配(候选集不足时启用,付费)
|
||
├── weak-point.strategy.ts # 薄弱点权重排序
|
||
└── similar-difficulty.strategy.ts # 难度匹配
|
||
```
|
||
|
||
**两阶段推荐策略**:
|
||
1. **粗筛**(关键词 + Jaccard 相似度)→ 快速召回候选集,零成本、低延迟
|
||
2. **精排**(AI 语义匹配)→ 候选集为空或不满足阈值时启用,语义理解泛化
|
||
3. 排序: 薄弱点权重 > 难度匹配度 > 去重(已做过的不推)
|
||
|
||
### 3.11 QuestionBank 模块(题库抽象层)
|
||
|
||
```
|
||
modules/question-bank/
|
||
├── question-bank.module.ts
|
||
├── question-bank.controller.ts # CRUD /questions
|
||
├── question-bank.service.ts # 多源题库路由
|
||
├── adapters/
|
||
│ ├── base-adapter.ts # 题库适配器接口
|
||
│ ├── self-built.adapter.ts # 自有题库适配器
|
||
│ ├── zuoyebang.adapter.ts # 作业帮 API 适配器
|
||
│ └── adapter.factory.ts # 按 source 路由到对应适配器
|
||
├── pdf-import/
|
||
│ ├── pdf-parser.service.ts # PDF → 文本
|
||
│ ├── ai-extractor.service.ts # AI 结构化提取题目
|
||
│ └── import-review.service.ts # 人工审核流程
|
||
└── dto/
|
||
├── create-question.dto.ts
|
||
├── query-question.dto.ts
|
||
└── pdf-import.dto.ts
|
||
```
|
||
|
||
**API**:
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| GET | /questions | 题目列表查询(分页+筛选) |
|
||
| GET | /questions/:id | 题目详情 |
|
||
| POST | /questions | 手动创建题目(自有题库录入) |
|
||
| POST | /questions/search | 跨源搜索(自有 + 作业帮,结果合并) |
|
||
| POST | /questions/pdf-import | 上传 PDF 启动导入任务 |
|
||
| GET | /questions/pdf-import/:taskId | 查询 PDF 导入进度 |
|
||
|
||
**适配器接口**:
|
||
```typescript
|
||
interface QuestionBankAdapter {
|
||
source: string;
|
||
search(params: SearchParams): Promise<Question[]>;
|
||
getById(id: string): Promise<Question>;
|
||
healthCheck(): Promise<boolean>;
|
||
}
|
||
```
|
||
|
||
**题库路由策略**: 请求时并行查询自有题库 + 作业帮 API,合并去重后返回。自有题库优先排序。
|
||
|
||
## 4. 前端状态管理 (Zustand)
|
||
|
||
```
|
||
stores/
|
||
├── auth.store.ts # 登录态、token、用户信息
|
||
├── error-item.store.ts # 错题列表、筛选条件、分页
|
||
├── capture.store.ts # 拍照流程状态机
|
||
└── ai-analysis.store.ts # AI 分析结果缓存
|
||
```
|
||
|
||
**capture 状态机**:
|
||
|
||
```
|
||
IDLE → CAMERA → PREVIEW → UPLOADING → ANALYZING → REVIEW → SAVING → DONE
|
||
↓ ↓ ↓
|
||
ERROR ERROR ERROR
|
||
```
|
||
|
||
## 5. MVP 开发顺序
|
||
|
||
```
|
||
Phase 2a (Week 1-2): 基础设施
|
||
- 数据库 Schema + 迁移
|
||
- Auth 模块(微信登录)
|
||
- User 模块
|
||
- Image 模块(图像预处理管线)
|
||
|
||
Phase 2b (Week 3-4): 核心闭环
|
||
- Upload 模块
|
||
- AI 模块(Coze SDK 集成)
|
||
- ErrorItem CRUD
|
||
- 拍照录入页 + 错题列表页
|
||
|
||
Phase 2c (Week 5-6): 分析+打印+打磨
|
||
- 错题详情 + AI 分析展示
|
||
- 薄弱点汇总
|
||
- Print 模块(PDF 输出)
|
||
- Subject 模块 + 筛选
|
||
- 交互打磨、异常处理
|
||
```
|
||
|
||
---
|
||
|
||
*关联: 总体架构.md → 技术选型.md → 数据模型.md*
|