Files
rxthinkcmf-wiki/RXThinkCMF_Laravel13_NaiveVue/zh/generator/code-engine.md
T
2026-10-11 19:06:33 +08:00

11 KiB
Raw Blame History

10.5 代码生成引擎

:::tip 概述 代码生成引擎基于模板文件,将表结构信息渲染为实际代码文件。渲染使用 PHP 原生 include + extract 机制,模板变量由 GeneratorService::buildTemplateVars() 统一构建,预览与生成的编排由 GeneratorLogic 负责。 :::

生成文件清单

后端文件(4 个文件,输出路径见 config/generator.php 的 backend_outputs)

文件 模板 说明
app/Http/Controllers/Api/{Name}Controller.php controller.php.tpl 控制器,含分页/列表/详情/增删改/批量删除/导入/导出
app/Services/{Name}Service.php service.php.tpl 业务服务,含属性配置、serializeMaps、导入导出方法
app/Models/{Name}.php model.php.tpl 数据模型,含软删除(is_delete)、审计字段自动填充;树形结构额外生成 children() 自关联
app/Http/Requests/{Name}Request.php request.php.tpl FormRequest 验证器,按字段分析自动生成验证规则(camelCase 字段名、required 规则、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 表格列配置(含图片 NAvatar、选项 NTag、链接等渲染)
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/ 树形模板(GeneratorService::buildTemplateVars() 内检测,结果体现在 is_tree 变量),否则使用 ui/ 普通列表模板。树形模板不生成 columns.ts 和 querySchemas.ts。 :::

GeneratorService 核心方法

// app/Services/GeneratorService.php

/**
 * 获取可生成的表列表
 *
 * 读取当前数据库所有表,返回表名、注释、引擎、行数等信息。
 * 支持 MySQL / PostgreSQL / SQL Server / Oracle / SQLite。
 */
public function getTableList(): array { ... }

/**
 * 解析单表结构
 *
 * 读取列信息、主键、索引与表注释,输出字段归一化结果。
 */
public function parseTableStructure(string $tableName): array { ... }

/**
 * 构建模板变量
 *
 * 解析表结构 → 字段分析 → 构建全部模板变量。
 * 是生成引擎的核心,决定模板中可用的所有变量。
 * 自动检测树形结构(parent_id / pid),切换 template_type 为 ui2。
 */
public function buildTemplateVars(string $tableName, string $moduleComment = '', string $templateType = 'ui'): array { ... }

/**
 * 渲染模板
 *
 * 使用 PHP extract + include 机制渲染 .tpl 文件。
 * 模板不存在或渲染抛错时,带模板文件名上下文重新抛出异常。
 */
public function renderTemplate(string $templatePath, array $vars): string { ... }

/**
 * 生成单个文件
 *
 * 已存在且未开启覆盖 → skipped;目录不存在自动创建(0755)。
 */
public function generateFile(string $path, string $content, bool $overwrite = false): array { ... }

/**
 * 创建菜单和权限节点
 *
 * 在 GENERATOR_PARENT_MENU_ID 指定的父菜单下创建主菜单(type=0)
 * 和 9 个标准权限节点(type=1):
 * page / list / detail / add / update / delete / batchDelete / import / export。
 * path 已存在则跳过(幂等),排序值按父级 max(sort) + 5 递增。
 */
public function createMenu(string $moduleComment, string $moduleName): array { ... }

/**
 * 创建字典数据
 *
 * 遍历 serialize_maps,为带选项的字段自动创建字典主记录和字典项。
 * 幂等:字典编码已存在则跳过。
 */
public function createDictData(string $moduleComment, string $moduleName, array $serializeMaps, array $fields): array { ... }

/**
 * 注册模块路由
 *
 * 在 routes/api.php 末尾的中间件组闭合 `});` 之前插入标准 CRUD 路由组。
 * 分组注释取表注释(为空时回退模块名),幂等以路由路径判断。
 * 树形结构不生成 page 路由。
 */
public function registerRoute(string $moduleName, string $controllerName, bool $isTree = false, string $moduleComment = ''): array { ... }

/**
 * 获取生成的文件列表
 *
 * 返回后端与前端应生成的文件相对路径,供生成结果核对或展示。
 */
public function getGenerateFiles(string $moduleName, string $templateType = 'ui'): array { ... }

GeneratorLogic 编排方法

// app/Services/GeneratorLogic.php — 面向控制器的编排层

// 获取表列表(含分页参数处理)
public function getTableList(array $params = []): array { ... }

// 预览生成代码(不写入文件):渲染全部模板,返回内容 + 是否已存在
public function preview(array $params): array { ... }

// 生成代码(写入文件):写后端 → 写前端 → 创建菜单(可选)→ 创建字典 → 注册路由
public function generate(array $params): array { ... }

// 批量生成:逐表调用 generate,单表失败不中断整体
public function batchGenerate(array $params): array { ... }

generate() 参数:tableNames(必填)、templateType(ui/ui2,可省略)、generateMenu(默认 true)、overwrite(默认 false,不覆盖已存在文件)。

字段分析流程

原始表字段(数据库列信息)
    │
    ▼
类型归一化(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|realname/i 且类型为 varchar
    ├─ 唯一字段   → 字段名匹配 /编码|code|username|mobile|email|account/i
    ├─ 排序字段   → 字段名为 sort(标记 has_sort)
    └─ 排除字段   → id / tenant_id / create_user / create_time / update_user / update_time / is_delete
                    不进表单与列表
    ▼
serialize_maps 构建
    │  有 choices 的字段自动生成映射:字段名 → "{模块名}_{字段名}"
    │  如 status → "example_status"
    ▼
输出分组字段列表
    │  $fields['all']     全部字段
    │  $fields['list']    列表展示字段(text 长文本默认不进列表)
    │  $fields['form']    表单字段(全量生成规则,含 id → validate_rules / validate_rules_update)
    │  $fields['filter']  筛选字段(含模糊搜索和精确匹配)
    │  $fields['file']    单文件/图片字段
    │  $fields['multi']   多文件字段(逗号分隔的多条路径,如图集)
    │  $fields['content'] 富文本字段
    │  $fields['like']    模糊搜索字段
    │  $fields['eq']      精确匹配字段(含选项字段)
    │  $fields['unique']  唯一字段
    │  $fields['serialize_maps']  枚举映射(字段 → 字典编码)
    │  $fields['field_labels'] / casts / hidden  字段中文名 / 类型转换 / 敏感字段
    │  $fields['validate_rules'] / validate_rules_update / validate_messages / validate_fields  FormRequest 规则

渲染机制

// 渲染原理(简化,见 GeneratorService::renderTemplate)
public function renderTemplate(string $templatePath, array $vars): string
{
    if (! file_exists($templatePath)) {
        throw new \Exception('模板文件不存在: '.$templatePath);
    }

    extract($vars);         // 将变量注入当前作用域
    ob_start();             // 开启输出缓冲
    try {
        include $templatePath;  // 执行模板文件
    } catch (\Throwable $e) {
        ob_end_clean();         // 丢弃半成品输出
        throw new \Exception('模板渲染失败 ['.basename($templatePath).'] '.$e->getMessage());
    }
    return ob_get_clean();  // 返回渲染结果
}

:::warning 模板编写规范

  • 使用 <?php echo ?> 输出变量,与 resources/templates/ 现有模板保持一致(现有模板均不含短标签)
  • 文件编码必须为 UTF-8 无 BOM
  • 控制结构(foreach/if)使用完整的 <?php ?> 标签
  • 模板渲染异常会带文件名抛出,便于定位是哪张模板出错 :::

生成后自动操作

代码生成后,引擎会自动执行以下操作:

操作 说明 幂等性
写入文件 生成 Controller / Service / Model / Request / API / Vue 文件 文件已存在则跳过(除非 overwrite=true)
创建菜单 在 GENERATOR_PARENT_MENU_ID 父菜单下创建主菜单和 9 个权限节点 path 已存在则跳过
创建字典 为带选项的字段自动创建字典和字典项 字典编码已存在则跳过
注册路由 在 routes/api.php 插入 CRUD 路由组(分组注释取表注释,如 // --- 案例演示 ---) 同模块路由已存在则跳过

:::warning 生成后需手动生效

  • 路由写入 routes/api.php 后,若生产环境执行过 php artisan route:cache,需重新执行 php artisan route:cache
  • 菜单与权限写入数据库后,需重新登录或刷新前端动态菜单才能看到新菜单 :::

相关文档