|
|
from flask import Flask, jsonify, render_template, request |
|
|
import pandas as pd |
|
|
import re |
|
|
from datetime import datetime, timedelta |
|
|
|
|
|
app = Flask(__name__) |
|
|
|
|
|
|
|
|
grade_files = { |
|
|
"22级": r"./数据表/22级.xlsx", |
|
|
"23级": r"./数据表/23级.xlsx", |
|
|
"24级": r"./数据表/24级.xlsx", |
|
|
} |
|
|
|
|
|
student_file_path = r"./数据表/区队-学号-姓名-1.xlsx" |
|
|
student_data = pd.read_excel(student_file_path) |
|
|
|
|
|
teacher_files = { |
|
|
"2024-2025学年第一学期": r"./数据表/教学安排表20241125112641.xlsx", |
|
|
} |
|
|
|
|
|
|
|
|
grade_dataframes = {} |
|
|
for grade, file_path in grade_files.items(): |
|
|
df = pd.read_excel(file_path) |
|
|
df["grade"] = grade |
|
|
grade_dataframes[grade] = df |
|
|
|
|
|
grade_data = pd.concat(grade_dataframes.values(), ignore_index=True) |
|
|
|
|
|
|
|
|
teacher_dataframes = {} |
|
|
for semester, file_path in teacher_files.items(): |
|
|
df = pd.read_excel(file_path) |
|
|
df["学年学期"] = semester |
|
|
teacher_dataframes[semester] = df |
|
|
|
|
|
teacher_data = pd.concat(teacher_dataframes.values(), ignore_index=True) |
|
|
|
|
|
|
|
|
first_week_start_date = datetime(2024, 9, 2) |
|
|
|
|
|
|
|
|
|
|
|
def parse_weeks(weeks_str): |
|
|
if not weeks_str or pd.isna(weeks_str): |
|
|
return set() |
|
|
weeks = set() |
|
|
for part in weeks_str.split(","): |
|
|
try: |
|
|
if "-" in part: |
|
|
start, end = map(int, part.split("-")) |
|
|
weeks.update(range(start, end + 1)) |
|
|
else: |
|
|
weeks.add(int(part)) |
|
|
except ValueError: |
|
|
print(f"跳过无效周次: {part}") |
|
|
continue |
|
|
return weeks |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_day_and_period(period_str): |
|
|
if not period_str or pd.isna(period_str): |
|
|
return None |
|
|
try: |
|
|
day_match = re.search(r"[一二三四五六日]", period_str) |
|
|
period_match = re.search(r"\[(\d+)-(\d+)节\]", period_str) |
|
|
|
|
|
if day_match and period_match: |
|
|
day = "一二三四五六日".index(day_match.group()) + 1 |
|
|
start, end = map(int, period_match.groups()) |
|
|
periods = list(range(start, end + 1)) |
|
|
return day, periods |
|
|
except Exception as e: |
|
|
print(f"解析失败: {period_str}, 错误: {e}") |
|
|
return None |
|
|
|
|
|
|
|
|
def calculate_date(week, day): |
|
|
days_from_start = (week - 1) * 7 + (day - 1) |
|
|
return first_week_start_date + timedelta(days=days_from_start) |
|
|
|
|
|
@app.route("/") |
|
|
def index(): |
|
|
return render_template("index.html") |
|
|
@app.route("/teachers") |
|
|
def teacher_page(): |
|
|
return render_template("teacher.html") |
|
|
|
|
|
@app.route("/api/student_courses") |
|
|
def get_student_courses(): |
|
|
week = request.args.get("week", 1) |
|
|
grade = request.args.get("grade", None) |
|
|
admin_class = request.args.get("admin_class", None) |
|
|
|
|
|
|
|
|
filtered_data = grade_data |
|
|
if grade: |
|
|
filtered_data = filtered_data[filtered_data["grade"] == grade] |
|
|
if admin_class: |
|
|
filtered_data = filtered_data[filtered_data["行政班级"].str.contains(admin_class, na=False)] |
|
|
|
|
|
|
|
|
filtered_data = filtered_data[filtered_data["课程类别"].str.contains("必修课", na=False)] |
|
|
|
|
|
if week: |
|
|
week = int(week) |
|
|
filtered_data = filtered_data[ |
|
|
filtered_data["周次"].apply(lambda x: week in parse_weeks(x) if pd.notna(x) else False) |
|
|
] |
|
|
|
|
|
|
|
|
results = [] |
|
|
for _, row in filtered_data.iterrows(): |
|
|
day_and_period = parse_day_and_period(row["节次"]) |
|
|
if day_and_period: |
|
|
day, periods = day_and_period |
|
|
course_date = calculate_date(week, day) |
|
|
results.append({ |
|
|
"课程": row["课程"].split("]")[1] if "]" in row["课程"] else row["课程"], |
|
|
"教师": row["教师"], |
|
|
"地点": row["地点"].split("(")[0] if "(" in row["地点"] else row["地点"], |
|
|
"星期": day, |
|
|
"日期": course_date.strftime("%Y-%m-%d"), |
|
|
"节次": periods, |
|
|
"节次范围": f"第{periods[0]}-{periods[-1]}节", |
|
|
"周次": row["周次"] |
|
|
}) |
|
|
|
|
|
|
|
|
results = sorted(results, key=lambda x: (x["星期"], x["节次"][0])) |
|
|
return jsonify(results) |
|
|
|
|
|
@app.route("/api/classes") |
|
|
def get_classes(): |
|
|
classes = grade_data["行政班级"].dropna().unique().tolist() |
|
|
return jsonify(sorted(classes)) |
|
|
|
|
|
|
|
|
@app.route("/api/teachers") |
|
|
def get_teachers(): |
|
|
teachers = teacher_data["教师"].dropna().unique().tolist() |
|
|
return jsonify(sorted(teachers)) |
|
|
|
|
|
@app.route("/api/teacher_courses") |
|
|
def get_courses_by_teacher(): |
|
|
week = request.args.get("week", 1) |
|
|
teacher = request.args.get("teacher", None) |
|
|
|
|
|
|
|
|
filtered_data = teacher_data |
|
|
if teacher: |
|
|
filtered_data = filtered_data[filtered_data["教师"] == teacher] |
|
|
if week: |
|
|
week = int(week) |
|
|
filtered_data = filtered_data[filtered_data["周次"].apply(lambda x: week in parse_weeks(x) if pd.notna(x) else False)] |
|
|
|
|
|
|
|
|
results = [] |
|
|
for _, row in filtered_data.iterrows(): |
|
|
day_and_period = parse_day_and_period(row["节次"]) |
|
|
if day_and_period: |
|
|
day, periods = day_and_period |
|
|
course_date = calculate_date(week, day) |
|
|
results.append({ |
|
|
"课程": row["课程"].split("]")[1] if "]" in row["课程"] else row["课程"], |
|
|
"教师": row["教师"], |
|
|
"地点": row["地点"].split("(")[0] if "(" in row["地点"] else row["地点"], |
|
|
"星期": day, |
|
|
"日期": course_date.strftime("%Y-%m-%d"), |
|
|
"节次": periods, |
|
|
"节次范围": f"第{periods[0]}-{periods[-1]}节", |
|
|
"周次": row["周次"] |
|
|
}) |
|
|
|
|
|
|
|
|
results = sorted(results, key=lambda x: (x["星期"], x["节次"][0])) |
|
|
return jsonify(results) |
|
|
|
|
|
|
|
|
@app.route("/students") |
|
|
def student_page(): |
|
|
return render_template("student.html") |
|
|
|
|
|
@app.route("/api/students") |
|
|
def get_students(): |
|
|
students = student_data["姓名"].dropna().unique().tolist() |
|
|
return jsonify(sorted(students)) |
|
|
|
|
|
@app.route("/api/student_courses_v2") |
|
|
def get_student_courses_v2(): |
|
|
week = request.args.get("week", 1) |
|
|
student_name = request.args.get("student_name", "").strip() |
|
|
|
|
|
if not student_name: |
|
|
return jsonify({"error": "缺少学生姓名参数"}), 400 |
|
|
|
|
|
|
|
|
student_data_copy = student_data.copy() |
|
|
student_data_copy["区队"] = student_data_copy["区队"].str.extract(r"\](.*)$")[0].str.strip() |
|
|
|
|
|
|
|
|
matching_students = student_data_copy[student_data_copy["姓名"].str.contains(student_name, na=False)] |
|
|
if matching_students.empty: |
|
|
return jsonify({"error": "未找到匹配的学生信息"}), 404 |
|
|
|
|
|
|
|
|
admin_classes = matching_students["区队"].unique() |
|
|
|
|
|
|
|
|
filtered_data = grade_data[grade_data["行政班级"].isin(admin_classes)] |
|
|
|
|
|
|
|
|
filtered_data = filtered_data[filtered_data["课程类别"].str.contains("必修课", na=False)] |
|
|
|
|
|
|
|
|
if week: |
|
|
week = int(week) |
|
|
filtered_data = filtered_data[ |
|
|
filtered_data["周次"].apply(lambda x: week in parse_weeks(x) if pd.notna(x) else False) |
|
|
] |
|
|
|
|
|
if filtered_data.empty: |
|
|
return jsonify({"error": "未找到匹配的课程表"}), 404 |
|
|
|
|
|
|
|
|
results = [] |
|
|
for _, row in filtered_data.iterrows(): |
|
|
day_and_period = parse_day_and_period(row["节次"]) |
|
|
if day_and_period: |
|
|
day, periods = day_and_period |
|
|
course_date = calculate_date(week, day) |
|
|
results.append({ |
|
|
"课程": row["课程"].split("]")[1] if "]" in row["课程"] else row["课程"], |
|
|
"教师": row["教师"], |
|
|
"地点": row["地点"].split("(")[0] if "(" in row["地点"] else row["地点"], |
|
|
"星期": day, |
|
|
"日期": course_date.strftime("%Y-%m-%d"), |
|
|
"节次": periods, |
|
|
"节次范围": f"第{periods[0]}-{periods[-1]}节", |
|
|
"周次": row["周次"] |
|
|
}) |
|
|
|
|
|
|
|
|
results = sorted(results, key=lambda x: (x["星期"], x["节次"][0])) |
|
|
return jsonify(results) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
app.run(host="0.0.0.0", port=7860) |
|
|
|
|
|
|