Commit 68c803360a2f5596818502fb28ee5654389069b2

Authored by puhui999
1 parent bde8637e

feat: 新增 vben5-ele-schema 代码生成模板

Showing 21 changed files with 3764 additions and 5 deletions
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/enums/codegen/CodegenFrontTypeEnum.java
... ... @@ -21,6 +21,10 @@ public enum CodegenFrontTypeEnum {
21 21 VUE3_VBEN5_ANTD_SCHEMA(40), // Vue3 VBEN5 + ANTD + schema 模版
22 22  
23 23 VUE3_VBEN5_ANTD_GENERAL(41), // Vue3 VBEN5 + ANTD 标准模版
  24 +
  25 + VUE3_VBEN5_EP_SCHEMA(42), // Vue3 VBEN5 + EP + schema 模版
  26 +
  27 + VUE3_VBEN5_EP_GENERAL(43), // Vue3 VBEN5 + EP 标准模版
24 28 ;
25 29  
26 30 /**
... ...
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java
... ... @@ -182,6 +182,25 @@ public class CodegenEngine {
182 182 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue"))
183 183 .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑
184 184 vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue"))
  185 + // VUE3_VBEN5_EP_SCHEMA
  186 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/data.ts"),
  187 + vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts"))
  188 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/index.vue"),
  189 + vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue"))
  190 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/form.vue"),
  191 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue"))
  192 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("api/api.ts"),
  193 + vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts"))
  194 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑
  195 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
  196 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑
  197 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
  198 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑
  199 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue"))
  200 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑
  201 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue"))
  202 + .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑
  203 + vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue"))
185 204 .build();
186 205  
187 206 @Resource
... ... @@ -590,6 +609,14 @@ public class CodegenEngine {
590 609 return "codegen/vue3_vben5_antd/general/" + path + ".vm";
591 610 }
592 611  
  612 + private static String vue3Vben5EpSchemaTemplatePath(String path) {
  613 + return "codegen/vue3_vben5_ele/schema/" + path + ".vm";
  614 + }
  615 +
  616 + private static String vue3Vben5EpGeneralTemplatePath(String path) {
  617 + return "codegen/vue3_vben5_ele/general/" + path + ".vm";
  618 + }
  619 +
593 620 private static boolean isSubTemplate(String path) {
594 621 return path.contains("_sub");
595 622 }
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/data.ts.vm
... ... @@ -426,9 +426,7 @@ export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${sim
426 426 #else
427 427 #if ($subTable.subJoinMany) ## 一对多
428 428 /** 新增/修改列表的字段 */
429   - export function use${subSimpleClassName}GridEditColumns(
430   - onActionClick?: OnActionClickFn<${simpleClassName}Api.${subSimpleClassName}>,
431   - ): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  429 + export function use${subSimpleClassName}GridEditColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
432 430 return [
433 431 #foreach($column in $subColumns)
434 432 #if ($column.createOperation || $column.updateOperation)
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm
... ... @@ -101,7 +101,6 @@ async function handleDeleteBatch() {
101 101 key: 'action_key_msg',
102 102 });
103 103 try {
104   - // TODO @puhui999: 移除所有模板中的 List
105 104 await delete${simpleClassName}List(checkedIds.value);
106 105 message.success({
107 106 content: $t('ui.actionMessage.deleteSuccess'),
... ... @@ -192,7 +191,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
192 191 select${simpleClassName}.value = row;
193 192 },
194 193 #end
195   - #if($deleteBatchEnable)
  194 + #if(${table.templateType} != 2 && $deleteBatchEnable)
196 195 checkboxAll: handleRowCheckboxChange,
197 196 checkboxChange: handleRowCheckboxChange,
198 197 #end
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/api/api.ts.vm 0 → 100644
  1 +import type { PageParam, PageResult } from '@vben/request';
  2 +import type { Dayjs } from 'dayjs';
  3 +
  4 +import { requestClient } from '#/api/request';
  5 +#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
  6 +
  7 +export namespace ${simpleClassName}Api {
  8 + ## 特殊:主子表专属逻辑
  9 + #foreach ($subTable in $subTables)
  10 + #set ($index = $foreach.count - 1)
  11 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  12 + #set ($subColumns = $subColumnsList.get($index))##当前字段数组
  13 + /** ${subTable.classComment}信息 */
  14 + export interface ${subSimpleClassName} {
  15 + #foreach ($column in $subColumns)
  16 + #if ($column.createOperation || $column.updateOperation)
  17 + #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
  18 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment}
  19 + #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
  20 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: string | Dayjs; // ${column.columnComment}
  21 + #else
  22 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment}
  23 + #end
  24 + #end
  25 + #end
  26 + }
  27 +
  28 + #end
  29 + /** ${table.classComment}信息 */
  30 + export interface ${simpleClassName} {
  31 + #foreach ($column in $columns)
  32 + #if ($column.createOperation || $column.updateOperation)
  33 + #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
  34 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment}
  35 + #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
  36 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: string | Dayjs; // ${column.columnComment}
  37 + #else
  38 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment}
  39 + #end
  40 + #end
  41 + #end
  42 + #if ( $table.templateType == 2 )
  43 + children?: ${simpleClassName}[];
  44 + #end
  45 + ## 特殊:主子表专属逻辑
  46 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  47 + #foreach ($subTable in $subTables)
  48 + #set ($index = $foreach.count - 1)
  49 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  50 + #if ( $subTable.subJoinMany )
  51 + ${subSimpleClassName.toLowerCase()}s?: ${subSimpleClassName}[]
  52 + #else
  53 + ${subSimpleClassName.toLowerCase()}?: ${subSimpleClassName}
  54 + #end
  55 + #end
  56 + #end
  57 + }
  58 +}
  59 +
  60 +#if ( $table.templateType != 2 )
  61 +/** 查询${table.classComment}分页 */
  62 +export function get${simpleClassName}Page(params: PageParam) {
  63 + return requestClient.get<PageResult<${simpleClassName}Api.${simpleClassName}>>('${baseURL}/page', { params });
  64 +}
  65 +#else
  66 +/** 查询${table.classComment}列表 */
  67 +export function get${simpleClassName}List(params: any) {
  68 + return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>('${baseURL}/list', { params });
  69 +}
  70 +#end
  71 +
  72 +/** 查询${table.classComment}详情 */
  73 +export function get${simpleClassName}(id: number) {
  74 + return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/get?id=${id}`);
  75 +}
  76 +
  77 +/** 新增${table.classComment} */
  78 +export function create${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  79 + return requestClient.post('${baseURL}/create', data);
  80 +}
  81 +
  82 +/** 修改${table.classComment} */
  83 +export function update${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  84 + return requestClient.put('${baseURL}/update', data);
  85 +}
  86 +
  87 +/** 删除${table.classComment} */
  88 +export function delete${simpleClassName}(id: number) {
  89 + return requestClient.delete(`${baseURL}/delete?id=${id}`);
  90 +}
  91 +
  92 +#if ( $table.templateType != 2 && $deleteBatchEnable)
  93 +/** 批量删除${table.classComment} */
  94 +export function delete${simpleClassName}List(ids: number[]) {
  95 + return requestClient.delete(`${baseURL}/delete-list?ids=${ids.join(',')}`)
  96 +}
  97 +#end
  98 +
  99 +/** 导出${table.classComment} */
  100 +export function export${simpleClassName}(params: any) {
  101 + return requestClient.download('${baseURL}/export-excel', params);
  102 +}
  103 +
  104 +## 特殊:主子表专属逻辑
  105 +#foreach ($subTable in $subTables)
  106 + #set ($index = $foreach.count - 1)
  107 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  108 + #set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
  109 + #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
  110 + #set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  111 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  112 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  113 + #set ($subClassNameVar = $subClassNameVars.get($index))
  114 +
  115 +// ==================== 子表($subTable.classComment) ====================
  116 +
  117 +## 情况一:MASTER_ERP 时,需要分查询页子表
  118 +#if ( $table.templateType == 11 )
  119 +/** 获得${subTable.classComment}分页 */
  120 +export function get${subSimpleClassName}Page(params: PageParam) {
  121 + return requestClient.get<PageResult<${simpleClassName}Api.${subSimpleClassName}>>(`${baseURL}/${subSimpleClassName_strikeCase}/page`, { params });
  122 +}
  123 + ## 情况二:非 MASTER_ERP 时,需要列表查询子表
  124 +#else
  125 +#if ( $subTable.subJoinMany )
  126 +/** 获得${subTable.classComment}列表 */
  127 +export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
  128 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}[]>(`${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  129 +}
  130 +#else
  131 +/** 获得${subTable.classComment} */
  132 +export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
  133 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  134 +}
  135 +#end
  136 +#end
  137 +## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作
  138 +#if ( $table.templateType == 11 )
  139 +/** 新增${subTable.classComment} */
  140 +export function create${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
  141 + return requestClient.post(`${baseURL}/${subSimpleClassName_strikeCase}/create`, data);
  142 +}
  143 +
  144 +/** 修改${subTable.classComment} */
  145 +export function update${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
  146 + return requestClient.put(`${baseURL}/${subSimpleClassName_strikeCase}/update`, data);
  147 +}
  148 +
  149 +/** 删除${subTable.classComment} */
  150 +export function delete${subSimpleClassName}(id: number) {
  151 + return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete?id=${id}`);
  152 +}
  153 +
  154 +#if ($deleteBatchEnable)
  155 +/** 批量删除${subTable.classComment} */
  156 +export function delete${subSimpleClassName}List(ids: number[]) {
  157 + return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete-list?ids=${ids.join(',')}`)
  158 +}
  159 +#end
  160 +
  161 +/** 获得${subTable.classComment} */
  162 +export function get${subSimpleClassName}(id: number) {
  163 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`);
  164 +}
  165 +#end
  166 +#end
  167 +
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/form.vue.vm 0 → 100644
  1 +<script lang="ts" setup>
  2 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  3 +import type { Rule } from 'ant-design-vue/es/form';
  4 +
  5 +import { useVbenModal } from '@vben/common-ui';
  6 +import { Tinymce as RichTextarea } from '#/components/tinymce';
  7 +import { ImageUpload, FileUpload } from "#/components/upload";
  8 +import { message, Tabs, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker, TreeSelect } from 'ant-design-vue';
  9 +import { DICT_TYPE, getDictOptions } from '#/utils';
  10 +#if($table.templateType == 2)## 树表需要导入这些
  11 +import { get${simpleClassName}List } from '#/api/${table.moduleName}/${table.businessName}';
  12 +import { handleTree } from '@vben/utils'
  13 +#end
  14 +## 特殊:主子表专属逻辑
  15 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  16 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  17 + #set ($index = $foreach.count - 1)
  18 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  19 + import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
  20 + #end
  21 +#end
  22 +
  23 +import { computed, ref } from 'vue';
  24 +import { $t } from '#/locales';
  25 +import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  26 +
  27 +const emit = defineEmits(['success']);
  28 +
  29 +const formRef = ref();
  30 +const formData = ref<Partial<${simpleClassName}Api.${simpleClassName}>>({
  31 +#foreach ($column in $columns)
  32 + #if ($column.createOperation || $column.updateOperation)
  33 + #if ($column.htmlType == "checkbox")
  34 + $column.javaField: [],
  35 + #else
  36 + $column.javaField: undefined,
  37 + #end
  38 + #end
  39 +#end
  40 +});
  41 +const rules: Record<string, Rule[]> = {
  42 + #foreach ($column in $columns)
  43 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  44 + #set($comment=$column.columnComment)
  45 + $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
  46 + #end
  47 + #end
  48 +};
  49 +## 特殊:树表专属逻辑
  50 +#if ( $table.templateType == 2 )
  51 +const ${classNameVar}Tree = ref<any[]>([]) // 树形结构
  52 +#end
  53 +const getTitle = computed(() => {
  54 + return formData.value?.id
  55 + ? $t('ui.actionTitle.edit', ['${table.classComment}'])
  56 + : $t('ui.actionTitle.create', ['${table.classComment}']);
  57 +});
  58 +
  59 +## 特殊:主子表专属逻辑
  60 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  61 + #if ( $subTables && $subTables.size() > 0 )
  62 + /** 子表的表单 */
  63 + const subTabsName = ref('$subClassNameVars.get(0)')
  64 + #foreach ($subClassNameVar in $subClassNameVars)
  65 + #set ($index = $foreach.count - 1)
  66 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  67 + const ${subClassNameVar}FormRef = ref<InstanceType<typeof ${subSimpleClassName}Form>>()
  68 + #end
  69 + #end
  70 +#end
  71 +
  72 +/** 重置表单 */
  73 +const resetForm = () => {
  74 + formData.value = {
  75 + #foreach ($column in $columns)
  76 + #if ($column.createOperation || $column.updateOperation)
  77 + #if ($column.htmlType == "checkbox")
  78 + $column.javaField: [],
  79 + #else
  80 + $column.javaField: undefined,
  81 + #end
  82 + #end
  83 + #end
  84 + };
  85 + formRef.value?.resetFields();
  86 +}
  87 +
  88 +## 特殊:树表专属逻辑
  89 +#if ( $table.templateType == 2 )
  90 +/** 获得${table.classComment}树 */
  91 +const get${simpleClassName}Tree = async () => {
  92 + ${classNameVar}Tree.value = []
  93 + const data = await get${simpleClassName}List({});
  94 + data.unshift({
  95 + id: 0,
  96 + name: '顶级${table.classComment}',
  97 + });
  98 + ${classNameVar}Tree.value = handleTree(data);
  99 +}
  100 +#end
  101 +
  102 +const [Modal, modalApi] = useVbenModal({
  103 + async onConfirm() {
  104 + await formRef.value?.validate();
  105 + ## 特殊:主子表专属逻辑
  106 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  107 + #if ( $subTables && $subTables.size() > 0 )
  108 + // 校验子表单
  109 + #foreach ($subTable in $subTables)
  110 + #set ($index = $foreach.count - 1)
  111 + #set ($subClassNameVar = $subClassNameVars.get($index))
  112 + #if ($subTable.subJoinMany) ## 一对多
  113 + ## TODO 列表值校验?
  114 + #else
  115 + try {
  116 + await ${subClassNameVar}FormRef.value?.validate()
  117 + } catch (e) {
  118 + subTabsName.value = '${subClassNameVar}'
  119 + return
  120 + }
  121 + #end
  122 + #end
  123 + #end
  124 + #end
  125 + modalApi.lock();
  126 + // 提交表单
  127 + const data = formData.value as ${simpleClassName}Api.${simpleClassName};
  128 + ## 特殊:主子表专属逻辑
  129 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  130 + #if ( $subTables && $subTables.size() > 0 )
  131 + // 拼接子表的数据
  132 + #foreach ($subTable in $subTables)
  133 + #set ($index = $foreach.count - 1)
  134 + #set ($subClassNameVar = $subClassNameVars.get($index))
  135 + #if ($subTable.subJoinMany)
  136 + data.${subClassNameVar}s = ${subClassNameVar}FormRef.value?.getData();
  137 + #else
  138 + data.${subClassNameVar} = ${subClassNameVar}FormRef.value?.getValues();
  139 + #end
  140 + #end
  141 + #end
  142 + #end
  143 + try {
  144 + await (formData.value?.id ? update${simpleClassName}(data) : create${simpleClassName}(data));
  145 + // 关闭并提示
  146 + await modalApi.close();
  147 + emit('success');
  148 + message.success({
  149 + content: $t('ui.actionMessage.operationSuccess'),
  150 + key: 'action_process_msg',
  151 + });
  152 + } finally {
  153 + modalApi.unlock();
  154 + }
  155 + },
  156 + async onOpenChange(isOpen: boolean) {
  157 + if (!isOpen) {
  158 + resetForm()
  159 + return;
  160 + }
  161 + // 加载数据
  162 + let data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>();
  163 + if (!data) {
  164 + return;
  165 + }
  166 + if (data.id) {
  167 + modalApi.lock();
  168 + try {
  169 + data = await get${simpleClassName}(data.id);
  170 + } finally {
  171 + modalApi.unlock();
  172 + }
  173 + }
  174 + formData.value = data;
  175 +#if ( $table.templateType == 2 )
  176 + // 加载树数据
  177 + await get${simpleClassName}Tree()
  178 +#end
  179 + },
  180 +});
  181 +</script>
  182 +
  183 +<template>
  184 + <Modal :title="getTitle">
  185 + <Form
  186 + ref="formRef"
  187 + :model="formData"
  188 + :rules="rules"
  189 + :label-col="{ span: 5 }"
  190 + :wrapper-col="{ span: 18 }"
  191 + >
  192 + #foreach($column in $columns)
  193 + #if ($column.createOperation || $column.updateOperation)
  194 + #set ($dictType = $column.dictType)
  195 + #set ($javaField = $column.javaField)
  196 + #set ($javaType = $column.javaType)
  197 + #set ($comment = $column.columnComment)
  198 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  199 + #set ($dictMethod = "number")
  200 + #elseif ($javaType == "String")
  201 + #set ($dictMethod = "string")
  202 + #elseif ($javaType == "Boolean")
  203 + #set ($dictMethod = "boolean")
  204 + #end
  205 + #if ( $table.templateType == 2 && $column.id == $treeParentColumn.id )
  206 + <Form.Item label="${comment}" name="${javaField}">
  207 + <TreeSelect
  208 + v-model:value="formData.${javaField}"
  209 + :treeData="${classNameVar}Tree"
  210 + #if ($treeNameColumn.javaField == "name")
  211 + :fieldNames="{
  212 + label: 'name',
  213 + value: 'id',
  214 + children: 'children',
  215 + }"
  216 + #else
  217 + :fieldNames="{
  218 + label: '$treeNameColumn.javaField',
  219 + value: 'id',
  220 + children: 'children',
  221 + }"
  222 + #end
  223 + checkable
  224 + treeDefaultExpandAll
  225 + placeholder="请选择${comment}"
  226 + />
  227 + </Form.Item>
  228 + #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  229 + <Form.Item label="${comment}" name="${javaField}">
  230 + <Input v-model:value="formData.${javaField}" placeholder="请输入${comment}" />
  231 + </Form.Item>
  232 + #elseif($column.htmlType == "imageUpload")## 图片上传
  233 + <Form.Item label="${comment}" name="${javaField}">
  234 + <ImageUpload v-model:value="formData.${javaField}" />
  235 + </Form.Item>
  236 + #elseif($column.htmlType == "fileUpload")## 文件上传
  237 + <Form.Item label="${comment}" name="${javaField}">
  238 + <FileUpload v-model:value="formData.${javaField}" />
  239 + </Form.Item>
  240 + #elseif($column.htmlType == "editor")## 文本编辑器
  241 + <Form.Item label="${comment}" name="${javaField}">
  242 + <RichTextarea v-model="formData.${javaField}" height="500px" />
  243 + </Form.Item>
  244 + #elseif($column.htmlType == "select")## 下拉框
  245 + <Form.Item label="${comment}" name="${javaField}">
  246 + <Select v-model:value="formData.${javaField}" placeholder="请选择${comment}">
  247 + #if ("" != $dictType)## 有数据字典
  248 + <Select.Option
  249 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  250 + :key="dict.value"
  251 + :value="dict.value"
  252 + >
  253 + {{ dict.label }}
  254 + </Select.Option>
  255 + #else##没数据字典
  256 + <Select.Option label="请选择字典生成" value="" />
  257 + #end
  258 + </Select>
  259 + </Form.Item>
  260 + #elseif($column.htmlType == "checkbox")## 多选框
  261 + <Form.Item label="${comment}" name="${javaField}">
  262 + <CheckboxGroup v-model:value="formData.${javaField}">
  263 + #if ("" != $dictType)## 有数据字典
  264 + <Checkbox
  265 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  266 + :key="dict.value"
  267 + :value="dict.value"
  268 + >
  269 + {{ dict.label }}
  270 + </Checkbox>
  271 + #else##没数据字典
  272 + <Checkbox label="请选择字典生成" />
  273 + #end
  274 + </CheckboxGroup>
  275 + </Form.Item>
  276 + #elseif($column.htmlType == "radio")## 单选框
  277 + <Form.Item label="${comment}" name="${javaField}">
  278 + <RadioGroup v-model:value="formData.${javaField}">
  279 + #if ("" != $dictType)## 有数据字典
  280 + <Radio
  281 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  282 + :key="dict.value"
  283 + :value="dict.value"
  284 + >
  285 + {{ dict.label }}
  286 + </Radio>
  287 + #else##没数据字典
  288 + <Radio value="1">请选择字典生成</Radio>
  289 + #end
  290 + </RadioGroup>
  291 + </Form.Item>
  292 + #elseif($column.htmlType == "datetime")## 时间框
  293 + <Form.Item label="${comment}" name="${javaField}">
  294 + <DatePicker
  295 + v-model:value="formData.${javaField}"
  296 + valueFormat="x"
  297 + placeholder="选择${comment}"
  298 + />
  299 + </Form.Item>
  300 + #elseif($column.htmlType == "textarea")## 文本框
  301 + <Form.Item label="${comment}" name="${javaField}">
  302 + <Textarea v-model:value="formData.${javaField}" placeholder="请输入${comment}" />
  303 + </Form.Item>
  304 + #end
  305 + #end
  306 + #end
  307 + </Form>
  308 + ## 特殊:主子表专属逻辑
  309 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  310 + <!-- 子表的表单 -->
  311 + <Tabs v-model:active-key="subTabsName">
  312 + #foreach ($subTable in $subTables)
  313 + #set ($index = $foreach.count - 1)
  314 + #set ($subClassNameVar = $subClassNameVars.get($index))
  315 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  316 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  317 + <Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
  318 + <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData?.id" />
  319 + </Tabs.TabPane>
  320 + #end
  321 + </Tabs>
  322 + #end
  323 + </Modal>
  324 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/index.vue.vm 0 → 100644
  1 +<script lang="ts" setup>
  2 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  3 +import type { VxeTableInstance } from '#/adapter/vxe-table';
  4 +
  5 +import { Page, useVbenModal } from '@vben/common-ui';
  6 +import { cloneDeep, formatDateTime } from '@vben/utils';
  7 +import { Button, message,Tabs,Pagination,Form,RangePicker,DatePicker,Select,Input } from 'ant-design-vue';
  8 +import { DictTag } from '#/components/dict-tag';
  9 +import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
  10 +import ${simpleClassName}Form from './modules/form.vue';
  11 +import { Download, Plus, RefreshCw, Search, Trash2 } from '@vben/icons';
  12 +import { ContentWrap } from '#/components/content-wrap';
  13 +import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
  14 +import { TableToolbar } from '#/components/table-toolbar';
  15 +import { useTableToolbar } from '#/hooks';
  16 +
  17 +## 特殊:主子表专属逻辑
  18 +#if ( $table.templateType == 11 || $table.templateType == 12 )
  19 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  20 + #set ($index = $foreach.count - 1)
  21 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  22 + import ${subSimpleClassName}List from './modules/${subSimpleClassName_strikeCase}-list.vue'
  23 + #end
  24 +#end
  25 +
  26 +import { ref, h, reactive,onMounted,nextTick } from 'vue';
  27 +import { $t } from '#/locales';
  28 +#if (${table.templateType} == 2)## 树表接口
  29 +import { handleTree,isEmpty } from '@vben/utils'
  30 +import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  31 +#else## 标准表接口
  32 +import { isEmpty } from '@vben/utils';
  33 +import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  34 +#end
  35 +import { downloadFileFromBlobPart } from '@vben/utils';
  36 +
  37 +#if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况
  38 +/** 子表的列表 */
  39 +const subTabsName = ref('$subClassNameVars.get(0)')
  40 +#if ($table.templateType == 11)
  41 +const select${simpleClassName} = ref<${simpleClassName}Api.${simpleClassName}>();
  42 +async function onCellClick({ row }: { row: ${simpleClassName}Api.${simpleClassName} }) {
  43 + select${simpleClassName}.value = row
  44 +}
  45 +#end
  46 +#end
  47 +
  48 +const loading = ref(true) // 列表的加载中
  49 +#if ( $table.templateType == 2 )
  50 +const list = ref<any[]>([]) // 树列表的数据
  51 +#else
  52 +const list = ref<${simpleClassName}Api.${simpleClassName}[]>([]) // 列表的数据
  53 +#end
  54 +
  55 +## 特殊:树表专属逻辑(树不需要分页接口)
  56 +#if ( $table.templateType != 2 )
  57 +const total = ref(0) // 列表的总页数
  58 +#end
  59 +const queryParams = reactive({
  60 +## 特殊:树表专属逻辑(树不需要分页接口)
  61 +#if ( $table.templateType != 2 )
  62 + pageNo: 1,
  63 + pageSize: 10,
  64 +#end
  65 +#foreach ($column in $columns)
  66 + #if ($column.listOperation)
  67 + #if ($column.listOperationCondition != 'BETWEEN')
  68 + $column.javaField: undefined,
  69 + #end
  70 + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
  71 + $column.javaField: undefined,
  72 + #end
  73 + #end
  74 +#end
  75 +})
  76 +const queryFormRef = ref() // 搜索的表单
  77 +const exportLoading = ref(false) // 导出的加载中
  78 +
  79 +/** 查询列表 */
  80 +const getList = async () => {
  81 + loading.value = true
  82 + try {
  83 + const params = cloneDeep(queryParams) as any;
  84 + #foreach ($column in $columns)
  85 + #if ($column.listOperation)
  86 + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
  87 + if (params.${column.javaField} && Array.isArray(params.${column.javaField})) {
  88 + params.${column.javaField} = (params.${column.javaField} as string[]).join(',');
  89 + }
  90 + #end
  91 + #end
  92 + #end
  93 + ## 特殊:树表专属逻辑(树不需要分页接口)
  94 + #if ( $table.templateType == 2 )
  95 + list.value = await get${simpleClassName}List(params);
  96 + #else
  97 + const data = await get${simpleClassName}Page(params)
  98 + list.value = data.list
  99 + total.value = data.total
  100 + #end
  101 + } finally {
  102 + loading.value = false
  103 + }
  104 +}
  105 +
  106 +/** 搜索按钮操作 */
  107 +const handleQuery = () => {
  108 +#if ( $table.templateType != 2 )
  109 + queryParams.pageNo = 1
  110 +#end
  111 + getList()
  112 +}
  113 +
  114 +/** 重置按钮操作 */
  115 +const resetQuery = () => {
  116 + queryFormRef.value.resetFields()
  117 + handleQuery()
  118 +}
  119 +
  120 +const [FormModal, formModalApi] = useVbenModal({
  121 + connectedComponent: ${simpleClassName}Form,
  122 + destroyOnClose: true,
  123 +});
  124 +
  125 +/** 创建${table.classComment} */
  126 +function handleCreate() {
  127 + formModalApi.setData({}).open();
  128 +}
  129 +
  130 +/** 编辑${table.classComment} */
  131 +function handleEdit(row: ${simpleClassName}Api.${simpleClassName}) {
  132 + formModalApi.setData(row).open();
  133 +}
  134 +
  135 +#if (${table.templateType} == 2)## 树表特有:新增下级
  136 +/** 新增下级${table.classComment} */
  137 +function handleAppend(row: ${simpleClassName}Api.${simpleClassName}) {
  138 + formModalApi.setData({ ${treeParentColumn.javaField}: row.id }).open();
  139 +}
  140 +#end
  141 +
  142 +/** 删除${table.classComment} */
  143 +async function handleDelete(row: ${simpleClassName}Api.${simpleClassName}) {
  144 + const hideLoading = message.loading({
  145 + content: $t('ui.actionMessage.deleting', [row.id]),
  146 + duration: 0,
  147 + key: 'action_process_msg',
  148 + });
  149 + try {
  150 + await delete${simpleClassName}(row.id as number);
  151 + message.success({
  152 + content: $t('ui.actionMessage.deleteSuccess', [row.id]),
  153 + key: 'action_process_msg',
  154 + });
  155 + await getList();
  156 + } finally {
  157 + hideLoading();
  158 + }
  159 +}
  160 +
  161 +#if ($table.templateType != 2 && $deleteBatchEnable)
  162 +/** 批量删除${table.classComment} */
  163 +async function handleDeleteBatch() {
  164 + const hideLoading = message.loading({
  165 + content: $t('ui.actionMessage.deleting'),
  166 + duration: 0,
  167 + key: 'action_process_msg',
  168 + });
  169 + try {
  170 + await delete${simpleClassName}List(checkedIds.value);
  171 + message.success( $t('ui.actionMessage.deleteSuccess') );
  172 + await getList();
  173 + } finally {
  174 + hideLoading();
  175 + }
  176 +}
  177 +
  178 +const checkedIds = ref<number[]>([])
  179 +function handleRowCheckboxChange({
  180 + records,
  181 +}: {
  182 + records: ${simpleClassName}Api.${simpleClassName}[];
  183 +}) {
  184 + checkedIds.value = records.map((item) => item.id);
  185 +}
  186 +#end
  187 +
  188 +/** 导出表格 */
  189 +async function onExport() {
  190 +try {
  191 + exportLoading.value = true;
  192 + const data = await export${simpleClassName}(queryParams);
  193 + downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data });
  194 +}finally {
  195 + exportLoading.value = false;
  196 +}
  197 +}
  198 +
  199 +#if (${table.templateType} == 2)
  200 +/** 切换树形展开/收缩状态 */
  201 +const isExpanded = ref(true);
  202 +function toggleExpand() {
  203 + isExpanded.value = !isExpanded.value;
  204 + tableRef.value?.setAllTreeExpand(isExpanded.value);
  205 +}
  206 +#end
  207 +
  208 +/** 初始化 */
  209 +const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar();
  210 +onMounted(() => {
  211 + getList();
  212 +});
  213 +</script>
  214 +
  215 +<template>
  216 + <Page auto-content-height>
  217 + <FormModal @success="getList" />
  218 +
  219 + <ContentWrap v-if="!hiddenSearchBar">
  220 + <!-- 搜索工作栏 -->
  221 + <Form
  222 + :model="queryParams"
  223 + ref="queryFormRef"
  224 + layout="inline"
  225 + >
  226 + #foreach($column in $columns)
  227 + #if ($column.listOperation)
  228 + #set ($dictType = $column.dictType)
  229 + #set ($javaField = $column.javaField)
  230 + #set ($javaType = $column.javaType)
  231 + #set ($comment = $column.columnComment)
  232 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  233 + #set ($dictMethod = "number")
  234 + #elseif ($javaType == "String")
  235 + #set ($dictMethod = "string")
  236 + #elseif ($javaType == "Boolean")
  237 + #set ($dictMethod = "boolean")
  238 + #end
  239 + #if ($column.htmlType == "input")
  240 + <Form.Item label="${comment}" name="${javaField}">
  241 + <Input
  242 + v-model:value="queryParams.${javaField}"
  243 + placeholder="请输入${comment}"
  244 + allowClear
  245 + @pressEnter="handleQuery"
  246 + class="w-full"
  247 + />
  248 + </Form.Item>
  249 + #elseif ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox")
  250 + <Form.Item label="${comment}" name="${javaField}">
  251 + <Select
  252 + v-model:value="queryParams.${javaField}"
  253 + placeholder="请选择${comment}"
  254 + allowClear
  255 + class="w-full"
  256 + >
  257 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  258 + <Select.Option
  259 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  260 + :key="dict.value"
  261 + :value="dict.value"
  262 + >
  263 + {{ dict.label }}
  264 + </Select.Option>
  265 + #else## 未设置 dictType 数据字典的情况
  266 + <Select.Option label="请选择字典生成" value="" />
  267 + #end
  268 + </Select>
  269 + </Form.Item>
  270 + #elseif($column.htmlType == "datetime")
  271 + #if ($column.listOperationCondition != "BETWEEN")## 非范围
  272 + <Form.Item label="${comment}" name="${javaField}">
  273 + <DatePicker
  274 + v-model:value="queryParams.${javaField}"
  275 + valueFormat="YYYY-MM-DD"
  276 + placeholder="选择${comment}"
  277 + allowClear
  278 + class="w-full"
  279 + />
  280 + </Form.Item>
  281 + #else## 范围
  282 + <Form.Item label="${comment}" name="${javaField}">
  283 + <RangePicker
  284 + v-model:value="queryParams.${javaField}"
  285 + v-bind="getRangePickerDefaultProps()"
  286 + class="w-full"
  287 + />
  288 + </Form.Item>
  289 + #end
  290 + #end
  291 + #end
  292 + #end
  293 + <Form.Item>
  294 + <Button class="ml-2" @click="resetQuery"> 重置 </Button>
  295 + <Button class="ml-2" @click="handleQuery" type="primary">
  296 + 搜索
  297 + </Button>
  298 + </Form.Item>
  299 + </Form>
  300 + </ContentWrap>
  301 +
  302 + <!-- 列表 -->
  303 + <ContentWrap title="${table.classComment}">
  304 + <template #extra>
  305 + <TableToolbar
  306 + ref="tableToolbarRef"
  307 + v-model:hidden-search="hiddenSearchBar"
  308 + >
  309 + #if (${table.templateType} == 2)
  310 + <Button @click="toggleExpand" class="mr-2">
  311 + {{ isExpanded ? '收缩' : '展开' }}
  312 + </Button>
  313 + #end
  314 + <Button
  315 + class="ml-2"
  316 + :icon="h(Plus)"
  317 + type="primary"
  318 + @click="handleCreate"
  319 + v-access:code="['${permissionPrefix}:create']"
  320 + >
  321 + {{ $t('ui.actionTitle.create', ['${table.classComment}']) }}
  322 + </Button>
  323 + <Button
  324 + :icon="h(Download)"
  325 + type="primary"
  326 + class="ml-2"
  327 + :loading="exportLoading"
  328 + @click="onExport"
  329 + v-access:code="['${permissionPrefix}:export']"
  330 + >
  331 + {{ $t('ui.actionTitle.export') }}
  332 + </Button>
  333 + #if ($table.templateType != 2 && $deleteBatchEnable)
  334 + <Button
  335 + :icon="h(Trash2)"
  336 + type="primary"
  337 + danger
  338 + class="ml-2"
  339 + :disabled="isEmpty(checkedIds)"
  340 + @click="handleDeleteBatch"
  341 + v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:delete']"
  342 + >
  343 + 批量删除
  344 + </Button>
  345 + #end
  346 + </TableToolbar>
  347 + </template>
  348 + <vxe-table
  349 + ref="tableRef"
  350 + :data="list"
  351 + #if ( $table.templateType == 2 )
  352 + :tree-config="{
  353 + parentField: '${treeParentColumn.javaField}',
  354 + rowField: 'id',
  355 + transform: true,
  356 + expandAll: true,
  357 + reserve: true,
  358 + }"
  359 + #end
  360 +#if ($table.templateType == 11) ## erp情况
  361 + @cell-click="onCellClick"
  362 + :row-config="{
  363 + keyField: 'id',
  364 + isHover: true,
  365 + isCurrent: true,
  366 + }"
  367 +#end
  368 + show-overflow
  369 + :loading="loading"
  370 +#if ($table.templateType != 2 && $deleteBatchEnable)
  371 + @checkboxAll="handleRowCheckboxChange"
  372 + @checkboxChange="handleRowCheckboxChange"
  373 +#end
  374 + >
  375 +#if ($table.templateType != 2 && $deleteBatchEnable)
  376 + <vxe-column type="checkbox" width="40"></vxe-column>
  377 +#end
  378 + ## 特殊:主子表专属逻辑
  379 + #if ( $table.templateType == 12 && $subTables && $subTables.size() > 0 )
  380 + <!-- 子表的列表 -->
  381 + <vxe-column type="expand" width="60">
  382 + <template #content="{ row }">
  383 + <!-- 子表的表单 -->
  384 + <Tabs v-model:active-key="subTabsName" class="mx-8">
  385 + #foreach ($subTable in $subTables)
  386 + #set ($index = $foreach.count - 1)
  387 + #set ($subClassNameVar = $subClassNameVars.get($index))
  388 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  389 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  390 + <Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
  391 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="row?.id" />
  392 + </Tabs.TabPane>
  393 + #end
  394 + </Tabs>
  395 + </template>
  396 + </vxe-column>
  397 + #end
  398 + #foreach($column in $columns)
  399 + #if ($column.listOperationResult)
  400 + #set ($dictType=$column.dictType)
  401 + #set ($javaField = $column.javaField)
  402 + #set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
  403 + #set ($comment=$column.columnComment)
  404 + #if ($column.javaType == "LocalDateTime")## 时间类型
  405 + <vxe-column field="${javaField}" title="${comment}" align="center">
  406 + <template #default="{row}">
  407 + {{formatDateTime(row.${javaField})}}
  408 + </template>
  409 + </vxe-column>
  410 + #elseif($column.dictType && "" != $column.dictType)## 数据字典
  411 + <vxe-column field="${javaField}" title="${comment}" align="center">
  412 + <template #default="{row}">
  413 + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" />
  414 + </template>
  415 + </vxe-column>
  416 + #elseif ($table.templateType == 2 && $javaField == $treeNameColumn.javaField)
  417 + <vxe-column field="${javaField}" title="${comment}" align="center" tree-node/>
  418 + #else
  419 + <vxe-column field="${javaField}" title="${comment}" align="center" />
  420 + #end
  421 + #end
  422 + #end
  423 + <vxe-column field="operation" title="操作" align="center">
  424 + <template #default="{row}">
  425 +#if ( $table.templateType == 2 )
  426 + <Button
  427 + size="small"
  428 + type="link"
  429 + @click="handleAppend(row as any)"
  430 + v-access:code="['${permissionPrefix}:create']"
  431 + >
  432 + 新增下级
  433 + </Button>
  434 +#end
  435 + <Button
  436 + size="small"
  437 + type="link"
  438 + @click="handleEdit(row as any)"
  439 + v-access:code="['${permissionPrefix}:update']"
  440 + >
  441 + {{ $t('ui.actionTitle.edit') }}
  442 + </Button>
  443 + <Button
  444 + size="small"
  445 + type="link"
  446 + danger
  447 + class="ml-2"
  448 + #if ( $table.templateType == 2 )
  449 + :disabled="!isEmpty(row?.children)"
  450 + #end
  451 + @click="handleDelete(row as any)"
  452 + v-access:code="['${permissionPrefix}:delete']"
  453 + >
  454 + {{ $t('ui.actionTitle.delete') }}
  455 + </Button>
  456 + </template>
  457 + </vxe-column>
  458 + </vxe-table>
  459 +#if ( $table.templateType != 2 )
  460 + <!-- 分页 -->
  461 + <div class="mt-2 flex justify-end">
  462 + <Pagination
  463 + :total="total"
  464 + v-model:current="queryParams.pageNo"
  465 + v-model:page-size="queryParams.pageSize"
  466 + show-size-changer
  467 + @change="getList"
  468 + />
  469 + </div>
  470 +#end
  471 + </ContentWrap>
  472 +#if ($table.templateType == 11) ## erp情况
  473 + <ContentWrap>
  474 + <!-- 子表的表单 -->
  475 + <Tabs v-model:active-key="subTabsName">
  476 + #foreach ($subTable in $subTables)
  477 + #set ($index = $foreach.count - 1)
  478 + #set ($subClassNameVar = $subClassNameVars.get($index))
  479 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  480 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  481 + <Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
  482 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="select${simpleClassName}?.id" />
  483 + </Tabs.TabPane>
  484 + #end
  485 + </Tabs>
  486 + </ContentWrap>
  487 +#end
  488 + </Page>
  489 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/form_sub_erp.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +<script lang="ts" setup>
  6 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  7 + import type { Rule } from 'ant-design-vue/es/form';
  8 +
  9 + import { useVbenModal } from '@vben/common-ui';
  10 + import { Tinymce as RichTextarea } from '#/components/tinymce';
  11 + import { ImageUpload, FileUpload } from "#/components/upload";
  12 + import { message, Tabs, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker, TreeSelect } from 'ant-design-vue';
  13 + import { DICT_TYPE, getDictOptions } from '#/utils';
  14 +
  15 + import { computed, ref } from 'vue';
  16 + import { $t } from '#/locales';
  17 +
  18 + import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  19 +
  20 + const emit = defineEmits(['success']);
  21 + const getTitle = computed(() => {
  22 + return formData.value?.id
  23 + ? $t('ui.actionTitle.edit', ['${subTable.classComment}'])
  24 + : $t('ui.actionTitle.create', ['${subTable.classComment}']);
  25 + });
  26 +
  27 + const formRef = ref();
  28 + const formData = ref<Partial<${simpleClassName}Api.${subSimpleClassName}>>({
  29 + #foreach ($column in $subColumns)
  30 + #if ($column.createOperation || $column.updateOperation)
  31 + #if ($column.htmlType == "checkbox")
  32 + $column.javaField: [],
  33 + #else
  34 + $column.javaField: undefined,
  35 + #end
  36 + #end
  37 + #end
  38 + });
  39 + const rules: Record<string, Rule[]> = {
  40 + #foreach ($column in $subColumns)
  41 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  42 + #set($comment=$column.columnComment)
  43 + $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
  44 + #end
  45 + #end
  46 + };
  47 +
  48 + const [Modal, modalApi] = useVbenModal({
  49 + async onConfirm() {
  50 + await formRef.value?.validate();
  51 +
  52 + modalApi.lock();
  53 + // 提交表单
  54 + const data = formData.value as ${simpleClassName}Api.${subSimpleClassName};
  55 + try {
  56 + await (formData.value?.id ? update${subSimpleClassName}(data) : create${subSimpleClassName}(data));
  57 + // 关闭并提示
  58 + await modalApi.close();
  59 + emit('success');
  60 + message.success({
  61 + content: $t('ui.actionMessage.operationSuccess'),
  62 + key: 'action_process_msg',
  63 + });
  64 + } finally {
  65 + modalApi.unlock();
  66 + }
  67 + },
  68 + async onOpenChange(isOpen: boolean) {
  69 + if (!isOpen) {
  70 + resetForm()
  71 + return;
  72 + }
  73 +
  74 + // 加载数据
  75 + let data = modalApi.getData<${simpleClassName}Api.${subSimpleClassName}>();
  76 + if (!data) {
  77 + return;
  78 + }
  79 + if (data.id) {
  80 + modalApi.lock();
  81 + try {
  82 + data = await get${subSimpleClassName}(data.id);
  83 + } finally {
  84 + modalApi.unlock();
  85 + }
  86 + }
  87 + // 设置到 values
  88 + formData.value = data;
  89 + },
  90 + });
  91 +
  92 + /** 重置表单 */
  93 + const resetForm = () => {
  94 + formData.value = {
  95 + #foreach ($column in $subColumns)
  96 + #if ($column.createOperation || $column.updateOperation)
  97 + #if ($column.htmlType == "checkbox")
  98 + $column.javaField: [],
  99 + #else
  100 + $column.javaField: undefined,
  101 + #end
  102 + #end
  103 + #end
  104 + };
  105 + formRef.value?.resetFields();
  106 + }
  107 +</script>
  108 +
  109 +<template>
  110 + <Modal :title="getTitle">
  111 + <Form
  112 + ref="formRef"
  113 + :model="formData"
  114 + :rules="rules"
  115 + :label-col="{ span: 5 }"
  116 + :wrapper-col="{ span: 18 }"
  117 + >
  118 + #foreach($column in $subColumns)
  119 + #if ($column.createOperation || $column.updateOperation)
  120 + #set ($dictType = $column.dictType)
  121 + #set ($javaField = $column.javaField)
  122 + #set ($javaType = $column.javaType)
  123 + #set ($comment = $column.columnComment)
  124 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  125 + #set ($dictMethod = "number")
  126 + #elseif ($javaType == "String")
  127 + #set ($dictMethod = "string")
  128 + #elseif ($javaType == "Boolean")
  129 + #set ($dictMethod = "boolean")
  130 + #end
  131 + #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  132 + <Form.Item label="${comment}" name="${javaField}">
  133 + <Input v-model:value="formData.${javaField}" placeholder="请输入${comment}" />
  134 + </Form.Item>
  135 + #elseif($column.htmlType == "imageUpload")## 图片上传
  136 + <Form.Item label="${comment}" name="${javaField}">
  137 + <ImageUpload v-model:value="formData.${javaField}" />
  138 + </Form.Item>
  139 + #elseif($column.htmlType == "fileUpload")## 文件上传
  140 + <Form.Item label="${comment}" name="${javaField}">
  141 + <FileUpload v-model:value="formData.${javaField}" />
  142 + </Form.Item>
  143 + #elseif($column.htmlType == "editor")## 文本编辑器
  144 + <Form.Item label="${comment}" name="${javaField}">
  145 + <RichTextarea v-model="formData.${javaField}" height="500px" />
  146 + </Form.Item>
  147 + #elseif($column.htmlType == "select")## 下拉框
  148 + <Form.Item label="${comment}" name="${javaField}">
  149 + <Select v-model:value="formData.${javaField}" placeholder="请选择${comment}">
  150 + #if ("" != $dictType)## 有数据字典
  151 + <Select.Option
  152 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  153 + :key="dict.value"
  154 + :value="dict.value"
  155 + >
  156 + {{ dict.label }}
  157 + </Select.Option>
  158 + #else##没数据字典
  159 + <Select.Option label="请选择字典生成" value="" />
  160 + #end
  161 + </Select>
  162 + </Form.Item>
  163 + #elseif($column.htmlType == "checkbox")## 多选框
  164 + <Form.Item label="${comment}" name="${javaField}">
  165 + <CheckboxGroup v-model:value="formData.${javaField}">
  166 + #if ("" != $dictType)## 有数据字典
  167 + <Checkbox
  168 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  169 + :key="dict.value"
  170 + :value="dict.value"
  171 + >
  172 + {{ dict.label }}
  173 + </Checkbox>
  174 + #else##没数据字典
  175 + <Checkbox label="请选择字典生成" />
  176 + #end
  177 + </CheckboxGroup>
  178 + </Form.Item>
  179 + #elseif($column.htmlType == "radio")## 单选框
  180 + <Form.Item label="${comment}" name="${javaField}">
  181 + <RadioGroup v-model:value="formData.${javaField}">
  182 + #if ("" != $dictType)## 有数据字典
  183 + <Radio
  184 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  185 + :key="dict.value"
  186 + :value="dict.value"
  187 + >
  188 + {{ dict.label }}
  189 + </Radio>
  190 + #else##没数据字典
  191 + <Radio value="1">请选择字典生成</Radio>
  192 + #end
  193 + </RadioGroup>
  194 + </Form.Item>
  195 + #elseif($column.htmlType == "datetime")## 时间框
  196 + <Form.Item label="${comment}" name="${javaField}">
  197 + <DatePicker
  198 + v-model:value="formData.${javaField}"
  199 + valueFormat="x"
  200 + placeholder="选择${comment}"
  201 + />
  202 + </Form.Item>
  203 + #elseif($column.htmlType == "textarea")## 文本框
  204 + <Form.Item label="${comment}" name="${javaField}">
  205 + <Textarea v-model:value="formData.${javaField}" placeholder="请输入${comment}" />
  206 + </Form.Item>
  207 + #end
  208 + #end
  209 + #end
  210 + </Form>
  211 + </Modal>
  212 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/form_sub_inner.vue.vm 0 → 100644
  1 +## 主表的 normal 和 inner 使用相同的 form 表单
  2 +#parse("codegen/vue3_vben5_antd/general/views/modules/form_sub_normal.vue.vm")
0 3 \ No newline at end of file
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/form_sub_normal.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($subClassNameVar = $subClassNameVars.get($subIndex))
  6 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  7 +<script lang="ts" setup>
  8 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  9 +
  10 + import { message, Tabs, Form, Input, Textarea,Button, Select, RadioGroup, Radio, CheckboxGroup, Checkbox, DatePicker } from 'ant-design-vue';
  11 + import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
  12 + import { $t } from '#/locales';
  13 + import { DICT_TYPE, getDictOptions } from '#/utils';
  14 +
  15 +#if ($subTable.subJoinMany) ## 一对多
  16 +import type { VxeTableInstance } from '#/adapter/vxe-table';
  17 +import { Plus } from "@vben/icons";
  18 +import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
  19 +import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  20 +#else
  21 +import type { Rule } from 'ant-design-vue/es/form';
  22 +import { Tinymce as RichTextarea } from '#/components/tinymce';
  23 +import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  24 +#end
  25 +
  26 +const props = defineProps<{
  27 + ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
  28 +}>()
  29 +
  30 +#if ($subTable.subJoinMany) ## 一对多
  31 +const list = ref<${simpleClassName}Api.${subSimpleClassName}[]>([]) // 列表的数据
  32 +const tableRef = ref<VxeTableInstance>();
  33 +/** 添加${subTable.classComment} */
  34 +const onAdd = async () => {
  35 + await tableRef.value?.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
  36 +}
  37 +
  38 +/** 删除${subTable.classComment} */
  39 +const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  40 + await tableRef.value?.remove(row);
  41 +}
  42 +
  43 +/** 提供获取表格数据的方法供父组件调用 */
  44 +defineExpose({
  45 + getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
  46 + const data = list.value as ${simpleClassName}Api.${subSimpleClassName}[];
  47 + const removeRecords = tableRef.value?.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  48 + const insertRecords = tableRef.value?.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  49 + return data
  50 + .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
  51 + ?.concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
  52 + },
  53 +});
  54 +
  55 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  56 +watch(
  57 + () => props.${subJoinColumn.javaField},
  58 + async (val) => {
  59 + if (!val) {
  60 + return;
  61 + }
  62 + list.value = await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
  63 + },
  64 + { immediate: true },
  65 +);
  66 +#else
  67 +const formRef = ref();
  68 +const formData = ref<Partial<${simpleClassName}Api.${subSimpleClassName}>>({
  69 + #foreach ($column in $subColumns)
  70 + #if ($column.createOperation || $column.updateOperation)
  71 + #if ($column.htmlType == "checkbox")
  72 + $column.javaField: [],
  73 + #else
  74 + $column.javaField: undefined,
  75 + #end
  76 + #end
  77 + #end
  78 +});
  79 +const rules: Record<string, Rule[]> = {
  80 + #foreach ($column in $subColumns)
  81 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  82 + #set($comment=$column.columnComment)
  83 + $column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
  84 + #end
  85 + #end
  86 +};
  87 +/** 暴露出表单校验方法和表单值获取方法 */
  88 +defineExpose({
  89 + validate: async () => await formRef.value?.validate(),
  90 + getValues: ()=> formData.value,
  91 +});
  92 +
  93 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  94 +watch(
  95 + () => props.${subJoinColumn.javaField},
  96 + async (val) => {
  97 + if (!val) {
  98 + return;
  99 + }
  100 + await nextTick();
  101 + formData.value = await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
  102 + },
  103 + { immediate: true },
  104 +);
  105 +#end
  106 +</script>
  107 +
  108 +<template>
  109 +#if ($subTable.subJoinMany) ## 一对多
  110 + <vxe-table ref="tableRef" :data="list" show-overflow class="mx-4">
  111 + #foreach($column in $subColumns)
  112 + #if ($column.createOperation || $column.updateOperation)
  113 + #set ($comment = $column.columnComment)
  114 + #set ($javaField = $column.javaField)
  115 + #set ($javaType = $column.javaType)
  116 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  117 + #set ($dictMethod = "number")
  118 + #elseif ($javaType == "String")
  119 + #set ($dictMethod = "string")
  120 + #elseif ($javaType == "Boolean")
  121 + #set ($dictMethod = "boolean")
  122 + #end
  123 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  124 + #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  125 + <vxe-column field="${javaField}" title="${comment}" align="center">
  126 + <template #default="{row}">
  127 + <Input v-model:value="row.${javaField}" />
  128 + </template>
  129 + </vxe-column>
  130 + #elseif($column.htmlType == "imageUpload")## 图片上传
  131 + <vxe-column field="${javaField}" title="${comment}" align="center">
  132 + <template #default="{row}">
  133 + <ImageUpload v-model:value="row.${javaField}" />
  134 + </template>
  135 + </vxe-column>
  136 + #elseif($column.htmlType == "fileUpload")## 文件上传
  137 + <vxe-column field="${javaField}" title="${comment}" align="center">
  138 + <template #default="{row}">
  139 + <FileUpload v-model:value="row.${javaField}" />
  140 + </template>
  141 + </vxe-column>
  142 + #elseif($column.htmlType == "select")## 下拉框
  143 + <vxe-column field="${javaField}" title="${comment}" align="center">
  144 + <template #default="{row}">
  145 + <Select v-model:value="row.${javaField}" placeholder="请选择${comment}">
  146 + #if ("" != $dictType)## 有数据字典
  147 + <Select.Option
  148 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  149 + :key="dict.value"
  150 + :value="dict.value"
  151 + >
  152 + {{ dict.label }}
  153 + </Select.Option>
  154 + #else##没数据字典
  155 + <Select.Option label="请选择字典生成" value="" />
  156 + #end
  157 + </Select>
  158 + </template>
  159 + </vxe-column>
  160 + #elseif($column.htmlType == "checkbox")## 多选框
  161 + <vxe-column field="${javaField}" title="${comment}" align="center">
  162 + <template #default="{row}">
  163 + <CheckboxGroup v-model:value="row.${javaField}">
  164 + #if ("" != $dictType)## 有数据字典
  165 + <Checkbox
  166 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  167 + :key="dict.value"
  168 + :value="dict.value"
  169 + >
  170 + {{ dict.label }}
  171 + </Checkbox>
  172 + #else##没数据字典
  173 + <Checkbox label="请选择字典生成" />
  174 + #end
  175 + </CheckboxGroup>
  176 + </template>
  177 + </vxe-column>
  178 + #elseif($column.htmlType == "radio")## 单选框
  179 + <vxe-column field="${javaField}" title="${comment}" align="center">
  180 + <template #default="{row}">
  181 + <RadioGroup v-model:value="row.${javaField}">
  182 + #if ("" != $dictType)## 有数据字典
  183 + <Radio
  184 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  185 + :key="dict.value"
  186 + :value="dict.value"
  187 + >
  188 + {{ dict.label }}
  189 + </Radio>
  190 + #else##没数据字典
  191 + <Radio value="1">请选择字典生成</Radio>
  192 + #end
  193 + </RadioGroup>
  194 + </template>
  195 + </vxe-column>
  196 + #elseif($column.htmlType == "datetime")## 时间框
  197 + <vxe-column field="${javaField}" title="${comment}" align="center">
  198 + <template #default="{row}">
  199 + <DatePicker
  200 + v-model:value="row.${javaField}"
  201 + :showTime="true"
  202 + format="YYYY-MM-DD HH:mm:ss"
  203 + valueFormat='x'
  204 + />
  205 + </template>
  206 + </vxe-column>
  207 + #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框
  208 + <vxe-column field="${javaField}" title="${comment}" align="center">
  209 + <template #default="{row}">
  210 + <Textarea v-model:value="row.${javaField}" />
  211 + </template>
  212 + </vxe-column>
  213 + #end
  214 + #end
  215 + #end
  216 + <vxe-column field="operation" title="操作" align="center">
  217 + <template #default="{row}">
  218 + <Button
  219 + size="small"
  220 + type="link"
  221 + danger
  222 + @click="onDelete(row as any)"
  223 + v-access:code="['${permissionPrefix}:delete']"
  224 + >
  225 + {{ $t('ui.actionTitle.delete') }}
  226 + </Button>
  227 + </template>
  228 + </vxe-column>
  229 + </vxe-table>
  230 + <div class="flex justify-center mt-4">
  231 + <Button :icon="h(Plus)" type="primary" ghost @click="onAdd" v-access:code="['${permissionPrefix}:create']">
  232 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  233 + </Button>
  234 + </div>
  235 +#else
  236 + <Form
  237 + ref="formRef"
  238 + class="mx-4"
  239 + :model="formData"
  240 + :rules="rules"
  241 + :label-col="{ span: 5 }"
  242 + :wrapper-col="{ span: 18 }"
  243 + >
  244 + #foreach($column in $subColumns)
  245 + #if ($column.createOperation || $column.updateOperation)
  246 + #set ($dictType = $column.dictType)
  247 + #set ($javaField = $column.javaField)
  248 + #set ($javaType = $column.javaType)
  249 + #set ($comment = $column.columnComment)
  250 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  251 + #set ($dictMethod = "number")
  252 + #elseif ($javaType == "String")
  253 + #set ($dictMethod = "string")
  254 + #elseif ($javaType == "Boolean")
  255 + #set ($dictMethod = "boolean")
  256 + #end
  257 + #if ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  258 + <Form.Item label="${comment}" name="${javaField}">
  259 + <Input v-model:value="formData.${javaField}" placeholder="请输入${comment}" />
  260 + </Form.Item>
  261 + #elseif($column.htmlType == "imageUpload")## 图片上传
  262 + <Form.Item label="${comment}" name="${javaField}">
  263 + <ImageUpload v-model:value="formData.${javaField}" />
  264 + </Form.Item>
  265 + #elseif($column.htmlType == "fileUpload")## 文件上传
  266 + <Form.Item label="${comment}" name="${javaField}">
  267 + <FileUpload v-model:value="formData.${javaField}" />
  268 + </Form.Item>
  269 + #elseif($column.htmlType == "editor")## 文本编辑器
  270 + <Form.Item label="${comment}" name="${javaField}">
  271 + <RichTextarea v-model="formData.${javaField}" height="500px" />
  272 + </Form.Item>
  273 + #elseif($column.htmlType == "select")## 下拉框
  274 + <Form.Item label="${comment}" name="${javaField}">
  275 + <Select v-model:value="formData.${javaField}" placeholder="请选择${comment}">
  276 + #if ("" != $dictType)## 有数据字典
  277 + <Select.Option
  278 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  279 + :key="dict.value"
  280 + :value="dict.value"
  281 + >
  282 + {{ dict.label }}
  283 + </Select.Option>
  284 + #else##没数据字典
  285 + <Select.Option label="请选择字典生成" value="" />
  286 + #end
  287 + </Select>
  288 + </Form.Item>
  289 + #elseif($column.htmlType == "checkbox")## 多选框
  290 + <Form.Item label="${comment}" name="${javaField}">
  291 + <CheckboxGroup v-model:value="formData.${javaField}">
  292 + #if ("" != $dictType)## 有数据字典
  293 + <Checkbox
  294 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  295 + :key="dict.value"
  296 + :value="dict.value"
  297 + >
  298 + {{ dict.label }}
  299 + </Checkbox>
  300 + #else##没数据字典
  301 + <Checkbox label="请选择字典生成" />
  302 + #end
  303 + </CheckboxGroup>
  304 + </Form.Item>
  305 + #elseif($column.htmlType == "radio")## 单选框
  306 + <Form.Item label="${comment}" name="${javaField}">
  307 + <RadioGroup v-model:value="formData.${javaField}">
  308 + #if ("" != $dictType)## 有数据字典
  309 + <Radio
  310 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  311 + :key="dict.value"
  312 + :value="dict.value"
  313 + >
  314 + {{ dict.label }}
  315 + </Radio>
  316 + #else##没数据字典
  317 + <Radio value="1">请选择字典生成</Radio>
  318 + #end
  319 + </RadioGroup>
  320 + </Form.Item>
  321 + #elseif($column.htmlType == "datetime")## 时间框
  322 + <Form.Item label="${comment}" name="${javaField}">
  323 + <DatePicker
  324 + v-model:value="formData.${javaField}"
  325 + valueFormat="x"
  326 + placeholder="选择${comment}"
  327 + />
  328 + </Form.Item>
  329 + #elseif($column.htmlType == "textarea")## 文本框
  330 + <Form.Item label="${comment}" name="${javaField}">
  331 + <Textarea v-model:value="formData.${javaField}" placeholder="请输入${comment}" />
  332 + </Form.Item>
  333 + #end
  334 + #end
  335 + #end
  336 + </Form>
  337 +#end
  338 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/list_sub_erp.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  6 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex))
  7 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  8 +<script lang="ts" setup>
  9 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  10 + import type { VxeTableInstance } from '#/adapter/vxe-table';
  11 +
  12 + import { DictTag } from '#/components/dict-tag';
  13 + import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
  14 + import { VxeColumn, VxeTable } from '#/adapter/vxe-table';
  15 + import { reactive,ref, h, nextTick,watch,onMounted } from 'vue';
  16 + import { cloneDeep, formatDateTime } from '@vben/utils';
  17 + import { ContentWrap } from '#/components/content-wrap';
  18 +
  19 +#if ($table.templateType == 11) ## erp
  20 + import { useVbenModal } from '@vben/common-ui';
  21 + import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
  22 + import { Tinymce as RichTextarea } from '#/components/tinymce';
  23 + import { ImageUpload, FileUpload } from "#/components/upload";
  24 + import { message,Button, Tabs,Pagination, Form, Input, Textarea, Select, RadioGroup, Radio, CheckboxGroup, Checkbox,RangePicker, DatePicker, TreeSelect } from 'ant-design-vue';
  25 + import { Plus, Trash2 } from '@vben/icons';
  26 + import { $t } from '#/locales';
  27 + import { TableToolbar } from '#/components/table-toolbar';
  28 + import { useTableToolbar } from '#/hooks';
  29 +#end
  30 +
  31 +#if ($table.templateType == 11) ## erp
  32 + import { delete${subSimpleClassName},#if ($deleteBatchEnable) delete${subSimpleClassName}List,#end get${subSimpleClassName}Page } from '#/api/${table.moduleName}/${table.businessName}';
  33 + import { isEmpty } from '@vben/utils';
  34 + #else
  35 + #if ($subTable.subJoinMany) ## 一对多
  36 + import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  37 + #else
  38 + import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
  39 + #end
  40 +#end
  41 +
  42 +const props = defineProps<{
  43 + ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
  44 +}>()
  45 +
  46 +#if ($table.templateType == 11) ## erp
  47 + const [FormModal, formModalApi] = useVbenModal({
  48 + connectedComponent: ${subSimpleClassName}Form,
  49 + destroyOnClose: true,
  50 + });
  51 +
  52 +/** 创建${subTable.classComment} */
  53 +function handleCreate() {
  54 + if (!props.${subJoinColumn.javaField}){
  55 + message.warning("请先选择一个${table.classComment}!")
  56 + return
  57 + }
  58 + formModalApi.setData({${subJoinColumn.javaField}: props.${subJoinColumn.javaField}}).open();
  59 +}
  60 +
  61 +/** 编辑${subTable.classComment} */
  62 +function handleEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
  63 + formModalApi.setData(row).open();
  64 +}
  65 +
  66 +/** 删除${subTable.classComment} */
  67 +async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
  68 + const hideLoading = message.loading({
  69 + content: $t('ui.actionMessage.deleting', [row.id]),
  70 + duration: 0,
  71 + key: 'action_process_msg',
  72 + });
  73 + try {
  74 + await delete${subSimpleClassName}(row.id as number);
  75 + message.success({
  76 + content: $t('ui.actionMessage.deleteSuccess', [row.id]),
  77 + key: 'action_process_msg',
  78 + });
  79 + await getList();
  80 + } finally {
  81 + hideLoading();
  82 + }
  83 +}
  84 +
  85 +#if ($deleteBatchEnable)
  86 +/** 批量删除${subTable.classComment} */
  87 +async function handleDeleteBatch() {
  88 + const hideLoading = message.loading({
  89 + content: $t('ui.actionMessage.deleting'),
  90 + duration: 0,
  91 + key: 'action_process_msg',
  92 + });
  93 + try {
  94 + await delete${subSimpleClassName}List(checkedIds.value);
  95 + message.success( $t('ui.actionMessage.deleteSuccess') );
  96 + await getList();
  97 + } finally {
  98 + hideLoading();
  99 + }
  100 +}
  101 +
  102 +const checkedIds = ref<number[]>([])
  103 +function handleRowCheckboxChange({
  104 + records,
  105 +}: {
  106 + records: ${simpleClassName}Api.${subSimpleClassName}[];
  107 +}) {
  108 + checkedIds.value = records.map((item) => item.id);
  109 +}
  110 +#end
  111 +#end
  112 +
  113 + const loading = ref(true) // 列表的加载中
  114 + const list = ref<${simpleClassName}Api.${subSimpleClassName}[]>([]) // 列表的数据
  115 +#if ($table.templateType == 11) ## erp
  116 + const total = ref(0) // 列表的总页数
  117 +#end
  118 +#if ($table.templateType == 11) ## erp
  119 + const queryFormRef = ref() // 搜索的表单
  120 + const queryParams = reactive({
  121 + pageNo: 1,
  122 + pageSize: 10,
  123 + #foreach ($column in $subColumns)
  124 + #if ($column.listOperation)
  125 + #if ($column.listOperationCondition != 'BETWEEN')
  126 + $column.javaField: undefined,
  127 + #end
  128 + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
  129 + $column.javaField: undefined,
  130 + #end
  131 + #end
  132 + #end
  133 + })
  134 +
  135 +/** 搜索按钮操作 */
  136 +const handleQuery = () => {
  137 + queryParams.pageNo = 1
  138 + getList()
  139 +}
  140 +
  141 +/** 重置按钮操作 */
  142 +const resetQuery = () => {
  143 + queryFormRef.value.resetFields()
  144 + handleQuery()
  145 +}
  146 +#end
  147 + /** 查询列表 */
  148 + const getList = async () => {
  149 + loading.value = true
  150 + try {
  151 + if (!props.${subJoinColumn.javaField}){
  152 + return []
  153 + }
  154 + ## 特殊:树表专属逻辑(树不需要分页接口)
  155 + #if ($table.templateType == 11) ## erp
  156 + const params = cloneDeep(queryParams) as any;
  157 + #foreach ($column in $columns)
  158 + #if ($column.listOperation)
  159 + #if ($column.htmlType == "datetime" || $column.listOperationCondition == "BETWEEN")
  160 + if (params.${column.javaField} && Array.isArray(params.${column.javaField})) {
  161 + params.${column.javaField} = (params.${column.javaField} as string[]).join(',');
  162 + }
  163 + #end
  164 + #end
  165 + #end
  166 + params.${subJoinColumn.javaField} = props.${subJoinColumn.javaField};
  167 + const data = await get${subSimpleClassName}Page(params)
  168 + list.value = data.list
  169 + total.value = data.total
  170 + #else
  171 + #if ($subTable.subJoinMany) ## 一对多
  172 + list.value = await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!);
  173 + #else
  174 + list.value = [await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)];
  175 + #end
  176 + #end
  177 + } finally {
  178 + loading.value = false
  179 + }
  180 + }
  181 +
  182 + /** 监听主表的关联字段的变化,加载对应的子表数据 */
  183 + watch(
  184 + () => props.${subJoinColumn.javaField},
  185 + async (val) => {
  186 + if (!val) {
  187 + return;
  188 + }
  189 + await nextTick();
  190 + await getList()
  191 + },
  192 + { immediate: true },
  193 + );
  194 +
  195 +#if ($table.templateType == 11) ## erp
  196 +/** 初始化 */
  197 +const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar();
  198 +onMounted(() => {
  199 + getList();
  200 +});
  201 +#end
  202 +</script>
  203 +
  204 +<template>
  205 + #if ($table.templateType == 11) ## erp
  206 + <FormModal @success="getList" />
  207 + <div class="h-[600px]">
  208 + <ContentWrap v-if="!hiddenSearchBar">
  209 + <!-- 搜索工作栏 -->
  210 + <Form
  211 + :model="queryParams"
  212 + ref="queryFormRef"
  213 + layout="inline"
  214 + >
  215 + #foreach($column in $subColumns)
  216 + #if ($column.listOperation)
  217 + #set ($dictType = $column.dictType)
  218 + #set ($javaField = $column.javaField)
  219 + #set ($javaType = $column.javaType)
  220 + #set ($comment = $column.columnComment)
  221 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  222 + #set ($dictMethod = "number")
  223 + #elseif ($javaType == "String")
  224 + #set ($dictMethod = "string")
  225 + #elseif ($javaType == "Boolean")
  226 + #set ($dictMethod = "boolean")
  227 + #end
  228 + #if ($column.htmlType == "input")
  229 + <Form.Item label="${comment}" name="${javaField}">
  230 + <Input
  231 + v-model:value="queryParams.${javaField}"
  232 + placeholder="请输入${comment}"
  233 + allowClear
  234 + @pressEnter="handleQuery"
  235 + class="w-full"
  236 + />
  237 + </Form.Item>
  238 + #elseif ($column.htmlType == "select" || $column.htmlType == "radio" || $column.htmlType == "checkbox")
  239 + <Form.Item label="${comment}" name="${javaField}">
  240 + <Select
  241 + v-model:value="queryParams.${javaField}"
  242 + placeholder="请选择${comment}"
  243 + allowClear
  244 + class="w-full"
  245 + >
  246 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  247 + <Select.Option
  248 + v-for="dict in getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod')"
  249 + :key="dict.value"
  250 + :value="dict.value"
  251 + >
  252 + {{ dict.label }}
  253 + </Select.Option>
  254 + #else## 未设置 dictType 数据字典的情况
  255 + <Select.Option label="请选择字典生成" value="" />
  256 + #end
  257 + </Select>
  258 + </Form.Item>
  259 + #elseif($column.htmlType == "datetime")
  260 + #if ($column.listOperationCondition != "BETWEEN")## 非范围
  261 + <Form.Item label="${comment}" name="${javaField}">
  262 + <DatePicker
  263 + v-model:value="queryParams.${javaField}"
  264 + valueFormat="YYYY-MM-DD"
  265 + placeholder="选择${comment}"
  266 + allowClear
  267 + class="w-full"
  268 + />
  269 + </Form.Item>
  270 + #else## 范围
  271 + <Form.Item label="${comment}" name="${javaField}">
  272 + <RangePicker
  273 + v-model:value="queryParams.${javaField}"
  274 + v-bind="getRangePickerDefaultProps()"
  275 + class="w-full"
  276 + />
  277 + </Form.Item>
  278 + #end
  279 + #end
  280 + #end
  281 + #end
  282 + <Form.Item>
  283 + <Button class="ml-2" @click="resetQuery"> 重置 </Button>
  284 + <Button class="ml-2" @click="handleQuery" type="primary">
  285 + 搜索
  286 + </Button>
  287 + </Form.Item>
  288 + </Form>
  289 + </ContentWrap>
  290 +
  291 + <!-- 列表 -->
  292 + <ContentWrap title="${table.classComment}">
  293 + <template #extra>
  294 + <TableToolbar
  295 + ref="tableToolbarRef"
  296 + v-model:hidden-search="hiddenSearchBar"
  297 + >
  298 + <Button
  299 + class="ml-2"
  300 + :icon="h(Plus)"
  301 + type="primary"
  302 + @click="handleCreate"
  303 + v-access:code="['${permissionPrefix}:create']"
  304 + >
  305 + {{ $t('ui.actionTitle.create', ['${table.classComment}']) }}
  306 + </Button>
  307 + #if ($deleteBatchEnable)
  308 + <Button
  309 + :icon="h(Trash2)"
  310 + type="primary"
  311 + danger
  312 + class="ml-2"
  313 + :disabled="isEmpty(checkedIds)"
  314 + @click="handleDeleteBatch"
  315 + v-access:code="['${table.moduleName}:${simpleClassName_strikeCase}:delete']"
  316 + >
  317 + 批量删除
  318 + </Button>
  319 + #end
  320 + </TableToolbar>
  321 + </template>
  322 + <vxe-table
  323 + ref="tableRef"
  324 + :data="list"
  325 + show-overflow
  326 + :loading="loading"
  327 + #if ($deleteBatchEnable)
  328 + @checkboxAll="handleRowCheckboxChange"
  329 + @checkboxChange="handleRowCheckboxChange"
  330 + #end
  331 + >
  332 + #if ($deleteBatchEnable)
  333 + <vxe-column type="checkbox" width="40"></vxe-column>
  334 + #end
  335 + #foreach($column in $subColumns)
  336 + #if ($column.listOperationResult)
  337 + #set ($dictType=$column.dictType)
  338 + #set ($javaField = $column.javaField)
  339 + #set ($comment=$column.columnComment)
  340 + #if ($column.javaType == "LocalDateTime")## 时间类型
  341 + <vxe-column field="${javaField}" title="${comment}" align="center">
  342 + <template #default="{row}">
  343 + {{formatDateTime(row.${javaField})}}
  344 + </template>
  345 + </vxe-column>
  346 + #elseif($column.dictType && "" != $column.dictType)## 数据字典
  347 + <vxe-column field="${javaField}" title="${comment}" align="center">
  348 + <template #default="{row}">
  349 + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" />
  350 + </template>
  351 + </vxe-column>
  352 + #elseif ($table.templateType == 2 && $javaField == $treeNameColumn.javaField)
  353 + <vxe-column field="${javaField}" title="${comment}" align="center" tree-node/>
  354 + #else
  355 + <vxe-column field="${javaField}" title="${comment}" align="center" />
  356 + #end
  357 + #end
  358 + #end
  359 + <vxe-column field="operation" title="操作" align="center">
  360 + <template #default="{row}">
  361 + <Button
  362 + size="small"
  363 + type="link"
  364 + @click="handleEdit(row as any)"
  365 + v-access:code="['${permissionPrefix}:update']"
  366 + >
  367 + {{ $t('ui.actionTitle.edit') }}
  368 + </Button>
  369 + <Button
  370 + size="small"
  371 + type="link"
  372 + danger
  373 + class="ml-2"
  374 + @click="handleDelete(row as any)"
  375 + v-access:code="['${permissionPrefix}:delete']"
  376 + >
  377 + {{ $t('ui.actionTitle.delete') }}
  378 + </Button>
  379 + </template>
  380 + </vxe-column>
  381 + </vxe-table>
  382 + <!-- 分页 -->
  383 + <div class="mt-2 flex justify-end">
  384 + <Pagination
  385 + :total="total"
  386 + v-model:current="queryParams.pageNo"
  387 + v-model:page-size="queryParams.pageSize"
  388 + show-size-changer
  389 + @change="getList"
  390 + />
  391 + </div>
  392 + </ContentWrap>
  393 + </div>
  394 + #else
  395 + <ContentWrap title="${subTable.classComment}列表">
  396 + <vxe-table
  397 + :data="list"
  398 + show-overflow
  399 + :loading="loading"
  400 + >
  401 + #foreach($column in $subColumns)
  402 + #if ($column.listOperationResult)
  403 + #set ($dictType=$column.dictType)
  404 + #set ($javaField = $column.javaField)
  405 + #set ($comment=$column.columnComment)
  406 + #if ($column.javaType == "LocalDateTime")## 时间类型
  407 + <vxe-column field="${javaField}" title="${comment}" align="center">
  408 + <template #default="{row}">
  409 + {{formatDateTime(row.${javaField})}}
  410 + </template>
  411 + </vxe-column>
  412 + #elseif($column.dictType && "" != $column.dictType)## 数据字典
  413 + <vxe-column field="${javaField}" title="${comment}" align="center">
  414 + <template #default="{row}">
  415 + <dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="row.${javaField}" />
  416 + </template>
  417 + </vxe-column>
  418 + #else
  419 + <vxe-column field="${javaField}" title="${comment}" align="center" />
  420 + #end
  421 + #end
  422 + #end
  423 + </vxe-table>
  424 + </ContentWrap>
  425 + #end
  426 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/general/views/modules/list_sub_inner.vue.vm 0 → 100644
  1 +## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
  2 +## 1)inner 使用 list 不分页,erp 使用 page 分页
  3 +## 2)erp 支持单个子表的新增、修改、删除,inner 不支持
  4 +#parse("codegen/vue3_vben5_antd/general/views/modules/list_sub_erp.vue.vm")
0 5 \ No newline at end of file
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/api/api.ts.vm 0 → 100644
  1 +import type { PageParam, PageResult } from '@vben/request';
  2 +import type { Dayjs } from 'dayjs';
  3 +
  4 +import { requestClient } from '#/api/request';
  5 +#set ($baseURL = "/${table.moduleName}/${simpleClassName_strikeCase}")
  6 +
  7 +export namespace ${simpleClassName}Api {
  8 +## 特殊:主子表专属逻辑
  9 +#foreach ($subTable in $subTables)
  10 + #set ($index = $foreach.count - 1)
  11 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  12 + #set ($subColumns = $subColumnsList.get($index))##当前字段数组
  13 + /** ${subTable.classComment}信息 */
  14 + export interface ${subSimpleClassName} {
  15 + #foreach ($column in $subColumns)
  16 + #if ($column.createOperation || $column.updateOperation)
  17 + #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
  18 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment}
  19 + #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
  20 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: string | Dayjs; // ${column.columnComment}
  21 + #else
  22 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment}
  23 + #end
  24 + #end
  25 + #end
  26 + }
  27 +
  28 +#end
  29 + /** ${table.classComment}信息 */
  30 + export interface ${simpleClassName} {
  31 +#foreach ($column in $columns)
  32 +#if ($column.createOperation || $column.updateOperation)
  33 +#if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal")
  34 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: number; // ${column.columnComment}
  35 +#elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime")
  36 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: string | Dayjs; // ${column.columnComment}
  37 +#else
  38 + ${column.javaField}#if($column.updateOperation && !$column.primaryKey && !$column.nullable)?#end: ${column.javaType.toLowerCase()}; // ${column.columnComment}
  39 +#end
  40 +#end
  41 +#end
  42 +#if ( $table.templateType == 2 )
  43 + children?: ${simpleClassName}[];
  44 +#end
  45 +## 特殊:主子表专属逻辑
  46 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  47 + #foreach ($subTable in $subTables)
  48 + #set ($index = $foreach.count - 1)
  49 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  50 + #if ( $subTable.subJoinMany )
  51 + ${subSimpleClassName.toLowerCase()}s?: ${subSimpleClassName}[]
  52 + #else
  53 + ${subSimpleClassName.toLowerCase()}?: ${subSimpleClassName}
  54 + #end
  55 + #end
  56 +#end
  57 + }
  58 +}
  59 +
  60 +#if ( $table.templateType != 2 )
  61 +/** 查询${table.classComment}分页 */
  62 +export function get${simpleClassName}Page(params: PageParam) {
  63 + return requestClient.get<PageResult<${simpleClassName}Api.${simpleClassName}>>('${baseURL}/page', { params });
  64 +}
  65 +#else
  66 +/** 查询${table.classComment}列表 */
  67 +export function get${simpleClassName}List(params: any) {
  68 + return requestClient.get<${simpleClassName}Api.${simpleClassName}[]>('${baseURL}/list', { params });
  69 +}
  70 +#end
  71 +
  72 +/** 查询${table.classComment}详情 */
  73 +export function get${simpleClassName}(id: number) {
  74 + return requestClient.get<${simpleClassName}Api.${simpleClassName}>(`${baseURL}/get?id=${id}`);
  75 +}
  76 +
  77 +/** 新增${table.classComment} */
  78 +export function create${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  79 + return requestClient.post('${baseURL}/create', data);
  80 +}
  81 +
  82 +/** 修改${table.classComment} */
  83 +export function update${simpleClassName}(data: ${simpleClassName}Api.${simpleClassName}) {
  84 + return requestClient.put('${baseURL}/update', data);
  85 +}
  86 +
  87 +/** 删除${table.classComment} */
  88 +export function delete${simpleClassName}(id: number) {
  89 + return requestClient.delete(`${baseURL}/delete?id=${id}`);
  90 +}
  91 +
  92 +#if ( $table.templateType != 2 && $deleteBatchEnable)
  93 +/** 批量删除${table.classComment} */
  94 +export function delete${simpleClassName}List(ids: number[]) {
  95 + return requestClient.delete(`${baseURL}/delete-list?ids=${ids.join(',')}`)
  96 +}
  97 +#end
  98 +
  99 +/** 导出${table.classComment} */
  100 +export function export${simpleClassName}(params: any) {
  101 + return requestClient.download('${baseURL}/export-excel', params);
  102 +}
  103 +
  104 +## 特殊:主子表专属逻辑
  105 +#foreach ($subTable in $subTables)
  106 +#set ($index = $foreach.count - 1)
  107 +#set ($subSimpleClassName = $subSimpleClassNames.get($index))
  108 +#set ($subPrimaryColumn = $subPrimaryColumns.get($index))##当前 primary 字段
  109 +#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
  110 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  111 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  112 +#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  113 +#set ($subClassNameVar = $subClassNameVars.get($index))
  114 +
  115 +// ==================== 子表($subTable.classComment) ====================
  116 +
  117 +## 情况一:MASTER_ERP 时,需要分查询页子表
  118 +#if ( $table.templateType == 11 )
  119 +/** 获得${subTable.classComment}分页 */
  120 +export function get${subSimpleClassName}Page(params: PageParam) {
  121 + return requestClient.get<PageResult<${simpleClassName}Api.${subSimpleClassName}>>(`${baseURL}/${subSimpleClassName_strikeCase}/page`, { params });
  122 +}
  123 +## 情况二:非 MASTER_ERP 时,需要列表查询子表
  124 +#else
  125 + #if ( $subTable.subJoinMany )
  126 +/** 获得${subTable.classComment}列表 */
  127 +export function get${subSimpleClassName}ListBy${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
  128 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}[]>(`${baseURL}/${subSimpleClassName_strikeCase}/list-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  129 +}
  130 + #else
  131 +/** 获得${subTable.classComment} */
  132 +export function get${subSimpleClassName}By${SubJoinColumnName}(${subJoinColumn.javaField}: number) {
  133 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get-by-${subJoinColumn_strikeCase}?${subJoinColumn.javaField}=${${subJoinColumn.javaField}}`);
  134 +}
  135 + #end
  136 +#end
  137 +## 特殊:MASTER_ERP 时,支持单个的新增、修改、删除操作
  138 +#if ( $table.templateType == 11 )
  139 +/** 新增${subTable.classComment} */
  140 +export function create${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
  141 + return requestClient.post(`${baseURL}/${subSimpleClassName_strikeCase}/create`, data);
  142 +}
  143 +
  144 +/** 修改${subTable.classComment} */
  145 +export function update${subSimpleClassName}(data: ${simpleClassName}Api.${subSimpleClassName}) {
  146 + return requestClient.put(`${baseURL}/${subSimpleClassName_strikeCase}/update`, data);
  147 +}
  148 +
  149 +/** 删除${subTable.classComment} */
  150 +export function delete${subSimpleClassName}(id: number) {
  151 + return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete?id=${id}`);
  152 +}
  153 +
  154 +#if ($deleteBatchEnable)
  155 +/** 批量删除${subTable.classComment} */
  156 +export function delete${subSimpleClassName}List(ids: number[]) {
  157 + return requestClient.delete(`${baseURL}/${subSimpleClassName_strikeCase}/delete-list?ids=${ids.join(',')}`)
  158 +}
  159 +#end
  160 +
  161 +/** 获得${subTable.classComment} */
  162 +export function get${subSimpleClassName}(id: number) {
  163 + return requestClient.get<${simpleClassName}Api.${subSimpleClassName}>(`${baseURL}/${subSimpleClassName_strikeCase}/get?id=${id}`);
  164 +}
  165 +#end
  166 +#end
  167 +
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/data.ts.vm 0 → 100644
  1 +import type { VbenFormSchema } from '#/adapter/form';
  2 +import type { VxeTableGridOptions } from '#/adapter/vxe-table';
  3 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  4 +
  5 +import { z } from '#/adapter/form';
  6 +import {
  7 + DICT_TYPE,
  8 + getDictOptions,
  9 + getRangePickerDefaultProps,
  10 +} from '#/utils';
  11 +#if(${table.templateType} == 2)## 树表需要导入这些
  12 +import { get${simpleClassName}List } from '#/api/${table.moduleName}/${table.businessName}';
  13 +import { handleTree } from '@vben/utils';
  14 +#end
  15 +
  16 +/** 新增/修改的表单 */
  17 +export function useFormSchema(): VbenFormSchema[] {
  18 + return [
  19 + {
  20 + fieldName: 'id',
  21 + component: 'Input',
  22 + dependencies: {
  23 + triggerFields: [''],
  24 + show: () => false,
  25 + },
  26 + },
  27 +#if(${table.templateType} == 2)## 树表特有字段:上级
  28 + {
  29 + fieldName: '${treeParentColumn.javaField}',
  30 + label: '上级${table.classComment}',
  31 + component: 'ApiTreeSelect',
  32 + componentProps: {
  33 + allowClear: true,
  34 + api: async () => {
  35 + const data = await get${simpleClassName}List({});
  36 + data.unshift({
  37 + id: 0,
  38 + ${treeNameColumn.javaField}: '顶级${table.classComment}',
  39 + });
  40 + return handleTree(data);
  41 + },
  42 + labelField: '${treeNameColumn.javaField}',
  43 + valueField: 'id',
  44 + childrenField: 'children',
  45 + placeholder: '请选择上级${table.classComment}',
  46 + treeDefaultExpandAll: true,
  47 + },
  48 + rules: 'selectRequired',
  49 + },
  50 +#end
  51 +#foreach($column in $columns)
  52 +#if ($column.createOperation || $column.updateOperation)
  53 +#if (!$column.primaryKey && ($table.templateType != 2 || ($table.templateType == 2 && $column.id != $treeParentColumn.id)))## 树表中已经添加了父ID字段,这里排除
  54 + #set ($dictType = $column.dictType)
  55 + #set ($javaType = $column.javaType)
  56 + #set ($javaField = $column.javaField)
  57 + #set ($comment = $column.columnComment)
  58 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  59 + #set ($dictMethod = "number")
  60 + #elseif ($javaType == "String")
  61 + #set ($dictMethod = "string")
  62 + #elseif ($javaType == "Boolean")
  63 + #set ($dictMethod = "boolean")
  64 + #end
  65 + {
  66 + fieldName: '${javaField}',
  67 + label: '${comment}',
  68 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  69 + rules: 'required',
  70 + #end
  71 + #if ($column.htmlType == "input")
  72 + component: 'Input',
  73 + componentProps: {
  74 + placeholder: '请输入${comment}',
  75 + },
  76 + #elseif($column.htmlType == "imageUpload")## 图片上传
  77 + component: 'ImageUpload',
  78 + #elseif($column.htmlType == "fileUpload")## 文件上传
  79 + component: 'FileUpload',
  80 + #elseif($column.htmlType == "editor")## 文本编辑器
  81 + component: 'RichTextarea',
  82 + #elseif($column.htmlType == "select")## 下拉框
  83 + component: 'Select',
  84 + componentProps: {
  85 + #if ("" != $dictType)## 有数据字典
  86 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  87 + #else##没数据字典
  88 + options: [],
  89 + #end
  90 + placeholder: '请选择${comment}',
  91 + },
  92 + #elseif($column.htmlType == "checkbox")## 多选框
  93 + component: 'Checkbox',
  94 + componentProps: {
  95 + #if ("" != $dictType)## 有数据字典
  96 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  97 + #else##没数据字典
  98 + options: [],
  99 + #end
  100 + },
  101 + #elseif($column.htmlType == "radio")## 单选框
  102 + component: 'RadioGroup',
  103 + componentProps: {
  104 + #if ("" != $dictType)## 有数据字典
  105 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  106 + #else##没数据字典
  107 + options: [],
  108 + #end
  109 + buttonStyle: 'solid',
  110 + optionType: 'button',
  111 + },
  112 + #elseif($column.htmlType == "datetime")## 时间框
  113 + component: 'DatePicker',
  114 + componentProps: {
  115 + showTime: true,
  116 + format: 'YYYY-MM-DD HH:mm:ss',
  117 + valueFormat: 'x',
  118 + },
  119 + #elseif($column.htmlType == "textarea")## 文本域
  120 + component: 'Textarea',
  121 + componentProps: {
  122 + placeholder: '请输入${comment}',
  123 + },
  124 + #elseif($column.htmlType == "inputNumber")## 数字输入框
  125 + component: 'InputNumber',
  126 + componentProps: {
  127 + min: 0,
  128 + controlsPosition: 'right',
  129 + placeholder: '请输入${comment}',
  130 + },
  131 + #end
  132 + },
  133 +#end
  134 +#end
  135 +#end
  136 + ];
  137 +}
  138 +
  139 +/** 列表的搜索表单 */
  140 +export function useGridFormSchema(): VbenFormSchema[] {
  141 + return [
  142 +#foreach($column in $columns)
  143 +#if ($column.listOperation)
  144 + #set ($dictType = $column.dictType)
  145 + #set ($javaType = $column.javaType)
  146 + #set ($javaField = $column.javaField)
  147 + #set ($comment = $column.columnComment)
  148 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  149 + #set ($dictMethod = "number")
  150 + #elseif ($javaType == "String")
  151 + #set ($dictMethod = "string")
  152 + #elseif ($javaType == "Boolean")
  153 + #set ($dictMethod = "boolean")
  154 + #end
  155 + {
  156 + fieldName: '${javaField}',
  157 + label: '${comment}',
  158 + #if ($column.htmlType == "input" || $column.htmlType == "textarea" || $column.htmlType == "editor")
  159 + component: 'Input',
  160 + componentProps: {
  161 + allowClear: true,
  162 + placeholder: '请输入${comment}',
  163 + },
  164 + #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
  165 + component: 'Select',
  166 + componentProps: {
  167 + allowClear: true,
  168 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  169 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  170 + #else## 未设置 dictType 数据字典的情况
  171 + options: [],
  172 + #end
  173 + placeholder: '请选择${comment}',
  174 + },
  175 + #elseif($column.htmlType == "datetime")
  176 + component: 'RangePicker',
  177 + componentProps: {
  178 + ...getRangePickerDefaultProps(),
  179 + allowClear: true,
  180 + },
  181 + #end
  182 + },
  183 +#end
  184 +#end
  185 + ];
  186 +}
  187 +
  188 +/** 列表的字段 */
  189 +export function useGridColumns(): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] {
  190 + return [
  191 +#if ($table.templateType != 2 && $deleteBatchEnable)
  192 + { type: 'checkbox', width: 40 },
  193 +#end
  194 +#if ($table.templateType == 12) ## 内嵌情况
  195 + { type: 'expand', width: 80, slots: { content: 'expand_content' } },
  196 +#end
  197 +#foreach($column in $columns)
  198 +#if ($column.listOperationResult)
  199 + #set ($dictType = $column.dictType)
  200 + #set ($javaField = $column.javaField)
  201 + #set ($comment = $column.columnComment)
  202 + {
  203 + field: '${javaField}',
  204 + title: '${comment}',
  205 + minWidth: 120,
  206 + #if ($column.javaType == "LocalDateTime")## 时间类型
  207 + formatter: 'formatDateTime',
  208 + #elseif("" != $dictType)## 数据字典
  209 + cellRender: {
  210 + name: 'CellDict',
  211 + props: { type: DICT_TYPE.$dictType.toUpperCase() },
  212 + },
  213 + #end
  214 + #if (${table.templateType} == 2 && $column.id == $treeNameColumn.id)## 树表特有:标记树节点列
  215 + treeNode: true,
  216 + #end
  217 + },
  218 +#end
  219 +#end
  220 + {
  221 + title: '操作',
  222 + width: 200,
  223 + fixed: 'right',
  224 + slots: { default: 'actions' },
  225 + },
  226 + ];
  227 +}
  228 +
  229 +## 标准模式和内嵌模式时,主子关系一对一则生成表单schema,一对多则生成列表schema(内嵌模式时表单schema也要生成)。erp 模式时都生成
  230 +## 特殊:主子表专属逻辑
  231 +#foreach ($subTable in $subTables)
  232 + #set ($index = $foreach.count - 1)
  233 + #set ($subColumns = $subColumnsList.get($index))##当前字段数组
  234 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  235 + #set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
  236 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  237 +// ==================== 子表($subTable.classComment) ====================
  238 +
  239 +#if ($table.templateType == 11) ## erp 情况
  240 +/** 新增/修改的表单 */
  241 +export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
  242 + return [
  243 + {
  244 + fieldName: 'id',
  245 + component: 'Input',
  246 + dependencies: {
  247 + triggerFields: [''],
  248 + show: () => false,
  249 + },
  250 + },
  251 + #foreach($column in $subColumns)
  252 + #if ($column.createOperation || $column.updateOperation)
  253 + #if (!$column.primaryKey && ($table.templateType != 2 || ($table.templateType == 2 && $column.id != $treeParentColumn.id)))## 树表中已经添加了父ID字段,这里排除
  254 + #set ($dictType = $column.dictType)
  255 + #set ($javaType = $column.javaType)
  256 + #set ($javaField = $column.javaField)
  257 + #set ($comment = $column.columnComment)
  258 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  259 + #set ($dictMethod = "number")
  260 + #elseif ($javaType == "String")
  261 + #set ($dictMethod = "string")
  262 + #elseif ($javaType == "Boolean")
  263 + #set ($dictMethod = "boolean")
  264 + #end
  265 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  266 + #else
  267 + {
  268 + fieldName: '${javaField}',
  269 + label: '${comment}',
  270 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  271 + rules: 'required',
  272 + #end
  273 + #if ($column.htmlType == "input")
  274 + component: 'Input',
  275 + componentProps: {
  276 + placeholder: '请输入${comment}',
  277 + },
  278 + #elseif($column.htmlType == "imageUpload")## 图片上传
  279 + component: 'ImageUpload',
  280 + #elseif($column.htmlType == "fileUpload")## 文件上传
  281 + component: 'FileUpload',
  282 + #elseif($column.htmlType == "editor")## 文本编辑器
  283 + component: 'RichTextarea',
  284 + #elseif($column.htmlType == "select")## 下拉框
  285 + component: 'Select',
  286 + componentProps: {
  287 + #if ("" != $dictType)## 有数据字典
  288 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  289 + #else##没数据字典
  290 + options: [],
  291 + #end
  292 + placeholder: '请选择${comment}',
  293 + },
  294 + #elseif($column.htmlType == "checkbox")## 多选框
  295 + component: 'Checkbox',
  296 + componentProps: {
  297 + #if ("" != $dictType)## 有数据字典
  298 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  299 + #else##没数据字典
  300 + options: [],
  301 + #end
  302 + },
  303 + #elseif($column.htmlType == "radio")## 单选框
  304 + component: 'RadioGroup',
  305 + componentProps: {
  306 + #if ("" != $dictType)## 有数据字典
  307 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  308 + #else##没数据字典
  309 + options: [],
  310 + #end
  311 + buttonStyle: 'solid',
  312 + optionType: 'button',
  313 + },
  314 + #elseif($column.htmlType == "datetime")## 时间框
  315 + component: 'DatePicker',
  316 + componentProps: {
  317 + showTime: true,
  318 + format: 'YYYY-MM-DD HH:mm:ss',
  319 + valueFormat: 'x',
  320 + },
  321 + #elseif($column.htmlType == "textarea")## 文本域
  322 + component: 'Textarea',
  323 + componentProps: {
  324 + placeholder: '请输入${comment}',
  325 + },
  326 + #elseif($column.htmlType == "inputNumber")## 数字输入框
  327 + component: 'InputNumber',
  328 + componentProps: {
  329 + min: 0,
  330 + controlsPosition: 'right',
  331 + placeholder: '请输入${comment}',
  332 + },
  333 + #end
  334 + },
  335 + #end
  336 + #end
  337 + #end
  338 + #end
  339 + ];
  340 +}
  341 +
  342 +/** 列表的搜索表单 */
  343 +export function use${subSimpleClassName}GridFormSchema(): VbenFormSchema[] {
  344 + return [
  345 + #foreach($column in $subColumns)
  346 + #if ($column.listOperation)
  347 + #set ($dictType = $column.dictType)
  348 + #set ($javaType = $column.javaType)
  349 + #set ($javaField = $column.javaField)
  350 + #set ($comment = $column.columnComment)
  351 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  352 + #set ($dictMethod = "number")
  353 + #elseif ($javaType == "String")
  354 + #set ($dictMethod = "string")
  355 + #elseif ($javaType == "Boolean")
  356 + #set ($dictMethod = "boolean")
  357 + #end
  358 + {
  359 + fieldName: '${javaField}',
  360 + label: '${comment}',
  361 + #if ($column.htmlType == "input" || $column.htmlType == "textarea" || $column.htmlType == "editor")
  362 + component: 'Input',
  363 + componentProps: {
  364 + allowClear: true,
  365 + placeholder: '请输入${comment}',
  366 + },
  367 + #elseif ($column.htmlType == "select" || $column.htmlType == "radio")
  368 + component: 'Select',
  369 + componentProps: {
  370 + allowClear: true,
  371 + #if ("" != $dictType)## 设置了 dictType 数据字典的情况
  372 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  373 + #else## 未设置 dictType 数据字典的情况
  374 + options: [],
  375 + #end
  376 + placeholder: '请选择${comment}',
  377 + },
  378 + #elseif($column.htmlType == "datetime")
  379 + component: 'RangePicker',
  380 + componentProps: {
  381 + ...getRangePickerDefaultProps(),
  382 + allowClear: true,
  383 + },
  384 + #end
  385 + },
  386 + #end
  387 + #end
  388 + ];
  389 +}
  390 +
  391 +/** 列表的字段 */
  392 +export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  393 + return [
  394 + #if ($table.templateType != 2 && $deleteBatchEnable)
  395 + { type: 'checkbox', width: 40 },
  396 + #end
  397 + #foreach($column in $subColumns)
  398 + #if ($column.listOperationResult)
  399 + #set ($dictType = $column.dictType)
  400 + #set ($javaField = $column.javaField)
  401 + #set ($comment = $column.columnComment)
  402 + {
  403 + field: '${javaField}',
  404 + title: '${comment}',
  405 + minWidth: 120,
  406 + #if ($column.javaType == "LocalDateTime")## 时间类型
  407 + formatter: 'formatDateTime',
  408 + #elseif("" != $dictType)## 数据字典
  409 + cellRender: {
  410 + name: 'CellDict',
  411 + props: { type: DICT_TYPE.$dictType.toUpperCase() },
  412 + },
  413 + #end
  414 + },
  415 + #end
  416 + #end
  417 + {
  418 + title: '操作',
  419 + width: 200,
  420 + fixed: 'right',
  421 + slots: { default: 'actions' },
  422 + },
  423 + ];
  424 +}
  425 +
  426 +#else
  427 + #if ($subTable.subJoinMany) ## 一对多
  428 + /** 新增/修改列表的字段 */
  429 + export function use${subSimpleClassName}GridEditColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  430 + return [
  431 + #foreach($column in $subColumns)
  432 + #if ($column.createOperation || $column.updateOperation)
  433 + #if (!$column.primaryKey && $column.listOperationResult && $column.id != $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  434 + #set ($dictType = $column.dictType)
  435 + #set ($javaField = $column.javaField)
  436 + #set ($comment = $column.columnComment)
  437 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  438 + #set ($dictMethod = "number")
  439 + #elseif ($javaType == "String")
  440 + #set ($dictMethod = "string")
  441 + #elseif ($javaType == "Boolean")
  442 + #set ($dictMethod = "boolean")
  443 + #end
  444 + {
  445 + field: '${javaField}',
  446 + title: '${comment}',
  447 + minWidth: 120,
  448 + slots: { default: '${javaField}' },
  449 + #if ($column.htmlType == "select" || $column.htmlType == "checkbox" || $column.htmlType == "radio")
  450 + #if ("" != $dictType)## 有数据字典
  451 + params: {
  452 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  453 + },
  454 + #else
  455 + params: {
  456 + options: [],
  457 + },
  458 + #end
  459 + #end
  460 + },
  461 + #end
  462 + #end
  463 + #end
  464 + {
  465 + title: '操作',
  466 + width: 200,
  467 + fixed: 'right',
  468 + slots: { default: 'actions' },
  469 + },
  470 + ];
  471 + }
  472 +
  473 + #else
  474 + /** 新增/修改的表单 */
  475 + export function use${subSimpleClassName}FormSchema(): VbenFormSchema[] {
  476 + return [
  477 + {
  478 + fieldName: 'id',
  479 + component: 'Input',
  480 + dependencies: {
  481 + triggerFields: [''],
  482 + show: () => false,
  483 + },
  484 + },
  485 + #foreach($column in $subColumns)
  486 + #if ($column.createOperation || $column.updateOperation)
  487 + #if (!$column.primaryKey && ($table.templateType != 2 || ($table.templateType == 2 && $column.id != $treeParentColumn.id)))## 树表中已经添加了父ID字段,这里排除
  488 + #set ($dictType = $column.dictType)
  489 + #set ($javaType = $column.javaType)
  490 + #set ($javaField = $column.javaField)
  491 + #set ($comment = $column.columnComment)
  492 + #if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
  493 + #set ($dictMethod = "number")
  494 + #elseif ($javaType == "String")
  495 + #set ($dictMethod = "string")
  496 + #elseif ($javaType == "Boolean")
  497 + #set ($dictMethod = "boolean")
  498 + #end
  499 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  500 + #else
  501 + {
  502 + fieldName: '${javaField}',
  503 + label: '${comment}',
  504 + #if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
  505 + rules: 'required',
  506 + #end
  507 + #if ($column.htmlType == "input")
  508 + component: 'Input',
  509 + componentProps: {
  510 + placeholder: '请输入${comment}',
  511 + },
  512 + #elseif($column.htmlType == "imageUpload")## 图片上传
  513 + component: 'ImageUpload',
  514 + #elseif($column.htmlType == "fileUpload")## 文件上传
  515 + component: 'FileUpload',
  516 + #elseif($column.htmlType == "editor")## 文本编辑器
  517 + component: 'RichTextarea',
  518 + #elseif($column.htmlType == "select")## 下拉框
  519 + component: 'Select',
  520 + componentProps: {
  521 + #if ("" != $dictType)## 有数据字典
  522 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  523 + #else##没数据字典
  524 + options: [],
  525 + #end
  526 + placeholder: '请选择${comment}',
  527 + },
  528 + #elseif($column.htmlType == "checkbox")## 多选框
  529 + component: 'Checkbox',
  530 + componentProps: {
  531 + #if ("" != $dictType)## 有数据字典
  532 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  533 + #else##没数据字典
  534 + options: [],
  535 + #end
  536 + },
  537 + #elseif($column.htmlType == "radio")## 单选框
  538 + component: 'RadioGroup',
  539 + componentProps: {
  540 + #if ("" != $dictType)## 有数据字典
  541 + options: getDictOptions(DICT_TYPE.$dictType.toUpperCase(), '$dictMethod'),
  542 + #else##没数据字典
  543 + options: [],
  544 + #end
  545 + buttonStyle: 'solid',
  546 + optionType: 'button',
  547 + },
  548 + #elseif($column.htmlType == "datetime")## 时间框
  549 + component: 'DatePicker',
  550 + componentProps: {
  551 + showTime: true,
  552 + format: 'YYYY-MM-DD HH:mm:ss',
  553 + valueFormat: 'x',
  554 + },
  555 + #elseif($column.htmlType == "textarea")## 文本域
  556 + component: 'Textarea',
  557 + componentProps: {
  558 + placeholder: '请输入${comment}',
  559 + },
  560 + #elseif($column.htmlType == "inputNumber")## 数字输入框
  561 + component: 'InputNumber',
  562 + componentProps: {
  563 + min: 0,
  564 + controlsPosition: 'right',
  565 + placeholder: '请输入${comment}',
  566 + },
  567 + #end
  568 + },
  569 + #end
  570 + #end
  571 + #end
  572 + #end
  573 + ];
  574 + }
  575 +
  576 + #end
  577 + #if ($table.templateType == 12) ## 内嵌情况
  578 + /** 列表的字段 */
  579 + export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
  580 + return [
  581 + #foreach($column in $subColumns)
  582 + #if ($column.listOperationResult)
  583 + #set ($dictType = $column.dictType)
  584 + #set ($javaField = $column.javaField)
  585 + #set ($comment = $column.columnComment)
  586 + {
  587 + field: '${javaField}',
  588 + title: '${comment}',
  589 + minWidth: 120,
  590 + #if ($column.javaType == "LocalDateTime")## 时间类型
  591 + formatter: 'formatDateTime',
  592 + #elseif("" != $dictType)## 数据字典
  593 + cellRender: {
  594 + name: 'CellDict',
  595 + props: { type: DICT_TYPE.$dictType.toUpperCase() },
  596 + },
  597 + #end
  598 + },
  599 + #end
  600 + #end
  601 + ];
  602 + }
  603 + #end
  604 +#end
  605 +#end
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/form.vue.vm 0 → 100644
  1 +<script lang="ts" setup>
  2 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  3 +
  4 +import { useVbenModal } from '@vben/common-ui';
  5 +import { ElMessage, ElTabs, ElTabPane, ElCheckbox, ElInput, ElSelect, ElRadioGroup, ElCheckboxGroup, ElDatePicker } from 'element-plus';
  6 +## 特殊:主子表专属逻辑
  7 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  8 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  9 + #set ($index = $foreach.count - 1)
  10 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  11 + import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
  12 + #end
  13 +#end
  14 +
  15 +import { computed, ref } from 'vue';
  16 +import { $t } from '#/locales';
  17 +import { useVbenForm } from '#/adapter/form';
  18 +import { get${simpleClassName}, create${simpleClassName}, update${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  19 +
  20 +import { useFormSchema } from '../data';
  21 +
  22 +const emit = defineEmits(['success']);
  23 +const formData = ref<${simpleClassName}Api.${simpleClassName}>();
  24 +const getTitle = computed(() => {
  25 + return formData.value?.id
  26 + ? $t('ui.actionTitle.edit', ['${table.classComment}'])
  27 + : $t('ui.actionTitle.create', ['${table.classComment}']);
  28 +});
  29 +
  30 +## 特殊:主子表专属逻辑
  31 +#if ( $table.templateType == 10 || $table.templateType == 12 )
  32 + #if ( $subTables && $subTables.size() > 0 )
  33 +
  34 + /** 子表的表单 */
  35 + const subTabsName = ref('$subClassNameVars.get(0)')
  36 + #foreach ($subClassNameVar in $subClassNameVars)
  37 + #set ($index = $foreach.count - 1)
  38 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  39 + const ${subClassNameVar}FormRef = ref<InstanceType<typeof ${subSimpleClassName}Form>>()
  40 + #end
  41 + #end
  42 +#end
  43 +
  44 +const [Form, formApi] = useVbenForm({
  45 + commonConfig: {
  46 + componentProps: {
  47 + class: 'w-full',
  48 + },
  49 + formItemClass: 'col-span-2',
  50 + labelWidth: 80,
  51 + },
  52 + layout: 'horizontal',
  53 + schema: useFormSchema(),
  54 + showDefaultActions: false
  55 +});
  56 +
  57 +const [Modal, modalApi] = useVbenModal({
  58 + async onConfirm() {
  59 + const { valid } = await formApi.validate();
  60 + if (!valid) {
  61 + return;
  62 + }
  63 + ## 特殊:主子表专属逻辑
  64 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  65 + #if ( $subTables && $subTables.size() > 0 )
  66 + // 校验子表单
  67 + #foreach ($subTable in $subTables)
  68 + #set ($index = $foreach.count - 1)
  69 + #set ($subClassNameVar = $subClassNameVars.get($index))
  70 + #if ($subTable.subJoinMany) ## 一对多
  71 + ## TODO 列表值校验?
  72 + #else
  73 + const ${subClassNameVar}Valid = await ${subClassNameVar}FormRef.value?.validate();
  74 + if (!${subClassNameVar}Valid) {
  75 + subTabsName.value = '${subClassNameVar}';
  76 + return;
  77 + }
  78 + #end
  79 + #end
  80 + #end
  81 + #end
  82 + modalApi.lock();
  83 + // 提交表单
  84 + const data = (await formApi.getValues()) as ${simpleClassName}Api.${simpleClassName};
  85 + ## 特殊:主子表专属逻辑
  86 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  87 + #if ( $subTables && $subTables.size() > 0 )
  88 + // 拼接子表的数据
  89 + #foreach ($subTable in $subTables)
  90 + #set ($index = $foreach.count - 1)
  91 + #set ($subClassNameVar = $subClassNameVars.get($index))
  92 + #if ($subTable.subJoinMany)
  93 + data.${subClassNameVar}s = ${subClassNameVar}FormRef.value?.getData();
  94 + #else
  95 + data.${subClassNameVar} = await ${subClassNameVar}FormRef.value?.getValues();
  96 + #end
  97 + #end
  98 + #end
  99 + #end
  100 + try {
  101 + await (formData.value?.id ? update${simpleClassName}(data) : create${simpleClassName}(data));
  102 + // 关闭并提示
  103 + await modalApi.close();
  104 + emit('success');
  105 + ElMessage.success($t('ui.actionMessage.operationSuccess'));
  106 + } finally {
  107 + modalApi.unlock();
  108 + }
  109 + },
  110 + async onOpenChange(isOpen: boolean) {
  111 + if (!isOpen) {
  112 + formData.value = undefined;
  113 + return;
  114 + }
  115 + // 加载数据
  116 + let data = modalApi.getData<${simpleClassName}Api.${simpleClassName}>();
  117 + if (!data) {
  118 + return;
  119 + }
  120 + if (data.id) {
  121 + modalApi.lock();
  122 + try {
  123 + data = await get${simpleClassName}(data.id);
  124 + } finally {
  125 + modalApi.unlock();
  126 + }
  127 + }
  128 + // 设置到 values
  129 + formData.value = data;
  130 + await formApi.setValues(formData.value);
  131 + },
  132 +});
  133 +</script>
  134 +
  135 +<template>
  136 + <Modal :title="getTitle">
  137 + <Form class="mx-4" />
  138 + ## 特殊:主子表专属逻辑
  139 + #if ( $table.templateType == 10 || $table.templateType == 12 )
  140 + <!-- 子表的表单 -->
  141 + <el-tabs v-model="subTabsName">
  142 + #foreach ($subTable in $subTables)
  143 + #set ($index = $foreach.count - 1)
  144 + #set ($subClassNameVar = $subClassNameVars.get($index))
  145 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  146 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  147 + <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}">
  148 + <${subSimpleClassName}Form ref="${subClassNameVar}FormRef" :${subJoinColumn_strikeCase}="formData?.id" />
  149 + </el-tab-pane>
  150 + #end
  151 + </el-tabs>
  152 + #end
  153 + </Modal>
  154 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm 0 → 100644
  1 +<script lang="ts" setup>
  2 +import type { VxeTableGridOptions } from '#/adapter/vxe-table';
  3 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  4 +
  5 +import { Page, useVbenModal } from '@vben/common-ui';
  6 +import { ElMessage, ElTabs, ElTabPane, ElLoading } from 'element-plus';
  7 +import Form from './modules/form.vue';
  8 +
  9 +## 特殊:主子表专属逻辑
  10 +#if ( $table.templateType == 11 || $table.templateType == 12 )
  11 + #foreach ($subSimpleClassName in $subSimpleClassNames)
  12 + #set ($index = $foreach.count - 1)
  13 + #set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
  14 +import ${subSimpleClassName}List from './modules/${subSimpleClassName_strikeCase}-list.vue'
  15 + #end
  16 +#end
  17 +
  18 +import { ref, computed } from 'vue';
  19 +import { $t } from '#/locales';
  20 +import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
  21 +#if (${table.templateType} == 2)## 树表接口
  22 +import { get${simpleClassName}List, delete${simpleClassName}, export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  23 +#else## 标准表接口
  24 +import { get${simpleClassName}Page, delete${simpleClassName},#if ($deleteBatchEnable) delete${simpleClassName}List,#end export${simpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  25 +#end
  26 +import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
  27 +
  28 +import { useGridColumns, useGridFormSchema } from './data';
  29 +
  30 +#if ($table.templateType == 12 || $table.templateType == 11) ## 内嵌和erp情况
  31 +/** 子表的列表 */
  32 +const subTabsName = ref('$subClassNameVars.get(0)')
  33 +#if ($table.templateType == 11)
  34 +const select${simpleClassName} = ref<${simpleClassName}Api.${simpleClassName}>();
  35 +#end
  36 +#end
  37 +
  38 +const [FormModal, formModalApi] = useVbenModal({
  39 + connectedComponent: Form,
  40 + destroyOnClose: true,
  41 +});
  42 +
  43 +#if (${table.templateType} == 2)## 树表特有:控制表格展开收缩
  44 +/** 切换树形展开/收缩状态 */
  45 +const isExpanded = ref(true);
  46 +function toggleExpand() {
  47 + isExpanded.value = !isExpanded.value;
  48 + gridApi.grid.setAllTreeExpand(isExpanded.value);
  49 +}
  50 +#end
  51 +
  52 +/** 刷新表格 */
  53 +function onRefresh() {
  54 +#if ($table.templateType == 12) ## 内嵌情况
  55 + gridApi.reload();
  56 +#else
  57 + gridApi.query();
  58 +#end
  59 +}
  60 +
  61 +/** 创建${table.classComment} */
  62 +function handleCreate() {
  63 + formModalApi.setData({}).open();
  64 +}
  65 +
  66 +/** 编辑${table.classComment} */
  67 +function handleEdit(row: ${simpleClassName}Api.${simpleClassName}) {
  68 + formModalApi.setData(row).open();
  69 +}
  70 +
  71 +#if (${table.templateType} == 2)## 树表特有:新增下级
  72 +/** 新增下级${table.classComment} */
  73 +function handleAppend(row: ${simpleClassName}Api.${simpleClassName}) {
  74 + formModalApi.setData({ ${treeParentColumn.javaField}: row.id }).open();
  75 +}
  76 +#end
  77 +
  78 +/** 删除${table.classComment} */
  79 +async function handleDelete(row: ${simpleClassName}Api.${simpleClassName}) {
  80 + const loadingInstance = ElLoading.service({
  81 + text: $t('ui.actionMessage.deleting', [row.id]),
  82 + background: 'rgba(0, 0, 0, 0.7)',
  83 + });
  84 + try {
  85 + await delete${simpleClassName}(row.id as number);
  86 + ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.id]));
  87 + onRefresh();
  88 + } finally {
  89 + loadingInstance.close();
  90 + }
  91 +}
  92 +
  93 +#if ($table.templateType != 2 && $deleteBatchEnable)
  94 +/** 批量删除${table.classComment} */
  95 +async function handleDeleteBatch() {
  96 + const loadingInstance = ElLoading.service({
  97 + text: $t('ui.actionMessage.deleting'),
  98 + background: 'rgba(0, 0, 0, 0.7)',
  99 + });
  100 + try {
  101 + await delete${simpleClassName}List(checkedIds.value);
  102 + ElMessage.success($t('ui.actionMessage.deleteSuccess'));
  103 + onRefresh();
  104 + } finally {
  105 + loadingInstance.close();
  106 + }
  107 +}
  108 +
  109 +const checkedIds = ref<number[]>([])
  110 +function handleRowCheckboxChange({
  111 + records,
  112 +}: {
  113 + records: ${simpleClassName}Api.${simpleClassName}[];
  114 +}) {
  115 + checkedIds.value = records.map((item) => item.id);
  116 +}
  117 +#end
  118 +
  119 +/** 导出表格 */
  120 +async function handleExport() {
  121 + const data = await export${simpleClassName}(await gridApi.formApi.getValues());
  122 + downloadFileFromBlobPart({ fileName: '${table.classComment}.xls', source: data });
  123 +}
  124 +
  125 +const [Grid, gridApi] = useVbenVxeGrid({
  126 + formOptions: {
  127 + schema: useGridFormSchema(),
  128 + },
  129 + gridOptions: {
  130 + columns: useGridColumns(),
  131 +#if (${table.templateType} == 11)
  132 + height: '600px',
  133 +#else
  134 + height: 'auto',
  135 +#end
  136 +#if (${table.templateType} == 2)## 树表设置
  137 + treeConfig: {
  138 + parentField: '${treeParentColumn.javaField}',
  139 + rowField: 'id',
  140 + transform: true,
  141 + expandAll: true,
  142 + reserve: true,
  143 + },
  144 + pagerConfig: {
  145 + enabled: false,
  146 + },
  147 +#else## 标准表设置
  148 + pagerConfig: {
  149 + enabled: true,
  150 + },
  151 +#end
  152 + proxyConfig: {
  153 + ajax: {
  154 +#if (${table.templateType} == 2)## 树表数据加载
  155 + query: async (_, formValues) => {
  156 + return await get${simpleClassName}List(formValues);
  157 + },
  158 +#else## 标准表数据加载
  159 + query: async ({ page }, formValues) => {
  160 + return await get${simpleClassName}Page({
  161 + pageNo: page.currentPage,
  162 + pageSize: page.pageSize,
  163 + ...formValues,
  164 + });
  165 + },
  166 +#end
  167 + },
  168 + },
  169 + rowConfig: {
  170 + keyField: 'id',
  171 + isHover: true,
  172 +#if (${table.templateType} == 11)
  173 + isCurrent: true,
  174 +#end
  175 + },
  176 + toolbarConfig: {
  177 + refresh: { code: 'query' },
  178 + search: true,
  179 + },
  180 + } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
  181 +#if (${table.templateType} == 11 || $deleteBatchEnable)
  182 + gridEvents:{
  183 + #if(${table.templateType} == 11)
  184 + cellClick: ({ row }: { row: ${simpleClassName}Api.${simpleClassName}}) => {
  185 + select${simpleClassName}.value = row;
  186 + },
  187 + #end
  188 + #if(${table.templateType} != 2 && $deleteBatchEnable)
  189 + checkboxAll: handleRowCheckboxChange,
  190 + checkboxChange: handleRowCheckboxChange,
  191 + #end
  192 + }
  193 +#end
  194 +});
  195 +</script>
  196 +
  197 +<template>
  198 + <Page auto-content-height>
  199 + <FormModal @success="onRefresh" />
  200 +
  201 +#if ($table.templateType == 11) ## erp情况
  202 + <div>
  203 +#end
  204 + <Grid table-title="${table.classComment}列表">
  205 + #if ($table.templateType == 12) ## 内嵌情况
  206 + <template #expand_content="{ row }">
  207 + <!-- 子表的表单 -->
  208 + <el-tabs v-model="subTabsName" class="mx-8">
  209 + #foreach ($subTable in $subTables)
  210 + #set ($index = $foreach.count - 1)
  211 + #set ($subClassNameVar = $subClassNameVars.get($index))
  212 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  213 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  214 + <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}">
  215 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="row?.id" />
  216 + </el-tab-pane>
  217 + #end
  218 + </el-tabs>
  219 + </template>
  220 + #end
  221 + <template #toolbar-tools>
  222 + <TableAction
  223 + :actions="[
  224 + #if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
  225 + {
  226 + label: isExpanded ? '收缩' : '展开',
  227 + type: 'primary',
  228 + onClick: toggleExpand,
  229 + },
  230 + #end
  231 + {
  232 + label: $t('ui.actionTitle.create', ['${table.classComment}']),
  233 + type: 'primary',
  234 + icon: ACTION_ICON.ADD,
  235 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:create'],
  236 + onClick: handleCreate,
  237 + },
  238 + {
  239 + label: $t('ui.actionTitle.export'),
  240 + type: 'primary',
  241 + icon: ACTION_ICON.DOWNLOAD,
  242 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:export'],
  243 + onClick: handleExport,
  244 + },
  245 + #if ($table.templateType != 2 && $deleteBatchEnable)
  246 + {
  247 + label: $t('ui.actionTitle.deleteBatch'),
  248 + type: 'danger',
  249 + icon: ACTION_ICON.DELETE,
  250 + disabled: isEmpty(checkedIds),
  251 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:delete'],
  252 + onClick: handleDeleteBatch,
  253 + },
  254 + #end
  255 + ]"
  256 + />
  257 + </template>
  258 + <template #actions="{ row }">
  259 + <TableAction
  260 + :actions="[
  261 + #if (${table.templateType} == 2)## 树表特有:新增下级
  262 + {
  263 + label: '新增下级',
  264 + type: 'text',
  265 + icon: ACTION_ICON.ADD,
  266 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:create'],
  267 + onClick: handleAppend.bind(null, row),
  268 + },
  269 + #end
  270 + {
  271 + label: $t('common.edit'),
  272 + type: 'text',
  273 + icon: ACTION_ICON.EDIT,
  274 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:update'],
  275 + onClick: handleEdit.bind(null, row),
  276 + },
  277 + {
  278 + label: $t('common.delete'),
  279 + type: 'danger',
  280 + text: true,
  281 + icon: ACTION_ICON.DELETE,
  282 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:delete'],
  283 + popConfirm: {
  284 + title: $t('ui.actionMessage.deleteConfirm', [row.id]),
  285 + confirm: handleDelete.bind(null, row),
  286 + },
  287 + },
  288 + ]"
  289 + />
  290 + </template>
  291 + </Grid>
  292 +
  293 +#if ($table.templateType == 11) ## erp情况
  294 + <!-- 子表的表单 -->
  295 + <el-tabs v-model="subTabsName" class="mt-2">
  296 + #foreach ($subTable in $subTables)
  297 + #set ($index = $foreach.count - 1)
  298 + #set ($subClassNameVar = $subClassNameVars.get($index))
  299 + #set ($subSimpleClassName = $subSimpleClassNames.get($index))
  300 + #set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
  301 + <el-tab-pane name="$subClassNameVar" label="${subTable.classComment}">
  302 + <${subSimpleClassName}List :${subJoinColumn_strikeCase}="select${simpleClassName}?.id" />
  303 + </el-tab-pane>
  304 + #end
  305 + </el-tabs>
  306 + </div>
  307 +#end
  308 + </Page>
  309 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/form_sub_erp.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +<script lang="ts" setup>
  6 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  7 +
  8 + import { useVbenModal } from '@vben/common-ui';
  9 + import { ElMessage } from 'element-plus';
  10 +
  11 + import { computed, ref } from 'vue';
  12 + import { $t } from '#/locales';
  13 + import { useVbenForm } from '#/adapter/form';
  14 + import { get${subSimpleClassName}, create${subSimpleClassName}, update${subSimpleClassName} } from '#/api/${table.moduleName}/${table.businessName}';
  15 +
  16 + import { use${subSimpleClassName}FormSchema } from '../data';
  17 +
  18 + const emit = defineEmits(['success']);
  19 + const formData = ref<${simpleClassName}Api.${subSimpleClassName}>();
  20 + const getTitle = computed(() => {
  21 + return formData.value?.id
  22 + ? $t('ui.actionTitle.edit', ['${subTable.classComment}'])
  23 + : $t('ui.actionTitle.create', ['${subTable.classComment}']);
  24 + });
  25 +
  26 + const [Form, formApi] = useVbenForm({
  27 + commonConfig: {
  28 + componentProps: {
  29 + class: 'w-full',
  30 + },
  31 + formItemClass: 'col-span-2',
  32 + labelWidth: 80,
  33 + },
  34 + layout: 'horizontal',
  35 + schema: use${subSimpleClassName}FormSchema(),
  36 + showDefaultActions: false
  37 + });
  38 +
  39 + const [Modal, modalApi] = useVbenModal({
  40 + async onConfirm() {
  41 + const { valid } = await formApi.validate();
  42 + if (!valid) {
  43 + return;
  44 + }
  45 +
  46 + modalApi.lock();
  47 + // 提交表单
  48 + const data = (await formApi.getValues()) as ${simpleClassName}Api.${subSimpleClassName};
  49 + data.${subJoinColumn.javaField} = formData.value?.${subJoinColumn.javaField};
  50 + try {
  51 + await (formData.value?.id ? update${subSimpleClassName}(data) : create${subSimpleClassName}(data));
  52 + // 关闭并提示
  53 + await modalApi.close();
  54 + emit('success');
  55 + ElMessage.success($t('ui.actionMessage.operationSuccess'));
  56 + } finally {
  57 + modalApi.unlock();
  58 + }
  59 + },
  60 + async onOpenChange(isOpen: boolean) {
  61 + if (!isOpen) {
  62 + formData.value = undefined;
  63 + return;
  64 + }
  65 +
  66 + // 加载数据
  67 + let data = modalApi.getData<${simpleClassName}Api.${subSimpleClassName}>();
  68 + if (!data) {
  69 + return;
  70 + }
  71 + if (data.id) {
  72 + modalApi.lock();
  73 + try {
  74 + data = await get${subSimpleClassName}(data.id);
  75 + } finally {
  76 + modalApi.unlock();
  77 + }
  78 + }
  79 + // 设置到 values
  80 + formData.value = data;
  81 + await formApi.setValues(formData.value);
  82 + },
  83 + });
  84 +</script>
  85 +
  86 +<template>
  87 + <Modal :title="getTitle">
  88 + <Form class="mx-4" />
  89 + </Modal>
  90 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/form_sub_inner.vue.vm 0 → 100644
  1 +## 主表的 normal 和 inner 使用相同的 form 表单
  2 +#parse("codegen/vue3_vben5_ele/schema/views/modules/form_sub_normal.vue.vm")
0 3 \ No newline at end of file
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/form_sub_normal.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($subClassNameVar = $subClassNameVars.get($subIndex))
  6 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  7 +<script lang="ts" setup>
  8 + import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  9 +
  10 + import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
  11 + import { $t } from '#/locales';
  12 +
  13 +#if ($subTable.subJoinMany) ## 一对多
  14 +import { Plus } from "@vben/icons";
  15 +import { ElButton, ElTabs, ElTabPane, ElCheckbox, ElInput, ElSelect, ElOption, ElRadioGroup, ElCheckboxGroup, ElDatePicker } from 'element-plus';
  16 +import { ImageUpload, FileUpload } from "#/components/upload";
  17 +import type { OnActionClickParams } from '#/adapter/vxe-table';
  18 +import { useVbenVxeGrid } from '#/adapter/vxe-table';
  19 +import { use${subSimpleClassName}GridEditColumns } from '../data';
  20 +import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}';
  21 +#else
  22 +import { useVbenForm } from '#/adapter/form';
  23 +import { use${subSimpleClassName}FormSchema } from '../data';
  24 +import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}';
  25 +#end
  26 +
  27 +const props = defineProps<{
  28 + ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
  29 +}>()
  30 +
  31 +#if ($subTable.subJoinMany) ## 一对多
  32 +/** 表格操作按钮的回调函数 */
  33 +function onActionClick({
  34 + code,
  35 + row,
  36 +}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
  37 + switch (code) {
  38 + case 'delete': {
  39 + onDelete(row);
  40 + break;
  41 + }
  42 + }
  43 +}
  44 +
  45 +const [Grid, gridApi] = useVbenVxeGrid({
  46 +gridOptions: {
  47 + columns: use${subSimpleClassName}GridEditColumns(onActionClick),
  48 + border: true,
  49 + showOverflow: true,
  50 + autoResize: true,
  51 + keepSource: true,
  52 + rowConfig: {
  53 + keyField: 'id',
  54 + },
  55 + pagerConfig: {
  56 + enabled: false,
  57 + },
  58 + toolbarConfig: {
  59 + enabled: false,
  60 + },
  61 +},
  62 +});
  63 +
  64 +/** 添加${subTable.classComment} */
  65 +const onAdd = async () => {
  66 + await gridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
  67 +}
  68 +
  69 +/** 删除${subTable.classComment} */
  70 +const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
  71 + await gridApi.grid.remove(row);
  72 +}
  73 +
  74 +/** 提供获取表格数据的方法供父组件调用 */
  75 +defineExpose({
  76 + getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
  77 + const data = gridApi.grid.getData() as ${simpleClassName}Api.${subSimpleClassName}[];
  78 + const removeRecords = gridApi.grid.getRemoveRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  79 + const insertRecords = gridApi.grid.getInsertRecords() as ${simpleClassName}Api.${subSimpleClassName}[];
  80 + return data
  81 + .filter((row) => !removeRecords.some((removed) => removed.id === row.id))
  82 + .concat(insertRecords.map((row: any) => ({ ...row, id: undefined })));
  83 + },
  84 +});
  85 +
  86 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  87 +watch(
  88 + () => props.${subJoinColumn.javaField},
  89 + async (val) => {
  90 + if (!val) {
  91 + return;
  92 + }
  93 + await nextTick();
  94 + await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  95 + },
  96 + { immediate: true },
  97 +);
  98 +#else
  99 +const [Form, formApi] = useVbenForm({
  100 + commonConfig: {
  101 + componentProps: {
  102 + class: 'w-full',
  103 + },
  104 + formItemClass: 'col-span-2',
  105 + labelWidth: 80,
  106 + },
  107 + layout: 'horizontal',
  108 + schema: use${subSimpleClassName}FormSchema(),
  109 + showDefaultActions: false
  110 +});
  111 +
  112 +/** 暴露出表单校验方法和表单值获取方法 */
  113 +defineExpose({
  114 + validate: async () => {
  115 + const { valid } = await formApi.validate();
  116 + return valid;
  117 + },
  118 + getValues: formApi.getValues,
  119 +});
  120 +
  121 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  122 +watch(
  123 + () => props.${subJoinColumn.javaField},
  124 + async (val) => {
  125 + if (!val) {
  126 + return;
  127 + }
  128 + await nextTick();
  129 + await formApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  130 + },
  131 + { immediate: true },
  132 +);
  133 +#end
  134 +</script>
  135 +
  136 +<template>
  137 +#if ($subTable.subJoinMany) ## 一对多
  138 + <Grid class="mx-4">
  139 + #foreach($column in $subColumns)
  140 + #if ($column.createOperation || $column.updateOperation)
  141 + #set ($javaField = $column.javaField)
  142 + #if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
  143 + #elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
  144 + <template #${javaField}="{ row }">
  145 + <el-input v-model="row.${javaField}" />
  146 + </template>
  147 + #elseif($column.htmlType == "imageUpload")## 图片上传
  148 + <template #${javaField}="{ row }">
  149 + <ImageUpload v-model="row.${javaField}" />
  150 + </template>
  151 + #elseif($column.htmlType == "fileUpload")## 文件上传
  152 + <template #${javaField}="{ row }">
  153 + <FileUpload v-model="row.${javaField}" />
  154 + </template>
  155 + #elseif($column.htmlType == "select")## 下拉框
  156 + <template #${javaField}="{ row, column }">
  157 + <el-select v-model="row.${javaField}" class="w-full">
  158 + <el-option v-for="option in column.params.options" :key="option.value" :value="option.value" :label="option.label" />
  159 + </el-select>
  160 + </template>
  161 + #elseif($column.htmlType == "checkbox")## 多选框
  162 + <template #${javaField}="{ row, column }">
  163 + <el-checkbox-group v-model="row.${javaField}">
  164 + <el-checkbox v-for="option in column.params.options" :key="option.value" :label="option.value">
  165 + {{ option.label }}
  166 + </el-checkbox>
  167 + </el-checkbox-group>
  168 + </template>
  169 + #elseif($column.htmlType == "radio")## 单选框
  170 + <template #${javaField}="{ row, column }">
  171 + <el-radio-group v-model="row.${javaField}">
  172 + <el-radio v-for="option in column.params.options" :key="option.value" :label="option.value">
  173 + {{ option.label }}
  174 + </el-radio>
  175 + </el-radio-group>
  176 + </template>
  177 + #elseif($column.htmlType == "datetime")## 时间框
  178 + <template #${javaField}="{ row }">
  179 + <el-date-picker
  180 + v-model="row.${javaField}"
  181 + type="datetime"
  182 + value-format="x"
  183 + format="YYYY-MM-DD HH:mm:ss"
  184 + />
  185 + </template>
  186 + #elseif($column.htmlType == "textarea" || $column.htmlType == "editor")## 文本框
  187 + <template #${javaField}="{ row }">
  188 + <el-input v-model="row.${javaField}" type="textarea" />
  189 + </template>
  190 + #end
  191 + #end
  192 + #end
  193 + </Grid>
  194 + <div class="flex justify-center -mt-4">
  195 + <el-button :icon="Plus" type="primary" plain @click="onAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
  196 + {{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
  197 + </el-button>
  198 + </div>
  199 +#else
  200 + <Form class="mx-4" />
  201 +#end
  202 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm 0 → 100644
  1 +#set ($subTable = $subTables.get($subIndex))##当前表
  2 +#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
  3 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  4 +#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
  5 +#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
  6 +#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($subIndex))
  7 +#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
  8 +<script lang="ts" setup>
  9 +import type { VxeTableGridOptions } from '#/adapter/vxe-table';
  10 +import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${table.businessName}';
  11 +
  12 +#if ($table.templateType == 11) ## erp
  13 +import ${subSimpleClassName}Form from './${subSimpleClassName_strikeCase}-form.vue'
  14 +#end
  15 +import { useVbenModal } from '@vben/common-ui';
  16 +import { ElMessage, ElLoading } from 'element-plus';
  17 +import { ref, computed, nextTick,watch } from 'vue';
  18 +import { $t } from '#/locales';
  19 +import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
  20 +
  21 +#if ($table.templateType == 11) ## erp
  22 +import { delete${subSimpleClassName},#if ($deleteBatchEnable) delete${subSimpleClassName}List,#end get${subSimpleClassName}Page } from '#/api/${table.moduleName}/${table.businessName}';
  23 +import { use${subSimpleClassName}GridFormSchema, use${subSimpleClassName}GridColumns } from '../data';
  24 +import { isEmpty } from '@vben/utils';
  25 +#else
  26 +#if ($subTable.subJoinMany) ## 一对多
  27 +import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}';
  28 +#else
  29 +import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${table.businessName}';
  30 +#end
  31 +import { use${subSimpleClassName}GridColumns } from '../data';
  32 +#end
  33 +
  34 +const props = defineProps<{
  35 + ${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
  36 +}>()
  37 +
  38 +#if ($table.templateType == 11) ## erp
  39 +const [FormModal, formModalApi] = useVbenModal({
  40 + connectedComponent: ${subSimpleClassName}Form,
  41 + destroyOnClose: true,
  42 +});
  43 +
  44 +/** 创建${subTable.classComment} */
  45 +function handleCreate() {
  46 + if (!props.${subJoinColumn.javaField}){
  47 + ElMessage.warning("请先选择一个${table.classComment}!")
  48 + return
  49 + }
  50 + formModalApi.setData({${subJoinColumn.javaField}: props.${subJoinColumn.javaField}}).open();
  51 +}
  52 +
  53 +/** 编辑${subTable.classComment} */
  54 +function handleEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
  55 + formModalApi.setData(row).open();
  56 +}
  57 +
  58 +/** 删除${subTable.classComment} */
  59 +async function handleDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
  60 + const loadingInstance = ElLoading.service({
  61 + text: $t('ui.actionMessage.deleting', [row.id]),
  62 + background: 'rgba(0, 0, 0, 0.7)',
  63 + });
  64 + try {
  65 + await delete${subSimpleClassName}(row.id as number);
  66 + ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.id]));
  67 + onRefresh();
  68 + } finally {
  69 + loadingInstance.close();
  70 + }
  71 +}
  72 +
  73 +#if ($deleteBatchEnable)
  74 +/** 批量删除${subTable.classComment} */
  75 +async function handleDeleteBatch() {
  76 + const loadingInstance = ElLoading.service({
  77 + text: $t('ui.actionMessage.deleting'),
  78 + background: 'rgba(0, 0, 0, 0.7)',
  79 + });
  80 + try {
  81 + await delete${subSimpleClassName}List(checkedIds.value);
  82 + ElMessage.success($t('ui.actionMessage.deleteSuccess'));
  83 + onRefresh();
  84 + } finally {
  85 + loadingInstance.close();
  86 + }
  87 +}
  88 +
  89 +const checkedIds = ref<number[]>([])
  90 +function handleRowCheckboxChange({
  91 + records,
  92 +}: {
  93 + records: ${simpleClassName}Api.${subSimpleClassName}[];
  94 +}) {
  95 + checkedIds.value = records.map((item) => item.id);
  96 +}
  97 +#end
  98 +
  99 +#end
  100 +const [Grid, gridApi] = useVbenVxeGrid({
  101 +#if ($table.templateType == 11)
  102 + formOptions: {
  103 + schema: use${subSimpleClassName}GridFormSchema(),
  104 + },
  105 +#end
  106 + gridOptions: {
  107 +#if ($table.templateType == 11)
  108 + columns: use${subSimpleClassName}GridColumns(),
  109 + proxyConfig: {
  110 + ajax: {
  111 + query: async ({ page }, formValues) => {
  112 + if (!props.${subJoinColumn.javaField}){
  113 + return []
  114 + }
  115 + return await get${subSimpleClassName}Page({
  116 + pageNo: page.currentPage,
  117 + pageSize: page.pageSize,
  118 + ${subJoinColumn.javaField}: props.${subJoinColumn.javaField},
  119 + ...formValues,
  120 + });
  121 + },
  122 + },
  123 + },
  124 + pagerConfig: {
  125 + enabled: true,
  126 + },
  127 + toolbarConfig: {
  128 + refresh: { code: 'query' },
  129 + search: true,
  130 + },
  131 +#else
  132 + columns: use${subSimpleClassName}GridColumns(),
  133 + pagerConfig: {
  134 + nabled: false,
  135 + },
  136 + toolbarConfig: {
  137 + enabled: false,
  138 + },
  139 +#end
  140 + height: '600px',
  141 + rowConfig: {
  142 + keyField: 'id',
  143 + isHover: true,
  144 + },
  145 + } as VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>,
  146 + #if (${table.templateType} == 11 && $deleteBatchEnable)
  147 + gridEvents:{
  148 + checkboxAll: handleRowCheckboxChange,
  149 + checkboxChange: handleRowCheckboxChange,
  150 + }
  151 + #end
  152 +});
  153 +
  154 +/** 刷新表格 */
  155 +async function onRefresh() {
  156 +#if ($table.templateType == 11) ## erp
  157 + await gridApi.query();
  158 +#else
  159 + #if ($subTable.subJoinMany) ## 一对多
  160 + await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
  161 + #else
  162 + await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
  163 + #end
  164 +#end
  165 +}
  166 +
  167 +/** 监听主表的关联字段的变化,加载对应的子表数据 */
  168 +watch(
  169 + () => props.${subJoinColumn.javaField},
  170 + async (val) => {
  171 + if (!val) {
  172 + return;
  173 + }
  174 + await nextTick();
  175 + await onRefresh()
  176 + },
  177 + { immediate: true },
  178 +);
  179 +</script>
  180 +
  181 +<template>
  182 + #if ($table.templateType == 11) ## erp
  183 + <FormModal @success="onRefresh" />
  184 + <Grid table-title="${subTable.classComment}列表">
  185 + <template #toolbar-tools>
  186 + <TableAction
  187 + :actions="[
  188 + {
  189 + label: $t('ui.actionTitle.create', ['${table.classComment}']),
  190 + type: 'primary',
  191 + icon: ACTION_ICON.ADD,
  192 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:create'],
  193 + onClick: handleCreate,
  194 + },
  195 + #if ($table.templateType == 11 && $deleteBatchEnable)
  196 + {
  197 + label: $t('ui.actionTitle.deleteBatch'),
  198 + type: 'danger',
  199 + icon: ACTION_ICON.DELETE,
  200 + disabled: isEmpty(checkedIds),
  201 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:delete'],
  202 + onClick: handleDeleteBatch,
  203 + },
  204 + #end
  205 + ]"
  206 + />
  207 + </template>
  208 + <template #actions="{ row }">
  209 + <TableAction
  210 + :actions="[
  211 + {
  212 + label: $t('common.edit'),
  213 + type: 'text',
  214 + icon: ACTION_ICON.EDIT,
  215 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:update'],
  216 + onClick: handleEdit.bind(null, row),
  217 + },
  218 + {
  219 + label: $t('common.delete'),
  220 + type: 'danger',
  221 + text: true,
  222 + icon: ACTION_ICON.DELETE,
  223 + auth: ['${table.moduleName}:${simpleClassName_strikeCase}:delete'],
  224 + popConfirm: {
  225 + title: $t('ui.actionMessage.deleteConfirm', [row.id]),
  226 + confirm: handleDelete.bind(null, row),
  227 + },
  228 + },
  229 + ]"
  230 + />
  231 + </template>
  232 + </Grid>
  233 + #else
  234 + <Grid table-title="${subTable.classComment}列表" />
  235 + #end
  236 +</template>
... ...
yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_inner.vue.vm 0 → 100644
  1 +## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
  2 +## 1)inner 使用 list 不分页,erp 使用 page 分页
  3 +## 2)erp 支持单个子表的新增、修改、删除,inner 不支持
  4 +#parse("codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm")
0 5 \ No newline at end of file
... ...