216 lines
6.7 KiB
Markdown
216 lines
6.7 KiB
Markdown
# Router层规范
|
||
|
||
## 概述
|
||
|
||
Router 层是 HTTP 接口层,定义路由和请求处理。每个模块的 Router 文件位于 `src/modules/{group}/{name}/router.py`,使用 Flask `Blueprint` 定义接口。
|
||
|
||
:::tip 设计原则
|
||
- Router 只做请求分发,不含业务逻辑
|
||
- 通过装饰器控制权限
|
||
- 委托 Service 处理业务逻辑
|
||
- 返回 R 封装的响应
|
||
:::
|
||
|
||
## 装饰器顺序
|
||
|
||
```python
|
||
@position_blue.route('/add', methods=['POST']) # 1. 路由定义
|
||
@check_permission('sys:position:add') # 2. 权限校验
|
||
def add():
|
||
from src.modules.system.position.service import add_position
|
||
from src.modules.system.position.schema import PositionForm
|
||
data = parse_request_body(request, PositionForm)
|
||
return add_position(data)
|
||
```
|
||
|
||
:::warning 装饰器顺序规则
|
||
1. `@blueprint.route()`:路由定义(最外层)
|
||
2. `@check_permission("权限标识")`:RBAC 权限校验
|
||
|
||
顺序不可调换,否则权限校验可能失效。
|
||
:::
|
||
|
||
## 读操作
|
||
|
||
```python
|
||
# 分页查询
|
||
@position_blue.route('/page', methods=['GET'])
|
||
@check_permission('sys:position:page')
|
||
def page():
|
||
from src.modules.system.position.service import get_position_page
|
||
return get_position_page()
|
||
|
||
# 详情查询
|
||
@position_blue.route('/detail/<int:id>', methods=['GET'])
|
||
@check_permission('sys:position:detail')
|
||
def detail(id):
|
||
from src.modules.system.position.service import get_position_detail
|
||
return R.ok(data=get_position_detail(id))
|
||
|
||
# 列表查询(无分页)
|
||
@position_blue.route('/list', methods=['GET'])
|
||
@check_permission('sys:position:list')
|
||
def get_position_list():
|
||
from src.modules.system.position.service import get_position_list
|
||
return R.ok(data=get_position_list())
|
||
```
|
||
|
||
## 写操作
|
||
|
||
```python
|
||
# 添加
|
||
@position_blue.route('/add', methods=['POST'])
|
||
@check_permission('sys:position:add')
|
||
def add():
|
||
from src.modules.system.position.service import add_position
|
||
from src.modules.system.position.schema import PositionForm
|
||
data = parse_request_body(request, PositionForm)
|
||
return add_position(data)
|
||
|
||
# 编辑
|
||
@position_blue.route('/update', methods=['PUT'])
|
||
@check_permission('sys:position:update')
|
||
def update():
|
||
from src.modules.system.position.service import update_position
|
||
from src.modules.system.position.schema import PositionForm
|
||
data = parse_request_body(request, PositionForm)
|
||
return update_position(data)
|
||
|
||
# 删除
|
||
@position_blue.route('/delete/<int:id>', methods=['DELETE'])
|
||
@check_permission('sys:position:delete')
|
||
def delete(id):
|
||
from src.modules.system.position.service import delete_position
|
||
return delete_position(id)
|
||
|
||
# 设置状态
|
||
@position_blue.route('/status', methods=['PUT'])
|
||
@check_permission('sys:position:status')
|
||
def status():
|
||
from src.modules.system.position.service import update_position_status
|
||
from src.modules.system.position.schema import PositionStatusForm
|
||
data = parse_request_body(request, PositionStatusForm)
|
||
return update_position_status(data)
|
||
|
||
# 批量删除
|
||
@position_blue.route('/batchDelete', methods=['DELETE'])
|
||
@check_permission('sys:position:batchDelete')
|
||
def batch_delete():
|
||
from src.modules.system.position.service import delete_positions
|
||
id_list = parse_batch_ids(request)
|
||
return delete_positions(id_list)
|
||
```
|
||
|
||
## 权限标识规范
|
||
|
||
权限标识格式:`sys:{module}:{action}`
|
||
|
||
| 操作 | 权限标识 | HTTP 方法 |
|
||
|------|---------|----------|
|
||
| 分页查询 | `sys:{module}:page` | GET |
|
||
| 详情查询 | `sys:{module}:detail` | GET |
|
||
| 列表查询 | `sys:{module}:list` | GET |
|
||
| 添加 | `sys:{module}:add` | POST |
|
||
| 编辑 | `sys:{module}:update` | PUT |
|
||
| 删除 | `sys:{module}:delete` | DELETE |
|
||
| 批量删除 | `sys:{module}:batchDelete` | DELETE |
|
||
| 状态设置 | `sys:{module}:status` | PUT |
|
||
|
||
:::tip admin 用户
|
||
用户 ID 为 1 的管理员账号跳过所有 `check_permission` 检查。
|
||
:::
|
||
|
||
## 完整 Router 文件模板
|
||
|
||
```python
|
||
from flask import Blueprint, request
|
||
|
||
from src.core.permission import check_permission
|
||
from src.core import response as R
|
||
from src.common.utils.request import parse_request_body, parse_batch_ids
|
||
|
||
# 创建 Blueprint 实例
|
||
position_blue = Blueprint('position', __name__, url_prefix='/position')
|
||
|
||
|
||
@position_blue.route('/page', methods=['GET'])
|
||
@check_permission('sys:position:page')
|
||
def page():
|
||
from src.modules.system.position.service import get_position_page
|
||
return get_position_page()
|
||
|
||
|
||
@position_blue.route('/detail/<int:id>', methods=['GET'])
|
||
@check_permission('sys:position:detail')
|
||
def detail(id):
|
||
from src.modules.system.position.service import get_position_detail
|
||
return R.ok(data=get_position_detail(id))
|
||
|
||
|
||
@position_blue.route('/list', methods=['GET'])
|
||
@check_permission('sys:position:list')
|
||
def get_position_list():
|
||
from src.modules.system.position.service import get_position_list
|
||
return R.ok(data=get_position_list())
|
||
|
||
|
||
@position_blue.route('/add', methods=['POST'])
|
||
@check_permission('sys:position:add')
|
||
def add():
|
||
from src.modules.system.position.service import add_position
|
||
from src.modules.system.position.schema import PositionForm
|
||
data = parse_request_body(request, PositionForm)
|
||
return add_position(data)
|
||
|
||
|
||
@position_blue.route('/update', methods=['PUT'])
|
||
@check_permission('sys:position:update')
|
||
def update():
|
||
from src.modules.system.position.service import update_position
|
||
from src.modules.system.position.schema import PositionForm
|
||
data = parse_request_body(request, PositionForm)
|
||
return update_position(data)
|
||
|
||
|
||
@position_blue.route('/delete/<int:id>', methods=['DELETE'])
|
||
@check_permission('sys:position:delete')
|
||
def delete(id):
|
||
from src.modules.system.position.service import delete_position
|
||
return delete_position(id)
|
||
|
||
|
||
@position_blue.route('/status', methods=['PUT'])
|
||
@check_permission('sys:position:status')
|
||
def status():
|
||
from src.modules.system.position.service import update_position_status
|
||
from src.modules.system.position.schema import PositionStatusForm
|
||
data = parse_request_body(request, PositionStatusForm)
|
||
return update_position_status(data)
|
||
|
||
|
||
@position_blue.route('/batchDelete', methods=['DELETE'])
|
||
@check_permission('sys:position:batchDelete')
|
||
def batch_delete():
|
||
from src.modules.system.position.service import delete_positions
|
||
id_list = parse_batch_ids(request)
|
||
return delete_positions(id_list)
|
||
```
|
||
|
||
## 路由注册
|
||
|
||
在 `src/routes/v1.py` 中注册模块路由:
|
||
|
||
```python
|
||
from src.modules.system.position.router import position_blue
|
||
|
||
BLUEPRINTS = [
|
||
# ... 其他模块
|
||
position_blue,
|
||
# ... 其他模块
|
||
]
|
||
```
|
||
|
||
## 总结
|
||
|
||
Router 层是 HTTP 接口定义层,只做请求分发和装饰器配置。核心规则:装饰器顺序为 `@blueprint.route()` → `@check_permission`;权限标识格式 `sys:{module}:{action}`;所有逻辑委托 Service 处理。
|