Commit f83d93bd5b21edd57e1f4aedaa26806e6e9e3037

Authored by 芋道源码
Committed by Gitee
2 parents 5d77e375 37e5152a

!1321 【功能新增】INFRA: vben next schema 单表和树表代码生成

Merge pull request !1321 from puhui999/master-jdk17
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java
@@ -15,6 +15,7 @@ public enum CodegenFrontTypeEnum { @@ -15,6 +15,7 @@ public enum CodegenFrontTypeEnum {
15 VUE2(10), // Vue2 Element UI 标准模版 15 VUE2(10), // Vue2 Element UI 标准模版
16 VUE3(20), // Vue3 Element Plus 标准模版 16 VUE3(20), // Vue3 Element Plus 标准模版
17 VUE3_VBEN(30), // Vue3 VBEN 模版 17 VUE3_VBEN(30), // Vue3 VBEN 模版
  18 + VUE3_VBEN_NEXT_SCHEMA(40), // Vue3 vben5 schema 模版
18 ; 19 ;
19 20
20 /** 21 /**
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
@@ -144,6 +144,24 @@ public class CodegenEngine { @@ -144,6 +144,24 @@ public class CodegenEngine {
144 vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Modal.vue")) 144 vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Modal.vue"))
145 .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("api/api.ts"), 145 .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("api/api.ts"),
146 vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) 146 vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
  147 + // Vue3 vben5 schema 模版
  148 + .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/data.ts"),
  149 + vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts"))
  150 + .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/index.vue"),
  151 + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
  152 + .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/form.vue"),
  153 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue"))
  154 + .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("api/api.ts"),
  155 + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
  156 + // 主子表模板配置 - Vue3 vben5 schema 模版
  157 + //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/master_slave_data.ts"),
  158 + // vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts"))
  159 + //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/master_slave_index.vue"),
  160 + // vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
  161 + //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/modules/master_slave_form.vue"),
  162 + // vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue"))
  163 + //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/modules/sub_table.vue"),
  164 + // vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/sub_table.vue"))
147 .build(); 165 .build();
148 166
149 @Resource 167 @Resource
@@ -496,6 +514,10 @@ public class CodegenEngine { @@ -496,6 +514,10 @@ public class CodegenEngine {
496 return "codegen/vue3_vben/" + path + ".vm"; 514 return "codegen/vue3_vben/" + path + ".vm";
497 } 515 }
498 516
  517 + private static String vue3VbenNextSchemaTemplatePath(String path) {
  518 + return "codegen/vue3_vben_next/schema/" + path + ".vm";
  519 + }
  520 +
499 private static boolean isSubTemplate(String path) { 521 private static boolean isSubTemplate(String path) {
500 return path.contains("_sub"); 522 return path.contains("_sub");
501 } 523 }
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/ant_design_vue/index.vue.vm 0 → 100644
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm 0 → 100644
  1 +import type { PageParam, PageResult } from '@vben/request';
  2 +
  3 +import { requestClient } from '#/api/request';
  4 +#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
  5 +
  6 +export namespace ${simpleClassName}Api {
  7 + /** ${table.classComment}信息 */
  8 + export interface ${simpleClassName} {
  9 +#foreach ($column in $columns)
  10 +#if ($column.createOperation || $column.updateOperation)
  11 +#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
  12 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment}
  13 +#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
  14 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: Date; // ${column.columnComment}
  15 +#else
  16 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment}
  17 +#end
  18 +#end
  19 +#end
  20 +#if ( $table.templateType == 2 )
  21 + children?: ${simpleClassName}[];
  22 +#end
  23 + }
  24 +}
  25 +
  26 +#if ( $table.templateType != 2 )
  27 +/** 查询${table.classComment}分页 */
  28 +export function get${simpleClassName}Page(params: PageParam) {
  29 + return requestClient.get<PageResult<${simpleClassName}Api.${simpleClassName}>>('${baseURL}/page', { params });
  30 +}
  31 +#else
  32 +/** 查询${table.classComment}列表 */
  33 +export function get${simpleClassName}List(params: any) {
  34 + return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>('${baseURL}/list', { params });
  35 +}
  36 +#end
  37 +
  38 +/** 查询${table.classComment}详情 */
  39 +export function get${simpleClassName}(id: number) {
  40 + return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/get?id=${id}`);
  41 +}
  42 +
  43 +/** 新增${table.classComment} */
  44 +export function create${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  45 + return requestClient.post('${baseURL}/create', data);
  46 +}
  47 +
  48 +/** 修改${table.classComment} */
  49 +export function update${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  50 + return requestClient.put('${baseURL}/update', data);
  51 +}
  52 +
  53 +/** 删除${table.classComment} */
  54 +export function delete${simpleClassName}(id: number) {
  55 + return requestClient.delete(`${baseURL}/delete?id=${id}`);
  56 +}
  57 +
  58 +/** 导出${table.classComment} */
  59 +export function export${simpleClassName}(params: any) {
  60 + return requestClient.download('${baseURL}/export-excel', params);
  61 +}
  62 +
  63 +## 特殊:主子表专属逻辑
  64 +#foreach ($subTable in $subTables)
  65 +#set ($index = $foreach.count - 1)
  66 +#set ($subSimpleClassName = $subSimpleClassNames.get($index))
  67 +#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
  68 +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
  69 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  70 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  71 +#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  72 +#set ($subClassNameVar = $subClassNameVars.get($index))
  73 +
  74 +// ==================== 子表($subTable.classComment) ====================
  75 +## 情况一:MASTER_ERP 时,需要分查询页子表
  76 +#if ( $table.templateType == 11 )
  77 +/** 获得${subTable.classComment}分页 */
  78 +export function get${subSimpleClassName}Page(params: PageParam) {
  79 + return requestClient.get<PageResult<${simpleClassName}Api.${simpleClassName}>>(`${baseURL}/${subSimpleClassName_strikeCase}/page`, { params });
  80 +}
  81 +## 情况二:非 MASTER_ERP 时,需要列表查询子表
  82 +#else
  83 + #if ( $subTable.subJoinMany )
  84 +/** 获得${subTable.classComment}列表 */
  85 +export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
  86 + return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>(`${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  87 +}
  88 + #else
  89 +/** 获得${subTable.classComment} */
  90 +export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
  91 + return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  92 +}
  93 + #end
  94 +#end
  95 +## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作
  96 +#if ( $table.templateType == 11 )
  97 +/** 新增${subTable.classComment} */
  98 +export function create${subSimpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  99 + return requestClient.post(`${baseURL}/${subSimpleClassName_strikeCase}/create`, data);
  100 +}
  101 +
  102 +/** 修改${subTable.classComment} */
  103 +export function update${subSimpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  104 + return requestClient.put(`${baseURL}/${subSimpleClassName_strikeCase}/update`, data);
  105 +}
  106 +
  107 +/** 删除${subTable.classComment} */
  108 +export function delete${subSimpleClassName}(id: number) {
  109 + return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete?id=${id}`);
  110 +}
  111 +
  112 +/** 获得${subTable.classComment} */
  113 +export function get${subSimpleClassName}(id: number) {
  114 + return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`);
  115 +}
  116 +#end
  117 +#end
  118 +
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm 0 → 100644
  1 +import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
  2 +import type { VbenFormSchema } from '#/adapter/form';
  3 +import type { OnActionClickFn } from '#/adapter/vxe-table';
  4 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  5 +
  6 +import { z } from '#/adapter/form';
  7 +#if(${table.templateType} == 2)## 树表需要导入这些
  8 +import { get${simpleClassName}List } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  9 +import { handleTree } from '#/utils/tree';
  10 +#end
  11 +import { DICT_TYPE, getDictOptions } from '#/utils/dict';
  12 +import { CommonStatusEnum } from '#/utils/constants';
  13 +import { useAccess } from '@vben/access';
  14 +
  15 +const { hasAccessByCodes } = useAccess();
  16 +
  17 +/** 新增/修改的表单 */
  18 +export function useFormSchema(): VbenFormSchema[] {
  19 + return [
  20 + {
  21 + fieldName: 'id',
  22 + component: 'Input',
  23 + dependencies: {
  24 + triggerFields: [''],
  25 + show: () => false,
  26 + },
  27 + },
  28 +#if(${table.templateType} == 2)## 树表特有字段:上级
  29 + {
  30 + fieldName: '${treeParentColumn.javaField}',
  31 + label: '上级${table.classComment}',
  32 + component: 'ApiTreeSelect',
  33 + componentProps: {
  34 + allowClear: true,
  35 + api: async () => {
  36 + const data = await get${simpleClassName}List({});
  37 + data.unshift({
  38 + id: 0,
  39 + ${treeNameColumn.javaField}: '顶级${table.classComment}',
  40 + });
  41 + return handleTree(data);
  42 + },
  43 + class: 'w-full',
  44 + labelField: '${treeNameColumn.javaField}',
  45 + valueField: 'id',
  46 + childrenField: 'children',
  47 + placeholder: '请选择上级${table.classComment}',
  48 + treeDefaultExpandAll: true,
  49 + },
  50 + rules: 'selectRequired',
  51 + },
  52 +#end
  53 +#foreach($column in $columns)
  54 +#if ($column.createOperation || $column.updateOperation)
  55 +#if (!$column.primaryKey && ($table.templateType != 2 || ($table.templateType == 2 && $column.id != $treeParentColumn.id)))## 树表中已经添加了父ID字段,这里排除
  56 + #set ($dictType = $column.dictType)
  57 + #set ($javaType = $column.javaType)
  58 + #set ($javaField = $column.javaField)
  59 + #set ($comment = $column.columnComment)
  60 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  61 + #set ($dictMethod = "number")
  62 + #elseif ($javaType == "String")
  63 + #set ($dictMethod = "string")
  64 + #elseif ($javaType == "Boolean")
  65 + #set ($dictMethod = "boolean")
  66 + #end
  67 + {
  68 + fieldName: '${javaField}',
  69 + label: '${comment}',
  70 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  71 + rules: 'required',
  72 + #end
  73 + #if ($column.htmlType == "input")
  74 + component: 'Input',
  75 + componentProps: {
  76 + placeholder: '请输入${comment}',
  77 + },
  78 + #elseif($column.htmlType == "imageUpload")## 图片上传
  79 + component: 'FileUpload',
  80 + componentProps: {
  81 + fileType: 'image',
  82 + maxCount: 1,
  83 + },
  84 + #elseif($column.htmlType == "fileUpload")## 文件上传
  85 + component: 'FileUpload',
  86 + componentProps: {
  87 + fileType: 'file',
  88 + maxCount: 1,
  89 + },
  90 + #elseif($column.htmlType == "editor")## 文本编辑器
  91 + component: 'Editor',
  92 + #elseif($column.htmlType == "select")## 下拉框
  93 + component: 'Select',
  94 + componentProps: {
  95 + #if ("" != $dictType)## 有数据字典
  96 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  97 + #else##没数据字典
  98 + options: [],
  99 + #end
  100 + placeholder: '请选择${comment}',
  101 + class: 'w-full',
  102 + },
  103 + #elseif($column.htmlType == "checkbox")## 多选框
  104 + component: 'Checkbox',
  105 + componentProps: {
  106 + #if ("" != $dictType)## 有数据字典
  107 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  108 + #else##没数据字典
  109 + options: [],
  110 + #end
  111 + },
  112 + #elseif($column.htmlType == "radio")## 单选框
  113 + component: 'RadioGroup',
  114 + componentProps: {
  115 + #if ("" != $dictType)## 有数据字典
  116 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  117 + #else##没数据字典
  118 + options: [],
  119 + #end
  120 + buttonStyle: 'solid',
  121 + optionType: 'button',
  122 + },
  123 + #elseif($column.htmlType == "datetime")## 时间框
  124 + component: 'DatePicker',
  125 + componentProps: {
  126 + showTime: true,
  127 + format: 'YYYY-MM-DD HH:mm:ss',
  128 + valueFormat: 'x',
  129 + },
  130 + #elseif($column.htmlType == "textarea")## 文本域
  131 + component: 'Textarea',
  132 + componentProps: {
  133 + placeholder: '请输入${comment}',
  134 + },
  135 + #elseif($column.htmlType == "inputNumber")## 数字输入框
  136 + component: 'InputNumber',
  137 + componentProps: {
  138 + min: 0,
  139 + class: 'w-full',
  140 + controlsPosition: 'right',
  141 + placeholder: '请输入${comment}',
  142 + },
  143 + #end
  144 + },
  145 +#end
  146 +#end
  147 +#end
  148 + ];
  149 +}
  150 +
  151 +/** 列表的搜索表单 */
  152 +export function useGridFormSchema(): VbenFormSchema[] {
  153 + return [
  154 +#foreach($column in $columns)
  155 +#if ($column.listOperation)
  156 + #set ($dictType = $column.dictType)
  157 + #set ($javaType = $column.javaType)
  158 + #set ($javaField = $column.javaField)
  159 + #set ($comment = $column.columnComment)
  160 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  161 + #set ($dictMethod = "number")
  162 + #elseif ($javaType == "String")
  163 + #set ($dictMethod = "string")
  164 + #elseif ($javaType == "Boolean")
  165 + #set ($dictMethod = "boolean")
  166 + #end
  167 + {
  168 + fieldName: '${javaField}',
  169 + label: '${comment}',
  170 + #if ($column.htmlType == "input")
  171 + component: 'Input',
  172 + componentProps: {
  173 + allowClear: true,
  174 + placeholder: '请输入${comment}',
  175 + },
  176 + #elseif ($column.htmlType == "select")
  177 + component: 'Select',
  178 + componentProps: {
  179 + allowClear: true,
  180 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  181 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  182 + #else## 未设置 dictType 数据字典的情况
  183 + options: [],
  184 + #end
  185 + placeholder: '请选择${comment}',
  186 + },
  187 + #elseif ($column.htmlType == "radio")
  188 + component: 'Select',
  189 + componentProps: {
  190 + allowClear: true,
  191 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  192 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  193 + #else## 未设置 dictType 数据字典的情况
  194 + options: [],
  195 + #end
  196 + },
  197 + #elseif($column.htmlType == "datetime")
  198 + component: 'RangePicker',
  199 + componentProps: {
  200 + allowClear: true,
  201 + },
  202 + #end
  203 + },
  204 +#end
  205 +#end
  206 + ];
  207 +}
  208 +
  209 +/** 列表的字段 */
  210 +export function useGridColumns(
  211 + onActionClick?: OnActionClickFn<${simpleClassName}Api.${simpleClassName}>,
  212 +): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] {
  213 + return [
  214 +#foreach($column in $columns)
  215 +#if ($column.listOperationResult)
  216 + #set ($dictType = $column.dictType)
  217 + #set ($javaField = $column.javaField)
  218 + #set ($comment = $column.columnComment)
  219 + {
  220 + field: '${javaField}',
  221 + title: '${comment}',
  222 + minWidth: 120,
  223 + #if ($column.javaType == "LocalDateTime")## 时间类型
  224 + formatter: 'formatDateTime',
  225 + #elseif("" != $dictType)## 数据字典
  226 + cellRender: {
  227 + name: 'CellDict',
  228 + props: { type: DICT_TYPE.$dictType.toUpperCase() },
  229 + },
  230 + #end
  231 + #if (${table.templateType} == 2 && $column.id == $treeNameColumn.id)## 树表特有:标记树节点列
  232 + treeNode: true,
  233 + #end
  234 + },
  235 +#end
  236 +#end
  237 + {
  238 + field: 'operation',
  239 + title: '操作',
  240 + minWidth: 200,
  241 + align: 'right',
  242 + fixed: 'right',
  243 + headerAlign: 'center',
  244 + showOverflow: false,
  245 + cellRender: {
  246 + attrs: {
  247 + nameField: '${columns[0].javaField}',
  248 + nameTitle: '${table.classComment}',
  249 + onClick: onActionClick,
  250 + },
  251 + name: 'CellOperation',
  252 + options: [
  253 +#if (${table.templateType} == 2)## 树表特有操作
  254 + {
  255 + code: 'add_child',
  256 + text: '新增下级',
  257 + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:create']),
  258 + },
  259 +#end
  260 + {
  261 + code: 'edit',
  262 + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:update']),
  263 + },
  264 + {
  265 + code: 'delete',
  266 + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']),
  267 +#if (${table.templateType} == 2)## 树表禁止删除带有子节点的数据
  268 + disabled: (row: ${simpleClassName}Api.${simpleClassName}) => {
  269 + return !!(row.children && row.children.length > 0);
  270 + },
  271 +#end
  272 + },
  273 + ],
  274 + },
  275 + },
  276 + ];
  277 +}
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm 0 → 100644
  1 +<script lang="ts" setup>
  2 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  3 +
  4 +import { useVbenModal } from '@vben/common-ui';
  5 +import { message } from 'ant-design-vue';
  6 +
  7 +import { computed, ref } from 'vue';
  8 +import { $t } from '#/locales';
  9 +import { useVbenForm } from '#/adapter/form';
  10 +import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  11 +
  12 +import { useFormSchema } from '../data';
  13 +
  14 +const emit = defineEmits(['success']);
  15 +const formData = ref<${simpleClassName}Api.${simpleClassName}>();
  16 +#if (${table.templateType} == 2)## 树表特有:父ID处理
  17 +// 新增下级时的父级ID
  18 +const parentId = ref<number>();
  19 +
  20 +const getTitle = computed(() => {
  21 + if (formData.value?.id) {
  22 + return $t('ui.actionTitle.edit', ['${table.classComment}']);
  23 + }
  24 + return parentId.value
  25 + ? $t('ui.actionTitle.create', ['下级${table.classComment}'])
  26 + : $t('ui.actionTitle.create', ['${table.classComment}']);
  27 +});
  28 +#else## 标准表标题
  29 +const getTitle = computed(() => {
  30 + return formData.value?.id
  31 + ? $t('ui.actionTitle.edit', ['${table.classComment}'])
  32 + : $t('ui.actionTitle.create', ['${table.classComment}']);
  33 +});
  34 +#end
  35 +
  36 +const [Form, formApi] = useVbenForm({
  37 + layout: 'horizontal',
  38 + schema: useFormSchema(),
  39 + showDefaultActions: false,
  40 + commonConfig: {
  41 + labelWidth: 120
  42 + }
  43 +});
  44 +
  45 +const [Modal, modalApi] = useVbenModal({
  46 + async onConfirm() {
  47 + const { valid } = await formApi.validate();
  48 + if (!valid) {
  49 + return;
  50 + }
  51 + modalApi.lock();
  52 + // 提交表单
  53 + const data = (await formApi.getValues()) as ${simpleClassName}Api.${simpleClassName};
  54 + try {
  55 + await (formData.value?.id ? update${simpleClassName}(data) : create${simpleClassName}(data));
  56 + // 关闭并提示
  57 + await modalApi.close();
  58 + emit('success');
  59 + message.success({
  60 + content: $t('ui.actionMessage.operationSuccess'),
  61 + key: 'action_process_msg',
  62 + });
  63 + } finally {
  64 + modalApi.lock(false);
  65 + }
  66 + },
  67 + async onOpenChange(isOpen: boolean) {
  68 + if (!isOpen) {
  69 + return;
  70 + }
  71 + // 加载数据
  72 +#if (${table.templateType} == 2)## 树表处理传入的父ID
  73 + let data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>();
  74 +#else## 标准表直接获取
  75 + const data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>();
  76 +#end
  77 + if (!data) {
  78 + return;
  79 + }
  80 +
  81 +#if (${table.templateType} == 2)## 树表特有:处理新增下级的情况
  82 + // 处理新增下级的情况
  83 + if (!data.id && data.${treeParentColumn.javaField}) {
  84 + parentId.value = data.${treeParentColumn.javaField};
  85 + formData.value = { ${treeParentColumn.javaField}: parentId.value } as ${simpleClassName}Api.${simpleClassName};
  86 + await formApi.setValues(formData.value);
  87 + return;
  88 + }
  89 +#end
  90 +
  91 + if (data.id) {
  92 + // 编辑
  93 + modalApi.lock();
  94 + try {
  95 +#if (${table.templateType} == 2)## 树表获取数据后重新赋值
  96 + data = await get${simpleClassName}(data.id);
  97 + formData.value = data;
  98 +#else## 标准表设置表单数据
  99 + formData.value = await get${simpleClassName}(data.id as number);
  100 +#end
  101 + await formApi.setValues(formData.value);
  102 + } finally {
  103 + modalApi.lock(false);
  104 + }
  105 + } else {
  106 + // 新增
  107 +#if (${table.templateType} == 2)## 树表特有:设置顶级ID
  108 + formData.value = { ${treeParentColumn.javaField}: 0 } as ${simpleClassName}Api.${simpleClassName};
  109 +#else## 标准表:设置空值
  110 + formData.value = data;
  111 +#end
  112 + await formApi.setValues(formData.value || {});
  113 + }
  114 + },
  115 +});
  116 +</script>
  117 +
  118 +<template>
  119 + <Modal :title="getTitle">
  120 + <Form class="mx-4" />
  121 + </Modal>
  122 +</template>
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm 0 → 100644
  1 +<script lang="ts" setup>
  2 +import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
  3 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  4 +
  5 +import { Page, useVbenModal } from '@vben/common-ui';
  6 +import { Button, message } from 'ant-design-vue';
  7 +import { Download, Plus } from '@vben/icons';
  8 +import Form from './modules/form.vue';
  9 +import { DocAlert } from '#/components/doc-alert';
  10 +
  11 +import { ref } from 'vue';
  12 +import { $t } from '#/locales';
  13 +import { useVbenVxeGrid } from '#/adapter/vxe-table';
  14 +#if (${table.templateType} == 2)## 树表接口
  15 +import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  16 +#else## 标准表接口
  17 +import { get${simpleClassName}Page, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  18 +#end
  19 +import { downloadByData } from '#/utils/download';
  20 +
  21 +import { useGridColumns, useGridFormSchema } from './data';
  22 +
  23 +const [FormModal, formModalApi] = useVbenModal({
  24 + connectedComponent: Form,
  25 + destroyOnClose: true,
  26 +});
  27 +
  28 +#if (${table.templateType} == 2)## 树表特有:控制表格展开收缩
  29 +/** 切换树形展开/收缩状态 */
  30 +const isExpanded = ref(true);
  31 +function toggleExpand() {
  32 + isExpanded.value = !isExpanded.value;
  33 + gridApi.grid.setAllTreeExpand(isExpanded.value);
  34 +}
  35 +#end
  36 +
  37 +/** 刷新表格 */
  38 +function onRefresh() {
  39 + gridApi.query();
  40 +}
  41 +
  42 +/** 导出表格 */
  43 +async function onExport() {
  44 + const data = await export${simpleClassName}(await gridApi.formApi.getValues());
  45 + downloadByData(data, '${table.classComment}.xls');
  46 +}
  47 +
  48 +/** 创建${table.classComment} */
  49 +function onCreate() {
  50 + formModalApi.setData(null).open();
  51 +}
  52 +
  53 +/** 编辑${table.classComment} */
  54 +function onEdit(row: ${simpleClassName}Api.${simpleClassName}) {
  55 + formModalApi.setData(row).open();
  56 +}
  57 +
  58 +#if (${table.templateType} == 2)## 树表特有:新增下级
  59 +/** 新增下级${table.classComment} */
  60 +function onAddChild(row: ${simpleClassName}Api.${simpleClassName}) {
  61 + formModalApi.setData({ ${treeParentColumn.javaField}: row.id }).open();
  62 +}
  63 +#end
  64 +
  65 +/** 删除${table.classComment} */
  66 +async function onDelete(row: ${simpleClassName}Api.${simpleClassName}) {
  67 + const hideLoading = message.loading({
  68 + content: $t('ui.actionMessage.deleting', [row.id]),
  69 + duration: 0,
  70 + key: 'action_process_msg',
  71 + });
  72 + try {
  73 + await delete${simpleClassName}(row.id as number);
  74 + message.success({
  75 + content: $t('ui.actionMessage.deleteSuccess', [row.id]),
  76 + key: 'action_process_msg',
  77 + });
  78 + onRefresh();
  79 + } catch {
  80 + hideLoading();
  81 + }
  82 +}
  83 +
  84 +/** 表格操作按钮的回调函数 */
  85 +function onActionClick({
  86 + code,
  87 + row,
  88 +}: OnActionClickParams<${simpleClassName}Api.${simpleClassName}>) {
  89 + switch (code) {
  90 + case 'edit': {
  91 + onEdit(row);
  92 + break;
  93 + }
  94 + case 'delete': {
  95 + onDelete(row);
  96 + break;
  97 + }
  98 +#if (${table.templateType} == 2)## 树表特有:新增下级
  99 + case 'add_child': {
  100 + onAddChild(row);
  101 + break;
  102 + }
  103 +#end
  104 + }
  105 +}
  106 +
  107 +const [Grid, gridApi] = useVbenVxeGrid({
  108 + formOptions: {
  109 + schema: useGridFormSchema(),
  110 + },
  111 + gridOptions: {
  112 + columns: useGridColumns(onActionClick),
  113 + height: 'auto',
  114 +#if (${table.templateType} == 2)## 树表设置
  115 + treeConfig: {
  116 + parentField: '${treeParentColumn.javaField}',
  117 + rowField: 'id',
  118 + transform: true,
  119 + expandAll: true,
  120 + reserve: true,
  121 + },
  122 + pagerConfig: {
  123 + enabled: false,
  124 + },
  125 +#else## 标准表设置
  126 + pagerConfig: {
  127 + enabled: true,
  128 + },
  129 +#end
  130 + proxyConfig: {
  131 + ajax: {
  132 +#if (${table.templateType} == 2)## 树表数据加载
  133 + query: async (_, formValues) => {
  134 + return await get${simpleClassName}List(formValues);
  135 + },
  136 +#else## 标准表数据加载
  137 + query: async ({ page }, formValues) => {
  138 + const { items, total } = await get${simpleClassName}Page({
  139 + pageNo: page.currentPage,
  140 + pageSize: page.pageSize,
  141 + ...formValues,
  142 + });
  143 + return { items, total };
  144 + },
  145 +#end
  146 + },
  147 + },
  148 + rowConfig: {
  149 + keyField: 'id',
  150 + isHover: true,
  151 + },
  152 + toolbarConfig: {
  153 + refresh: { code: 'query' },
  154 + search: true,
  155 + },
  156 + } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
  157 +});
  158 +</script>
  159 +
  160 +<template>
  161 + <Page auto-content-height>
  162 + <DocAlert title="${table.classComment}" url="https://doc.iocoder.cn/${table.moduleName}/" />
  163 +
  164 + <FormModal @success="onRefresh" />
  165 +
  166 + <Grid table-title="${table.classComment}列表">
  167 + <template #toolbar-tools>
  168 +#if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
  169 + <Button @click="toggleExpand" class="mr-2">
  170 + {{ isExpanded ? '收缩' : '展开' }}
  171 + </Button>
  172 +#end
  173 + <Button type="primary" @click="onCreate" v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:create']">
  174 + <Plus class="size-5" />
  175 + {{ $t('ui.actionTitle.create', ['${table.classComment}']) }}
  176 + </Button>
  177 + <Button type="primary" class="ml-2" @click="onExport" v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:export']">
  178 + <Download class="size-5" />
  179 + {{ $t('ui.actionTitle.export') }}
  180 + </Button>
  181 + </template>
  182 + </Grid>
  183 + </Page>
  184 +</template>