Skip to content

Latest commit

 

History

History
196 lines (148 loc) · 5.77 KB

File metadata and controls

196 lines (148 loc) · 5.77 KB

筆記評分系統開發說明

本文件提供給維護者與開發者,說明專案架構、資料模型、關鍵流程與擴充建議。

1. 技術棧

  • Web Framework: FastAPI
  • Template Engine: Jinja2
  • ORM: SQLAlchemy 2.x
  • Database: SQLite(每週一個 DB)
  • Frontend: Server-rendered HTML + vanilla JS

依賴請見 requirements.txt

2. 專案結構

app.py                     # 應用入口,掛載路由與中介層
models.py                  # SQLAlchemy 模型 + 多週 DB/session 管理
utils.py                   # 檔案工具函式(副檔名、hash、size)
core/security.py           # CSRF token 注入/驗證
routers/
  admin.py                 # 管理端重置
  dashboard.py             # 儀表板(單週 / 跨週)
  imports.py               # 匯入入口
  grading.py               # 評分入口
  results.py               # 成績與覆寫、匯出
  files.py                 # 檔案下載與預覽
services/
  import_service.py        # 匯入核心邏輯
  grading_service.py       # 評分資料查詢 + upsert
  results_service.py       # 成績整併、覆寫、CSV 匯出
  dashboard_service.py     # 儀表板統計
  preview_service.py       # DOCX/MD/PPTX 預覽 HTML 生成
  staff_service.py         # 預設 TA/Professor 初始化
templates/                 # Jinja2 模板
uploads/                   # 上傳檔案(uploads/weekNN)
week_dbs/                  # SQLite(weekNN.db)

3. 應用啟動流程

app.py

  1. 建立 FastAPIJinja2Templates
  2. init_security(app, templates):啟用 CSRF middleware 與模板 helper
  3. 初始化 app state:
  • upload_folder = "uploads"
  • page_size = 50
  • default_rubric(由 DEFAULT_RUBRIC 解析)
  1. 掛載 static/uploads
  2. include routers
  3. startup 事件執行 init_db()(預設 week01)

4. 多週資料庫設計

4.1 核心概念

  • 每週獨立 SQLite:week_dbs/weekNN.db
  • 週次由 query 參數 ?week=weekNN 決定
  • normalize_week() 會將 1, week1, Week 01 正規化為 week01

4.2 Session 生命周期

  • 路由透過 Depends(get_db) 取得 session
  • get_db 會:
  1. normalize week
  2. ensure schema + staff 初始化(lazy)
  3. yield session
  4. finally close session

4.3 跨週查詢

dashboard_service.get_all_weeks_stats() 會遍歷 list_existing_weeks(),逐一開啟各週 session 彙整資料。

5. 資料模型摘要

models.py

  • Student(student_id, name)
  • Submission(student_id FK, filename, file_hash unique, file_path, file_type...)
  • TA(name unique)
  • Professor(name unique)
  • Grade(submission_id FK, ta_id FK, score, cr1..cr4, comments)
  • GradeOverride(submission_id unique FK, professor_id FK, final_score, reason)

重要約束:

  • Grade: (submission_id, ta_id) unique
  • Grade/GradeOverride 分數有 0~100 check constraint
  • GradeOverride: 每份 submission 最多一筆覆寫

6. 路由與職責

  • GET /:單週儀表板
  • GET /dashboard/all-weeks:跨週儀表板
  • GET/POST /import:匯入頁與上傳處理
  • GET/POST /grade:評分頁與提交
  • GET /results:成績頁
  • POST /override:教授覆寫
  • GET /export:匯出 CSV
  • GET /download/{submission_id}:檔案下載/inline
  • GET /preview/{submission_id}:預覽頁
  • POST /admin/reset:重置當週資料

7. 匯入流程細節

services/import_service.py

  1. 將 multipart 資料先寫入 temp dir
  2. 過濾非法路徑與不支援檔案
  3. 掃描候選檔案,計算 SHA256
  4. 以資料夾名/檔名推斷學號姓名
  5. 批次查既有 hash 與 student
  6. 複製檔案到 uploads/weekNN/
  7. 建立 Submission 記錄

注意:

  • 重複檔案判定依 file_hash
  • 同名檔案會自動加 _1, _2 避免覆蓋

8. 評分與覆寫邏輯

8.1 TA 評分

grading_service.upsert_grade

  • 若該 TA 已評該 submission -> update
  • 否則若該 submission 已有 >=2 筆 -> 拋錯拒絕
  • 否則新增新評分

8.2 最終成績

results_service.get_results_page_data

  • avg_score = 既有 TA score 平均
  • final_score = override.final_score(若存在)否則 avg_score

9. CSRF 安全機制

core/security.py

  • 模板 get_csrf_token(request) 注入 hidden input
  • middleware 確保 cookie csrf_token 存在
  • POST 行為呼叫 verify_csrf(request, submitted_token)

重點:

  • 表單需包含 csrf_token
  • JS fetch(例如 reset)需帶 X-CSRF-Token

10. 預覽機制

services/preview_service.py

  • DOCX: docx-preview 前端渲染
  • Markdown: marked + DOMPurify
  • PPTX: 目前回傳「下載原檔」提示頁

這段是純 HTML 字串組裝,若未來改成 API + SPA,可拆分為靜態資源與前端框架。

11. 本機開發指令

安裝:

pip install -r requirements.txt

啟動:

python app.py

快速語法檢查:

python -m compileall app.py routers services core models.py utils.py

12. 測試建議

目前專案未包含完整自動化測試,建議補上:

  • 匯入流程(副檔名過濾、hash 去重、學號姓名解析)
  • 週次隔離(同 submission 跨週不互相污染)
  • TA 評分上限(每 submission 最多 2 位)
  • 覆寫優先權(final score 覆蓋平均分)
  • CSRF 驗證(缺 token/不一致 token)

建議使用 pytest + httpx/TestClient

13. 擴充方向

  • 增加身份驗證與角色權限(TA/Professor/Admin)
  • 將 staff 初始化改成可配置資料來源(DB migration 或 seed script)
  • 增加 migration 工具(Alembic)
  • 支援 S3/物件儲存,避免本地檔案依賴
  • dashboard_service 增加聚合查詢優化

14. 已知限制

  • SQLite 適合單機/中小規模,不適合高併發
  • secure=False cookie 設定僅適用本機開發,正式環境需 HTTPS + secure cookie
  • preview_service 使用外部 CDN(需網路)