初始化提交
This commit is contained in:
233
NBATransfer-backend/models.py
Normal file
233
NBATransfer-backend/models.py
Normal file
@@ -0,0 +1,233 @@
|
||||
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
|
||||
Reference in New Issue
Block a user