فهرست منبع

下一个学生跳转 显示已批改数/未批改数开发

WCG2025 1 سال پیش
والد
کامیت
48292dd5d7

+ 18 - 1
src/apis/engagement.ts

@@ -64,7 +64,24 @@ const engagementApis = {
                 assignmentId
             }
         })
-    }
+    },
+    // 获取下一个学生的ID
+    getNextStudentId: (assignmentId: number, studentId: number) => {
+        return axiosInstance.get(`${ENGAGE_PREFIX}/next`, {
+            params: {
+                assignmentId,
+                studentId
+            }
+        });
+    },
+    // 获取作业的批改统计
+    getEngagementStats: (assignmentId: number) => {
+    return axiosInstance.get(`${ENGAGE_PREFIX}/number`, {
+      params: {
+        assignmentId
+      }
+    });
+  }
 }
 
 export default engagementApis

+ 148 - 49
src/router/index.ts

@@ -16,13 +16,17 @@ const router = createRouter({
     },
 
     // 登录与注册
+    // {
+    //   path: "/",
+    //   redirect: () => {
+    //     window.location.href = "https://p-nju.seec.seecoder.cn/login?from=https://air.seec.seecoder.cn/";
+    //     // {本地门户首页地址}?from={本地eai首页地址}
+    //     return "/"; // 占位返回值,实际不会执行
+    // },
+    // },
     {
       path: "/",
-      redirect: () => {
-        window.location.href = "https://p-nju.seec.seecoder.cn/login?from=https://air.seec.seecoder.cn/";
-        // {本地门户首页地址}?from={本地eai首页地址}
-        return "/"; // 占位返回值,实际不会执行
-    },
+      redirect: "/login"
     },
     {
       path: '/login',
@@ -180,54 +184,149 @@ const router = createRouter({
   ]
 })
 
-/*
-  路由守卫
- */
-  router.beforeEach(async (to) => {
-    const store = useStore();
-    const publicPaths = ['/login', '/register', '/passwordChange', '/admin/login'];
-    // 1. 检查URL中的token
-    const urlToken = new URLSearchParams(window.location.search).get('token');
-    if (urlToken) {
-      try {
-        // 等待 token 验证完成
-        const res = await authApis.authToken(urlToken || store.token);
-        const data = res.data.data;
-        // 存储用户状态
-        store.setUser(data);
-        store.setToken(data?.token);
-        localStorage.setItem('Authorization', data?.token);
-        localStorage.setItem('User', JSON.stringify(data));
-        // 清除 URL 中的 token
-        if (urlToken) {
-            window.history.replaceState({}, '', to.path);
-        }
+// /*
+//   路由守卫
+//  */
+//   router.beforeEach(async (to) => {
+//     const store = useStore();
+//     const publicPaths = ['/login', '/register', '/passwordChange', '/admin/login'];
+//     // 1. 检查URL中的token
+//     const urlToken = new URLSearchParams(window.location.search).get('token');
+//     if (urlToken) {
+//       try {
+//         // 等待 token 验证完成
+//         const res = await authApis.authToken(urlToken || store.token);
+//         const data = res.data.data;
+//         // 存储用户状态
+//         store.setUser(data);
+//         store.setToken(data?.token);
+//         localStorage.setItem('Authorization', data?.token);
+//         localStorage.setItem('User', JSON.stringify(data));
+//         // 清除 URL 中的 token
+//         if (urlToken) {
+//             window.history.replaceState({}, '', to.path);
+//         }
 
-        // 如果当前路径是公开路径,允许继续;否则跳转到首页
-        if (!publicPaths.includes(to.path)) {
-            return '/home';
-        }
-    } catch (error) {
-        console.error('Token验证失败:', error);
-        // 验证失败,清除无效的 token
-        store.setUser(null);
-        store.setToken(null);
-        localStorage.removeItem('Authorization');
-        localStorage.removeItem('User');
-    }
-    }
+//         // 如果当前路径是公开路径,允许继续;否则跳转到首页
+//         if (!publicPaths.includes(to.path)) {
+//             return '/home';
+//         }
+//     } catch (error) {
+//         console.error('Token验证失败:', error);
+//         // 验证失败,清除无效的 token
+//         store.setUser(null);
+//         store.setToken(null);
+//         localStorage.removeItem('Authorization');
+//         localStorage.removeItem('User');
+//     }
+//     }
   
-    if (publicPaths.includes(to.path)) return true;
+//     if (publicPaths.includes(to.path)) return true;
   
-    if (!store.user?.role) {
-      return '/login';
-    }
+//     if (!store.user?.role) {
+//       return '/login';
+//     }
   
-    if (to.meta?.roles && !to.meta.roles.includes(store.user.role)) {
-      return '/login';
-    }
+//     if (to.meta?.roles && !to.meta.roles.includes(store.user.role)) {
+//       return '/login';
+//     }
   
-    return true;
-  });
+//     return true;
+//   });
 
 export default router
+
+// import { createRouter, createWebHistory } from 'vue-router'
+
+// const router = createRouter({
+//   history: createWebHistory(import.meta.env.BASE_URL),
+//   routes: [
+//     {
+//       path: "/",
+//       redirect: "/login"
+//     },
+//     {
+//       path: '/login',
+//       name: 'login',
+//       component: () => import('../views/LoginPage/LoginPage.vue')
+//     },
+//     {
+//       path: '/register',
+//       name: 'register', 
+//       component: () => import('../views/LoginPage/RegisterPage.vue')
+//     },
+//     {
+//       path: '/course',
+//       name: 'course',
+//       component: () => import('../views/CoursePage/CoursePage.vue')
+//     },
+//     {
+//       path: '/home',
+//       name: 'home',
+//       redirect: '/home/courseSquare',
+//       component: () => import('../layout/Layout/Layout.vue'),
+//       children: [
+//         {
+//           path: 'courseSquare',
+//           name: 'courseSquare',
+//           component: () => import("../views/CourseSquare/index.vue")
+//         },
+//         {
+//           path: 'courseDetail/:courseId',
+//           name: 'courseDetail',
+//           component: () => import("../views/CourseSquare/component/CourseDetails/index.vue")
+//         },
+//         {
+//           path: 'moreCourse',
+//           name: 'moreCourse',
+//           component: () => import("../views/CourseSquare/component/AllCourse/MoreCourse.vue"),
+//           props(route) {
+//             return route.query
+//           },
+//         },
+//         {
+//           path: 'myCourse',
+//           name: 'myCourse',
+//           component: () => import("../views/CoursePage/CoursePage.vue")
+//         },
+//         {
+//           path: 'myHomework',
+//           name: 'myHomework',
+//           component: () => import("@/views/HomeworkPage/index.vue")
+//         },
+//         {
+//           path: 'homeworkDetail/:assignmentId',
+//           name: 'homeworkDetail',
+//           component: () => import("@/views/HomeworkPage/component/HomeworkDetail.vue")
+//         },
+//         {
+//           path: 'assignment/:assignmentId/edit',
+//           name: 'edit',
+//           component: () => import('../views/EditPage/EditPage.vue')
+//         },
+//         {
+//           path: 'assignment/:assignmentId/correct',
+//           name: 'correct',
+//           component: () => import('../views/CorrectPage/CorrectPage.vue')
+//         },
+//         {
+//           path: 'myCorrect/course',
+//           name: 'myCorrectWithCourse',
+//           component: () => import("@/views/CorrectPage/CoursePage.vue")
+//         },
+//         {
+//           path: 'myCorrect/assignment',
+//           name: 'myCorrectWithAssignment',
+//           component: () => import("@/views/CorrectPage/AssignmentPage.vue")
+//         },
+//         {
+//           path: 'myCorrect/assignment/:assignmentId',
+//           name: 'myCorrectWithAssignmentId',
+//           component: () => import("@/views/CorrectPage/CorrectAssignmentPage.vue")
+//         },
+//       ]
+//     },
+//   ]
+// })
+
+// export default router

+ 93 - 4
src/views/AiSpeakingPage/SpeakingRecord.vue

@@ -251,9 +251,29 @@
               score-template="{value} 分"
             />
           </div>
-          <el-button style="background-color:#597D3B;color:white" @click="submitComment" class="submit-button"
+          <!-- <el-button style="background-color:#597D3B;color:white" @click="submitComment" class="submit-button"
             >提交评语</el-button
-          >
+          > -->
+          <div class="submit-next-group">
+            <el-button 
+              style="background-color:#597D3B;color:white" 
+              @click="submitComment" 
+              class="submit-button"
+            >
+              提交评语
+            </el-button>
+            <el-button
+              style="background-color:#597D3B;color:white"  
+              class="next-button" 
+              @click="goToNextStudent"
+            >
+              下一个学生
+            </el-button>
+          </div>
+          <div class="engagement-stats">
+            已批改:{{ engagementStats.correctNumber }}
+            未批改:{{ engagementStats.engageNumber - engagementStats.correctNumber }}
+          </div>
         </template>
       </div>
     </el-card>
@@ -319,6 +339,11 @@ const engagement = ref({
   remark: "",
 });
 
+const engagementStats = ref({
+  correctNumber: 0,
+  engageNumber: 0,
+});
+
 const isSuggestionLoading = ref(true);
 const isVideoEmotionLoading = ref(true);
 
@@ -370,6 +395,47 @@ const createEmotionPieChart = (emotionList) => {
   window.addEventListener("resize", () => emotionChartInstance.resize());
 };
 
+// 跳转到下一个学生
+const goToNextStudent = async () => {
+  try {
+    // 获取下一个学生的 ID
+    const nextStudentRes = await engagementApis.getNextStudentId(props.assignmentId, props.userId);
+    if (nextStudentRes.data.code !== 200 || !nextStudentRes.data.data) {
+      ElMessage.error("获取下一个学生失败");
+      return;
+    }
+
+    // 获取当前作业的批改统计数据
+    const statsRes = await engagementApis.getEngagementStats(props.assignmentId);
+    if (statsRes.data.code !== 200 || !statsRes.data.data) {
+      ElMessage.error("获取批改统计数据失败");
+      return;
+    }
+
+    const { engageNumber, correctNumber } = statsRes.data.data;
+
+    // 判断是否已经完成所有批改
+    if (correctNumber === engageNumber) {
+      ElMessage.info("已全部批改完毕");
+      router.push(`/home/myCorrect/assignment/${props.assignmentId}`);
+      return;
+    }
+
+    // 如果未完成所有批改,跳转到下一个学生
+    const nextStudentId = nextStudentRes.data.data;
+    router.push({
+      path: `/home/myCorrect/assignment/${props.assignmentId}/airecord`,
+      query: {
+      userId: nextStudentId,
+      assignmentId: props.assignmentId,
+      assignmentName: props.assignmentName || ''
+  },
+});
+  } catch (err) {
+    console.error("跳转失败", err);
+    ElMessage.error("获取下一个学生或批改统计数据失败");
+  }
+};
 // 提交评语
 const submitComment = async () => {
   if (!engagement.value.remark || engagement.value.score === 0) {
@@ -840,6 +906,17 @@ onMounted(async () => {
         speakingAIDialogue.value.videoAnalysis.emotion_percentage_dict
       );
     }
+
+    const statsRes = await engagementApis.getEngagementStats(props.assignmentId);
+    if (statsRes.data.code === 200 && statsRes.data.data) {
+      engagementStats.value = {
+        correctNumber: statsRes.data.data.correctNumber,
+       engageNumber: statsRes.data.data.engageNumber
+      };
+    } else {
+      console.warn("获取批改统计失败");
+    }
+
     const engagementRes = await engagementApis.getEngagement(
       props.userId,
       props.assignmentId
@@ -1050,8 +1127,8 @@ onMounted(async () => {
   margin-left: 40%;
 }
 
-.submit-button {
-  width: 30%;
+.submit-button ,.next-button{
+  width: 300px;
   margin-top: 50px;
 }
 
@@ -1106,4 +1183,16 @@ onMounted(async () => {
 .el-card {
   margin-bottom: 30px !important;
 }
+
+.submit-next-group {
+  display: flex;
+  justify-content: center;
+  /* gap: 20px; */
+  margin-top: 50px;
+}
+
+.engagement-stats
+{
+  margin: 0 auto;
+}
 </style>

+ 126 - 1
src/views/CorrectPage/CorrectPage.vue

@@ -31,6 +31,15 @@
         <Remark :studentId="studentId" :assignmentId="assignmentId" />
       </div>
 
+      <div class="my-correct-number">
+        已批改:{{ engagementStats.correctNumber }}
+        未批改:{{ engagementStats.engageNumber - engagementStats.correctNumber }}
+      </div>
+
+      <div class="my-correct-next">
+        <el-button color="#597D3B" @click="goToNextStudent">下一个</el-button>
+      </div>
+
       <div class="my-correct-goback">
         <el-button color="#597D3B" @click="goBack">返回</el-button>
       </div>
@@ -75,7 +84,7 @@ import { useRoute } from 'vue-router'
 import StudentEssay from "../Home/component/StudentEssay/StudentEssay.vue";
 import StudentWritingRequirements from "../Home/component/StudentEssay/StudentWritingRequirements.vue";
 import Remark from "../Home/component/Remark/Remark.vue";
-
+import { ElMessage } from 'element-plus';
 
 // 获得路由中的assignmentId
 const route = useRoute()
@@ -99,6 +108,11 @@ const dataForm = reactive<{
   engagement: {} as engagementVO
 })
 
+const engagementStats = reactive({
+  engageNumber: 0,
+  correctNumber: 0
+});
+
 // 获取数据
 async function fetchData() {
   await apis.getAIDialogues(assignmentId, studentId)
@@ -122,6 +136,17 @@ async function fetchData() {
       console.log(_err)
       router.push("/login")
     })
+
+    await apis.getEngagementStats(assignmentId)
+    .then((_res: any) => {
+      if (_res.data.code === 200 && _res.data.data) {
+        engagementStats.engageNumber = _res.data.data.engageNumber;
+        engagementStats.correctNumber = _res.data.data.correctNumber;
+      }
+    })
+    .catch((err: any) => {
+      console.error("获取批改统计数据失败", err);
+    });
 }
 
 const getBehaviorRecords = () => {
@@ -147,6 +172,106 @@ const downloadAllFiles = () => {
   showDialog.value = false;
 };
 
+
+//跳转到下一个学生
+const goToNextStudent = async () => {
+  try {
+    // 获取当前作业的批改统计数据
+    const statsRes = await apis.getEngagementStats(assignmentId);
+    if (statsRes.data.code !== 200 || !statsRes.data.data) {
+      ElMessage.error("获取批改统计数据失败");
+      return;
+    }
+
+    const { engageNumber, correctNumber } = statsRes.data.data;
+
+    // 判断是否已经完成所有批改
+    if (correctNumber === engageNumber) 
+      {
+      ElMessage.info("已全部批改完毕");
+      router.push(`/home/myCorrect/assignment/${assignmentId}`);
+      return;
+    }
+
+    // 获取下一个学生的 ID
+    const nextStudentRes = await apis.getNextStudentId(assignmentId, studentId);
+    if (nextStudentRes.data.code !== 200 || !nextStudentRes.data.data) 
+    {
+      ElMessage.error("获取下一个学生失败");
+      return;
+    }
+
+    const nextStudentId = nextStudentRes.data.data;
+
+    // 如果未完成所有批改,跳转到下一个学生
+    router.push({
+      path: `/home/myCorrect/assignment/${assignmentId}`,
+      query: { studentId: nextStudentId },
+    });
+  } catch (err) {
+    console.error("跳转失败", err);
+    ElMessage.error("获取下一个学生或批改统计数据失败");
+  }
+};
+
+
+// const goToNextStudent = async () => {
+//   try {
+//     const res = await apis.getNextStudentId(assignmentId, studentId);
+//     if (res.data.code === 200) {
+//       const nextStudentId = res.data.data;
+//       if (nextStudentId && nextStudentId !== -1) {
+//         router.push(`/home/myCorrect/assignment/${assignmentId}?studentId=${nextStudentId}`);
+//       } else {
+//         ElMessage.success("所有作业已批改完成!");
+//         router.push(`/home/myCorrect/assignment/${assignmentId}`);
+//       }
+//     } else {
+//       ElMessage.error("获取下一个学生失败" + res.data.msg);
+//     }
+//   } catch (err) {
+//     console.log(err);
+//     ElMessage.error("请求失败,请稍后重试");
+//   }
+// };
+
+// const goToNextStudent = async () => {
+//   try {
+//     // 获取下一个学生的 ID
+//     const nextStudentRes = await apis.getNextStudentId(assignmentId, studentId);
+//     if (nextStudentRes.data.code !== 200 || !nextStudentRes.data.data) {
+//       ElMessage.error("获取下一个学生失败");
+//       return;
+//     }
+
+//     // 获取当前作业的批改统计数据
+//     const statsRes = await apis.getEngagementStats(assignmentId);
+//     if (statsRes.data.code !== 200 || !statsRes.data.data) {
+//       ElMessage.error("获取批改统计数据失败");
+//       return;
+//     }
+    
+
+//     const { engageNumber, correctNumber } = statsRes.data.data;
+
+//     // 判断是否已经完成所有批改
+//     if (correctNumber === engageNumber) 
+//       {
+//       ElMessage.info("已全部批改完毕");
+//       router.push(`/home/myCorrect/assignment/${assignmentId}`);
+//       return;
+//     }
+
+//     // 如果未完成所有批改,跳转到下一个学生
+//     const nextStudentId = nextStudentRes.data.data;
+//     router.push(`/home/myCorrect/assignment/${assignmentId}?studentId=${nextStudentId}`);
+//   } catch (err) {
+//     console.error("跳转失败", err);
+//     ElMessage.error("获取下一个学生或批改统计数据失败");
+//   }
+// };
+
+
 onMounted(() => {
   fetchData()
   getBehaviorRecords()

+ 12 - 1
src/views/CorrectPage/index.scss

@@ -11,6 +11,12 @@
       bottom: 5vh;  
       right: 3vh; 
     }
+
+    .my-correct-next{
+      position: absolute;
+      bottom: 5vh;
+      right: 15vh;
+    } 
   
     .my-correct-header {
       width: 50%;
@@ -46,7 +52,12 @@
         //border: 1px solid black;
         background-color: #fff;
       }
-
+      .my-correct-number
+      {
+        position: absolute;
+        bottom: 6vh;
+        right: 28vh;
+      }
 
     }
  

+ 1 - 1
src/views/Home/component/Remark/Remark.vue

@@ -79,7 +79,7 @@ export default defineComponent({
             .then(res => {
               if (res.data.code === 200) {
                 ElMessage.success("批改成功");
-                router.push(`/home/myCorrect/assignment/${props.assignmentId}`);
+             //   router.push(`/home/myCorrect/assignment/${props.assignmentId}`);
               } else {
                 ElMessage.error("批改异常" + res.data.msg);
               }