- 移除未使用的TabPane组件 - 修复类型定义和导入方式 - 优化mock数据源的环境变量判断逻辑 - 更新文档结构并归档旧文件 - 添加新的UI组件和Memo组件 - 调整API路径和响应处理
214 lines
3.7 KiB
Markdown
214 lines
3.7 KiB
Markdown
# API规则
|
||
|
||
> **入口**: [_index.md](_index.md)
|
||
|
||
---
|
||
|
||
## 1. 路由规范
|
||
|
||
### 1.1 路由格式
|
||
|
||
```
|
||
/api/{版本}/{模块}/{资源}/{动作}
|
||
|
||
示例:
|
||
/api/v1/products # 商品列表
|
||
/api/v1/products/:id # 商品详情
|
||
/api/v1/products/:id/publish # 商品刊登
|
||
/api/v1/orders # 订单列表
|
||
/api/v1/orders/:id/fulfill # 订单履约
|
||
```
|
||
|
||
### 1.2 HTTP方法映射
|
||
|
||
| 方法 | 用途 | 示例 |
|
||
|------|------|------|
|
||
| GET | 查询 | `GET /api/v1/products` |
|
||
| POST | 创建 | `POST /api/v1/products` |
|
||
| PUT | 全量更新 | `PUT /api/v1/products/:id` |
|
||
| PATCH | 部分更新 | `PATCH /api/v1/products/:id` |
|
||
| DELETE | 删除 | `DELETE /api/v1/products/:id` |
|
||
|
||
---
|
||
|
||
## 2. 权限校验
|
||
|
||
### 2.1 中间件使用
|
||
|
||
```typescript
|
||
// ✅ 正确:路由层使用 authorize() 中间件
|
||
router.get('/api/v1/products', authorize('product:read'), ProductController.list);
|
||
router.post('/api/v1/products', authorize('product:create'), ProductController.create);
|
||
router.put('/api/v1/products/:id', authorize('product:update'), ProductController.update);
|
||
|
||
// ❌ 错误:Controller 中硬编码角色
|
||
async create(ctx: Context) {
|
||
if (ctx.state.user.role === 'ADMIN') { // 禁止
|
||
// ...
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2.2 权限格式
|
||
|
||
```
|
||
{模块}:{动作}
|
||
|
||
示例:
|
||
product:read # 查看商品
|
||
product:create # 创建商品
|
||
product:update # 更新商品
|
||
product:delete # 删除商品
|
||
order:fulfill # 订单履约
|
||
finance:approve # 财务审批
|
||
```
|
||
|
||
### 2.3 数据隔离
|
||
|
||
非 ADMIN 用户查询必须根据 `parentId` 层级过滤:
|
||
|
||
```typescript
|
||
// ✅ 正确:Service层处理数据隔离
|
||
async listProducts(ctx: Context) {
|
||
const { tenantId, role, parentId } = ctx.state.user;
|
||
|
||
const query = db('cf_product').where('tenant_id', tenantId);
|
||
|
||
if (role !== 'ADMIN') {
|
||
query.where('parent_id', parentId);
|
||
}
|
||
|
||
return query;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 响应格式
|
||
|
||
### 3.1 成功响应
|
||
|
||
```typescript
|
||
// 单条数据
|
||
{
|
||
"success": true,
|
||
"data": { ... }
|
||
}
|
||
|
||
// 列表数据
|
||
{
|
||
"success": true,
|
||
"data": [...],
|
||
"pagination": {
|
||
"total": 100,
|
||
"page": 1,
|
||
"pageSize": 20
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.2 错误响应
|
||
|
||
```typescript
|
||
{
|
||
"success": false,
|
||
"error": {
|
||
"code": "PRODUCT_NOT_FOUND",
|
||
"message": "商品不存在",
|
||
"details": {}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.3 错误码规范
|
||
|
||
| 前缀 | 类别 | 示例 |
|
||
|------|------|------|
|
||
| `VAL_` | 参数校验 | `VAL_INVALID_PARAM` |
|
||
| `AUTH_` | 认证授权 | `AUTH_UNAUTHORIZED` |
|
||
| `BIZ_` | 业务逻辑 | `BIZ_PRODUCT_NOT_FOUND` |
|
||
| `SYS_` | 系统错误 | `SYS_DATABASE_ERROR` |
|
||
|
||
---
|
||
|
||
## 4. 请求参数
|
||
|
||
### 4.1 分页参数
|
||
|
||
```typescript
|
||
// 请求
|
||
GET /api/v1/products?page=1&pageSize=20
|
||
|
||
// 响应
|
||
{
|
||
"data": [...],
|
||
"pagination": {
|
||
"total": 100,
|
||
"page": 1,
|
||
"pageSize": 20,
|
||
"totalPages": 5
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.2 排序参数
|
||
|
||
```typescript
|
||
// 请求
|
||
GET /api/v1/products?sortBy=created_at&sortOrder=desc
|
||
|
||
// 默认排序
|
||
sortBy: 'created_at'
|
||
sortOrder: 'desc'
|
||
```
|
||
|
||
### 4.3 过滤参数
|
||
|
||
```typescript
|
||
// 请求
|
||
GET /api/v1/products?platform=SHOPIFY&status=ACTIVE
|
||
|
||
// 多值过滤
|
||
GET /api/v1/products?platform=SHOPIFY,AMAZON
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 追踪字段
|
||
|
||
所有API请求必须携带五元组:
|
||
|
||
```typescript
|
||
// 请求头
|
||
{
|
||
'X-Tenant-Id': 'xxx',
|
||
'X-Shop-Id': 'xxx',
|
||
'X-Task-Id': 'xxx', // 可选
|
||
'X-Trace-Id': 'xxx',
|
||
'X-Business-Type': 'TOC'
|
||
}
|
||
|
||
// 或请求体
|
||
{
|
||
"tenantId": "xxx",
|
||
"shopId": "xxx",
|
||
"taskId": "xxx",
|
||
"traceId": "xxx",
|
||
"businessType": "TOC"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. 速率限制
|
||
|
||
| 端点类型 | 限制 | 窗口 |
|
||
|---------|------|------|
|
||
| 查询接口 | 100次 | 1分钟 |
|
||
| 写入接口 | 30次 | 1分钟 |
|
||
| 批量接口 | 10次 | 1分钟 |
|
||
|
||
---
|
||
|
||
*最后更新: 2026-03-22*
|