Commit 69486939d5b48aea0902de3ec1b9a79a6a301333

Authored by puhui999
1 parent be416b7d

【功能新增】INFRA: vben next 单表代码生成

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