feat(studentMsg): 换班级支持批量 UI 与串行提交

弹窗改为学生列表+共用目标表单,串行调用现有接口并汇总失败明细。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-09-15 16:58:56 +08:00
1 parent b7175105ed
commit 3de49f732b
1 file changed
+106 -68
@@ -926,41 +926,17 @@
<!-- 换班级对话框 -->
<el-dialog v-model="changeClassDialog.visible" :title="changeClassDialog.title" width="800px" append-to-body>
<el-form ref="changeClassFormRef" :model="changeClassForm" :rules="changeClassRules" label-width="120px">
<!-- 学生基本信息和原班级信息展示 -->
<el-card shadow="never" class="mb-4">
<template #header>
<div class="text-lg font-medium">学生信息</div>
<div class="text-lg font-medium">学生信息(共 {{ changeClassStudents.length }} 人)</div>
</template>
<div class="student-info-grid">
<div class="info-row">
<div class="info-item">
<span class="info-label">学号:</span>
<span class="info-value">{{ changeClassForm.studentNo }}</span>
</div>
<div class="info-item">
<span class="info-label">姓名:</span>
<span class="info-value">{{ changeClassForm.studentName }}</span>
</div>
<div class="info-item">
<span class="info-label">性别:</span>
<span class="info-value">{{ changeClassForm.gender === '0' ? '男' : changeClassForm.gender === '1' ? '女' : '未知' }}</span>
</div>
</div>
<div class="info-row">
<div class="info-item">
<span class="info-label">原学院:</span>
<span class="info-value">{{ changeClassForm.originalCollegeName }}</span>
</div>
<div class="info-item">
<span class="info-label">原专业:</span>
<span class="info-value">{{ changeClassForm.originalMajorName }}</span>
</div>
<div class="info-item">
<span class="info-label">原班级:</span>
<span class="info-value">{{ changeClassForm.originalClassName }}</span>
</div>
</div>
</div>
<el-table :data="changeClassStudents" max-height="240" border size="small">
<el-table-column label="学号" prop="studentNo" min-width="110" />
<el-table-column label="姓名" prop="studentName" min-width="90" />
<el-table-column label="原学院" prop="originalCollegeName" min-width="120" show-overflow-tooltip />
<el-table-column label="原专业" prop="originalMajorName" min-width="120" show-overflow-tooltip />
<el-table-column label="原班级" prop="originalClassName" min-width="120" show-overflow-tooltip />
</el-table>
</el-card>
<!-- 新班级信息选择 -->
@@ -1026,10 +1002,20 @@
</el-row>
</el-card>
</el-form>
<div v-if="changeClassFailList.length" class="mt-3">
<el-alert type="error" :closable="false" title="部分学生提交失败">
<ul class="pl-4 m-0">
<li v-for="(item, idx) in changeClassFailList" :key="idx">{{ item.studentNo }} {{ item.studentName }}:{{ item.reason }}</li>
</ul>
</el-alert>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="changeClassDialog.visible = false">取消</el-button>
<el-button type="primary" @click="submitChangeClass">确定</el-button>
<el-button :disabled="changeClassSubmitting" @click="changeClassDialog.visible = false">取消</el-button>
<el-button type="primary" :loading="changeClassSubmitting" @click="submitChangeClass">
<template v-if="changeClassSubmitting"> 提交中 {{ changeClassProgress.current }}/{{ changeClassProgress.total }} </template>
<template v-else>确定</template>
</el-button>
</div>
</template>
</el-dialog>
@@ -3373,7 +3359,7 @@ const openChangeClassModal = async () => {
studentName: s.name,
gender: s.gender,
originalCollegeId: s.collegeId,
originalCollegeName: s.collegeName,
originalCollegeName: (s as any).collegeName || (s as any).colegeName || '',
originalMajorId: s.majorId,
originalMajorName: s.majorName,
originalClassId: s.classId,
@@ -3474,56 +3460,108 @@ const handleChangeClassMajorChange = async (majorId: string) => {
}
};
/** 提交换班级申请 */
/** 提交换班级申请(支持批量串行) */
const submitChangeClass = async () => {
const formRef = changeClassFormRef.value;
if (!formRef) return;
await formRef.validate(async (valid: boolean) => {
if (valid) {
try {
// 检查是否选择了不同的班级
if (changeClassForm.newClassId === changeClassForm.originalClassId) {
ElMessage.warning('请选择不同的班级进行换班');
return;
if (!valid) return;
if (!changeClassStudents.value.length) {
ElMessage.warning('没有待换班级的学生');
return;
}
const newCollegeName = collegeOptions.value.find((c) => c.id === changeClassForm.newCollegeId)?.label || '';
const newMajorName = majorOptions.value.find((m) => m.id === changeClassForm.newMajorId)?.label || '';
const newClassName = classOptions.value.find((c) => c.id === changeClassForm.newClassId)?.label || '';
const changeTime = proxy?.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}');
changeClassSubmitting.value = true;
changeClassFailList.value = [];
changeClassProgress.value = { current: 0, total: changeClassStudents.value.length };
let successCount = 0;
try {
for (const student of changeClassStudents.value) {
changeClassProgress.value.current += 1;
if (student.originalClassId === undefined || student.originalClassId === null || student.originalClassId === '') {
changeClassFailList.value.push({
studentNo: student.studentNo,
studentName: student.studentName,
reason: '学生信息不完整'
});
continue;
}
if (String(student.originalClassId) === String(changeClassForm.newClassId)) {
changeClassFailList.value.push({
studentNo: student.studentNo,
studentName: student.studentName,
reason: '已在目标班级'
});
continue;
}
const submitData = {
studentId: changeClassForm.studentId,
studentNo: changeClassForm.studentNo,
studentName: changeClassForm.studentName,
originalCollegeId: changeClassForm.originalCollegeId,
originalCollegeName: changeClassForm.originalCollegeName,
originalMajorId: changeClassForm.originalMajorId,
originalMajorName: changeClassForm.originalMajorName,
originalClassId: changeClassForm.originalClassId,
originalClassCode: '', // 可以根据需要获取
originalClassName: changeClassForm.originalClassName,
studentId: student.studentId,
studentNo: student.studentNo,
studentName: student.studentName,
originalCollegeId: student.originalCollegeId,
originalCollegeName: student.originalCollegeName,
originalMajorId: student.originalMajorId,
originalMajorName: student.originalMajorName,
originalClassId: student.originalClassId,
originalClassCode: '',
originalClassName: student.originalClassName,
newCollegeId: changeClassForm.newCollegeId,
newCollegeName: collegeOptions.value.find((c) => c.id === changeClassForm.newCollegeId)?.label || '',
newCollegeName,
newMajorId: changeClassForm.newMajorId,
newMajorName: majorOptions.value.find((m) => m.id === changeClassForm.newMajorId)?.label || '',
newMajorName,
newClassId: changeClassForm.newClassId,
newClassName: classOptions.value.find((c) => c.id === changeClassForm.newClassId)?.label || '',
newClassName,
changeReason: changeClassForm.changeReason,
changeType: '1', // 主动申请
changeTime: proxy?.parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}'),
changeType: '1',
changeTime,
effectiveTime: changeClassForm.effectiveTime,
status: '0' // 未处理状态
status: '0'
};
const res = await service.post('/studentMsg/studentClassChange', submitData);
if (res && res.code === 200) {
ElMessage.success('换班级申请提交成功');
changeClassDialog.visible = false;
await getList(); // 刷新列表
} else {
ElMessage.error(res?.msg || '提交失败');
try {
const res = await service.post('/studentMsg/studentClassChange', submitData);
if (res && res.code === 200) {
successCount += 1;
} else {
changeClassFailList.value.push({
studentNo: student.studentNo,
studentName: student.studentName,
reason: res?.msg || '提交失败'
});
}
} catch (error: any) {
console.error('提交换班级申请失败:', error);
changeClassFailList.value.push({
studentNo: student.studentNo,
studentName: student.studentName,
reason: error?.message || '提交失败,请重试'
});
}
} catch (error) {
console.error('提交换班级申请失败:', error);
ElMessage.error('提交失败,请重试');
}
if (changeClassFailList.value.length === 0) {
ElMessage.success(changeClassStudents.value.length === 1 ? '换班级申请提交成功' : `批量换班级成功(${successCount} 人)`);
changeClassDialog.visible = false;
await getList();
} else if (successCount > 0) {
ElMessage.warning(`成功 ${successCount} 人,失败 ${changeClassFailList.value.length} 人`);
await getList();
} else {
ElMessage.error('全部提交失败,请查看失败明细');
}
} finally {
changeClassSubmitting.value = false;
}
});
};