mirror of
https://github.com/handsomezhuzhu/QQuiz.git
synced 2026-04-18 14:32:54 +00:00
完善文档与前端迁移,补充开源协议
This commit is contained in:
86
docs/PLAN.md
Normal file
86
docs/PLAN.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# QQuiz Execution Plan
|
||||
|
||||
更新时间:2026-04-17
|
||||
|
||||
## 目标
|
||||
|
||||
把当前项目推进到可以持续开发和稳定验收的状态,重点落实:
|
||||
|
||||
1. 默认 SQLite,兼容 MySQL
|
||||
2. 前端界面简洁、可直接操作、少说明文字
|
||||
3. 用户管理达到可上市产品的基础要求
|
||||
4. push 后 GitHub 自动构建镜像
|
||||
5. 逐步完成旧 Vite 前端到新 Next 前端的替换
|
||||
|
||||
## 已完成的代码级工作
|
||||
|
||||
- 默认 Docker 拓扑已切到 SQLite
|
||||
- MySQL 兼容拓扑已拆到 `docker-compose.mysql.yml`
|
||||
- 新前端容器已接入并替换 Docker 默认前端
|
||||
- 管理员用户管理已经接入真实接口
|
||||
- 管理员设置页已经接入真实配置接口
|
||||
- 侧边栏选中态 bug 已修复
|
||||
- 新前端色彩已收敛为更简洁的产品风格
|
||||
|
||||
## 当前代码扫描后的主要问题
|
||||
|
||||
### 后端
|
||||
|
||||
1. 数据库迁移体系仍然不完整
|
||||
2. `LLMService` 仍存在启动期副作用
|
||||
3. 文档解析任务仍依赖进程内后台任务
|
||||
4. 题库导入并发与去重约束还没彻底补完
|
||||
5. 管理模块还缺用户状态、审计、批量能力
|
||||
|
||||
### 前端
|
||||
|
||||
1. Exam detail / Question / Mistake / Quiz 仍是占位或半占位页面
|
||||
2. 部分页面仍有旧迁移骨架内容,需要继续清理
|
||||
3. 确认类交互还没统一替换为更正式的对话框方案
|
||||
4. 视觉层还需要统一列表、表单、状态、分页组件
|
||||
|
||||
### 部署与文档
|
||||
|
||||
1. Compose 仍缺 dev/prod 分离
|
||||
2. 文档体系仍需把运行方式统一到 SQLite 默认 + MySQL 兼容
|
||||
3. CI 只有主干镜像构建,还缺 PR 验证与 smoke test
|
||||
|
||||
## 后续执行顺序
|
||||
|
||||
### 第一阶段:后端稳定性
|
||||
|
||||
1. Alembic 基线迁移
|
||||
2. 去掉 `create_all` 正式职责
|
||||
3. 去掉 LLM import side effect
|
||||
4. 统一事务边界
|
||||
5. 补用户状态字段与审计日志模型
|
||||
|
||||
### 第二阶段:前端业务页
|
||||
|
||||
1. 接通 `exams/[examId]`
|
||||
2. 接通 `questions`
|
||||
3. 接通 `mistakes`
|
||||
4. 接通 `quiz/[examId]`
|
||||
5. 接通 `mistake-quiz`
|
||||
|
||||
### 第三阶段:用户管理产品化
|
||||
|
||||
1. 用户状态管理
|
||||
2. 审计日志
|
||||
3. 批量操作
|
||||
4. 更完整的密码与安全策略
|
||||
|
||||
### 第四阶段:工程化
|
||||
|
||||
1. Compose dev/prod 分离
|
||||
2. PR workflow
|
||||
3. SQLite/MySQL 双栈 smoke
|
||||
4. 文档统一
|
||||
|
||||
## 前端视觉要求
|
||||
|
||||
1. 主色:深蓝,作为动作与选中态
|
||||
2. 背景:浅灰蓝,不用大面积高饱和装饰
|
||||
3. 卡片:白底、细边框、轻阴影
|
||||
4. 状态色:成功绿、警告橙、错误红
|
||||
5. 页面信息结构:标题、数据、动作优先,减少解释文字
|
||||
92
docs/TASKS.md
Normal file
92
docs/TASKS.md
Normal file
@@ -0,0 +1,92 @@
|
||||
# QQuiz Task Checklist
|
||||
|
||||
更新时间:2026-04-17
|
||||
|
||||
## P0 运行基线
|
||||
|
||||
- [x] 默认 Docker 拓扑切回 SQLite
|
||||
- [x] 保留 MySQL 兼容 Compose 覆盖文件
|
||||
- [x] 前后端容器可启动并完成最小探活
|
||||
- [x] GitHub Actions 改成 push 后自动构建 backend/frontend 镜像
|
||||
- [ ] 补开发/生产分离 Compose
|
||||
- [ ] 补 PR 级别 build/smoke workflow
|
||||
- [ ] 清理根目录 Docker 文档漂移
|
||||
|
||||
## P1 后端稳定性
|
||||
|
||||
- [x] 管理员配置接口忽略打码后的密钥回写
|
||||
- [x] 用户列表返回改为强类型
|
||||
- [x] 用户列表统计去掉 N+1 查询
|
||||
- [x] 最后一个管理员保护
|
||||
- [x] 管理员密码重置接口
|
||||
- [ ] 去掉启动期 `create_all` 作为正式迁移方式
|
||||
- [ ] 建 Alembic 初始迁移
|
||||
- [ ] 去掉 `LLMService` import side effect
|
||||
- [ ] 收敛事务边界
|
||||
- [ ] 修 ingestion 并发与唯一约束
|
||||
- [ ] 规范健康检查和错误模型
|
||||
|
||||
## P2 用户管理
|
||||
|
||||
- [x] 用户搜索
|
||||
- [x] 创建用户
|
||||
- [x] 编辑用户
|
||||
- [x] 重置密码
|
||||
- [x] 删除用户
|
||||
- [ ] 用户状态字段(启用/禁用/锁定)
|
||||
- [ ] 审计日志
|
||||
- [ ] 批量操作
|
||||
- [ ] 密码强度与重置流程优化
|
||||
- [ ] 默认管理员保护策略文档化
|
||||
|
||||
## P3 新前端基础层
|
||||
|
||||
- [x] Next.js App Router 骨架
|
||||
- [x] BFF 登录/登出/`/me` 代理
|
||||
- [x] 同源 API 代理
|
||||
- [x] SSE 代理入口
|
||||
- [x] 移除旧前端 ESA 人机验证
|
||||
- [ ] 中间件与服务端守卫完善
|
||||
- [ ] 错误页/空状态统一
|
||||
- [ ] URL 状态策略统一
|
||||
|
||||
## P4 页面迁移
|
||||
|
||||
### 已接入真实数据
|
||||
|
||||
- [x] Dashboard
|
||||
- [x] Exams list
|
||||
- [x] Exam detail
|
||||
- [x] Questions list
|
||||
- [x] Mistakes list
|
||||
- [x] Quiz player
|
||||
- [x] Mistake quiz
|
||||
- [x] Admin user management
|
||||
- [x] Admin settings
|
||||
|
||||
### 待继续
|
||||
|
||||
- [ ] 上传/进度/失败重试链路
|
||||
|
||||
## P5 前端视觉与交互
|
||||
|
||||
- [x] 侧边栏选中态修复
|
||||
- [x] 新前端配色收敛为更简洁的产品风格
|
||||
- [x] 去掉大段迁移说明文案
|
||||
- [ ] 统一表格、表单、按钮、状态徽标
|
||||
- [ ] 清理页面中的占位内容
|
||||
- [ ] 替换 `window.confirm` 为统一对话框
|
||||
- [ ] 移动端布局细化
|
||||
|
||||
## P6 测试与验收
|
||||
|
||||
- [x] 旧前端构建通过
|
||||
- [x] 新前端构建通过
|
||||
- [x] Docker 最小登录链路验证
|
||||
- [x] 管理员配置、用户管理、上传解析、题目、错题、刷题链路验证
|
||||
- [x] 管理员与普通用户登录验证
|
||||
- [x] PowerShell smoke 脚本固化全流程验证
|
||||
- [ ] 后端集成测试
|
||||
- [ ] 前端 E2E 烟测
|
||||
- [ ] SQLite / MySQL 双栈验证
|
||||
- [ ] 用户管理回归用例
|
||||
70
docs/audit/architecture.md
Normal file
70
docs/audit/architecture.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# QQuiz Architecture Audit
|
||||
|
||||
## Scope
|
||||
|
||||
This document records the current system shape and the approved target
|
||||
direction for the ongoing refactor.
|
||||
|
||||
Audit date: 2026-04-17
|
||||
|
||||
## Current Architecture
|
||||
|
||||
### Backend
|
||||
|
||||
- Runtime: FastAPI + SQLAlchemy async
|
||||
- Database access: direct ORM session injection per request
|
||||
- Task execution: in-process `BackgroundTasks`
|
||||
- Progress streaming: in-memory `ProgressService`
|
||||
- Schema management: mixed `create_all()` and Alembic placeholders
|
||||
|
||||
### Frontend
|
||||
|
||||
- Runtime: React 18 + Vite SPA
|
||||
- Routing: `react-router-dom`
|
||||
- Auth state: client-only `localStorage` token + context
|
||||
- API transport: axios interceptor with browser redirects
|
||||
- Styling: Tailwind CSS with page-local utility classes
|
||||
|
||||
### Deployment
|
||||
|
||||
- `docker-compose.yml`: development-oriented split stack
|
||||
- `docker-compose-single.yml`: monolith container with SQLite
|
||||
- `Dockerfile`: FastAPI serves the built SPA as static assets
|
||||
|
||||
## Target Architecture
|
||||
|
||||
### Backend
|
||||
|
||||
- Keep FastAPI as the system API boundary
|
||||
- Move heavy router logic into typed services
|
||||
- Use Alembic as the only schema migration path
|
||||
- Introduce durable ingestion execution semantics
|
||||
- Replace implicit transaction patterns with explicit service-level boundaries
|
||||
|
||||
### Frontend
|
||||
|
||||
- New app in `web/`
|
||||
- Stack: Next.js App Router + TypeScript + Tailwind + shadcn/ui
|
||||
- Auth: `HttpOnly` session cookie mediated by Next route handlers
|
||||
- Data fetching: `fetch` wrappers for server/client usage
|
||||
- Streaming: Next proxy route for exam progress SSE
|
||||
|
||||
### Deployment
|
||||
|
||||
- Split deployment becomes the primary production shape
|
||||
- Monolith mode remains secondary compatibility mode
|
||||
- Development and production Compose files must be separated
|
||||
|
||||
## Core Constraints
|
||||
|
||||
1. Do not overwrite existing uncommitted user changes in the legacy frontend.
|
||||
2. Keep the legacy `frontend/` app available until the new `web/` app reaches functional parity.
|
||||
3. Preserve backend API contracts where possible during the frontend migration.
|
||||
4. Fix deployment/documentation drift before treating new frontend work as production-ready.
|
||||
|
||||
## Immediate Workstreams
|
||||
|
||||
1. Remove abandoned ESA captcha wiring from the legacy frontend.
|
||||
2. Write audit documents and freeze the migration backlog.
|
||||
3. Scaffold the new `web/` frontend without disturbing the legacy app.
|
||||
4. Fix first-order deployment issues such as health checks and documented mount paths.
|
||||
86
docs/audit/backend-findings.md
Normal file
86
docs/audit/backend-findings.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Backend Findings
|
||||
|
||||
## Critical Findings
|
||||
|
||||
### Schema lifecycle is unsafe
|
||||
|
||||
- App startup still calls `create_all()`
|
||||
- Alembic metadata exists but the migration chain is effectively empty
|
||||
- This prevents controlled upgrades and rollbacks
|
||||
|
||||
Files:
|
||||
|
||||
- `backend/main.py`
|
||||
- `backend/database.py`
|
||||
- `backend/alembic/versions/.gitkeep`
|
||||
|
||||
### Parsing tasks are not durable
|
||||
|
||||
- Document ingestion runs inside FastAPI `BackgroundTasks`
|
||||
- Progress state lives in-process only
|
||||
- Process restarts or horizontal scaling can strand exams in `pending` or `processing`
|
||||
|
||||
Files:
|
||||
|
||||
- `backend/routers/exam.py`
|
||||
- `backend/services/progress_service.py`
|
||||
|
||||
### Transaction boundaries are inconsistent
|
||||
|
||||
- `get_db()` performs commit/rollback automatically
|
||||
- Routers and background tasks also call `commit()` directly
|
||||
- SSE endpoints keep a database dependency open for long-lived streams
|
||||
|
||||
Files:
|
||||
|
||||
- `backend/database.py`
|
||||
- `backend/routers/exam.py`
|
||||
|
||||
## High-Priority Bugs
|
||||
|
||||
### Admin config can destroy secrets
|
||||
|
||||
- `GET /api/admin/config` masks API keys
|
||||
- `PUT /api/admin/config` persists whatever the frontend sends back
|
||||
- A round-trip save can replace the real secret with the masked placeholder
|
||||
|
||||
Files:
|
||||
|
||||
- `backend/routers/admin.py`
|
||||
|
||||
### LLM service has import-time side effects
|
||||
|
||||
- `LLMService()` is instantiated at module import time
|
||||
- Missing environment variables can break startup before DB-backed config is loaded
|
||||
|
||||
Files:
|
||||
|
||||
- `backend/services/llm_service.py`
|
||||
|
||||
### Ingestion deduplication is race-prone
|
||||
|
||||
- No unique DB constraint on `(exam_id, content_hash)`
|
||||
- Multiple append operations can race and insert duplicates
|
||||
|
||||
Files:
|
||||
|
||||
- `backend/models.py`
|
||||
- `backend/routers/exam.py`
|
||||
|
||||
### Answer checking degrades incorrectly on infra failure
|
||||
|
||||
- Short-answer grading failures are converted into zero scores
|
||||
- User mistake data can be polluted by provider outages or config errors
|
||||
|
||||
Files:
|
||||
|
||||
- `backend/services/llm_service.py`
|
||||
- `backend/routers/question.py`
|
||||
|
||||
## Refactor Order
|
||||
|
||||
1. Replace runtime schema creation with Alembic-first migrations.
|
||||
2. Move ingestion, config, and answer checking into service classes.
|
||||
3. Introduce explicit transaction boundaries and idempotent ingestion rules.
|
||||
4. Add durable task execution and real status/error semantics.
|
||||
5. Add integration tests for config round-trips, ingestion races, and answer normalization.
|
||||
49
docs/audit/deployment-findings.md
Normal file
49
docs/audit/deployment-findings.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Deployment Findings
|
||||
|
||||
## Current Problems
|
||||
|
||||
### Monolith persistence documentation is wrong
|
||||
|
||||
- Existing `docker run` examples mounted the wrong path
|
||||
- SQLite and upload persistence must target `/app/data` and `/app/uploads`
|
||||
|
||||
### Monolith health check was broken
|
||||
|
||||
- `docker-compose-single.yml` used `curl`
|
||||
- The image does not guarantee `curl` exists
|
||||
- The health check has been switched to Python stdlib HTTP probing
|
||||
|
||||
### Split Compose is development-oriented
|
||||
|
||||
- Source mounts are enabled
|
||||
- Backend runs with `uvicorn --reload`
|
||||
- Frontend runs a dev server
|
||||
- This is not a production deployment model
|
||||
|
||||
### Security posture is weak
|
||||
|
||||
- Compose contains hard-coded MySQL credentials
|
||||
- MySQL is exposed on `3306`
|
||||
- Environment guidance is inconsistent across README, Compose, and `.env.example`
|
||||
|
||||
## Approved Direction
|
||||
|
||||
1. Treat split deployment as the default production topology.
|
||||
2. Keep monolith deployment as a compatibility target only.
|
||||
3. Separate development assets from production assets.
|
||||
4. Validate all release images with smoke checks before publishing.
|
||||
|
||||
## Backlog
|
||||
|
||||
### Short term
|
||||
|
||||
- Create `compose.dev.yml` and `compose.prod.yml`
|
||||
- Remove dev-server assumptions from production documentation
|
||||
- Add backend runtime dependencies explicitly to image builds
|
||||
- Align README with actual mount paths and health checks
|
||||
|
||||
### Medium term
|
||||
|
||||
- Add PR build, typecheck, lint, and smoke-test workflows
|
||||
- Publish separate images for API and Next web app
|
||||
- Document rollback by image tag and Compose profile
|
||||
70
docs/audit/frontend-migration.md
Normal file
70
docs/audit/frontend-migration.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Frontend Migration Plan
|
||||
|
||||
## Decision
|
||||
|
||||
The legacy Vite SPA remains in `frontend/` as a fallback.
|
||||
|
||||
The new frontend is being built in `web/` with:
|
||||
|
||||
- Next.js App Router
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- shadcn/ui component model
|
||||
|
||||
The abandoned ESA captcha integration has been removed from the legacy login page.
|
||||
|
||||
## Why a Rewrite Instead of an In-Place Port
|
||||
|
||||
The legacy frontend mixes too many browser-only assumptions into core runtime
|
||||
boundaries:
|
||||
|
||||
- token storage in `localStorage`
|
||||
- `window.location` redirects inside transport code
|
||||
- client-only route protection
|
||||
- SSE token passing in query strings
|
||||
|
||||
Those patterns do not map cleanly onto Next App Router and server-first auth.
|
||||
|
||||
## New Runtime Model
|
||||
|
||||
### Auth
|
||||
|
||||
- Login goes through Next route handlers
|
||||
- Backend JWT is stored in an `HttpOnly` cookie
|
||||
- Browser code never reads the raw token
|
||||
|
||||
### Data
|
||||
|
||||
- Server pages use server-side fetch helpers
|
||||
- Client mutations use browser-side fetch helpers against Next proxy routes
|
||||
- URL state is used for pagination and filters
|
||||
|
||||
### Streaming
|
||||
|
||||
- Browser connects to a same-origin Next progress route
|
||||
- The route reads the session cookie and proxies backend SSE
|
||||
- Backend URL tokens are hidden from the browser
|
||||
|
||||
## Directory Map
|
||||
|
||||
```text
|
||||
web/
|
||||
src/app/
|
||||
src/components/
|
||||
src/lib/
|
||||
src/middleware.ts
|
||||
```
|
||||
|
||||
## Migration Order
|
||||
|
||||
1. Auth shell, layouts, middleware, and proxy routes
|
||||
2. Dashboard, exams list, questions list, and admin overview
|
||||
3. Exam detail upload and progress streaming
|
||||
4. Quiz and mistake-practice flows
|
||||
5. Cutover, smoke testing, and legacy frontend retirement
|
||||
|
||||
## Non-Goals for This First Slice
|
||||
|
||||
- No immediate removal of the legacy `frontend/`
|
||||
- No backend contract rewrite yet
|
||||
- No server actions as the primary data mutation layer
|
||||
BIN
docs/cover.png
Normal file
BIN
docs/cover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 371 KiB |
Reference in New Issue
Block a user