mobile . themes

This commit is contained in:
2026-03-16 14:00:50 +08:00
parent 33763d279e
commit dd9609165c
6 changed files with 110 additions and 78 deletions

View File

@@ -1,6 +1,11 @@
# models.py
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from datetime import datetime, timezone, timedelta
_beijing_tz = timezone(timedelta(hours=8))
def beijing_now():
return datetime.now(_beijing_tz).replace(tzinfo=None)
import json
db = SQLAlchemy()
@@ -17,7 +22,7 @@ class User(db.Model):
is_banned = db.Column(db.Boolean, default=False)
completed_exams = db.Column(db.Integer, default=0) # 已完成并批改的考试次数
name_changed_at = db.Column(db.DateTime, nullable=True) # 上次修改用户名时间
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
# 关系
exams_created = db.relationship('Exam', back_populates='creator', lazy=True)
@@ -39,7 +44,7 @@ class ContestMembership(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
contest_id = db.Column(db.Integer, db.ForeignKey('contest.id'), nullable=False)
role = db.Column(db.String(20), nullable=False) # 'owner' 或 'teacher'
joined_at = db.Column(db.DateTime, default=datetime.utcnow)
joined_at = db.Column(db.DateTime, default=beijing_now)
user = db.relationship('User', back_populates='contest_memberships')
contest = db.relationship('Contest', back_populates='members')
@@ -55,7 +60,7 @@ class ContestApplication(db.Model):
description = db.Column(db.Text)
contact = db.Column(db.String(100))
status = db.Column(db.String(20), default='pending') # pending, approved, rejected
applied_at = db.Column(db.DateTime, default=datetime.utcnow)
applied_at = db.Column(db.DateTime, default=beijing_now)
reviewed_at = db.Column(db.DateTime)
total_score = db.Column(db.Integer, default=150) # 杯赛默认满分
start_date = db.Column(db.String(20)) # 申请时填写的开始日期
@@ -78,7 +83,7 @@ class ContestRegistration(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
contest_id = db.Column(db.Integer, db.ForeignKey('contest.id'), nullable=False)
registered_at = db.Column(db.DateTime, default=datetime.utcnow)
registered_at = db.Column(db.DateTime, default=beijing_now)
__table_args__ = (db.UniqueConstraint('user_id', 'contest_id', name='uq_user_contest_reg'),)
@@ -93,7 +98,7 @@ class Contest(db.Model):
status = db.Column(db.String(20), default='upcoming')
participants = db.Column(db.Integer, default=0)
created_by = db.Column(db.Integer, db.ForeignKey('user.id'))
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
past_papers = db.Column(db.Text) # JSON 存储历年真题 [{year, title, file}]
total_score = db.Column(db.Integer, default=150) # 杯赛默认考试满分
visible = db.Column(db.Boolean, default=True) # 是否对普通用户可见
@@ -125,7 +130,7 @@ class QuestionBankItem(db.Model):
options = db.Column(db.Text) # JSON选择题选项
answer = db.Column(db.Text) # 答案
score = db.Column(db.Integer, default=10) # 建议分值
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
contest = db.relationship('Contest', backref='question_bank_items')
contributor = db.relationship('User', backref='contributed_questions')
@@ -146,7 +151,7 @@ class Exam(db.Model):
scheduled_start = db.Column(db.DateTime, nullable=True) # 预定开始时间
scheduled_end = db.Column(db.DateTime, nullable=True) # 预定结束时间
score_release_time = db.Column(db.DateTime, nullable=True) # 成绩公布时间
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
status = db.Column(db.String(20), default='available')
visibility = db.Column(db.String(20), default='private') # 'private' 或 'public'
@@ -170,7 +175,7 @@ class Submission(db.Model):
question_scores = db.Column(db.Text) # JSON
graded = db.Column(db.Boolean, default=False)
graded_by = db.Column(db.String(80))
submitted_at = db.Column(db.DateTime, default=datetime.utcnow)
submitted_at = db.Column(db.DateTime, default=beijing_now)
exam = db.relationship('Exam', back_populates='submissions')
user = db.relationship('User', back_populates='submissions')
@@ -193,7 +198,7 @@ class Draft(db.Model):
exam_id = db.Column(db.Integer, db.ForeignKey('exam.id'))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
answers = db.Column(db.Text) # JSON
saved_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
saved_at = db.Column(db.DateTime, default=beijing_now, onupdate=beijing_now)
exam = db.relationship('Exam', back_populates='drafts')
user = db.relationship('User', back_populates='drafts')
@@ -219,8 +224,8 @@ class Post(db.Model):
has_poll = db.Column(db.Boolean, default=False)
images = db.Column(db.Text) # JSON
contest_id = db.Column(db.Integer, db.ForeignKey('contest.id'), nullable=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
updated_at = db.Column(db.DateTime, default=beijing_now, onupdate=beijing_now)
author = db.relationship('User', back_populates='posts')
replies = db.relationship('Reply', back_populates='post', lazy=True, cascade='all, delete-orphan')
@@ -243,8 +248,8 @@ class Reply(db.Model):
content = db.Column(db.Text, nullable=False)
likes = db.Column(db.Integer, default=0)
reply_to = db.Column(db.String(80))
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
updated_at = db.Column(db.DateTime, default=beijing_now, onupdate=beijing_now)
post = db.relationship('Post', back_populates='replies')
author = db.relationship('User', back_populates='replies')
@@ -259,7 +264,7 @@ class Poll(db.Model):
voters = db.Column(db.Text) # JSON
multi = db.Column(db.Boolean, default=False)
total_votes = db.Column(db.Integer, default=0)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
post = db.relationship('Post', back_populates='poll')
@@ -282,7 +287,7 @@ class Reaction(db.Model):
post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=True)
reply_id = db.Column(db.Integer, db.ForeignKey('reply.id'), nullable=True)
reaction = db.Column(db.String(20))
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
user = db.relationship('User', back_populates='reactions')
post = db.relationship('Post', back_populates='reactions')
@@ -298,7 +303,7 @@ class Bookmark(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
post_id = db.Column(db.Integer, db.ForeignKey('post.id'))
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
user = db.relationship('User', back_populates='bookmarks')
post = db.relationship('Post', back_populates='bookmarks')
@@ -314,7 +319,7 @@ class Report(db.Model):
reason = db.Column(db.String(100))
detail = db.Column(db.Text)
status = db.Column(db.String(20), default='pending')
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
# reporter 已在 User 中通过 backref 定义
@@ -327,7 +332,7 @@ class Notification(db.Model):
from_user = db.Column(db.String(80))
post_id = db.Column(db.Integer, nullable=True)
read = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
# user 已在 User 中通过 backref 定义
@@ -338,8 +343,8 @@ class SystemNotification(db.Model):
content = db.Column(db.Text, nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
pinned = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
updated_at = db.Column(db.DateTime, default=beijing_now, onupdate=beijing_now)
author = db.relationship('User', backref='system_notifications')
@@ -350,7 +355,7 @@ class EditHistory(db.Model):
title = db.Column(db.String(200))
content = db.Column(db.Text)
edited_by = db.Column(db.String(80))
edited_at = db.Column(db.DateTime, default=datetime.utcnow)
edited_at = db.Column(db.DateTime, default=beijing_now)
post = db.relationship('Post')
@@ -364,7 +369,7 @@ class TeacherApplication(db.Model):
email = db.Column(db.String(120), nullable=False) # 申请人邮箱
reason = db.Column(db.Text, nullable=False) # 申请理由
status = db.Column(db.String(20), default='pending') # pending, approved, rejected
applied_at = db.Column(db.DateTime, default=datetime.utcnow)
applied_at = db.Column(db.DateTime, default=beijing_now)
reviewed_at = db.Column(db.DateTime)
reviewed_by = db.Column(db.Integer, db.ForeignKey('user.id'))
# 拒绝次数控制
@@ -384,7 +389,7 @@ class Friend(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
friend_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
status = db.Column(db.String(20), default='pending') # pending, accepted
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
user = db.relationship('User', foreign_keys=[user_id], backref=db.backref('friends_initiated', lazy='dynamic'))
friend = db.relationship('User', foreign_keys=[friend_id], backref=db.backref('friends_received', lazy='dynamic'))
@@ -394,7 +399,7 @@ class ExamBookmark(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
exam_id = db.Column(db.Integer, db.ForeignKey('exam.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
user = db.relationship('User', backref=db.backref('exam_bookmarks', lazy='dynamic', cascade='all, delete-orphan'))
exam = db.relationship('Exam', backref=db.backref('bookmarked_by', lazy='dynamic', cascade='all, delete-orphan'))
@@ -412,7 +417,7 @@ class ChatRoom(db.Model):
announcement = db.Column(db.Text, default='')
announcement_by = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=True)
announcement_at = db.Column(db.DateTime, nullable=True)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
creator = db.relationship('User', foreign_keys=[creator_id], backref='chatrooms_created')
announcement_user = db.relationship('User', foreign_keys=[announcement_by])
@@ -428,8 +433,8 @@ class ChatRoomMember(db.Model):
role = db.Column(db.String(20), default='member') # 'admin' | 'member'
nickname = db.Column(db.String(50), default='')
muted = db.Column(db.Boolean, default=False)
last_read_at = db.Column(db.DateTime, default=datetime.utcnow)
joined_at = db.Column(db.DateTime, default=datetime.utcnow)
last_read_at = db.Column(db.DateTime, default=beijing_now)
joined_at = db.Column(db.DateTime, default=beijing_now)
user = db.relationship('User', backref='chat_memberships')
@@ -447,7 +452,7 @@ class Message(db.Model):
recalled = db.Column(db.Boolean, default=False)
reply_to_id = db.Column(db.Integer, db.ForeignKey('message.id'), nullable=True)
mentions = db.Column(db.Text, default='') # JSON array of user IDs, e.g. "[1,2,3]" or "all"
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
sender = db.relationship('User', backref='messages_sent')
reply_to = db.relationship('Message', remote_side='Message.id', backref='replies')
@@ -459,7 +464,7 @@ class MessageReaction(db.Model):
message_id = db.Column(db.Integer, db.ForeignKey('message.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
emoji = db.Column(db.String(10), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
user = db.relationship('User', backref='message_reactions')
@@ -472,7 +477,7 @@ class InviteCode(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
application_id = db.Column(db.Integer, db.ForeignKey('teacher_application.id'), nullable=False)
used = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
created_at = db.Column(db.DateTime, default=beijing_now)
used_at = db.Column(db.DateTime, nullable=True)
user = db.relationship('User', backref='invite_codes')