签入版本

This commit is contained in:
2026-10-08 17:50:29 +08:00
parent 809750b47e
commit e213a9b31d
444 changed files with 39366 additions and 37533 deletions
@@ -1,17 +1,17 @@
# 10.6 自定义模板开发
:::tip 概述
代码生成器使用 PHP 原生模板引擎渲染代码,模板文件存放在 `templates/` 目录下。修改模板即可自定义生成代码的格式。
代码生成器使用 PHP 原生模板引擎渲染代码,模板文件存放在 `resources/templates/` 目录下(由 `config/generator.php` 的 `template_dir` 配置)。修改模板即可自定义生成代码的格式。
:::
## 模板目录结构
```text
templates/
resources/templates/
├── controller.php.tpl # 控制器模板
├── logic.php.tpl # 业务逻辑模板(含 serializeMaps、导入导出)
├── service.php.tpl # 业务服务模板(含 serializeMaps、导入导出)
├── model.php.tpl # 模型模板
├── validate.php.tpl # 验证器模板
├── request.php.tpl # FormRequest 验证器模板
├── ui/ # 普通列表模板(6个前端文件)
│ ├── api.ts.tpl # API 接口模块模板
│ ├── index.vue.tpl # 列表页模板
@@ -26,6 +26,8 @@ templates/
└── detail.vue.tpl
```
后端 4 张模板的目标输出路径由 `config/generator.php` 的 `backend_outputs` 决定(`{ClassName}` 占位符替换为模型类名),前端输出路径由 `GeneratorLogic` 按 `app_name` 与模块名拼接。
## 模板变量
模板使用 PHP 原生语法,变量通过 `GeneratorService::buildTemplateVars()` 构建,渲染时通过 `extract($vars)` 注入。
@@ -34,8 +36,8 @@ templates/
| 变量 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `$app_name` | string | 应用名(路由前缀) | `tool` |
| `$module_name` | string | 模块名(小写下划线) | `example` |
| `$app_name` | string | 应用名(路由前缀、前端目录),读 `GENERATOR_APP_NAME` | `tool` |
| `$module_name` | string | 模块名(小写下划线,表名去前缀) | `example` |
| `$module_comment` | string | 功能名称(表注释清洗后) | `案例` |
| `$model_class_name` | string | 模型类名(大驼峰) | `Example` |
| `$model_class_name_camel` | string | 模型类名(小驼峰) | `example` |
@@ -44,15 +46,16 @@ templates/
| `$permission_prefix` | string | 权限码前缀 | `sys:example` |
| `$primary_key` | string | 主键字段名 | `id` |
| `$table_name` | string | 表名(不含前缀) | `example` |
| `$parent_menu_id` | int | 菜单挂载父ID,读 `GENERATOR_PARENT_MENU_ID` | `189` |
### 树形结构变量
| 变量 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `$is_tree` | bool | 是否为树形结构 | `true` |
| `$parent_id_field` | string | 父级字段名 | `parent_id` |
| `$parent_id_field` | string | 父级字段名(pid 优先) | `parent_id` |
| `$parent_id_field_camel` | string | 父级字段名(驼峰) | `parentId` |
| `$display_field` | string | 显示字段名 | `name` |
| `$display_field` | string | 显示字段名(按候选列表自动探测) | `name` |
| `$display_field_camel` | string | 显示字段名(驼峰) | `name` |
### 字段列表变量
@@ -65,26 +68,31 @@ templates/
| `$filter_fields` | array | 筛选字段(搜索表单用) |
| `$file_fields` | array | 文件/图片字段名列表 |
| `$content_fields` | array | 富文本字段名列表 |
| `$multi_file_fields` | array | 多文件字段名列表(逗号分隔的多条路径) |
| `$like_fields` | array | 模糊搜索字段名列表 |
| `$eq_fields` | array | 精确匹配字段名列表 |
| `$unique_fields` | array | 唯一性校验字段名列表 |
| `$validate_rules` | array | 验证规则 |
| `$validate_rules` | array | 新增接口验证规则(必填 + 类型 + 长度约束,含 `id`) |
| `$validate_rules_update` | array | 修改接口验证规则(required 降级为 nullable,其余约束保持) |
| `$validate_messages` | array | 验证提示信息 |
| `$validate_fields` | array | 需验证的字段列表 |
| `$validate_fields` | array | 必填字段列表 |
| `$serialize_maps` | array | 枚举字段 → 字典编码映射 |
| `$foreign_keys` | array | 外键关联信息 |
| `$field_labels` | array | 字段中文名映射(唯一性冲突提示用) |
| `$casts` | array | 字段类型转换(时间列 → datetime / date) |
| `$hidden_fields` | array | 需隐藏的敏感字段(密码、令牌等) |
### 功能标记变量
| 变量 | 类型 | 说明 |
|------|------|------|
| `$has_import` | bool | 是否生成导入方法 |
| `$has_export` | bool | 是否生成导出方法 |
| `$has_import` | bool | 是否生成导入方法(当前恒为 true) |
| `$has_export` | bool | 是否生成导出方法(当前恒为 true) |
| `$has_image_field` | bool | 是否包含图片字段 |
| `$has_rich_text_field` | bool | 是否包含富文本字段 |
| `$has_sort` | bool | 是否包含排序字段 |
| `$is_tree_structure` | bool | 是否为树形结构(`$is_tree` 别名) |
| `$template_type` | string | 模板类型:`ui` 或 `ui2` |
| `$tenant_scope` | bool | 表中是否含 `tenant_id`(决定继承 `BaseTenantService`) |
### 排序变量
@@ -101,12 +109,22 @@ templates/
$field = [
'name' => 'status', // 字段名(下划线)
'camel_name' => 'status', // 字段名(驼峰)
'label' => '状态', // 中文标签(取字段 COMMENT)
'type' => 'IntegerField', // 字段类型归一化后的类名
'db_type' => 'int', // 原始数据库类型
'label' => '状态', // 中文标签(注释清洗后,无注释回退字段名)
'comment' => '状态:1-正常 2-停用', // 原始字段注释
'type' => 'IntegerField', // 字段类型归一化后的配置类名
'rawType' => 'int', // 原始数据库类型
'default' => 0, // 默认值
'required' => false, // 是否必填(非空且无默认值)
'nullable' => true, // 数据库是否允许 NULL
'is_image' => false, // 是否为图片字段
'is_rich_text' => false, // 是否为富文本字段
'is_textarea' => false, // 是否为多行文本
'is_number' => false, // 是否为数字字段
'is_datetime' => false, // 是否为时间字段
'in_form' => true, // 是否进表单
'in_list' => true, // 是否进列表
'filterable' => false, // 是否可筛选
'filter_type' => '', // 筛选方式:'精确匹配' / '' / '模糊'
'choices' => [ // 选项列表(有值时可生成 ElTag 渲染)
['value' => 0, 'label' => '正常', 'type' => 'success'],
['value' => 1, 'label' => '禁用', 'type' => 'danger'],
@@ -118,28 +136,28 @@ $field = [
模板使用 PHP 原生语法,通过 `<?php echo ?>` 输出变量,使用 `<?php foreach ?>` 等控制结构:
### 后端模板示例(logic.php.tpl 片段)
### 后端模板示例(service.php.tpl 片段)
```php
<?php echo '<?php' ?>
declare(strict_types=1);
namespace App\Services;
namespace app\logic;
use App\Models\<?php echo $model_class_name ?>;
use app\BaseLogic;
use app\model\<?php echo $model_class_name ?>;
class <?php echo $model_class_name ?>Logic extends BaseLogic
class <?php echo $model_class_name ?>Service extends <?php echo $is_tree ? 'BaseService' : ($tenant_scope ? 'BaseTenantService' : 'BaseService') ?>
{
use HasCrudOperations, HasQueryScopes, HasSerializeMaps<?php if (!empty($unique_fields)) { echo ', HasUniqueCheck'; } ?>;
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; ?>
protected array $pageOrderBy = ['field' => '<?php echo $order_field ?>', 'type' => '<?php echo $order_type ?>'];
<?php if (!empty($serialize_maps)): ?>
protected array $serializeMaps = [
<?php foreach ($serialize_maps as $field => $dict): ?>
@@ -190,15 +208,16 @@ export const columns = [
## 自定义模板步骤
1. 修改 `templates/` 目录下的 `.tpl` 文件
1. 修改 `resources/templates/` 目录下的 `.tpl` 文件(或调整 `config/generator.php` 的 `template_dir` 指向其它目录)
2. 使用上述模板变量(`$model_class_name`、`$module_comment` 等)
3. 下次生成时自动使用新模板
:::warning 注意事项
- 修改模板后,已生成的代码不会自动更新
- 模板中不能使用短标签 `<?= ?>`,必须用 `<?php echo ?>`(渲染前有预检)
- 模板文件不能含 UTF-8 BOM 头
- 修改模板后,已生成的代码不会自动更新(需重新生成,且注意 `overwrite` 参数)
- 模板中使用 `<?php echo ?>` 输出变量,与现有模板保持一致(现有模板均不含短标签)
- 模板文件不能含 UTF-8 BOM 头,否则渲染结果开头会带不可见字符
- 树形结构模块使用 `ui2/` 模板,普通模块使用 `ui/` 模板
- 后端模板输出路径若调整 `backend_outputs`,注意同步 `GeneratorService::getGenerateFiles()` 的文件清单
:::
## 模板选择逻辑