""" app/core/response.py — 统一响应包络 成功:{ "code": 0, "data": {...} } 失败:{ "code": <错误码>, "message": "用户可读信息" } HTTP 状态码与业务 code 分离(契约§0)。 """ from typing import Any from fastapi import HTTPException from fastapi.responses import JSONResponse from app.constants.enums import ErrorCode def ok(data: Any = None) -> dict: """标准成功响应。""" return {"code": ErrorCode.SUCCESS, "data": data} def err(code: int, message: str) -> dict: """标准失败响应体(不含 HTTP 状态,由调用方决定)。""" return {"code": code, "message": message} def paginate(items: list, total: int, page: int, page_size: int) -> dict: """分页数据包装。""" return { "items": items, "total": total, "page": page, "page_size": page_size, } # ── 常用异常 ────────────────────────────────────────────── class CloverHTTPException(HTTPException): """携带业务 code 的 HTTP 异常,供全局 handler 格式化。""" def __init__(self, http_status: int, code: int, message: str): super().__init__(status_code=http_status, detail=message) self.biz_code = code self.biz_message = message def raise_not_found(message: str = "资源不存在") -> None: raise CloverHTTPException(404, ErrorCode.NOT_FOUND, message) def raise_forbidden(message: str = "无权限访问") -> None: raise CloverHTTPException(403, ErrorCode.FORBIDDEN, message) def raise_unauthorized(message: str = "未认证或 Token 失效") -> None: raise CloverHTTPException(401, ErrorCode.UNAUTHORIZED, message) def raise_business(message: str) -> None: raise CloverHTTPException(422, ErrorCode.BUSINESS_ERROR, message) def raise_param_error(message: str = "参数非法") -> None: raise CloverHTTPException(400, ErrorCode.PARAM_INVALID, message) def raise_state_invalid(message: str = "状态机非法流转") -> None: raise CloverHTTPException(409, ErrorCode.STATE_INVALID, message)