mirror of
https://github.com/handsomezhuzhu/QQuiz.git
synced 2026-02-20 12:00:14 +00:00
codex/fix-security-vulnerabilities-in-qquiz
QQuiz - 智能刷题与题库管理平台
QQuiz 是一个支持 Docker/源码双模部署的智能刷题平台,核心功能包括多文件上传、自动去重、异步解析、断点续做和错题本管理。
功能特性
- 📚 多文件上传与去重: 支持向同一题库追加文档,自动识别并过滤重复题目
- 🤖 AI 智能解析: 支持 Google Gemini (推荐) / OpenAI / Anthropic / Qwen 多种 AI 提供商
- 📄 原生 PDF 理解: Gemini 支持直接处理 PDF(最多1000页),完整保留图片、表格、公式等内容
- 🎓 AI 参考答案: 对于没有提供答案的题目,自动生成 AI 参考答案
- 📊 断点续做: 自动记录刷题进度,随时继续
- ❌ 错题本管理: 自动收集错题,支持手动添加/移除
- 🎯 多题型支持: 单选、多选、判断、简答
- 🔐 权限管理: 管理员配置、用户隔离
- 📱 移动端优先: 完美适配手机端
快速开始
使用预构建镜像(最快)
直接使用 GitHub 自动构建的镜像,无需等待本地构建:
# 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
镜像说明:
- 镜像地址:
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 数据库和上传文件,确保数据不会丢失。
单容器部署(自行构建)
从源码构建,一个容器包含前后端和 SQLite 数据库:
# 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
传统部署(3 个容器)
前后端分离 + MySQL:
# 启动服务(建议直接在命令行生成强密钥和管理员密码)
SECRET_KEY=$(openssl rand -base64 48) \
ADMIN_PASSWORD=$(openssl rand -base64 16) \
docker-compose up -d
# 前端: http://localhost:3000
# 后端: http://localhost:8000
方式二:本地运行
前置要求
- Python 3.11+
- Node.js 18+
- MySQL 8.0+ 或 Docker (用于运行 MySQL)
Linux/macOS 用户:
# 1. 配置环境变量
cp .env.example .env
# 编辑 .env,修改 DATABASE_URL 为本地数据库地址
# 2. 启动 MySQL
# macOS: brew services start mysql
# Linux: sudo systemctl start mysql
# 3. 运行启动脚本
chmod +x scripts/run_local.sh
./scripts/run_local.sh
MySQL 安装指南: 详见 docs/MYSQL_SETUP.md
GitHub Actions 自动构建设置
如果你 fork 了本项目并想启用自动构建 Docker 镜像功能:
-
启用 GitHub Actions:
- 进入你的仓库 Settings → Actions → General
- 确保 "Actions permissions" 设置为 "Allow all actions"
-
启用 Packages 写入权限:
- Settings → Actions → General
- 找到 "Workflow permissions"
- 选择 "Read and write permissions"
- 勾选 "Allow GitHub Actions to create and approve pull requests"
-
触发构建:
- 推送代码到
main分支会自动触发构建 - 或者创建 tag(如
v1.0.0)会构建带版本号的镜像 - 也可以在 Actions 页面手动触发 "Build and Publish Docker Image" workflow
- 推送代码到
-
查看构建的镜像:
- 构建完成后,镜像会自动发布到
ghcr.io/handsomezhuzhu/qquiz - 在仓库主页右侧 "Packages" 可以看到已发布的镜像
- 镜像默认是私有的,如需公开:进入 Package 页面 → Package settings → Change visibility
- 构建完成后,镜像会自动发布到
镜像地址:
# 拉取最新镜像
docker pull ghcr.io/handsomezhuzhu/qquiz:latest
默认账户
管理员账户:
- 用户名:
admin - 密码: 取自环境变量
ADMIN_PASSWORD(必须至少 12 位,建议随机生成)
⚠️ 重要: 在部署前就必须设置强管理员密码;如果需要轮换密码,请更新环境变量后重启服务。
项目结构
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 # 项目说明
核心业务流程
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 支持两种配置方式:
- 环境变量配置 (
.env文件):适合 Docker 部署和开发环境 - 数据库配置 (管理员后台):适合生产环境,支持在线修改,无需重启服务
推荐流程:首次部署使用环境变量,部署成功后通过管理员后台修改配置。
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 客户端
开发进度
- Step 1: Foundation & Models ✅
- Step 2: Backend Core Logic
- Step 3: Frontend Config & API
- Step 4: Frontend Complex UI
License
MIT
Description
Languages
JavaScript
51.7%
Python
46.4%
Shell
0.7%
Dockerfile
0.6%
HTML
0.2%
Other
0.4%