Update app.py

main
pagfcvmb9 2 months ago
parent 2d1881ff41
commit bfc640118e

268
app.py

@ -1,95 +1,175 @@
from flask import Flask, render_template, request, jsonify, send_file
from services import RollCallService, ScoreService
import io
app = Flask(__name__)
roll_call_service = RollCallService()
score_service = ScoreService()
@app.route('/')
def index():
"""主页面"""
return render_template('index.html')
@app.route('/roll_call')
def roll_call_page():
"""点名页面"""
return render_template('roll_call.html')
@app.route('/scores')
def scores_page():
"""积分页面"""
return render_template('scores.html')
# API接口
@app.route('/api/roll_call/random', methods=['POST'])
def random_roll_call():
"""随机点名API"""
class_name = request.json.get('class_name', '软工K班')
student = roll_call_service.random_roll_call(class_name)
if student:
return jsonify({
'success': True,
'data': student.to_dict()
})
else:
return jsonify({
'success': False,
'message': '没有找到学生'
})
@app.route('/api/scores/update', methods=['POST'])
def update_score():
"""更新积分API"""
data = request.json
student_id = data.get('student_id')
answer_type = data.get('answer_type')
performance = data.get('performance')
success, score_delta = roll_call_service.update_student_score(
student_id, answer_type, performance
)
return jsonify({
'success': success,
'score_delta': score_delta
})
@app.route('/api/scores/ranking')
def get_ranking():
"""获取积分排名API"""
class_name = request.args.get('class_name', '软工K班')
ranking = score_service.get_class_ranking(class_name)
return jsonify({
'success': True,
'data': [student.to_dict() for student in ranking]
})
@app.route('/api/scores/export')
def export_scores():
"""导出积分Excel API"""
class_name = request.args.get('class_name', '软工K班')
excel_data = score_service.export_scores_excel(class_name)
return send_file(
excel_data,
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
as_attachment=True,
download_name=f'{class_name}_积分统计.xlsx'
)
@app.route('/api/roll_call/history')
def get_roll_call_history():
"""获取点名历史API"""
db = roll_call_service.db
recent_records = db.get_recent_records(10)
return jsonify({
'success': True,
'data': recent_records
})
if __name__ == '__main__':
from flask import Flask, render_template, request, jsonify, send_file, redirect, url_for, flash
from services import RollCallService, ScoreService
import io
from models import init_db, get_db, Student # 新增导入
import pandas as pd # 新增导入
# 初始化数据库(首次运行创建表)
init_db()
app = Flask(__name__)
app.secret_key = 'your_secret_key' # 用于flash提示
roll_call_service = RollCallService()
score_service = ScoreService()
# 首页
@app.route('/')
def index():
return render_template('index.html')
# 点名页面(支持选择模式)
@app.route('/roll_call')
def roll_call_page():
return render_template('roll_call.html')
# 积分页面(含可视化)
@app.route('/scores')
def scores_page():
class_name = request.args.get('class_name', '软工K班')
chart_base64 = score_service.generate_score_chart(class_name)
return render_template('scores.html', chart_base64=chart_base64, class_name=class_name)
# 新增Excel导入页面
@app.route('/import')
def import_page():
return render_template('import.html')
# APIExcel导入学生 - 修复版本
@app.route('/api/students/import', methods=['POST'])
def import_students(): # 移除嵌套的函数定义
try:
# 检查文件是否存在
if 'excel_file' not in request.files:
return jsonify({'success': False, 'message': '未选择文件'})
file = request.files['excel_file']
# 检查文件名
if file.filename == '':
return jsonify({'success': False, 'message': '未选择文件'})
# 检查文件格式
if not (file.filename.endswith('.xlsx') or file.filename.endswith('.xls')):
return jsonify({'success': False, 'message': '只支持 .xlsx 或 .xls 格式'})
# 读取Excel文件
df = pd.read_excel(file)
required_columns = ['学号', '姓名']
missing_columns = [col for col in required_columns if col not in df.columns]
if missing_columns:
return jsonify({
'success': False,
'message': f'缺少必要列: {", ".join(missing_columns)}'
})
# 检查数据是否为空
if df.empty:
return jsonify({'success': False, 'message': 'Excel文件为空'})
# 数据验证
for index, row in df.iterrows():
if pd.isna(row['学号']) or pd.isna(row['姓名']):
return jsonify({
'success': False,
'message': f'{index + 2}行数据不完整'
})
# 获取数据库会话
db = next(get_db())
# 保存到数据库
students_imported = 0
for index, row in df.iterrows():
# 检查学生是否已存在
existing_student = db.query(Student).filter_by(student_id=str(row['学号'])).first()
if not existing_student:
# 简化:只需要学号和姓名,其他字段使用默认值
student = Student(
student_id=str(row['学号']),
name=row['姓名'],
major='软件工程', # 默认专业
class_name='软工K班', # 默认班级
total_score=0,
call_count=0
)
db.add(student)
students_imported += 1
else:
# 如果学生已存在,更新姓名
existing_student.name = row['姓名']
db.commit()
db.close()
return jsonify({
'success': True,
'message': f'成功导入 {students_imported} 名学生数据'
})
except Exception as e:
# 错误处理
db.rollback()
db.close()
return jsonify({
'success': False,
'message': f'导入失败: {str(e)}'
})
# API点名支持random/order模式
@app.route('/api/roll_call', methods=['POST'])
def roll_call():
data = request.json
class_name = data.get('class_name', '软工K班')
call_mode = data.get('call_mode', 'random') # 新增模式参数
student, msg = roll_call_service.roll_call(class_name, call_mode)
if student:
return jsonify({'success': True, 'data': student.to_dict()})
return jsonify({'success': False, 'message': msg})
# 其他原有API保持不变仅更新积分更新接口
@app.route('/api/scores/update', methods=['POST'])
def update_score():
data = request.json
student_id = data.get('student_id')
answer_type = data.get('answer_type')
performance = data.get('performance')
status = data.get('status', 'present') # 新增到场状态
success, score_delta = roll_call_service.update_student_score(student_id, answer_type, performance, status)
return jsonify({'success': success, 'score_delta': score_delta})
# 新增导出积分详单API复用原有路由内部逻辑已更新
@app.route('/api/scores/export_detailed')
def export_detailed_scores():
class_name = request.args.get('class_name', '软工K班')
excel_data = score_service.export_scores_excel(class_name)
return send_file(
excel_data,
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
as_attachment=True,
download_name=f'{class_name}_积分详单.xlsx'
)
@app.route('/api/scores/ranking')
def get_class_ranking():
class_name = request.args.get('class_name', '软工K班')
students = score_service.get_class_ranking(class_name)
return jsonify({
'success': True,
'data': [s.to_dict() for s in students]
})
if __name__ == '__main__':
app.run(debug=True, port=5000)
Loading…
Cancel
Save