#!/usr/bin/env python # -*- coding: utf-8 -*- """ 提示词管理接口 """ from flask import Blueprint, request, jsonify import logging from datetime import datetime from auth_utils import require_auth, AuthUtils from database_config import get_db_manager, format_datetime_fields from log_utils import log_create, log_update, log_delete, log_error, log_operation logger = logging.getLogger('article_server') # 创建蓝图 prompt_bp = Blueprint('prompt', __name__, url_prefix='/api/prompts') @prompt_bp.route('/list_info', methods=['GET']) @require_auth def get_prompts_list_info(): """获取提示词列表(简化版,仅返回4个字段)""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[获取提示词列表简化版] 开始处理请求, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') logger.info(f"[获取提示词列表简化版] 用户信息 - 用户ID: {current_user.get('user_id')}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: logger.warning(f"[获取提示词列表简化版] 无法获取企业ID, IP: {client_ip}") return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 db_manager = get_db_manager() # 查询提示词列表(仅返回4个字段,优化性能) sql = """ SELECT id, prompt_workflow_name, created_at, updated_at FROM ai_prompt_workflow WHERE enterprise_id = %s ORDER BY created_at DESC """ prompts = db_manager.execute_query(sql, (enterprise_id,)) # 格式化日期时间字段 prompts = format_datetime_fields(prompts) logger.info(f"[获取提示词列表简化版] 查询成功, 返回数量: {len(prompts)}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': 'success', 'data': { 'list': prompts }, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[获取提示词列表简化版] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500 @prompt_bp.route('/list', methods=['GET']) @require_auth def get_prompts_list(): """获取提示词列表""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[获取提示词列表] 开始处理请求, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') user_id = current_user.get('user_id') logger.info(f"[获取提示词列表] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 # 获取查询参数 page = int(request.args.get('page', 1)) page_size = int(request.args.get('pageSize', 20)) # 计算偏移量 offset = (page - 1) * page_size db_manager = get_db_manager() # 查询总数 count_sql = "SELECT COUNT(*) as total FROM ai_prompt_workflow WHERE enterprise_id = %s" count_result = db_manager.execute_query(count_sql, (enterprise_id,)) total = count_result[0]['total'] # 查询提示词列表 sql = """ SELECT id, prompt_workflow_name, workflow_id, content, usage_count, created_at, updated_at FROM ai_prompt_workflow WHERE enterprise_id = %s ORDER BY created_at DESC LIMIT %s OFFSET %s """ prompts = db_manager.execute_query(sql, (enterprise_id, page_size, offset)) # 查询每个提示词的标签 for prompt in prompts: tag_sql = """ SELECT t.id, t.tag_name FROM ai_prompt_tags t INNER JOIN ai_prompt_tags_relation r ON t.id = r.tag_id WHERE r.prompt_workflow_id = %s """ tags = db_manager.execute_query(tag_sql, (prompt['id'],)) prompt['tags'] = [tag['tag_name'] for tag in tags] # 格式化日期时间字段 prompts = format_datetime_fields(prompts) logger.info(f"[获取提示词列表] 查询成功, 总数: {total}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': 'success', 'data': { 'total': total, 'list': prompts }, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[获取提示词列表] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500 @prompt_bp.route('/create', methods=['POST']) @require_auth def create_prompt(): """创建提示词""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[创建提示词] 开始处理请求, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') user_id = current_user.get('user_id') logger.info(f"[创建提示词] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 data = request.get_json() if not data: return jsonify({ 'code': 400, 'message': '请求参数错误', 'data': None }), 400 # 验证必需字段 required_fields = ['prompt_workflow_name', 'content'] for field in required_fields: if not data.get(field): return jsonify({ 'code': 400, 'message': f'缺少必需字段: {field}', 'data': None }), 400 db_manager = get_db_manager() # 生成workflow_id import uuid workflow_id = f"WF-{str(uuid.uuid4())[:8].upper()}" # 创建提示词 sql = """ INSERT INTO ai_prompt_workflow (enterprise_id, prompt_workflow_name, workflow_id, content, usage_count) VALUES (%s, %s, %s, %s, %s) """ prompt_id = db_manager.execute_insert(sql, ( enterprise_id, data['prompt_workflow_name'], workflow_id, data['content'], 0 )) # 记录SQL操作日志 log_create( target_type='prompt_workflow', target_id=prompt_id, description=f"创建提示词: {data['prompt_workflow_name']}" ) # 添加标签关联 if data.get('tags'): # ✅ 去重处理,避免重复标签导致唯一索引冲突 unique_tags = list(set(data['tags'])) # 去除重复标签 processed_tag_ids = set() # 记录已处理的 tag_id for tag_name in unique_tags: if not tag_name or not tag_name.strip(): # 跳过空标签 continue tag_name = tag_name.strip() # ✅ 查找或创建标签(基于 enterprise_id 隔离) tag_sql = "SELECT id FROM ai_prompt_tags WHERE enterprise_id = %s AND tag_name = %s" tag_result = db_manager.execute_query(tag_sql, (enterprise_id, tag_name)) if tag_result: tag_id = tag_result[0]['id'] else: tag_insert_sql = "INSERT INTO ai_prompt_tags (enterprise_id, tag_name, created_user_id) VALUES (%s, %s, %s)" tag_id = db_manager.execute_insert(tag_insert_sql, (enterprise_id, tag_name, current_user.get('user_id', 0))) # ✅ 检查是否已经处理过该 tag_id,避免重复插入 if tag_id in processed_tag_ids: continue processed_tag_ids.add(tag_id) # ✅ 创建关联(添加 enterprise_id) try: rel_sql = "INSERT INTO ai_prompt_tags_relation (enterprise_id, prompt_workflow_id, prompt_workflow_name, tag_id, tag_name, created_user_id) VALUES (%s, %s, %s, %s, %s, %s)" db_manager.execute_insert(rel_sql, (enterprise_id, prompt_id, data['prompt_workflow_name'], tag_id, tag_name, current_user.get('user_id', 0))) except Exception as rel_error: # 如果关联已存在,跳过 logger.warning(f"标签关联已存在: prompt_id={prompt_id}, tag_id={tag_id}, error={str(rel_error)}") continue logger.info(f"[创建提示词] 创建成功, ID: {prompt_id}, 名称: {data['prompt_workflow_name']}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': '创建成功', 'data': { 'id': prompt_id, 'prompt_workflow_name': data['prompt_workflow_name'] }, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[创建提示词] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500 @prompt_bp.route('/', methods=['PUT']) @require_auth def update_prompt(prompt_id): """更新提示词""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[更新提示词] 开始处理请求, ID: {prompt_id}, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') user_id = current_user.get('user_id') logger.info(f"[更新提示词] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 data = request.get_json() if not data: return jsonify({ 'code': 400, 'message': '请求参数错误', 'data': None }), 400 db_manager = get_db_manager() # 检查提示词是否存在且属于当前企业 check_sql = "SELECT id FROM ai_prompt_workflow WHERE id = %s AND enterprise_id = %s" existing = db_manager.execute_query(check_sql, (prompt_id, enterprise_id)) if not existing: return jsonify({ 'code': 404, 'message': '提示词不存在', 'data': None }), 404 # 构建更新字段 update_fields = [] params = [] if 'prompt_workflow_name' in data: update_fields.append("prompt_workflow_name = %s") params.append(data['prompt_workflow_name']) if 'content' in data: update_fields.append("content = %s") params.append(data['content']) if update_fields: params.append(prompt_id) sql = f"UPDATE ai_prompt_workflow SET {', '.join(update_fields)}, updated_at = NOW() WHERE id = %s" db_manager.execute_update(sql, params) # 记录SQL操作日志 log_update( target_type='prompt_workflow', target_id=prompt_id, description=f"更新提示词字段: {', '.join(update_fields)}" ) # 更新标签关联 if 'tags' in data: # 删除旧标签关联 del_sql = "DELETE FROM ai_prompt_tags_relation WHERE prompt_workflow_id = %s" db_manager.execute_update(del_sql, (prompt_id,)) # ✅ 去重处理,避免重复标签导致唯一索引冲突 unique_tags = list(set(data['tags'])) # 去除重复标签 processed_tag_ids = set() # 记录已处理的 tag_id # 查询prompt_workflow_name prompt_info = db_manager.execute_query("SELECT prompt_workflow_name FROM ai_prompt_workflow WHERE id = %s", (prompt_id,)) prompt_workflow_name = prompt_info[0]['prompt_workflow_name'] if prompt_info else '' # 添加新标签 for tag_name in unique_tags: if not tag_name or not tag_name.strip(): # 跳过空标签 continue tag_name = tag_name.strip() # ✅ 查找或创建标签(基于 enterprise_id 隔离) tag_sql = "SELECT id FROM ai_prompt_tags WHERE enterprise_id = %s AND tag_name = %s" tag_result = db_manager.execute_query(tag_sql, (enterprise_id, tag_name)) if tag_result: tag_id = tag_result[0]['id'] else: tag_insert_sql = "INSERT INTO ai_prompt_tags (enterprise_id, tag_name, created_user_id) VALUES (%s, %s, %s)" tag_id = db_manager.execute_insert(tag_insert_sql, (enterprise_id, tag_name, current_user.get('user_id', 0))) # ✅ 检查是否已经处理过该 tag_id,避免重复插入 if tag_id in processed_tag_ids: continue processed_tag_ids.add(tag_id) # ✅ 创建关联(添加 enterprise_id) try: rel_sql = "INSERT INTO ai_prompt_tags_relation (enterprise_id, prompt_workflow_id, prompt_workflow_name, tag_id, tag_name, created_user_id) VALUES (%s, %s, %s, %s, %s, %s)" db_manager.execute_insert(rel_sql, (enterprise_id, prompt_id, prompt_workflow_name, tag_id, tag_name, current_user.get('user_id', 0))) except Exception as rel_error: # 如果关联已存在,跳过 logger.warning(f"标签关联已存在: prompt_id={prompt_id}, tag_id={tag_id}, error={str(rel_error)}") continue logger.info(f"[更新提示词] 更新成功, ID: {prompt_id}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': '更新成功', 'data': None, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[更新提示词] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500 @prompt_bp.route('/', methods=['DELETE']) @require_auth def delete_prompt(prompt_id): """删除提示词""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[删除提示词] 开始处理请求, ID: {prompt_id}, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') user_id = current_user.get('user_id') logger.info(f"[删除提示词] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 db_manager = get_db_manager() # 检查提示词是否存在且属于当前企业 check_sql = "SELECT id, prompt_workflow_name FROM ai_prompt_workflow WHERE id = %s AND enterprise_id = %s" existing = db_manager.execute_query(check_sql, (prompt_id, enterprise_id)) if not existing: return jsonify({ 'code': 404, 'message': '提示词不存在', 'data': None }), 404 # 删除标签关联 del_rel_sql = "DELETE FROM ai_prompt_tags_relation WHERE prompt_workflow_id = %s" db_manager.execute_update(del_rel_sql, (prompt_id,)) # 删除提示词 sql = "DELETE FROM ai_prompt_workflow WHERE id = %s" db_manager.execute_update(sql, (prompt_id,)) # 记录SQL操作日志 log_delete( target_type='prompt_workflow', target_id=prompt_id, description=f"删除提示词: {existing[0]['prompt_workflow_name']}" ) logger.info(f"[删除提示词] 删除成功, ID: {prompt_id}, 名称: {existing[0]['prompt_workflow_name']}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': '删除成功', 'data': None, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[删除提示词] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500 # ==================== 提示词标签管理 (ai_prompt_tags) ==================== @prompt_bp.route('/tags/list', methods=['GET']) @require_auth def get_tags_list(): """获取标签列表""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[获取标签列表] 开始处理请求, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') user_id = current_user.get('user_id') logger.info(f"[获取标签列表] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 # 获取查询参数 page = int(request.args.get('page', 1)) page_size = int(request.args.get('pageSize', 20)) keyword = request.args.get('keyword', '').strip() # 计算偏移量 offset = (page - 1) * page_size db_manager = get_db_manager() # ✅ 构建查询条件(基于 enterprise_id 隔离) where_conditions = ["enterprise_id = %s"] params = [enterprise_id] if keyword: where_conditions.append("tag_name LIKE %s") params.append(f"%{keyword}%") where_clause = " WHERE " + " AND ".join(where_conditions) # 查询总数 count_sql = f"SELECT COUNT(*) as total FROM ai_prompt_tags{where_clause}" count_result = db_manager.execute_query(count_sql, params) total = count_result[0]['total'] # 查询标签列表 sql = f""" SELECT id, tag_name, created_user_id, created_at, updated_at FROM ai_prompt_tags {where_clause} ORDER BY created_at DESC LIMIT %s OFFSET %s """ params.extend([page_size, offset]) tags = db_manager.execute_query(sql, params) # 格式化日期时间字段 tags = format_datetime_fields(tags) logger.info(f"[获取标签列表] 查询成功, 总数: {total}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': 'success', 'data': { 'total': total, 'list': tags }, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[获取标签列表] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500 @prompt_bp.route('/tags/create', methods=['POST']) @require_auth def create_tag(): """创建标签""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[创建标签] 开始处理请求, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') user_id = current_user.get('user_id', 0) logger.info(f"[创建标签] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 data = request.get_json() if not data or not data.get('tag_name'): return jsonify({ 'code': 400, 'message': '标签名称不能为空', 'data': None }), 400 db_manager = get_db_manager() # ✅ 检查标签是否已存在(基于 enterprise_id 隔离) check_sql = "SELECT id FROM ai_prompt_tags WHERE enterprise_id = %s AND tag_name = %s" existing = db_manager.execute_query(check_sql, (enterprise_id, data['tag_name'])) if existing: return jsonify({ 'code': 409, 'message': '标签名称已存在', 'data': None }), 409 # ✅ 创建标签(添加 enterprise_id) sql = """ INSERT INTO ai_prompt_tags (enterprise_id, tag_name, created_user_id) VALUES (%s, %s, %s) """ tag_id = db_manager.execute_insert(sql, (enterprise_id, data['tag_name'], user_id)) # 记录SQL操作日志 log_create( target_type='prompt_tag', target_id=tag_id, description=f"创建标签: {data['tag_name']}" ) logger.info(f"[创建标签] 创建成功, ID: {tag_id}, 名称: {data['tag_name']}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': '创建成功', 'data': { 'id': tag_id, 'tag_name': data['tag_name'] }, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[创建标签] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500 @prompt_bp.route('/tags/', methods=['PUT']) @require_auth def update_tag(tag_id): """更新标签""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[更新标签] 开始处理请求, ID: {tag_id}, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') user_id = current_user.get('user_id') logger.info(f"[更新标签] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 data = request.get_json() if not data or not data.get('tag_name'): return jsonify({ 'code': 400, 'message': '标签名称不能为空', 'data': None }), 400 db_manager = get_db_manager() # ✅ 检查标签是否存在(基于 enterprise_id 隔离) check_sql = "SELECT id FROM ai_prompt_tags WHERE id = %s AND enterprise_id = %s" existing = db_manager.execute_query(check_sql, (tag_id, enterprise_id)) if not existing: return jsonify({ 'code': 404, 'message': '标签不存在', 'data': None }), 404 # ✅ 检查新名称是否与其他标签重复(基于 enterprise_id 隔离) dup_sql = "SELECT id FROM ai_prompt_tags WHERE enterprise_id = %s AND tag_name = %s AND id != %s" duplicate = db_manager.execute_query(dup_sql, (enterprise_id, data['tag_name'], tag_id)) if duplicate: return jsonify({ 'code': 409, 'message': '标签名称已存在', 'data': None }), 409 # 更新标签 sql = "UPDATE ai_prompt_tags SET tag_name = %s, updated_at = NOW() WHERE id = %s" db_manager.execute_update(sql, (data['tag_name'], tag_id)) # 同步更新关系表中的标签名称 rel_sql = "UPDATE ai_prompt_tags_relation SET tag_name = %s WHERE tag_id = %s" db_manager.execute_update(rel_sql, (data['tag_name'], tag_id)) # 记录SQL操作日志 log_update( target_type='prompt_tag', target_id=tag_id, description=f"更新标签: {data['tag_name']}" ) logger.info(f"[更新标签] 更新成功, ID: {tag_id}, 名称: {data['tag_name']}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': '更新成功', 'data': None, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[更新标签] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500 @prompt_bp.route('/tags/', methods=['DELETE']) @require_auth def delete_tag(tag_id): """删除标签""" client_ip = request.environ.get('HTTP_X_FORWARDED_FOR', request.environ.get('REMOTE_ADDR', '未知')) logger.info(f"[删除标签] 开始处理请求, ID: {tag_id}, IP: {client_ip}") try: current_user = AuthUtils.get_current_user() enterprise_id = current_user.get('enterprise_id') user_id = current_user.get('user_id') logger.info(f"[删除标签] 用户信息 - 用户ID: {user_id}, 企业ID: {enterprise_id}, IP: {client_ip}") if not enterprise_id: return jsonify({ 'code': 400, 'message': '无法获取企业ID', 'data': None }), 400 db_manager = get_db_manager() # ✅ 检查标签是否存在(基于 enterprise_id 隔离) check_sql = "SELECT id, tag_name FROM ai_prompt_tags WHERE id = %s AND enterprise_id = %s" existing = db_manager.execute_query(check_sql, (tag_id, enterprise_id)) if not existing: return jsonify({ 'code': 404, 'message': '标签不存在', 'data': None }), 404 # 检查是否有提示词正在使用该标签 rel_sql = "SELECT COUNT(*) as count FROM ai_prompt_tags_relation WHERE tag_id = %s" rel_result = db_manager.execute_query(rel_sql, (tag_id,)) if rel_result[0]['count'] > 0: return jsonify({ 'code': 409, 'message': '该标签正在被使用,无法删除', 'data': None }), 409 # 删除标签 sql = "DELETE FROM ai_prompt_tags WHERE id = %s" db_manager.execute_update(sql, (tag_id,)) # 记录SQL操作日志 log_delete( target_type='prompt_tag', target_id=tag_id, description=f"删除标签: {existing[0]['tag_name']}" ) logger.info(f"[删除标签] 删除成功, ID: {tag_id}, 名称: {existing[0]['tag_name']}, 企业ID: {enterprise_id}, IP: {client_ip}") return jsonify({ 'code': 200, 'message': '删除成功', 'data': None, 'timestamp': int(datetime.now().timestamp() * 1000) }) except Exception as e: logger.error(f"[删除标签] 处理请求时发生错误: {str(e)}", exc_info=True) return jsonify({ 'code': 500, 'message': '服务器内部错误', 'data': None }), 500