Files
2026-10-20 21:19:44 +08:00

205 lines
8.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 10.5 代码生成引擎
:::tip 概述
代码生成引擎基于模板文件,将表结构信息渲染为实际代码文件。渲染使用 PHP 原生 `include` + `extract` 机制,模板变量由 `GeneratorService::buildTemplateVars()` 统一构建。
:::
## 生成文件清单
### 后端文件
| 文件 | 模板 | 说明 |
|------|------|------|
| `app/controller/{Name}Controller.php` | controller.php.tpl | 控制器,含分页/列表/详情/增删改/批量删除/导入/导出 |
| `app/logic/{Name}Logic.php` | logic.php.tpl | 业务逻辑,含属性配置、serializeMaps、导入导出方法 |
| `app/model/{Name}.php` | model.php.tpl | 数据模型,含软删除、审计字段自动填充;树形结构额外生成 `children()` 自关联 |
| `app/validate/{Name}Validate.php` | validate.php.tpl | 验证器,按字段分析自动生成验证规则(camelCase 字段名、require 规则、add/update 场景) |
### 前端文件(ui/ 普通列表模板 — 6 个文件)
| 文件 | 模板 | 说明 |
|------|------|------|
| `ui/src/api/{app}/{name}.ts` | api.ts.tpl | API 接口模块(page/list/detail/add/update/delete/import/export) |
| `ui/src/views/{app}/{name}/index.vue` | index.vue.tpl | 列表页(含搜索、表格、新增/编辑/详情弹窗、导入导出按钮) |
| `ui/src/views/{app}/{name}/edit.vue` | edit.vue.tpl | 编辑弹窗(新增/复用) |
| `ui/src/views/{app}/{name}/detail.vue` | detail.vue.tpl | 详情弹窗 |
| `ui/src/views/{app}/{name}/columns.ts` | columns.ts.tpl | 表格列配置(含图片 ElAvatar、选项 ElTag、链接等渲染) |
| `ui/src/views/{app}/{name}/querySchemas.ts` | querySchemas.ts.tpl | 查询表单配置(按字段类型自动选 Input/Select/InputNumber/DatePicker) |
### 前端文件(ui2/ 树形模板 — 4 个文件)
| 文件 | 模板 | 说明 |
|------|------|------|
| `ui/src/api/{app}/{name}.ts` | api.ts.tpl | API 接口模块 |
| `ui/src/views/{app}/{name}/index.vue` | index.vue.tpl | 树形列表页(Tree + Table 左右布局) |
| `ui/src/views/{app}/{name}/edit.vue` | edit.vue.tpl | 编辑弹窗(含上级节点选择) |
| `ui/src/views/{app}/{name}/detail.vue` | detail.vue.tpl | 详情弹窗 |
:::info 模板选择
表结构中包含 `parent_id` 或 `pid` 字段时自动使用 `ui2/` 树形模板,否则使用 `ui/` 普通列表模板。树形模板不生成 `columns.ts` 和 `querySchemas.ts`。
:::
## GeneratorService 核心方法
```php
// app/service/GeneratorService.php
/**
* 获取可生成的表列表
*
* 读取当前数据库所有表,返回表名、注释、引擎、行数等信息。
* 支持 MySQL / PostgreSQL / SQL Server / Oracle / SQLite。
*/
public function page(array $params): array { ... }
/**
* 构建模板变量
*
* 解析表结构 → 字段分析 → 构建全部模板变量。
* 是生成引擎的核心,决定模板中可用的所有变量。
*/
public function buildTemplateVars(string $tableName, string $moduleComment, string $templateType): array { ... }
/**
* 渲染模板
*
* 使用 PHP extract + include 机制渲染 .tpl 文件。
* 渲染前预检:禁止短标签 <?= 和 UTF-8 BOM 头。
*/
public function renderTemplate(string $templatePath, array $vars): string { ... }
/**
* 预览生成代码(不写入文件)
*
* 返回所有待生成文件的渲染结果,供前端预览。
*/
public function preview(array $params): array { ... }
/**
* 生成代码(写入文件)
*
* 渲染模板 → 写入文件 → 创建菜单 → 创建字典 → 注册路由。
*/
public function generate(array $params): array { ... }
/**
* 批量生成
*
* 遍历多张表,逐表调用 generate。
*/
public function batchGenerate(array $params): array { ... }
/**
* 生成单个文件
*
* 检查文件是否存在(可跳过或覆盖)→ 创建目录 → 写入文件。
*/
public function generateFile(string $path, string $content, bool $overwrite): array { ... }
/**
* 创建菜单和权限节点
*
* 自动创建主菜单(type=0)和标准权限节点(type=1):
* page / list / detail / add / update / delete / batchDelete / import / export。
*/
public function createMenu(string $moduleComment, string $moduleName): array { ... }
/**
* 创建字典数据
*
* 遍历 serialize_maps,为带选项的字段自动创建字典主记录和字典项。
* 幂等:字典编码已存在则跳过。
*/
public function createDictData(string $moduleComment, string $moduleName, array $serializeMaps, array $fields): array { ... }
/**
* 注册模块路由
*
* 在 route/app.php 中自动插入标准 CRUD 路由组(含中间件)。
* 树形结构不生成 page 路由。
*/
public function registerRoute(string $moduleName, bool $isTree): array { ... }
```
## 字段分析流程
```text
原始表字段(数据库列信息)
│
▼
类型归一化(db_type → type 类名)
│ int → IntegerField, varchar → CharField, text → TextField
│ datetime → DateTimeField, decimal → DecimalField, ...
▼
属性分析(详见 10.4 表结构解析引擎)
│
├─ 图片字段 → 注释/字段名匹配 /图片|头像|logo|icon|image|avatar|photo/i 且类型为 varchar
├─ 富文本 → 注释匹配 /内容|详情|正文/i 且类型为 text
├─ 多行文本 → 注释匹配 /备注|说明|描述|介绍|简介/i 且类型为 varchar
├─ 选项字段 → 注释中解析 "数字-文字" 格式(如 "1-启用 2-停用")
├─ 状态字段 → 字段名 status 且无选项时,自动补 0=正常 1=停用
├─ 模糊搜索 → 字段名匹配 /名称|标题|name|title|username/i 且类型为 varchar
├─ 唯一字段 → 字段名匹配 /编码|code|username|mobile|email/i
├─ 外键字段 → 字段名以 _id 或 _ids 结尾
└─ 排序字段 → 字段名为 sort
▼
serialize_maps 构建
│ 有 choices 的字段自动生成映射:字段名 → "{模块名}_{字段名}"
│ 如 status → "example_status"
▼
输出分组字段列表
│ $fields['all'] 全部字段
│ $fields['list'] 列表展示字段
│ $fields['form'] 表单字段
│ $fields['filter'] 筛选字段(含模糊搜索和精确匹配)
│ $fields['file'] 文件/图片字段
│ $fields['content'] 富文本字段
│ $fields['like'] 模糊搜索字段
│ $fields['eq'] 精确匹配字段(含选项字段)
│ $fields['unique'] 唯一字段
│ $fields['serialize_maps'] 枚举映射(字段 → 字典编码)
│ $fields['foreign_keys'] 外键字段
```
## 渲染机制
```php
// 渲染原理(简化)
public function renderTemplate(string $templatePath, array $vars): string
{
// 预检:禁止短标签和 BOM
$tplContent = file_get_contents($templatePath);
if (preg_match('/<\?=(?!.*<\?php echo)/s', $tplContent)) {
throw new \Exception('模板包含短标签 <?= ,请改为 <?php echo');
}
extract($vars); // 将变量注入当前作用域
ob_start(); // 开启输出缓冲
include $templatePath; // 执行模板文件
return ob_get_clean(); // 返回渲染结果
}
```
:::warning 模板编写规范
- 必须使用 `<?php echo ?>` 输出变量,不能使用短标签 `<?= ?>`
- 文件编码必须为 UTF-8 无 BOM
- 控制结构(foreach/if)使用完整的 `<?php ?>` 标签
:::
## 生成后自动操作
代码生成后,引擎会自动执行以下操作:
| 操作 | 说明 | 幂等性 |
|------|------|--------|
| 写入文件 | 生成 Controller / Logic / Model / Validate / API / Vue 文件 | 文件已存在则跳过 |
| 创建菜单 | 在指定父菜单下创建主菜单和权限节点 | 路径已存在则跳过 |
| 创建字典 | 为带选项的字段自动创建字典和字典项 | 字典编码已存在则跳过 |
| 注册路由 | 在 route/app.php 中插入 CRUD 路由组 | 路由组已存在则跳过 |
## 相关文档
- [10.4 表结构解析引擎](/zh/generator/parser.html)
- [10.6 自定义模板开发](/zh/generator/templates.html)
- [10.7 配置文件详解](/zh/generator/config.html)