Jelajahi Sumber

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

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

Co-authored-by: Cursor <cursoragent@cursor.com>
zlwu 1 bulan lalu
induk
melakukan
3de49f732b
1 mengubah file dengan 106 tambahan dan 68 penghapusan
  1. 106 68
      web/src/views/xg/xsjcxx/studentMsg/studentMsg/index.vue

+ 106 - 68
web/src/views/xg/xsjcxx/studentMsg/studentMsg/index.vue

@@ -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;
     }
   });
 };