refactor(api): 统一响应格式迁移 + 异步任务系统 + 状态码体系完善

- 将全部路由文件(12个)的 jsonify 响应迁移至 success_response/error_response 统一格式
- 修复 sync_routes.py error_response 参数错误(P0)
- 新增异步任务系统:task_registry + task_routes
- 新增状态码:TASK_NOT_FOUND(4014)、TASK_CONFLICT(4015)、REINDEX_ERROR(5040)
- 修正 task_routes/exam_pkg 中语义不匹配的状态码
- 更新 curl 测试手册、后端对接规范文档
- 添加缓存性能报告和 Redis 迁移计划
This commit is contained in:
lacerate551
2026-06-05 22:56:00 +08:00
parent 54a6815ad4
commit 183a57e7f1
19 changed files with 2659 additions and 548 deletions

View File

@@ -33,6 +33,11 @@
from flask import Blueprint, request, jsonify
from auth.gateway import require_gateway_auth, require_role
from core.status_codes import (
SUCCESS, CREATED, DELETE_SUCCESS, UPDATE_SUCCESS,
BAD_REQUEST, NOT_FOUND, INTERNAL_ERROR
)
from api.response_utils import success_response, error_response
import logging
logger = logging.getLogger(__name__)
@@ -75,10 +80,10 @@ def submit_feedback():
user_id = data.get('user_id', '')
if not session_id or not query or rating is None:
return jsonify({"error": "缺少必要参数"}), 400
return error_response("MISSING_PARAMS", BAD_REQUEST, "缺少必要参数", http_status=400)
if rating not in [1, -1]:
return jsonify({"error": "rating 必须是 1 或 -1"}), 400
return error_response("INVALID_PARAMS", BAD_REQUEST, "rating 必须是 1 或 -1", http_status=400)
try:
feedback_service = _get_feedback_service()
@@ -91,15 +96,14 @@ def submit_feedback():
reason=reason,
user_id=user_id
)
return jsonify({
"success": True,
return success_response(data={
"feedback_id": result['feedback_id'],
"faq_suggested": result.get('faq_suggested', False),
"suggestion_id": result.get('suggestion_id')
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/feedback/stats', methods=['GET'])
@@ -112,13 +116,12 @@ def get_feedback_stats():
try:
feedback_db = _get_feedback_db()
stats = feedback_db.get_feedback_stats(start_date, end_date)
return jsonify({
"success": True,
return success_response(data={
"stats": stats
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/feedback/list', methods=['GET'])
@@ -140,14 +143,13 @@ def get_feedback_list():
end_date=end_date,
limit=limit
)
return jsonify({
"success": True,
return success_response(data={
"feedbacks": feedbacks,
"total": len(feedbacks)
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/reports/weekly', methods=['GET'])
@@ -157,13 +159,12 @@ def get_weekly_report():
try:
feedback_service = _get_feedback_service()
report = feedback_service.generate_report("weekly")
return jsonify({
"success": True,
return success_response(data={
"report": report.to_dict()
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/reports/monthly', methods=['GET'])
@@ -173,13 +174,12 @@ def get_monthly_report():
try:
feedback_service = _get_feedback_service()
report = feedback_service.generate_report("monthly")
return jsonify({
"success": True,
return success_response(data={
"report": report.to_dict()
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/faq', methods=['GET'])
@@ -192,14 +192,13 @@ def get_faq_list():
try:
feedback_db = _get_feedback_db()
faqs = feedback_db.get_faqs(status=status, limit=limit)
return jsonify({
"success": True,
return success_response(data={
"faqs": faqs,
"total": len(faqs)
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/faq', methods=['POST'])
@@ -220,7 +219,7 @@ def create_faq():
answer = data.get('answer')
if not question or not answer:
return jsonify({"error": "缺少问题或答案"}), 400
return error_response("MISSING_PARAMS", BAD_REQUEST, "缺少问题或答案", http_status=400)
try:
from services.feedback import FAQ
@@ -235,15 +234,14 @@ def create_faq():
)
faq_id = feedback_db.add_faq(faq)
return jsonify({
"success": True,
return success_response(data={
"faq_id": faq_id,
"status": "draft",
"message": "FAQ已创建请通过 /faq/<id>/approve 接口确认后生效"
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/faq/<int:faq_id>/approve', methods=['POST'])
@@ -263,10 +261,10 @@ def approve_faq(faq_id):
# 检查 FAQ 状态
faq = feedback_db.get_faq(faq_id)
if not faq:
return jsonify({"error": "FAQ不存在"}), 404
return error_response("NOT_FOUND", NOT_FOUND, "FAQ不存在", http_status=404)
if faq.get('status') == 'approved':
return jsonify({"success": True, "message": "FAQ已经是批准状态"})
return success_response(message="FAQ已经是批准状态")
# 更新状态为 approved
feedback_db.update_faq(faq_id, {"status": "approved"})
@@ -279,15 +277,14 @@ def approve_faq(faq_id):
answer=faq['answer']
)
return jsonify({
"success": True,
return success_response(data={
"faq_id": faq_id,
"sync_status": "synced" if sync_success else "sync_failed",
"message": "FAQ已批准并同步到知识库"
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/faq/<int:faq_id>', methods=['PUT'])
@@ -303,11 +300,11 @@ def update_faq(faq_id):
# 获取更新前的 FAQ 信息(用于判断是否需要重新同步)
old_faq = feedback_db.get_faq(faq_id)
if not old_faq:
return jsonify({"error": "FAQ不存在"}), 404
return error_response("NOT_FOUND", NOT_FOUND, "FAQ不存在", http_status=404)
updated = feedback_db.update_faq(faq_id, data)
if not updated:
return jsonify({"error": "FAQ更新失败"}), 500
return error_response("UPDATE_FAILED", INTERNAL_ERROR, "FAQ更新失败", http_status=500)
# 检查是否需要重新同步向量库question 或 answer 变更时)
need_sync = False
@@ -331,14 +328,13 @@ def update_faq(faq_id):
)
sync_status = "synced" if sync_success else "sync_failed"
return jsonify({
"success": True,
return success_response(data={
"message": "FAQ更新成功",
"sync_status": sync_status
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/faq/<int:faq_id>', methods=['DELETE'])
@@ -365,13 +361,10 @@ def delete_faq(faq_id):
feedback_service = _get_feedback_service()
feedback_service._delete_faq_vectors(faq_id)
return jsonify({
"success": deleted,
"message": "FAQ删除成功" if deleted else "FAQ不存在"
})
return success_response(data={"deleted": deleted}, message="FAQ删除成功" if deleted else "FAQ不存在")
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/faq/suggestions', methods=['GET'])
@@ -385,14 +378,13 @@ def get_faq_suggestions():
try:
feedback_db = _get_feedback_db()
suggestions = feedback_db.get_faq_suggestions(status=status, limit=limit)
return jsonify({
"success": True,
return success_response(data={
"suggestions": suggestions,
"total": len(suggestions)
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/faq/suggestions/<int:suggestion_id>/approve', methods=['POST'])
@@ -418,17 +410,16 @@ def approve_faq_suggestion(suggestion_id):
)
if result.get('success'):
return jsonify({
"success": True,
return success_response(data={
"faq_id": result['faq_id'],
"sync_status": result.get('sync_status'),
"message": "FAQ建议已批准并同步到知识库"
})
else:
return jsonify({"error": result.get('error', '批准失败')}), 400
return error_response("APPROVE_FAILED", BAD_REQUEST, result.get('error', '批准失败'), http_status=400)
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/faq/suggestions/<int:suggestion_id>/reject', methods=['POST'])
@@ -439,13 +430,13 @@ def reject_faq_suggestion(suggestion_id):
try:
feedback_db = _get_feedback_db()
rejected = feedback_db.reject_faq_suggestion(suggestion_id)
return jsonify({
"success": rejected,
return success_response(data={
"rejected": rejected,
"message": "FAQ建议已拒绝" if rejected else "建议不存在"
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
# ==================== Bad Case 分析接口 ====================
@@ -477,8 +468,7 @@ def get_bad_cases():
for case in bad_cases:
case['status'] = 'pending' # pending/resolved/ignored
return jsonify({
"success": True,
return success_response(data={
"bad_cases": bad_cases,
"blacklisted_sources": blacklisted_sources,
"suggestions": [
@@ -489,7 +479,7 @@ def get_bad_cases():
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)
@feedback_bp.route('/feedback/blacklist', methods=['GET'])
@@ -507,12 +497,11 @@ def get_chunk_blacklist():
feedback_service = _get_feedback_service()
blacklist = feedback_service.get_chunk_blacklist(min_dislikes=min_dislikes)
return jsonify({
"success": True,
return success_response(data={
"blacklist": list(blacklist),
"count": len(blacklist),
"usage": "在检索时过滤这些来源以提升回答质量"
})
except Exception as e:
logger.error(f"反馈操作异常: {e}")
return jsonify({"error": "操作失败,请稍后重试"}), 500
return error_response("OPERATION_FAILED", INTERNAL_ERROR, "操作失败,请稍后重试", http_status=500)