From 69486939d5b48aea0902de3ec1b9a79a6a301333 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 11 Apr 2025 16:47:11 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91INFRA:=20vben=20next=20=E5=8D=95=E8=A1=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/codegen/CodegenFrontTypeEnum.java | 1 + .../service/codegen/inner/CodegenEngine.java | 13 + .../ant_design_vue/index.vue.vm | 0 .../vue3_vben_next/schema/api/api.ts.vm | 115 +++++++++ .../vue3_vben_next/schema/views/data.ts.vm | 223 ++++++++++++++++++ .../vue3_vben_next/schema/views/form.vue.vm | 78 ++++++ .../vue3_vben_next/schema/views/index.vue.vm | 128 ++++++++++ 7 files changed, 558 insertions(+) create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/ant_design_vue/index.vue.vm create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java index 101781c48c..b3550ddd00 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java +++ b/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 { VUE2(10), // Vue2 Element UI 标准模版 VUE3(20), // Vue3 Element Plus 标准模版 VUE3_VBEN(30), // Vue3 VBEN 模版 + VUE3_VBEN_NEXT_SCHEMA(40), // Vue3 vben5 schema 模版 ; /** diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index 8f00682735..ec12bfb839 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -144,6 +144,15 @@ public class CodegenEngine { vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Modal.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN.getType(), vue3VbenTemplatePath("api/api.ts"), vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) + // Vue3 vben5 schema 模版 + .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/data.ts"), + vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts")) + .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/index.vue"), + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) + .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/form.vue"), + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("api/api.ts"), + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .build(); @Resource @@ -496,6 +505,10 @@ public class CodegenEngine { return "codegen/vue3_vben/" + path + ".vm"; } + private static String vue3VbenNextSchemaTemplatePath(String path) { + return "codegen/vue3_vben_next/schema/" + path + ".vm"; + } + private static boolean isSubTemplate(String path) { return path.contains("_sub"); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/ant_design_vue/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/ant_design_vue/index.vue.vm new file mode 100644 index 0000000000..e69de29bb2 diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm new file mode 100644 index 0000000000..e313b1c7d5 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm @@ -0,0 +1,115 @@ +import type { PageParam, PageResult } from '@vben/request'; + +import { requestClient } from '#/api/request'; +#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}") + +export namespace ${simpleClassName}Api { + /** ${table.classComment}信息 */ + export interface ${simpleClassName} { +#foreach ($column in $columns) +#if ($column.createOperation || $column.updateOperation) +#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment} +#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime") + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: Date; // ${column.columnComment} +#else + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment} +#end +#end +#end + } +} + +#if ( $table.templateType != 2 ) +/** 查询${table.classComment}分页 */ +export function get${simpleClassName}Page(params: PageParam) { + return requestClient.get>('${baseURL}/page', { params }); +} +#else +/** 查询${table.classComment}列表 */ +export function get${simpleClassName}List(params: any) { + return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>('${baseURL}/list', { params }); +} +#end + +/** 查询${table.classComment}详情 */ +export function get${simpleClassName}(id: number) { + return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/get?id=${id}`); +} + +/** 新增${table.classComment} */ +export function create${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) { + return requestClient.post('${baseURL}/create', data); +} + +/** 修改${table.classComment} */ +export function update${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) { + return requestClient.put('${baseURL}/update', data); +} + +/** 删除${table.classComment} */ +export function delete${simpleClassName}(id: number) { + return requestClient.delete(`${baseURL}/delete?id=${id}`); +} + +/** 导出${table.classComment} */ +export function export${simpleClassName}(params: any) { + return requestClient.download('${baseURL}/export-excel', params); +} + +## 特殊:主子表专属逻辑 +#foreach ($subTable in $subTables) +#set ($index = $foreach.count - 1) +#set ($subSimpleClassName = $subSimpleClassNames.get($index)) +#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段 +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index)) +#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index)) +#set ($subClassNameVar = $subClassNameVars.get($index)) + +// ==================== 子表($subTable.classComment) ==================== +## 情况一:MASTER_ERP 时,需要分查询页子表 +#if ( $table.templateType == 11 ) +/** 获得${subTable.classComment}分页 */ +export function get${subSimpleClassName}Page(params: PageParam) { + return requestClient.get>(`${baseURL}/${subSimpleClassName_strikeCase}/page`, { params }); +} +## 情况二:非 MASTER_ERP 时,需要列表查询子表 +#else + #if ( $subTable.subJoinMany ) +/** 获得${subTable.classComment}列表 */ +export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}: number) { + return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>(`${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`); +} + #else +/** 获得${subTable.classComment} */ +export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}: number) { + return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`); +} + #end +#end +## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作 +#if ( $table.templateType == 11 ) +/** 新增${subTable.classComment} */ +export function create${subSimpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) { + return requestClient.post(`${baseURL}/${subSimpleClassName_strikeCase}/create`, data); +} + +/** 修改${subTable.classComment} */ +export function update${subSimpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) { + return requestClient.put(`${baseURL}/${subSimpleClassName_strikeCase}/update`, data); +} + +/** 删除${subTable.classComment} */ +export function delete${subSimpleClassName}(id: number) { + return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete?id=${id}`); +} + +/** 获得${subTable.classComment} */ +export function get${subSimpleClassName}(id: number) { + return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`); +} +#end +#end + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm new file mode 100644 index 0000000000..99223df0f8 --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm @@ -0,0 +1,223 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; + +import { z } from '#/adapter/form'; +import { CommonStatusEnum } from '#/utils/constants'; +import { DICT_TYPE, getDictOptions } from '#/utils/dict'; +import { getRangePickerDefaultProps } from '#/utils/date'; +import { useAccess } from '@vben/access'; + +const { hasAccessByCodes } = useAccess(); + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'id', + component: 'Input', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, +#foreach($column in $columns) +#if ($column.createOperation || $column.updateOperation) +#if (!$column.primaryKey)## 忽略主键,不用在表单里 + #set ($dictType = $column.dictType) + #set ($javaType = $column.javaType) + #set ($javaField = $column.javaField) + #set ($comment = $column.columnComment) + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") + #set ($dictMethod = "number") + #elseif ($javaType == "String") + #set ($dictMethod = "string") + #elseif ($javaType == "Boolean") + #set ($dictMethod = "boolean") + #end + { + fieldName: '${javaField}', + label: '${comment}', + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键 + rules: 'required', + #end + #if ($column.htmlType == "input") + component: 'Input', + componentProps: { + placeholder: '请输入${comment}', + }, + #elseif($column.htmlType == "imageUpload")## 图片上传 + component: 'FileUpload', + componentProps: { + fileType: 'image', + maxCount: 1, + }, + #elseif($column.htmlType == "fileUpload")## 文件上传 + component: 'FileUpload', + componentProps: { + fileType: 'file', + maxCount: 1, + }, + #elseif($column.htmlType == "editor")## 文本编辑器 + component: 'Editor', + #elseif($column.htmlType == "select")## 下拉框 + component: 'Select', + componentProps: { + #if ("" != $dictType)## 有数据字典 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), + #else##没数据字典 + options: [], + #end + placeholder: '请选择${comment}', + }, + #elseif($column.htmlType == "checkbox")## 多选框 + component: 'Checkbox', + componentProps: { + #if ("" != $dictType)## 有数据字典 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), + #else##没数据字典 + options: [], + #end + }, + #elseif($column.htmlType == "radio")## 单选框 + component: 'RadioGroup', + componentProps: { + #if ("" != $dictType)## 有数据字典 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), + #else##没数据字典 + options: [], + #end + buttonStyle: 'solid', + optionType: 'button', + }, + #elseif($column.htmlType == "datetime")## 时间框 + component: 'DatePicker', + componentProps: { + showTime: true, + format: 'YYYY-MM-DD HH:mm:ss', + valueFormat: 'x', + }, + #elseif($column.htmlType == "textarea")## 文本域 + component: 'Textarea', + componentProps: { + placeholder: '请输入${comment}', + }, + #end + }, +#end +#end +#end + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ +#foreach($column in $columns) +#if ($column.listOperation) + #set ($dictType = $column.dictType) + #set ($javaType = $column.javaType) + #set ($javaField = $column.javaField) + #set ($comment = $column.columnComment) + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short") + #set ($dictMethod = "number") + #elseif ($javaType == "String") + #set ($dictMethod = "string") + #elseif ($javaType == "Boolean") + #set ($dictMethod = "boolean") + #end + { + fieldName: '${javaField}', + label: '${comment}', + #if ($column.htmlType == "input") + component: 'Input', + componentProps: { + allowClear: true, + placeholder: '请输入${comment}', + }, + #elseif ($column.htmlType == "select") + component: 'Select', + componentProps: { + allowClear: true, + #if ("" != $dictType)## 设置了 dictType 数据字典的情况 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), + #else## 未设置 dictType 数据字典的情况 + options: [], + #end + placeholder: '请选择${comment}', + }, + #elseif ($column.htmlType == "radio") + component: 'Select', + componentProps: { + allowClear: true, + #if ("" != $dictType)## 设置了 dictType 数据字典的情况 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'), + #else## 未设置 dictType 数据字典的情况 + options: [], + #end + }, + #elseif($column.htmlType == "datetime") + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + #end + }, +#end +#end + ]; +} + +/** 列表的字段 */ +export function useGridColumns( + onActionClick: OnActionClickFn, +): VxeTableGridOptions['columns'] { + return [ +#foreach($column in $columns) +#if ($column.listOperationResult) + #set ($dictType = $column.dictType) + #set ($javaField = $column.javaField) + #set ($comment = $column.columnComment) + { + field: '${javaField}', + title: '${comment}', + minWidth: 120, + #if ($column.javaType == "LocalDateTime")## 时间类型 + formatter: 'formatDateTime', + #elseif("" != $dictType)## 数据字典 + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.$dictType.toUpperCase() }, + }, + #end + }, +#end +#end + { + field: 'operation', + title: '操作', + minWidth: 180, + align: 'center', + fixed: 'right', + cellRender: { + attrs: { + nameField: '${columns[0].javaField}', + nameTitle: '${table.classComment}', + onClick: onActionClick, + }, + name: 'CellOperation', + options: [ + { + code: 'edit', + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:update']), + }, + { + code: 'delete', + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']), + } + ], + }, + }, + ]; +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm new file mode 100644 index 0000000000..1970b3707c --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm @@ -0,0 +1,78 @@ + + + diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm new file mode 100644 index 0000000000..62d0bd568a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm @@ -0,0 +1,128 @@ + + + From 015565cc9a577f6e2174f08d8a683f2574d41d53 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Fri, 11 Apr 2025 18:21:42 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91INFRA:=20vben=20next=20=E6=A0=91=E8=A1=A8?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/codegen/inner/CodegenEngine.java | 9 +++ .../vue3_vben_next/schema/api/api.ts.vm | 3 + .../vue3_vben_next/schema/views/data.ts.vm | 76 ++++++++++++++++--- .../vue3_vben_next/schema/views/form.vue.vm | 60 +++++++++++++-- .../vue3_vben_next/schema/views/index.vue.vm | 62 ++++++++++++++- 5 files changed, 187 insertions(+), 23 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index ec12bfb839..2380c6d89a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -153,6 +153,15 @@ public class CodegenEngine { vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("api/api.ts"), vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) + // 主子表模板配置 - Vue3 vben5 schema 模版 + //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/master_slave_data.ts"), + // vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts")) + //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/master_slave_index.vue"), + // vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) + //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/modules/master_slave_form.vue"), + // vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + //.put(CodegenFrontTypeEnum.VUE3_VBEN_NEXT_SCHEMA.getType(), vue3VbenNextSchemaTemplatePath("views/modules/sub_table.vue"), + // vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/sub_table.vue")) .build(); @Resource diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm index e313b1c7d5..b1a24af09c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/api/api.ts.vm @@ -16,6 +16,9 @@ export namespace ${simpleClassName}Api { ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment} #end #end +#end +#if ( $table.templateType == 2 ) + children?: ${simpleClassName}[]; #end } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm index 99223df0f8..2ff36e963c 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/data.ts.vm @@ -1,11 +1,15 @@ +import type { VxeTableGridOptions } from '@vben/plugins/vxe-table'; import type { VbenFormSchema } from '#/adapter/form'; -import type { OnActionClickFn, VxeTableGridOptions } from '#/adapter/vxe-table'; +import type { OnActionClickFn } from '#/adapter/vxe-table'; import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; import { z } from '#/adapter/form'; -import { CommonStatusEnum } from '#/utils/constants'; +#if(${table.templateType} == 2)## 树表需要导入这些 +import { get${simpleClassName}List } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; +import { handleTree } from '#/utils/tree'; +#end import { DICT_TYPE, getDictOptions } from '#/utils/dict'; -import { getRangePickerDefaultProps } from '#/utils/date'; +import { CommonStatusEnum } from '#/utils/constants'; import { useAccess } from '@vben/access'; const { hasAccessByCodes } = useAccess(); @@ -21,9 +25,34 @@ export function useFormSchema(): VbenFormSchema[] { show: () => false, }, }, +#if(${table.templateType} == 2)## 树表特有字段:上级 + { + fieldName: '${treeParentColumn.javaField}', + label: '上级${table.classComment}', + component: 'ApiTreeSelect', + componentProps: { + allowClear: true, + api: async () => { + const data = await get${simpleClassName}List({}); + data.unshift({ + id: 0, + ${treeNameColumn.javaField}: '顶级${table.classComment}', + }); + return handleTree(data); + }, + class: 'w-full', + labelField: '${treeNameColumn.javaField}', + valueField: 'id', + childrenField: 'children', + placeholder: '请选择上级${table.classComment}', + treeDefaultExpandAll: true, + }, + rules: 'selectRequired', + }, +#end #foreach($column in $columns) #if ($column.createOperation || $column.updateOperation) -#if (!$column.primaryKey)## 忽略主键,不用在表单里 +#if (!$column.primaryKey && ($table.templateType != 2 || ($table.templateType == 2 && $column.id != $treeParentColumn.id)))## 树表中已经添加了父ID字段,这里排除 #set ($dictType = $column.dictType) #set ($javaType = $column.javaType) #set ($javaField = $column.javaField) @@ -69,6 +98,7 @@ export function useFormSchema(): VbenFormSchema[] { options: [], #end placeholder: '请选择${comment}', + class: 'w-full', }, #elseif($column.htmlType == "checkbox")## 多选框 component: 'Checkbox', @@ -102,6 +132,14 @@ export function useFormSchema(): VbenFormSchema[] { componentProps: { placeholder: '请输入${comment}', }, + #elseif($column.htmlType == "inputNumber")## 数字输入框 + component: 'InputNumber', + componentProps: { + min: 0, + class: 'w-full', + controlsPosition: 'right', + placeholder: '请输入${comment}', + }, #end }, #end @@ -159,7 +197,6 @@ export function useGridFormSchema(): VbenFormSchema[] { #elseif($column.htmlType == "datetime") component: 'RangePicker', componentProps: { - ...getRangePickerDefaultProps(), allowClear: true, }, #end @@ -170,9 +207,9 @@ export function useGridFormSchema(): VbenFormSchema[] { } /** 列表的字段 */ -export function useGridColumns( - onActionClick: OnActionClickFn, -): VxeTableGridOptions['columns'] { +export function useGridColumns( + onActionClick?: OnActionClickFn<${simpleClassName}Api.${simpleClassName}>, +): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] { return [ #foreach($column in $columns) #if ($column.listOperationResult) @@ -190,6 +227,9 @@ export function useGridColumns( name: 'CellDict', props: { type: DICT_TYPE.$dictType.toUpperCase() }, }, + #end + #if (${table.templateType} == 2 && $column.id == $treeNameColumn.id)## 树表特有:标记树节点列 + treeNode: true, #end }, #end @@ -197,9 +237,11 @@ export function useGridColumns( { field: 'operation', title: '操作', - minWidth: 180, - align: 'center', + minWidth: 200, + align: 'right', fixed: 'right', + headerAlign: 'center', + showOverflow: false, cellRender: { attrs: { nameField: '${columns[0].javaField}', @@ -208,6 +250,13 @@ export function useGridColumns( }, name: 'CellOperation', options: [ +#if (${table.templateType} == 2)## 树表特有操作 + { + code: 'add_child', + text: '新增下级', + show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:create']), + }, +#end { code: 'edit', show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:update']), @@ -215,7 +264,12 @@ export function useGridColumns( { code: 'delete', show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']), - } +#if (${table.templateType} == 2)## 树表禁止删除带有子节点的数据 + disabled: (row: ${simpleClassName}Api.${simpleClassName}) => { + return !!(row.children && row.children.length > 0); + }, +#end + }, ], }, }, diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm index 1970b3707c..91d86e7e9a 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/form.vue.vm @@ -4,8 +4,8 @@ import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleCl import { useVbenModal } from '@vben/common-ui'; import { message } from 'ant-design-vue'; -import { $t } from '#/locales'; import { computed, ref } from 'vue'; +import { $t } from '#/locales'; import { useVbenForm } from '#/adapter/form'; import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; @@ -13,11 +13,25 @@ import { useFormSchema } from '../data'; const emit = defineEmits(['success']); const formData = ref<${simpleClassName}Api.${simpleClassName}>(); +#if (${table.templateType} == 2)## 树表特有:父ID处理 +// 新增下级时的父级ID +const parentId = ref(); + +const getTitle = computed(() => { + if (formData.value?.id) { + return $t('ui.actionTitle.edit', ['${table.classComment}']); + } + return parentId.value + ? $t('ui.actionTitle.create', ['下级${table.classComment}']) + : $t('ui.actionTitle.create', ['${table.classComment}']); +}); +#else## 标准表标题 const getTitle = computed(() => { return formData.value?.id ? $t('ui.actionTitle.edit', ['${table.classComment}']) : $t('ui.actionTitle.create', ['${table.classComment}']); }); +#end const [Form, formApi] = useVbenForm({ layout: 'horizontal', @@ -55,17 +69,47 @@ const [Modal, modalApi] = useVbenModal({ return; } // 加载数据 +#if (${table.templateType} == 2)## 树表处理传入的父ID + let data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>(); +#else## 标准表直接获取 const data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>(); - if (!data || !data.id) { +#end + if (!data) { return; } - modalApi.lock(); - try { - formData.value = await get${simpleClassName}(data.id as number); - // 设置到 values + +#if (${table.templateType} == 2)## 树表特有:处理新增下级的情况 + // 处理新增下级的情况 + if (!data.id && data.${treeParentColumn.javaField}) { + parentId.value = data.${treeParentColumn.javaField}; + formData.value = { ${treeParentColumn.javaField}: parentId.value } as ${simpleClassName}Api.${simpleClassName}; await formApi.setValues(formData.value); - } finally { - modalApi.lock(false); + return; + } +#end + + if (data.id) { + // 编辑 + modalApi.lock(); + try { +#if (${table.templateType} == 2)## 树表获取数据后重新赋值 + data = await get${simpleClassName}(data.id); + formData.value = data; +#else## 标准表设置表单数据 + formData.value = await get${simpleClassName}(data.id as number); +#end + await formApi.setValues(formData.value); + } finally { + modalApi.lock(false); + } + } else { + // 新增 +#if (${table.templateType} == 2)## 树表特有:设置顶级ID + formData.value = { ${treeParentColumn.javaField}: 0 } as ${simpleClassName}Api.${simpleClassName}; +#else## 标准表:设置空值 + formData.value = data; +#end + await formApi.setValues(formData.value || {}); } }, }); diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm index 62d0bd568a..e0ba37174b 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3_vben_next/schema/views/index.vue.vm @@ -8,9 +8,15 @@ import { Download, Plus } from '@vben/icons'; import Form from './modules/form.vue'; import { DocAlert } from '#/components/doc-alert'; +import { ref } from 'vue'; import { $t } from '#/locales'; import { useVbenVxeGrid } from '#/adapter/vxe-table'; +#if (${table.templateType} == 2)## 树表接口 +import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; +import { handleTree } from '#/utils/tree'; +#else## 标准表接口 import { get${simpleClassName}Page, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}'; +#end import { downloadByData } from '#/utils/download'; import { useGridColumns, useGridFormSchema } from './data'; @@ -20,6 +26,15 @@ const [FormModal, formModalApi] = useVbenModal({ destroyOnClose: true, }); +#if (${table.templateType} == 2)## 树表特有:控制表格展开收缩 +/** 切换树形展开/收缩状态 */ +const isExpanded = ref(true); +function toggleExpand() { + isExpanded.value = !isExpanded.value; + gridApi.grid.setAllTreeExpand(isExpanded.value); +} +#end + /** 刷新表格 */ function onRefresh() { gridApi.query(); @@ -41,17 +56,24 @@ function onEdit(row: ${simpleClassName}Api.${simpleClassName}) { formModalApi.setData(row).open(); } +#if (${table.templateType} == 2)## 树表特有:新增下级 +/** 新增下级${table.classComment} */ +function onAddChild(row: ${simpleClassName}Api.${simpleClassName}) { + formModalApi.setData({ ${treeParentColumn.javaField}: row.id }).open(); +} +#end + /** 删除${table.classComment} */ async function onDelete(row: ${simpleClassName}Api.${simpleClassName}) { const hideLoading = message.loading({ - content: $t('ui.actionMessage.deleting', [row.${columns[0].javaField}]), + content: $t('ui.actionMessage.deleting', [row.id]), duration: 0, key: 'action_process_msg', }); try { await delete${simpleClassName}(row.id as number); message.success({ - content: $t('ui.actionMessage.deleteSuccess', [row.${columns[0].javaField}]), + content: $t('ui.actionMessage.deleteSuccess', [row.id]), key: 'action_process_msg', }); onRefresh(); @@ -74,6 +96,12 @@ function onActionClick({ onDelete(row); break; } +#if (${table.templateType} == 2)## 树表特有:新增下级 + case 'add_child': { + onAddChild(row); + break; + } +#end } } @@ -84,20 +112,40 @@ const [Grid, gridApi] = useVbenVxeGrid({ gridOptions: { columns: useGridColumns(onActionClick), height: 'auto', - keepSource: true, +#if (${table.templateType} == 2)## 树表设置 + treeConfig: { + parentField: '${treeParentColumn.javaField}', + rowField: 'id', + transform: true, + expandAll: true, + reserve: true, + }, +#else## 标准表设置 + pagerConfig: { + enabled: true, + }, +#end proxyConfig: { ajax: { +#if (${table.templateType} == 2)## 树表数据加载 + query: async (_, formValues) => { + return await get${simpleClassName}List(formValues); + }, +#else## 标准表数据加载 query: async ({ page }, formValues) => { - return await get${simpleClassName}Page({ + const { items, total } = await get${simpleClassName}Page({ pageNo: page.currentPage, pageSize: page.pageSize, ...formValues, }); + return { items, total }; }, +#end }, }, rowConfig: { keyField: 'id', + isHover: true, }, toolbarConfig: { refresh: { code: 'query' }, @@ -112,8 +160,14 @@ const [Grid, gridApi] = useVbenVxeGrid({ +