from flask import request, jsonify, current_app from datetime import datetime from app import db from app.models import Product from . import api_bp from .decorators import require_admin from flask_login import login_required import traceback import sys @api_bp.route('/products', methods=['GET']) @require_admin def get_products(): """获取产品列表""" try: page = request.args.get('page', 1, type=int) per_page = min(request.args.get('per_page', 20, type=int), 100) keyword = request.args.get('keyword', '').strip() query = Product.query if keyword: query = query.filter( Product.product_name.like(f'%{keyword}%') | Product.description.like(f'%{keyword}%') ) query = query.order_by(Product.create_time.desc()) pagination = query.paginate(page=page, per_page=per_page, error_out=False) products = [product.to_dict(include_stats=True) for product in pagination.items] return jsonify({ 'success': True, 'data': { 'products': products, 'pagination': { 'page': page, 'per_page': per_page, 'total': pagination.total, 'pages': pagination.pages, 'has_prev': pagination.has_prev, 'has_next': pagination.has_next } } }) except Exception as e: current_app.logger.error(f"获取产品列表失败: {str(e)}") current_app.logger.error(f"错误类型: {type(e)}") current_app.logger.error(f"错误堆栈: {traceback.format_exc()}") return jsonify({ 'success': False, 'message': '服务器内部错误,请稍后重试' }), 500 @api_bp.route('/products', methods=['POST']) @require_admin def create_product(): """创建产品""" try: data = request.get_json() if not data: return jsonify({ 'success': False, 'message': '请求数据为空' }), 400 product_name = data.get('product_name', '').strip() description = data.get('description', '').strip() custom_id = data.get('product_id', '').strip() if not product_name: return jsonify({ 'success': False, 'message': '产品名称不能为空' }), 400 # 检查自定义ID是否重复 if custom_id: existing = Product.query.filter_by(product_id=custom_id).first() if existing: return jsonify({ 'success': False, 'message': '产品ID已存在' }), 400 # 创建产品 product = Product( product_id=custom_id if custom_id else None, product_name=product_name, description=description, status=1 ) db.session.add(product) db.session.commit() return jsonify({ 'success': True, 'message': '产品创建成功', 'data': product.to_dict() }) except Exception as e: db.session.rollback() current_app.logger.error(f"创建产品失败: {str(e)}") return jsonify({ 'success': False, 'message': '服务器内部错误' }), 500 @api_bp.route('/products/', methods=['GET']) @login_required def get_product(product_id): """获取产品详情""" try: product = Product.query.filter_by(product_id=product_id).first() if not product: return jsonify({ 'success': False, 'message': '产品不存在' }), 404 return jsonify({ 'success': True, 'data': product.to_dict(include_stats=True) }) except Exception as e: current_app.logger.error(f"获取产品详情失败: {str(e)}") return jsonify({ 'success': False, 'message': '服务器内部错误' }), 500 @api_bp.route('/products/', methods=['PUT']) @require_admin def update_product(product_id): """更新产品""" try: product = Product.query.filter_by(product_id=product_id).first() if not product: return jsonify({ 'success': False, 'message': '产品不存在' }), 404 data = request.get_json() if not data: return jsonify({ 'success': False, 'message': '请求数据为空' }), 400 if 'product_name' in data: product.product_name = data['product_name'].strip() if 'description' in data: product.description = data['description'].strip() if 'status' in data: product.status = data['status'] db.session.commit() return jsonify({ 'success': True, 'message': '产品更新成功', 'data': product.to_dict() }) except Exception as e: db.session.rollback() current_app.logger.error(f"更新产品失败: {str(e)}") return jsonify({ 'success': False, 'message': '服务器内部错误' }), 500 @api_bp.route('/products/', methods=['DELETE']) @require_admin def delete_product(product_id): """删除产品""" try: product = Product.query.filter_by(product_id=product_id).first() if not product: return jsonify({ 'success': False, 'message': '产品不存在' }), 404 # 检查是否有关联的卡密 license_count = product.licenses.count() if license_count > 0: return jsonify({ 'success': False, 'message': f'产品下还有 {license_count} 个卡密,无法删除' }), 400 db.session.delete(product) db.session.commit() return jsonify({ 'success': True, 'message': '产品删除成功' }) except Exception as e: db.session.rollback() current_app.logger.error(f"删除产品失败: {str(e)}") return jsonify({ 'success': False, 'message': '服务器内部错误' }), 500 @api_bp.route('/products/batch', methods=['DELETE']) @require_admin def batch_delete_products(): """批量删除产品""" try: data = request.get_json() if not data or 'product_ids' not in data: return jsonify({ 'success': False, 'message': '请求数据为空或缺少product_ids字段' }), 400 product_ids = data['product_ids'] if not isinstance(product_ids, list) or len(product_ids) == 0: return jsonify({ 'success': False, 'message': 'product_ids必须是非空列表' }), 400 # 查找所有要删除的产品 products = Product.query.filter(Product.product_id.in_(product_ids)).all() if len(products) != len(product_ids): found_ids = [p.product_id for p in products] missing_ids = [pid for pid in product_ids if pid not in found_ids] return jsonify({ 'success': False, 'message': f'以下产品不存在: {", ".join(missing_ids)}' }), 404 # 检查是否有产品有关联的卡密 undeletable_products = [] for product in products: license_count = product.licenses.count() if license_count > 0: undeletable_products.append({ 'product_id': product.product_id, 'product_name': product.product_name, 'license_count': license_count }) if undeletable_products: return jsonify({ 'success': False, 'message': '部分产品无法删除,因为有关联的卡密', 'undeletable_products': undeletable_products }), 400 # 批量删除产品 for product in products: db.session.delete(product) db.session.commit() return jsonify({ 'success': True, 'message': f'成功删除 {len(products)} 个产品' }) except Exception as e: db.session.rollback() current_app.logger.error(f"批量删除产品失败: {str(e)}") return jsonify({ 'success': False, 'message': '服务器内部错误' }), 500 @api_bp.route('/products/batch/status', methods=['PUT']) @require_admin def batch_update_product_status(): """批量更新产品状态""" try: data = request.get_json() if not data or 'product_ids' not in data or 'status' not in data: return jsonify({ 'success': False, 'message': '请求数据为空或缺少product_ids/status字段' }), 400 product_ids = data['product_ids'] status = data['status'] if not isinstance(product_ids, list) or len(product_ids) == 0: return jsonify({ 'success': False, 'message': 'product_ids必须是非空列表' }), 400 if status not in [0, 1]: return jsonify({ 'success': False, 'message': 'status必须是0(禁用)或1(启用)' }), 400 # 查找所有要更新的产品 products = Product.query.filter(Product.product_id.in_(product_ids)).all() if len(products) != len(product_ids): found_ids = [p.product_id for p in products] missing_ids = [pid for pid in product_ids if pid not in found_ids] return jsonify({ 'success': False, 'message': f'以下产品不存在: {", ".join(missing_ids)}' }), 404 # 批量更新产品状态 for product in products: product.status = status db.session.commit() status_name = '启用' if status == 1 else '禁用' return jsonify({ 'success': True, 'message': f'成功{status_name} {len(products)} 个产品' }) except Exception as e: db.session.rollback() current_app.logger.error(f"批量更新产品状态失败: {str(e)}") return jsonify({ 'success': False, 'message': '服务器内部错误' }), 500