外观
开发规范
统一响应结构
所有 HTTP 接口都返回同一个结构 ResponseSchema,无论成功与否,前端都能用同一套逻辑解析:
json
{
"code": 0,
"msg": "操作成功",
"data": { ... },
"status_code": 200,
"success": true
}字段含义:
code:业务状态码,0表示成功,非0表示业务失败(详见下文错误码)msg:对用户的提示信息,失败时用于直接展示data:业务数据,无数据时为空status_code:HTTP 状态码success:是否成功,与code === 0等价
约定与机制:
- 后端统一用
SuccessResponse(data=..., msg=...)返回成功,用ErrorResponse或抛出CustomException返回失败,不要在业务代码里直接拼dict。 - 响应体在输出时会自动完成两件事:字段名由 snake_case 转为小驼峰(如
dept_name→deptName),时间字段格式化为YYYY-MM-DD HH:MM:SS。所以后端用 Python 习惯的蛇形命名,前端拿到的永远是驼峰命名。 - 文件下载、流式响应(SSE)走独立的
UploadFileResponse/StreamResponse,不套ResponseSchema。
业务状态码
错误码集中在 framework/web/status_code.py 的 RET 枚举,分为三段区间:
| 区间 | 含义 | 示例 |
|---|---|---|
0 / 200 段 | 成功 | OK=0、SUCCESS=200、CREATED=201 |
400–600 | HTTP 标准错误 | UNAUTHORIZED=401、FORBIDDEN=403、NOT_FOUND=404 |
4000+ | 自定义业务码 | DATAEXIST=4003、PARAMERR=4103、令牌相关 4504/4505、权限相关 4512 等 |
约定:
code === 0即成功,前端以此作为唯一判断依据,不要依赖 HTTP 200。- 抛出业务异常统一用
raise CustomException(code=RET.XXX.code, msg="可读的提示"),由全局异常处理器归一化为ErrorResponse,避免把 Python 堆栈直接抛给前端。
异常处理约定
全局异常处理器(framework/web/exception.py):业务异常通过 CustomException(code, msg) 抛出,框架统一捕获并返回 ErrorResponse,无需在 controller 中手动构造错误响应。
开发时只在真正需要区分业务语义时抛 CustomException,其余交给框架。
python
from app.framework.web.exception import CustomException
from app.framework.web.status_code import RET
if not exists:
raise CustomException(code=RET.DATAERR.code, msg="数据不存在")分页约定
分页结果统一返回 PageResultSchema:
| 字段 | 说明 |
|---|---|
pageNo | 当前页码(默认 1) |
pageSize | 每页大小(默认 10) |
total | 总记录数 |
hasNext | 是否有下一页 |
items | 当前页数据列表 |
关系型表的分页请使用 CRUDBase.page(数据库层 OFFSET/LIMIT);仅在数据源无法 SQL 分页(如内存列表、Redis 列表)时使用 PageUtil.paginate。
命名规范
后端接口按模块组织,控制器使用 APIRouter(prefix="/xxx", tags=["模块-功能"]),并遵循固定的动作命名,便于前端和权限系统识别:
| 动作 | 方法 + 路径 | 说明 |
|---|---|---|
| 列表 | GET /list | 扁平列表 |
| 树 / 详情 | GET /tree、GET /get、GET /detail/{id} | 查询类 |
| 新增 | POST /create | |
| 修改 | PUT /update | |
| 删除 | DELETE /delete、DELETE /delete-list | 单删 / 批量删(ids 逗号分隔) |
| 状态批量 | PATCH /status/batch | 启停等批量操作 |
命名规范与示例
| 对象 | 规范 | 示例 |
|---|---|---|
| 路由类 | XxxRouter | DictTypeRouter |
| 分页查询参数 | XxxQueryParam(@dataclass,用 Query) | DictTypeQueryParam |
| 响应模型 | XxxOutSchema(继承 CamelModel) | DictTypeOutSchema |
| 创建/更新模型 | XxxCreateSchema / XxxUpdateSchema | DictTypeCreateSchema |
| 分页接口 | 端点 /page,接收 XxxQueryParam | GET /dict-type/page |
接口声明示例:
python
@DictTypeRouter.get(
"/get",
summary="获取字典类型详情",
response_model=ResponseSchema[DictTypeOutSchema],
)
async def get_type_detail_controller(
id: Annotated[int, Query(description="字典类型ID")],
auth: Annotated[AuthSchema, Depends(AuthPermission(["system:dict:query"]))],
) -> JSONResponse:
result_dict = await DictTypeService(auth).detail(id=id)
return SuccessResponse(data=result_dict, msg="获取字典类型详情成功")