feat: 【ele】新增 general 主子表 normal 模式代码生成示例
							parent
							
								
									836d6ab3f3
								
							
						
					
					
						commit
						fe8c7b67f7
					
				|  | @ -0,0 +1,316 @@ | |||
| <script lang="ts" setup> | ||||
| import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { h, onMounted, reactive, ref } from 'vue'; | ||||
| 
 | ||||
| import { Page, useVbenModal } from '@vben/common-ui'; | ||||
| import { Download, Plus, Trash2 } from '@vben/icons'; | ||||
| import { | ||||
|   cloneDeep, | ||||
|   downloadFileFromBlobPart, | ||||
|   formatDateTime, | ||||
|   isEmpty, | ||||
| } from '@vben/utils'; | ||||
| 
 | ||||
| import { | ||||
|   ElButton, | ||||
|   ElDatePicker, | ||||
|   ElForm, | ||||
|   ElFormItem, | ||||
|   ElInput, | ||||
|   ElLoading, | ||||
|   ElMessage, | ||||
|   ElOption, | ||||
|   ElPagination, | ||||
|   ElSelect, | ||||
| } from 'element-plus'; | ||||
| 
 | ||||
| import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||||
| import { | ||||
|   deleteDemo03Student, | ||||
|   deleteDemo03StudentList, | ||||
|   exportDemo03Student, | ||||
|   getDemo03StudentPage, | ||||
| } from '#/api/infra/demo/demo03/normal'; | ||||
| import { ContentWrap } from '#/components/content-wrap'; | ||||
| import { DictTag } from '#/components/dict-tag'; | ||||
| import { TableToolbar } from '#/components/table-toolbar'; | ||||
| import { useTableToolbar } from '#/hooks'; | ||||
| import { $t } from '#/locales'; | ||||
| import { DICT_TYPE, getDictOptions } from '#/utils'; | ||||
| 
 | ||||
| import Demo03StudentForm from './modules/form.vue'; | ||||
| 
 | ||||
| const loading = ref(true); // 列表的加载中 | ||||
| const list = ref<Demo03StudentApi.Demo03Student[]>([]); // 列表的数据 | ||||
| 
 | ||||
| const total = ref(0); // 列表的总页数 | ||||
| const queryParams = reactive({ | ||||
|   pageNo: 1, | ||||
|   pageSize: 10, | ||||
|   name: undefined, | ||||
|   sex: undefined, | ||||
|   description: undefined, | ||||
|   createTime: undefined, | ||||
| }); | ||||
| const queryFormRef = ref(); // 搜索的表单 | ||||
| const exportLoading = ref(false); // 导出的加载中 | ||||
| 
 | ||||
| /** 查询列表 */ | ||||
| const getList = async () => { | ||||
|   loading.value = true; | ||||
|   try { | ||||
|     const params = cloneDeep(queryParams) as any; | ||||
|     if (params.createTime && Array.isArray(params.createTime)) { | ||||
|       params.createTime = (params.createTime as string[]).join(','); | ||||
|     } | ||||
|     const data = await getDemo03StudentPage(params); | ||||
|     list.value = data.list; | ||||
|     total.value = data.total; | ||||
|   } finally { | ||||
|     loading.value = false; | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| /** 搜索按钮操作 */ | ||||
| const handleQuery = () => { | ||||
|   queryParams.pageNo = 1; | ||||
|   getList(); | ||||
| }; | ||||
| 
 | ||||
| /** 重置按钮操作 */ | ||||
| const resetQuery = () => { | ||||
|   queryFormRef.value.resetFields(); | ||||
|   handleQuery(); | ||||
| }; | ||||
| 
 | ||||
| const [FormModal, formModalApi] = useVbenModal({ | ||||
|   connectedComponent: Demo03StudentForm, | ||||
|   destroyOnClose: true, | ||||
| }); | ||||
| 
 | ||||
| /** 创建学生 */ | ||||
| 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])); | ||||
|     await getList(); | ||||
|   } 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')); | ||||
|     await getList(); | ||||
|   } finally { | ||||
|     loadingInstance.close(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const checkedIds = ref<number[]>([]); | ||||
| function handleRowCheckboxChange({ | ||||
|   records, | ||||
| }: { | ||||
|   records: Demo03StudentApi.Demo03Student[]; | ||||
| }) { | ||||
|   checkedIds.value = records.map((item) => item.id); | ||||
| } | ||||
| 
 | ||||
| /** 导出表格 */ | ||||
| async function onExport() { | ||||
|   try { | ||||
|     exportLoading.value = true; | ||||
|     const data = await exportDemo03Student(queryParams); | ||||
|     downloadFileFromBlobPart({ fileName: '学生.xls', source: data }); | ||||
|   } finally { | ||||
|     exportLoading.value = false; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /** 初始化 */ | ||||
| const { hiddenSearchBar, tableToolbarRef, tableRef } = useTableToolbar(); | ||||
| onMounted(() => { | ||||
|   getList(); | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Page auto-content-height> | ||||
|     <FormModal @success="getList" /> | ||||
| 
 | ||||
|     <ContentWrap v-if="!hiddenSearchBar"> | ||||
|       <!-- 搜索工作栏 --> | ||||
|       <ElForm :model="queryParams" ref="queryFormRef" inline> | ||||
|         <ElFormItem label="名字"> | ||||
|           <ElInput | ||||
|             v-model="queryParams.name" | ||||
|             placeholder="请输入名字" | ||||
|             clearable | ||||
|             @keyup.enter="handleQuery" | ||||
|             class="!w-[240px]" | ||||
|           /> | ||||
|         </ElFormItem> | ||||
|         <ElFormItem label="性别"> | ||||
|           <ElSelect | ||||
|             v-model="queryParams.sex" | ||||
|             placeholder="请选择性别" | ||||
|             clearable | ||||
|             class="!w-[240px]" | ||||
|           > | ||||
|             <ElOption | ||||
|               v-for="dict in getDictOptions( | ||||
|                 DICT_TYPE.SYSTEM_USER_SEX, | ||||
|                 'number', | ||||
|               )" | ||||
|               :key="dict.value" | ||||
|               :value="dict.value" | ||||
|               :label="dict.label" | ||||
|             /> | ||||
|           </ElSelect> | ||||
|         </ElFormItem> | ||||
|         <ElFormItem label="创建时间"> | ||||
|           <ElDatePicker | ||||
|             v-model="queryParams.createTime" | ||||
|             type="daterange" | ||||
|             value-format="YYYY-MM-DD" | ||||
|             range-separator="至" | ||||
|             start-placeholder="开始日期" | ||||
|             end-placeholder="结束日期" | ||||
|             class="!w-[240px]" | ||||
|           /> | ||||
|         </ElFormItem> | ||||
|         <ElFormItem> | ||||
|           <ElButton class="ml-2" @click="resetQuery"> 重置 </ElButton> | ||||
|           <ElButton class="ml-2" @click="handleQuery" type="primary"> | ||||
|             搜索 | ||||
|           </ElButton> | ||||
|         </ElFormItem> | ||||
|       </ElForm> | ||||
|     </ContentWrap> | ||||
| 
 | ||||
|     <!-- 列表 --> | ||||
|     <ContentWrap title="学生"> | ||||
|       <template #extra> | ||||
|         <TableToolbar | ||||
|           ref="tableToolbarRef" | ||||
|           v-model:hidden-search="hiddenSearchBar" | ||||
|         > | ||||
|           <ElButton | ||||
|             class="ml-2" | ||||
|             :icon="h(Plus)" | ||||
|             type="primary" | ||||
|             @click="handleCreate" | ||||
|             v-access:code="['infra:demo03-student:create']" | ||||
|           > | ||||
|             {{ $t('ui.actionTitle.create', ['学生']) }} | ||||
|           </ElButton> | ||||
|           <ElButton | ||||
|             :icon="h(Download)" | ||||
|             type="primary" | ||||
|             class="ml-2" | ||||
|             :loading="exportLoading" | ||||
|             @click="onExport" | ||||
|             v-access:code="['infra:demo03-student:export']" | ||||
|           > | ||||
|             {{ $t('ui.actionTitle.export') }} | ||||
|           </ElButton> | ||||
|           <ElButton | ||||
|             :icon="h(Trash2)" | ||||
|             type="danger" | ||||
|             class="ml-2" | ||||
|             :disabled="isEmpty(checkedIds)" | ||||
|             @click="handleDeleteBatch" | ||||
|             v-access:code="['infra:demo03-student:delete']" | ||||
|           > | ||||
|             批量删除 | ||||
|           </ElButton> | ||||
|         </TableToolbar> | ||||
|       </template> | ||||
|       <VxeTable | ||||
|         ref="tableRef" | ||||
|         :data="list" | ||||
|         show-overflow | ||||
|         :loading="loading" | ||||
|         @checkbox-all="handleRowCheckboxChange" | ||||
|         @checkbox-change="handleRowCheckboxChange" | ||||
|       > | ||||
|         <VxeColumn type="checkbox" width="40" /> | ||||
|         <VxeColumn field="id" title="编号" align="center" /> | ||||
|         <VxeColumn field="name" title="名字" align="center" /> | ||||
|         <VxeColumn field="sex" title="性别" align="center"> | ||||
|           <template #default="{ row }"> | ||||
|             <DictTag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="row.sex" /> | ||||
|           </template> | ||||
|         </VxeColumn> | ||||
|         <VxeColumn field="birthday" title="出生日期" align="center"> | ||||
|           <template #default="{ row }"> | ||||
|             {{ formatDateTime(row.birthday) }} | ||||
|           </template> | ||||
|         </VxeColumn> | ||||
|         <VxeColumn field="description" title="简介" align="center" /> | ||||
|         <VxeColumn field="createTime" title="创建时间" align="center"> | ||||
|           <template #default="{ row }"> | ||||
|             {{ formatDateTime(row.createTime) }} | ||||
|           </template> | ||||
|         </VxeColumn> | ||||
|         <VxeColumn field="operation" title="操作" align="center"> | ||||
|           <template #default="{ row }"> | ||||
|             <ElButton | ||||
|               size="small" | ||||
|               type="primary" | ||||
|               link | ||||
|               @click="handleEdit(row as any)" | ||||
|               v-access:code="['infra:demo03-student:update']" | ||||
|             > | ||||
|               {{ $t('ui.actionTitle.edit') }} | ||||
|             </ElButton> | ||||
|             <ElButton | ||||
|               size="small" | ||||
|               type="danger" | ||||
|               link | ||||
|               class="ml-2" | ||||
|               @click="handleDelete(row as any)" | ||||
|               v-access:code="['infra:demo03-student:delete']" | ||||
|             > | ||||
|               {{ $t('ui.actionTitle.delete') }} | ||||
|             </ElButton> | ||||
|           </template> | ||||
|         </VxeColumn> | ||||
|       </VxeTable> | ||||
|       <!-- 分页 --> | ||||
|       <div class="mt-2 flex justify-end"> | ||||
|         <ElPagination | ||||
|           :total="total" | ||||
|           v-model:current-page="queryParams.pageNo" | ||||
|           v-model:page-size="queryParams.pageSize" | ||||
|           :page-sizes="[10, 20, 50, 100]" | ||||
|           layout="total, sizes, prev, pager, next, jumper" | ||||
|           @size-change="getList" | ||||
|           @current-change="getList" | ||||
|         /> | ||||
|       </div> | ||||
|     </ContentWrap> | ||||
|   </Page> | ||||
| </template> | ||||
|  | @ -0,0 +1,95 @@ | |||
| <script lang="ts" setup> | ||||
| import type { VxeTableInstance } from '#/adapter/vxe-table'; | ||||
| import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { h, ref, watch } from 'vue'; | ||||
| 
 | ||||
| import { Plus } from '@vben/icons'; | ||||
| 
 | ||||
| import { ElButton, ElInput } from 'element-plus'; | ||||
| 
 | ||||
| import { VxeColumn, VxeTable } from '#/adapter/vxe-table'; | ||||
| import { getDemo03CourseListByStudentId } from '#/api/infra/demo/demo03/normal'; | ||||
| import { $t } from '#/locales'; | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|   studentId?: number; // 学生编号(主表的关联字段) | ||||
| }>(); | ||||
| 
 | ||||
| const list = ref<Demo03StudentApi.Demo03Course[]>([]); // 列表的数据 | ||||
| const tableRef = ref<VxeTableInstance>(); | ||||
| /** 添加学生课程 */ | ||||
| const onAdd = async () => { | ||||
|   await tableRef.value?.insertAt({} as Demo03StudentApi.Demo03Course, -1); | ||||
| }; | ||||
| 
 | ||||
| /** 删除学生课程 */ | ||||
| const onDelete = async (row: Demo03StudentApi.Demo03Course) => { | ||||
|   await tableRef.value?.remove(row); | ||||
| }; | ||||
| 
 | ||||
| /** 提供获取表格数据的方法供父组件调用 */ | ||||
| defineExpose({ | ||||
|   getData: (): Demo03StudentApi.Demo03Course[] => { | ||||
|     const data = list.value as Demo03StudentApi.Demo03Course[]; | ||||
|     const removeRecords = | ||||
|       tableRef.value?.getRemoveRecords() as Demo03StudentApi.Demo03Course[]; | ||||
|     const insertRecords = | ||||
|       tableRef.value?.getInsertRecords() as Demo03StudentApi.Demo03Course[]; | ||||
|     return data | ||||
|       .filter((row) => !removeRecords.some((removed) => removed.id === row.id)) | ||||
|       ?.concat(insertRecords.map((row: any) => ({ ...row, id: undefined }))); | ||||
|   }, | ||||
| }); | ||||
| 
 | ||||
| /** 监听主表的关联字段的变化,加载对应的子表数据 */ | ||||
| watch( | ||||
|   () => props.studentId, | ||||
|   async (val) => { | ||||
|     if (!val) { | ||||
|       return; | ||||
|     } | ||||
|     list.value = await getDemo03CourseListByStudentId(props.studentId!); | ||||
|   }, | ||||
|   { immediate: true }, | ||||
| ); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <VxeTable ref="tableRef" :data="list" show-overflow class="mx-4"> | ||||
|     <VxeColumn field="name" title="名字" align="center"> | ||||
|       <template #default="{ row }"> | ||||
|         <ElInput v-model="row.name" /> | ||||
|       </template> | ||||
|     </VxeColumn> | ||||
|     <VxeColumn field="score" title="分数" align="center"> | ||||
|       <template #default="{ row }"> | ||||
|         <ElInput v-model="row.score" /> | ||||
|       </template> | ||||
|     </VxeColumn> | ||||
|     <VxeColumn field="operation" title="操作" align="center"> | ||||
|       <template #default="{ row }"> | ||||
|         <ElButton | ||||
|           size="small" | ||||
|           type="danger" | ||||
|           link | ||||
|           @click="onDelete(row as any)" | ||||
|           v-access:code="['infra:demo03-student:delete']" | ||||
|         > | ||||
|           {{ $t('ui.actionTitle.delete') }} | ||||
|         </ElButton> | ||||
|       </template> | ||||
|     </VxeColumn> | ||||
|   </VxeTable> | ||||
|   <div class="mt-4 flex justify-center"> | ||||
|     <ElButton | ||||
|       :icon="h(Plus)" | ||||
|       type="primary" | ||||
|       plain | ||||
|       @click="onAdd" | ||||
|       v-access:code="['infra:demo03-student:create']" | ||||
|     > | ||||
|       {{ $t('ui.actionTitle.create', ['学生课程']) }} | ||||
|     </ElButton> | ||||
|   </div> | ||||
| </template> | ||||
|  | @ -0,0 +1,67 @@ | |||
| <script lang="ts" setup> | ||||
| import type { FormRules } from 'element-plus'; | ||||
| 
 | ||||
| import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { nextTick, reactive, ref, watch } from 'vue'; | ||||
| 
 | ||||
| import { ElForm, ElFormItem, ElInput } from 'element-plus'; | ||||
| 
 | ||||
| import { getDemo03GradeByStudentId } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| const props = defineProps<{ | ||||
|   studentId?: number; // 学生编号(主表的关联字段) | ||||
| }>(); | ||||
| 
 | ||||
| const formRef = ref(); | ||||
| const formData = ref<Partial<Demo03StudentApi.Demo03Grade>>({ | ||||
|   id: undefined, | ||||
|   studentId: undefined, | ||||
|   name: undefined, | ||||
|   teacher: undefined, | ||||
| }); | ||||
| const rules = reactive<FormRules>({ | ||||
|   studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }], | ||||
|   name: [{ required: true, message: '名字不能为空', trigger: 'blur' }], | ||||
|   teacher: [{ required: true, message: '班主任不能为空', trigger: 'blur' }], | ||||
| }); | ||||
| /** 暴露出表单校验方法和表单值获取方法 */ | ||||
| defineExpose({ | ||||
|   validate: async () => await formRef.value?.validate(), | ||||
|   getValues: () => formData.value, | ||||
| }); | ||||
| 
 | ||||
| /** 监听主表的关联字段的变化,加载对应的子表数据 */ | ||||
| watch( | ||||
|   () => props.studentId, | ||||
|   async (val) => { | ||||
|     if (!val) { | ||||
|       return; | ||||
|     } | ||||
|     await nextTick(); | ||||
|     formData.value = await getDemo03GradeByStudentId(props.studentId!); | ||||
|   }, | ||||
|   { immediate: true }, | ||||
| ); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <ElForm | ||||
|     ref="formRef" | ||||
|     class="mx-4" | ||||
|     :model="formData" | ||||
|     :rules="rules" | ||||
|     label-width="120px" | ||||
|     label-position="right" | ||||
|   > | ||||
|     <ElFormItem label="学生编号" prop="studentId"> | ||||
|       <ElInput v-model="formData.studentId" placeholder="请输入学生编号" /> | ||||
|     </ElFormItem> | ||||
|     <ElFormItem label="名字" prop="name"> | ||||
|       <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||||
|     </ElFormItem> | ||||
|     <ElFormItem label="班主任" prop="teacher"> | ||||
|       <ElInput v-model="formData.teacher" placeholder="请输入班主任" /> | ||||
|     </ElFormItem> | ||||
|   </ElForm> | ||||
| </template> | ||||
|  | @ -0,0 +1,171 @@ | |||
| <script lang="ts" setup> | ||||
| import type { FormRules } from 'element-plus'; | ||||
| 
 | ||||
| import type { Demo03StudentApi } from '#/api/infra/demo/demo03/normal'; | ||||
| 
 | ||||
| import { computed, reactive, ref } from 'vue'; | ||||
| 
 | ||||
| import { useVbenModal } from '@vben/common-ui'; | ||||
| 
 | ||||
| import { | ||||
|   ElDatePicker, | ||||
|   ElForm, | ||||
|   ElFormItem, | ||||
|   ElInput, | ||||
|   ElMessage, | ||||
|   ElRadio, | ||||
|   ElRadioGroup, | ||||
|   ElTabPane, | ||||
|   ElTabs, | ||||
| } from 'element-plus'; | ||||
| 
 | ||||
| import { | ||||
|   createDemo03Student, | ||||
|   getDemo03Student, | ||||
|   updateDemo03Student, | ||||
| } from '#/api/infra/demo/demo03/normal'; | ||||
| import { Tinymce as RichTextarea } from '#/components/tinymce'; | ||||
| import { $t } from '#/locales'; | ||||
| import { DICT_TYPE, getDictOptions } from '#/utils'; | ||||
| 
 | ||||
| import Demo03CourseForm from './demo03-course-form.vue'; | ||||
| import Demo03GradeForm from './demo03-grade-form.vue'; | ||||
| 
 | ||||
| const emit = defineEmits(['success']); | ||||
| 
 | ||||
| const formRef = ref(); | ||||
| const formData = ref<Partial<Demo03StudentApi.Demo03Student>>({ | ||||
|   id: undefined, | ||||
|   name: undefined, | ||||
|   sex: undefined, | ||||
|   birthday: undefined, | ||||
|   description: undefined, | ||||
| }); | ||||
| const rules = reactive<FormRules>({ | ||||
|   name: [{ required: true, message: '名字不能为空', trigger: 'blur' }], | ||||
|   sex: [{ required: true, message: '性别不能为空', trigger: 'blur' }], | ||||
|   birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }], | ||||
|   description: [{ required: true, message: '简介不能为空', trigger: 'blur' }], | ||||
| }); | ||||
| 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 resetForm = () => { | ||||
|   formData.value = { | ||||
|     id: undefined, | ||||
|     name: undefined, | ||||
|     sex: undefined, | ||||
|     birthday: undefined, | ||||
|     description: undefined, | ||||
|   }; | ||||
|   formRef.value?.resetFields(); | ||||
| }; | ||||
| 
 | ||||
| const [Modal, modalApi] = useVbenModal({ | ||||
|   async onConfirm() { | ||||
|     await formRef.value?.validate(); | ||||
|     // 校验子表单 | ||||
|     try { | ||||
|       await demo03GradeFormRef.value?.validate(); | ||||
|     } catch { | ||||
|       subTabsName.value = 'demo03Grade'; | ||||
|       return; | ||||
|     } | ||||
|     modalApi.lock(); | ||||
|     // 提交表单 | ||||
|     const data = formData.value as Demo03StudentApi.Demo03Student; | ||||
|     // 拼接子表的数据 | ||||
|     data.demo03Courses = demo03CourseFormRef.value?.getData(); | ||||
|     data.demo03Grade = 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) { | ||||
|       resetForm(); | ||||
|       return; | ||||
|     } | ||||
|     // 加载数据 | ||||
|     let data = modalApi.getData<Demo03StudentApi.Demo03Student>(); | ||||
|     if (!data) { | ||||
|       return; | ||||
|     } | ||||
|     if (data.id) { | ||||
|       modalApi.lock(); | ||||
|       try { | ||||
|         data = await getDemo03Student(data.id); | ||||
|       } finally { | ||||
|         modalApi.unlock(); | ||||
|       } | ||||
|     } | ||||
|     formData.value = data; | ||||
|   }, | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <template> | ||||
|   <Modal :title="getTitle"> | ||||
|     <ElForm | ||||
|       ref="formRef" | ||||
|       :model="formData" | ||||
|       :rules="rules" | ||||
|       label-width="120px" | ||||
|       label-position="right" | ||||
|     > | ||||
|       <ElFormItem label="名字" prop="name"> | ||||
|         <ElInput v-model="formData.name" placeholder="请输入名字" /> | ||||
|       </ElFormItem> | ||||
|       <ElFormItem label="性别" prop="sex"> | ||||
|         <ElRadioGroup v-model="formData.sex"> | ||||
|           <ElRadio | ||||
|             v-for="dict in getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number')" | ||||
|             :key="dict.value" | ||||
|             :label="dict.value" | ||||
|           > | ||||
|             {{ dict.label }} | ||||
|           </ElRadio> | ||||
|         </ElRadioGroup> | ||||
|       </ElFormItem> | ||||
|       <ElFormItem label="出生日期" prop="birthday"> | ||||
|         <ElDatePicker | ||||
|           v-model="formData.birthday" | ||||
|           value-format="x" | ||||
|           placeholder="选择出生日期" | ||||
|         /> | ||||
|       </ElFormItem> | ||||
|       <ElFormItem label="简介" prop="description"> | ||||
|         <RichTextarea v-model="formData.description" height="500px" /> | ||||
|       </ElFormItem> | ||||
|     </ElForm> | ||||
|     <!-- 子表的表单 --> | ||||
|     <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