feat: 新增平台

This commit is contained in:
2025-11-30 19:49:25 +08:00
parent c3e56a954d
commit fbd2c491b2
41 changed files with 4293 additions and 76 deletions

174
routes/apikey.py Normal file
View File

@@ -0,0 +1,174 @@
from flask import Blueprint, request, jsonify, render_template
from flask_login import login_required, current_user
from models import db, UserApiKey, ApiKeyDailyStat
from datetime import datetime, date
import secrets
apikey_bp = Blueprint('apikey', __name__, url_prefix='/user/apikey')
def generate_api_key():
"""生成 API Key"""
return f"sk_{secrets.token_hex(24)}"
@apikey_bp.route('/')
@login_required
def manage_page():
"""API Key 管理页面"""
return render_template('apikey/manage.html')
@apikey_bp.route('/list', methods=['GET'])
@login_required
def list_keys():
"""获取用户的 API Key 列表"""
keys = UserApiKey.query.filter_by(user_id=current_user.id).order_by(UserApiKey.created_at.desc()).all()
result = []
for key in keys:
# 获取今日调用次数
today_stat = ApiKeyDailyStat.query.filter_by(
api_key_id=key.id,
date=date.today()
).first()
result.append({
'id': key.id,
'name': key.name,
'api_key': key.api_key[:12] + '...' + key.api_key[-4:], # 隐藏中间部分
'is_active': key.is_active,
'daily_limit': key.daily_limit,
'total_calls': key.total_calls,
'today_calls': today_stat.call_count if today_stat else 0,
'last_used_at': key.last_used_at.strftime('%Y-%m-%d %H:%M:%S') if key.last_used_at else None,
'created_at': key.created_at.strftime('%Y-%m-%d %H:%M:%S')
})
return jsonify({
'success': True,
'data': result
})
@apikey_bp.route('/create', methods=['POST'])
@login_required
def create_key():
"""创建新的 API Key"""
data = request.get_json()
name = data.get('name', '').strip()
if not name:
return jsonify({'success': False, 'message': '请输入 Key 名称'}), 400
if len(name) > 100:
return jsonify({'success': False, 'message': 'Key 名称不能超过100个字符'}), 400
# 检查用户已有的 Key 数量限制每个用户最多5个
key_count = UserApiKey.query.filter_by(user_id=current_user.id).count()
if key_count >= 5:
return jsonify({'success': False, 'message': '每个用户最多创建5个 API Key'}), 400
# 生成新的 API Key
api_key = generate_api_key()
# 根据用户等级设置每日限制
daily_limit = 100 # 默认
if current_user.group:
if current_user.group.id == 3: # VIP
daily_limit = 500
elif current_user.group.id == 4: # SVIP
daily_limit = 2000
new_key = UserApiKey(
user_id=current_user.id,
name=name,
api_key=api_key,
daily_limit=daily_limit
)
db.session.add(new_key)
db.session.commit()
return jsonify({
'success': True,
'message': 'API Key 创建成功',
'data': {
'id': new_key.id,
'name': new_key.name,
'api_key': api_key, # 只在创建时返回完整的 Key
'daily_limit': new_key.daily_limit
}
})
@apikey_bp.route('/delete/<int:key_id>', methods=['DELETE'])
@login_required
def delete_key(key_id):
"""删除 API Key"""
key = UserApiKey.query.filter_by(id=key_id, user_id=current_user.id).first()
if not key:
return jsonify({'success': False, 'message': 'API Key 不存在'}), 404
db.session.delete(key)
db.session.commit()
return jsonify({
'success': True,
'message': 'API Key 已删除'
})
@apikey_bp.route('/toggle/<int:key_id>', methods=['POST'])
@login_required
def toggle_key(key_id):
"""启用/禁用 API Key"""
key = UserApiKey.query.filter_by(id=key_id, user_id=current_user.id).first()
if not key:
return jsonify({'success': False, 'message': 'API Key 不存在'}), 404
key.is_active = not key.is_active
db.session.commit()
return jsonify({
'success': True,
'message': f"API Key 已{'启用' if key.is_active else '禁用'}",
'is_active': key.is_active
})
@apikey_bp.route('/stats/<int:key_id>', methods=['GET'])
@login_required
def get_stats(key_id):
"""获取 API Key 统计数据"""
key = UserApiKey.query.filter_by(id=key_id, user_id=current_user.id).first()
if not key:
return jsonify({'success': False, 'message': 'API Key 不存在'}), 404
# 获取最近7天的统计
from datetime import timedelta
stats = ApiKeyDailyStat.query.filter(
ApiKeyDailyStat.api_key_id == key_id,
ApiKeyDailyStat.date >= date.today() - timedelta(days=6)
).order_by(ApiKeyDailyStat.date.asc()).all()
result = []
for stat in stats:
result.append({
'date': stat.date.strftime('%Y-%m-%d'),
'call_count': stat.call_count,
'success_count': stat.success_count,
'fail_count': stat.fail_count
})
return jsonify({
'success': True,
'data': {
'key_name': key.name,
'total_calls': key.total_calls,
'daily_stats': result
}
})