Files
NBATransfer/NBATransfer-backend/services/admin_service.py
2025-12-14 15:40:49 +08:00

245 lines
8.2 KiB
Python

from models import db, User, Order, ApiCall, Transaction
from sqlalchemy import desc, func
from datetime import datetime, timedelta
class AdminService:
@staticmethod
def get_users(page=1, per_page=20, search=''):
"""获取用户列表"""
query = User.query
if search:
query = query.filter(
(User.email.contains(search)) | (User.username.contains(search))
)
# 分页查询
pagination = query.order_by(desc(User.created_at))\
.paginate(page=page, per_page=per_page, error_out=False)
return {
'users': [user.to_dict() for user in pagination.items],
'total': pagination.total,
'page': page,
'per_page': per_page,
'pages': pagination.pages
}, 200
@staticmethod
def get_user_detail(user_id):
"""获取用户详情"""
user = User.query.get(user_id)
if not user:
return {'error': '用户不存在'}, 404
# 统计信息
total_recharge = db.session.query(func.sum(Transaction.amount))\
.filter_by(user_id=user_id, type='recharge').scalar() or 0
total_consume = db.session.query(func.sum(Transaction.amount))\
.filter_by(user_id=user_id, type='consume').scalar() or 0
total_api_calls = ApiCall.query.filter_by(user_id=user_id).count()
return {
'user': user.to_dict(),
'stats': {
'total_recharge': total_recharge,
'total_consume': abs(total_consume),
'total_api_calls': total_api_calls
}
}, 200
@staticmethod
def toggle_user_status(admin_user_id, user_id):
"""启用/禁用用户"""
user = User.query.get(user_id)
if not user:
return {'error': '用户不存在'}, 404
# 检查是否尝试禁用其他管理员 (需要传入当前管理员ID)
if user.is_admin and user.id != admin_user_id:
return {'error': '不能禁用其他管理员'}, 403
user.is_active = not user.is_active
try:
db.session.commit()
return {
'message': f'用户已{"启用" if user.is_active else "禁用"}',
'user': user.to_dict()
}, 200
except Exception as e:
db.session.rollback()
return {'error': '操作失败'}, 500
@staticmethod
def adjust_balance(user_id, data):
"""调整用户余额"""
user = User.query.get(user_id)
if not user:
return {'error': '用户不存在'}, 404
amount = data.get('amount')
description = data.get('description', '管理员调整余额')
if amount is None or amount == 0:
return {'error': '金额不能为0'}, 400
try:
balance_before = user.balance
user.balance += amount
balance_after = user.balance
# 创建交易记录
transaction = Transaction(
user_id=user_id,
type='recharge' if amount > 0 else 'consume',
amount=amount,
balance_before=balance_before,
balance_after=balance_after,
description=description
)
db.session.add(transaction)
db.session.commit()
return {
'message': '余额调整成功',
'user': user.to_dict(),
'transaction': transaction.to_dict()
}, 200
except Exception as e:
db.session.rollback()
return {'error': '余额调整失败'}, 500
@staticmethod
def get_all_orders(page=1, per_page=20, status=None):
"""获取所有订单"""
query = Order.query
if status:
query = query.filter_by(status=status)
# 分页查询
pagination = query.order_by(desc(Order.created_at))\
.paginate(page=page, per_page=per_page, error_out=False)
return {
'orders': [order.to_dict() for order in pagination.items],
'total': pagination.total,
'page': page,
'per_page': per_page,
'pages': pagination.pages
}, 200
@staticmethod
def get_all_api_calls(page=1, per_page=20, status=None):
"""获取所有API调用记录"""
query = ApiCall.query
if status:
query = query.filter_by(status=status)
# 分页查询
pagination = query.order_by(desc(ApiCall.created_at))\
.paginate(page=page, per_page=per_page, error_out=False)
return {
'api_calls': [call.to_dict() for call in pagination.items],
'total': pagination.total,
'page': page,
'per_page': per_page,
'pages': pagination.pages
}, 200
@staticmethod
def get_overview_stats():
"""获取总览统计"""
# 用户统计
total_users = User.query.count()
active_users = User.query.filter_by(is_active=True).count()
# 订单统计
total_orders = Order.query.count()
paid_orders = Order.query.filter_by(status='paid').count()
total_revenue = db.session.query(func.sum(Order.amount))\
.filter_by(status='paid').scalar() or 0
# API调用统计
total_api_calls = ApiCall.query.count()
success_calls = ApiCall.query.filter_by(status='success').count()
failed_calls = ApiCall.query.filter_by(status='failed').count()
# 今日统计
today = datetime.utcnow().date()
today_start = datetime.combine(today, datetime.min.time())
today_users = User.query.filter(User.created_at >= today_start).count()
today_orders = Order.query.filter(Order.created_at >= today_start).count()
today_revenue = db.session.query(func.sum(Order.amount))\
.filter(Order.created_at >= today_start, Order.status == 'paid').scalar() or 0
today_api_calls = ApiCall.query.filter(ApiCall.created_at >= today_start).count()
return {
'total': {
'users': total_users,
'active_users': active_users,
'orders': total_orders,
'paid_orders': paid_orders,
'revenue': total_revenue,
'api_calls': total_api_calls,
'success_calls': success_calls,
'failed_calls': failed_calls
},
'today': {
'users': today_users,
'orders': today_orders,
'revenue': today_revenue,
'api_calls': today_api_calls
}
}, 200
@staticmethod
def get_chart_data(days=7):
"""获取图表数据"""
# 计算日期范围
end_date = datetime.utcnow().date()
start_date = end_date - timedelta(days=days-1)
chart_data = []
for i in range(days):
date = start_date + timedelta(days=i)
date_start = datetime.combine(date, datetime.min.time())
date_end = datetime.combine(date, datetime.max.time())
# 统计当天数据
users = User.query.filter(
User.created_at >= date_start,
User.created_at <= date_end
).count()
revenue = db.session.query(func.sum(Order.amount))\
.filter(
Order.created_at >= date_start,
Order.created_at <= date_end,
Order.status == 'paid'
).scalar() or 0
api_calls = ApiCall.query.filter(
ApiCall.created_at >= date_start,
ApiCall.created_at <= date_end
).count()
chart_data.append({
'date': date.isoformat(),
'users': users,
'revenue': float(revenue),
'api_calls': api_calls
})
return {
'chart_data': chart_data
}, 200