签入版本

This commit is contained in:
2026-09-29 10:14:04 +08:00
parent 3e5fc01124
commit d6b552103d
1664 changed files with 298944 additions and 0 deletions
@@ -0,0 +1,136 @@
# 10.2 CLI 命令行使用
:::tip 概述
代码生成器提供 CLI 命令行方式,适合批量生成或 CI/CD 集成场景。
:::
## 命令格式
```bash
# =============================================================================
# 代码生成器 CLI 命令
# =============================================================================
# php think generate:code → ThinkPHP 命令行调用代码生成器
# <表名> → 数据库表名(不含表前缀)
# |<注释> → 可选,用 | 分隔表注释(用于生成菜单标题)
# =============================================================================
php think generate:code <表名>[|注释]
```
## 参数说明
| 参数 | 必填 | 说明 | 示例 |
|------|------|------|------|
| `table`(参数) | 否 | 数据库表名,多表用逗号分隔(需配合 `--batch`) | `think_example` 或 `think_example\|案例演示` |
| `--config` / `-c` | 否 | 指定已有的 JSON 配置文件路径,跳过表解析 | `--config config.json` |
| `--output` / `-o` | 否 | 将配置导出为 JSON 文件 | `--output config.json` |
| `--dry-run` / `-d` | 否 | 仅预览,不写入代码文件 | `--dry-run` |
| `--type` / `-t` | 否 | 模板类型:`ui`(默认)或 `ui2` | `--type ui2` |
| `--overwrite` / `-w` | 否 | 覆盖已存在的文件 | `--overwrite` |
| `--no-menu` | 否 | 不生成菜单 | `--no-menu` |
| `--batch` / `-b` | 否 | 批量模式,table 参数支持逗号分隔多表 | `--batch` |
## 使用示例
```bash
# -----------------------------------------------------------------------------
# 列出所有可生成的数据库表
# -----------------------------------------------------------------------------
php think generate:code
# -----------------------------------------------------------------------------
# 预览生成代码(不写入文件,仅输出到终端)
# -----------------------------------------------------------------------------
php think generate:code think_example --dry-run
# -----------------------------------------------------------------------------
# 生成案例演示模块(带表注释)
# -----------------------------------------------------------------------------
php think generate:code think_example|案例演示
# -----------------------------------------------------------------------------
# 生成文章管理模块(覆盖已有文件)
# -----------------------------------------------------------------------------
php think generate:code think_article|文章管理 --overwrite
# -----------------------------------------------------------------------------
# 生成用户管理模块(使用 ui2 树形模板)
# -----------------------------------------------------------------------------
php think generate:code think_user|用户管理 --type ui2
# -----------------------------------------------------------------------------
# 批量生成多张表
# -----------------------------------------------------------------------------
php think generate:code think_order,think_product,think_category --batch
# -----------------------------------------------------------------------------
# 导出配置为 JSON 文件
# -----------------------------------------------------------------------------
php think generate:code think_example --output config.json
# -----------------------------------------------------------------------------
# 从配置文件生成(跳过表解析)
# -----------------------------------------------------------------------------
php think generate:code --config config.json
```
## 生成的文件
执行命令后,自动生成以下文件:
```text
app/controller/ExampleController.php # 控制器(定义 API 接口方法)
app/logic/ExampleLogic.php # 业务逻辑(继承 BaseLogic 获得 CRUD)
app/model/Example.php # 数据模型(继承 BaseModel 获得软删除/时间戳)
app/validate/ExampleValidate.php # 验证器(字段验证规则)
ui/src/api/tool/example.ts # 前端 API 接口定义
ui/src/views/tool/example/index.vue # 列表页(分页表格 + 搜索)
ui/src/views/tool/example/edit.vue # 编辑弹窗(新增/编辑表单)
ui/src/views/tool/example/detail.vue # 详情弹窗(只读展示)
ui/src/views/tool/example/columns.ts # 表格列配置(仅 ui/ 模板)
ui/src/views/tool/example/querySchemas.ts # 查询表单配置(仅 ui/ 模板)
```
## 生成后操作
生成完成后,路由、菜单、字典均已自动创建。通常只需:
```bash
# -----------------------------------------------------------------------------
# 第 1 步:检查生成的文件是否正确
# -----------------------------------------------------------------------------
ls app/controller/Example* # 控制器
ls app/logic/Example* # 业务逻辑
ls app/model/Example* # 数据模型
ls app/validate/Example* # 验证器
ls ui/src/api/tool/example* # 前端 API
ls ui/src/views/tool/example/ # 前端页面
# -----------------------------------------------------------------------------
# 第 2 步:根据业务需求调整 Logic 属性配置
# -----------------------------------------------------------------------------
# 可调整:pageLikeFields、pageEqFields、serializeMaps 等
# -----------------------------------------------------------------------------
# 第 3 步:在菜单管理中调整菜单排序和图标
# -----------------------------------------------------------------------------
```
## 与 Web 界面对比
| 特性 | CLI 命令 | Web 界面 |
|------|----------|----------|
| 使用方式 | 命令行 | 浏览器 |
| 适用场景 | 批量生成、CI/CD、自动化 | 单表生成、可视化配置 |
| 预览功能 | 支持(`--dry-run`) | 支持预览 |
| 批量生成 | 支持(`--batch` 原生支持) | 支持(多选表) |
| 树形结构 | 支持(`--type ui2`) | 自动检测 parent_id 字段 |
| 覆盖文件 | 支持(`--overwrite`) | 支持 |
| 跳过菜单 | 支持(`--no-menu`) | 不支持 |
| 导出配置 | 支持(`--output`) | 不支持 |
| 从配置生成 | 支持(`--config`) | 不支持 |
| 权限限制 | 不受限制 | 受权限和演示模式限制 |
:::tip 推荐
日常开发推荐使用 Web 界面(可视化配置更方便),批量生成或自动化场景使用 CLI 命令。
:::
@@ -0,0 +1,204 @@
# 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)
@@ -0,0 +1,112 @@
# 10.7 配置文件详解
:::tip 概述
代码生成器通过 `.env` 和 Web 界面配置,主要控制生成行为和默认值。
:::
## .env 配置
```ini
; 代码生成器配置
[GENERATOR]
; 父菜单ID(生成的菜单挂在此菜单下)
; 在菜单管理中查看目标父菜单的 ID
PARENT_MENU_ID = 189
; 应用名(路由前缀)
; 影响生成的菜单路径和前端目录
; 如:tool → /tool/xxx,system → /system/xxx
APP_NAME = tool
```
## Web 界面配置
通过「工具管理 → 代码生成」页面配置:
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| 表名 | 选择要生成的表 | - |
| 模块名 | 生成的模块名(影响路由前缀和前端目录) | 表名去掉前缀 |
| 功能名 | 功能中文名称(用于注释和菜单标题) | 表注释 |
| 作者 | 代码注释中的作者 | admin |
| 包名 | 生成文件的命名空间 | app |
| 是否导入导出 | 是否生成 import/export 方法 | 是 |
| 树形结构 | 是否使用树形模板(需有 parent_id 字段) | 否 |
| 上级菜单 | 生成菜单挂载到的父菜单 | 由 PARENT_MENU_ID 决定 |
## 生成的文件路径
| 文件 | 路径 | 说明 |
|------|------|------|
| Controller | `app/controller/{Name}Controller.php` | 控制器 |
| Logic | `app/logic/{Name}Logic.php` | 业务逻辑 |
| Model | `app/model/{Name}.php` | 数据模型 |
| Validate | `app/validate/{Name}Validate.php` | 验证器 |
| API | `ui/src/api/{app}/{name}.ts` | 前端 API |
| 列表页 | `ui/src/views/{app}/{name}/index.vue` | 列表页 |
| 编辑弹窗 | `ui/src/views/{app}/{name}/edit.vue` | 编辑弹窗 |
| 详情弹窗 | `ui/src/views/{app}/{name}/detail.vue` | 详情弹窗 |
| 表格列配置 | `ui/src/views/{app}/{name}/columns.ts` | 表格列定义(仅 ui/ 模板) |
| 查询表单配置 | `ui/src/views/{app}/{name}/querySchemas.ts` | 搜索表单定义(仅 ui/ 模板) |
## 自动生成的 Logic 属性
代码生成器会根据表结构自动分析并生成以下 Logic 属性:
| 属性 | 生成条件 | 说明 |
|------|----------|------|
| `$fileFields` | 字段名含 image/avatar/photo/pic 等且类型为 varchar | 文件/图片字段,自动迁移临时文件并补全 URL |
| `$fileSaveDir` | 有 `$fileFields` 时生成 | 文件上传子目录 |
| `$contentFields` | 字段名含 content/body/description 且类型为 text | 富文本字段,自动处理临时文件和图片占位符 |
| `$pageLikeFields` | 字段名含 name/title/keyword 且类型为 varchar | 模糊搜索字段,分页查询时 LIKE 匹配 |
| `$pageEqFields` | 字段名含 status/type/group 且类型为 int | 精确匹配字段,分页查询时等值过滤 |
| `$uniqueFields` | 字段有 UNIQUE 索引 | 唯一性校验字段,新增/修改时自动校验 |
| `$serializeMaps` | 字段有选项(choices)时自动生成 | 枚举显示名映射,查询时自动补 `{字段名}Text` |
| `$treeParentField` | 表含 parent_id 或 pid 字段 | 树形结构父级字段 |
| `$treeLikeField` | 树形结构时生成 | 树形查询模糊搜索字段 |
## serializeMaps 与字典自动创建
当字段被分析出有选项(choices)时,代码生成器会:
1. **自动生成 `$serializeMaps` 映射**
```php
// 示例:字段 status 有选项(0=正常, 1=禁用)
protected array $serializeMaps = [
'status' => 'example_status', // 字典编码 = {模块名}_{字段名}
];
```
2. **自动创建字典数据**
在 `think_dict` 和 `think_dict_item` 表中自动创建对应记录:
| 表 | 字段 | 值 |
|----|------|------|
| think_dict | name | 案例-状态 |
| think_dict | code | example_status |
| think_dict_item | name / value | 正常 / 0,禁用 / 1 |
3. **查询时自动翻译**
`BaseLogic::processSerializeMaps()` 在查询结果中自动补 `statusText` 字段,值为字典翻译后的文本。
:::info 幂等性
字典创建是幂等的:如果 `think_dict` 中已存在相同 `code` 的记录,会自动跳过,不会重复创建。
:::
## 配置影响总结
| 配置项 | 影响范围 |
|--------|----------|
| `GENERATOR.PARENT_MENU_ID` | 生成的菜单挂载位置 |
| `GENERATOR.APP_NAME` | 菜单路径、前端目录、API 路径、路由前缀 |
| 是否导入导出 | Controller 中是否生成 import/export 方法,Logic 中是否生成对应方法 |
| 树形结构 | 使用 ui/ 还是 ui2/ 模板,Controller 中是否生成 page 方法 |
## 相关文档
- [10.5 代码生成引擎](/zh/generator/code-engine.html)
- [10.6 自定义模板开发](/zh/generator/templates.html)
- [10.8 实战案例](/zh/generator/demo.html)
@@ -0,0 +1,74 @@
# 10.8 实战案例
:::tip 概述
以「案例演示」模块为例,演示代码生成器的完整使用流程。
:::
## 第 1 步:建表
```sql
CREATE TABLE think_example (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(200) NOT NULL COMMENT '案例名称',
type TINYINT(1) DEFAULT 0 COMMENT '案例类型',
status TINYINT(1) DEFAULT 0 COMMENT '案例状态',
sort INT DEFAULT 0 COMMENT '排序',
avatar VARCHAR(500) DEFAULT '' COMMENT '头像',
is_delete TINYINT(1) DEFAULT 0,
create_user VARCHAR(50) DEFAULT '',
create_time DATETIME,
update_user VARCHAR(50) DEFAULT '',
update_time DATETIME
);
```
## 第 2 步:代码生成器操作
1. 进入「工具管理 → 代码生成」
2. 找到 `think_example` 表
3. 配置:
- 模块名:`example`
- 功能名:`案例演示`
- 作者:`admin`
- 是否导入导出:是
4. 点击「预览」查看生成代码
5. 点击「生成」创建文件
## 第 3 步:生成的文件
```text
app/controller/ExampleController.php # 控制器
app/logic/ExampleLogic.php # 业务逻辑
app/model/Example.php # 数据模型
app/validate/ExampleValidate.php # 验证器
ui/src/api/tool/example.ts # 前端 API
ui/src/views/tool/example/index.vue # 列表页
ui/src/views/tool/example/edit.vue # 编辑弹窗
ui/src/views/tool/example/detail.vue # 详情弹窗
ui/src/views/tool/example/columns.ts # 表格列配置
ui/src/views/tool/example/querySchemas.ts # 查询表单配置
```
## 第 4 步:后续操作
生成完成后,以下内容已自动创建:
| 项目 | 状态 | 说明 |
|------|------|------|
| 路由 | ✅ 自动注册 | `route/app.php` 中已插入 CRUD 路由组 |
| 菜单 | ✅ 自动创建 | 主菜单和权限节点已创建 |
| 字典 | ✅ 自动创建 | 带选项的字段已创建字典和字典项 |
通常还需要手动调整:
1. 根据业务需求调整 Logic 属性配置(如 `pageLikeFields`、`pageEqFields`)
2. 补充自定义钩子(如 `beforeDelete`、`afterDetail` 等)
3. 在菜单管理中调整菜单排序和图标
:::tip 生成后调整
生成的代码是基础骨架,通常需要:
- 调整 Logic 的查询条件配置
- 添加删除前校验(beforeDelete)
- 补充详情后的关联数据(afterDetail)
- 配置文件字段和富文本字段
:::
@@ -0,0 +1,67 @@
# 10.9 常见问题
### Q: 生成的文件在哪里?
A: 后端文件生成到 `app/` 目录,前端文件生成到 `ui/src/` 目录。具体路径:
```text
app/controller/{Name}Controller.php # 控制器
app/logic/{Name}Logic.php # 业务逻辑
app/model/{Name}.php # 数据模型
app/validate/{Name}Validate.php # 验证器
ui/src/api/{app}/{name}.ts # API 接口
ui/src/views/{app}/{name}/index.vue # 列表页
ui/src/views/{app}/{name}/edit.vue # 编辑弹窗
ui/src/views/{app}/{name}/detail.vue # 详情弹窗
ui/src/views/{app}/{name}/columns.ts # 表格列配置(仅 ui/ 模板)
ui/src/views/{app}/{name}/querySchemas.ts # 查询表单配置(仅 ui/ 模板)
```
树形结构模块(含 `parent_id` 字段)使用 `ui2/` 模板,不生成 `columns.ts` 和 `querySchemas.ts`。
### Q: 生成后需要手动修改吗?
A: 通常需要。生成的是基础 CRUD 代码,复杂业务逻辑(如关联查询、钩子处理、导入导出)需要手动补充。
### Q: 可以重新生成吗?
A: 可以,但会覆盖已有文件。建议先备份自定义修改。预览接口(preview)不会写入文件,可安全查看。
### Q: 树形结构表怎么生成?
A: 表中包含 `parent_id` 字段时,生成器会自动使用 `ui2/` 树形模板。
### Q: 生成的权限码格式是什么?
A: 格式为 `sys:{模块名}:{操作}`,如 `sys:example:add`。
### Q: 支持哪些数据库?
A: 支持 MySQL、PostgreSQL、SQL Server、Oracle、SQLite 五种数据库。生成器会自动检测当前配置的数据库类型。
### Q: 生成时报错"表名格式不合法"
A: 表名只允许字母、数字、下划线,且不能以数字开头。检查表名是否包含特殊字符。
### Q: 演示环境下能用吗?
A: 预览功能(preview)在演示环境下可用,实际生成(generate)会被拦截。
### Q: 可以用命令行生成吗?
A: 可以。使用 `php think generate:code <表名>` 命令行生成。CLI 不受演示环境限制,也不需要权限配置。详见 [10.2 CLI 命令行使用](/zh/generator/cli.html)。
### Q: CLI 命令和 Web 端有什么区别?
A: 底层引擎完全相同,区别在于操作方式:
- CLI 适合开发环境、批量操作、CI/CD 集成
- Web 端适合日常开发、可视化配置
- CLI 不受权限和演示模式限制
- CLI 支持 `--output` 导出配置、`--config` 从配置生成
### Q: 如何批量生成多张表?
A: Web 端可多选表后点击批量生成。CLI 使用 `--batch` 选项:
```bash
php think generate:code table1,table2,table3 --batch
```
@@ -0,0 +1,206 @@
# 10.1 概述与架构
:::tip 概述
代码生成器可根据数据库表结构一键生成 CRUD 模块的全部代码,包括后端 Controller/Logic/Model/Validate 和前端 API/View。支持 MySQL、PostgreSQL、SQL Server、Oracle、SQLite 五种数据库。
:::
## 使用方式
### 方式一:CLI 命令行
```bash
# -----------------------------------------------------------------------------
# 代码生成器 CLI 命令
# -----------------------------------------------------------------------------
# php think generate:code → 调用 ThinkPHP 命令行的代码生成器
# Example "案例演示" → 表名与注释(用 | 分隔,如 think_example|案例演示)
# --dry-run → 仅预览,不写入文件
php think generate:code think_example|案例演示 --dry-run
```
详见 [CLI 命令行使用](/zh/generator/cli.html)。
### 方式二:Web 管理界面
进入「工具管理 → 代码生成」菜单,可视化操作。
详见 [Web 管理界面](/zh/generator/web-ui.html)。
## 生成流程
```text
┌──────────────┐
│ 数据库表 │ 如 think_example
└──────┬───────┘
│
▼
┌──────────────┐
│ GeneratorService│ 读取表字段信息(多数据库适配)
│ ::getTableList()│
└──────┬───────┘
│
▼
┌──────────────┐
│ GeneratorService│ 字段类型归一化 + 属性分析
│ ::getTableColumns│ (图片、富文本、筛选项、唯一等)
└──────┬───────┘
│
▼
┌──────────────┐
│ GeneratorService│ 模板变量构建 + 模板渲染
│ ::preview() │
└──────┬───────┘
│
▼
┌──────────────┐
│ GeneratorService│ 文件生成 + 菜单创建
│ ::generate() │
└──────┬───────┘
│
┌────┼────┬────┬────┐
▼ ▼ ▼ ▼ ▼
┌────┐┌────┐┌────┐┌────┐┌────┐
│Ctrl││Logi││Mode││Vali││API │
│ . ││ c ││ l ││date││+Vue│
│php ││php ││php ││php ││ │
└────┘└────┘└────┘└────┘└────┘
```
## 核心能力
| 能力 | 说明 |
|------|------|
| 多数据库适配 | MySQL / PostgreSQL / SQL Server / Oracle / SQLite |
| 字段分析 | 自动识别图片字段、富文本字段、筛选字段、唯一字段 |
| 模板渲染 | 基于 PHP 模板引擎,支持自定义模板 |
| 菜单创建 | 自动生成菜单和权限节点 |
| 字典创建 | 自动创建关联字典(含字典项),幂等不重复 |
| 路由注册 | 自动在 route/app.php 中插入 CRUD 路由组 |
| 安全校验 | 表名合法性校验,防止 SQL 注入 |
| CLI 命令行 | `php think generate:code` 命令行操作,支持预览、导出配置、批量生成 |
## API 接口
| 方法 | 路径 | 权限码 | 说明 |
|------|------|--------|------|
| GET | `/api/generator/page` | sys:generator:page | 获取可生成的表列表 |
| POST | `/api/generator/preview` | sys:generator:generate | 预览生成代码(不写入文件) |
| POST | `/api/generator/generate` | sys:generator:generate | 一键生成 |
| POST | `/api/generator/batchGenerate` | sys:generator:generate | 批量生成 |
## CLI 命令行
除 Web 接口外,还提供 CLI 命令行工具,适合开发环境和批量操作:
```bash
# -----------------------------------------------------------------------------
# 列出所有可生成的数据库表
# -----------------------------------------------------------------------------
php think generate:code
# -----------------------------------------------------------------------------
# 预览生成代码(不写入文件,仅输出到终端)
# -----------------------------------------------------------------------------
# --dry-run → 干运行模式(只预览不执行)
php think generate:code think_example --dry-run
# -----------------------------------------------------------------------------
# 一键生成(实际写入文件到 app/ 和 ui/src/)
# -----------------------------------------------------------------------------
php think generate:code think_example
# -----------------------------------------------------------------------------
# 导出配置(将生成参数保存为 JSON,便于重复使用)
# -----------------------------------------------------------------------------
# --output config.json → 输出配置文件路径
php think generate:code think_example --output config.json
# -----------------------------------------------------------------------------
# 从配置生成(读取之前导出的配置文件)
# -----------------------------------------------------------------------------
# --config config.json → 读取配置文件
php think generate:code --config config.json
```
详见 [10.2 CLI 命令行使用](/zh/generator/cli.html)
:::tip 演示模式
preview 接口标注了 `#[DemoAllow]`,演示环境下也可使用。generate 和 batchGenerate 在演示环境下会被拦截。
:::
## 核心代码
```php
// app/controller/GeneratorController.php — 代码生成器控制器
class GeneratorController extends BaseController
{
protected GeneratorLogic $logic;
protected function initialize(): void
{
$this->logic = new GeneratorLogic(); // 初始化代码生成器业务逻辑
}
// 预览生成代码(不写入文件,仅返回渲染结果)
#[Log('代码生成-预览代码', Log::TYPE_QUERY)]
#[Permission('sys:generator:generate', '代码生成')]
#[DemoAllow] // 演示模式允许(只读操作)
public function preview(): Json
{
try {
$params = $this->getJsonBody(); // 获取前端传入的 JSON 参数
$result = $this->logic->preview($params); // 调用逻辑层预览方法
return $this->success($result);
} catch (\Throwable $e) {
// 返回详细错误信息(包含文件名和行号,便于调试)
return $this->fail($e->getMessage() . ' [File: ' . $e->getFile() . ', Line: ' . $e->getLine() . ']');
}
}
// 一键生成(实际写入文件到 app/ 和 ui/src/ 目录)
#[Log('代码生成-一键生成', Log::TYPE_GENERATE)]
#[Permission('sys:generator:generate', '代码生成')]
public function generate(): Json
{
try {
$params = $this->getJsonBody();
$result = $this->logic->generate($params); // 调用逻辑层生成方法
$generated = count($result['generated']); // 成功生成的文件数
$skipped = count($result['skipped']); // 跳过的文件数(已存在)
$msg = "生成完成:成功 {$generated} 个文件";
if ($skipped > 0) {
$msg .= ",跳过 {$skipped} 个文件";
}
return $this->success($result, $msg);
} catch (\Throwable $e) {
return $this->fail($e->getMessage());
}
}
}
```
## 模板文件
```text
templates/ # 代码生成器模板目录
├── controller.php.tpl # 控制器模板
├── logic.php.tpl # 业务逻辑模板(含 serializeMaps、导入导出)
├── model.php.tpl # 数据模型模板
├── validate.php.tpl # 验证器模板
├── ui/ # 普通列表模板(6个前端文件)
│ ├── api.ts.tpl # API 接口模块
│ ├── index.vue.tpl # 列表页
│ ├── edit.vue.tpl # 编辑弹窗
│ ├── detail.vue.tpl # 详情弹窗
│ ├── columns.ts.tpl # 表格列配置
│ └── querySchemas.ts.tpl # 查询表单配置
└── ui2/ # 树形结构模板(4个前端文件)
├── api.ts.tpl
├── index.vue.tpl
├── edit.vue.tpl
└── detail.vue.tpl
```
@@ -0,0 +1,215 @@
# 10.4 表结构解析引擎
:::tip 概述
解析引擎读取数据库表的字段信息(名称、类型、注释、是否必填等),并自动分析字段属性(图片、富文本、选项、外键等),作为代码生成的数据源。支持 MySQL、PostgreSQL、SQL Server、Oracle、SQLite 五种数据库。
:::
## 多数据库适配
```php
// app/service/GeneratorService.php
// 获取当前数据库驱动类型
protected function getDbDriver(): string
{
$default = config('database.default', 'mysql');
return strtolower(config("database.connections.{$default}.type", $default));
}
// 根据驱动分发到对应的查询实现
public function getTableList(): array
{
$driver = $this->getDbDriver();
// MySQL: SHOW TABLE STATUS
// PostgreSQL: information_schema.tables
// SQL Server: sys.tables
// Oracle: all_tables
// SQLite: sqlite_master
}
```
## 基础解析内容
| 信息 | 用途 |
|------|------|
| 字段名 | 生成属性名、查询条件 |
| 字段类型 | 生成验证规则、表单组件 |
| 字段注释 | 生成标签名、注释 |
| 是否必填 | 生成 require 验证规则 |
| 默认值 | 生成默认值配置 |
| 索引信息 | 判断是否唯一校验 |
## 字段类型映射
| 数据库类型 | 归一化类型 | 表单组件 | 验证规则 |
|-----------|---------|---------|---------|
| VARCHAR | CharField | Input | max:N |
| TEXT | TextField | Editor | - |
| INT | IntegerField | InputNumber | number |
| TINYINT | IntegerField | Select / Radio | in:0,1 |
| DECIMAL | DecimalField | InputNumber | float |
| DATETIME | DateTimeField | DatePicker | date |
| DATE | DateField | DatePicker | date |
| TIME | TimeField | TimePicker | - |
| BOOLEAN | BooleanField | Switch | - |
## 字段自动识别规则
解析引擎会自动分析每个字段的属性,识别规则如下:
### 图片字段
| 条件 | 规则 |
|------|------|
| 类型 | VARCHAR |
| 匹配 | 注释或字段名匹配 `/图片\|封面\|头像\|logo\|icon\|image\|avatar\|photo/i` |
识别后:`is_image = true`,归入 `file_fields`,前端用 ElAvatar 渲染。
### 富文本字段
| 条件 | 规则 |
|------|------|
| 类型 | TEXT |
| 匹配 | 注释匹配 `/内容\|详情\|正文/i` |
识别后:`is_rich_text = true`,归入 `content_fields`,自动处理临时文件和图片占位符。
### 多行文本字段
| 条件 | 规则 |
|------|------|
| 类型 | VARCHAR |
| 匹配 | 注释匹配 `/备注\|说明\|描述\|介绍\|简介/i` |
识别后:`is_textarea = true`,前端用 textarea 组件渲染。
### 选项字段(枚举)
解析引擎从字段注释中自动解析选项,支持以下注释格式:
```text
状态:1-启用 2-停用 ← 中文冒号 + 数字-文字
状态:1-启用 2-停用 ← 英文冒号 + 数字-文字
类型:1:制造业 2:旅游业 ← 中文冒号 + 数字:文字
执行策略:1-立即执行 2-执行一次 3-放弃执行
```
解析规则:
1. 以冒号(中文 `:` 或英文 `:`)分割,取冒号后面的部分
2. 匹配 `数字-文字` 或 `数字:文字` 格式
3. 每个匹配项生成一个选项:`{value: 数字, label: 文字, type: 标签颜色}`
标签颜色映射:
| 选项值 | 标签颜色 | Element Plus type |
|--------|---------|-------------------|
| 1 | 绿色 | `success` |
| 2 | 红色 | `danger` |
| 3 | 橙色 | `warning` |
| 其他 | 灰色 | `info` |
识别后:`choices` 数组非空,自动归入 `eq_fields`(精确匹配)和 `serialize_maps`(字典映射)。
### 状态字段自动补全
| 条件 | 规则 |
|------|------|
| 字段名 | `status` |
| 类型 | INT |
| 前提 | 注释中未解析出选项 |
自动生成默认选项:
| 值 | 标签 | 颜色 |
|----|------|------|
| 0 | 正常 | success |
| 1 | 停用 | danger |
### 模糊搜索字段
| 条件 | 规则 |
|------|------|
| 类型 | VARCHAR |
| 匹配 | 字段名匹配 `/名称\|标题\|name\|title\|username\|realname\|nickname\|job_name\|category_name\|dept_name\|role_name/i` |
识别后:归入 `like_fields`,分页查询时 LIKE 匹配,同时加入筛选表单。
### 唯一字段
| 条件 | 规则 |
|------|------|
| 匹配 | 字段名匹配 `/编码\|code\|username\|mobile\|email\|account/i` |
识别后:归入 `unique_fields`,新增/修改时自动校验唯一性。
### 外键字段
| 条件 | 规则 |
|------|------|
| 匹配 | 字段名以 `_id` 或 `_ids` 结尾(排除 `id` 本身) |
识别后:`is_foreign_key = true`,记录 `fk_target`(如 `dept_id` → `dept`),供模板渲染下拉选择使用。
### 排序字段
| 条件 | 规则 |
|------|------|
| 字段名 | `sort` |
识别后:`has_sort = true`,默认排序改为 `sort asc`(而非 `id desc`)。
### 系统字段排除
以下字段自动从表单和列表中排除:
`id`、`tenant_id`、`create_user`、`create_time`、`update_user`、`update_time`、`is_delete`
### 字段注释清洗
注释中的选项部分会被自动移除,只保留中文名称:
```text
"案例状态:1-正常 2-禁用" → "案例状态"
"执行策略:1-立即执行 2-执行一次 3-放弃执行" → "执行策略"
```
## 安全校验
```php
// 表名合法性校验(防 SQL 注入)
protected function validateTableName(string $tableName): string
{
if (!preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $tableName)) {
throw new \Exception('表名格式不合法: ' . $tableName);
}
return $tableName;
}
```
:::warning 安全提示
涉及表名拼接的 SQL 一律先经 `validateTableName` 校验,只允许字母、数字、下划线,防止 SQL 注入。
:::
## 自动创建的权限节点
生成菜单时,自动创建以下 10 个权限节点:
| 权限码 | 说明 |
|--------|------|
| `sys:{模块名}:page` | 分页查询 |
| `sys:{模块名}:list` | 列表查询 |
| `sys:{模块名}:detail` | 详情查询 |
| `sys:{模块名}:add` | 新增 |
| `sys:{模块名}:update` | 编辑 |
| `sys:{模块名}:delete` | 删除 |
| `sys:{模块名}:batchDelete` | 批量删除 |
| `sys:{模块名}:status` | 状态管理 |
| `sys:{模块名}:import` | 导入 |
| `sys:{模块名}:export` | 导出 |
## 相关文档
- [10.5 代码生成引擎](/zh/generator/code-engine.html)
- [10.6 自定义模板开发](/zh/generator/templates.html)
- [10.7 配置文件详解](/zh/generator/config.html)
@@ -0,0 +1,231 @@
# 10.6 自定义模板开发
:::tip 概述
代码生成器使用 PHP 原生模板引擎渲染代码,模板文件存放在 `templates/` 目录下。修改模板即可自定义生成代码的格式。
:::
## 模板目录结构
```text
templates/
├── controller.php.tpl # 控制器模板
├── logic.php.tpl # 业务逻辑模板(含 serializeMaps、导入导出)
├── model.php.tpl # 模型模板
├── validate.php.tpl # 验证器模板
├── ui/ # 普通列表模板(6个前端文件)
│ ├── api.ts.tpl # API 接口模块模板
│ ├── index.vue.tpl # 列表页模板
│ ├── edit.vue.tpl # 编辑弹窗模板
│ ├── detail.vue.tpl # 详情弹窗模板
│ ├── columns.ts.tpl # 表格列配置模板
│ └── querySchemas.ts.tpl # 查询表单配置模板
└── ui2/ # 树形结构模板(4个前端文件)
├── api.ts.tpl
├── index.vue.tpl
├── edit.vue.tpl
└── detail.vue.tpl
```
## 模板变量
模板使用 PHP 原生语法,变量通过 `GeneratorService::buildTemplateVars()` 构建,渲染时通过 `extract($vars)` 注入。
### 基础信息变量
| 变量 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `$app_name` | string | 应用名(路由前缀) | `tool` |
| `$module_name` | string | 模块名(小写下划线) | `example` |
| `$module_comment` | string | 功能名称(表注释清洗后) | `案例` |
| `$model_class_name` | string | 模型类名(大驼峰) | `Example` |
| `$model_class_name_camel` | string | 模型类名(小驼峰) | `example` |
| `$route_prefix` | string | 路由前缀 | `example` |
| `$api_path` | string | API 路径 | `tool/example` |
| `$permission_prefix` | string | 权限码前缀 | `sys:example` |
| `$primary_key` | string | 主键字段名 | `id` |
| `$table_name` | string | 表名(不含前缀) | `example` |
### 树形结构变量
| 变量 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `$is_tree` | bool | 是否为树形结构 | `true` |
| `$parent_id_field` | string | 父级字段名 | `parent_id` |
| `$parent_id_field_camel` | string | 父级字段名(驼峰) | `parentId` |
| `$display_field` | string | 显示字段名 | `name` |
| `$display_field_camel` | string | 显示字段名(驼峰) | `name` |
### 字段列表变量
| 变量 | 类型 | 说明 |
|------|------|------|
| `$fields` | array | 全部字段列表 |
| `$list_fields` | array | 列表页展示字段(排除隐藏字段) |
| `$form_fields` | array | 表单字段(编辑弹窗用) |
| `$filter_fields` | array | 筛选字段(搜索表单用) |
| `$file_fields` | array | 文件/图片字段名列表 |
| `$content_fields` | array | 富文本字段名列表 |
| `$like_fields` | array | 模糊搜索字段名列表 |
| `$eq_fields` | array | 精确匹配字段名列表 |
| `$unique_fields` | array | 唯一性校验字段名列表 |
| `$validate_rules` | array | 验证规则 |
| `$validate_messages` | array | 验证提示信息 |
| `$validate_fields` | array | 需验证的字段列表 |
| `$serialize_maps` | array | 枚举字段 → 字典编码映射 |
| `$foreign_keys` | array | 外键关联信息 |
### 功能标记变量
| 变量 | 类型 | 说明 |
|------|------|------|
| `$has_import` | bool | 是否生成导入方法 |
| `$has_export` | bool | 是否生成导出方法 |
| `$has_image_field` | bool | 是否包含图片字段 |
| `$has_rich_text_field` | bool | 是否包含富文本字段 |
| `$has_sort` | bool | 是否包含排序字段 |
| `$is_tree_structure` | bool | 是否为树形结构(`$is_tree` 别名) |
| `$template_type` | string | 模板类型:`ui` 或 `ui2` |
### 排序变量
| 变量 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `$order_field` | string | 默认排序字段 | `id` 或 `sort` |
| `$order_type` | string | 默认排序方向 | `desc` 或 `asc` |
### 字段结构
每个字段为一个数组,包含以下属性:
```php
$field = [
'name' => 'status', // 字段名(下划线)
'camel_name' => 'status', // 字段名(驼峰)
'label' => '状态', // 中文标签(取字段 COMMENT)
'type' => 'IntegerField', // 字段类型归一化后的类名
'db_type' => 'int', // 原始数据库类型
'default' => 0, // 默认值
'is_image' => false, // 是否为图片字段
'is_rich_text' => false, // 是否为富文本字段
'choices' => [ // 选项列表(有值时可生成 ElTag 渲染)
['value' => 0, 'label' => '正常', 'type' => 'success'],
['value' => 1, 'label' => '禁用', 'type' => 'danger'],
],
];
```
## 模板语法
模板使用 PHP 原生语法,通过 `<?php echo ?>` 输出变量,使用 `<?php foreach ?>` 等控制结构:
### 后端模板示例(logic.php.tpl 片段)
```php
<?php echo '<?php' ?>
declare(strict_types=1);
namespace app\logic;
use app\BaseLogic;
use app\model\<?php echo $model_class_name ?>;
class <?php echo $model_class_name ?>Logic extends BaseLogic
{
protected string $modelClass = <?php echo $model_class_name ?>::class;
protected string $validateClass = \app\validate\<?php echo $model_class_name ?>Validate::class;
<?php if (!empty($file_fields)): ?>
protected array $fileFields = [<?php echo implode(', ', array_map(fn($f) => "'$f'", $file_fields)) ?>];
protected string $fileSaveDir = '<?php echo $module_name ?>';
<?php endif; ?>
<?php if (!empty($serialize_maps)): ?>
protected array $serializeMaps = [
<?php foreach ($serialize_maps as $field => $dict): ?>
'<?php echo $field ?>' => '<?php echo $dict ?>',
<?php endforeach; ?>
];
<?php endif; ?>
<?php if ($is_tree): ?>
protected string $treeParentField = '<?php echo $parent_id_field ?>';
protected string $treeLikeField = '<?php echo $display_field ?>';
<?php endif; ?>
}
```
### 前端模板示例(columns.ts.tpl 片段)
```typescript
import { h } from 'vue';
import { ElAvatar, ElTag } from 'element-plus';
export const columns = [
{ type: 'selection' },
{ label: 'ID', prop: 'id', fixed: 'left', width: 50 },
<?php foreach ($list_fields as $field): ?>
{
label: '<?php echo $field['label'] ?>',
prop: '<?php echo $field['camel_name'] ?>',
<?php if ($field['is_image']): ?>
render(record) {
return h(ElAvatar, { size: 48, src: record.row.<?php echo $field['camel_name'] ?> });
},
<?php elseif ($field['choices']): ?>
render(record) {
const map = {
<?php foreach ($field['choices'] as $choice): ?>
<?php echo $choice['value'] ?>: { text: '<?php echo $choice['label'] ?>', type: '<?php echo $choice['type'] ?>' },
<?php endforeach; ?>
};
const s = map[record.row.<?php echo $field['camel_name'] ?>];
return h(ElTag, { type: s?.type || 'info' }, { default: () => s?.text });
},
<?php endif; ?>
},
<?php endforeach; ?>
];
```
## 自定义模板步骤
1. 修改 `templates/` 目录下的 `.tpl` 文件
2. 使用上述模板变量(`$model_class_name`、`$module_comment` 等)
3. 下次生成时自动使用新模板
:::warning 注意事项
- 修改模板后,已生成的代码不会自动更新
- 模板中不能使用短标签 `<?= ?>`,必须用 `<?php echo ?>`(渲染前有预检)
- 模板文件不能含 UTF-8 BOM 头
- 树形结构模块使用 `ui2/` 模板,普通模块使用 `ui/` 模板
:::
## 模板选择逻辑
```text
表结构中包含 parent_id 或 pid 字段?
│
├─ 是 → 使用 ui2/ 树形模板(自动,无需手动选择)
│
└─ 否 → 使用 ui/ 普通列表模板
```
## 生成的前端文件
`ui/` 模板生成 6 个文件(`ui2/` 生成 4 个,无 columns.ts 和 querySchemas.ts):
| 文件 | 说明 | 引用关系 |
|------|------|----------|
| `api.ts` | API 接口模块 | 被 index.vue、edit.vue 导入 |
| `index.vue` | 列表页 | 导入 columns.ts、querySchemas.ts |
| `edit.vue` | 编辑弹窗 | 被 index.vue 动态加载 |
| `detail.vue` | 详情弹窗 | 被 index.vue 动态加载 |
| `columns.ts` | 表格列配置 | 被 index.vue 导入,含 ElTag/ElAvatar 渲染 |
| `querySchemas.ts` | 查询表单配置 | 被 index.vue 导入,含 Select/Input/DatePicker 组件 |
## 相关文档
- [10.5 代码生成引擎](/zh/generator/code-engine.html)
- [10.7 配置文件详解](/zh/generator/config.html)
- [10.8 实战案例](/zh/generator/demo.html)
@@ -0,0 +1,262 @@
# 10.3 Web 管理界面
:::tip 概述
代码生成器提供 Web 管理界面,通过可视化操作完成代码生成,无需命令行。支持表选择、配置生成选项、预览代码和一键生成。界面位于「工具管理 → 代码生成」菜单。
:::
## 操作流程
```text
1. 登录管理后台
2. 进入「工具管理 → 代码生成」菜单
3. 查看可生成的数据库表列表(自动读取当前数据库的所有表)
4. 选择目标表,点击「配置」
5. 配置生成选项(模块名、功能名、作者等)
6. 点击「预览」查看生成代码(不写入文件,可安全查看)
7. 确认无误后点击「生成」创建文件
8. 在 route/app.php 中添加路由(通常已自动生成)
9. 在菜单管理中配置菜单权限
10. 刷新前端页面,新模块即可使用
```
## 界面说明
### 表列表页
进入「工具管理 → 代码生成」后,首先进入表列表页:
| 列 | 说明 |
|----|------|
| 表名 | 数据库表名(不含前缀) |
| 表注释 | 表的 COMMENT 字段(显示为中文说明) |
| 引擎 | 存储引擎(InnoDB / MyISAM) |
| 行数 | 表中的数据行数 |
| 创建时间 | 表的创建时间 |
| 操作 | 配置 / 预览 / 生成 / 删除 |
### 配置弹窗
点击「配置」按钮后,可设置以下生成选项:
| 配置项 | 参数名 | 说明 | 示例 |
|--------|--------|------|------|
| 表名 | `tableNames` | 选择要生成的表(自动带入,格式 `"表名\|注释"`) | `["think_example\|案例演示"]` |
| 模板类型 | `templateType` | `ui` 普通列表 或 `ui2` 树形(含 parent_id 时自动切换) | `ui` |
| 生成菜单 | `generateMenu` | 是否自动创建菜单和权限节点 | `true` |
| 覆盖文件 | `overwrite` | 是否覆盖已存在的文件 | `false` |
### 预览功能
点击「预览」按钮,可查看即将生成的所有文件代码:
- 预览模式**不会写入文件**,可安全查看
- 支持切换查看不同文件(Controller / Logic / Model / Validate / API / Vue / columns.ts / querySchemas.ts)
- 确认无误后再点击「生成」实际创建文件
### 批量生成
在表列表页勾选多张表,点击「批量生成」:
- 批量生成会为每张表分别生成完整的 CRUD 模块(含文件、菜单、字典、路由)
- 单张表失败不影响其它表继续生成
- 生成结果会显示每张表的成功/失败状态和文件统计
## 配置选项详解
### 模块名(自动推导)
模块名由表名去掉前缀自动推导,影响以下内容:
| 影响范围 | 规则 | 示例(模块名=example) |
|----------|------|----------------------|
| 后端路由前缀 | `/api/{模块名}/` | `/api/example/page` |
| 前端 API 文件 | `ui/src/api/{app}/{模块名}.ts` | `ui/src/api/tool/example.ts` |
| 前端视图目录 | `ui/src/views/{app}/{模块名}/` | `ui/src/views/tool/example/` |
| 权限码前缀 | `sys:{模块名}:` | `sys:example:page` |
| 字典编码前缀 | `{模块名}_{字段名}` | `example_status` |
### 树形结构(自动检测)
当表中包含 `parent_id` 或 `pid` 字段时,引擎自动切换为 `ui2/` 树形模板:
- 前端使用 Tree + Table 左右布局
- 支持拖拽排序、展开/折叠
- 自动处理父子关系的新增和编辑
- 树形模板不生成 `columns.ts` 和 `querySchemas.ts`
- Controller 中不生成 `page()` 方法
### 导入导出(默认生成)
默认生成 `import()` 和 `export()` 方法:
- 后端基于 `ExcelService` 实现分批导入导出
- 枚举字段自动做正向/反向映射(值 ↔ 文本)
- 前端生成导入/导出按钮
### 字典自动创建
带选项(choices)的字段会自动创建字典:
- 在 `think_dict` 和 `think_dict_item` 表中创建记录
- Logic 中自动生成 `$serializeMaps` 映射
- 查询时自动补 `{字段名}Text` 翻译字段
- 幂等:字典编码已存在则跳过
### 路由自动注册
在 `route/app.php` 中自动插入 CRUD 路由组:
- 包含 list / detail / add / update / delete / batchDelete / import / export
- 非树形结构额外包含 page 路由
- 幂等:路由组已存在则跳过
## API 接口
| 方法 | 路径 | 权限码 | 说明 |
|------|------|--------|------|
| GET | `/api/generator/page` | sys:generator:page | 获取可生成的表列表(分页) |
| POST | `/api/generator/preview` | sys:generator:generate | 预览生成代码(不写入文件) |
| POST | `/api/generator/generate` | sys:generator:generate | 一键生成(写入文件) |
| POST | `/api/generator/batchGenerate` | sys:generator:generate | 批量生成(多表) |
:::tip 演示模式
预览接口(preview)标注了 `#[DemoAllow]`,演示环境下也可使用。生成接口(generate / batchGenerate)在演示环境下会被拦截。
:::
### 请求参数
```json
{
"tableNames": ["think_example|案例演示"],
"templateType": "ui",
"generateMenu": true,
"overwrite": false
}
```
| 参数 | 类型 | 必填 | 说明 | 默认值 |
|------|------|------|------|--------|
| `tableNames` | string[] | 是 | 表名数组,格式为 `"表名\|注释"` | - |
| `templateType` | string | 否 | 模板类型:`ui`(普通列表)或 `ui2`(树形) | `ui` |
| `generateMenu` | bool | 否 | 是否自动创建菜单和权限节点 | `true` |
| `overwrite` | bool | 否 | 是否覆盖已存在的文件 | `false` |
:::info 树形结构自动切换
当表中包含 `parent_id` 或 `pid` 字段时,即使传入 `templateType: "ui"`,也会自动切换为 `ui2` 树形模板。
:::
### 请求示例
```bash
# -----------------------------------------------------------------------------
# 预览生成代码(不写入文件)
# -----------------------------------------------------------------------------
# POST /api/generator/preview
# Content-Type: application/json
# Authorization: Bearer <token>
curl -X POST http://localhost:8000/api/generator/preview \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{
"tableNames": ["think_example|案例演示"],
"templateType": "ui"
}'
```
### 响应示例
```json
{
"code": 0,
"ok": true,
"msg": "操作成功",
"data": {
"files": [
{
"path": "app/controller/ExampleController.php",
"content": "<?php\nnamespace app\\controller;\n// ...",
"exists": false,
"type": "backend"
},
{
"path": "app/logic/ExampleLogic.php",
"content": "<?php\nnamespace app\\logic;\n// ...",
"exists": false,
"type": "backend"
},
{
"path": "ui/src/views/tool/example/columns.ts",
"content": "import { h } from 'vue';\n// ...",
"exists": false,
"type": "frontend"
}
],
"vars": {
"module_name": "example",
"module_comment": "案例",
"model_class_name": "Example",
"template_type": "ui",
"is_tree": false
},
"menu_info": {
"name": "案例",
"path": "/tool/example",
"component": "tool/example/index"
}
}
}
```
:::tip 响应结构说明
- `files`:待生成文件数组,每项含 `path`(相对路径)、`content`(渲染后内容)、`exists`(是否已存在)、`type`(backend/frontend)
- `vars`:模板变量,供调试和导出配置使用
- `menu_info`:将要创建的菜单信息
:::
## 生成后操作清单
```bash
# -----------------------------------------------------------------------------
# 第 1 步:检查生成的文件
# -----------------------------------------------------------------------------
ls app/controller/Example* # 控制器
ls app/logic/Example* # 业务逻辑
ls app/model/Example* # 数据模型
ls app/validate/Example* # 验证器
ls ui/src/api/tool/example* # 前端 API
ls ui/src/views/tool/example/ # 前端页面(含 index.vue / edit.vue / detail.vue / columns.ts / querySchemas.ts)
# -----------------------------------------------------------------------------
# 第 2 步:在 route/app.php 中添加路由(通常已自动生成)
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# 第 3 步:在菜单管理中配置菜单权限
# -----------------------------------------------------------------------------
# 新增菜单:案例演示(路径:/example,组件:tool/example/index)
# 新增按钮权限:sys:example:page / sys:example:add / sys:example:update / sys:example:delete
# -----------------------------------------------------------------------------
# 第 4 步:根据业务需求调整 Logic 属性配置
# -----------------------------------------------------------------------------
# 可调整:fileFields(文件字段)、serializeMaps(字典映射)、pageLikeFields(模糊查询)等
```
## 与 CLI 命令对比
| 特性 | Web 界面 | CLI 命令 |
|------|----------|----------|
| 使用方式 | 浏览器可视化操作 | 命令行 |
| 适用场景 | 日常开发、单表生成 | 批量生成、CI/CD 集成 |
| 预览功能 | ✅ 支持(不写入文件) | ✅ 支持(--dry-run) |
| 批量生成 | ✅ 支持(多选表) | ✅ 支持(--batch) |
| 配置选项 | 更多(树形、导入导出等) | 基础配置 |
| 权限限制 | 受权限和演示模式限制 | 不受限制 |
| 导出配置 | ❌ 不支持 | ✅ 支持(--output) |
## 相关文档
- [10.1 概述与架构](/zh/generator/overview.html)
- [10.2 CLI 命令行使用](/zh/generator/cli.html)
- [10.4 表结构解析引擎](/zh/generator/parser.html)
- [10.8 实战案例](/zh/generator/demo.html)