From f8e2a16c18275bde6bf891e0220d641d4da8c82f Mon Sep 17 00:00:00 2001 From: root Date: Tue, 19 May 2026 08:03:24 +0800 Subject: [PATCH] =?utf8?q?update:=20=E7=AB=A0=E8=8A=82=E9=A6=96=E9=A1=B5?= =?utf8?q?=E4=B8=BA=E7=A9=BA=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D=EF=BC=8C?= =?utf8?q?=E4=BD=86=E6=98=AF=E6=89=93=E5=BC=80=E5=90=8E=E7=AB=A0=E8=8A=82?= =?utf8?q?=E5=90=8D=E7=A7=B0=E4=BE=9D=E7=84=B6=E6=98=AF=E9=94=99=E8=AF=AF?= =?utf8?q?=E7=9A=84=EF=BC=9B=E7=9F=A5=E8=AF=86=E7=82=B9=E9=A6=96=E9=A1=B5?= =?utf8?q?=E7=9B=AE=E5=89=8D=E4=BE=9D=E7=84=B6=E6=98=BE=E7=A4=BA=E4=B8=BA?= =?utf8?q?=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- app.py | 174 ++++++++++++++++------- templates/subject/chapters.html | 165 ++++++++++++++++++++++ templates/subject/index.html | 231 +++++++++++++++++++++---------- templates/subject/knowledge.html | 64 +++++++++ 4 files changed, 512 insertions(+), 122 deletions(-) create mode 100644 templates/subject/chapters.html create mode 100644 templates/subject/knowledge.html diff --git a/app.py b/app.py index 00ce655..8c80782 100644 --- a/app.py +++ b/app.py @@ -3,61 +3,59 @@ from database import query_db app = Flask(__name__) -# 1. 首页 +# --- 1. 页面路由 --- + @app.route('/') def index(): return render_template('index.html') -# 2. 科目面板 (注意:路由加了斜杠,匹配你的访问日志) +# 科目首页 @app.route('/subject/') def subject_portal(): - try: - subjects = query_db("SELECT ID, Subject as name FROM Subject WHERE enabled = 1") - stages = query_db("SELECT ID, stage_name FROM stage WHERE enabled = 1 ORDER BY ID") - default_subject_id = subjects[0]['ID'] if subjects else None - return render_template('subject/index.html', - subjects=subjects, - stages=stages, - default_id=default_subject_id) - except Exception as e: - return f"数据库连接失败: {e}" + subjects = query_db("SELECT ID, Subject as name FROM Subject WHERE enabled = 1") + stages = query_db("SELECT ID, stage_name FROM stage WHERE enabled = 1 ORDER BY ID") + default_id = subjects[0]['ID'] if subjects else None + return render_template('subject/index.html', subjects=subjects, stages=stages, default_id=default_id) + +# 章节分析页 +@app.route('/subject/chapters') +def subject_chapters(): + subjects = query_db("SELECT DISTINCT Subject FROM Subject ORDER BY Subject") + return render_template('subject/chapters.html', subjects=subjects) + +# 知识点分析页 +@app.route('/subject/knowledge') +def subject_knowledge(): + subjects = query_db("SELECT DISTINCT Subject FROM Subject ORDER BY Subject") + chapter_id = request.args.get('chapter_id', '') + return render_template('subject/knowledge.html', subjects=subjects, chapter_id=chapter_id) -# 3. 题目管理 @app.route('/questions/') -def questions(): - return render_template('questions/index.html') +def questions(): return render_template('questions/index.html') -# 4. 试卷管理 @app.route('/papers/') -def papers(): - return render_template('papers/index.html') +def papers(): return render_template('papers/index.html') -# 5. 系统设定 @app.route('/settings/') -def settings(): - return render_template('settings/index.html') +def settings(): return render_template('settings/index.html') -# 6. API 接口 + +# --- 2. API 接口 --- + +# 科目概览统计 API @app.route('/api/subject_stats') def get_subject_stats(): sub_id = request.args.get('subject_id') stage_ids = request.args.get('stage_ids', '').split(',') - if not sub_id or not stage_ids or stage_ids == ['']: - return jsonify({"error": "未选中科目或阶段"}), 400 + return jsonify({"error": "参数错误"}), 400 - # 构造阶段过滤 SQL - stage_placeholders = ','.join(['?'] * len(stage_ids)) + placeholders = ','.join(['?'] * len(stage_ids)) - def get_count(q_type, extra_condition=""): - sql = f""" - SELECT COUNT(*) as count FROM questions - WHERE question_type = ? AND subject_id = ? - AND stage_id IN ({stage_placeholders}) {extra_condition} - """ - params = [q_type, sub_id] + stage_ids - res = query_db(sql, params, one=True) - return res['count'] if res else 0 + def get_count(q_type, extra=""): + sql = f"SELECT COUNT(*) as c FROM questions WHERE question_type=? AND subject_id=? AND stage_id IN ({placeholders}) {extra}" + res = query_db(sql, [q_type, sub_id] + stage_ids, one=True) + return res['c'] if res else 0 w_total = get_count('错题') w_fixed = get_count('错题', 'AND right_times > 0') @@ -65,20 +63,98 @@ def get_subject_stats(): p_fixed = get_count('推题', 'AND right_times > 0') return jsonify({ - "wrong": { - "total": w_total, - "fixed": w_fixed, - "ratio": f"{(w_fixed/w_total*100):.1f}%" if w_total > 0 else "0%", - "remained": w_total - w_fixed - }, - "push": { - "total": p_total, - "fixed": p_fixed, - "ratio": f"{(p_fixed/p_total*100):.1f}%" if p_total > 0 else "0%", - "remained": p_total - p_fixed - } + "wrong": {"total": w_total, "fixed": w_fixed, "ratio": f"{(w_fixed/w_total*100):.1f}%" if w_total>0 else "0%", "remained": w_total-w_fixed}, + "push": {"total": p_total, "fixed": p_fixed, "ratio": f"{(p_fixed/p_total*100):.1f}%" if p_total>0 else "0%", "remained": p_total-p_fixed} }) +# 章节数据 API (基于顶级知识点) +@app.route('/api/chapters') +def get_chapters(): + subject = request.args.get('subject', '全部') + keyword = request.args.get('keyword', '') + params = [] + + # 过滤 parent_id 为空作为章节 + where = " WHERE kp.parent_id IS NULL AND kp.is_enabled = 1" + if subject != '全部': + where += " AND s.Subject = ?" + params.append(subject) + if keyword: + where += " AND kp.content LIKE ?" + params.append(f"%{keyword}%") + + sql = f""" + SELECT + kp.id AS chapter_id, + s.Subject AS SubjectName, + kp.content AS ChapterDesc, + (SELECT COUNT(DISTINCT r.question_id) FROM question_kp_relation r WHERE r.kp_id = kp.id) AS total, + (SELECT COUNT(DISTINCT r.question_id) FROM question_kp_relation r + JOIN questions q ON r.question_id = q.id + WHERE r.kp_id = kp.id AND q.right_times > 0) AS correct + FROM knowledge_point kp + JOIN Subject s ON kp.subject_id = s.ID + {where} + """ + try: + rows = query_db(sql, params) + result = [] + for row in rows: + item = dict(row) # 必须转字典,Row 不支持赋值 + item['not_correct'] = (item['total'] or 0) - (item['correct'] or 0) + # 只要有题目就显示 + if item['total'] > 0: + result.append(item) + return jsonify(result) + except Exception as e: + print(f"SQL Error in chapters: {e}") + return jsonify({"error": str(e)}), 500 + +# 知识点数据 API +@app.route('/api/knowledge') +def get_knowledge(): + subject = request.args.get('subject', '全部') + keyword = request.args.get('keyword', '') + chapter_id = request.args.get('chapter_id', '') + params = [] + + where = " WHERE kp.is_enabled = 1" + if chapter_id: + # 如果有章节ID,查询该节点及其子节点 + where += " AND (kp.id = ? OR kp.parent_id = ?)" + params.extend([chapter_id, chapter_id]) + if subject != '全部': + where += " AND s.Subject = ?" + params.append(subject) + if keyword: + where += " AND kp.content LIKE ?" + params.append(f"%{keyword}%") + + sql = f""" + SELECT + kp.id, + s.Subject as subject_name, + kp.content, + (SELECT COUNT(*) FROM question_kp_relation r WHERE r.kp_id = kp.id) as total, + (SELECT COUNT(DISTINCT r.question_id) FROM question_kp_relation r + JOIN questions q ON r.question_id = q.id + WHERE r.kp_id = kp.id AND q.right_times >= 1) as correct + FROM knowledge_point kp + JOIN Subject s ON kp.subject_id = s.ID + {where} + """ + try: + rows = query_db(sql, params) + result = [] + for row in rows: + item = dict(row) + item['not_correct'] = (item['total'] or 0) - (item['correct'] or 0) + result.append(item) + return jsonify(result) + except Exception as e: + print(f"SQL Error in knowledge: {e}") + return jsonify({"error": str(e)}), 500 + if __name__ == '__main__': - # 开启 debug=True,这样报错会有详细提示 - app.run(host='0.0.0.0', port=5000, debug=True, threaded=True) + # 确保在服务器上运行时监听 0.0.0.0 + app.run(host='0.0.0.0', port=5000, debug=True) diff --git a/templates/subject/chapters.html b/templates/subject/chapters.html new file mode 100644 index 0000000..b7d5cba --- /dev/null +++ b/templates/subject/chapters.html @@ -0,0 +1,165 @@ + + + + + + 章节分析 + + + + + + +
+ +
+ + + +
+ + +
+ + + + + + + + + + + + + + +
科目章节名称错题总数尚未正确
正在加载数据...
+
+ +
+ 返回科目首页 +
+
+ + + + diff --git a/templates/subject/index.html b/templates/subject/index.html index 0b4c63a..8ec125e 100644 --- a/templates/subject/index.html +++ b/templates/subject/index.html @@ -1,119 +1,204 @@ - + - + 科目概要面板 - + - - + + + -
- -
-
- - {% for sub in subjects %} {% endfor %}
-
- -
- {% for stage in stages %} - - {% endfor %} + + +
+ {% for stage in stages %} +
+ {{ stage.stage_name }}
+ {% endfor %}
- +
-
-
错题情况回顾
-
错题总数0
-
已解决数0
-
- 解决比例 - 0% -
-
遗留题目数0
+
+

错题情况回顾

+ 0% +
总数0
+
已解决0
+
遗留0
-
-
强化推题追踪
-
推题总数0
-
已完成数0
-
- 完成比例 - 0% -
-
遗留题目数0
+
+

强化推题追踪

+ 0% +
总数0
+
已完成0
+
遗留0
+ + + +
diff --git a/templates/subject/knowledge.html b/templates/subject/knowledge.html new file mode 100644 index 0000000..80dc95b --- /dev/null +++ b/templates/subject/knowledge.html @@ -0,0 +1,64 @@ + + + + + + 知识点分析 + + + + +
+
+ + + +
+ + + + + + + + + + + +
科目知识点内容总题数待完成
+ 返回科目首页 +
+ + + + -- 2.43.0