Procházet zdrojové kódy

补交功能开发完毕

Jiang Pengyu před 1 rokem
rodič
revize
ddb7e936de

+ 3 - 2
src/apis/engagement.ts

@@ -27,11 +27,12 @@ const engagementApis = {
         })
     },
     // 提交作业
-    engagementSubmit: (studentId: number, assignmentId: number) => {
+    engagementSubmit: (studentId: number, assignmentId: number,supplementarySubmission:boolean) => {
         return axiosInstance.put(ENGAGE_PREFIX+"/submit", {}, {
             params: {
                 studentId,
-                assignmentId
+                assignmentId,
+                supplementarySubmission
             }
         })
     },

+ 12 - 0
src/views/CorrectPage/CorrectPage.vue

@@ -69,6 +69,12 @@
           <span class="student-name">{{ studentInfo.name }}</span>
           <span class="class-label">所属班级:</span>
           <span class="class-name">{{ studentInfo.className || '信息与计算科学(强基计划)' }}</span>
+          <span 
+            v-if="!isStudent && isLateSubmission" 
+            class="late-submission-badge"
+          >
+            补交
+          </span>
         </div>
         <div class="student-answer-content">
           {{ studentAnswer }}
@@ -345,6 +351,12 @@ const isAllCorrected = computed(() => {
 // 判断当前用户是否为学生
 const isStudent = computed(() => store.user.role === 'STUDENT');
 
+// 判断是否为补交状态
+const isLateSubmission = computed(() => {
+  const status = dataForm.engagement?.status;
+  return status === 'LATE_SUBMITTED' || status === 'LATE_SUBMITTED_CORRECTED';
+});
+
 const dataForm = reactive<{
   messages: IDialogue[],
   dialogueId: string;

+ 59 - 10
src/views/CorrectPage/CoursePage.vue

@@ -138,6 +138,8 @@
                 <el-option label="未提交" value="未提交"></el-option>
                 <el-option label="已提交未批改" value="已提交未批改"></el-option>
                 <el-option label="已批改" value="已批改"></el-option>
+                <el-option label="补交_未批改" value="补交_未批改"></el-option>
+                <el-option label="补交_已批改" value="补交_已批改"></el-option>
               </el-select>
               <el-select v-model="classFilter" placeholder="班级" class="filter-select" @change="handleClassFilterChange">
                 <el-option label="全部" value=""></el-option>
@@ -183,7 +185,13 @@
                   </span>
                 </template>
               </el-table-column>
-              <el-table-column label="备注" width="230"></el-table-column>
+              <el-table-column label="备注" width="230">
+                <template #default="scope">
+                  <span v-if="isLateSubmission(scope.row.status)" class="late-submission-badge">
+                    补交
+                  </span>
+                </template>
+              </el-table-column>
               <el-table-column label="操作" width="230">
                 <template #default="scope">
                   <el-button 
@@ -489,7 +497,9 @@
   const statusMap = {
     'NOT_SUBMITTED': '未提交',
     'SUBMITTED': '已提交未批改', 
-    'CORRECTED': '已批改'
+    'CORRECTED': '已批改',
+    'LATE_SUBMITTED': '补交_未批改',
+    'LATE_SUBMITTED_CORRECTED': '补交_已批改'
   }
   
   // 当前页码
@@ -607,9 +617,9 @@
   
   // 获取用于排序的分数值
   const getScoreForSort = (student: StudentAssignmentStatusDTO) => {
-    if (student.status === 'CORRECTED' && student.score !== null) {
+    if ((student.status === 'CORRECTED' || student.status === 'LATE_SUBMITTED_CORRECTED') && student.score !== null) {
       return student.score
-    } else if (student.status === 'SUBMITTED') {
+    } else if (student.status === 'SUBMITTED' || student.status === 'LATE_SUBMITTED') {
       return -1 // 未批改排在未提交前面
     } else {
       return -2 // 未提交排在最后
@@ -639,8 +649,8 @@
   // 获取分数样式类
   const getScoreClass = (row: StudentAssignmentStatusDTO) => {
     if (row.status === 'NOT_SUBMITTED') return 'score-not-submitted'
-    if (row.status === 'SUBMITTED') return 'score-not-graded'
-    if (row.status === 'CORRECTED' && row.score !== null) {
+    if (row.status === 'SUBMITTED' || row.status === 'LATE_SUBMITTED') return 'score-not-graded'
+    if ((row.status === 'CORRECTED' || row.status === 'LATE_SUBMITTED_CORRECTED') && row.score !== null) {
       return row.score < 60 ? 'score-low' : 'score-high'
     }
     return ''
@@ -649,8 +659,16 @@
   // 获取分数显示内容
   const getScoreDisplay = (row: StudentAssignmentStatusDTO) => {
     if (row.status === 'NOT_SUBMITTED') return '未提交'
-    if (row.status === 'SUBMITTED') return '未批改'
-    return row.score !== null ? row.score : '未批改'
+    if (row.status === 'SUBMITTED' || row.status === 'LATE_SUBMITTED') return '未批改'
+    if (row.status === 'CORRECTED' || row.status === 'LATE_SUBMITTED_CORRECTED') {
+      return row.score !== null ? row.score : '未批改'
+    }
+    return '未批改'
+  }
+  
+  // 判断是否为补交状态
+  const isLateSubmission = (status: string) => {
+    return status === 'LATE_SUBMITTED' || status === 'LATE_SUBMITTED_CORRECTED'
   }
   
   // 处理批改操作
@@ -744,8 +762,12 @@
   const updateStatsData = () => {
     console.log(studentList)
     const total = studentList.length
-    const corrected = studentList.filter(student => student.status === 'CORRECTED').length
-    const submittedNotCorrected = studentList.filter(student => student.status === 'SUBMITTED').length
+    const corrected = studentList.filter(student => 
+      student.status === 'CORRECTED' || student.status === 'LATE_SUBMITTED_CORRECTED'
+    ).length
+    const submittedNotCorrected = studentList.filter(student => 
+      student.status === 'SUBMITTED' || student.status === 'LATE_SUBMITTED'
+    ).length
     const notSubmitted = studentList.filter(student => student.status === 'NOT_SUBMITTED').length
     
     statsData.totalStudents = total
@@ -1324,6 +1346,16 @@ export default {
     color: white;
   }
   
+  .status-补交未批改 {
+    background-color: #F2A947;
+    color: white;
+  }
+  
+  .status-补交已批改 {
+    background-color: #52C41A;
+    color: white;
+  }
+  
   /* 分数标签样式 */
   .score-badge {
     padding: 4px 8px;
@@ -1358,6 +1390,9 @@ export default {
   
   /* 操作按钮样式 */
   .action-button {
+    width: 60px;
+    height: 30px;
+    border-radius: 4px;
     background-color: #4A90C4;
     border-color: #4A90C4;
     padding: 4px 8px;
@@ -1417,6 +1452,20 @@ export default {
     color: #4A90C4;
   }
   
+  /* 补交标识样式 */
+  .late-submission-badge {
+    padding: 4px 8px;
+    background-color: #C45C4A;
+    color: white;
+    border-radius: 4px;
+    font-size: 12px;
+    font-weight: 500;
+    display: inline-block;
+    min-width: 60px;
+    text-align: center;
+    font-family: "Noto Sans SC", sans-serif;
+  }
+  
 
 
 /* 搜索弹窗样式 */

+ 15 - 0
src/views/CorrectPage/index.scss

@@ -962,6 +962,21 @@
       .student-name {
         margin-right: 30px;
       }
+      
+      // 补交标识样式
+      .late-submission-badge {
+        padding: 4px 8px;
+        background-color: #C45C4A;
+        color: white;
+        border-radius: 4px;
+        font-size: 12px;
+        font-weight: 500;
+        display: inline-block;
+        min-width: 60px;
+        text-align: center;
+        font-family: "Noto Sans SC", sans-serif;
+        margin-left: 10px;
+      }
     }
 
     .student-answer-content {

+ 8 - 13
src/views/Home/component/Edit/index.vue

@@ -11,8 +11,8 @@
         <QuillEditor/>
       </div>
       <div class="button-right">
-        <el-button type="primary" @click="handleSubmit" :disabled="useBtn" color="#4A90C4" style="color: #FFFFFF; width: 70px;">提交</el-button>
-        <el-button type="primary" @click="handleStage" :disabled="useBtn" color="#4A90C4" style="color: #FFFFFF; width: 70px; margin-left: 15px;">暂存</el-button>
+        <el-button type="primary" @click="handleSubmit"  color="#4A90C4" style="color: #FFFFFF; width: 70px;">提交</el-button>
+        <el-button type="primary" @click="handleStage"  color="#4A90C4" style="color: #FFFFFF; width: 70px; margin-left: 15px;">暂存</el-button>
       </div>
     </div>
   </div>
@@ -91,17 +91,18 @@
     }
     const endTime = dayjs(data.assignment.endTime); // 假设截止时间在 assignment 的 endTime 属性中
     const currentTime = dayjs();
+    let supplementarySubmission = false
     if (currentTime.isAfter(endTime)) {
-      ElMessage.error('作业已截止,无法提交!');
-      return;
+      supplementarySubmission = true
     }
-    apis.engagementSubmit(store.user.id, props.engagement.assignmentId, )
+    apis.engagementSubmit(store.user.id, props.engagement.assignmentId, supplementarySubmission)
     .then((_res: any) => {
       success(_res.data.data);
-      router.push("/home/myHomework")
+      router.push("/home/myHomework").then(() => {
+        window.location.reload()
+      })
     })
     .catch((error: any) => {
-      console.error('提交失败', error);
       console.error('提交失败', error);
       error('提交失败');
     });
@@ -109,12 +110,6 @@
 
   // 暂存操作
   const handleStage = async () => {
-    const endTime = dayjs(data.assignment.endTime); // 假设截止时间在 assignment 的 endTime 属性中
-    const currentTime = dayjs();
-    if (currentTime.isAfter(endTime)) {
-      ElMessage.error('作业已截止,无法暂存!');
-      return;
-    }
     try {
       const _res = await apis.engagementStage(store.user.id, props.engagement.assignmentId, JSON.stringify(getQuillContent), getText.value, getHTML.value);
       emitter.emit('click-stage');

+ 56 - 6
src/views/HomeworkPage/component/HomeworkDetail.vue

@@ -64,8 +64,8 @@
 <script lang="ts" setup>
 import useApis from "@/apis";
 import {useRoute} from "vue-router";
-import {onMounted, reactive, computed} from "vue";
-import type {IAssignment} from "@/types/vo";
+import {onMounted, reactive, computed, ref} from "vue";
+import type {IAssignment, engagementVO} from "@/types/vo";
 import './homeworkDetail.scss'
 import {useStore} from "@/store";
 import router from "@/router";
@@ -92,14 +92,32 @@ let data = reactive<IAssignment>({
   type:""
 })
 
+// 学生作业参与状态
+const engagementStatus = ref<engagementVO | null>(null)
+
 // 计算属性:判断作业是否应该禁用
 const isAssignmentDisabled = computed(() => {
   const now = new Date()
   const startTime = new Date(data.startTime)
   const endTime = new Date(data.endTime)
   
-  // 如果当前时间小于开始时间,或者大于结束时间,则禁用
-  return now < startTime || now > endTime
+  // 如果当前时间小于开始时间,则禁用
+  if (now < startTime) {
+    return true
+  }
+  
+  // 如果当前时间大于结束时间
+  if (now > endTime) {
+    // 超过截止日期时,只有未完成状态的学生可以点击
+    if (engagementStatus.value) {
+      return engagementStatus.value.status !== 'NOT_SUBMITTED'
+    }
+    // 如果没有参与状态信息,允许点击(首次参与)
+    return false
+  }
+  
+  // 在作业时间范围内,不禁用
+  return false
 })
 
 // 计算属性:按钮提示文本
@@ -111,6 +129,16 @@ const getButtonTooltip = computed(() => {
   if (now < startTime) {
     return `作业尚未开始,开始时间:${startTime.toLocaleString()}`
   } else if (now > endTime) {
+    if (engagementStatus.value) {
+      const status = engagementStatus.value.status
+      if (status === 'NOT_SUBMITTED') {
+        return '作业已截止,但您可以继续完成作业'
+      } else if (status === 'SUBMITTED') {
+        return '作业已截止且已提交,无法再次编辑'
+      } else if (status === 'CORRECTED') {
+        return '作业已截止且已批改,无法再次编辑'
+      }
+    }
     return `作业已截止,截止时间:${endTime.toLocaleString()}`
   } else {
     return '点击开始作业'
@@ -121,9 +149,13 @@ function handleStart(){
   getEngagement()
   console.log(data.type)
   if(data.type == 'writing' || data.type == '写作'){
-    router.push(`/home/assignment/${assignmentId}/edit`)
+    router.push(`/home/assignment/${assignmentId}/edit`).then(() => {
+      window.location.reload()
+    })
   } else if(data.type == 'speaking' || data.type == 'AI口语'){
-    router.push(`/home/assignment/${assignmentId}/aispeaking`)
+    router.push(`/home/assignment/${assignmentId}/aispeaking`).then(() => {
+      window.location.reload()
+    })
   }
 }
 
@@ -136,6 +168,21 @@ function downloadFile(url:string, fileName:string) {
 }
 
 
+// 获取学生作业参与状态(仅查询,不自动加入)
+async function fetchEngagementStatus() {
+  try {
+    const response = await apis.getEngagement(store.user.id, assignmentId)
+    if (response.data.code === 200 && response.data.data) {
+      engagementStatus.value = response.data.data
+    } else {
+      engagementStatus.value = null
+    }
+  } catch (error) {
+    console.log('获取作业参与状态失败:', error)
+    engagementStatus.value = null
+  }
+}
+
 async function getEngagement(){
   apis.getEngagement(store.user.id, assignmentId)
       .then((_res:any) => {
@@ -147,6 +194,8 @@ async function getEngagement(){
                   message: '参加作业成功',
                   type: 'success',
                 })
+                // 加入作业后重新获取状态
+                fetchEngagementStatus()
               })
               .catch((_err:any) => {
                 console.log("参加做业的错误",_err)
@@ -178,6 +227,7 @@ const handleBack = () => {
 
 onMounted(() => {
   fetchData()
+  fetchEngagementStatus()
 })
 </script>