from flask import Blueprint, request, jsonify, session from app.models import db, StudentGoal, StudentGoalEvaluation, Goal from app.routes.auth import login_required_json from datetime import datetime, timedelta student_goals_bp = Blueprint("student_goals", __name__) @student_goals_bp.route("/api/students//goals", methods=["GET"]) @login_required_json def get_student_goals(student_id): records = StudentGoal.query.filter_by(student_id=student_id).all() # 同步状态并排序 for r in records: r.sync_status() def sort_key(r): status_order = {"进行中": 1, "未开始": 2, "已过期": 3, "已完成": 4} order = status_order.get(r.status, 5) assessment = r.assessment_date if r.assessment_date else datetime.min return (order, -assessment.timestamp() if assessment else 0) records.sort(key=sort_key) return jsonify([r.to_dict() for r in records]) @student_goals_bp.route("/api/students//goals", methods=["POST"]) @login_required_json def assign_goal(student_id): data = request.get_json() # 检查目标是否存在 goal = Goal.query.get(data["goal_id"]) if not goal: return jsonify({"error": "目标不存在"}), 404 # 检查是否已分配 existing = StudentGoal.query.filter_by(student_id=student_id, goal_id=data["goal_id"]).first() if existing: return jsonify({"error": "目标已分配"}), 400 # 处理评估日期 assessment_date = None if data.get("assessment_date"): # 直接指定日期 assessment_date = datetime.fromisoformat(data["assessment_date"]) elif data.get("assessment_days"): # 指定天数后 assessment_date = datetime.now() + timedelta(days=int(data["assessment_days"])) # 处理开始日期 start_date = None if data.get("start_date"): start_date = datetime.fromisoformat(data["start_date"]) # 如果没有指定开始日期,默认为当前时间 elif data.get("start_now"): start_date = datetime.now() record = StudentGoal( student_id=student_id, goal_id=data["goal_id"], start_date=start_date, assessment_date=assessment_date ) db.session.add(record) db.session.commit() return jsonify(record.to_dict()), 201 @student_goals_bp.route("/api/students//goals/", methods=["PUT"]) @login_required_json def update_student_goal(student_id, goal_id): record = StudentGoal.query.filter_by(student_id=student_id, goal_id=goal_id).first_or_404() data = request.get_json() # 评估操作 if "mastery_level" in data or "comment" in data: is_final = data.get("is_final", False) assessment_date = datetime.now() if data.get("assessment_date"): assessment_date = datetime.fromisoformat(data["assessment_date"]) # 如果提供了 evaluation_id,则是更新现有评估记录 if data.get("evaluation_id"): evaluation = StudentGoalEvaluation.query.get(data["evaluation_id"]) if evaluation and evaluation.student_goal_id == record.id: evaluation.mastery_level = data["mastery_level"] evaluation.comment = data.get("comment") evaluation.is_final = is_final evaluation.updated_at = datetime.now() # 如果是最终评估,同步到 StudentGoal if is_final: record.achievement_date = assessment_date record.mastery_level = data["mastery_level"] record.comment = data.get("comment") record.sync_status() else: # 创建新评估记录 evaluation = StudentGoalEvaluation( student_goal_id=record.id, evaluator_id=None, assessment_date=assessment_date, mastery_level=data["mastery_level"], comment=data.get("comment"), is_final=is_final ) db.session.add(evaluation) # 如果是最终评估,同步到 StudentGoal if is_final: record.achievement_date = assessment_date record.mastery_level = data["mastery_level"] record.comment = data.get("comment") record.sync_status() else: # 调整操作:只更新日期 if "start_date" in data: if data["start_date"]: record.start_date = datetime.fromisoformat(data["start_date"]) else: record.start_date = None if "assessment_date" in data: if data["assessment_date"]: record.assessment_date = datetime.fromisoformat(data["assessment_date"]) else: record.assessment_date = None record.sync_status() db.session.commit() return jsonify(record.to_dict()) @student_goals_bp.route("/api/students//goals/", methods=["DELETE"]) @login_required_json def remove_student_goal(student_id, goal_id): """移除学员的目标分配(仅管理员)""" from app.models import User user = User.query.get(session.get("user_id")) if not user or user.role != "admin": return jsonify({"error": "权限不足,仅管理员可操作"}), 403 record = StudentGoal.query.filter_by(student_id=student_id, goal_id=goal_id).first_or_404() # 先删除关联的评估记录 StudentGoalEvaluation.query.filter_by(student_goal_id=record.id).delete() db.session.delete(record) db.session.commit() return jsonify({"message": "移除成功"}) @student_goals_bp.route("/api/evaluations/", methods=["DELETE"]) @login_required_json def delete_evaluation(evaluation_id): """删除评估记录""" evaluation = StudentGoalEvaluation.query.get_or_404(evaluation_id) db.session.delete(evaluation) db.session.commit() return jsonify({"message": "删除成功"}) @student_goals_bp.route("/api/students//evaluations", methods=["GET"]) @login_required_json def get_student_evaluations(student_id): """获取学员所有目标的所有评估记录""" evaluations = StudentGoalEvaluation.query.join(StudentGoal).filter( StudentGoal.student_id == student_id ).order_by(StudentGoalEvaluation.assessment_date.desc()).all() # 补充目标信息 result = [] for e in evaluations: d = e.to_dict() # 获取关联的目标信息 sg = StudentGoal.query.get(e.student_goal_id) if sg: d["goal_name"] = sg.goal.name if sg.goal else None d["goal_level"] = sg.goal.level if sg.goal else None d["student_goal_id"] = sg.id d["student_goal_goal_id"] = sg.goal_id d["goal_start_date"] = sg.start_date.isoformat() if sg.start_date else None d["goal_assessment_date"] = sg.assessment_date.isoformat() if sg.assessment_date else None result.append(d) return jsonify(result)