Files
param-hub-python/modules/routes/api_reviews.py
T

159 lines
4.9 KiB
Python
Raw Normal View History

"""
产品审核 API
"""
import uuid
import json
from datetime import datetime
from flask import Blueprint, request, jsonify, session
from config import DATA_DIR, MODELS_FILE, GPUS_FILE, CPUS_FILE
from utils import load_data, save_data
reviews_bp = Blueprint('api_reviews', __name__)
PENDING_FILE = DATA_DIR / 'pending_reviews.json'
@reviews_bp.route('/api/reviews')
def api_reviews():
"""获取待审核列表"""
reviews = load_data(PENDING_FILE)
# 筛选参数
status = request.args.get('status', 'pending') # pending, approved, rejected, all
limit = int(request.args.get('limit', 100))
if status != 'all':
reviews = [r for r in reviews if r.get('status', 'pending') == status]
# 按时间倒序
reviews = sorted(reviews, key=lambda x: x.get('created_at', ''), reverse=True)
return jsonify(reviews[:limit])
@reviews_bp.route('/api/reviews/count')
def api_reviews_count():
"""获取待审核数量"""
reviews = load_data(PENDING_FILE)
pending_count = len([r for r in reviews if r.get('status', 'pending') == 'pending'])
return jsonify({'count': pending_count})
@reviews_bp.route('/api/reviews/<review_id>')
def api_review_detail(review_id):
"""获取审核详情"""
reviews = load_data(PENDING_FILE)
review = next((r for r in reviews if r['id'] == review_id), None)
if not review:
return jsonify({'error': 'Review not found'}), 404
return jsonify(review)
@reviews_bp.route('/api/reviews/<review_id>/approve', methods=['POST'])
def api_approve_review(review_id):
"""通过审核"""
reviews = load_data(PENDING_FILE)
review = next((r for r in reviews if r['id'] == review_id), None)
if not review:
return jsonify({'error': 'Review not found'}), 404
if review.get('status') != 'pending':
return jsonify({'error': '该申请已处理'}), 400
# 获取数据文件
category_id = review.get('category_id')
data_file = get_data_file(category_id)
if not data_file:
return jsonify({'error': 'Unknown category'}), 400
# 添加数据到正式文件
items = load_data(data_file)
item_data = review.get('data', {})
# 确保有ID和时间戳
if 'id' not in item_data or not item_data['id']:
item_data['id'] = uuid.uuid4().hex[:12]
item_data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
item_data['visible'] = True
item_data['approved'] = True
item_data['approved_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
items.append(item_data)
save_data(data_file, items)
# 更新审核状态
review['status'] = 'approved'
review['approved_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
review['approved_by'] = session.get('username', 'admin')
save_data(PENDING_FILE, reviews)
return jsonify({'success': True, 'item': item_data})
@reviews_bp.route('/api/reviews/<review_id>/reject', methods=['POST'])
def api_reject_review(review_id):
"""拒绝审核"""
reviews = load_data(PENDING_FILE)
review = next((r for r in reviews if r['id'] == review_id), None)
if not review:
return jsonify({'error': 'Review not found'}), 404
if review.get('status') != 'pending':
return jsonify({'error': '该申请已处理'}), 400
data = request.get_json() or {}
reason = data.get('reason', '')
# 更新审核状态
review['status'] = 'rejected'
review['rejected_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
review['rejected_by'] = session.get('username', 'admin')
review['reject_reason'] = reason
save_data(PENDING_FILE, reviews)
return jsonify({'success': True})
def get_data_file(category_id):
"""获取类别对应的数据文件"""
builtin_map = {
'ai-models': MODELS_FILE,
'gpus': GPUS_FILE,
'cpus': CPUS_FILE
}
if category_id in builtin_map:
return builtin_map[category_id]
# 动态分类
return DATA_DIR / f'items_{category_id}.json'
# ─── 内部函数:提交审核 ───────────────────────────────────────────────────────
def submit_for_review(category_id, data, source='web', submitter=None):
"""
提交产品到审核队列
参数:
category_id: 分类ID
data: 产品数据(dict)
source: 来源 web/api
submitter: 提交者
"""
reviews = load_data(PENDING_FILE)
review = {
'id': uuid.uuid4().hex[:12],
'category_id': category_id,
'data': data,
'source': source,
'submitter': submitter or 'anonymous',
'status': 'pending', # pending, approved, rejected
'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
}
reviews.append(review)
save_data(PENDING_FILE, reviews)
return review