Files
wecom_it_smart_desk/backend/app/utils/response.py
T

144 lines
5.2 KiB
Python
Raw Normal View History

# =============================================================================
# 企微IT智能服务台 — 统一响应格式工具
# =============================================================================
# 说明:定义所有 API 的统一响应格式和异常处理
# 格式:{code: 0, data: {}, message: "success"}
# code=0 表示成功,非0表示错误(1000+通用/2000+企微/3000+业务)
# =============================================================================
from typing import Any, Dict, Optional
from fastapi import Request
from fastapi.responses import JSONResponse
# --------------------------------------------------------------------------
# 统一响应函数
# --------------------------------------------------------------------------
def success_response(data: Any = None, message: str = "success") -> Dict[str, Any]:
"""构建成功响应。
所有 API 成功时都应使用此函数返回统一格式。
Args:
data: 业务数据(可以是字典、列表、None等)
message: 成功消息(默认 "success"
Returns:
Dict[str, Any]: 统一格式的响应字典
示例: {"code": 0, "data": {...}, "message": "success"}
"""
return {
"code": 0,
"data": data,
"message": message,
}
def error_response(code: int, message: str, data: Any = None) -> Dict[str, Any]:
"""构建错误响应。
所有 API 错误时都应使用此函数返回统一格式。
Args:
code: 错误码(1000+通用/2000+企微/3000+业务)
message: 错误消息
data: 附加数据(可选,如验证错误详情)
Returns:
Dict[str, Any]: 统一格式的错误响应字典
示例: {"code": 1001, "data": null, "message": "参数错误"}
"""
return {
"code": code,
"data": data,
"message": message,
}
# --------------------------------------------------------------------------
# 业务异常类
# --------------------------------------------------------------------------
class AppException(Exception):
"""业务异常基类。
在业务逻辑中抛出此异常,全局异常处理器会自动转换为统一响应格式。
避免在每个路由函数中重复写 try/except 和响应构造代码。
Attributes:
code: 错误码
message: 错误消息
data: 附加数据
"""
def __init__(self, code: int, message: str, data: Any = None):
"""初始化业务异常。
Args:
code: 错误码
message: 错误消息
data: 附加数据
"""
self.code = code
self.message = message
self.data = data
super().__init__(self.message)
# --------------------------------------------------------------------------
# 预定义错误常量
# --------------------------------------------------------------------------
# 错误码规范:
# 0 = 成功
# 1000+ = 通用错误(参数错误、未授权等)
# 2000+ = 企微 API 错误
# 3000+ = 业务逻辑错误
# --- 通用错误 (1000+) ---
ERR_PARAMS = AppException(1001, "参数错误")
ERR_UNAUTHORIZED = AppException(1002, "未授权")
ERR_NOT_FOUND = AppException(1003, "资源不存在")
ERR_FORBIDDEN = AppException(1004, "无权限访问")
ERR_INTERNAL = AppException(1005, "服务器内部错误")
# --- 企微 API 错误 (2000+) ---
ERR_WECOM_TOKEN = AppException(2001, "企微 access_token 获取失败")
ERR_WECOM_SEND = AppException(2002, "企微消息发送失败")
ERR_WECOM_DECRYPT = AppException(2003, "企微消息解密失败")
ERR_WECOM_ENCRYPT = AppException(2004, "企微消息加密失败")
ERR_WECOM_VERIFY = AppException(2005, "企微回调签名验证失败")
ERR_WECOM_USER_INFO = AppException(2006, "企微用户信息获取失败")
# --- 业务逻辑错误 (3000+) ---
ERR_AGENT_OFFLINE = AppException(3001, "坐席不在线")
ERR_CONVERSATION_RESOLVED = AppException(3002, "会话已结单")
ERR_CONVERSATION_NOT_FOUND = AppException(3003, "会话不存在")
ERR_AGENT_NOT_FOUND = AppException(3004, "坐席不存在")
ERR_AGENT_BUSY = AppException(3005, "坐席已满负荷,无法接单")
ERR_DUPLICATE_ASSIGN = AppException(3006, "会话已分配坐席")
ERR_GRAB_NO_AGENT = AppException(3011, "该会话尚未分配坐席,请使用接单功能")
ERR_GRAB_SELF = AppException(3012, "不能接手自己的会话")
ERR_GRAB_NOT_SERVING = AppException(3013, "只能接手服务中的会话")
# --------------------------------------------------------------------------
# 全局异常处理器
# --------------------------------------------------------------------------
async def app_exception_handler(request: Request, exc: AppException) -> JSONResponse:
"""AppException 全局异常处理器。
当业务逻辑抛出 AppException 时,FastAPI 自动调用此处理器,
将异常转换为统一响应格式返回给前端。
Args:
request: 请求对象(FastAPI 自动传入)
exc: 业务异常对象(FastAPI 自动传入)
Returns:
JSONResponse: 统一格式的错误响应
"""
return JSONResponse(
status_code=200, # 业务错误仍返回 HTTP 200,通过 code 区分
content=error_response(exc.code, exc.message, exc.data),
)