204 lines
6.4 KiB
Markdown
204 lines
6.4 KiB
Markdown
:::tip 本章概要
|
||
代码生成引擎的工作原理,包括配置解析、模板渲染、文件写入和自动注册的完整流程。
|
||
:::
|
||
|
||
# 代码生成引擎
|
||
|
||
`src/modules/generator/code_generator.py` 是代码生成器的执行层,负责接收配置字典、渲染模板、写入文件、自动注册路由和菜单。
|
||
|
||
## 核心类:CodeGenerator
|
||
|
||
```python
|
||
from src.modules.generator.code_generator import CodeGenerator
|
||
|
||
generator = CodeGenerator(config)
|
||
generator.generate(auto=True)
|
||
```
|
||
|
||
### 构造参数
|
||
|
||
| 参数 | 说明 |
|
||
|:----|:----|
|
||
| `config` | 配置字典(由 `parser.parse()` 或 JSON 文件提供) |
|
||
|
||
构造时自动:
|
||
- 调用 `normalize_config()` 标准化配置(幂等,已标准化的配置原样返回)
|
||
- 设置输出目录:`src/modules/{app_name}`
|
||
- 初始化 Jinja2 模板环境(`trim_blocks=True`, `lstrip_blocks=True`)
|
||
|
||
## generate() 主方法
|
||
|
||
```python
|
||
def generate(self, auto=False, request=None):
|
||
```
|
||
|
||
### 执行流程
|
||
|
||
```
|
||
1. 校验输出目录不存在(避免覆盖已有模块)
|
||
2. 创建输出目录 src/modules/{app_name}/
|
||
3. 准备模板上下文数据
|
||
4. 渲染后端模板 → 写入 modules 目录
|
||
5. 渲染前端模板 → 写入 ui/src/views/ 和 ui/src/api/
|
||
6. 自动注册到 v1.py
|
||
7. 自动创建菜单 + 权限节点
|
||
```
|
||
|
||
### 参数
|
||
|
||
| 参数 | 说明 |
|
||
|:----|:----|
|
||
| `auto` | 自动模式(当前无交互差异) |
|
||
| `request` | Flask 请求对象(用于获取操作人信息) |
|
||
|
||
## 配置标准化
|
||
|
||
`normalize_config()` 将 parser 产出的配置转为模板可用的标准格式:
|
||
|
||
```python
|
||
# parser 产出的字段
|
||
{"name": "type", "db_type": "Integer", "comment": "案例类型:1-类型1 2-类型2"}
|
||
|
||
# 标准化后
|
||
{
|
||
"name": "type",
|
||
"camel_name": "type", # 驼峰命名
|
||
"db_type": "Integer",
|
||
"form_type": "int", # WTForms 类型
|
||
"comment": "案例类型:1-类型1 2-类型2",
|
||
"py_comment": "案例类型:1-类型1 2-类型2", # 转义后
|
||
"default_repr": "1", # 默认值表示
|
||
"is_status": False, # 状态字段标识
|
||
"is_sort": False, # 排序字段标识
|
||
}
|
||
```
|
||
|
||
## 模板上下文
|
||
|
||
### _prepare_context()
|
||
|
||
准备后端模板的渲染上下文:
|
||
|
||
| 变量 | 类型 | 说明 |
|
||
|:----|:----|:----|
|
||
| `app_name` | str | 模块名(如 `example`) |
|
||
| `module_comment` | str | 中文名(如 `案例`) |
|
||
| `model_class_name` | str | 类名(如 `Example`) |
|
||
| `permission_prefix` | str | 权限前缀(如 `sys:example`) |
|
||
| `display_field` | str | 显示字段(如 `name`) |
|
||
| `has_sort` | bool | 有排序字段 |
|
||
| `has_status` | bool | 有状态字段 |
|
||
| `has_status_route` | bool | 生成状态路由 |
|
||
| `has_image_field` | bool | 有图片字段 |
|
||
| `has_rich_text_field` | bool | 有富文本字段 |
|
||
| `serialize_maps` | dict | 枚举映射 |
|
||
| `sort_field` | str | 排序字段名 |
|
||
| `fields` | list | 全部字段 |
|
||
| `form_fields` | list | 表单字段 |
|
||
| `filter_fields` | list | 精确匹配字段 |
|
||
| `like_fields` | list | 模糊查询字段 |
|
||
|
||
### _prepare_vue_context()
|
||
|
||
在后端上下文基础上扩展前端专用变量:
|
||
|
||
| 变量 | 类型 | 说明 |
|
||
|:----|:----|:----|
|
||
| `module_name` | str | 驼峰模块名 |
|
||
| `model_class_name_camel` | str | 驼峰类名(首字母小写) |
|
||
| `list_fields` | list | 列表展示字段 |
|
||
| `searchable_fields` | list | 可搜索字段 |
|
||
| `editable_fields` | list | 可编辑字段 |
|
||
| `has_export` | bool | 有导出功能 |
|
||
| `route_prefix` | str | 路由前缀 |
|
||
| `api_path` | str | API 路径 |
|
||
| `is_tree_structure` | bool | 是否树形结构 |
|
||
| `parent_id_field` | str | 父级字段名 |
|
||
| `has_search_form` | bool | 显示搜索表单 |
|
||
| `show_selection` | bool | 显示复选框 |
|
||
|
||
## 文件生成
|
||
|
||
### 后端文件
|
||
|
||
| 模板 | 输出路径 | 说明 |
|
||
|:----|:----|:----|
|
||
| `__init__.py.tpl` | `src/modules/{name}/__init__.py` | 模块初始化 |
|
||
| `models.py.tpl` | `src/modules/{name}/models.py` | ORM 模型 |
|
||
| `schema.py.tpl` | `src/modules/{name}/schema.py` | WTForms 表单 |
|
||
| `repository.py.tpl` | `src/modules/{name}/repository.py` | 数据访问层 |
|
||
| `service.py.tpl` | `src/modules/{name}/service.py` | 业务逻辑层 |
|
||
| `router.py.tpl` | `src/modules/{name}/router.py` | 路由定义层 |
|
||
|
||
### 前端文件(普通列表)
|
||
|
||
| 模板 | 输出路径 |
|
||
|:----|:----|
|
||
| `ui/index.vue.tpl` | `ui/src/views/tool/{name}/index.vue` |
|
||
| `ui/edit.vue.tpl` | `ui/src/views/tool/{name}/edit.vue` |
|
||
| `ui/detail.vue.tpl` | `ui/src/views/tool/{name}/detail.vue` |
|
||
| `ui/columns.ts.tpl` | `ui/src/views/tool/{name}/columns.ts` |
|
||
| `ui/querySchemas.ts.tpl` | `ui/src/views/tool/{name}/querySchemas.ts` |
|
||
| `ui/api.ts.tpl` | `ui/src/api/tool/{name}.ts` |
|
||
|
||
### 前端文件(树状列表)
|
||
|
||
| 模板 | 输出路径 |
|
||
|:----|:----|
|
||
| `ui2/index.vue.tpl` | `ui/src/views/tool/{name}/index.vue` |
|
||
| `ui2/edit.vue.tpl` | `ui/src/views/tool/{name}/edit.vue` |
|
||
| `ui2/detail.vue.tpl` | `ui/src/views/tool/{name}/detail.vue` |
|
||
| `ui/api.ts.tpl` | `ui/src/api/tool/{name}.ts` |
|
||
|
||
树状列表与普通列表共用 `api.ts.tpl`。
|
||
|
||
## 自动注册
|
||
|
||
### 路由注册
|
||
|
||
`_register_module()` 在 `src/routes/v1.py` 中追加:
|
||
|
||
```python
|
||
# 导入语句(插入到最后一个 from src.modules 导入之后)
|
||
from src.modules.example.router import example_blue
|
||
|
||
# 注册语句(追加到 BLUEPRINTS 列表)
|
||
BLUEPRINTS = [
|
||
# ... 其他模块
|
||
example_blue,
|
||
]
|
||
```
|
||
|
||
幂等操作:如果导入语句已存在,跳过。
|
||
|
||
### 菜单创建
|
||
|
||
`_create_menus()` 在数据库中创建:
|
||
|
||
1. **二级菜单**(type=0):页面路由
|
||
- name: 模块中文名
|
||
- path: `/tool/{module_camel}`
|
||
- component: `/tool/{module_camel}/index`
|
||
- parent_id: 189(开发工具)
|
||
|
||
2. **三级权限节点**(type=1)× 10 个:
|
||
|
||
| 权限 | 标识 |
|
||
|:----|:----|
|
||
| 分页查询 | `{prefix}:page` |
|
||
| 列表查询 | `{prefix}:list` |
|
||
| 详情查询 | `{prefix}:detail` |
|
||
| 新增 | `{prefix}:add` |
|
||
| 编辑 | `{prefix}:update` |
|
||
| 删除 | `{prefix}:delete` |
|
||
| 批量删除 | `{prefix}:batchDelete` |
|
||
| 状态管理 | `{prefix}:status` |
|
||
| 导入 | `{prefix}:import` |
|
||
| 导出 | `{prefix}:export` |
|
||
|
||
幂等操作:如果 path 已存在,跳过。创建后自动清除所有用户权限缓存。
|
||
|
||
## 总结
|
||
|
||
代码生成引擎根据数据库表结构和配置信息,通过 Jinja2 模板渲染生成后端(models/schema/repository/service/router)和前端(index.vue/edit.vue/columns.ts/querySchemas.ts/api.ts)全套代码,生成后自动注册路由和权限。
|