feat: 用户个人中心功能
- 账户余额显示和管理 - 充值功能(模拟模式) - 退款申请功能(需管理员审核) - 账户流水记录查看 - 会员购买记录查看 - 使用统计展示 - 新增模型:UserRecharge, UserRefund, MembershipPurchase, AccountTransaction - User模型添加balance字段 - 导航栏添加个人中心入口
This commit is contained in:
189
models.py
189
models.py
@@ -38,8 +38,13 @@ class User(db.Model):
|
||||
is_active = db.Column(db.Boolean, default=True) # 是否启用
|
||||
is_admin = db.Column(db.Boolean, default=False) # 是否管理员
|
||||
|
||||
# 余额
|
||||
balance = db.Column(db.Float, default=0.0) # 账户余额(元)
|
||||
|
||||
# 关系
|
||||
translations = db.relationship('Translation', backref='user', lazy=True)
|
||||
recharges = db.relationship('UserRecharge', backref='user', lazy=True)
|
||||
refunds = db.relationship('UserRefund', backref='user', lazy=True)
|
||||
|
||||
def set_password(self, password):
|
||||
self.password_hash = generate_password_hash(password)
|
||||
@@ -102,6 +107,7 @@ class User(db.Model):
|
||||
'is_vip': self.is_vip(),
|
||||
'is_admin': self.is_admin,
|
||||
'is_active': self.is_active,
|
||||
'balance': self.balance,
|
||||
'daily_count': self.daily_count,
|
||||
'total_count': self.total_count,
|
||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||
@@ -520,4 +526,187 @@ class MembershipPlanConfig(db.Model):
|
||||
'is_active': self.is_active,
|
||||
'is_recommended': self.is_recommended,
|
||||
'is_system': self.is_system,
|
||||
}
|
||||
|
||||
|
||||
# ==================== 用户充值记录 ====================
|
||||
class UserRecharge(db.Model):
|
||||
"""用户充值记录"""
|
||||
__tablename__ = 'user_recharges'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
|
||||
# 充值信息
|
||||
amount = db.Column(db.Float, nullable=False) # 充值金额
|
||||
balance_before = db.Column(db.Float, default=0) # 充值前余额
|
||||
balance_after = db.Column(db.Float, default=0) # 充值后余额
|
||||
|
||||
# 支付方式
|
||||
payment_method = db.Column(db.String(20), default='balance') # balance, alipay, wechat, manual
|
||||
|
||||
# 状态
|
||||
status = db.Column(db.String(20), default='pending') # pending, completed, failed, cancelled
|
||||
order_no = db.Column(db.String(64), unique=True, nullable=True) # 订单号
|
||||
|
||||
# 备注
|
||||
remark = db.Column(db.String(255), nullable=True) # 管理员备注
|
||||
operator_id = db.Column(db.Integer, nullable=True) # 操作管理员ID
|
||||
|
||||
# 时间
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
completed_at = db.Column(db.DateTime, nullable=True)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'user_id': self.user_id,
|
||||
'amount': self.amount,
|
||||
'balance_before': self.balance_before,
|
||||
'balance_after': self.balance_after,
|
||||
'payment_method': self.payment_method,
|
||||
'status': self.status,
|
||||
'order_no': self.order_no,
|
||||
'remark': self.remark,
|
||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||
'completed_at': self.completed_at.isoformat() if self.completed_at else None,
|
||||
}
|
||||
|
||||
|
||||
# ==================== 用户退款记录 ====================
|
||||
class UserRefund(db.Model):
|
||||
"""用户退款记录"""
|
||||
__tablename__ = 'user_refunds'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
recharge_id = db.Column(db.Integer, db.ForeignKey('user_recharges.id'), nullable=True) # 关联充值记录
|
||||
|
||||
# 退款信息
|
||||
amount = db.Column(db.Float, nullable=False) # 退款金额
|
||||
balance_before = db.Column(db.Float, default=0) # 退款前余额
|
||||
balance_after = db.Column(db.Float, default=0) # 退款后余额
|
||||
|
||||
# 原因
|
||||
reason = db.Column(db.String(255), nullable=True) # 退款原因
|
||||
reason_type = db.Column(db.String(20), default='user_request') # user_request, system_error, admin_initiated
|
||||
|
||||
# 状态
|
||||
status = db.Column(db.String(20), default='pending') # pending, approved, completed, rejected
|
||||
|
||||
# 操作
|
||||
operator_id = db.Column(db.Integer, nullable=True) # 处理管理员ID
|
||||
operator_remark = db.Column(db.String(255), nullable=True) # 管理员处理备注
|
||||
|
||||
# 时间
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
processed_at = db.Column(db.DateTime, nullable=True)
|
||||
completed_at = db.Column(db.DateTime, nullable=True)
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'user_id': self.user_id,
|
||||
'recharge_id': self.recharge_id,
|
||||
'amount': self.amount,
|
||||
'balance_before': self.balance_before,
|
||||
'balance_after': self.balance_after,
|
||||
'reason': self.reason,
|
||||
'reason_type': self.reason_type,
|
||||
'status': self.status,
|
||||
'operator_remark': self.operator_remark,
|
||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||
'processed_at': self.processed_at.isoformat() if self.processed_at else None,
|
||||
'completed_at': self.completed_at.isoformat() if self.completed_at else None,
|
||||
}
|
||||
|
||||
|
||||
# ==================== 会员购买记录 ====================
|
||||
class MembershipPurchase(db.Model):
|
||||
"""会员购买记录"""
|
||||
__tablename__ = 'membership_purchases'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
|
||||
# 套餐信息
|
||||
plan_key = db.Column(db.String(50), nullable=False) # vip_basic, vip_pro, vip_enterprise
|
||||
plan_name = db.Column(db.String(100), nullable=False) # 基础会员, 专业会员
|
||||
|
||||
# 价格
|
||||
price = db.Column(db.Float, nullable=False) # 实付金额
|
||||
original_price = db.Column(db.Float, nullable=True) # 原价
|
||||
|
||||
# 有效期
|
||||
period_days = db.Column(db.Integer, default=30) # 购买天数
|
||||
expire_before = db.Column(db.DateTime, nullable=True) # 购买前到期时间
|
||||
expire_after = db.Column(db.DateTime, nullable=True) # 购买后到期时间
|
||||
|
||||
# 支付方式
|
||||
payment_method = db.Column(db.String(20), default='balance') # balance, alipay, wechat
|
||||
|
||||
# 状态
|
||||
status = db.Column(db.String(20), default='completed') # pending, completed, refunded
|
||||
|
||||
# 时间
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
# 关系
|
||||
user = db.relationship('User', backref=db.backref('membership_purchases', lazy=True))
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'user_id': self.user_id,
|
||||
'plan_key': self.plan_key,
|
||||
'plan_name': self.plan_name,
|
||||
'price': self.price,
|
||||
'original_price': self.original_price,
|
||||
'period_days': self.period_days,
|
||||
'expire_after': self.expire_after.isoformat() if self.expire_after else None,
|
||||
'payment_method': self.payment_method,
|
||||
'status': self.status,
|
||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||
}
|
||||
|
||||
|
||||
# ==================== 账户流水记录 ====================
|
||||
class AccountTransaction(db.Model):
|
||||
"""账户流水记录"""
|
||||
__tablename__ = 'account_transactions'
|
||||
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
|
||||
|
||||
# 流水信息
|
||||
transaction_type = db.Column(db.String(20), nullable=False) # recharge, refund, purchase, consume, refund_purchase
|
||||
amount = db.Column(db.Float, nullable=False) # 金额(正数加,负数减)
|
||||
balance_before = db.Column(db.Float, default=0) # 操作前余额
|
||||
balance_after = db.Column(db.Float, default=0) # 操作后余额
|
||||
|
||||
# 关联
|
||||
related_id = db.Column(db.Integer, nullable=True) # 关联记录ID(充值ID、退款ID等)
|
||||
related_type = db.Column(db.String(50), nullable=True) # 关联类型(recharge, refund, membership_purchase等)
|
||||
|
||||
# 描述
|
||||
description = db.Column(db.String(255), nullable=True) # 流水描述
|
||||
|
||||
# 时间
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
# 关系
|
||||
user = db.relationship('User', backref=db.backref('transactions', lazy=True))
|
||||
|
||||
def to_dict(self):
|
||||
return {
|
||||
'id': self.id,
|
||||
'user_id': self.user_id,
|
||||
'transaction_type': self.transaction_type,
|
||||
'amount': self.amount,
|
||||
'balance_before': self.balance_before,
|
||||
'balance_after': self.balance_after,
|
||||
'related_id': self.related_id,
|
||||
'related_type': self.related_type,
|
||||
'description': self.description,
|
||||
'created_at': self.created_at.isoformat() if self.created_at else None,
|
||||
}
|
||||
Reference in New Issue
Block a user