|
|
# 模块协议
|
|
|
|
|
|
模块用于业务项目内的代码边界。
|
|
|
|
|
|
模块运行在同一个 Flask 进程内。
|
|
|
它不是独立服务。
|
|
|
|
|
|
## 适用范围
|
|
|
|
|
|
适合做模块的能力:
|
|
|
|
|
|
- 某个业务项目内部的业务域。
|
|
|
- 需要独立路由、service 和 model 目录的功能。
|
|
|
- 多人并行开发,但共享同一个部署单元和数据库。
|
|
|
|
|
|
不适合做模块的能力:
|
|
|
|
|
|
- 需要被多个项目跨进程复用。
|
|
|
- 有独立数据源。
|
|
|
- 有独立发布节奏。
|
|
|
- 业务项目不应该理解其内部细节。
|
|
|
|
|
|
这类能力应拆成 HTTP JSON 服务。
|
|
|
ERP Service 属于服务候选。
|
|
|
|
|
|
## 注册方式
|
|
|
|
|
|
业务项目在 `app.py` 传入模块实例:
|
|
|
|
|
|
```python
|
|
|
from iti.applications import create_app
|
|
|
from my_project.modules.example import ExampleModule
|
|
|
|
|
|
app = create_app(modules=[ExampleModule()])
|
|
|
```
|
|
|
|
|
|
模块可以声明这些阶段:
|
|
|
|
|
|
```python
|
|
|
class ExampleModule:
|
|
|
name = "example"
|
|
|
|
|
|
def init_app(self, app):
|
|
|
...
|
|
|
|
|
|
def register_commands(self, app):
|
|
|
...
|
|
|
|
|
|
def register_routes(self, app):
|
|
|
...
|
|
|
|
|
|
def register_permissions(self, app):
|
|
|
...
|
|
|
|
|
|
def register_menu_seed(self, app):
|
|
|
...
|
|
|
```
|
|
|
|
|
|
执行顺序固定:
|
|
|
|
|
|
1. `init_app`
|
|
|
2. `register_commands`
|
|
|
3. `register_routes`
|
|
|
4. `register_permissions`
|
|
|
5. `register_menu_seed`
|
|
|
|
|
|
## 权限声明
|
|
|
|
|
|
模块通过注册表声明权限码:
|
|
|
|
|
|
```python
|
|
|
from iti.modules import ModulePermission, get_module_registry
|
|
|
|
|
|
|
|
|
def register_permissions(self, app):
|
|
|
registry = get_module_registry(app)
|
|
|
registry.register_permission(
|
|
|
ModulePermission(
|
|
|
code="example:item:list",
|
|
|
name="示例列表",
|
|
|
description="查看示例模块数据",
|
|
|
)
|
|
|
)
|
|
|
```
|
|
|
|
|
|
权限码本身不单独落表。
|
|
|
实际授权仍然来自菜单 `auth_code`。
|
|
|
|
|
|
## 菜单 Seed
|
|
|
|
|
|
模块可以声明菜单 seed:
|
|
|
|
|
|
```python
|
|
|
from iti.applications.common.enums import MenuTypeEnum
|
|
|
from iti.modules import ModuleMenuSeed, get_module_registry
|
|
|
|
|
|
|
|
|
def register_menu_seed(self, app):
|
|
|
registry = get_module_registry(app)
|
|
|
registry.register_menu_seed(
|
|
|
ModuleMenuSeed(
|
|
|
id="example-menu-root",
|
|
|
name="Example",
|
|
|
type=MenuTypeEnum.MENU.value,
|
|
|
path="/example",
|
|
|
component="/example/list",
|
|
|
auth_code="example:item:list",
|
|
|
meta={"title": "示例模块", "icon": "carbon:application"},
|
|
|
sort=100,
|
|
|
)
|
|
|
)
|
|
|
```
|
|
|
|
|
|
菜单 seed 只是模块元数据。
|
|
|
iTi-Flask 只负责收集,不负责写入系统表。
|
|
|
|
|
|
如果业务项目引入 `iti-system`,可以由 `iti-system` seed 把模块菜单写入 `sys_menu`,并默认绑定到 `ADMIN`。
|
|
|
|
|
|
## 边界
|
|
|
|
|
|
模块可以:
|
|
|
|
|
|
- 注册蓝图。
|
|
|
- 注册 CLI 命令。
|
|
|
- 声明权限。
|
|
|
- 声明菜单 seed。
|
|
|
- 使用业务项目自己的 model。
|
|
|
|
|
|
模块不应该:
|
|
|
|
|
|
- 修改框架内部实现。
|
|
|
- 直接导入其它模块内部 model 或 service。
|
|
|
- 自建独立 migration 流。
|
|
|
- 在系统 seed 中写业务数据。
|
|
|
|
|
|
业务 model 仍然集中在业务项目 `models/` 下。
|
|
|
整个业务项目只保留一条 migration 流。
|