# 班级管理路由 from flask import request, jsonify, render_template, session from app.routes import main_bp from app.models import db, Class, Student from app.routes.auth import login_required_json, admin_required import logging logger = logging.getLogger(__name__) @main_bp.route("/classes") @login_required_json def classes_page(): """班级管理页面""" return render_template("classes.html", active_nav="classes") @main_bp.route("/api/classes", methods=["GET"]) @login_required_json def api_classes_list(): """班级列表""" # 支持筛选参数: active=true, active=false, 不传则返回全部 active_filter = request.args.get("active") query = Class.query if active_filter is not None: if active_filter.lower() == "true": query = query.filter(Class.active == True) elif active_filter.lower() == "false": query = query.filter(Class.active == False) classes = query.order_by(Class.created_at.desc()).all() return jsonify([c.to_dict() for c in classes]) @main_bp.route("/api/classes", methods=["POST"]) @admin_required def api_classes_create(): """新增班级""" data = request.get_json() name = data.get("name", "").strip() description = data.get("description", "") active = data.get("active", True) # 默认进行中 if not name: return jsonify({"error": "请输入班级名称", "code": "VALIDATION_ERROR"}), 400 if Class.query.filter_by(name=name).first(): return jsonify({"error": "班级名称已存在", "code": "DUPLICATE_NAME"}), 400 try: cls = Class(name=name, description=description, active=active) db.session.add(cls) db.session.commit() return jsonify(cls.to_dict()) except Exception as e: db.session.rollback() logger.error(f"创建班级失败: {str(e)}") return jsonify({"error": "操作失败,请稍后重试", "code": "SERVER_ERROR"}), 500 @main_bp.route("/api/classes/", methods=["PUT"]) @admin_required def api_classes_update(class_id): """编辑班级""" cls = Class.query.get_or_404(class_id) data = request.get_json() if "name" in data and data["name"]: # 检查名称是否与其他班级冲突 existing = Class.query.filter_by(name=data["name"]).first() if existing and existing.id != class_id: return jsonify({"error": "班级名称已存在", "code": "DUPLICATE_NAME"}), 400 cls.name = data["name"] if "description" in data: cls.description = data["description"] if "active" in data: cls.active = data["active"] try: db.session.commit() return jsonify(cls.to_dict()) except Exception as e: db.session.rollback() logger.error(f"更新班级失败: {str(e)}") return jsonify({"error": "操作失败,请稍后重试", "code": "SERVER_ERROR"}), 500 @main_bp.route("/api/classes/", methods=["DELETE"]) @admin_required def api_classes_delete(class_id): """删除班级(不删除学员,仅解除关联)""" cls = Class.query.get_or_404(class_id) try: # 解除学员与班级的关联 Student.query.filter_by(class_id=class_id).update({"class_id": None}) db.session.delete(cls) db.session.commit() return jsonify({"message": "删除成功"}) except Exception as e: db.session.rollback() logger.error(f"删除班级失败: {str(e)}") return jsonify({"error": "操作失败,请稍后重试", "code": "SERVER_ERROR"}), 500 @main_bp.route("/api/classes//students", methods=["GET"]) @login_required_json def api_classes_students(class_id): """班级学员列表""" cls = Class.query.get_or_404(class_id) # 直接查询而非使用relationship students = Student.query.filter_by(class_id=class_id).all() return jsonify( [ { "id": s.id, "name": s.name, "phone": s.phone, "practice_time": s.practice_time, } for s in students ] ) @main_bp.route("/api/classes//assign", methods=["POST"]) @login_required_json def api_classes_assign(class_id): """分配学员到班级""" cls = Class.query.get_or_404(class_id) data = request.get_json() student_ids = data.get("student_ids", []) try: # 1. 先清除这个班级的所有学员关联 Student.query.filter_by(class_id=class_id).update({"class_id": None}) # 2. 再分配选中的学员到这个班级 if student_ids: Student.query.filter(Student.id.in_(student_ids)).update( {"class_id": class_id} ) db.session.commit() return jsonify({"message": "分配成功"}) except Exception as e: db.session.rollback() logger.error(f"分配学员失败: {str(e)}") return jsonify({"error": "操作失败,请稍后重试", "code": "SERVER_ERROR"}), 500