Files
rxthinkcmf-wiki/RXThinkCMF_Laravel13_NaiveVue/zh/generator/templates.md
T
2026-10-08 17:50:29 +08:00

11 KiB
Raw Blame History

10.6 自定义模板开发

:::tip 概述 代码生成器使用 PHP 原生模板引擎渲染代码,模板文件存放在 resources/templates/ 目录下(由 config/generator.php 的 template_dir 配置)。修改模板即可自定义生成代码的格式。 :::

模板目录结构

resources/templates/
├── controller.php.tpl          # 控制器模板
├── service.php.tpl             # 业务服务模板(含 serializeMaps、导入导出)
├── model.php.tpl               # 模型模板
├── request.php.tpl             # FormRequest 验证器模板
├── 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

后端 4 张模板的目标输出路径由 config/generator.php 的 backend_outputs 决定({ClassName} 占位符替换为模型类名),前端输出路径由 GeneratorLogic 按 app_name 与模块名拼接。

模板变量

模板使用 PHP 原生语法,变量通过 GeneratorService::buildTemplateVars() 构建,渲染时通过 extract($vars) 注入。

基础信息变量

变量 类型 说明 示例
$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
$route_prefix string 路由前缀 example
$api_path string API 路径 tool/example
$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 父级字段名(pid 优先) 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 富文本字段名列表
$multi_file_fields array 多文件字段名列表(逗号分隔的多条路径)
$like_fields array 模糊搜索字段名列表
$eq_fields array 精确匹配字段名列表
$unique_fields array 唯一性校验字段名列表
$validate_rules array 新增接口验证规则(必填 + 类型 + 长度约束,含 id)
$validate_rules_update array 修改接口验证规则(required 降级为 nullable,其余约束保持)
$validate_messages array 验证提示信息
$validate_fields array 必填字段列表
$serialize_maps array 枚举字段 → 字典编码映射
$field_labels array 字段中文名映射(唯一性冲突提示用)
$casts array 字段类型转换(时间列 → datetime / date)
$hidden_fields array 需隐藏的敏感字段(密码、令牌等)

功能标记变量

变量 类型 说明
$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)

排序变量

变量 类型 说明 示例
$order_field string 默认排序字段 id 或 sort
$order_type string 默认排序方向 desc 或 asc

字段结构

每个字段为一个数组,包含以下属性:

$field = [
    'name'       => 'status',        // 字段名(下划线)
    'camel_name' => 'status',        // 字段名(驼峰)
    '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'],
    ],
];

模板语法

模板使用 PHP 原生语法,通过 <?php echo ?> 输出变量,使用 <?php foreach ?> 等控制结构:

后端模板示例(service.php.tpl 片段)

<?php echo '<?php' ?>

namespace App\Services;

use App\Models\<?php echo $model_class_name ?>;

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;

<?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): ?>
        '<?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 片段)

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. 修改 resources/templates/ 目录下的 .tpl 文件(或调整 config/generator.php 的 template_dir 指向其它目录)
  2. 使用上述模板变量($model_class_name、$module_comment 等)
  3. 下次生成时自动使用新模板

:::warning 注意事项

  • 修改模板后,已生成的代码不会自动更新(需重新生成,且注意 overwrite 参数)
  • 模板中使用 <?php echo ?> 输出变量,与现有模板保持一致(现有模板均不含短标签)
  • 模板文件不能含 UTF-8 BOM 头,否则渲染结果开头会带不可见字符
  • 树形结构模块使用 ui2/ 模板,普通模块使用 ui/ 模板
  • 后端模板输出路径若调整 backend_outputs,注意同步 GeneratorService::getGenerateFiles() 的文件清单 :::

模板选择逻辑

表结构中包含 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 组件

相关文档