from flask_sqlalchemy import SQLAlchemy from werkzeug.security import generate_password_hash, check_password_hash from datetime import datetime import bcrypt db = SQLAlchemy() class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(50), unique=True, nullable=False) password_hash = db.Column(db.String(255), nullable=False) email = db.Column(db.String(100), unique=True, nullable=False) uid = db.Column(db.String(50)) # 站点UID role = db.Column(db.String(20), default='user') # admin/user status = db.Column(db.String(20), default='pending') # pending/active/disabled tags = db.Column(db.String(200)) # 用户标签,逗号分隔 note = db.Column(db.Text) # 管理员备注 created_at = db.Column(db.DateTime, default=datetime.utcnow) approved_at = db.Column(db.DateTime) # 审核通过时间 approved_by = db.Column(db.Integer, db.ForeignKey('users.id')) # 审核人 def set_password(self, password): self.password_hash = generate_password_hash(password, method='pbkdf2:sha256') def check_password(self, password): return check_password_hash(self.password_hash, password) class Group(db.Model): __tablename__ = 'groups' id = db.Column(db.Integer, primary_key=True) group_name = db.Column(db.String(50), nullable=False) group_key = db.Column(db.String(50), unique=True, nullable=False) description = db.Column(db.Text) status = db.Column(db.String(20), default='active') created_at = db.Column(db.DateTime, default=datetime.utcnow) class UserGroup(db.Model): __tablename__ = 'user_groups' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) group_id = db.Column(db.Integer, db.ForeignKey('groups.id'), nullable=False) is_admin = db.Column(db.Boolean, default=False) # 是否为组管理员 join_date = db.Column(db.DateTime, default=datetime.utcnow) user = db.relationship('User', backref='user_groups') group = db.relationship('Group', backref='user_groups') class Task(db.Model): __tablename__ = 'tasks' id = db.Column(db.Integer, primary_key=True) group_id = db.Column(db.Integer, db.ForeignKey('groups.id'), nullable=False) # 发布组特定字段 series_name = db.Column(db.String(200), nullable=False) series_link = db.Column(db.String(500)) series_date = db.Column(db.Date, nullable=False) priority = db.Column(db.String(20)) # 高/中/低 # 流程字段 status = db.Column(db.String(20), default='pending') # pending/claimed/completed/cancelled claimed_by = db.Column(db.Integer, db.ForeignKey('users.id')) claimed_at = db.Column(db.DateTime) claim_note = db.Column(db.Text) torrent_id = db.Column(db.String(100)) complete_note = db.Column(db.Text) completed_at = db.Column(db.DateTime) created_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) # 关系 group = db.relationship('Group', backref='tasks') claimer = db.relationship('User', foreign_keys=[claimed_by], backref='claimed_tasks') creator = db.relationship('User', foreign_keys=[created_by], backref='created_tasks') class TaskLog(db.Model): __tablename__ = 'task_logs' id = db.Column(db.Integer, primary_key=True) task_id = db.Column(db.Integer, db.ForeignKey('tasks.id'), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) action = db.Column(db.String(50), nullable=False) # create/claim/complete/cancel comment = db.Column(db.Text) created_at = db.Column(db.DateTime, default=datetime.utcnow) task = db.relationship('Task', backref='logs') user = db.relationship('User', backref='task_logs')