Files
ai_soc_sw/docs/02_系统架构/模块设计.md
T
tupingr e3f4af9c0c docs(arch): 旧架构合并 — 30项决策落地,5份文档升级至v0.4.0
- 总体架构:新增打印/图像预处理/双飞轮/三环境部署
- 技术选型:调整决策理由(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>
2026-05-26 12:00:52 +08:00

14 KiB
Raw Blame History

模块设计

版本: 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 导入进度

适配器接口:

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