diff --git a/src/api/infra/demo/demo02/index.ts b/src/api/infra/demo/demo02/index.ts new file mode 100644 index 00000000..21e45c90 --- /dev/null +++ b/src/api/infra/demo/demo02/index.ts @@ -0,0 +1,37 @@ +import request from '@/config/axios' + +export interface Demo02CategoryVO { + id: number + name: string + parentId: number +} + +// 查询示例分类列表 +export const getDemo02CategoryList = async (params) => { + return await request.get({ url: `/infra/demo02-category/list`, params }) +} + +// 查询示例分类详情 +export const getDemo02Category = async (id: number) => { + return await request.get({ url: `/infra/demo02-category/get?id=` + id }) +} + +// 新增示例分类 +export const createDemo02Category = async (data: Demo02CategoryVO) => { + return await request.post({ url: `/infra/demo02-category/create`, data }) +} + +// 修改示例分类 +export const updateDemo02Category = async (data: Demo02CategoryVO) => { + return await request.put({ url: `/infra/demo02-category/update`, data }) +} + +// 删除示例分类 +export const deleteDemo02Category = async (id: number) => { + return await request.delete({ url: `/infra/demo02-category/delete?id=` + id }) +} + +// 导出示例分类 Excel +export const exportDemo02Category = async (params) => { + return await request.download({ url: `/infra/demo02-category/export-excel`, params }) +} \ No newline at end of file diff --git a/src/api/infra/demo02/index.ts b/src/api/infra/demo02/index.ts deleted file mode 100644 index 500adde5..00000000 --- a/src/api/infra/demo02/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import request from '@/config/axios' - -export interface DemoStudentVO { - id: number -} - -// 查询学生列表 -export const getDemoStudentPage = async (params) => { - return await request.get({ url: `/infra/demo-student/page`, params }) -} - -// 查询学生详情 -export const getDemoStudent = async (id: number) => { - return await request.get({ url: `/infra/demo-student/get?id=` + id }) -} - -// 新增学生 -export const createDemoStudent = async (data: DemoStudentVO) => { - return await request.post({ url: `/infra/demo-student/create`, data }) -} - -// 修改学生 -export const updateDemoStudent = async (data: DemoStudentVO) => { - return await request.put({ url: `/infra/demo-student/update`, data }) -} - -// 删除学生 -export const deleteDemoStudent = async (id: number) => { - return await request.delete({ url: `/infra/demo-student/delete?id=` + id }) -} - -// 导出学生 Excel -export const exportDemoStudent = async (params) => { - return await request.download({ url: `/infra/demo-student/export-excel`, params }) -} - -// 获得学生联系人列表 -export const getDemoStudentContactListByStudentId = async (studentId) => { - return await request.get({ - url: `/infra/demo-student/demo-student/list-by-student-id?studentId=` + studentId - }) -} - -// 获得学生地址 -export const getDemoStudentAddressByStudentId = async (studentId) => { - return await request.get({ - url: `/infra/demo-student/demo-student/get-by-student-id?studentId=` + studentId - }) -} diff --git a/src/views/infra/demo02/DemoStudentForm.vue b/src/views/infra/demo/demo02/Demo02CategoryForm.vue similarity index 55% rename from src/views/infra/demo02/DemoStudentForm.vue rename to src/views/infra/demo/demo02/Demo02CategoryForm.vue index e9454c0f..9002d5ee 100644 --- a/src/views/infra/demo02/DemoStudentForm.vue +++ b/src/views/infra/demo/demo02/Demo02CategoryForm.vue @@ -6,16 +6,21 @@ :rules="formRules" label-width="100px" v-loading="formLoading" - /> - <!-- 子表的表单 --> - <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> + > + <el-form-item label="名字" prop="name"> + <el-input v-model="formData.name" placeholder="请输入名字" /> + </el-form-item> + <el-form-item label="父级编号" prop="parentId"> + <el-tree-select + v-model="formData.parentId" + :data="demo02CategoryTree" + :props="defaultProps" + check-strictly + default-expand-all + placeholder="请选择父级编号" + /> + </el-form-item> + </el-form> <template #footer> <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> <el-button @click="dialogVisible = false">取 消</el-button> @@ -23,9 +28,8 @@ </Dialog> </template> <script setup lang="ts"> -import * as DemoStudentApi from '@/api/infra/demo02' -import DemoStudentContactForm from './DemoStudentContactForm.vue' -import DemoStudentAddressForm from './DemoStudentAddressForm.vue' +import * as Demo02CategoryApi from '@/api/infra/demo/demo02' +import { defaultProps, handleTree } from '@/utils/tree' const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 @@ -35,15 +39,16 @@ const dialogTitle = ref('') // 弹窗的标题 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 const formType = ref('') // 表单的类型:create - 新增;update - 修改 const formData = ref({ - id: undefined + id: undefined, + name: undefined, + parentId: undefined +}) +const formRules = reactive({ + name: [{ required: true, message: '名字不能为空', trigger: 'blur' }], + parentId: [{ required: true, message: '父级编号不能为空', trigger: 'blur' }] }) -const formRules = reactive({}) const formRef = ref() // 表单 Ref - -/** 子表的表单 */ -const subTabsName = ref('demoStudentContact') -const demoStudentContactFormRef = ref() -const demoStudentAddressFormRef = ref() +const demo02CategoryTree = ref() // 树形结构 /** 打开弹窗 */ const open = async (type: string, id?: number) => { @@ -55,11 +60,12 @@ const open = async (type: string, id?: number) => { if (id) { formLoading.value = true try { - formData.value = await DemoStudentApi.getDemoStudent(id) + formData.value = await Demo02CategoryApi.getDemo02Category(id) } finally { formLoading.value = false } } + await getDemo02CategoryTree() } defineExpose({ open }) // 提供 open 方法,用于打开弹窗 @@ -68,31 +74,15 @@ 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() + const data = formData.value as unknown as Demo02CategoryApi.Demo02CategoryVO if (formType.value === 'create') { - await DemoStudentApi.createDemoStudent(data) + await Demo02CategoryApi.createDemo02Category(data) message.success(t('common.createSuccess')) } else { - await DemoStudentApi.updateDemoStudent(data) + await Demo02CategoryApi.updateDemo02Category(data) message.success(t('common.updateSuccess')) } dialogVisible.value = false @@ -106,8 +96,19 @@ const submitForm = async () => { /** 重置表单 */ const resetForm = () => { formData.value = { - id: undefined + id: undefined, + name: undefined, + parentId: undefined } formRef.value?.resetFields() } -</script> + +/** 获得示例分类树 */ +const getDemo02CategoryTree = async () => { + demo02CategoryTree.value = [] + const data = await Demo02CategoryApi.getDemo02CategoryList() + const root: Tree = { id: 0, name: '顶级示例分类', children: [] } + root.children = handleTree(data, 'id', 'parentId') + demo02CategoryTree.value.push(root) +} +</script> \ No newline at end of file diff --git a/src/views/infra/demo02/index.vue b/src/views/infra/demo/demo02/index.vue similarity index 51% rename from src/views/infra/demo02/index.vue rename to src/views/infra/demo/demo02/index.vue index 89fd656b..e46c77dc 100644 --- a/src/views/infra/demo02/index.vue +++ b/src/views/infra/demo/demo02/index.vue @@ -8,10 +8,35 @@ :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="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:demo02-category:create']" + > <Icon icon="ep:plus" class="mr-5px" /> 新增 </el-button> <el-button @@ -19,28 +44,52 @@ plain @click="handleExport" :loading="exportLoading" - v-hasPermi="['infra:demo-student:export']" + v-hasPermi="['infra:demo02-category:export']" > <Icon icon="ep:download" class="mr-5px" /> 导出 </el-button> + <el-button type="danger" plain @click="toggleExpandAll"> + <Icon icon="ep:sort" class="mr-5px" /> 展开/折叠 + </el-button> </el-form-item> </el-form> </ContentWrap> <!-- 列表 --> <ContentWrap> - <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> + <el-table + v-loading="loading" + :data="list" + :stripe="true" + :show-overflow-tooltip="true" + row-key="id" + :default-expand-all="isExpandAll" + v-if="refreshTable" + > <el-table-column label="编号" align="center" prop="id" /> + <el-table-column label="名字" align="center" prop="name" /> + <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:demo02-category:update']" + > 编辑 </el-button> <el-button link type="danger" @click="handleDelete(scope.row.id)" - v-hasPermi="['infra:demo-student:delete']" + v-hasPermi="['infra:demo02-category:delete']" > 删除 </el-button> @@ -57,25 +106,27 @@ </ContentWrap> <!-- 表单弹窗:添加/修改 --> - <DemoStudentForm ref="formRef" @success="getList" /> + <Demo02CategoryForm ref="formRef" @success="getList" /> </template> <script setup lang="ts"> +import { dateFormatter } from '@/utils/formatTime' +import { handleTree } from '@/utils/tree' import download from '@/utils/download' -import * as DemoStudentApi from '@/api/infra/demo02' -import DemoStudentForm from './DemoStudentForm.vue' +import * as Demo02CategoryApi from '@/api/infra/demo/demo02' +import Demo02CategoryForm from './Demo02CategoryForm.vue' -defineOptions({ name: 'InfraDemoStudent' }) +defineOptions({ name: 'Demo02Category' }) const message = useMessage() // 消息弹窗 const { t } = useI18n() // 国际化 const loading = ref(true) // 列表的加载中 -const total = ref(0) // 列表的总页数 const list = ref([]) // 列表的数据 const queryParams = reactive({ - pageNo: 1, - pageSize: 10 + name: null, + parentId: null, + createTime: [] }) const queryFormRef = ref() // 搜索的表单 const exportLoading = ref(false) // 导出的加载中 @@ -84,13 +135,8 @@ const exportLoading = ref(false) // 导出的加载中 const getList = async () => { loading.value = true try { - // const data = await DemoStudentApi.getDemoStudentPage(queryParams) - list.value = [ - { - id: 1 - } - ] - total.value = 10 + const data = await Demo02CategoryApi.getDemo02CategoryList(queryParams) + list.value = handleTree(data, 'id', 'parentId') } finally { loading.value = false } @@ -110,10 +156,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) } @@ -123,7 +166,7 @@ const handleDelete = async (id: number) => { // 删除的二次确认 await message.delConfirm() // 发起删除 - await DemoStudentApi.deleteDemoStudent(id) + await Demo02CategoryApi.deleteDemo02Category(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() @@ -137,16 +180,26 @@ const handleExport = async () => { await message.exportConfirm() // 发起导出 exportLoading.value = true - const data = await DemoStudentApi.exportDemoStudent(queryParams) - download.excel(data, '学生.xls') + const data = await Demo02CategoryApi.exportDemo02Category(queryParams) + download.excel(data, '示例分类.xls') } catch { } finally { exportLoading.value = false } } +/** 展开/折叠操作 */ +const isExpandAll = ref(true) // 是否展开,默认全部展开 +const refreshTable = ref(true) // 重新渲染表格状态 +const toggleExpandAll = async () => { + refreshTable.value = false + isExpandAll.value = !isExpandAll.value + await nextTick() + refreshTable.value = true +} + /** 初始化 **/ onMounted(() => { getList() }) -</script> +</script> \ No newline at end of file diff --git a/src/views/infra/demo02/DemoStudentAddressForm.vue b/src/views/infra/demo02/DemoStudentAddressForm.vue deleted file mode 100644 index 6d031406..00000000 --- a/src/views/infra/demo02/DemoStudentAddressForm.vue +++ /dev/null @@ -1,126 +0,0 @@ -<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="个人简介"> - <Editor v-model="formData.description" height="150px" /> - </el-form-item> - <el-form-item label="性别 1" prop="sex1"> - <el-select v-model="formData.sex1" placeholder="请选择性别 1"> - <el-option - v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SEX1)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - <el-form-item label="性别 2" prop="sex2"> - <el-checkbox-group v-model="formData.sex2"> - <el-checkbox - v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_SEX2)" - :key="dict.value" - :label="dict.value" - > - {{ dict.label }} - </el-checkbox> - </el-checkbox-group> - </el-form-item> - <el-form-item label="性别 3" prop="sex3"> - <el-radio-group v-model="formData.sex3"> - <el-radio - v-for="dict in getBoolDictOptions(DICT_TYPE.SYSTEM_SEX3)" - :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="memo"> - <el-input v-model="formData.memo" type="textarea" placeholder="请输入备注" /> - </el-form-item> - </el-form> -</template> -<script setup lang="ts"> -import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict' -import * as DemoStudentApi from '@/api/infra/demo02' - -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' }], - avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }], - video: [{ required: true, message: '视频不能为空', trigger: 'blur' }], - description: [{ required: true, message: '个人简介不能为空', trigger: 'blur' }], - sex1: [{ required: true, message: '性别 1不能为空', trigger: 'change' }], - sex2: [{ required: true, message: '性别 2不能为空', trigger: 'blur' }], - sex3: [{ required: true, message: '性别 3不能为空', trigger: 'blur' }], - birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }], - memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }] -}) -const formRef = ref() // 表单 Ref - -/** 监听主表的关联字段的变化,加载对应的子表数据 */ -watch( - () => props.studentId, - async (val) => { - // 情况一:val 为空,说明是新增,则置空 - if (!val) { - formData.value = { - id: undefined, - studentId: undefined, - name: undefined, - avatar: undefined, - video: undefined, - description: undefined, - sex1: undefined, - sex2: [], - sex3: undefined, - birthday: undefined, - memo: undefined - } - return - } - // 情况二:val 非空,说明是修改,则加载数据 - try { - formLoading.value = true - formData.value = await DemoStudentApi.getDemoStudentAddressByStudentId(val) - } finally { - formLoading.value = false - } - }, - { immediate: true } -) - -/** 表单校验 */ -const validate = () => { - return formRef.value.validate() -} - -/** 表单值 */ -const getData = () => { - return formData.value -} - -defineExpose({ validate, getData }) -</script> diff --git a/src/views/infra/demo02/DemoStudentContactForm.vue b/src/views/infra/demo02/DemoStudentContactForm.vue deleted file mode 100644 index 5f173f14..00000000 --- a/src/views/infra/demo02/DemoStudentContactForm.vue +++ /dev/null @@ -1,177 +0,0 @@ -<template> - <el-form - ref="formRef" - :model="formData" - :rules="formRules" - 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="名字" 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="个人简介" width="400"> - <template #default="{ row, $index }"> - <el-form-item - :prop="`${$index}.description`" - :rules="formRules.description" - class="mb-0px!" - > - <Editor v-model="row.description" height="150px" /> - </el-form-item> - </template> - </el-table-column> - <el-table-column label="性别 1" width="150"> - <template #default="{ row, $index }"> - <el-form-item :prop="`${$index}.sex1`" :rules="formRules.sex1" class="mb-0px!"> - <el-select v-model="row.sex1" placeholder="请选择性别 1"> - <el-option - v-for="dict in getStrDictOptions(DICT_TYPE.SYSTEM_SEX1)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - </template> - </el-table-column> - <el-table-column label="性别 2" width="150"> - <template #default="{ row, $index }"> - <el-form-item :prop="`${$index}.sex2`" :rules="formRules.sex2" class="mb-0px!"> - <el-checkbox-group v-model="row.sex2"> - <el-checkbox - v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_SEX2)" - :key="dict.value" - :label="dict.value" - > - {{ dict.label }} - </el-checkbox> - </el-checkbox-group> - </el-form-item> - </template> - </el-table-column> - <el-table-column label="性别 3" width="150"> - <template #default="{ row, $index }"> - <el-form-item :prop="`${$index}.sex3`" :rules="formRules.sex3" class="mb-0px!"> - <el-radio-group v-model="row.sex3"> - <el-radio - v-for="dict in getBoolDictOptions(DICT_TYPE.SYSTEM_SEX3)" - :key="dict.value" - :label="dict.value" - > - {{ dict.label }} - </el-radio> - </el-radio-group> - </el-form-item> - </template> - </el-table-column> - <el-table-column label="出生日期" width="150"> - <template #default="{ row, $index }"> - <el-form-item :prop="`${$index}.birthday`" :rules="formRules.birthday" class="mb-0px!"> - <el-date-picker - v-model="row.birthday" - type="date" - value-format="x" - placeholder="选择出生日期" - /> - </el-form-item> - </template> - </el-table-column> - <el-table-column label="备注" width="200"> - <template #default="{ row, $index }"> - <el-form-item :prop="`${$index}.memo`" :rules="formRules.memo" class="mb-0px!"> - <el-input v-model="row.memo" type="textarea" placeholder="请输入备注" /> - </el-form-item> - </template> - </el-table-column> - </el-table> - </el-form> - <el-row justify="center" class="mt-3"> - <el-button @click="handleAdd" round>+ 添加联系人</el-button> - </el-row> -</template> -<script setup lang="ts"> -import { getIntDictOptions, getStrDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict' -import * as DemoStudentApi from '@/api/infra/demo02' - -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' }], - avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }], - video: [{ required: true, message: '视频不能为空', trigger: 'blur' }], - description: [{ required: true, message: '个人简介不能为空', trigger: 'blur' }], - sex1: [{ required: true, message: '性别 1不能为空', trigger: 'change' }], - sex2: [{ required: true, message: '性别 2不能为空', trigger: 'blur' }], - sex3: [{ required: true, message: '性别 3不能为空', trigger: 'blur' }], - birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }], - memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }] -}) -const formRef = ref() // 表单 Ref - -/** 监听主表的关联字段的变化,加载对应的子表数据 */ -watch( - () => props.studentId, - async (val) => { - // 情况一:val 为空,说明是新增,则置空 - if (!val) { - formData.value = [] - return - } - // 情况二:val 非空,说明是修改,则加载数据 - try { - formLoading.value = true - formData.value = await DemoStudentApi.getDemoStudentContactListByStudentId(val) - } finally { - formLoading.value = false - } - }, - { immediate: true } -) - -/** 新增按钮操作 */ -const handleAdd = () => { - const row = { - id: undefined, - studentId: undefined, - name: undefined, - avatar: undefined, - video: undefined, - description: undefined, - sex1: undefined, - sex2: [], - sex3: undefined, - birthday: undefined, - memo: undefined - } - row.studentId = props.studentId - formData.value.push(row) -} - -/** 删除按钮操作 */ -const handleDelete = (index) => { - formData.value.splice(index, 1) -} - -/** 表单校验 */ -const validate = () => { - return formRef.value.validate() -} - -/** 表单值 */ -const getData = () => { - return formData.value -} - -defineExpose({ validate, getData }) -</script> diff --git a/src/views/infra/demo02/bak/DemoStudentAddressForm.vue b/src/views/infra/demo02/bak/DemoStudentAddressForm.vue deleted file mode 100644 index af4cd8f1..00000000 --- a/src/views/infra/demo02/bak/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>