diff --git a/src/api/infra/demo/demo03/normal/index.ts b/src/api/infra/demo/demo03/normal/index.ts new file mode 100644 index 00000000..f15ee1dc --- /dev/null +++ b/src/api/infra/demo/demo03/normal/index.ts @@ -0,0 +1,53 @@ +import request from '@/config/axios' + +export interface Demo03StudentVO { + id: number + name: string + sex: number + birthday: Date + description: string +} + +// 查询学生分页 +export const getDemo03StudentPage = async (params) => { + return await request.get({ url: `/infra/demo03-student/page`, params }) +} + +// 查询学生详情 +export const getDemo03Student = async (id: number) => { + return await request.get({ url: `/infra/demo03-student/get?id=` + id }) +} + +// 新增学生 +export const createDemo03Student = async (data: Demo03StudentVO) => { + return await request.post({ url: `/infra/demo03-student/create`, data }) +} + +// 修改学生 +export const updateDemo03Student = async (data: Demo03StudentVO) => { + return await request.put({ url: `/infra/demo03-student/update`, data }) +} + +// 删除学生 +export const deleteDemo03Student = async (id: number) => { + return await request.delete({ url: `/infra/demo03-student/delete?id=` + id }) +} + +// 导出学生 Excel +export const exportDemo03Student = async (params) => { + return await request.download({ url: `/infra/demo03-student/export-excel`, params }) +} + +// ==================== 子表(学生课程) ==================== + +// 获得学生课程列表 +export const getDemo03CourseListByStudentId = async (studentId) => { + return await request.get({ url: `/infra/demo03-student/demo03-course/list-by-student-id?studentId=` + studentId }) +} + +// ==================== 子表(学生班级) ==================== + +// 获得学生班级 +export const getDemo03GradeByStudentId = async (studentId) => { + return await request.get({ url: `/infra/demo03-student/demo03-grade/get-by-student-id?studentId=` + studentId }) +} \ No newline at end of file diff --git a/src/views/infra/codegen/components/GenerateInfoForm.vue b/src/views/infra/codegen/components/GenerateInfoForm.vue index a4f5ad97..d2a01cc0 100644 --- a/src/views/infra/codegen/components/GenerateInfoForm.vue +++ b/src/views/infra/codegen/components/GenerateInfoForm.vue @@ -183,7 +183,7 @@ </el-row> <!-- 树表信息 --> - <el-row v-show="formData.templateType == 2"> + <el-row v-if="formData.templateType == 2"> <el-col :span="24"> <h4 class="form-header">树表信息</h4> </el-col> diff --git a/src/views/infra/demo/demo03/normal/Demo03StudentForm.vue b/src/views/infra/demo/demo03/normal/Demo03StudentForm.vue new file mode 100644 index 00000000..00508228 --- /dev/null +++ b/src/views/infra/demo/demo03/normal/Demo03StudentForm.vue @@ -0,0 +1,153 @@ +<template> + <Dialog :title="dialogTitle" v-model="dialogVisible"> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="100px" + v-loading="formLoading" + > + <el-form-item label="名字" prop="name"> + <el-input v-model="formData.name" placeholder="请输入名字" /> + </el-form-item> + <el-form-item label="性别" prop="sex"> + <el-radio-group v-model="formData.sex"> + <el-radio + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)" + :key="dict.value" + :label="dict.value" + > + {{ dict.label }} + </el-radio> + </el-radio-group> + </el-form-item> + <el-form-item label="出生日期" prop="birthday"> + <el-date-picker + v-model="formData.birthday" + type="date" + value-format="x" + placeholder="选择出生日期" + /> + </el-form-item> + <el-form-item label="简介" prop="description"> + <Editor v-model="formData.description" height="150px" /> + </el-form-item> + </el-form> + <!-- 子表的表单 --> + <el-tabs v-model="subTabsName"> + <el-tab-pane label="学生课程" name="demo03Course"> + <Demo03CourseForm ref="demo03CourseFormRef" :student-id="formData.id" /> + </el-tab-pane> + <el-tab-pane label="学生班级" name="demo03Grade"> + <Demo03GradeForm ref="demo03GradeFormRef" :student-id="formData.id" /> + </el-tab-pane> + </el-tabs> + <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, DICT_TYPE } from '@/utils/dict' +import * as Demo03StudentApi from '@/api/infra/demo/demo03/normal' +import Demo03CourseForm from './components/Demo03CourseForm.vue' +import Demo03GradeForm from './components/Demo03GradeForm.vue' + +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({ + id: undefined, + name: undefined, + sex: undefined, + birthday: undefined, + description: undefined +}) +const formRules = reactive({ + 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 formRef = ref() // 表单 Ref + +/** 子表的表单 */ +const subTabsName = ref('demo03Course') +const demo03CourseFormRef = ref() +const demo03GradeFormRef = ref() + +/** 打开弹窗 */ +const open = async (type: string, id?: number) => { + dialogVisible.value = true + dialogTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await Demo03StudentApi.getDemo03Student(id) + } finally { + formLoading.value = false + } + } +} +defineExpose({ open }) // 提供 open 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 +const submitForm = async () => { + // 校验表单 + await formRef.value.validate() + // 校验子表单 + try { + await demo03CourseFormRef.value.validate() + } catch (e) { + subTabsName.value = 'demo03Course' + return + } + try { + await demo03GradeFormRef.value.validate() + } catch (e) { + subTabsName.value = 'demo03Grade' + return + } + // 提交请求 + formLoading.value = true + try { + const data = formData.value as unknown as Demo03StudentApi.Demo03StudentVO + // 拼接子表的数据 + data.demo03Courses = demo03CourseFormRef.value.getData() + data.demo03Grade = demo03GradeFormRef.value.getData() + if (formType.value === 'create') { + await Demo03StudentApi.createDemo03Student(data) + message.success(t('common.createSuccess')) + } else { + await Demo03StudentApi.updateDemo03Student(data) + message.success(t('common.updateSuccess')) + } + dialogVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} + +/** 重置表单 */ +const resetForm = () => { + formData.value = { + id: undefined, + name: undefined, + sex: undefined, + birthday: undefined, + description: undefined + } + formRef.value?.resetFields() +} +</script> \ No newline at end of file diff --git a/src/views/infra/demo03/DemoStudentContactForm.vue b/src/views/infra/demo/demo03/normal/components/Demo03CourseForm.vue similarity index 52% rename from src/views/infra/demo03/DemoStudentContactForm.vue rename to src/views/infra/demo/demo03/normal/components/Demo03CourseForm.vue index 50c44263..b6f58572 100644 --- a/src/views/infra/demo03/DemoStudentContactForm.vue +++ b/src/views/infra/demo/demo03/normal/components/Demo03CourseForm.vue @@ -3,23 +3,23 @@ ref="formRef" :model="formData" :rules="formRules" - label-width="0px" v-loading="formLoading" + label-width="0px" :inline-message="true" > <el-table :data="formData" class="-mt-10px"> <el-table-column label="序号" type="index" width="100" /> - <el-table-column label="名字" prop="name" width="300"> - <template #default="row"> - <el-form-item class="mb-0px!"> + <el-table-column label="名字" min-width="150"> + <template #default="{ row, $index }"> + <el-form-item :prop="`${$index}.name`" :rules="formRules.name" class="mb-0px!"> <el-input v-model="row.name" placeholder="请输入名字" /> </el-form-item> </template> </el-table-column> - <el-table-column label="手机号码"> + <el-table-column label="分数" min-width="150"> <template #default="{ row, $index }"> - <el-form-item :prop="`${$index}.mobile`" :rules="formRules.mobile" class="mb-0px!"> - <el-input type="number" placeholder="输入手机号码" v-model="row.mobile" /> + <el-form-item :prop="`${$index}.score`" :rules="formRules.score" class="mb-0px!"> + <el-input v-model="row.score" placeholder="请输入分数" /> </el-form-item> </template> </el-table-column> @@ -31,33 +31,39 @@ </el-table> </el-form> <el-row justify="center" class="mt-3"> - <el-button @click="handleAdd" round>+ 添加联系人</el-button> + <el-button @click="handleAdd" round>+ 添加学生课程</el-button> </el-row> </template> <script setup lang="ts"> +import * as Demo03StudentApi from '@/api/infra/demo/demo03/normal' + const props = defineProps<{ - studentId: undefined // 学生编号 + studentId: undefined // 学生编号(主表的关联字段) }>() const formLoading = ref(false) // 表单的加载中 const formData = ref([]) const formRules = reactive({ - mobile: [required] + studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }], + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }], + score: [{ required: true, message: '分数不能为空', trigger: 'blur' }] }) const formRef = ref() // 表单 Ref /** 监听主表的关联字段的变化,加载对应的子表数据 */ watch( () => props.studentId, - (val) => { - if (val) { - formData.value = [ - { - name: '芋艿', - mobile: '15601691300' - } - ] - } else { - formData.value = [] + async (val) => { + // 1. 重置表单 + formData.value = [] + // 2. val 非空,则加载数据 + if (!val) { + return; + } + try { + formLoading.value = true + formData.value = await Demo03StudentApi.getDemo03CourseListByStudentId(val) + } finally { + formLoading.value = false } }, { immediate: true } @@ -65,9 +71,14 @@ watch( /** 新增按钮操作 */ const handleAdd = () => { - formData.value.push({ - name: '土豆' - }) + const row = { + id: undefined, + studentId: undefined, + name: undefined, + score: undefined + } + row.studentId = props.studentId + formData.value.push(row) } /** 删除按钮操作 */ @@ -80,10 +91,10 @@ const validate = () => { return formRef.value.validate() } -/** 表单值 **/ +/** 表单值 */ const getData = () => { return formData.value } defineExpose({ validate, getData }) -</script> +</script> \ No newline at end of file diff --git a/src/views/infra/demo/demo03/normal/components/Demo03GradeForm.vue b/src/views/infra/demo/demo03/normal/components/Demo03GradeForm.vue new file mode 100644 index 00000000..12653b6c --- /dev/null +++ b/src/views/infra/demo/demo03/normal/components/Demo03GradeForm.vue @@ -0,0 +1,72 @@ +<template> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + label-width="100px" + v-loading="formLoading" + > + <el-form-item label="名字" prop="name"> + <el-input v-model="formData.name" placeholder="请输入名字" /> + </el-form-item> + <el-form-item label="班主任" prop="teacher"> + <el-input v-model="formData.teacher" placeholder="请输入班主任" /> + </el-form-item> + </el-form> +</template> +<script setup lang="ts"> +import * as Demo03StudentApi from '@/api/infra/demo/demo03/normal' + +const props = defineProps<{ + studentId: undefined // 学生编号(主表的关联字段) +}>() +const formLoading = ref(false) // 表单的加载中 +const formData = ref([]) +const formRules = reactive({ + studentId: [{ required: true, message: '学生编号不能为空', trigger: 'blur' }], + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }], + teacher: [{ required: true, message: '班主任不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref + +/** 监听主表的关联字段的变化,加载对应的子表数据 */ +watch( + () => props.studentId, + async (val) => { + // 1. 重置表单 + formData.value = { + id: undefined, + studentId: undefined, + name: undefined, + teacher: undefined, + } + // 2. val 非空,则加载数据 + if (!val) { + return; + } + try { + formLoading.value = true + const data = await Demo03StudentApi.getDemo03GradeByStudentId(val) + if (!data) { + return + } + formData.value = data + } finally { + formLoading.value = false + } + }, + { immediate: true } +) + +/** 表单校验 */ +const validate = () => { + return formRef.value.validate() +} + +/** 表单值 */ +const getData = () => { + return formData.value +} + +defineExpose({ validate, getData }) +</script> \ No newline at end of file diff --git a/src/views/infra/demo03/index.vue b/src/views/infra/demo/demo03/normal/index.vue similarity index 50% rename from src/views/infra/demo03/index.vue rename to src/views/infra/demo/demo03/normal/index.vue index afd5cbfc..52029107 100644 --- a/src/views/infra/demo03/index.vue +++ b/src/views/infra/demo/demo03/normal/index.vue @@ -8,10 +8,50 @@ :inline="true" label-width="68px" > + <el-form-item label="名字" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="请输入名字" + clearable + @keyup.enter="handleQuery" + class="!w-240px" + /> + </el-form-item> + <el-form-item label="性别" prop="sex"> + <el-select + v-model="queryParams.sex" + placeholder="请选择性别" + clearable + class="!w-240px" + > + <el-option + v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="创建时间" prop="createTime"> + <el-date-picker + v-model="queryParams.createTime" + value-format="YYYY-MM-DD HH:mm:ss" + type="daterange" + start-placeholder="开始日期" + end-placeholder="结束日期" + :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" + class="!w-240px" + /> + </el-form-item> <el-form-item> <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button> <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button> - <el-button type="primary" plain @click="openForm('create')"> + <el-button + type="primary" + plain + @click="openForm('create')" + v-hasPermi="['infra:demo03-student:create']" + > <Icon icon="ep:plus" class="mr-5px" /> 新增 </el-button> <el-button @@ -19,7 +59,7 @@ plain @click="handleExport" :loading="exportLoading" - v-hasPermi="['infra:demo-student:export']" + v-hasPermi="['infra:demo03-student:export']" > <Icon icon="ep:download" class="mr-5px" /> 导出 </el-button> @@ -29,37 +69,44 @@ <!-- 列表 --> <ContentWrap> - <el-table - v-loading="loading" - :data="list" - :stripe="true" - :show-overflow-tooltip="true" - row-key="id" - > - <el-table-column type="expand"> + <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> + <el-table-column label="编号" align="center" prop="id" /> + <el-table-column label="名字" align="center" prop="name" /> + <el-table-column label="性别" align="center" prop="sex"> <template #default="scope"> - <!-- 子表的表单 --> - <el-tabs model-value="DemoStudentContact"> - <el-tab-pane label="联系人信息" name="DemoStudentContact"> - <DemoStudentContactList :student-id="scope.row.id" /> - </el-tab-pane> - <el-tab-pane label="地址信息" name="DemoStudentAddress"> - <DemoStudentAddressList :student-id="scope.row.id" /> - </el-tab-pane> - </el-tabs> + <dict-tag :type="DICT_TYPE.SYSTEM_USER_SEX" :value="scope.row.sex" /> </template> </el-table-column> - <el-table-column label="编号" align="center" prop="id" /> + <el-table-column + label="出生日期" + align="center" + prop="birthday" + :formatter="dateFormatter" + width="180px" + /> + <el-table-column label="简介" align="center" prop="description" /> + <el-table-column + label="创建时间" + align="center" + prop="createTime" + :formatter="dateFormatter" + width="180px" + /> <el-table-column label="操作" align="center"> <template #default="scope"> - <el-button link type="primary" @click="openForm('update', scope.row.id)"> + <el-button + link + type="primary" + @click="openForm('update', scope.row.id)" + v-hasPermi="['infra:demo03-student:update']" + > 编辑 </el-button> <el-button link type="danger" @click="handleDelete(scope.row.id)" - v-hasPermi="['infra:demo-student:delete']" + v-hasPermi="['infra:demo03-student:delete']" > 删除 </el-button> @@ -76,27 +123,31 @@ </ContentWrap> <!-- 表单弹窗:添加/修改 --> - <DemoStudentForm ref="formRef" @success="getList" /> + <Demo03StudentForm ref="formRef" @success="getList" /> </template> <script setup lang="ts"> +import { getIntDictOptions, DICT_TYPE } from '@/utils/dict' +import { dateFormatter } from '@/utils/formatTime' import download from '@/utils/download' -import * as DemoStudentApi from '@/api/infra/demo02' -import DemoStudentForm from './DemoStudentForm.vue' -import DemoStudentContactList from './DemoStudentContactList.vue' -import DemoStudentAddressList from './DemoStudentAddressList.vue' +import * as Demo03StudentApi from '@/api/infra/demo/demo03/normal' +import Demo03StudentForm from './Demo03StudentForm.vue' -defineOptions({ name: 'InfraDemoStudent' }) +defineOptions({ name: 'Demo03Student' }) const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 const loading = ref(true) // 列表的加载中 -const total = ref(0) // 列表的总页数 const list = ref([]) // 列表的数据 +const total = ref(0) // 列表的总页数 const queryParams = reactive({ pageNo: 1, - pageSize: 10 + pageSize: 10, + name: null, + sex: null, + description: null, + createTime: [] }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 @@ -105,16 +156,9 @@ const exportLoading = ref(false) // 导出的加载中 const getList = async () => { loading.value = true try { - // const data = await DemoStudentApi.getDemoStudentPage(queryParams) - list.value = [ - { - id: 1 - }, - { - id: 10 - } - ] - total.value = 10 + const data = await Demo03StudentApi.getDemo03StudentPage(queryParams) + list.value = data.list + total.value = data.total } finally { loading.value = false } @@ -134,10 +178,7 @@ const resetQuery = () => { /** 添加/修改操作 */ const formRef = ref() -// const demoStudentContactFormRef = ref() const openForm = (type: string, id?: number) => { - // console.log(demoStudentContactFormRef, 'xx demoStudentContactFormRef xx') - // demoStudentContactFormRef.value.validate() formRef.value.open(type, id) } @@ -147,7 +188,7 @@ const handleDelete = async (id: number) => { // 删除的二次确认 await message.delConfirm() // 发起删除 - await DemoStudentApi.deleteDemoStudent(id) + await Demo03StudentApi.deleteDemo03Student(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() @@ -161,7 +202,7 @@ const handleExport = async () => { await message.exportConfirm() // 发起导出 exportLoading.value = true - const data = await DemoStudentApi.exportDemoStudent(queryParams) + const data = await Demo03StudentApi.exportDemo03Student(queryParams) download.excel(data, '学生.xls') } catch { } finally { @@ -173,4 +214,4 @@ const handleExport = async () => { onMounted(() => { getList() }) -</script> +</script> \ No newline at end of file diff --git a/src/views/infra/demo03/DemoStudentAddressForm.vue b/src/views/infra/demo03/DemoStudentAddressForm.vue deleted file mode 100644 index af4cd8f1..00000000 --- a/src/views/infra/demo03/DemoStudentAddressForm.vue +++ /dev/null @@ -1,58 +0,0 @@ -<template> - <el-form - ref="formRef" - :model="formData" - :rules="formRules" - label-width="100px" - v-loading="formLoading" - > - <el-form-item label="子字段 1" prop="field1"> - <el-input v-model="formData.field1" placeholder="请输入字段 1" /> - </el-form-item> - <el-form-item label="子字段 2" prop="field2"> - <el-input v-model="formData.field2" placeholder="请输入字段 2" /> - </el-form-item> - <el-form-item label="子字段 3" prop="field3"> - <el-input v-model="formData.field3" placeholder="请输入字段 3" /> - </el-form-item> - </el-form> -</template> -<script setup lang="ts"> -const props = defineProps<{ - studentId: undefined // 学生编号 -}>() -const formLoading = ref(false) // 表单的加载中 -const formData = ref({}) -const formRules = reactive({ - field1: [required] -}) -const formRef = ref() // 表单 Ref - -/** 监听主表的关联字段的变化,加载对应的子表数据 */ -watch( - () => props.studentId, - (val) => { - if (val) { - formData.value = { - field2: '番茄', - field3: '西瓜' - } - } else { - formData.value = {} - } - }, - { immediate: true } -) - -/** 表单校验 */ -const validate = () => { - return formRef.value.validate() -} - -/** 表单值 **/ -const getData = () => { - return formData.value -} - -defineExpose({ validate, getData }) -</script> diff --git a/src/views/infra/demo03/DemoStudentAddressList.vue b/src/views/infra/demo03/DemoStudentAddressList.vue deleted file mode 100644 index 2354db56..00000000 --- a/src/views/infra/demo03/DemoStudentAddressList.vue +++ /dev/null @@ -1,38 +0,0 @@ -<template> - <!-- 列表 --> - <ContentWrap> - <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> - <el-table-column label="编号" align="center" prop="id" /> - <el-table-column label="手机" align="center" prop="mobile" /> - </el-table> - </ContentWrap> -</template> - -<script setup lang="ts"> -const props = defineProps<{ - studentId: undefined // 学生编号 -}>() -const loading = ref(true) // 列表的加载中 -const list = ref([]) // 列表的数据 - -/** 查询列表 */ -const getList = async () => { - loading.value = true - try { - // const data = await DemoStudentApi.getDemoStudentPage(queryParams) - list.value = [ - { - id: props.studentId, - mobile: '88888' - } - ] - } finally { - loading.value = false - } -} - -/** 初始化 **/ -onMounted(() => { - getList() -}) -</script> diff --git a/src/views/infra/demo03/DemoStudentContactList.vue b/src/views/infra/demo03/DemoStudentContactList.vue deleted file mode 100644 index 76d46116..00000000 --- a/src/views/infra/demo03/DemoStudentContactList.vue +++ /dev/null @@ -1,38 +0,0 @@ -<template> - <!-- 列表 --> - <ContentWrap> - <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> - <el-table-column label="编号" align="center" prop="id" /> - <el-table-column label="手机" align="center" prop="mobile" /> - </el-table> - </ContentWrap> -</template> - -<script setup lang="ts"> -const props = defineProps<{ - studentId: undefined // 学生编号 -}>() -const loading = ref(true) // 列表的加载中 -const list = ref([]) // 列表的数据 - -/** 查询列表 */ -const getList = async () => { - loading.value = true - try { - // const data = await DemoStudentApi.getDemoStudentPage(queryParams) - list.value = [ - { - id: props.studentId, - mobile: '15601691300' - } - ] - } finally { - loading.value = false - } -} - -/** 初始化 **/ -onMounted(() => { - getList() -}) -</script> diff --git a/src/views/infra/demo03/DemoStudentForm.vue b/src/views/infra/demo03/DemoStudentForm.vue deleted file mode 100644 index fe0788c4..00000000 --- a/src/views/infra/demo03/DemoStudentForm.vue +++ /dev/null @@ -1,132 +0,0 @@ -<template> - <Dialog :title="dialogTitle" v-model="dialogVisible"> - <el-form - ref="formRef" - :model="formData" - :rules="formRules" - label-width="100px" - v-loading="formLoading" - > - <el-form-item label="字段 1" prop="field1"> - <el-input v-model="formData.field1" placeholder="请输入字段 1" /> - </el-form-item> - <el-form-item label="字段 2" prop="field2"> - <el-input v-model="formData.field2" placeholder="请输入字段 2" /> - </el-form-item> - <el-form-item label="字段 3" prop="field3"> - <el-input v-model="formData.field3" placeholder="请输入字段 3" /> - </el-form-item> - </el-form> - <!-- 子表的表单 --> - <el-tabs v-model="subTabsName"> - <el-tab-pane label="联系人信息" name="DemoStudentContact"> - <DemoStudentContactForm ref="demoStudentContactFormRef" :student-id="formData.id" /> - </el-tab-pane> - <el-tab-pane label="地址信息" name="DemoStudentAddress"> - <DemoStudentAddressForm ref="demoStudentAddressFormRef" :student-id="formData.id" /> - </el-tab-pane> - </el-tabs> - <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 * as DemoStudentApi from '@/api/infra/demo02' -import DemoStudentContactForm from './DemoStudentContactForm.vue' -import DemoStudentAddressForm from './DemoStudentAddressForm.vue' - -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({ - id: undefined -}) -const formRules = reactive({ - field2: [required] -}) -const formRef = ref() // 表单 Ref - -/** 子表的表单 */ -const demoStudentContactFormRef = ref() -const demoStudentAddressFormRef = ref() -const subTabsName = ref('DemoStudentContact') - -/** 打开弹窗 */ -const open = async (type: string, id?: number) => { - dialogVisible.value = true - dialogTitle.value = t('action.' + type) - formType.value = type - resetForm() - // 修改时,设置数据 - if (id) { - // debugger - formLoading.value = true - try { - // formData.value = await DemoStudentApi.getDemoStudent(id) - formData.value = { - id: id, - field1: '1', - field2: '22', - field3: '333' - } - } finally { - formLoading.value = false - } - } -} -defineExpose({ open }) // 提供 open 方法,用于打开弹窗 - -/** 提交表单 */ -const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 -const submitForm = async () => { - // 校验表单 - await formRef.value.validate() - // 校验子表单 - try { - await demoStudentContactFormRef.value.validate() - } catch (e) { - subTabsName.value = 'DemoStudentContact' - return - } - try { - await demoStudentAddressFormRef.value.validate() - } catch (e) { - subTabsName.value = 'DemoStudentAddress' - return - } - // 提交请求 - formLoading.value = true - try { - const data = formData.value as unknown as DemoStudentApi.DemoStudentVO - // 拼接子表的数据 - data.demoStudentContacts = demoStudentContactFormRef.value.getData() - data.demoStudentAddress = demoStudentAddressFormRef.value.getData() - if (formType.value === 'create') { - await DemoStudentApi.createDemoStudent(data) - message.success(t('common.createSuccess')) - } else { - await DemoStudentApi.updateDemoStudent(data) - message.success(t('common.updateSuccess')) - } - dialogVisible.value = false - // 发送操作成功的事件 - emit('success') - } finally { - formLoading.value = false - } -} - -/** 重置表单 */ -const resetForm = () => { - formData.value = { - id: undefined - } - formRef.value?.resetFields() -} -</script>