feat: 【ele】新增主子表 normal 代码生成示例
							parent
							
								
									78c7e9aec2
								
							
						
					
					
						commit
						50ef308a8a
					
				|  | @ -0,0 +1,208 @@ | |||
| import type { VbenFormSchema } from '#/adapter/form'; | ||||
| import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||
| import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; | ||||
| 
 | ||||
| /** 新增/修改的表单 */ | ||||
| export function useFormSchema(): VbenFormSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       fieldName: 'id', | ||||
|       component: 'Input', | ||||
|       dependencies: { | ||||
|         triggerFields: [''], | ||||
|         show: () => false, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'name', | ||||
|       label: '名字', | ||||
|       rules: 'required', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入名字', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'sex', | ||||
|       label: '性别', | ||||
|       rules: 'required', | ||||
|       component: 'RadioGroup', | ||||
|       componentProps: { | ||||
|         options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | ||||
|         buttonStyle: 'solid', | ||||
|         optionType: 'button', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'birthday', | ||||
|       label: '出生日期', | ||||
|       rules: 'required', | ||||
|       component: 'DatePicker', | ||||
|       componentProps: { | ||||
|         showTime: true, | ||||
|         format: 'YYYY-MM-DD HH:mm:ss', | ||||
|         valueFormat: 'x', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'description', | ||||
|       label: '简介', | ||||
|       rules: 'required', | ||||
|       component: 'RichTextarea', | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 列表的搜索表单 */ | ||||
| export function useGridFormSchema(): VbenFormSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       fieldName: 'name', | ||||
|       label: '名字', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         allowClear: true, | ||||
|         placeholder: '请输入名字', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'sex', | ||||
|       label: '性别', | ||||
|       component: 'Select', | ||||
|       componentProps: { | ||||
|         allowClear: true, | ||||
|         options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), | ||||
|         placeholder: '请选择性别', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'description', | ||||
|       label: '简介', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         allowClear: true, | ||||
|         placeholder: '请输入简介', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'createTime', | ||||
|       label: '创建时间', | ||||
|       component: 'RangePicker', | ||||
|       componentProps: { | ||||
|         ...getRangePickerDefaultProps(), | ||||
|         allowClear: true, | ||||
|       }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| /** 列表的字段 */ | ||||
| export function useGridColumns(): VxeTableGridOptions<Demo03StudentApi.Demo03Student>['columns'] { | ||||
|   return [ | ||||
|     { type: 'checkbox', width: 40 }, | ||||
|     { | ||||
|       field: 'id', | ||||
|       title: '编号', | ||||
|       minWidth: 120, | ||||
|     }, | ||||
|     { | ||||
|       field: 'name', | ||||
|       title: '名字', | ||||
|       minWidth: 120, | ||||
|     }, | ||||
|     { | ||||
|       field: 'sex', | ||||
|       title: '性别', | ||||
|       minWidth: 120, | ||||
|       cellRender: { | ||||
|         name: 'CellDict', | ||||
|         props: { type: DICT_TYPE.SYSTEM_USER_SEX }, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       field: 'birthday', | ||||
|       title: '出生日期', | ||||
|       minWidth: 120, | ||||
|       formatter: 'formatDateTime', | ||||
|     }, | ||||
|     { | ||||
|       field: 'description', | ||||
|       title: '简介', | ||||
|       minWidth: 120, | ||||
|     }, | ||||
|     { | ||||
|       field: 'createTime', | ||||
|       title: '创建时间', | ||||
|       minWidth: 120, | ||||
|       formatter: 'formatDateTime', | ||||
|     }, | ||||
|     { | ||||
|       title: '操作', | ||||
|       width: 200, | ||||
|       fixed: 'right', | ||||
|       slots: { default: 'actions' }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| // ==================== 子表(学生课程) ====================
 | ||||
| 
 | ||||
| /** 新增/修改列表的字段 */ | ||||
| export function useDemo03CourseGridEditColumns(): VxeTableGridOptions<Demo03StudentApi.Demo03Course>['columns'] { | ||||
|   return [ | ||||
|     { | ||||
|       field: 'name', | ||||
|       title: '名字', | ||||
|       minWidth: 120, | ||||
|       slots: { default: 'name' }, | ||||
|     }, | ||||
|     { | ||||
|       field: 'score', | ||||
|       title: '分数', | ||||
|       minWidth: 120, | ||||
|       slots: { default: 'score' }, | ||||
|     }, | ||||
|     { | ||||
|       title: '操作', | ||||
|       width: 200, | ||||
|       fixed: 'right', | ||||
|       slots: { default: 'actions' }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
| 
 | ||||
| // ==================== 子表(学生班级) ====================
 | ||||
| 
 | ||||
| /** 新增/修改的表单 */ | ||||
| export function useDemo03GradeFormSchema(): VbenFormSchema[] { | ||||
|   return [ | ||||
|     { | ||||
|       fieldName: 'id', | ||||
|       component: 'Input', | ||||
|       dependencies: { | ||||
|         triggerFields: [''], | ||||
|         show: () => false, | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'name', | ||||
|       label: '名字', | ||||
|       rules: 'required', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入名字', | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       fieldName: 'teacher', | ||||
|       label: '班主任', | ||||
|       rules: 'required', | ||||
|       component: 'Input', | ||||
|       componentProps: { | ||||
|         placeholder: '请输入班主任', | ||||
|       }, | ||||
|     }, | ||||
|   ]; | ||||
| } | ||||
|  | @ -0,0 +1,185 @@ | |||
| <script lang="ts" setup> | ||||
| import type { VxeTableGridOptions } from '#/adapter/vxe-table'; | ||||
| import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { ref } from 'vue'; | ||||
| 
 | ||||
| import { Page, useVbenModal } from '@vben/common-ui'; | ||||
| import { downloadFileFromBlobPart, isEmpty } from '@vben/utils'; | ||||
| 
 | ||||
| import { ElLoading, ElMessage } from 'element-plus'; | ||||
| 
 | ||||
| import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table'; | ||||
| import { | ||||
|   deleteDemo03Student, | ||||
|   deleteDemo03StudentList, | ||||
|   exportDemo03Student, | ||||
|   getDemo03StudentPage, | ||||
| } from '#/api/infra/demo/demo03/normal'; | ||||
| import { $t } from '#/locales'; | ||||
| 
 | ||||
| import { useGridColumns, useGridFormSchema } from './data'; | ||||
| import Form from './modules/form.vue'; | ||||
| 
 | ||||
| const [FormModal, formModalApi] = useVbenModal({ | ||||
|   connectedComponent: Form, | ||||
|   destroyOnClose: true, | ||||
| }); | ||||
| 
 | ||||
| /** 刷新表格 */ | ||||
| function onRefresh() { | ||||
|   gridApi.query(); | ||||
| } | ||||
| 
 | ||||
| /** 创建学生 */ | ||||
| function handleCreate() { | ||||
|   formModalApi.setData({}).open(); | ||||
| } | ||||
| 
 | ||||
| /** 编辑学生 */ | ||||
| function handleEdit(row: Demo03StudentApi.Demo03Student) { | ||||
|   formModalApi.setData(row).open(); | ||||
| } | ||||
| 
 | ||||
| /** 删除学生 */ | ||||
| async function handleDelete(row: Demo03StudentApi.Demo03Student) { | ||||
|   const loadingInstance = ElLoading.service({ | ||||
|     text: $t('ui.actionMessage.deleting', [row.id]), | ||||
|     background: 'rgba(0, 0, 0, 0.7)', | ||||
|   }); | ||||
|   try { | ||||
|     await deleteDemo03Student(row.id as number); | ||||
|     ElMessage.success($t('ui.actionMessage.deleteSuccess', [row.id])); | ||||
|     onRefresh(); | ||||
|   } finally { | ||||
|     loadingInstance.close(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 批量删除学生 */ | ||||
| async function handleDeleteBatch() { | ||||
|   const loadingInstance = ElLoading.service({ | ||||
|     text: $t('ui.actionMessage.deleting'), | ||||
|     background: 'rgba(0, 0, 0, 0.7)', | ||||
|   }); | ||||
|   try { | ||||
|     await deleteDemo03StudentList(checkedIds.value); | ||||
|     ElMessage.success($t('ui.actionMessage.deleteSuccess')); | ||||
|     onRefresh(); | ||||
|   } finally { | ||||
|     loadingInstance.close(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const checkedIds = ref<number[]>([]); | ||||
| function handleRowCheckboxChange({ | ||||
|   records, | ||||
| }: { | ||||
|   records: Demo03StudentApi.Demo03Student[]; | ||||
| }) { | ||||
|   checkedIds.value = records.map((item) => item.id); | ||||
| } | ||||
| 
 | ||||
| /** 导出表格 */ | ||||
| async function handleExport() { | ||||
|   const data = await exportDemo03Student(await gridApi.formApi.getValues()); | ||||
|   downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | ||||
| } | ||||
| 
 | ||||
| const [Grid, gridApi] = useVbenVxeGrid({ | ||||
|   formOptions: { | ||||
|     schema: useGridFormSchema(), | ||||
|   }, | ||||
|   gridOptions: { | ||||
|     columns: useGridColumns(), | ||||
|     height: 'auto', | ||||
|     pagerConfig: { | ||||
|       enabled: true, | ||||
|     }, | ||||
|     proxyConfig: { | ||||
|       ajax: { | ||||
|         query: async ({ page }, formValues) => { | ||||
|           return await getDemo03StudentPage({ | ||||
|             pageNo: page.currentPage, | ||||
|             pageSize: page.pageSize, | ||||
|             ...formValues, | ||||
|           }); | ||||
|         }, | ||||
|       }, | ||||
|     }, | ||||
|     rowConfig: { | ||||
|       keyField: 'id', | ||||
|       isHover: true, | ||||
|     }, | ||||
|     toolbarConfig: { | ||||
|       refresh: { code: 'query' }, | ||||
|       search: true, | ||||
|     }, | ||||
|   } as VxeTableGridOptions<Demo03StudentApi.Demo03Student>, | ||||
|   gridEvents: { | ||||
|     checkboxAll: handleRowCheckboxChange, | ||||
|     checkboxChange: handleRowCheckboxChange, | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Page auto-content-height> | ||||
|     <FormModal @success="onRefresh" /> | ||||
| 
 | ||||
|     <Grid table-title="学生列表"> | ||||
|       <template #toolbar-tools> | ||||
|         <TableAction | ||||
|           :actions="[ | ||||
|             { | ||||
|               label: $t('ui.actionTitle.create', ['学生']), | ||||
|               type: 'primary', | ||||
|               icon: ACTION_ICON.ADD, | ||||
|               auth: ['infra:demo03-student:create'], | ||||
|               onClick: handleCreate, | ||||
|             }, | ||||
|             { | ||||
|               label: $t('ui.actionTitle.export'), | ||||
|               type: 'primary', | ||||
|               icon: ACTION_ICON.DOWNLOAD, | ||||
|               auth: ['infra:demo03-student:export'], | ||||
|               onClick: handleExport, | ||||
|             }, | ||||
|             { | ||||
|               label: $t('ui.actionTitle.deleteBatch'), | ||||
|               type: 'danger', | ||||
|               icon: ACTION_ICON.DELETE, | ||||
|               disabled: isEmpty(checkedIds), | ||||
|               auth: ['infra:demo03-student:delete'], | ||||
|               onClick: handleDeleteBatch, | ||||
|             }, | ||||
|           ]" | ||||
|         /> | ||||
|       </template> | ||||
|       <template #actions="{ row }"> | ||||
|         <TableAction | ||||
|           :actions="[ | ||||
|             { | ||||
|               label: $t('common.edit'), | ||||
|               type: 'text', | ||||
|               icon: ACTION_ICON.EDIT, | ||||
|               auth: ['infra:demo03-student:update'], | ||||
|               onClick: handleEdit.bind(null, row), | ||||
|             }, | ||||
|             { | ||||
|               label: $t('common.delete'), | ||||
|               type: 'danger', | ||||
|               text: true, | ||||
|               icon: ACTION_ICON.DELETE, | ||||
|               auth: ['infra:demo03-student:delete'], | ||||
|               popConfirm: { | ||||
|                 title: $t('ui.actionMessage.deleteConfirm', [row.id]), | ||||
|                 confirm: handleDelete.bind(null, row), | ||||
|               }, | ||||
|             }, | ||||
|           ]" | ||||
|         /> | ||||
|       </template> | ||||
|     </Grid> | ||||
|   </Page> | ||||
| </template> | ||||
|  | @ -0,0 +1,116 @@ | |||
| <script lang="ts" setup> | ||||
| import type { OnActionClickParams } from '#/adapter/vxe-table'; | ||||
| import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { nextTick, watch } from 'vue'; | ||||
| 
 | ||||
| import { Plus } from '@vben/icons'; | ||||
| 
 | ||||
| import { ElButton, ElInput } from 'element-plus'; | ||||
| 
 | ||||
| import { useVbenVxeGrid } from '#/adapter/vxe-table'; | ||||
| import { getDemo03CourseListByStudentId } from '#/api/infra/demo/demo03/normal'; | ||||
| import { $t } from '#/locales'; | ||||
| 
 | ||||
| import { useDemo03CourseGridEditColumns } from '../data'; | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|   studentId?: number; // 学生编号(主表的关联字段) | ||||
| }>(); | ||||
| 
 | ||||
| /** 表格操作按钮的回调函数 */ | ||||
| function onActionClick({ | ||||
|   code, | ||||
|   row, | ||||
| }: OnActionClickParams<Demo03StudentApi.Demo03Course>) { | ||||
|   switch (code) { | ||||
|     case 'delete': { | ||||
|       onDelete(row); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const [Grid, gridApi] = useVbenVxeGrid({ | ||||
|   gridOptions: { | ||||
|     columns: useDemo03CourseGridEditColumns(onActionClick), | ||||
|     border: true, | ||||
|     showOverflow: true, | ||||
|     autoResize: true, | ||||
|     keepSource: true, | ||||
|     rowConfig: { | ||||
|       keyField: 'id', | ||||
|     }, | ||||
|     pagerConfig: { | ||||
|       enabled: false, | ||||
|     }, | ||||
|     toolbarConfig: { | ||||
|       enabled: false, | ||||
|     }, | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| /** 添加学生课程 */ | ||||
| const onAdd = async () => { | ||||
|   await gridApi.grid.insertAt({} as Demo03StudentApi.Demo03Course, -1); | ||||
| }; | ||||
| 
 | ||||
| /** 删除学生课程 */ | ||||
| const onDelete = async (row: Demo03StudentApi.Demo03Course) => { | ||||
|   await gridApi.grid.remove(row); | ||||
| }; | ||||
| 
 | ||||
| /** 提供获取表格数据的方法供父组件调用 */ | ||||
| defineExpose({ | ||||
|   getData: (): Demo03StudentApi.Demo03Course[] => { | ||||
|     const data = gridApi.grid.getData() as Demo03StudentApi.Demo03Course[]; | ||||
|     const removeRecords = | ||||
|       gridApi.grid.getRemoveRecords() as Demo03StudentApi.Demo03Course[]; | ||||
|     const insertRecords = | ||||
|       gridApi.grid.getInsertRecords() as Demo03StudentApi.Demo03Course[]; | ||||
|     return [ | ||||
|       ...data.filter( | ||||
|         (row) => !removeRecords.some((removed) => removed.id === row.id), | ||||
|       ), | ||||
|       ...insertRecords.map((row: any) => ({ ...row, id: undefined })), | ||||
|     ]; | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| /** 监听主表的关联字段的变化,加载对应的子表数据 */ | ||||
| watch( | ||||
|   () => props.studentId, | ||||
|   async (val) => { | ||||
|     if (!val) { | ||||
|       return; | ||||
|     } | ||||
|     await nextTick(); | ||||
|     await gridApi.grid.loadData( | ||||
|       await getDemo03CourseListByStudentId(props.studentId!), | ||||
|     ); | ||||
|   }, | ||||
|   { immediate: true }, | ||||
| ); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Grid class="mx-4"> | ||||
|     <template #name="{ row }"> | ||||
|       <ElInput v-model="row.name" /> | ||||
|     </template> | ||||
|     <template #score="{ row }"> | ||||
|       <ElInput v-model="row.score" /> | ||||
|     </template> | ||||
|   </Grid> | ||||
|   <div class="-mt-4 flex justify-center"> | ||||
|     <ElButton | ||||
|       :icon="Plus" | ||||
|       type="primary" | ||||
|       plain | ||||
|       @click="onAdd" | ||||
|       v-access:code="['infra:demo03-student:create']" | ||||
|     > | ||||
|       {{ $t('ui.actionTitle.create', ['学生课程']) }} | ||||
|     </ElButton> | ||||
|   </div> | ||||
| </template> | ||||
|  | @ -0,0 +1,51 @@ | |||
| <script lang="ts" setup> | ||||
| import { nextTick, watch } from 'vue'; | ||||
| 
 | ||||
| import { useVbenForm } from '#/adapter/form'; | ||||
| import { getDemo03GradeByStudentId } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { useDemo03GradeFormSchema } from '../data'; | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|   studentId?: number; // 学生编号(主表的关联字段) | ||||
| }>(); | ||||
| 
 | ||||
| const [Form, formApi] = useVbenForm({ | ||||
|   commonConfig: { | ||||
|     componentProps: { | ||||
|       class: 'w-full', | ||||
|     }, | ||||
|     formItemClass: 'col-span-2', | ||||
|     labelWidth: 80, | ||||
|   }, | ||||
|   layout: 'horizontal', | ||||
|   schema: useDemo03GradeFormSchema(), | ||||
|   showDefaultActions: false, | ||||
| }); | ||||
| 
 | ||||
| /** 暴露出表单校验方法和表单值获取方法 */ | ||||
| defineExpose({ | ||||
|   validate: async () => { | ||||
|     const { valid } = await formApi.validate(); | ||||
|     return valid; | ||||
|   }, | ||||
|   getValues: formApi.getValues, | ||||
| }); | ||||
| 
 | ||||
| /** 监听主表的关联字段的变化,加载对应的子表数据 */ | ||||
| watch( | ||||
|   () => props.studentId, | ||||
|   async (val) => { | ||||
|     if (!val) { | ||||
|       return; | ||||
|     } | ||||
|     await nextTick(); | ||||
|     await formApi.setValues(await getDemo03GradeByStudentId(props.studentId!)); | ||||
|   }, | ||||
|   { immediate: true }, | ||||
| ); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Form class="mx-4" /> | ||||
| </template> | ||||
|  | @ -0,0 +1,119 @@ | |||
| <script lang="ts" setup> | ||||
| import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { computed, ref } from 'vue'; | ||||
| 
 | ||||
| import { useVbenModal } from '@vben/common-ui'; | ||||
| 
 | ||||
| import { ElMessage, ElTabPane, ElTabs } from 'element-plus'; | ||||
| 
 | ||||
| import { useVbenForm } from '#/adapter/form'; | ||||
| import { | ||||
|   createDemo03Student, | ||||
|   getDemo03Student, | ||||
|   updateDemo03Student, | ||||
| } from '#/api/infra/demo/demo03/normal'; | ||||
| import { $t } from '#/locales'; | ||||
| 
 | ||||
| import { useFormSchema } from '../data'; | ||||
| import Demo03CourseForm from './demo03-course-form.vue'; | ||||
| import Demo03GradeForm from './demo03-grade-form.vue'; | ||||
| 
 | ||||
| const emit = defineEmits(['success']); | ||||
| const formData = ref<Demo03StudentApi.Demo03Student>(); | ||||
| const getTitle = computed(() => { | ||||
|   return formData.value?.id | ||||
|     ? $t('ui.actionTitle.edit', ['学生']) | ||||
|     : $t('ui.actionTitle.create', ['学生']); | ||||
| }); | ||||
| 
 | ||||
| /** 子表的表单 */ | ||||
| const subTabsName = ref('demo03Course'); | ||||
| const demo03CourseFormRef = ref<InstanceType<typeof Demo03CourseForm>>(); | ||||
| const demo03GradeFormRef = ref<InstanceType<typeof Demo03GradeForm>>(); | ||||
| 
 | ||||
| const [Form, formApi] = useVbenForm({ | ||||
|   commonConfig: { | ||||
|     componentProps: { | ||||
|       class: 'w-full', | ||||
|     }, | ||||
|     formItemClass: 'col-span-2', | ||||
|     labelWidth: 80, | ||||
|   }, | ||||
|   layout: 'horizontal', | ||||
|   schema: useFormSchema(), | ||||
|   showDefaultActions: false, | ||||
| }); | ||||
| 
 | ||||
| const [Modal, modalApi] = useVbenModal({ | ||||
|   async onConfirm() { | ||||
|     const { valid } = await formApi.validate(); | ||||
|     if (!valid) { | ||||
|       return; | ||||
|     } | ||||
|     // 校验子表单 | ||||
|     const demo03GradeValid = await demo03GradeFormRef.value?.validate(); | ||||
|     if (!demo03GradeValid) { | ||||
|       subTabsName.value = 'demo03Grade'; | ||||
|       return; | ||||
|     } | ||||
|     modalApi.lock(); | ||||
|     // 提交表单 | ||||
|     const data = (await formApi.getValues()) as Demo03StudentApi.Demo03Student; | ||||
|     // 拼接子表的数据 | ||||
|     data.demo03Courses = demo03CourseFormRef.value?.getData(); | ||||
|     data.demo03Grade = await demo03GradeFormRef.value?.getValues(); | ||||
|     try { | ||||
|       await (formData.value?.id | ||||
|         ? updateDemo03Student(data) | ||||
|         : createDemo03Student(data)); | ||||
|       // 关闭并提示 | ||||
|       await modalApi.close(); | ||||
|       emit('success'); | ||||
|       ElMessage.success($t('ui.actionMessage.operationSuccess')); | ||||
|     } finally { | ||||
|       modalApi.unlock(); | ||||
|     } | ||||
|   }, | ||||
|   async onOpenChange(isOpen: boolean) { | ||||
|     if (!isOpen) { | ||||
|       formData.value = undefined; | ||||
|       return; | ||||
|     } | ||||
|     // 加载数据 | ||||
|     let data = modalApi.getData<Demo03StudentApi.Demo03Student>(); | ||||
|     if (!data) { | ||||
|       return; | ||||
|     } | ||||
|     if (data.id) { | ||||
|       modalApi.lock(); | ||||
|       try { | ||||
|         data = await getDemo03Student(data.id); | ||||
|       } finally { | ||||
|         modalApi.unlock(); | ||||
|       } | ||||
|     } | ||||
|     // 设置到 values | ||||
|     formData.value = data; | ||||
|     await formApi.setValues(formData.value); | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Modal :title="getTitle"> | ||||
|     <Form class="mx-4" /> | ||||
|     <!-- 子表的表单 --> | ||||
|     <ElTabs v-model="subTabsName"> | ||||
|       <ElTabPane name="demo03Course" label="学生课程"> | ||||
|         <Demo03CourseForm | ||||
|           ref="demo03CourseFormRef" | ||||
|           :student-id="formData?.id" | ||||
|         /> | ||||
|       </ElTabPane> | ||||
|       <ElTabPane name="demo03Grade" label="学生班级"> | ||||
|         <Demo03GradeForm ref="demo03GradeFormRef" :student-id="formData?.id" /> | ||||
|       </ElTabPane> | ||||
|     </ElTabs> | ||||
|   </Modal> | ||||
| </template> | ||||
		Loading…
	
		Reference in New Issue
	
	 puhui999
						puhui999