update pay function

This commit is contained in:
2025-11-23 20:34:49 +08:00
parent 7538f2d935
commit 15def1c931
2 changed files with 1406 additions and 0 deletions

878
app.py
View File

@@ -4672,6 +4672,13 @@ class TopicComment(db.Model):
# 统计
likes_count = db.Column(db.Integer, default=0, nullable=False)
# 观点IPO 相关
total_investment = db.Column(db.Integer, default=0, nullable=False) # 总投资额
investor_count = db.Column(db.Integer, default=0, nullable=False) # 投资人数
is_verified = db.Column(db.Boolean, default=False, nullable=False) # 是否已验证
verification_result = db.Column(db.String(20)) # 验证结果correct/incorrect/null
position_rank = db.Column(db.Integer) # 评论位置排名(用于首发权拍卖)
# 时间
created_at = db.Column(db.DateTime, default=beijing_now, nullable=False)
updated_at = db.Column(db.DateTime, default=beijing_now, onupdate=beijing_now)
@@ -4704,6 +4711,148 @@ class TopicCommentLike(db.Model):
return f'<TopicCommentLike comment_id={self.comment_id} user_id={self.user_id}>'
class CommentInvestment(db.Model):
"""评论投资记录观点IPO"""
__tablename__ = 'comment_investment'
id = db.Column(db.Integer, primary_key=True)
comment_id = db.Column(db.Integer, db.ForeignKey('topic_comment.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
# 投资数据
shares = db.Column(db.Integer, nullable=False) # 投资份额
amount = db.Column(db.Integer, nullable=False) # 投资金额
avg_price = db.Column(db.Float, nullable=False) # 平均价格
# 状态
status = db.Column(db.String(20), default='active', nullable=False) # active/settled
# 时间
created_at = db.Column(db.DateTime, default=beijing_now, nullable=False)
# 关系
user = db.relationship('User', backref='comment_investments')
comment = db.relationship('TopicComment', backref='investments')
def __repr__(self):
return f'<CommentInvestment id={self.id} comment_id={self.comment_id} user_id={self.user_id} shares={self.shares}>'
class CommentPositionBid(db.Model):
"""评论位置竞拍记录(首发权拍卖)"""
__tablename__ = 'comment_position_bid'
id = db.Column(db.Integer, primary_key=True)
topic_id = db.Column(db.Integer, db.ForeignKey('prediction_topic.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
# 竞拍数据
position = db.Column(db.Integer, nullable=False) # 位置1/2/3
bid_amount = db.Column(db.Integer, nullable=False) # 出价金额
status = db.Column(db.String(20), default='pending', nullable=False) # pending/won/lost
# 时间
created_at = db.Column(db.DateTime, default=beijing_now, nullable=False)
expires_at = db.Column(db.DateTime, nullable=False) # 竞拍截止时间
# 关系
user = db.relationship('User', backref='comment_position_bids')
topic = db.relationship('PredictionTopic', backref='position_bids')
def __repr__(self):
return f'<CommentPositionBid id={self.id} topic_id={self.topic_id} position={self.position} bid={self.bid_amount}>'
class TimeCapsuleTopic(db.Model):
"""时间胶囊话题(长期预测)"""
__tablename__ = 'time_capsule_topic'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
# 话题内容
title = db.Column(db.String(200), nullable=False)
description = db.Column(db.Text)
encrypted_content = db.Column(db.Text) # 加密的预测内容
encryption_key = db.Column(db.String(500)) # 加密密钥(后端存储)
# 时间范围
start_year = db.Column(db.Integer, nullable=False) # 起始年份
end_year = db.Column(db.Integer, nullable=False) # 结束年份
# 状态
status = db.Column(db.String(20), default='active', nullable=False) # active/settled
is_decrypted = db.Column(db.Boolean, default=False, nullable=False) # 是否已解密
actual_happened_year = db.Column(db.Integer) # 实际发生年份
# 统计
total_pool = db.Column(db.Integer, default=0, nullable=False) # 总奖池
# 时间
created_at = db.Column(db.DateTime, default=beijing_now, nullable=False)
updated_at = db.Column(db.DateTime, default=beijing_now, onupdate=beijing_now)
# 关系
user = db.relationship('User', backref='time_capsule_topics')
time_slots = db.relationship('TimeCapsuleTimeSlot', backref='topic', lazy='dynamic')
def __repr__(self):
return f'<TimeCapsuleTopic id={self.id} title={self.title} years={self.start_year}-{self.end_year}>'
class TimeCapsuleTimeSlot(db.Model):
"""时间胶囊时间段"""
__tablename__ = 'time_capsule_time_slot'
id = db.Column(db.Integer, primary_key=True)
topic_id = db.Column(db.Integer, db.ForeignKey('time_capsule_topic.id'), nullable=False)
# 时间段
year_start = db.Column(db.Integer, nullable=False)
year_end = db.Column(db.Integer, nullable=False)
# 竞拍数据
current_holder_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 当前持有者
current_price = db.Column(db.Integer, default=100, nullable=False) # 当前价格
total_bids = db.Column(db.Integer, default=0, nullable=False) # 总竞拍次数
# 状态
status = db.Column(db.String(20), default='active', nullable=False) # active/won/expired
# 时间
created_at = db.Column(db.DateTime, default=beijing_now, nullable=False)
updated_at = db.Column(db.DateTime, default=beijing_now, onupdate=beijing_now)
# 关系
current_holder = db.relationship('User', foreign_keys=[current_holder_id])
bids = db.relationship('TimeSlotBid', backref='time_slot', lazy='dynamic')
def __repr__(self):
return f'<TimeCapsuleTimeSlot id={self.id} years={self.year_start}-{self.year_end} price={self.current_price}>'
class TimeSlotBid(db.Model):
"""时间段竞拍记录"""
__tablename__ = 'time_slot_bid'
id = db.Column(db.Integer, primary_key=True)
slot_id = db.Column(db.Integer, db.ForeignKey('time_capsule_time_slot.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
# 竞拍数据
bid_amount = db.Column(db.Integer, nullable=False)
status = db.Column(db.String(20), default='outbid', nullable=False) # outbid/holding/won
# 时间
created_at = db.Column(db.DateTime, default=beijing_now, nullable=False)
# 关系
user = db.relationship('User', backref='time_slot_bids')
def __repr__(self):
return f'<TimeSlotBid id={self.id} slot_id={self.slot_id} user_id={self.user_id} bid={self.bid_amount}>'
class Event(db.Model):
"""事件模型"""
id = db.Column(db.Integer, primary_key=True)
@@ -14056,6 +14205,735 @@ def like_topic_comment(comment_id):
return jsonify({'success': False, 'error': str(e)}), 500
# ==================== 观点IPO API ====================
@app.route('/api/prediction/comments/<int:comment_id>/invest', methods=['POST'])
@login_required
def invest_comment(comment_id):
"""投资评论观点IPO"""
try:
data = request.json
shares = data.get('shares', 1)
# 获取评论
comment = TopicComment.query.get_or_404(comment_id)
# 检查评论是否已结算
if comment.is_verified:
return jsonify({'success': False, 'error': '该评论已结算,无法继续投资'}), 400
# 检查是否是自己的评论
if comment.user_id == current_user.id:
return jsonify({'success': False, 'error': '不能投资自己的评论'}), 400
# 计算投资金额简化每份100积分基础价格 + 已有投资额/10
base_price = 100
price_increase = comment.total_investment / 10 if comment.total_investment > 0 else 0
price_per_share = base_price + price_increase
amount = int(price_per_share * shares)
# 获取用户积分账户
account = UserCreditAccount.query.filter_by(user_id=current_user.id).first()
if not account:
return jsonify({'success': False, 'error': '账户不存在'}), 404
# 检查余额
if account.balance < amount:
return jsonify({'success': False, 'error': '积分不足'}), 400
# 扣减积分
account.balance -= amount
# 检查是否已有投资记录
existing_investment = CommentInvestment.query.filter_by(
comment_id=comment_id,
user_id=current_user.id,
status='active'
).first()
if existing_investment:
# 更新投资记录
total_shares = existing_investment.shares + shares
total_amount = existing_investment.amount + amount
existing_investment.shares = total_shares
existing_investment.amount = total_amount
existing_investment.avg_price = total_amount / total_shares
else:
# 创建新投资记录
investment = CommentInvestment(
comment_id=comment_id,
user_id=current_user.id,
shares=shares,
amount=amount,
avg_price=price_per_share
)
db.session.add(investment)
comment.investor_count += 1
# 更新评论统计
comment.total_investment += amount
# 记录积分交易
transaction = CreditTransaction(
user_id=current_user.id,
type='comment_investment',
amount=-amount,
balance_after=account.balance,
description=f'投资评论 #{comment_id}'
)
db.session.add(transaction)
db.session.commit()
return jsonify({
'success': True,
'data': {
'shares': shares,
'amount': amount,
'price_per_share': price_per_share,
'total_investment': comment.total_investment,
'investor_count': comment.investor_count,
'new_balance': account.balance
}
})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/prediction/comments/<int:comment_id>/investments', methods=['GET'])
def get_comment_investments(comment_id):
"""获取评论的投资列表"""
try:
investments = CommentInvestment.query.filter_by(
comment_id=comment_id,
status='active'
).all()
result = []
for inv in investments:
user = User.query.get(inv.user_id)
result.append({
'id': inv.id,
'user_id': inv.user_id,
'user_name': user.username if user else '未知用户',
'user_avatar': user.avatar if user else None,
'shares': inv.shares,
'amount': inv.amount,
'avg_price': inv.avg_price,
'created_at': inv.created_at.strftime('%Y-%m-%d %H:%M:%S')
})
return jsonify({
'success': True,
'data': result
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/prediction/comments/<int:comment_id>/verify', methods=['POST'])
@login_required
def verify_comment(comment_id):
"""管理员验证评论预测结果"""
try:
# 检查管理员权限(简化版:假设 user_id=1 是管理员)
if current_user.id != 1:
return jsonify({'success': False, 'error': '无权限操作'}), 403
data = request.json
result = data.get('result') # 'correct' or 'incorrect'
if result not in ['correct', 'incorrect']:
return jsonify({'success': False, 'error': '无效的验证结果'}), 400
comment = TopicComment.query.get_or_404(comment_id)
# 检查是否已验证
if comment.is_verified:
return jsonify({'success': False, 'error': '该评论已验证'}), 400
# 更新验证状态
comment.is_verified = True
comment.verification_result = result
# 如果预测正确,进行收益分配
if result == 'correct' and comment.total_investment > 0:
# 获取所有投资记录
investments = CommentInvestment.query.filter_by(
comment_id=comment_id,
status='active'
).all()
# 计算总收益总投资额的1.5倍)
total_reward = int(comment.total_investment * 1.5)
# 按份额比例分配收益
total_shares = sum([inv.shares for inv in investments])
for inv in investments:
# 计算该投资者的收益
investor_reward = int((inv.shares / total_shares) * total_reward)
# 获取投资者账户
account = UserCreditAccount.query.filter_by(user_id=inv.user_id).first()
if account:
account.balance += investor_reward
# 记录积分交易
transaction = CreditTransaction(
user_id=inv.user_id,
type='comment_investment_profit',
amount=investor_reward,
balance_after=account.balance,
description=f'评论投资收益 #{comment_id}'
)
db.session.add(transaction)
# 更新投资状态
inv.status = 'settled'
# 评论作者也获得奖励总投资额的20%
author_reward = int(comment.total_investment * 0.2)
author_account = UserCreditAccount.query.filter_by(user_id=comment.user_id).first()
if author_account:
author_account.balance += author_reward
transaction = CreditTransaction(
user_id=comment.user_id,
type='comment_author_bonus',
amount=author_reward,
balance_after=author_account.balance,
description=f'评论作者奖励 #{comment_id}'
)
db.session.add(transaction)
db.session.commit()
return jsonify({
'success': True,
'data': {
'comment_id': comment_id,
'verification_result': result,
'total_investment': comment.total_investment
}
})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/prediction/topics/<int:topic_id>/bid-position', methods=['POST'])
@login_required
def bid_comment_position(topic_id):
"""竞拍评论位置(首发权拍卖)"""
try:
data = request.json
position = data.get('position') # 1/2/3
bid_amount = data.get('bid_amount')
if position not in [1, 2, 3]:
return jsonify({'success': False, 'error': '无效的位置'}), 400
if bid_amount < 500:
return jsonify({'success': False, 'error': '最低出价500积分'}), 400
# 获取用户积分账户
account = UserCreditAccount.query.filter_by(user_id=current_user.id).first()
if not account or account.balance < bid_amount:
return jsonify({'success': False, 'error': '积分不足'}), 400
# 检查该位置的当前最高出价
current_highest = CommentPositionBid.query.filter_by(
topic_id=topic_id,
position=position,
status='pending'
).order_by(CommentPositionBid.bid_amount.desc()).first()
if current_highest and bid_amount <= current_highest.bid_amount:
return jsonify({
'success': False,
'error': f'出价必须高于当前最高价 {current_highest.bid_amount}'
}), 400
# 扣减积分(冻结)
account.balance -= bid_amount
account.frozen += bid_amount
# 如果有之前的出价,退还积分
user_previous_bid = CommentPositionBid.query.filter_by(
topic_id=topic_id,
position=position,
user_id=current_user.id,
status='pending'
).first()
if user_previous_bid:
account.frozen -= user_previous_bid.bid_amount
account.balance += user_previous_bid.bid_amount
user_previous_bid.status = 'lost'
# 创建竞拍记录
topic = PredictionTopic.query.get_or_404(topic_id)
bid = CommentPositionBid(
topic_id=topic_id,
user_id=current_user.id,
position=position,
bid_amount=bid_amount,
expires_at=topic.deadline # 竞拍截止时间与话题截止时间相同
)
db.session.add(bid)
# 记录积分交易
transaction = CreditTransaction(
user_id=current_user.id,
type='position_bid',
amount=-bid_amount,
balance_after=account.balance,
description=f'竞拍评论位置 #{position} (话题#{topic_id})'
)
db.session.add(transaction)
db.session.commit()
return jsonify({
'success': True,
'data': {
'bid_id': bid.id,
'position': position,
'bid_amount': bid_amount,
'new_balance': account.balance,
'frozen': account.frozen
}
})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/prediction/topics/<int:topic_id>/position-bids', methods=['GET'])
def get_position_bids(topic_id):
"""获取话题的位置竞拍列表"""
try:
result = {}
for position in [1, 2, 3]:
bids = CommentPositionBid.query.filter_by(
topic_id=topic_id,
position=position,
status='pending'
).order_by(CommentPositionBid.bid_amount.desc()).limit(5).all()
position_bids = []
for bid in bids:
user = User.query.get(bid.user_id)
position_bids.append({
'id': bid.id,
'user_id': bid.user_id,
'user_name': user.username if user else '未知用户',
'user_avatar': user.avatar if user else None,
'bid_amount': bid.bid_amount,
'created_at': bid.created_at.strftime('%Y-%m-%d %H:%M:%S')
})
result[f'position_{position}'] = position_bids
return jsonify({
'success': True,
'data': result
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
# ==================== 时间胶囊 API ====================
@app.route('/api/time-capsule/topics', methods=['POST'])
@login_required
def create_time_capsule_topic():
"""创建时间胶囊话题"""
try:
data = request.json
title = data.get('title')
description = data.get('description', '')
encrypted_content = data.get('encrypted_content')
encryption_key = data.get('encryption_key')
start_year = data.get('start_year')
end_year = data.get('end_year')
# 验证
if not title or not encrypted_content or not encryption_key:
return jsonify({'success': False, 'error': '缺少必要参数'}), 400
if not start_year or not end_year or end_year <= start_year:
return jsonify({'success': False, 'error': '无效的时间范围'}), 400
# 获取用户积分账户
account = UserCreditAccount.query.filter_by(user_id=current_user.id).first()
if not account or account.balance < 100:
return jsonify({'success': False, 'error': '积分不足需要100积分'}), 400
# 扣减积分
account.balance -= 100
# 创建话题
topic = TimeCapsuleTopic(
user_id=current_user.id,
title=title,
description=description,
encrypted_content=encrypted_content,
encryption_key=encryption_key,
start_year=start_year,
end_year=end_year,
total_pool=100 # 创建费用进入奖池
)
db.session.add(topic)
db.session.flush() # 获取 topic.id
# 自动创建时间段(每年一个时间段)
for year in range(start_year, end_year + 1):
slot = TimeCapsuleTimeSlot(
topic_id=topic.id,
year_start=year,
year_end=year
)
db.session.add(slot)
# 记录积分交易
transaction = CreditTransaction(
user_id=current_user.id,
type='time_capsule_create',
amount=-100,
balance_after=account.balance,
description=f'创建时间胶囊话题 #{topic.id}'
)
db.session.add(transaction)
db.session.commit()
return jsonify({
'success': True,
'data': {
'topic_id': topic.id,
'title': topic.title,
'new_balance': account.balance
}
})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/time-capsule/topics', methods=['GET'])
def get_time_capsule_topics():
"""获取时间胶囊话题列表"""
try:
status = request.args.get('status', 'active')
query = TimeCapsuleTopic.query.filter_by(status=status)
topics = query.order_by(TimeCapsuleTopic.created_at.desc()).all()
result = []
for topic in topics:
# 获取用户信息
user = User.query.get(topic.user_id)
# 获取时间段统计
slots = TimeCapsuleTimeSlot.query.filter_by(topic_id=topic.id).all()
total_slots = len(slots)
active_slots = len([s for s in slots if s.status == 'active'])
result.append({
'id': topic.id,
'title': topic.title,
'description': topic.description,
'start_year': topic.start_year,
'end_year': topic.end_year,
'total_pool': topic.total_pool,
'total_slots': total_slots,
'active_slots': active_slots,
'is_decrypted': topic.is_decrypted,
'status': topic.status,
'author_id': topic.user_id,
'author_name': user.username if user else '未知用户',
'author_avatar': user.avatar if user else None,
'created_at': topic.created_at.strftime('%Y-%m-%d %H:%M:%S')
})
return jsonify({
'success': True,
'data': result
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/time-capsule/topics/<int:topic_id>', methods=['GET'])
def get_time_capsule_topic(topic_id):
"""获取时间胶囊话题详情"""
try:
topic = TimeCapsuleTopic.query.get_or_404(topic_id)
user = User.query.get(topic.user_id)
# 获取所有时间段
slots = TimeCapsuleTimeSlot.query.filter_by(topic_id=topic_id).order_by(TimeCapsuleTimeSlot.year_start).all()
slots_data = []
for slot in slots:
holder = User.query.get(slot.current_holder_id) if slot.current_holder_id else None
slots_data.append({
'id': slot.id,
'year_start': slot.year_start,
'year_end': slot.year_end,
'current_price': slot.current_price,
'total_bids': slot.total_bids,
'status': slot.status,
'current_holder_id': slot.current_holder_id,
'current_holder_name': holder.username if holder else None,
'current_holder_avatar': holder.avatar if holder else None
})
result = {
'id': topic.id,
'title': topic.title,
'description': topic.description,
'start_year': topic.start_year,
'end_year': topic.end_year,
'total_pool': topic.total_pool,
'is_decrypted': topic.is_decrypted,
'decrypted_content': topic.encrypted_content if topic.is_decrypted else None,
'actual_happened_year': topic.actual_happened_year,
'status': topic.status,
'author_id': topic.user_id,
'author_name': user.username if user else '未知用户',
'author_avatar': user.avatar if user else None,
'time_slots': slots_data,
'created_at': topic.created_at.strftime('%Y-%m-%d %H:%M:%S')
}
return jsonify({
'success': True,
'data': result
})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/time-capsule/slots/<int:slot_id>/bid', methods=['POST'])
@login_required
def bid_time_slot(slot_id):
"""竞拍时间段"""
try:
data = request.json
bid_amount = data.get('bid_amount')
slot = TimeCapsuleTimeSlot.query.get_or_404(slot_id)
# 检查时间段是否还在竞拍
if slot.status != 'active':
return jsonify({'success': False, 'error': '该时间段已结束竞拍'}), 400
# 检查出价是否高于当前价格
min_bid = slot.current_price + 50 # 至少比当前价格高50积分
if bid_amount < min_bid:
return jsonify({
'success': False,
'error': f'出价必须至少为 {min_bid} 积分'
}), 400
# 获取用户积分账户
account = UserCreditAccount.query.filter_by(user_id=current_user.id).first()
if not account or account.balance < bid_amount:
return jsonify({'success': False, 'error': '积分不足'}), 400
# 扣减积分
account.balance -= bid_amount
# 如果有前任持有者,退还积分
if slot.current_holder_id:
prev_holder_account = UserCreditAccount.query.filter_by(user_id=slot.current_holder_id).first()
if prev_holder_account:
prev_holder_account.balance += slot.current_price
# 更新前任的竞拍记录状态
prev_bid = TimeSlotBid.query.filter_by(
slot_id=slot_id,
user_id=slot.current_holder_id,
status='holding'
).first()
if prev_bid:
prev_bid.status = 'outbid'
# 创建竞拍记录
bid = TimeSlotBid(
slot_id=slot_id,
user_id=current_user.id,
bid_amount=bid_amount,
status='holding'
)
db.session.add(bid)
# 更新时间段
slot.current_holder_id = current_user.id
slot.current_price = bid_amount
slot.total_bids += 1
# 更新话题奖池
topic = TimeCapsuleTopic.query.get(slot.topic_id)
price_increase = bid_amount - (slot.current_price if slot.current_holder_id else 100)
topic.total_pool += price_increase
# 记录积分交易
transaction = CreditTransaction(
user_id=current_user.id,
type='time_slot_bid',
amount=-bid_amount,
balance_after=account.balance,
description=f'竞拍时间段 {slot.year_start}-{slot.year_end}'
)
db.session.add(transaction)
db.session.commit()
return jsonify({
'success': True,
'data': {
'slot_id': slot_id,
'bid_amount': bid_amount,
'new_balance': account.balance,
'total_pool': topic.total_pool
}
})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/time-capsule/topics/<int:topic_id>/decrypt', methods=['POST'])
@login_required
def decrypt_time_capsule(topic_id):
"""解密时间胶囊(管理员或作者)"""
try:
topic = TimeCapsuleTopic.query.get_or_404(topic_id)
# 检查权限(管理员或作者)
if current_user.id != 1 and current_user.id != topic.user_id:
return jsonify({'success': False, 'error': '无权限操作'}), 403
# 检查是否已解密
if topic.is_decrypted:
return jsonify({'success': False, 'error': '该话题已解密'}), 400
# 解密(前端会用密钥解密内容)
topic.is_decrypted = True
db.session.commit()
return jsonify({
'success': True,
'data': {
'encrypted_content': topic.encrypted_content,
'encryption_key': topic.encryption_key
}
})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/api/time-capsule/topics/<int:topic_id>/settle', methods=['POST'])
@login_required
def settle_time_capsule(topic_id):
"""结算时间胶囊话题"""
try:
# 检查管理员权限
if current_user.id != 1:
return jsonify({'success': False, 'error': '无权限操作'}), 403
data = request.json
happened_year = data.get('happened_year')
topic = TimeCapsuleTopic.query.get_or_404(topic_id)
# 检查是否已结算
if topic.status == 'settled':
return jsonify({'success': False, 'error': '该话题已结算'}), 400
# 更新话题状态
topic.status = 'settled'
topic.actual_happened_year = happened_year
# 找到中奖的时间段
winning_slot = TimeCapsuleTimeSlot.query.filter_by(
topic_id=topic_id,
year_start=happened_year
).first()
if winning_slot and winning_slot.current_holder_id:
# 中奖者获得全部奖池
winner_account = UserCreditAccount.query.filter_by(user_id=winning_slot.current_holder_id).first()
if winner_account:
winner_account.balance += topic.total_pool
# 记录积分交易
transaction = CreditTransaction(
user_id=winning_slot.current_holder_id,
type='time_capsule_win',
amount=topic.total_pool,
balance_after=winner_account.balance,
description=f'时间胶囊中奖 #{topic_id}'
)
db.session.add(transaction)
# 更新竞拍记录
winning_bid = TimeSlotBid.query.filter_by(
slot_id=winning_slot.id,
user_id=winning_slot.current_holder_id,
status='holding'
).first()
if winning_bid:
winning_bid.status = 'won'
# 更新时间段状态
winning_slot.status = 'won'
# 其他时间段设为过期
other_slots = TimeCapsuleTimeSlot.query.filter(
TimeCapsuleTimeSlot.topic_id == topic_id,
TimeCapsuleTimeSlot.id != (winning_slot.id if winning_slot else None)
).all()
for slot in other_slots:
slot.status = 'expired'
db.session.commit()
return jsonify({
'success': True,
'data': {
'topic_id': topic_id,
'happened_year': happened_year,
'winner_id': winning_slot.current_holder_id if winning_slot else None,
'prize': topic.total_pool
}
})
except Exception as e:
db.session.rollback()
return jsonify({'success': False, 'error': str(e)}), 500
if __name__ == '__main__':
# 创建数据库表
with app.app_context():