Backend: FastAPI + Async SQLAlchemy + SQLite (backend/jlpt_exam.db).
Frontend: React (Vite) + Tailwind trong frontend/.
| Công cụ | Ghi chú |
|---|---|
| Python | 3.11+ |
| Node.js + npm | Cho frontend |
| Windows | Script start_server.ps1 dùng PowerShell |
jlpt_exam/
├── backend/ # API, DB, script PDF → JSON → DB
│ ├── app/ # FastAPI, models, API routes
│ ├── data/ # PDF, JSON, audio (quan trọng khi chạy pipeline)
│ ├── jlpt_exam.db # SQLite (tạo sau khi chạy app hoặc import)
│ └── requirements.txt
└── frontend/ # UI Exam Viewer
DATABASE_URL trỏ tuyệt đối tới backend/jlpt_exam.db (xem backend/app/core/database.py).
Luôn làm việc trong thư mục backend/ khi cài package và chạy uvicorn (module app nằm ở đây).
cd backend
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txtMigration SQLite (an toàn, idempotent):
python migrate_sqlite.pyChạy server (port 8000):
# Cách 1: script có sẵn (giải phóng port 8000 nếu bị chiếm)
.\start_server.ps1
# Cách 2: tay
python -m uvicorn app.main:app --reload --host 127.0.0.1 --port 8000Kiểm tra: mở http://127.0.0.1:8000/ → JSON { "message": "..." }.
Docs: http://127.0.0.1:8000/docs.
API UI dùng:
GET /api/exams/available— danh sách(year, month)trong DBGET /api/exams?year=YYYY&month=MM— full exam (sections + questions)- Audio tĩnh:
GET /data/audio/...(mount từbackend/data/)
Đặt file:
- PDF:
backend/data/exams/exam_YYYY_MM.pdf(ví dụexam_2010_07.pdf,exam_2010_12.pdf) - Audio (listening):
backend/data/audio/YYYY/MM/hoặcbackend/data/audio/YYYY/
Tạo JSON + import DB (mặc định 2010–2024; --overwrite ghi đè exam đã có):
cd backend
python process_exam_pdfs.py --start 2010 --end 2024
# Chỉ tạo JSON, không import:
python process_exam_pdfs.py --start 2010 --end 2024 --no-import
# Ghi đè bản đã import:
python process_exam_pdfs.py --start 2010 --end 2010 --overwriteChỉ import từ JSON có sẵn:
python import_data.pyJSON output: backend/data/exam_YYYY_MM.json.
Terminal mới (backend vẫn chạy ở port 8000):
cd frontend
npm install
npm run devMở URL Vite in ra (thường http://localhost:5173).
vite.config.ts proxy /api và /data → http://localhost:8000 — không đổi port backend hay phải đổi CORS cho dev.
python/nodeđã cài.- Backend: venv →
pip install→migrate_sqlite.py→start_server.ps1. - (Có đủ PDF/audio) chạy
process_exam_pdfs.pyhoặcimport_data.py. - Frontend:
npm install→npm run dev→ chọn exam trong UI.
| Hiện tượng | Hướng xử lý |
|---|---|
ModuleNotFoundError: app |
Chạy uvicorn từ thư mục backend/, không phải root repo. |
| Port 8000 bị chiếm | Dùng start_server.ps1 hoặc Get-NetTCPConnection / taskkill theo PID. |
| UI không load exam / 404 API | Backend chưa chạy hoặc sai port; kiểm tra http://127.0.0.1:8000/docs. |
DB thiếu cột month / audio_path |
Chạy python migrate_sqlite.py trong backend/. |
Trong backend/:
python test_month_insert.py
python test_api_exams.pyTài liệu này ngắn gọn; chi tiết implementation nằm trong mã nguồn và comment trong các script.