将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。 当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包), M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""
|
||
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_state_invalid(message: str = "状态机非法流转") -> None:
|
||
raise CloverHTTPException(409, ErrorCode.STATE_INVALID, message)
|