""" CPU CRUD API """ import uuid import json from datetime import datetime from flask import Blueprint, request, jsonify, Response from config import CPUS_FILE from utils import load_data, save_data, parse_date_to_timestamp cpus_bp = Blueprint('api_cpus', __name__) def is_review_required(): try: import app as app_module return getattr(app_module, 'REQUIRE_REVIEW', False) except: return False def _safe_sort_key(x, key): val = x.get(key) if val is None: return 0 if key in ['cores', 'threads', 'views'] else '' return val @cpus_bp.route('/api/cpus') def api_cpus(): cpus = load_data(CPUS_FILE) hide_hidden = request.args.get('all', '0') == '0' if hide_hidden: cpus = [c for c in cpus if c.get('visible', True)] keyword = request.args.get('q', '').strip().lower() if keyword: cpus = [c for c in cpus if keyword in c.get('name', '').lower() or keyword in c.get('manufacturer', '').lower()] sort_by = request.args.get('sort', 'default') reverse = request.args.get('order', 'desc') == 'desc' if sort_by == 'default': cpus = sorted(cpus, key=lambda x: ( not x.get('is_pinned', False), -(parse_date_to_timestamp(x.get('publish_date', '')) or parse_date_to_timestamp(x.get('created_at', '')) or 0) )) elif sort_by in ['name', 'cores', 'threads', 'price_usd', 'created_at', 'publish_date', 'views', 'updated_at']: cpus = sorted(cpus, key=lambda x: _safe_sort_key(x, sort_by), reverse=reverse) return jsonify(cpus) @cpus_bp.route('/api/cpus/') def api_cpu_detail(cpu_id): cpus = load_data(CPUS_FILE) cpu = next((c for c in cpus if c['id'] == cpu_id), None) if not cpu: return jsonify({'error': 'CPU not found'}), 404 return jsonify(cpu) @cpus_bp.route('/api/cpus', methods=['POST']) def api_create_cpu(): data = request.get_json() # 审核模式 if is_review_required(): from modules.routes.api_reviews import submit_for_review from modules.routes.api_notifications import create_notification review = submit_for_review('cpus', data, source='web') product_name = data.get('name', '未知') create_notification( title='新产品待审核', message=f'有新的CPU "{product_name}"待审核', level='warning', category='review', data={'review_id': review['id'], 'category': 'cpus'} ) return jsonify({'success': True, 'message': '已提交审核,请等待管理员确认', 'review_id': review['id']}) cpus = load_data(CPUS_FILE) data['id'] = uuid.uuid4().hex[:12] data['created_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') data['visible'] = data.get('visible', True) data['publish_date'] = data.get('publish_date', '') data['views'] = data.get('views', 0) data['is_pinned'] = data.get('is_pinned', False) cpus.append(data) save_data(CPUS_FILE, cpus) return jsonify(data) @cpus_bp.route('/api/cpus/', methods=['PUT']) def api_update_cpu(cpu_id): data = request.get_json() cpus = load_data(CPUS_FILE) cpu = next((c for c in cpus if c['id'] == cpu_id), None) if not cpu: return jsonify({'error': 'CPU not found'}), 404 cpu.update(data) cpu['updated_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S') save_data(CPUS_FILE, cpus) return jsonify(cpu) @cpus_bp.route('/api/cpus/', methods=['DELETE']) def api_delete_cpu(cpu_id): cpus = load_data(CPUS_FILE) cpus = [c for c in cpus if c['id'] != cpu_id] save_data(CPUS_FILE, cpus) return jsonify({'success': True}) @cpus_bp.route('/api/cpus//visible', methods=['POST']) def api_toggle_cpu_visible(cpu_id): cpus = load_data(CPUS_FILE) cpu = next((c for c in cpus if c['id'] == cpu_id), None) if not cpu: return jsonify({'error': 'CPU not found'}), 404 cpu['visible'] = not cpu.get('visible', True) save_data(CPUS_FILE, cpus) return jsonify({'success': True, 'visible': cpu['visible']}) # ─── 导出导入 ─────────────────────────────────────────────────────── @cpus_bp.route('/api/cpus/export', methods=['GET']) def api_export_cpus(): """导出所有CPU数据""" try: cpus = load_data(CPUS_FILE) export_data = { 'type': 'cpus', 'items': cpus, 'count': len(cpus), 'export_time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'version': '1.0' } json_str = json.dumps(export_data, ensure_ascii=False, indent=2) response = Response( json_str, mimetype='application/json', headers={'Content-Disposition': f'attachment; filename=cpus-export-{datetime.now().strftime("%Y%m%d%H%M%S")}.json'} ) return response except Exception as e: return jsonify({'error': str(e)}), 500 @cpus_bp.route('/api/cpus/import', methods=['GET', 'POST']) def api_import_cpus(): """导入CPU数据""" try: if request.method == 'GET': return jsonify({'endpoint': '/api/cpus/import', 'method': 'POST', 'params': {'mode': 'merge 或 replace'}}) import_data = request.get_json() if not import_data or 'items' not in import_data: return jsonify({'error': '缺少 items 字段'}), 400 mode = request.args.get('mode', 'merge') cpus = load_data(CPUS_FILE) imported_items = import_data['items'] result = {'success': True, 'imported': 0, 'updated': 0, 'skipped': []} for item in imported_items: existing = next((c for c in cpus if c['id'] == item['id']), None) if existing: if mode == 'replace': existing.update(item) result['updated'] += 1 else: result['skipped'].append(item['id']) else: cpus.append(item) result['imported'] += 1 save_data(CPUS_FILE, cpus) return jsonify(result) except Exception as e: return jsonify({'error': str(e)}), 500