【代码优化】代码生成: vue3_vben5_antd schema 主子表标准模式和内嵌模式模板完成

This commit is contained in:
puhui999 2025-04-17 18:42:05 +08:00
parent dfcbcf09d4
commit e1fa4e1a70
8 changed files with 404 additions and 395 deletions

View File

@ -202,6 +202,9 @@ export function useGridColumns(
onActionClick?: OnActionClickFn<${simpleClassName}Api.${simpleClassName}>,
): VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>['columns'] {
return [
#if ($table.templateType == 12) ## 内嵌情况
{ type: 'expand', width: 80, slots: { content: 'expand_content' } },
#end
#foreach($column in $columns)
#if ($column.listOperationResult)
#set ($dictType = $column.dictType)
@ -274,6 +277,7 @@ export function useGridColumns(
#set ($subColumns = $subColumnsList.get($index))##当前字段数组
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn = $subJoinColumns.get($index))##当前 join 字段
#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
// ==================== 子表($subTable.classComment ====================
#if ($table.templateType == 11) ## erp 情况
/** 新增/修改的表单 */
@ -409,9 +413,6 @@ export function use${subSimpleClassName}GridColumns(
props: { type: DICT_TYPE.$dictType.toUpperCase() },
},
#end
#if (${table.templateType} == 2 && $column.id == $treeNameColumn.id)## 树表特有:标记树节点列
treeNode: true,
#end
},
#end
#end
@ -426,30 +427,18 @@ export function use${subSimpleClassName}GridColumns(
cellRender: {
attrs: {
nameField: '${columns[0].javaField}',
nameTitle: '${table.classComment}',
nameTitle: '${subTable.classComment}',
onClick: onActionClick,
},
name: 'CellOperation',
options: [
#if (${table.templateType} == 2)## 树表特有操作
{
code: 'append',
text: '新增下级',
show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:create']),
},
#end
{
code: 'edit',
show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:update']),
show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:update']),
},
{
code: 'delete',
show: hasAccessByCodes(['${table.moduleName}:${simpleClassName_strikeCase}:delete']),
#if (${table.templateType} == 2)## 树表禁止删除带有子节点的数据
disabled: (row: ${simpleClassName}Api.${simpleClassName}) => {
return !!(row.children && row.children.length > 0);
},
#end
show: hasAccessByCodes(['${subTable.moduleName}:${subSimpleClassName_strikeCase}:delete']),
},
],
},
@ -458,8 +447,8 @@ export function use${subSimpleClassName}GridColumns(
}
#else
#if ($subTable.subJoinMany) ## 一对多
/** 列表的字段 */
export function use${subSimpleClassName}GridColumns(
/** 新增/修改列表的字段 */
export function use${subSimpleClassName}GridEditColumns(
onActionClick?: OnActionClickFn<${simpleClassName}Api.${subSimpleClassName}>,
): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
return [
@ -634,5 +623,32 @@ export function use${subSimpleClassName}GridColumns(
];
}
#end
#if ($table.templateType == 12) ## 内嵌情况
/** 列表的字段 */
export function use${subSimpleClassName}GridColumns(): VxeTableGridOptions<${simpleClassName}Api.${subSimpleClassName}>['columns'] {
return [
#foreach($column in $subColumns)
#if ($column.listOperationResult)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($comment = $column.columnComment)
{
field: '${javaField}',
title: '${comment}',
minWidth: 120,
#if ($column.javaType == "LocalDateTime")## 时间类型
formatter: 'formatDateTime',
#elseif("" != $dictType)## 数据字典
cellRender: {
name: 'CellDict',
props: { type: DICT_TYPE.$dictType.toUpperCase() },
},
#end
},
#end
#end
];
}
#end
#end
#end

View File

@ -116,6 +116,7 @@ const [Modal, modalApi] = useVbenModal({
},
async onOpenChange(isOpen: boolean) {
if (!isOpen) {
formData.value = undefined;
return;
}

View File

@ -3,10 +3,17 @@ import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-tab
import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
import { Page, useVbenModal } from '@vben/common-ui';
import { Button, message } from 'ant-design-vue';
import { Button, message,Tabs } from 'ant-design-vue';
import { Download, Plus } from '@vben/icons';
import Form from './modules/form.vue';
## 特殊:主子表专属逻辑
#if ( $table.templateType == 11 || $table.templateType == 12 )
#foreach ($subSimpleClassName in $subSimpleClassNames)
import ${subSimpleClassName}List from './modules/${subSimpleClassName}List.vue'
#end
#end
import { ref, h } from 'vue';
import { $t } from '#/locales';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
@ -19,6 +26,11 @@ import { downloadByData } from '#/utils/download';
import { useGridColumns, useGridFormSchema } from './data';
#if ($table.templateType == 12) ## 内嵌情况
/** 子表的列表 */
const subTabsName = ref('$subClassNameVars.get(0)')
#end
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
destroyOnClose: true,
@ -35,7 +47,11 @@ function toggleExpand() {
/** 刷新表格 */
function onRefresh() {
#if ($table.templateType == 12) ## 内嵌情况
gridApi.reload();
#else
gridApi.query();
#end
}
/** 导出表格 */
@ -46,7 +62,7 @@ async function onExport() {
/** 创建${table.classComment} */
function onCreate() {
formModalApi.setData(null).open();
formModalApi.setData({}).open();
}
/** 编辑${table.classComment} */
@ -160,6 +176,22 @@ const [Grid, gridApi] = useVbenVxeGrid({
<FormModal @success="onRefresh" />
<Grid table-title="${table.classComment}列表">
#if ($table.templateType == 12) ## 内嵌情况
<template #expand_content="{ row }">
<!-- 子表的表单 -->
<Tabs v-model:active-key="subTabsName">
#foreach ($subTable in $subTables)
#set ($index = $foreach.count - 1)
#set ($subClassNameVar = $subClassNameVars.get($index))
#set ($subSimpleClassName = $subSimpleClassNames.get($index))
#set ($subJoinColumn_strikeCase = $subJoinColumn_strikeCases.get($index))
<Tabs.TabPane key="$subClassNameVar" tab="${subTable.classComment}" force-render>
<${subSimpleClassName}List :${subJoinColumn_strikeCase}="row?.id" />
</Tabs.TabPane>
#end
</Tabs>
</template>
#end
<template #toolbar-tools>
#if (${table.templateType} == 2)## 树表特有:展开/收缩按钮
<Button @click="toggleExpand" class="mr-2">

View File

@ -1,204 +1,193 @@
#set ($subTable = $subTables.get($subIndex))##当前表
#set ($subColumns = $subColumnsList.get($subIndex))##当前字段数组
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subClassNameVar = $subClassNameVars.get($subIndex))
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
<script lang="ts" setup>
import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
import { computed, ref, h, onMounted,watch,nextTick } from 'vue';
import { $t } from '#/locales';
#if ($subTable.subJoinMany) ## 一对多
import { Plus } from "@vben/icons";
import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
import type { OnActionClickParams } from '#/adapter/vxe-table';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { use${subSimpleClassName}GridColumns } from '../data';
import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
#else
import { useVbenForm } from '#/adapter/form';
import { use${subSimpleClassName}FormSchema } from '../data';
import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
#end
const props = defineProps<{
${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
}>()
#if ($subTable.subJoinMany) ## 一对多
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
}
}
const [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
gridOptions: {
columns: use${subSimpleClassName}GridColumns(onActionClick),
border: true,
showOverflow: true,
autoResize: true,
keepSource: true,
rowConfig: {
keyField: 'id',
},
pagerConfig: {
enabled: false,
},
toolbarConfig: {
enabled: false,
},
},
});
/** 删除${subTable.classComment} */
const onDelete = async (row: ${simpleClassName}Api.${subSimpleClassName}) => {
await ${subClassNameVar}GridApi.grid.remove(row);
}
/** 添加${subTable.classComment} */
const handleAdd = async () => {
await ${subClassNameVar}GridApi.grid.insertAt({} as ${simpleClassName}Api.${subSimpleClassName}, -1);
}
/** 提供获取表格数据的方法供父组件调用 */
defineExpose({
getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
return [
...${subClassNameVar}GridApi.grid.getData(),
...${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
delete row.id;
return row;
}),
];
},
});
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.${subJoinColumn.javaField},
async (val) => {
if (!val) {
return;
}
await nextTick();
await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
},
);
#else
const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
layout: 'horizontal',
schema: use${subSimpleClassName}FormSchema(),
showDefaultActions: false
});
/** 暴露出表单校验方法和表单值获取方法 */
defineExpose({
validate: async () => {
const { valid } = await ${subClassNameVar}FormApi.validate();
return valid;
},
getValues: ${subClassNameVar}FormApi.getValues,
});
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.${subJoinColumn.javaField},
async (val) => {
if (!val) {
return;
}
await nextTick();
await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
},
);
#end
</script>
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($dictType = $column.dictType)
#set ($javaField = $column.javaField)
#set ($javaType = $column.javaType)
#set ($AttrName = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment = $column.columnComment)
#set ($dictMethod = "getDictOptions")## 计算使用哪个 dict 字典方法
#if ($javaType == "Integer" || $javaType == "Long" || $javaType == "Byte" || $javaType == "Short")
#set ($dictMethod = "getIntDictOptions")
#elseif ($javaType == "String")
#set ($dictMethod = "getStrDictOptions")
#elseif ($javaType == "Boolean")
#set ($dictMethod = "getBoolDictOptions")
#end
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" placeholder="请输入${comment}" />
</el-form-item>
#elseif($column.htmlType == "imageUpload")## 图片上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadImg v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "fileUpload")## 文件上传
<el-form-item label="${comment}" prop="${javaField}">
<UploadFile v-model="formData.${javaField}" />
</el-form-item>
#elseif($column.htmlType == "editor")## 文本编辑器
<el-form-item label="${comment}" prop="${javaField}">
<Editor v-model="formData.${javaField}" height="150px" />
</el-form-item>
#elseif($column.htmlType == "select")## 下拉框
<el-form-item label="${comment}" prop="${javaField}">
<el-select v-model="formData.${javaField}" placeholder="请选择${comment}">
#if ("" != $dictType)## 有数据字典
<el-option
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-option label="请选择字典生成" value="" />
#end
</el-select>
</el-form-item>
#elseif($column.htmlType == "checkbox")## 多选框
<el-form-item label="${comment}" prop="${javaField}">
<el-checkbox-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-checkbox
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
#else##没数据字典
<el-checkbox label="请选择字典生成" />
#end
</el-checkbox-group>
</el-form-item>
#elseif($column.htmlType == "radio")## 单选框
<el-form-item label="${comment}" prop="${javaField}">
<el-radio-group v-model="formData.${javaField}">
#if ("" != $dictType)## 有数据字典
<el-radio
v-for="dict in $dictMethod(DICT_TYPE.$dictType.toUpperCase())"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
#else##没数据字典
<el-radio value="1">请选择字典生成</el-radio>
#end
</el-radio-group>
</el-form-item>
#elseif($column.htmlType == "datetime")## 时间框
<el-form-item label="${comment}" prop="${javaField}">
<el-date-picker
v-model="formData.${javaField}"
type="date"
value-format="x"
placeholder="选择${comment}"
/>
</el-form-item>
#elseif($column.htmlType == "textarea")## 文本框
<el-form-item label="${comment}" prop="${javaField}">
<el-input v-model="formData.${javaField}" type="textarea" placeholder="请输入${comment}" />
</el-form-item>
#end
#if ($subTable.subJoinMany) ## 一对多
<${subSimpleClassName}Grid class="mx-4">
#foreach($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#set ($javaField = $column.javaField)
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.htmlType == "input" && !$column.primaryKey)## 忽略主键,不用在表单里
<template #${javaField}="{ row }">
<Input v-model:value="row.${javaField}" />
</template>
#elseif($column.htmlType == "imageUpload")## 图片上传
<template #${javaField}="{ row }">
<UploadImg v-model:value="row.${javaField}" />
</template>
#elseif($column.htmlType == "fileUpload")## 文件上传
<template #${javaField}="{ row }">
<UploadFile v-model:value="row.${javaField}" />
</template>
#elseif($column.htmlType == "editor")## 文本编辑器
<template #${javaField}="{ row }">
<Textarea v-model:value="row.${javaField}" />
</template>
#elseif($column.htmlType == "select")## 下拉框
<template #${javaField}="{ row, column }">
<Select v-model:value="row.${javaField}" class="w-full">
<Select.Option v-for="option in column.params.options" :key="option.value" :value="option.value">
{{ option.label }}
</Select.Option>
</Select>
</template>
#elseif($column.htmlType == "checkbox")## 多选框
<template #${javaField}="{ row, column }">
<CheckboxGroup v-model:value="row.${javaField}" :options="column.params.options" />
</template>
#elseif($column.htmlType == "radio")## 单选框
<template #${javaField}="{ row, column }">
<RadioGroup v-model:value="row.${javaField}" :options="column.params.options" />
</template>
#elseif($column.htmlType == "datetime")## 时间框
<template #${javaField}="{ row }">
<DatePicker
v-model:value="row.${javaField}"
:showTime="true"
format="YYYY-MM-DD HH:mm:ss"
valueFormat='x'
/>
</template>
#elseif($column.htmlType == "textarea")## 文本框
<template #${javaField}="{ row }">
<Textarea v-model:value="row.${javaField}" />
</template>
#end
#end
#end
</${subSimpleClassName}Grid>
<div class="flex justify-center">
<Button :icon="h(Plus)" type="primary" ghost @click="handleAdd" v-access:code="['${subTable.moduleName}:${simpleClassName_strikeCase}:create']">
{{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
</Button>
</div>
#else
<${subSimpleClassName}Form class="mx-4" />
#end
#end
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中1修改时的数据加载2提交的按钮禁用
const formType = ref('') // 表单的类型create - 新增update - 修改
const formData = ref({
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
})
const formRules = reactive({
#foreach ($column in $subColumns)
#if (($column.createOperation || $column.updateOperation) && !$column.nullable && !${column.primaryKey})## 创建或者更新操作 && 要求非空 && 非主键
#set($comment=$column.columnComment)
$column.javaField: [{ required: true, message: '${comment}不能为空', trigger: #if($column.htmlType == 'select')'change'#else'blur'#end }],
#end
#end
})
const formRef = ref() // 表单 Ref
/** 打开弹窗 */
const open = async (type: string, id?: number, ${subJoinColumn.javaField}: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
formData.value.${subJoinColumn.javaField} = ${subJoinColumn.javaField}
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await ${simpleClassName}Api.get${subSimpleClassName}(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = formData.value
if (formType.value === 'create') {
await ${simpleClassName}Api.create${subSimpleClassName}(data)
message.success(t('common.createSuccess'))
} else {
await ${simpleClassName}Api.update${subSimpleClassName}(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
#foreach ($column in $subColumns)
#if ($column.createOperation || $column.updateOperation)
#if ($column.htmlType == "checkbox")
$column.javaField: [],
#else
$column.javaField: undefined,
#end
#end
#end
}
formRef.value?.resetFields()
}
</script>

View File

@ -1,2 +1,2 @@
## 主表的 normal 和 inner 使用相同的 form 表单
#parse("codegen/vue3/views/components/form_sub_normal.vue.vm")
#parse("codegen/vue3_vben5_antd/schema/views/modules/form_sub_normal.vue.vm")

View File

@ -15,7 +15,7 @@ import { Plus } from "@vben/icons";
import { Button, Tabs, Checkbox, Input, Textarea, Select,RadioGroup,CheckboxGroup, DatePicker } from 'ant-design-vue';
import type { OnActionClickParams } from '#/adapter/vxe-table';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { use${subSimpleClassName}GridColumns } from '../data';
import { use${subSimpleClassName}GridEditColumns } from '../data';
import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
#else
import { useVbenForm } from '#/adapter/form';
@ -43,7 +43,7 @@ function onActionClick({
const [${subSimpleClassName}Grid, ${subClassNameVar}GridApi] = useVbenVxeGrid({
gridOptions: {
columns: use${subSimpleClassName}GridColumns(onActionClick),
columns: use${subSimpleClassName}GridEditColumns(onActionClick),
border: true,
showOverflow: true,
autoResize: true,
@ -73,13 +73,21 @@ const handleAdd = async () => {
/** 提供获取表格数据的方法供父组件调用 */
defineExpose({
getData: (): ${simpleClassName}Api.${subSimpleClassName}[] => {
return [
...${subClassNameVar}GridApi.grid.getData(),
...${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
delete row.id;
return row;
}),
];
// 获取当前数据,但排除已删除的记录
const allData = ${subClassNameVar}GridApi.grid.getData();
const removedData = ${subClassNameVar}GridApi.grid.getRemoveRecords();
const removedIds = new Set(removedData.map((row) => row.id));
// 过滤掉已删除的记录
const currentData = allData.filter((row) => !removedIds.has(row.id));
// 获取新插入的记录并移除id
const insertedData = ${subClassNameVar}GridApi.grid.getInsertRecords().map((row) => {
delete row.id;
return row;
});
return [...currentData, ...insertedData];
},
});
@ -94,6 +102,7 @@ watch(
await nextTick();
await ${subClassNameVar}GridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
},
{ immediate: true },
);
#else
const [${subSimpleClassName}Form, ${subClassNameVar}FormApi] = useVbenForm({
@ -122,6 +131,7 @@ watch(
await nextTick();
await ${subClassNameVar}FormApi.setValues(await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
},
{ immediate: true },
);
#end
</script>

View File

@ -3,182 +3,143 @@
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName = $subSimpleClassNames.get($subIndex))
#set ($subJoinColumn = $subJoinColumns.get($subIndex))##当前 join 字段
#set ($subSimpleClassName_strikeCase = $subSimpleClassName_strikeCases.get($index))
#set ($SubJoinColumnName = $subJoinColumn.javaField.substring(0,1).toUpperCase() + ${subJoinColumn.javaField.substring(1)})##首字母大写
<template>
<!-- 列表 -->
<ContentWrap>
#if ($table.templateType == 11)
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['${permissionPrefix}:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
#end
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
#foreach($column in $subColumns)
#if ($column.listOperationResult)
#set ($dictType=$column.dictType)
#set ($javaField = $column.javaField)
#set ($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
#set ($comment=$column.columnComment)
#if ( $column.id == $subJoinColumn.id) ## 特殊:忽略主子表的 join 字段,不用填写
#elseif ($column.javaType == "LocalDateTime")## 时间类型
<el-table-column
label="${comment}"
align="center"
prop="${javaField}"
:formatter="dateFormatter"
width="180px"
/>
#elseif($column.dictType && "" != $column.dictType)## 数据字典
<el-table-column label="${comment}" align="center" prop="${javaField}">
<template #default="scope">
<dict-tag :type="DICT_TYPE.$dictType.toUpperCase()" :value="scope.row.${column.javaField}" />
</template>
</el-table-column>
#else
<el-table-column label="${comment}" align="center" prop="${javaField}" />
#end
#end
#end
#if ($table.templateType == 11)
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['${permissionPrefix}:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['${permissionPrefix}:delete']"
>
删除
</el-button>
</template>
</el-table-column>
#end
</el-table>
#if ($table.templateType == 11)
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
#end
</ContentWrap>
#if ($table.templateType == 11)
<!-- 表单弹窗:添加/修改 -->
<${subSimpleClassName}Form ref="formRef" @success="getList" />
#end
</template>
<script setup lang="ts">
import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import { ${simpleClassName}Api } from '@/api/${table.moduleName}/${table.businessName}'
#if ($table.templateType == 11)
import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue'
#end
<script lang="ts" setup>
import type { OnActionClickParams, VxeTableGridOptions } from '#/adapter/vxe-table';
import type { ${simpleClassName}Api } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
import { useVbenModal } from '@vben/common-ui';
import { Button, message } from 'ant-design-vue';
import { Plus } from '@vben/icons';
import { ref, h, nextTick,watch } from 'vue';
import { $t } from '#/locales';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
#if ($table.templateType == 11) ## erp
import ${subSimpleClassName}Form from './${subSimpleClassName}Form.vue';
#end
import { use${subSimpleClassName}GridColumns } from '../data';
#if ($subTable.subJoinMany) ## 一对多
import { get${subSimpleClassName}ListBy${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
#else
import { get${subSimpleClassName}By${SubJoinColumnName} } from '#/api/${table.moduleName}/${simpleClassName_strikeCase}';
#end
const props = defineProps<{
${subJoinColumn.javaField}?: number // ${subJoinColumn.columnComment}(主表的关联字段)
${subJoinColumn.javaField}?: any // ${subJoinColumn.columnComment}(主表的关联字段)
}>()
const loading = ref(false) // 列表的加载中
const list = ref([]) // 列表的数据
#if ($table.templateType == 11)
const total = ref(0) // 列表的总页数
const queryParams = reactive({
pageNo: 1,
pageSize: 10,
${subJoinColumn.javaField}: undefined as unknown
})
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.${subJoinColumn.javaField},
(val: number) => {
if (!val) {
return
}
queryParams.${subJoinColumn.javaField} = val
handleQuery()
},
{ immediate: true, deep: true }
)
#end
#if ($table.templateType == 11) ## erp
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: ${subSimpleClassName}Form,
destroyOnClose: true,
});
/** 查询列表 */
const getList = async () => {
loading.value = true
/** 创建${subTable.classComment} */
function onCreate() {
formModalApi.setData({}).open();
}
/** 编辑${subTable.classComment} */
function onEdit(row: ${simpleClassName}Api.${subSimpleClassName}) {
formModalApi.setData(row).open();
}
/** 删除${subTable.classComment} */
async function onDelete(row: ${simpleClassName}Api.${subSimpleClassName}) {
const hideLoading = message.loading({
content: $t('ui.actionMessage.deleting', [row.id]),
duration: 0,
key: 'action_process_msg',
});
try {
await delete${subSimpleClassName}(row.id as number);
message.success({
content: $t('ui.actionMessage.deleteSuccess', [row.id]),
key: 'action_process_msg',
});
onRefresh();
} catch {
hideLoading();
}
}
/** 表格操作按钮的回调函数 */
function onActionClick({
code,
row,
}: OnActionClickParams<${simpleClassName}Api.${subSimpleClassName}>) {
switch (code) {
case 'delete': {
onDelete(row);
break;
}
case 'edit': {
onEdit(row);
break;
}
}
}
#end
const [Grid, gridApi] = useVbenVxeGrid({
gridOptions: {
#if ($table.templateType == 11)
const data = await ${simpleClassName}Api.get${subSimpleClassName}Page(queryParams)
list.value = data.list
total.value = data.total
columns: use${subSimpleClassName}GridColumns(onActionClick),
#else
#if ( $subTable.subJoinMany )
list.value = await ${simpleClassName}Api.get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField})
columns: use${subSimpleClassName}GridColumns(),
#end
height: 'auto',
rowConfig: {
keyField: 'id',
isHover: true,
},
pagerConfig: {
enabled: false,
},
toolbarConfig: {
enabled: false,
},
} as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>,
});
/** 刷新表格 */
const onRefresh = async ()=> {
#if ($subTable.subJoinMany) ## 一对多
await gridApi.grid.loadData(await get${subSimpleClassName}ListBy${SubJoinColumnName}(props.${subJoinColumn.javaField}!));
#else
const data = await ${simpleClassName}Api.get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField})
if (!data) {
return
}
list.value.push(data)
await gridApi.grid.loadData([await get${subSimpleClassName}By${SubJoinColumnName}(props.${subJoinColumn.javaField}!)]);
#end
#end
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
#if ($table.templateType == 11)
/** 监听主表的关联字段的变化,加载对应的子表数据 */
watch(
() => props.${subJoinColumn.javaField},
async (val) => {
if (!val) {
return;
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
if (!props.${subJoinColumn.javaField}) {
message.error('请选择一个${table.classComment}')
return
}
formRef.value.open(type, id, props.${subJoinColumn.javaField})
}
await nextTick();
await onRefresh()
},
{ immediate: true },
);
</script>
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await ${simpleClassName}Api.delete${subSimpleClassName}(id)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
} catch {}
}
#end
#if ($table.templateType != 11)
/** 初始化 **/
onMounted(() => {
getList()
})
#end
</script>
<template>
<div class="mx-4">
#if ($table.templateType == 11) ## erp
<FormModal @success="onRefresh" />
<Grid table-title="${subTable.classComment}列表">
<template #toolbar-tools>
<Button :icon="h(Plus)" type="primary" @click="onCreate" v-access:code="['${subTable.moduleName}:${subSimpleClassName_strikeCase}:create']">
{{ $t('ui.actionTitle.create', ['${subTable.classComment}']) }}
</Button>
</template>
</Grid>
#else
<Grid table-title="${subTable.classComment}列表" />
#end
</div>
</template>

View File

@ -1,4 +1,4 @@
## 子表的 erp 和 inner 使用相似的 list 列表,差异主要两点:
## 1inner 使用 list 不分页erp 使用 page 分页
## 2erp 支持单个子表的新增、修改、删除inner 不支持
#parse("codegen/vue3/views/components/list_sub_erp.vue.vm")
#parse("codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm")