Files
QQuiz/PROJECT_STRUCTURE.md
handsomezhuzhu c5ecbeaec2 🎉 Initial commit: QQuiz - 智能刷题与题库管理平台
## 功能特性

 **核心功能**
- 多文件上传与智能去重(基于 content_hash)
- 异步文档解析(支持 TXT/PDF/DOCX/XLSX)
- AI 智能题目提取与评分(OpenAI/Anthropic/Qwen)
- 断点续做与进度管理
- 自动错题本收集

 **技术栈**
- Backend: FastAPI + SQLAlchemy 2.0 + PostgreSQL
- Frontend: React 18 + Vite + Tailwind CSS
- Deployment: Docker Compose

 **项目结构**
- 53 个文件
- 完整的前后端分离架构
- Docker/源码双模部署支持

🚀 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 12:39:46 +08:00

12 KiB
Raw Blame History

QQuiz 项目结构

📁 完整目录结构

QQuiz/
├── backend/                    # FastAPI 后端
│   ├── alembic/                # 数据库迁移
│   │   ├── versions/           # 迁移脚本
│   │   ├── env.py              # Alembic 环境配置
│   │   └── script.py.mako      # 迁移脚本模板
│   ├── routers/                # API 路由
│   │   ├── __init__.py         # 路由包初始化
│   │   ├── auth.py             # 认证路由(登录/注册)
│   │   ├── admin.py            # 管理员路由
│   │   ├── exam.py             # 题库路由(创建/追加/查询)⭐
│   │   ├── question.py         # 题目路由(刷题/答题)
│   │   └── mistake.py          # 错题本路由
│   ├── services/               # 业务逻辑层
│   │   ├── __init__.py         # 服务包初始化
│   │   ├── auth_service.py     # 认证服务JWT/权限)
│   │   ├── llm_service.py      # AI 服务(解析/评分)⭐
│   │   └── document_parser.py  # 文档解析服务
│   ├── models.py               # SQLAlchemy 数据模型 ⭐
│   ├── schemas.py              # Pydantic 请求/响应模型
│   ├── database.py             # 数据库配置
│   ├── utils.py                # 工具函数Hash/密码)
│   ├── main.py                 # FastAPI 应用入口
│   ├── requirements.txt        # Python 依赖
│   ├── alembic.ini             # Alembic 配置
│   └── Dockerfile              # 后端 Docker 镜像
│
├── frontend/                   # React 前端
│   ├── src/
│   │   ├── api/
│   │   │   └── client.js       # API 客户端Axios⭐
│   │   ├── components/
│   │   │   ├── Layout.jsx      # 主布局(导航栏)
│   │   │   └── ProtectedRoute.jsx  # 路由保护
│   │   ├── context/
│   │   │   └── AuthContext.jsx # 认证上下文
│   │   ├── pages/
│   │   │   ├── Login.jsx       # 登录页
│   │   │   ├── Register.jsx    # 注册页
│   │   │   ├── Dashboard.jsx   # 仪表盘
│   │   │   ├── ExamList.jsx    # 题库列表 ⭐
│   │   │   ├── ExamDetail.jsx  # 题库详情(追加上传)⭐
│   │   │   ├── QuizPlayer.jsx  # 刷题核心页面 ⭐
│   │   │   ├── MistakeList.jsx # 错题本
│   │   │   └── AdminSettings.jsx   # 系统设置
│   │   ├── utils/
│   │   │   └── helpers.js      # 工具函数
│   │   ├── App.jsx             # 应用根组件
│   │   ├── index.jsx           # 应用入口
│   │   └── index.css           # 全局样式
│   ├── public/
│   │   └── index.html          # HTML 模板
│   ├── package.json            # Node 依赖
│   ├── vite.config.js          # Vite 配置
│   ├── tailwind.config.js      # Tailwind CSS 配置
│   ├── postcss.config.js       # PostCSS 配置
│   └── Dockerfile              # 前端 Docker 镜像
│
├── docker-compose.yml          # Docker 编排配置 ⭐
├── .env.example                # 环境变量模板
├── .gitignore                  # Git 忽略文件
├── README.md                   # 项目说明
├── DEPLOYMENT.md               # 部署指南
├── PROJECT_STRUCTURE.md        # 项目结构(本文件)
└── run_local.sh                # 本地运行脚本

⭐ 表示核心文件

🔑 核心文件说明

后端核心

models.py - 数据模型

定义了 5 个核心数据表:

  • User: 用户表(用户名、密码、管理员标识)
  • SystemConfig: 系统配置KV 存储)
  • Exam: 题库表(标题、状态、进度、题目数)
  • Question: 题目表(内容、类型、选项、答案、content_hash
  • UserMistake: 错题本(用户 ID、题目 ID

关键设计:

  • content_hash: MD5 哈希,用于题目去重
  • current_index: 记录刷题进度
  • status: Enum 管理题库状态pending/processing/ready/failed

exam.py - 题库路由

实现了最核心的业务逻辑:

  • POST /create: 创建题库并上传第一份文档
  • POST /{exam_id}/append: 追加文档到现有题库
  • GET /: 获取题库列表
  • GET /{exam_id}: 获取题库详情
  • PUT /{exam_id}/progress: 更新刷题进度

去重逻辑:

# 1. 解析文档获取题目
questions_data = await llm_service.parse_document(content)

# 2. 计算每道题的 Hash
for q in questions_data:
    q["content_hash"] = calculate_content_hash(q["content"])

# 3. 仅在当前 exam_id 范围内查询去重
existing_hashes = await db.execute(
    select(Question.content_hash).where(Question.exam_id == exam_id)
)

# 4. 仅插入 Hash 不存在的题目
for q in questions_data:
    if q["content_hash"] not in existing_hashes:
        db.add(Question(**q))

llm_service.py - AI 服务

提供两个核心功能:

  1. parse_document(): 调用 LLM 解析文档,提取题目
  2. grade_short_answer(): AI 评分简答题

支持 3 个 AI 提供商:

  • OpenAI (GPT-4o-mini)
  • Anthropic (Claude-3-haiku)
  • Qwen (通义千问)

前端核心

client.js - API 客户端

封装了所有后端 API

  • authAPI: 登录、注册、用户信息
  • examAPI: 题库 CRUD、追加文档
  • questionAPI: 获取题目、答题
  • mistakeAPI: 错题本管理
  • adminAPI: 系统配置

特性:

  • 自动添加 JWT Token
  • 统一错误处理和 Toast 提示
  • 401 自动跳转登录

ExamDetail.jsx - 题库详情

最复杂的前端页面,包含:

  • 追加上传: 上传新文档并去重
  • 状态轮询: 每 3 秒轮询一次状态
  • 智能按钮:
    • 处理中时禁用「添加文档」
    • 就绪后显示「开始/继续刷题」
  • 进度展示: 题目数、完成度、进度条

状态轮询实现:

useEffect(() => {
  const interval = setInterval(() => {
    pollExamStatus()  // 轮询状态
  }, 3000)

  return () => clearInterval(interval)
}, [examId])

const pollExamStatus = async () => {
  const newExam = await examAPI.getDetail(examId)

  // 检测状态变化
  if (exam?.status === 'processing' && newExam.status === 'ready') {
    toast.success('文档解析完成!')
    await loadExamDetail()  // 重新加载数据
  }

  setExam(newExam)
}

QuizPlayer.jsx - 刷题核心

实现完整的刷题流程:

  1. 基于 current_index 加载当前题目
  2. 根据题型显示不同的答题界面
  3. 提交答案并检查(简答题调用 AI 评分)
  4. 答错自动加入错题本
  5. 点击下一题自动更新进度

断点续做实现:

// 始终基于 exam.current_index 加载题目
const loadCurrentQuestion = async () => {
  const question = await questionAPI.getCurrentQuestion(examId)
  // 后端会根据 current_index 返回对应题目
}

// 下一题时更新进度
const handleNext = async () => {
  const newIndex = exam.current_index + 1
  await examAPI.updateProgress(examId, newIndex)
  await loadCurrentQuestion()
}

🔄 核心业务流程

1. 创建题库流程

用户上传文档
    ↓
后端创建 Exam (status=pending)
    ↓
后台任务开始解析
    ↓
更新状态为 processing
    ↓
调用 document_parser 解析文件
    ↓
调用 llm_service 提取题目
    ↓
计算 content_hash 并去重
    ↓
插入新题目到数据库
    ↓
更新 total_questions 和 status=ready
    ↓
前端轮询检测到状态变化
    ↓
自动刷新显示新题目

2. 追加文档流程

用户点击「添加题目文档」
    ↓
上传新文档
    ↓
后端检查 Exam 是否在处理中
    ↓
更新状态为 processing
    ↓
后台任务解析新文档
    ↓
提取题目并计算 Hash
    ↓
仅在当前 exam_id 范围内查重
    ↓
插入不重复的题目
    ↓
更新 total_questions
    ↓
更新状态为 ready
    ↓
前端轮询检测并刷新

3. 刷题流程

用户点击「开始刷题」
    ↓
基于 current_index 加载题目
    ↓
用户选择/输入答案
    ↓
提交答案到后端
    ↓
后端检查答案
  ├─ 选择题:字符串比对
  ├─ 多选题:排序后比对
  ├─ 判断题:字符串比对
  └─ 简答题:调用 AI 评分
    ↓
答错自动加入错题本
    ↓
返回结果和解析
    ↓
用户点击「下一题」
    ↓
更新 current_index += 1
    ↓
加载下一题

🗄️ 数据库设计

关键索引

-- Exam 表
CREATE INDEX ix_exams_user_status ON exams(user_id, status);

-- Question 表
CREATE INDEX ix_questions_exam_hash ON questions(exam_id, content_hash);
CREATE INDEX ix_questions_content_hash ON questions(content_hash);

-- UserMistake 表
CREATE UNIQUE INDEX ix_user_mistakes_unique ON user_mistakes(user_id, question_id);

关键约束

  • Question.content_hash: 用于去重,同一 exam_id 下不允许重复
  • UserMistake: user_id + question_id 唯一约束,防止重复添加
  • 级联删除:删除 Exam 时自动删除所有关联的 Question 和 UserMistake

🎨 技术栈

后端

  • FastAPI: 现代化 Python Web 框架
  • SQLAlchemy 2.0: 异步 ORM
  • Alembic: 数据库迁移
  • Pydantic: 数据验证
  • JWT: 无状态认证
  • OpenAI/Anthropic/Qwen: AI 解析和评分

前端

  • React 18: UI 框架
  • Vite: 构建工具(比 CRA 更快)
  • Tailwind CSS: 原子化 CSS
  • Axios: HTTP 客户端
  • React Router: 路由管理
  • React Hot Toast: 消息提示

部署

  • Docker + Docker Compose: 容器化部署
  • PostgreSQL 15: 关系型数据库
  • Nginx (可选): 反向代理

📊 API 接口汇总

认证相关

  • POST /api/auth/register: 用户注册
  • POST /api/auth/login: 用户登录
  • GET /api/auth/me: 获取当前用户信息
  • POST /api/auth/change-password: 修改密码

题库相关

  • POST /api/exams/create: 创建题库
  • POST /api/exams/{exam_id}/append: 追加文档
  • GET /api/exams/: 获取题库列表
  • GET /api/exams/{exam_id}: 获取题库详情
  • DELETE /api/exams/{exam_id}: 删除题库
  • PUT /api/exams/{exam_id}/progress: 更新进度

题目相关

  • GET /api/questions/exam/{exam_id}/questions: 获取题库所有题目
  • GET /api/questions/exam/{exam_id}/current: 获取当前题目
  • GET /api/questions/{question_id}: 获取题目详情
  • POST /api/questions/check: 检查答案

错题本相关

  • GET /api/mistakes/: 获取错题列表
  • POST /api/mistakes/add: 添加错题
  • DELETE /api/mistakes/{mistake_id}: 移除错题
  • DELETE /api/mistakes/question/{question_id}: 按题目 ID 移除

管理员相关

  • GET /api/admin/config: 获取系统配置
  • PUT /api/admin/config: 更新系统配置

🔒 安全特性

  1. 密码加密: bcrypt 哈希
  2. JWT 认证: 无状态 Token
  3. 权限控制: 管理员/普通用户
  4. CORS 保护: 可配置允许的来源
  5. 文件类型验证: 仅允许特定格式
  6. 文件大小限制: 可配置最大上传大小
  7. 速率限制: 每日上传次数限制

🎯 核心创新点

  1. 智能去重: 基于 content_hash 的高效去重算法
  2. 追加上传: 支持向现有题库添加新文档
  3. 异步处理: 后台任务处理文档解析,不阻塞用户
  4. 状态轮询: 前端实时显示处理状态
  5. 断点续做: 基于 current_index 的进度管理
  6. AI 评分: 简答题智能评分和反馈
  7. 自动错题本: 答错自动收集,支持手动管理
  8. 多 AI 支持: 灵活切换 AI 提供商

这就是 QQuiz 的完整架构!🎉