from datetime import datetime, timedelta from flask_sqlalchemy import SQLAlchemy from werkzeug.security import generate_password_hash, check_password_hash import secrets import string from extensions import db # db = SQLAlchemy() # Moved to extensions.py class User(db.Model): """用户模型""" __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(120), unique=True, nullable=False, index=True) password_hash = db.Column(db.String(255), nullable=False) username = db.Column(db.String(80)) balance = db.Column(db.Float, default=0.0) # 账户余额 is_active = db.Column(db.Boolean, default=True) is_admin = 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) # 关系 orders = db.relationship('Order', backref='user', lazy='dynamic', cascade='all, delete-orphan') api_calls = db.relationship('ApiCall', backref='user', lazy='dynamic', cascade='all, delete-orphan') transactions = db.relationship('Transaction', backref='user', lazy='dynamic', cascade='all, delete-orphan') api_keys = db.relationship('APIKey', backref='user', lazy='dynamic', cascade='all, delete-orphan') verification_codes = db.relationship('VerificationCode', backref='user', lazy='dynamic', cascade='all, delete-orphan') # 验证状态 email_verified = db.Column(db.Boolean, default=False) email_verified_at = db.Column(db.DateTime) def set_password(self, password): """设置密码""" self.password_hash = generate_password_hash(password) def check_password(self, password): """验证密码""" return check_password_hash(self.password_hash, password) def to_dict(self): """转换为字典""" return { 'id': self.id, 'email': self.email, 'username': self.username, 'balance': self.balance, 'is_active': self.is_active, 'is_admin': self.is_admin, 'created_at': self.created_at.isoformat(), 'updated_at': self.updated_at.isoformat() } class Order(db.Model): """订单模型""" __tablename__ = 'orders' id = db.Column(db.Integer, primary_key=True) order_no = db.Column(db.String(50), unique=True, nullable=False, index=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) amount = db.Column(db.Float, nullable=False) # 充值金额 payment_method = db.Column(db.String(20)) # wechat, alipay status = db.Column(db.String(20), default='pending') # pending, paid, cancelled, failed transaction_id = db.Column(db.String(100)) # 第三方交易ID created_at = db.Column(db.DateTime, default=datetime.utcnow) paid_at = db.Column(db.DateTime) def to_dict(self): """转换为字典""" return { 'id': self.id, 'order_no': self.order_no, 'user_id': self.user_id, 'amount': self.amount, 'payment_method': self.payment_method, 'status': self.status, 'transaction_id': self.transaction_id, 'created_at': self.created_at.isoformat(), 'paid_at': self.paid_at.isoformat() if self.paid_at else None } class Transaction(db.Model): """交易记录模型""" __tablename__ = 'transactions' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) type = db.Column(db.String(20), nullable=False) # recharge, consume, refund amount = db.Column(db.Float, nullable=False) balance_before = db.Column(db.Float, nullable=False) balance_after = db.Column(db.Float, nullable=False) description = db.Column(db.String(255)) order_id = db.Column(db.Integer, db.ForeignKey('orders.id')) api_call_id = db.Column(db.Integer, db.ForeignKey('api_calls.id')) created_at = db.Column(db.DateTime, default=datetime.utcnow) def to_dict(self): """转换为字典""" return { 'id': self.id, 'user_id': self.user_id, 'type': self.type, 'amount': self.amount, 'balance_before': self.balance_before, 'balance_after': self.balance_after, 'description': self.description, 'order_id': self.order_id, 'api_call_id': self.api_call_id, 'created_at': self.created_at.isoformat() } class ApiCall(db.Model): """API调用记录模型""" __tablename__ = 'api_calls' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) api_type = db.Column(db.String(50), default='text_to_image') # text_to_image prompt = db.Column(db.Text) parameters = db.Column(db.Text) # JSON格式的参数 status = db.Column(db.String(20), default='pending') # pending, processing, success, failed result_url = db.Column(db.String(500)) # 生成结果的URL cost = db.Column(db.Float, default=0.0) # 本次调用费用 error_message = db.Column(db.Text) request_time = db.Column(db.DateTime, default=datetime.utcnow) response_time = db.Column(db.DateTime) created_at = db.Column(db.DateTime, default=datetime.utcnow) def to_dict(self): """转换为字典""" return { 'id': self.id, 'user_id': self.user_id, 'api_type': self.api_type, 'prompt': self.prompt, 'status': self.status, 'result_url': self.result_url, 'cost': self.cost, 'error_message': self.error_message, 'request_time': self.request_time.isoformat(), 'response_time': self.response_time.isoformat() if self.response_time else None, 'created_at': self.created_at.isoformat() } class SystemConfig(db.Model): """系统配置模型""" __tablename__ = 'system_configs' id = db.Column(db.Integer, primary_key=True) key = db.Column(db.String(50), unique=True, nullable=False) value = db.Column(db.Text) description = db.Column(db.String(255)) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) def to_dict(self): """转换为字典""" return { 'id': self.id, 'key': self.key, 'value': self.value, 'description': self.description, 'updated_at': self.updated_at.isoformat() } class VerificationCode(db.Model): """邮箱验证码模型""" __tablename__ = 'verification_codes' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) email = db.Column(db.String(120), nullable=False) code = db.Column(db.String(6), nullable=False) # 6位验证码 purpose = db.Column(db.String(20), default='register') # register, password_reset used = db.Column(db.Boolean, default=False) expired_at = db.Column(db.DateTime, nullable=False) # 过期时间 created_at = db.Column(db.DateTime, default=datetime.utcnow) def is_valid(self): """检查验证码是否有效""" return not self.used and datetime.utcnow() < self.expired_at @staticmethod def generate_code(): """生成6位验证码""" return ''.join(secrets.choice(string.digits) for _ in range(6)) def to_dict(self): return { 'id': self.id, 'email': self.email, 'purpose': self.purpose, 'expired_at': self.expired_at.isoformat() } class APIKey(db.Model): """API密钥模型 - 用户可自己生成""" __tablename__ = 'api_keys' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) name = db.Column(db.String(100), nullable=False) # API密钥名称 api_key = db.Column(db.String(100), unique=True, nullable=False, index=True) # 实际密钥 # secret_key 字段已移除 is_active = db.Column(db.Boolean, default=True) last_used_at = db.Column(db.DateTime) # 最后使用时间 created_at = db.Column(db.DateTime, default=datetime.utcnow) @staticmethod def generate_key(): """生成 API Key""" api_key = 'sk_' + ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(32)) return api_key def to_dict(self): """转换为字典""" data = { 'id': self.id, 'name': self.name, 'api_key': self.api_key, 'is_active': self.is_active, 'last_used_at': self.last_used_at.isoformat() if self.last_used_at else None, 'created_at': self.created_at.isoformat() } return data