完善文档与前端迁移,补充开源协议

This commit is contained in:
2026-04-17 19:48:13 +08:00
parent 466fa50aa8
commit 31916e68a6
94 changed files with 7019 additions and 480 deletions

377
README.md
View File

@@ -1,281 +1,186 @@
# QQuiz - 智能刷题与题库管理平台
# QQuiz
QQuiz 是一个支持 Docker/源码双模部署的智能刷题平台,核心功能包括多文件上传、自动去重、异步解析、断点续做错题本管理。
QQuiz 是一个面向题库管理与刷题训练的全栈应用,支持文档导入、异步解析、题目去重、断点续做错题本管理员配置
## 功能特性
## 界面预览
- 📚 **多文件上传与去重**: 支持向同一题库追加文档,自动识别并过滤重复题目
- 🤖 **AI 智能解析**: 支持 Google Gemini (推荐) / OpenAI / Anthropic / Qwen 多种 AI 提供商
- 📄 **原生 PDF 理解**: Gemini 支持直接处理 PDF最多1000页完整保留图片、表格、公式等内容
- 🎓 **AI 参考答案**: 对于没有提供答案的题目,自动生成 AI 参考答案
- 📊 **断点续做**: 自动记录刷题进度,随时继续
- **错题本管理**: 自动收集错题,支持手动添加/移除
- 🎯 **多题型支持**: 单选、多选、判断、简答
- 🔐 **权限管理**: 管理员配置、用户隔离
- 📱 **移动端优先**: 完美适配手机端
![QQuiz 界面截图](docs/cover.png)
## 核心能力
- 多文件导入与题目去重
- 异步解析进度回传
- 单选、多选、判断、简答题统一管理
- 刷题进度保存与继续作答
- 错题本与错题练习
- 管理员用户管理与系统配置
- 支持 Gemini / OpenAI / Anthropic / Qwen
## 当前架构
- `backend/`FastAPI + SQLAlchemy + Alembic
- `web/`当前主前端Next.js App Router + TypeScript + Tailwind CSS
- `frontend/`:保留中的 legacy Vite 前端,用于单容器兼容路径
说明:
- 分离部署优先使用 `web/`
- 单容器镜像当前仍复用 `frontend/` 构建静态资源
## 快速开始
### 使用预构建镜像(最快)
### 1. 分离部署,推荐
直接使用 GitHub 自动构建的镜像,无需等待本地构建:
前端运行在 `3000`,后端运行在 `8000`
```bash
# 1. 拉取最新镜像
docker pull ghcr.io/handsomezhuzhu/qquiz:latest
# 2. 配置环境变量
cp .env.example .env
# 编辑 .env填入你的 API Key
# 3. 运行容器
docker run -d \
--name qquiz \
-p 8000:8000 \
-v $(pwd)/qquiz_data:/app/qquiz_data \
--env-file .env \
ghcr.io/handsomezhuzhu/qquiz:latest
# 4. 访问应用: http://localhost:8000
docker compose up -d --build
```
**镜像说明:**
- **镜像地址**: `ghcr.io/handsomezhuzhu/qquiz:latest`
- **构建来源**: GitHub Actions 自动构建,每次 push 到 main 分支自动更新
- **架构支持**: linux/amd64, linux/arm64支持树莓派、Apple Silicon 等)
- **大小**: 约 400-500MB包含前后端完整运行环境
- **标签说明**:
- `latest`: 最新主分支版本
- `v1.0.0`: 特定版本号(如果有 tag
访问地址:
**数据持久化:** 使用 `-v` 参数挂载 `qquiz_data` 目录,包含 SQLite 数据库和上传文件,确保数据不会丢失。
- 前端:`http://localhost:3000`
- 后端:`http://localhost:8000`
- 后端健康检查:`http://localhost:8000/health`
### 单容器部署(自行构建)
从源码构建,一个容器包含前后端和 SQLite 数据库:
### 2. 分离部署 + MySQL
```bash
# 1. 配置环境变量(必须提供强密码和密钥)
cp .env.example .env
# 编辑 .env填入至少 32 位的 SECRET_KEY 和至少 12 位的 ADMIN_PASSWORD建议使用随机生成值
# 2. 启动服务(未设置强密码/密钥会直接报错终止)
SECRET_KEY=$(openssl rand -base64 48) \
ADMIN_PASSWORD=$(openssl rand -base64 16) \
docker-compose -f docker-compose-single.yml up -d
# 3. 访问应用: http://localhost:8000
# API 文档: http://localhost:8000/docs
docker compose -f docker-compose.yml -f docker-compose.mysql.yml up -d --build
```
### 传统部署3 个容器)
### 3. 单容器部署
前后端分离 + MySQL
单容器模式会把前端静态资源集成到后端服务中,统一通过 `8000` 提供。
```bash
# 启动服务(建议直接在命令行生成强密钥和管理员密码)
SECRET_KEY=$(openssl rand -base64 48) \
ADMIN_PASSWORD=$(openssl rand -base64 16) \
docker-compose up -d
cp .env.example .env
# 前端: http://localhost:3000
# 后端: http://localhost:8000
docker compose -f docker-compose-single.yml up -d --build
```
### 方式二:本地运行
访问地址:
- 应用:`http://localhost:8000`
- API 文档:`http://localhost:8000/docs`
## 本地开发
### 后端
```bash
cd backend
pip install -r requirements.txt
alembic upgrade head
uvicorn main:app --reload --host 0.0.0.0 --port 8000
```
### 新前端
```bash
cd web
npm install
npm run dev
```
### 旧前端
仅在兼容或迁移场景下需要:
```bash
cd frontend
npm install
npm run dev
```
## 运行要求
#### 前置要求
- Python 3.11+
- Node.js 18+
- MySQL 8.0+ 或 Docker (用于运行 MySQL)
- Docker / Docker Compose
**Linux/macOS 用户:**
```bash
# 1. 配置环境变量
cp .env.example .env
# 编辑 .env修改 DATABASE_URL 为本地数据库地址
## 关键环境变量
# 2. 启动 MySQL
# macOS: brew services start mysql
# Linux: sudo systemctl start mysql
| 变量 | 说明 |
| --- | --- |
| `DATABASE_URL` | 数据库连接字符串 |
| `SECRET_KEY` | JWT 密钥,至少 32 位 |
| `ADMIN_PASSWORD` | 默认管理员密码,至少 12 位 |
| `AI_PROVIDER` | `gemini` / `openai` / `anthropic` / `qwen` |
| `GEMINI_API_KEY` | Gemini API Key |
| `OPENAI_API_KEY` | OpenAI API Key |
| `OPENAI_BASE_URL` | OpenAI 或兼容网关地址 |
| `ALLOW_REGISTRATION` | 是否允许注册 |
| `MAX_UPLOAD_SIZE_MB` | 单次上传大小限制 |
| `MAX_DAILY_UPLOADS` | 每日上传次数限制 |
# 3. 运行启动脚本
chmod +x scripts/run_local.sh
./scripts/run_local.sh
```
更多示例见 [`.env.example`](.env.example)。
**MySQL 安装指南:** 详见 [docs/MYSQL_SETUP.md](docs/MYSQL_SETUP.md)
## 目录结构
## GitHub Actions 自动构建设置
如果你 fork 了本项目并想启用自动构建 Docker 镜像功能:
1. **启用 GitHub Actions**:
- 进入你的仓库 Settings → Actions → General
- 确保 "Actions permissions" 设置为 "Allow all actions"
2. **启用 Packages 写入权限**:
- Settings → Actions → General
- 找到 "Workflow permissions"
- 选择 "Read and write permissions"
- 勾选 "Allow GitHub Actions to create and approve pull requests"
3. **触发构建**:
- 推送代码到 `main` 分支会自动触发构建
- 或者创建 tag`v1.0.0`)会构建带版本号的镜像
- 也可以在 Actions 页面手动触发 "Build and Publish Docker Image" workflow
4. **查看构建的镜像**:
- 构建完成后,镜像会自动发布到 `ghcr.io/handsomezhuzhu/qquiz`
- 在仓库主页右侧 "Packages" 可以看到已发布的镜像
- 镜像默认是私有的,如需公开:进入 Package 页面 → Package settings → Change visibility
**镜像地址:**
```bash
# 拉取最新镜像
docker pull ghcr.io/handsomezhuzhu/qquiz:latest
```
## 默认账户
**管理员账户:**
- 用户名: `admin`
- 密码: 取自环境变量 `ADMIN_PASSWORD`(必须至少 12 位,建议随机生成)
⚠️ **重要**: 在部署前就必须设置强管理员密码;如果需要轮换密码,请更新环境变量后重启服务。
## 项目结构
```
```text
QQuiz/
├─ backend/ # FastAPI 后端
├── alembic/ # 数据库迁移
├── routers/ # API 路由
├── services/ # 业务逻辑
├── models.py # 数据模型
├── database.py # 数据库配置
├── main.py # 应用入口
│ └── requirements.txt # Python 依赖
├── frontend/ # React 前端
├── src/
│ ├── api/ # API 客户端
├── pages/ # 页面组件
├── components/ # 通用组件
└── App.jsx # 应用入口
│ ├── package.json # Node 依赖
│ └── vite.config.js # Vite 配置
├── scripts/ # 部署和启动脚本
│ └── run_local.sh # Linux/macOS 启动脚本
├── docs/ # 文档目录
│ ├── MYSQL_SETUP.md # MySQL 安装配置指南
│ └── PROJECT_STRUCTURE.md # 项目架构详解
├── test_data/ # 测试数据
│ └── sample_questions.txt # 示例题目
├── docker-compose.yml # Docker 编排
├── .env.example # 环境变量模板
└── README.md # 项目说明
├─ backend/ FastAPI 后端
─ alembic/ 数据库迁移
─ routers/ API 路由
─ services/ 业务服务
─ models.py ORM 模型
├─ schemas.py Pydantic Schema
─ main.py 应用入口
├─ web/ Next.js 前端
│ ├─ src/app/ App Router 页面与 API Route
─ src/components/ UI 与业务组件
└─ src/lib/ 前端 API、鉴权、工具
├─ frontend/ Legacy Vite 前端
├─ docs/ 部署、审计与截图
├─ test_data/ 示例题库文件
├─ docker-compose.yml 前后端分离部署
├─ docker-compose.mysql.yml MySQL overlay
├─ docker-compose-single.yml 单容器部署
└─ Dockerfile 单容器镜像构建
```
## 核心业务流程
### 1. 创建题库
用户首次上传文档时,创建新的 Exam (题库容器)
### 2. 追加文档
在已有题库详情页点击 "添加题目文档",上传新文件
### 3. 去重逻辑
- 对题目内容进行标准化处理 (去空格、标点、转小写)
- 计算 MD5 Hash
- 仅在当前题库范围内查询去重
- 仅插入 Hash 不存在的题目
### 4. 异步处理
- 后台任务处理 AI 解析
- 状态: `pending``processing``ready` / `failed`
- 前端轮询状态,自动刷新
### 5. 刷题体验
- 基于 `current_index` 实现断点续做
- 错题自动加入错题本
- 简答题 AI 评分
## 环境变量说明
| 变量 | 说明 | 默认值 |
|------|------|--------|
| `DATABASE_URL` | 数据库连接字符串 | - |
| `SECRET_KEY` | JWT 密钥(必须至少 32 位随机字符串) | - |
| `ADMIN_PASSWORD` | 默认管理员密码(必须至少 12 位,建议随机生成) | - |
| `AI_PROVIDER` | AI 提供商 (gemini/openai/anthropic/qwen) | gemini |
| `GEMINI_API_KEY` | Google Gemini API 密钥 | - |
| `GEMINI_BASE_URL` | Gemini API 地址(可选,支持代理) | https://generativelanguage.googleapis.com |
| `GEMINI_MODEL` | Gemini 模型 | gemini-2.0-flash-exp |
| `OPENAI_API_KEY` | OpenAI API 密钥 | - |
| `OPENAI_BASE_URL` | OpenAI API 地址 | https://api.openai.com/v1 |
| `OPENAI_MODEL` | OpenAI 模型 | gpt-4o-mini |
| `ANTHROPIC_API_KEY` | Anthropic API 密钥 | - |
| `ANTHROPIC_MODEL` | Anthropic 模型 | claude-3-haiku-20240307 |
| `QWEN_API_KEY` | 通义千问 API 密钥 | - |
| `QWEN_BASE_URL` | 通义千问 API 地址 | https://dashscope.aliyuncs.com/compatible-mode/v1 |
| `QWEN_MODEL` | 通义千问模型 | qwen-plus |
| `ALLOW_REGISTRATION` | 是否允许注册 | true |
| `MAX_UPLOAD_SIZE_MB` | 最大上传文件大小 (MB) | 10 |
| `MAX_DAILY_UPLOADS` | 每日上传次数限制 | 20 |
### AI 提供商对比
| 提供商 | PDF 原生支持 | 文本解析 | 推荐度 | 说明 |
|--------|--------------|----------|--------|------|
| **Google Gemini** | ✅ | ✅ | ⭐⭐⭐⭐⭐ | 支持原生 PDF最多1000页保留图片、表格、公式 |
| OpenAI | ❌ | ✅ | ⭐⭐⭐⭐ | 仅文本提取PDF 会丢失格式和图片 |
| Anthropic | ❌ | ✅ | ⭐⭐⭐⭐ | 仅文本提取PDF 会丢失格式和图片 |
| Qwen (通义千问) | ❌ | ✅ | ⭐⭐⭐ | 仅文本提取PDF 会丢失格式和图片 |
**推荐使用 Gemini**:如果你的题库包含 PDF 文件(特别是含有图片、公式、表格的学科试卷),强烈推荐使用 Gemini。
### 如何获取 API Key
- **Google Gemini**: https://aistudio.google.com/apikey (免费额度充足)
- **OpenAI**: https://platform.openai.com/api-keys
- **Anthropic**: https://console.anthropic.com/settings/keys
- **Qwen (通义千问)**: https://dashscope.console.aliyun.com/apiKey
### AI 配置方式
QQuiz 支持两种配置方式:
1. **环境变量配置** (`.env` 文件):适合 Docker 部署和开发环境
2. **数据库配置** (管理员后台):适合生产环境,支持在线修改,无需重启服务
**推荐流程**:首次部署使用环境变量,部署成功后通过管理员后台修改配置。
**Gemini 自定义代理**: 如果需要使用 Key 轮训服务或代理,可以在管理员后台配置 `GEMINI_BASE_URL`,支持自定义 Gemini API 地址。
## 技术栈
**后端:**
- FastAPI - 现代化 Python Web 框架
- SQLAlchemy 2.0 - 异步 ORM
- Alembic - 数据库迁移
- MySQL 8.0 - 数据库
- aiomysql - MySQL 异步驱动
- Pydantic - 数据验证
### 后端
**前端:**
- React 18 - UI 框架
- Vite - 构建工具
- Tailwind CSS - 样式框架
- React Router - 路由
- Axios - HTTP 客户端
- FastAPI
- SQLAlchemy 2.x
- Alembic
- SQLite / MySQL
- httpx
- OpenAI / Anthropic SDK
## 开发进度
### 前端
- [x] **Step 1**: Foundation & Models ✅
- [ ] **Step 2**: Backend Core Logic
- [ ] **Step 3**: Frontend Config & API
- [ ] **Step 4**: Frontend Complex UI
- Next.js 14 App Router
- React 18
- TypeScript
- Tailwind CSS
- TanStack Query
- Radix UI / shadcn 风格组件
## License
## 构建检查
MIT
常用检查命令:
```bash
cd web && npm run build
docker compose build backend frontend
```
仓库当前没有完整自动化测试套件,提交前至少建议手动验证:
- 登录 / 退出
- 创建题库 / 上传文档 / 查看解析进度
- 刷题与错题加入
- 管理员用户管理与系统设置
- 大数据量列表分页
## 开源协议
本项目采用 [MIT License](LICENSE)。