from flask import Blueprint, jsonify, request from server.auth import login_required from server.db import get_db, now_iso typing_bp = Blueprint("typing", __name__) def row_to_dict(row): return dict(row) def to_int(value, default=0): try: return int(value) except (TypeError, ValueError): return default @typing_bp.get("/api/typing/logs") @login_required def list_typing_logs(user): conn = get_db() try: rows = conn.execute( """ SELECT id, mode, category_id, category_name, item_count, correct_keys, error_keys, accuracy, duration_seconds, created_at FROM typing_logs WHERE user_id = ? ORDER BY id DESC LIMIT 200 """, (user["id"],), ).fetchall() return jsonify([row_to_dict(r) for r in rows]) finally: conn.close() @typing_bp.post("/api/typing/logs") @login_required def create_typing_log(user): data = request.get_json(silent=True) or {} mode = (data.get("mode") or "").strip() if mode not in ("vocab", "phrases"): return jsonify({"error": "练习类型不正确"}), 400 item_count = to_int(data.get("itemCount")) correct_keys = to_int(data.get("correctKeys")) error_keys = to_int(data.get("errorKeys")) accuracy = to_int(data.get("accuracy")) duration_seconds = to_int(data.get("durationSeconds")) if item_count < 1: return jsonify({"error": "练习数量不正确"}), 400 if accuracy < 0 or accuracy > 100: return jsonify({"error": "正确率不正确"}), 400 if duration_seconds < 0: return jsonify({"error": "练习时长不正确"}), 400 conn = get_db() try: cur = conn.execute( """ INSERT INTO typing_logs ( user_id, mode, category_id, category_name, item_count, correct_keys, error_keys, accuracy, duration_seconds, created_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """, ( user["id"], mode, (data.get("categoryId") or "").strip(), (data.get("categoryName") or "").strip(), item_count, max(0, correct_keys), max(0, error_keys), accuracy, duration_seconds, now_iso(), ), ) conn.commit() row = conn.execute( """ SELECT id, mode, category_id, category_name, item_count, correct_keys, error_keys, accuracy, duration_seconds, created_at FROM typing_logs WHERE id = ? """, (cur.lastrowid,), ).fetchone() return jsonify(row_to_dict(row)), 201 finally: conn.close()