Compare commits
No commits in common. "ced1020235d8296dc78493b0a100a5181924c223" and "1aa3cb4151f7922b953d3fe9c3d60687ef336d50" have entirely different histories.
ced1020235
...
1aa3cb4151
@ -1,7 +1,7 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
from extensions import db
|
||||
from models import User, Role, Permission, SystemDict, SystemNotification, Order, to_bj_time, get_bj_now
|
||||
from models import User, Role, Permission, SystemDict, SystemNotification, Order, to_bj_time
|
||||
from middlewares.auth import permission_required
|
||||
from services.logger import system_logger
|
||||
|
||||
@ -277,7 +277,7 @@ def delete_notification():
|
||||
@admin_bp.route('/orders', methods=['GET'])
|
||||
@permission_required('manage_system') # 仅限超级管理员
|
||||
def get_orders():
|
||||
thirty_min_ago = get_bj_now() - timedelta(minutes=30)
|
||||
thirty_min_ago = datetime.utcnow() - timedelta(minutes=30)
|
||||
|
||||
# 过滤掉超过 30 分钟未支付的订单
|
||||
orders = Order.query.filter(
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
from flask import Blueprint, request, jsonify, session, render_template, redirect, url_for
|
||||
import json
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
from extensions import db
|
||||
from models import User, get_bj_now
|
||||
from models import User
|
||||
from services.sms_service import SMSService
|
||||
from services.captcha_service import CaptchaService
|
||||
from services.logger import system_logger
|
||||
@ -57,7 +57,7 @@ def buy_page():
|
||||
user_id = session['user_id']
|
||||
user = db.session.get(User, user_id)
|
||||
|
||||
thirty_min_ago = get_bj_now() - timedelta(minutes=30)
|
||||
thirty_min_ago = datetime.utcnow() - timedelta(minutes=30)
|
||||
|
||||
# 获取用户个人充值记录 (过滤掉超过 30 分钟未支付的订单)
|
||||
personal_orders = Order.query.filter(
|
||||
@ -158,7 +158,8 @@ def send_code():
|
||||
success, msg = SMSService.send_code(phone)
|
||||
if success:
|
||||
# 设置各种限制标记
|
||||
now = get_bj_now()
|
||||
from datetime import datetime
|
||||
now = datetime.now()
|
||||
seconds_until_midnight = ((23 - now.hour) * 3600) + ((59 - now.minute) * 60) + (60 - now.second)
|
||||
|
||||
redis_client.setex(f"sms_lock:{phone}", 60, "1")
|
||||
@ -420,7 +421,7 @@ def get_logs():
|
||||
for log in pagination.items:
|
||||
logs_data.append({
|
||||
"id": log.id,
|
||||
"time": log.created_at_bj.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
"time": log.created_at.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
"level": log.level,
|
||||
"message": log.message,
|
||||
"module": log.module,
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
from flask import Blueprint, request, redirect, url_for, session, jsonify, render_template
|
||||
from extensions import db
|
||||
from models import Order, User, to_bj_time, get_bj_now
|
||||
from models import Order, User, to_bj_time
|
||||
from services.alipay_service import AlipayService
|
||||
from services.logger import system_logger
|
||||
import uuid
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
payment_bp = Blueprint('payment', __name__, url_prefix='/payment')
|
||||
|
||||
@ -91,7 +91,7 @@ def payment_history():
|
||||
if 'user_id' not in session:
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
thirty_min_ago = get_bj_now() - timedelta(minutes=30)
|
||||
thirty_min_ago = datetime.utcnow() - timedelta(minutes=30)
|
||||
|
||||
user_id = session['user_id']
|
||||
orders = Order.query.filter(
|
||||
@ -111,7 +111,7 @@ def api_payment_history():
|
||||
if 'user_id' not in session:
|
||||
return jsonify({'code': 401, 'msg': '请先登录'}), 401
|
||||
|
||||
thirty_min_ago = get_bj_now() - timedelta(minutes=30)
|
||||
thirty_min_ago = datetime.utcnow() - timedelta(minutes=30)
|
||||
|
||||
user_id = session['user_id']
|
||||
orders = Order.query.filter(
|
||||
@ -155,7 +155,7 @@ def payment_notify():
|
||||
if order and order.status == 'PENDING':
|
||||
order.status = 'PAID'
|
||||
order.trade_no = trade_no
|
||||
order.paid_at = get_bj_now()
|
||||
order.paid_at = datetime.now()
|
||||
|
||||
user = db.session.get(User, order.user_id)
|
||||
if user:
|
||||
|
||||
26
models.py
26
models.py
@ -6,20 +6,18 @@ from werkzeug.security import generate_password_hash, check_password_hash
|
||||
UTC_TZ = timezone.utc
|
||||
BEIJING_TZ = timezone(timedelta(hours=8))
|
||||
|
||||
def get_bj_now():
|
||||
"""获取当前北京时间(无时区信息的 naive datetime)"""
|
||||
return datetime.now(BEIJING_TZ).replace(tzinfo=None)
|
||||
|
||||
def to_bj_time(dt):
|
||||
"""返回北京时间
|
||||
"""将 UTC 时间转换为北京时间 (UTC+8)
|
||||
|
||||
注意:为统一时间处理,现在所有时间存储都直接使用北京时间。
|
||||
此函数主要用于兼容性,直接返回输入时间。
|
||||
无论系统时区设置如何,都能正确转换为北京时间
|
||||
"""
|
||||
if not dt:
|
||||
return None
|
||||
# 直接返回(数据库存储的已经是北京时间)
|
||||
return dt if dt.tzinfo is None else dt.replace(tzinfo=None)
|
||||
# 如果 dt 没有时区信息,假设它是 UTC 时间
|
||||
if dt.tzinfo is None:
|
||||
dt = dt.replace(tzinfo=UTC_TZ)
|
||||
# 转换为北京时间
|
||||
return dt.astimezone(BEIJING_TZ).replace(tzinfo=None)
|
||||
|
||||
|
||||
# 角色与权限的多对多关联表
|
||||
@ -56,7 +54,7 @@ class User(db.Model):
|
||||
is_banned = db.Column(db.Boolean, default=False) # 账号是否被封禁
|
||||
# 关联角色 ID
|
||||
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
|
||||
created_at = db.Column(db.DateTime, default=get_bj_now)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
@property
|
||||
def created_at_bj(self):
|
||||
@ -108,7 +106,7 @@ class GenerationRecord(db.Model):
|
||||
cost = db.Column(db.Integer, default=0) # 消耗积分
|
||||
# 存储生成的图片 URL 列表 (JSON 字符串)
|
||||
image_urls = db.Column(db.Text)
|
||||
created_at = db.Column(db.DateTime, default=get_bj_now)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
@property
|
||||
def created_at_bj(self):
|
||||
@ -130,7 +128,7 @@ class SystemNotification(db.Model):
|
||||
title = db.Column(db.String(200), nullable=False)
|
||||
content = db.Column(db.Text, nullable=False)
|
||||
is_active = db.Column(db.Boolean, default=True)
|
||||
created_at = db.Column(db.DateTime, default=get_bj_now)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
@property
|
||||
def created_at_bj(self):
|
||||
@ -150,7 +148,7 @@ class Order(db.Model):
|
||||
points = db.Column(db.Integer, nullable=False) # 购买的积分
|
||||
status = db.Column(db.String(20), default='PENDING') # PENDING, PAID, CANCELLED
|
||||
trade_no = db.Column(db.String(64)) # 支付宝交易号
|
||||
created_at = db.Column(db.DateTime, default=get_bj_now)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
paid_at = db.Column(db.DateTime)
|
||||
|
||||
@property
|
||||
@ -180,7 +178,7 @@ class SystemLog(db.Model):
|
||||
method = db.Column(db.String(10))
|
||||
user_agent = db.Column(db.String(255))
|
||||
|
||||
created_at = db.Column(db.DateTime, default=get_bj_now)
|
||||
created_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
@property
|
||||
def created_at_bj(self):
|
||||
|
||||
@ -86,16 +86,13 @@ class SystemLogger:
|
||||
try:
|
||||
from models import SystemLog
|
||||
|
||||
# 直接存储北京时间,避免时区转换问题
|
||||
bj_now = datetime.now(BEIJING_TZ).replace(tzinfo=None)
|
||||
|
||||
log_data = {
|
||||
'level': level,
|
||||
'message': message,
|
||||
'module': module,
|
||||
'user_id': extra.get('user_id') if extra else None,
|
||||
'extra': json.dumps(extra, ensure_ascii=False) if extra else None,
|
||||
'created_at': bj_now # 直接存储北京时间
|
||||
'created_at': datetime.now(timezone.utc).replace(tzinfo=None) # 存储 UTC 时间(无时区信息)
|
||||
}
|
||||
|
||||
# 捕获请求上下文信息
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
from models import GenerationRecord, Order, db, to_bj_time, get_bj_now
|
||||
from models import GenerationRecord, Order, db, to_bj_time
|
||||
from sqlalchemy import func
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
def get_point_stats(user_id, days=7):
|
||||
"""获取用户积分消耗统计数据 (用于图表)"""
|
||||
end_date = get_bj_now()
|
||||
end_date = datetime.utcnow()
|
||||
start_date = end_date - timedelta(days=days-1)
|
||||
|
||||
# 1. 获取消耗统计 (从 GenerationRecord)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user