mobile . themes
This commit is contained in:
113
app.py
113
app.py
@@ -13,7 +13,7 @@ from functools import wraps
|
||||
|
||||
from flask import (
|
||||
Flask, render_template, request, jsonify, session,
|
||||
redirect, url_for, flash, abort, send_from_directory
|
||||
redirect, url_for, flash, abort, send_from_directory, send_file
|
||||
)
|
||||
from flask_caching import Cache
|
||||
from werkzeug.utils import secure_filename
|
||||
@@ -27,6 +27,7 @@ from openai import OpenAI as DashScopeClient
|
||||
# 引入数据库模型(添加 TeacherApplication)
|
||||
from models import db, User, Exam, Submission, Draft, Contest, ContestMembership, ContestApplication, Post, Reply, Poll, Report, Bookmark, Reaction, Notification, EditHistory, ContestRegistration, TeacherApplication, Friend, ExamBookmark, ChatRoom, ChatRoomMember, Message, MessageReaction, QuestionBankItem, InviteCode, SystemNotification
|
||||
from flask_socketio import SocketIO, emit, join_room as sio_join, leave_room as sio_leave
|
||||
from excel_export import export_users_to_excel, export_exams_to_excel, export_submissions_to_excel, export_contests_to_excel, export_posts_to_excel
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -2761,9 +2762,18 @@ def api_update_exam_visibility(exam_id):
|
||||
if new_visibility not in ('private', 'public'):
|
||||
return jsonify({'success': False, 'message': '无效的可见性设置'}), 400
|
||||
|
||||
# 检查权限:只有教师和管理员可以设置为公开
|
||||
if new_visibility == 'public' and user.get('role') not in ('teacher', 'admin'):
|
||||
return jsonify({'success': False, 'message': '只有教师和管理员可以创建公开考试'}), 403
|
||||
# 检查权限:教师、管理员、杯赛负责人和杯赛老师可以设置为公开
|
||||
if new_visibility == 'public':
|
||||
has_permission = user.get('role') in ('teacher', 'admin')
|
||||
# 如果是杯赛考试,检查是否为杯赛负责人或老师
|
||||
if not has_permission and exam.contest_id:
|
||||
membership = ContestMembership.query.filter_by(
|
||||
user_id=user['id'], contest_id=exam.contest_id).first()
|
||||
if membership and membership.role in ('owner', 'teacher'):
|
||||
has_permission = True
|
||||
|
||||
if not has_permission:
|
||||
return jsonify({'success': False, 'message': '只有教师、管理员或杯赛负责人/老师可以创建公开考试'}), 403
|
||||
|
||||
exam.visibility = new_visibility
|
||||
db.session.commit()
|
||||
@@ -3303,6 +3313,7 @@ def api_search_posts():
|
||||
'content': p.content[:200] + ('...' if len(p.content) > 200 else ''),
|
||||
'author': p.author.name,
|
||||
'author_id': p.author_id,
|
||||
'author_avatar': p.author.avatar or '',
|
||||
'author_level': author_level,
|
||||
'tag': p.tag,
|
||||
'is_official': p.is_official,
|
||||
@@ -3360,6 +3371,7 @@ def api_get_post(post_id):
|
||||
'content': post.content,
|
||||
'author': post.author.name,
|
||||
'author_id': post.author_id,
|
||||
'author_avatar': post.author.avatar or '',
|
||||
'tag': post.tag,
|
||||
'is_official': post.is_official,
|
||||
'pinned': post.pinned,
|
||||
@@ -3380,6 +3392,7 @@ def api_get_post(post_id):
|
||||
'content': r.content,
|
||||
'author': r.author.name,
|
||||
'author_id': r.author_id,
|
||||
'author_avatar': r.author.avatar or '',
|
||||
'likes': r.likes,
|
||||
'reply_to': r.reply_to,
|
||||
'created_at': r.created_at.strftime('%Y-%m-%d %H:%M'),
|
||||
@@ -4895,5 +4908,97 @@ with app.app_context():
|
||||
conn.commit()
|
||||
except Exception:
|
||||
pass
|
||||
# ========== Excel导出路由 ==========
|
||||
|
||||
@app.route('/admin/export/users')
|
||||
def admin_export_users():
|
||||
"""导出用户数据为Excel"""
|
||||
user = session.get('user')
|
||||
if not user or user['role'] != 'admin':
|
||||
return jsonify({'error': '无权限'}), 403
|
||||
|
||||
users = User.query.order_by(User.created_at.desc()).all()
|
||||
output = export_users_to_excel(users)
|
||||
|
||||
filename = f"用户数据_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=filename
|
||||
)
|
||||
|
||||
@app.route('/admin/export/exams')
|
||||
def admin_export_exams():
|
||||
"""导出考试数据为Excel"""
|
||||
user = session.get('user')
|
||||
if not user or user['role'] != 'admin':
|
||||
return jsonify({'error': '无权限'}), 403
|
||||
|
||||
exams = Exam.query.order_by(Exam.created_at.desc()).all()
|
||||
output = export_exams_to_excel(exams)
|
||||
|
||||
filename = f"考试数据_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=filename
|
||||
)
|
||||
|
||||
@app.route('/admin/export/submissions')
|
||||
def admin_export_submissions():
|
||||
"""导出提交记录为Excel"""
|
||||
user = session.get('user')
|
||||
if not user or user['role'] != 'admin':
|
||||
return jsonify({'error': '无权限'}), 403
|
||||
|
||||
submissions = Submission.query.order_by(Submission.submitted_at.desc()).all()
|
||||
output = export_submissions_to_excel(submissions)
|
||||
|
||||
filename = f"提交记录_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=filename
|
||||
)
|
||||
|
||||
@app.route('/admin/export/contests')
|
||||
def admin_export_contests():
|
||||
"""导出杯赛数据为Excel"""
|
||||
user = session.get('user')
|
||||
if not user or user['role'] != 'admin':
|
||||
return jsonify({'error': '无权限'}), 403
|
||||
|
||||
contests = Contest.query.order_by(Contest.created_at.desc()).all()
|
||||
output = export_contests_to_excel(contests)
|
||||
|
||||
filename = f"杯赛数据_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=filename
|
||||
)
|
||||
|
||||
@app.route('/admin/export/posts')
|
||||
def admin_export_posts():
|
||||
"""导出论坛帖子为Excel"""
|
||||
user = session.get('user')
|
||||
if not user or user['role'] != 'admin':
|
||||
return jsonify({'error': '无权限'}), 403
|
||||
|
||||
posts = Post.query.order_by(Post.created_at.desc()).all()
|
||||
output = export_posts_to_excel(posts)
|
||||
|
||||
filename = f"论坛帖子_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
|
||||
return send_file(
|
||||
output,
|
||||
mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
as_attachment=True,
|
||||
download_name=filename
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
socketio.run(app, debug=True,host='0.0.0.0', port=5080)
|
||||
Reference in New Issue
Block a user