diff --git a/app.py b/app.py index ffa10cf..b0c883f 100644 --- a/app.py +++ b/app.py @@ -409,7 +409,7 @@ def api_contest_edit(contest_id): is_owner = (membership and membership.role == 'owner') or user.get('role') == 'admin' if not is_owner: return jsonify({'success': False, 'message': '没有权限'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) if data.get('description') is not None: contest.description = data['description'] if data.get('organizer') is not None: @@ -692,7 +692,7 @@ def api_user_friends(): @login_required def api_add_friend(): user_id = session['user']['id'] - data = request.get_json() + data = request.get_json(force=True, silent=True) friend_id = data.get('friend_id') if not friend_id or friend_id == user_id: return jsonify({'success': False, 'message': '无效的好友ID'}), 400 @@ -893,7 +893,7 @@ def api_change_name(): if datetime.utcnow() - user.name_changed_at < timedelta(days=30): remaining = 30 - (datetime.utcnow() - user.name_changed_at).days return jsonify({'success': False, 'message': f'每月仅可修改一次用户名,还需等待{remaining}天'}), 400 - data = request.get_json() + data = request.get_json(force=True, silent=True) new_name = data.get('name', '').strip() if not new_name or len(new_name) > 80: return jsonify({'success': False, 'message': '用户名不能为空且不超过80字符'}), 400 @@ -1159,7 +1159,7 @@ def api_system_notifications(): @admin_required def api_create_system_notification(): """管理员发布系统公告""" - data = request.get_json() or {} + data = request.get_json(force=True, silent=True) or {} title = (data.get('title') or '').strip() content = (data.get('content') or '').strip() if not title or not content: @@ -1183,7 +1183,7 @@ def api_create_system_notification(): def api_update_system_notification(sn_id): """管理员修改系统公告""" sn = SystemNotification.query.get_or_404(sn_id) - data = request.get_json() or {} + data = request.get_json(force=True, silent=True) or {} if 'title' in data: sn.title = data['title'].strip() if 'content' in data: @@ -1221,7 +1221,7 @@ def api_admin_search_users(): @app.route('/api/admin/send-private-notification', methods=['POST']) @admin_required def api_admin_send_private_notification(): - data = request.get_json() + data = request.get_json(force=True, silent=True) user_ids = data.get('user_ids', []) content = data.get('content', '').strip() if not user_ids or not content: @@ -1523,7 +1523,7 @@ def reject_teacher_application(app_id): def api_activate_invite_code(): """老师输入邀请码激活教师身份""" user = session['user'] - data = request.get_json() or {} + data = request.get_json(force=True, silent=True) or {} code_str = (data.get('code') or '').strip() if not code_str: return jsonify({'success': False, 'message': '请输入邀请码'}), 400 @@ -1585,7 +1585,7 @@ def api_captcha(): @app.route('/api/send-email-code', methods=['POST']) def api_send_email_code(): global captcha_store, email_codes - data = request.get_json() + data = request.get_json(force=True, silent=True) email = data.get('email', '') captcha_id = data.get('captchaId', '') captcha_text = data.get('captchaText', '') @@ -1623,7 +1623,7 @@ def api_send_email_code(): def api_register(): """邮箱注册(需绑定手机号)""" global email_codes - data = request.get_json() + data = request.get_json(force=True, silent=True) name = data.get('name', '') email = data.get('email', '') phone = data.get('phone', '') @@ -1667,7 +1667,7 @@ def api_register(): @app.route('/api/register-mobile', methods=['POST']) def api_register_mobile(): """手机号注册""" - data = request.get_json() + data = request.get_json(force=True, silent=True) name = data.get('name', '') phone = data.get('phone', '') password = data.get('password', '') @@ -1737,7 +1737,7 @@ def api_login(): @app.route('/api/send-sms', methods=['POST']) def api_send_sms(): global captcha_store - data = request.get_json() + data = request.get_json(force=True, silent=True) phone = data.get('phone', '') captcha_id = data.get('captchaId', '') captcha_text = data.get('captchaText', '') @@ -1795,7 +1795,7 @@ def api_send_sms(): @app.route('/api/verify-code', methods=['POST']) def api_verify_code(): - data = request.get_json() + data = request.get_json(force=True, silent=True) phone = data.get('phone', '') code = data.get('code', '') @@ -2278,7 +2278,7 @@ def api_create_exam(): user = session.get('user') if not user: return jsonify({'success': False, 'message': '请先登录'}), 401 - data = request.get_json() + data = request.get_json(force=True, silent=True) contest_id = data.get('contest_id') # 杯赛考试:只有杯赛负责人或系统管理员可以创建 @@ -2360,7 +2360,7 @@ def api_verify_exam_password(exam_id): exam = Exam.query.get(exam_id) if not exam: return jsonify({'success': False, 'message': '考试不存在'}), 404 - data = request.get_json() + data = request.get_json(force=True, silent=True) password = data.get('password', '') if password == exam.access_password: session[f'exam_verified_{exam_id}'] = True @@ -2375,7 +2375,7 @@ def api_save_draft(exam_id): exam = Exam.query.get(exam_id) if not exam: return jsonify({'success': False, 'message': '试卷不存在'}), 404 - data = request.get_json() + data = request.get_json(force=True, silent=True) answers = data.get('answers', {}) draft = Draft.query.filter_by(exam_id=exam_id, user_id=user.get('id')).first() if not draft: @@ -2403,7 +2403,7 @@ def api_submit_exam(exam_id): return jsonify({'success': False, 'message': '考试已结束'}), 400 if Submission.query.filter_by(exam_id=exam_id, user_id=user.get('id')).first(): return jsonify({'success': False, 'message': '您已提交过该试卷'}), 400 - data = request.get_json() + data = request.get_json(force=True, silent=True) answers = data.get('answers', {}) score = 0 auto_graded = True @@ -2455,7 +2455,7 @@ def api_grade_submission(exam_id, sub_id): return jsonify({'success': False, 'message': '考试不存在'}), 404 if not can_grade_exam(user, exam): return jsonify({'success': False, 'message': '无权限'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) scores = data.get('scores', {}) total = sum(scores.values()) sub.score = total @@ -2479,7 +2479,7 @@ def api_update_exam_status(exam_id): return jsonify({'success': False, 'message': '试卷不存在'}), 404 if exam.creator_id != user.get('id'): return jsonify({'success': False, 'message': '只能修改自己创建的试卷'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) new_status = data.get('status', '') if new_status not in ('available', 'closed'): return jsonify({'success': False, 'message': '无效状态'}), 400 @@ -2595,7 +2595,7 @@ def api_import_exam_to_contest(contest_id): is_owner = (membership and membership.role == 'owner') or user.get('role') == 'admin' if not is_owner: return jsonify({'success': False, 'message': '无权操作'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) exam_id = data.get('exam_id') if not exam_id: return jsonify({'success': False, 'message': '请选择考试'}), 400 @@ -2620,7 +2620,7 @@ def api_remove_exam_from_contest(contest_id): is_owner = (membership and membership.role == 'owner') or user.get('role') == 'admin' if not is_owner: return jsonify({'success': False, 'message': '无权操作'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) exam_id = data.get('exam_id') exam = Exam.query.get(exam_id) if not exam or exam.contest_id != contest_id: @@ -2689,7 +2689,7 @@ def api_create_contest(): user = session.get('user') if not user: return jsonify({'success': False, 'message': '请先登录'}), 401 - data = request.get_json() + data = request.get_json(force=True, silent=True) contest = Contest( name=data.get('name'), organizer=data.get('organizer'), @@ -2749,7 +2749,7 @@ def api_add_question_bank(contest_id): membership = ContestMembership.query.filter_by(user_id=user['id'], contest_id=contest_id).first() if not membership and user.get('role') != 'admin': return jsonify({'success': False, 'message': '无权限'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) qtype = data.get('type', '') content = data.get('content', '') if not qtype or not content: @@ -2798,7 +2798,7 @@ def api_create_exam_from_bank(contest_id): membership = ContestMembership.query.filter_by(user_id=user['id'], contest_id=contest_id, role='owner').first() if not membership and user.get('role') != 'admin': return jsonify({'success': False, 'message': '只有杯赛负责人才能组卷'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) title = data.get('title', '') duration = data.get('duration', 120) question_ids = data.get('question_ids', []) @@ -2956,7 +2956,7 @@ def api_create_contest_post(contest_id): if not can_post_in_contest(user, contest): return jsonify({'success': False, 'message': '您没有权限在此杯赛讨论区发帖'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) title = data.get('title', '').strip() content = data.get('content', '').strip() if not title or not content: @@ -3033,7 +3033,7 @@ def api_create_post(): user = session.get('user') if not user: return jsonify({'success': False, 'message': '请先登录'}), 401 - data = request.get_json() + data = request.get_json(force=True, silent=True) title = data.get('title', '').strip() content = data.get('content', '').strip() tag = data.get('tag', '全部') @@ -3175,7 +3175,7 @@ def api_create_reply(post_id): post = Post.query.get(post_id) if not post: return jsonify({'success': False, 'message': '帖子不存在'}), 404 - data = request.get_json() + data = request.get_json(force=True, silent=True) content = data.get('content', '').strip() if not content: return jsonify({'success': False, 'message': '回复内容不能为空'}), 400 @@ -3266,7 +3266,7 @@ def api_edit_post(post_id): return jsonify({'success': False, 'message': '帖子不存在'}), 404 if post.author_id != user.get('id') and user.get('role') not in ('teacher', 'admin'): return jsonify({'success': False, 'message': '无权编辑'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) new_title = data.get('title', '').strip() new_content = data.get('content', '').strip() new_tag = data.get('tag', post.tag) @@ -3288,7 +3288,7 @@ def api_edit_reply(reply_id): return jsonify({'success': False, 'message': '回复不存在'}), 404 if reply.author_id != user.get('id'): return jsonify({'success': False, 'message': '无权编辑'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) new_content = data.get('content', '').strip() if not new_content: return jsonify({'success': False, 'message': '内容不能为空'}), 400 @@ -3308,7 +3308,7 @@ def api_create_poll(post_id): return jsonify({'success': False, 'message': '只有作者可以创建投票'}), 403 if post.poll: return jsonify({'success': False, 'message': '该帖子已有投票'}), 400 - data = request.get_json() + data = request.get_json(force=True, silent=True) question = data.get('question', '').strip() options = data.get('options', []) multi = data.get('multi', False) @@ -3338,7 +3338,7 @@ def api_vote_poll(post_id): voters = poll.get_voters() if str(uid) in voters: return jsonify({'success': False, 'message': '您已投过票'}), 400 - data = request.get_json() + data = request.get_json(force=True, silent=True) choices = data.get('choices', []) if not choices: return jsonify({'success': False, 'message': '请选择选项'}), 400 @@ -3388,7 +3388,7 @@ def api_report(): user = session.get('user') if not user: return jsonify({'success': False, 'message': '请先登录'}), 401 - data = request.get_json() + data = request.get_json(force=True, silent=True) rtype = data.get('type', '') target_id = data.get('target_id', 0) reason = data.get('reason', '') @@ -3414,7 +3414,7 @@ def api_react_post(post_id): post = Post.query.get(post_id) if not post: return jsonify({'success': False, 'message': '帖子不存在'}), 404 - data = request.get_json() + data = request.get_json(force=True, silent=True) reaction_type = data.get('reaction', '') if reaction_type not in ('like', 'love', 'haha', 'wow', 'sad', 'angry'): return jsonify({'success': False, 'message': '无效反应'}), 400 @@ -3548,7 +3548,7 @@ def api_create_post_with_poll(): user = session.get('user') if not user: return jsonify({'success': False, 'message': '请先登录'}), 401 - data = request.get_json() + data = request.get_json(force=True, silent=True) title = data.get('title', '').strip() content = data.get('content', '').strip() tag = data.get('tag', '全部') @@ -3640,7 +3640,7 @@ def api_chat_rooms(): def api_create_chat_room(): """创建群聊""" user_id = session['user']['id'] - data = request.get_json() + data = request.get_json(force=True, silent=True) name = data.get('name', '').strip() member_ids = data.get('member_ids', []) if not name: @@ -3668,7 +3668,7 @@ def api_update_chat_room(room_id): member = ChatRoomMember.query.filter_by(room_id=room_id, user_id=user_id).first() if not member or member.role != 'admin': return jsonify({'success': False, 'message': '无权限'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) if 'name' in data: room.name = data['name'] if 'avatar' in data: @@ -3780,7 +3780,7 @@ def api_invite_chat_members(room_id): member = ChatRoomMember.query.filter_by(room_id=room_id, user_id=user_id).first() if not member: return jsonify({'success': False, 'message': '您不是该聊天室成员'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) user_ids = data.get('user_ids', []) added = [] for uid in user_ids: @@ -3977,7 +3977,7 @@ def api_set_announcement(room_id): if not member or member.role != 'admin': return jsonify({'success': False, 'message': '无权限'}), 403 room = ChatRoom.query.get_or_404(room_id) - data = request.get_json() + data = request.get_json(force=True, silent=True) room.announcement = data.get('content', '').strip() room.announcement_by = user_id room.announcement_at = datetime.utcnow() @@ -4106,7 +4106,7 @@ def api_set_nickname(room_id): member = ChatRoomMember.query.filter_by(room_id=room_id, user_id=user_id).first() if not member: return jsonify({'success': False, 'message': '您不是该聊天室成员'}), 403 - data = request.get_json() + data = request.get_json(force=True, silent=True) member.nickname = data.get('nickname', '').strip()[:50] db.session.commit() return jsonify({'success': True}) @@ -4116,7 +4116,7 @@ def api_set_nickname(room_id): def api_toggle_reaction(msg_id): """添加/取消表情回应""" user_id = session['user']['id'] - data = request.get_json() + data = request.get_json(force=True, silent=True) emoji = data.get('emoji', '') if not emoji: return jsonify({'success': False, 'message': '请选择表情'}), 400 @@ -4229,7 +4229,7 @@ def admin_contests_api(): } for c in contests] return jsonify({'success': True, 'contests': data}) elif request.method == 'POST': - data = request.get_json() + data = request.get_json(force=True, silent=True) contest = Contest( name=data['name'], organizer=data['organizer'], @@ -4259,7 +4259,7 @@ def admin_contest_detail(contest_id): 'status': contest.status }}) elif request.method == 'PUT': - data = request.get_json() + data = request.get_json(force=True, silent=True) contest.name = data.get('name', contest.name) contest.organizer = data.get('organizer', contest.organizer) contest.start_date = data.get('start_date', contest.start_date) @@ -4384,7 +4384,7 @@ def admin_update_exam_status(exam_id): exam = Exam.query.get(exam_id) if not exam: return jsonify({'success': False, 'message': '考试不存在'}) - data = request.get_json() + data = request.get_json(force=True, silent=True) exam.status = data.get('status', exam.status) db.session.commit() return jsonify({'success': True})