pangu-user-platform/frontend/src/views/business/member/components/EducationDialog.vue

349 lines
8.9 KiB
Vue
Raw Normal View History

<!--
任教信息编辑弹窗
2026-02-03 20:26:45 +08:00
@author pangu
-->
<template>
<el-dialog
v-model="visible"
:title="isEdit ? '编辑任教信息' : '添加任教信息'"
width="550px"
:close-on-click-modal="false"
destroy-on-close
>
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="80px"
>
<el-form-item label="区域" prop="regionId">
<el-cascader
v-model="regionIds"
:options="regionTree"
:props="{ value: 'regionId', label: 'regionName', checkStrictly: true }"
placeholder="请选择区域"
clearable
style="width: 100%"
@change="handleRegionChange"
/>
</el-form-item>
<el-form-item label="学校" prop="schoolId">
<el-select v-model="form.schoolId" placeholder="请选择学校" clearable style="width: 100%" @change="handleSchoolChange">
<el-option v-for="item in schoolList" :key="item.schoolId" :label="item.schoolName" :value="item.schoolId" />
</el-select>
</el-form-item>
<el-form-item label="年级" prop="schoolGradeId">
<el-select v-model="form.schoolGradeId" placeholder="请选择年级" clearable style="width: 100%" @change="handleGradeChange">
<el-option v-for="item in gradeList" :key="item.id" :label="item.gradeName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="班级" prop="schoolClassId">
<el-select v-model="form.schoolClassId" placeholder="请选择班级" clearable style="width: 100%">
<el-option v-for="item in classList" :key="item.id" :label="item.className" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="学科" prop="subjectId">
<el-select v-model="form.subjectId" placeholder="请选择学科(可选)" clearable style="width: 100%">
<el-option v-for="item in subjectList" :key="item.subjectId" :label="item.subjectName" :value="item.subjectId" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
</template>
</el-dialog>
</template>
<script setup>
import request from '@/utils/request'
import { ElMessage } from 'element-plus'
import { reactive, ref } from 'vue'
import useBaseDataStore from '@/store/modules/baseData'
const baseDataStore = useBaseDataStore()
const emit = defineEmits(['success', 'add', 'update'])
const visible = ref(false)
const isEdit = ref(false)
const formRef = ref(null)
const submitLoading = ref(false)
// 会员ID和任教信息IDmemberId 为 null 表示本地模式)
const memberId = ref(null)
const educationId = ref(null)
// 本地模式下的临时索引
const localIndex = ref(null)
// 区域ID数组用于级联选择器
const regionIds = ref([])
// 表单数据
const form = reactive({
regionId: null,
schoolId: null,
schoolGradeId: null,
schoolClassId: null,
subjectId: null
})
// 表单验证规则
const rules = {
schoolId: [{ required: true, message: '请选择学校', trigger: 'change' }],
schoolGradeId: [{ required: true, message: '请选择年级', trigger: 'change' }],
schoolClassId: [{ required: true, message: '请选择班级', trigger: 'change' }]
}
// 下拉选项数据
const regionTree = ref([])
const schoolList = ref([])
const gradeList = ref([])
const classList = ref([])
const subjectList = ref([])
/**
* 打开弹窗
* @param {Long} mId 会员IDnull 表示本地模式
* @param {Object} row 编辑时传入任教信息数据
* @param {Number} index 本地模式下的数组索引
*/
const open = async (mId, row, index) => {
resetForm()
memberId.value = mId
isEdit.value = !!row
localIndex.value = index ?? null
visible.value = true
// 加载基础数据
await Promise.all([loadRegionTree(), loadSubjectList()])
// 编辑模式
if (row) {
educationId.value = row.educationId
form.schoolId = row.schoolId
form.schoolGradeId = row.schoolGradeId
form.schoolClassId = row.schoolClassId
form.subjectId = row.subjectId
// 加载关联数据
if (row.regionId) {
// 本地模式下 regionIds 可能已有值
if (row.regionIds) {
regionIds.value = row.regionIds
} else {
regionIds.value = await getRegionPath(row.regionId)
}
form.regionId = row.regionId
await loadSchoolList(row.regionId)
}
if (row.schoolId) {
await loadGradeList(row.schoolId)
}
if (row.schoolGradeId) {
await loadClassList(row.schoolGradeId)
}
}
}
/**
* 重置表单
*/
const resetForm = () => {
educationId.value = null
regionIds.value = []
form.regionId = null
form.schoolId = null
form.schoolGradeId = null
form.schoolClassId = null
form.subjectId = null
schoolList.value = []
gradeList.value = []
classList.value = []
}
/**
* 加载区域树使用 Store 缓存
*/
const loadRegionTree = async () => {
try {
regionTree.value = await baseDataStore.fetchRegionTree()
} catch (e) {
regionTree.value = []
}
}
/**
* 加载学科列表使用 Store 缓存
*/
const loadSubjectList = async () => {
try {
subjectList.value = await baseDataStore.fetchSubjects()
} catch (e) {
subjectList.value = []
}
}
/**
* 加载学校列表
*/
const loadSchoolList = async (regionId) => {
try {
const res = await request.get('/business/school/listAll', { params: { regionId } })
schoolList.value = res.data || []
} catch (e) {
schoolList.value = []
}
}
/**
* 加载年级列表
*/
const loadGradeList = async (schoolId) => {
try {
const res = await request.get(`/business/school/${schoolId}/grades`)
gradeList.value = res.data || []
} catch (e) {
gradeList.value = []
}
}
/**
* 加载班级列表
*/
const loadClassList = async (schoolGradeId) => {
try {
const res = await request.get(`/business/school/grade/${schoolGradeId}/classes`)
classList.value = res.data || []
} catch (e) {
classList.value = []
}
}
/**
* 获取区域路径用于回显
*/
const getRegionPath = async (regionId) => {
try {
const res = await request.get(`/business/region/${regionId}/path`)
return res.data || []
} catch (e) {
return []
}
}
/**
* 区域变更
*/
const handleRegionChange = (val) => {
form.regionId = val && val.length ? val[val.length - 1] : null
form.schoolId = null
form.schoolGradeId = null
form.schoolClassId = null
schoolList.value = []
gradeList.value = []
classList.value = []
if (form.regionId) {
loadSchoolList(form.regionId)
}
}
/**
* 学校变更
*/
const handleSchoolChange = () => {
form.schoolGradeId = null
form.schoolClassId = null
gradeList.value = []
classList.value = []
if (form.schoolId) {
loadGradeList(form.schoolId)
}
}
/**
* 年级变更
*/
const handleGradeChange = () => {
form.schoolClassId = null
classList.value = []
if (form.schoolGradeId) {
loadClassList(form.schoolGradeId)
}
}
/**
* 提交表单
*/
const handleSubmit = async () => {
try {
await formRef.value?.validate()
} catch (e) {
return
}
// 构建数据(包含名称用于本地展示)
const data = {
regionId: form.regionId,
regionIds: [...regionIds.value],
schoolId: form.schoolId,
schoolGradeId: form.schoolGradeId,
schoolClassId: form.schoolClassId,
subjectId: form.subjectId,
// 添加名称用于列表展示
schoolName: schoolList.value.find(s => s.schoolId === form.schoolId)?.schoolName || '',
gradeName: gradeList.value.find(g => g.id === form.schoolGradeId)?.gradeName || '',
className: classList.value.find(c => c.id === form.schoolClassId)?.className || '',
subjectName: subjectList.value.find(s => s.subjectId === form.subjectId)?.subjectName || ''
}
// 本地模式:返回数据给父组件
if (!memberId.value) {
visible.value = false
if (isEdit.value) {
emit('update', data, localIndex.value)
} else {
emit('add', data)
}
return
}
// 远程模式:调用 API
submitLoading.value = true
try {
const apiData = {
regionId: form.regionId,
schoolId: form.schoolId,
schoolGradeId: form.schoolGradeId,
schoolClassId: form.schoolClassId,
subjectId: form.subjectId
}
if (isEdit.value) {
const res = await request.put(`/business/member/${memberId.value}/educations/${educationId.value}`, apiData)
if (res.code === 200) {
ElMessage.success('修改成功')
visible.value = false
emit('success')
}
} else {
const res = await request.post(`/business/member/${memberId.value}/educations`, apiData)
if (res.code === 200) {
ElMessage.success('添加成功')
visible.value = false
emit('success')
}
}
} finally {
submitLoading.value = false
}
}
defineExpose({ open })
</script>