潘志宝
2024-09-09 ed81b7371e376df35448b81531d30dd9024bd44a
提交 | 用户 | 时间
e7c126 1 <template>
H 2   <Dialog :title="dialogTitle" v-model="dialogVisible">
3     <el-form
4       ref="formRef"
5       :model="formData"
6       :rules="formRules"
7       label-width="100px"
8       v-loading="formLoading"
9     >
10       <el-form-item label="名字" prop="name">
11         <el-input v-model="formData.name" placeholder="请输入名字" />
12       </el-form-item>
13       <el-form-item label="简介" prop="description">
14         <el-input v-model="formData.description" type="textarea" placeholder="请输入简介" />
15       </el-form-item>
16       <el-form-item label="出生日期" prop="birthday">
17         <el-date-picker
18           v-model="formData.birthday"
19           type="date"
20           value-format="x"
21           placeholder="选择出生日期"
22         />
23       </el-form-item>
24       <el-form-item label="性别" prop="sex">
25         <el-select v-model="formData.sex" placeholder="请选择性别">
26           <el-option
27             v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_USER_SEX)"
28             :key="dict.value"
29             :label="dict.label"
30             :value="dict.value"
31           />
32         </el-select>
33       </el-form-item>
34       <el-form-item label="是否有效" prop="enabled">
35         <el-radio-group v-model="formData.enabled">
36           <el-radio
37             v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
38             :key="dict.value"
39             :label="dict.value"
40           >
41             {{ dict.label }}
42           </el-radio>
43         </el-radio-group>
44       </el-form-item>
45       <el-form-item label="头像" prop="avatar">
46         <UploadImg v-model="formData.avatar" />
47       </el-form-item>
48       <el-form-item label="附件" prop="video">
49         <UploadFile v-model="formData.video" />
50       </el-form-item>
51       <el-form-item label="备注" prop="memo">
52         <Editor v-model="formData.memo" height="150px" />
53       </el-form-item>
54     </el-form>
55     <!-- 子表的表单 -->
56     <el-tabs v-model="subTabsName">
57       <el-tab-pane label="学生联系人" name="studentContact">
58         <StudentContactForm ref="studentContactFormRef" :student-id="formData.id" />
59       </el-tab-pane>
60       <el-tab-pane label="学生班主任" name="studentTeacher">
61         <StudentTeacherForm ref="studentTeacherFormRef" :student-id="formData.id" />
62       </el-tab-pane>
63     </el-tabs>
64     <template #footer>
65       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
66       <el-button @click="dialogVisible = false">取 消</el-button>
67     </template>
68   </Dialog>
69 </template>
70 <script setup lang="ts">
71 import { getIntDictOptions, getBoolDictOptions, DICT_TYPE } from '@/utils/dict'
72 import * as StudentApi from '@/api/infra/demo'
73 import StudentContactForm from './components/StudentContactForm.vue'
74 import StudentTeacherForm from './components/StudentTeacherForm.vue'
75
76 const { t } = useI18n() // 国际化
77 const message = useMessage() // 消息弹窗
78
79 const dialogVisible = ref(false) // 弹窗的是否展示
80 const dialogTitle = ref('') // 弹窗的标题
81 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
82 const formType = ref('') // 表单的类型:create - 新增;update - 修改
83 const formData = ref({
84   id: undefined,
85   name: undefined,
86   description: undefined,
87   birthday: undefined,
88   sex: undefined,
89   enabled: undefined,
90   avatar: undefined,
91   video: undefined,
92   memo: undefined,
93 })
94 const formRules = reactive({
95   name: [{ required: true, message: '名字不能为空', trigger: 'blur' }],
96   description: [{ required: true, message: '简介不能为空', trigger: 'blur' }],
97   birthday: [{ required: true, message: '出生日期不能为空', trigger: 'blur' }],
98   sex: [{ required: true, message: '性别不能为空', trigger: 'change' }],
99   enabled: [{ required: true, message: '是否有效不能为空', trigger: 'blur' }],
100   avatar: [{ required: true, message: '头像不能为空', trigger: 'blur' }],
101   video: [{ required: true, message: '附件不能为空', trigger: 'blur' }],
102   memo: [{ required: true, message: '备注不能为空', trigger: 'blur' }],
103 })
104 const formRef = ref() // 表单 Ref
105
106 /** 子表的表单 */
107 const subTabsName = ref('studentContact')
108 const studentContactFormRef = ref()
109 const studentTeacherFormRef = ref()
110
111 /** 打开弹窗 */
112 const open = async (type: string, id?: number) => {
113   dialogVisible.value = true
114   dialogTitle.value = t('action.' + type)
115   formType.value = type
116   resetForm()
117   // 修改时,设置数据
118   if (id) {
119     formLoading.value = true
120     try {
121       formData.value = await StudentApi.getStudent(id)
122     } finally {
123       formLoading.value = false
124     }
125   }
126 }
127 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
128
129 /** 提交表单 */
130 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
131 const submitForm = async () => {
132   // 校验表单
133   await formRef.value.validate()
134   // 校验子表单
135   try {
136     await studentContactFormRef.value.validate()
137   } catch (e) {
138     subTabsName.value = 'studentContact'
139     return
140   }
141   try {
142     await studentTeacherFormRef.value.validate()
143   } catch (e) {
144     subTabsName.value = 'studentTeacher'
145     return
146   }
147   // 提交请求
148   formLoading.value = true
149   try {
150     const data = formData.value as unknown as StudentApi.StudentVO
151     // 拼接子表的数据
152     data.studentContacts = studentContactFormRef.value.getData()
153     data.studentTeacher = studentTeacherFormRef.value.getData()
154     if (formType.value === 'create') {
155       await StudentApi.createStudent(data)
156       message.success(t('common.createSuccess'))
157     } else {
158       await StudentApi.updateStudent(data)
159       message.success(t('common.updateSuccess'))
160     }
161     dialogVisible.value = false
162     // 发送操作成功的事件
163     emit('success')
164   } finally {
165     formLoading.value = false
166   }
167 }
168
169 /** 重置表单 */
170 const resetForm = () => {
171   formData.value = {
172     id: undefined,
173     name: undefined,
174     description: undefined,
175     birthday: undefined,
176     sex: undefined,
177     enabled: undefined,
178     avatar: undefined,
179     video: undefined,
180     memo: undefined,
181   }
182   formRef.value?.resetFields()
183 }
184 </script>