Переглянути джерело

进行卡片样式调整前的保存

Jiang Pengyu 1 рік тому
батько
коміт
bf1220a830

+ 8 - 1
src/apis/assignment.ts

@@ -56,7 +56,14 @@ const assignmentApis = {
                 assignmentId
             }
         })
-
+    },
+    // 新增:查询某班级某作业的情况
+    getAssignmentStatusByClass: (classId: string, assignmentId: string) => {
+        return axiosInstance.get(`${ASSIGNMENT_PREFIX}/class/${classId}/status`, {
+            params: {
+                assignmentId
+            }
+        })
     }
 
 }

+ 8 - 0
src/apis/course.ts

@@ -82,6 +82,14 @@ const courseApis = {
             }
         })
     },
+    // 新增:查询某课程的所有班级
+    getClassesByCourse: (courseId: number) => {
+        return axiosInstance.get(`/api/class/select`, {
+            params: {
+                courseId
+            }
+        })
+    },
 }
 
 export default courseApis

+ 19 - 0
src/types/dto.ts

@@ -85,3 +85,22 @@ export interface PasswordChangeDTO {
     officialEmail: string; 
     verifyCode: string; 
 }
+
+// 新增:班级信息接口
+export interface ClassDTO {
+    classId: number;
+    className: string;
+    courseId: number;
+    stuNumber: number;
+    classTime: string;
+    teacherId: number;
+}
+
+// 新增:学生作业状态接口
+export interface StudentAssignmentStatusDTO {
+    studentId: number;
+    officialNumber: string;
+    stuName: string;
+    status: string; // "CORRECTED" | "NOT_SUBMITTED" | "SUBMITTED"
+    score: number;
+}

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

@@ -285,7 +285,7 @@ import { useRoute } from 'vue-router'
 // 导入所需组件
 import StudentWritingRequirements from "@/views/Home/component/StudentEssay/StudentWritingRequirements.vue";
 
-import * as dayjs from 'dayjs';
+import dayjs from 'dayjs';
 const formatDateTime = (isoString: string): string => {
   return dayjs(isoString).format('YYYY-MM-DD HH:mm:ss');
 };

+ 376 - 127
src/views/CorrectPage/CoursePage.vue

@@ -22,14 +22,18 @@
       
       <!-- 菜单列表 -->
       <div class="menu-section">
-        <div class="menu-item" v-for="course in courseList" :key="course.id">
-          <div class="course-header" @click="toggleCourse(course.id)">
+        <!-- 加载状态 -->
+        <div v-if="loading" class="loading-container">
+          <div class="loading-text">加载中...</div>
+        </div>
+        <div class="menu-item" v-for="course in courseList" :key="course.courseId">
+          <div class="course-header" @click="toggleCourse(course.courseId)">
             <el-icon class="expand-icon" :class="{ 'expanded': course.expanded }">
               <ArrowDown v-if="course.expanded" />
               <ArrowRight v-else />
             </el-icon>
             <el-icon class="course-icon"><Document /></el-icon>
-            <span class="course-name">{{ course.name }}</span>
+            <span class="course-name">{{ course.courseName }}</span>
           </div>
           
           <!-- 作业子菜单 -->
@@ -37,14 +41,14 @@
             <div 
               class="assignment-item" 
               v-for="assignment in course.assignments" 
-              :key="assignment.id"
+              :key="assignment.assignmentId"
               :class="{ 'active': assignment.active }"
-              @click="selectAssignment(assignment.id)"
+              @click="selectAssignment(assignment.assignmentId)"
             >
               <el-icon class="assignment-icon" :class="{ 'active-icon': assignment.active }">
                 <Document />
               </el-icon>
-              <span class="assignment-name">{{ assignment.name }}</span>
+              <span class="assignment-name">{{ assignment.assignmentName }}</span>
             </div>
           </div>
         </div>
@@ -76,7 +80,7 @@
             </div>
             <div class="stats-content">
               <div class="stats-label">作业总人数</div>
-              <div class="stats-value">32</div>
+              <div class="stats-value">{{ statsData.totalStudents }}</div>
             </div>
           </div>
           
@@ -86,7 +90,7 @@
             </div>
             <div class="stats-content">
               <div class="stats-label">已批改人数</div>
-              <div class="stats-value">10</div>
+              <div class="stats-value">{{ statsData.correctedCount }}</div>
             </div>
           </div>
           
@@ -96,7 +100,7 @@
             </div>
             <div class="stats-content">
               <div class="stats-label">已提交未批改人数</div>
-              <div class="stats-value">12</div>
+              <div class="stats-value">{{ statsData.submittedNotCorrectedCount }}</div>
             </div>
           </div>
           
@@ -106,7 +110,7 @@
             </div>
             <div class="stats-content">
               <div class="stats-label">未提交人数</div>
-              <div class="stats-value">10</div>
+              <div class="stats-value">{{ statsData.notSubmittedCount }}</div>
             </div>
           </div>
         </div>
@@ -114,7 +118,7 @@
         <div class="assignment-body">
           <!-- 课程作业标题 -->
           <div class="assignment-title-section">
-            <h3 class="assignment-full-title">{{ selectedAssignment.courseName }}:{{ selectedAssignment.name }}</h3>
+            <h3 class="assignment-full-title">{{ selectedAssignment.courseName }}:{{ selectedAssignment.assignmentName }}</h3>
           </div>
           
           <!-- 搜索筛选栏 -->
@@ -135,13 +139,14 @@
                 <el-option label="已提交未批改" value="已提交未批改"></el-option>
                 <el-option label="已批改" value="已批改"></el-option>
               </el-select>
-              <el-select v-model="classFilter" placeholder="班级" class="filter-select">
+              <el-select v-model="classFilter" placeholder="班级" class="filter-select" @change="handleClassFilterChange">
                 <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-option label="信息与计算科学(强基计划)" value="信息与计算科学(强基计划)"></el-option>
+                <el-option 
+                  v-for="classItem in classList" 
+                  :key="classItem.classId" 
+                  :label="classItem.className" 
+                  :value="classItem.classId.toString()"
+                ></el-option>
               </el-select>
               <el-button type="primary" class="search-button">搜索</el-button>
             </div>
@@ -153,12 +158,16 @@
               <el-table-column prop="status" label="状态" width="290" align="left">
                 <template #default="scope">
                   <span :class="getStatusClass(scope.row.status)" class="status-badge">
-                    {{ scope.row.status }}
+                    {{ statusMap[scope.row.status] || scope.row.status }}
                   </span>
                 </template>
               </el-table-column>
-              <el-table-column prop="name" label="学生姓名" width="290"></el-table-column>
-              <el-table-column prop="className" label="所属班级" width="290"></el-table-column>
+              <el-table-column prop="stuName" label="学生姓名" width="290"></el-table-column>
+              <el-table-column label="班级" width="290">
+                <template #default="scope">
+                  {{ getStudentClassName(scope.row) }}
+                </template>
+              </el-table-column>
               <el-table-column prop="score" label="得分" width="290">
                 <template #header>
                   <div class="score-header" @click="toggleSort">
@@ -196,6 +205,7 @@
                 :page-size="pageSize"
                 layout="total, prev, pager, next"
                 :total="total"
+                :page-count="totalPages"
                 @current-change="handleCurrentChange"
               />
           </div>
@@ -261,73 +271,145 @@
 
 <script lang="ts" setup>
   import useApis from "@/apis";
-  import {useStore} from "@/store";
-  import {inject, ref, reactive, computed} from "vue";
-  import {Refresh, Search, Document, ArrowDown, ArrowRight, User, CircleCheck, WarningFilled, View, Sort, ZoomIn} from "@element-plus/icons-vue";
+  import {ref, reactive, computed, onMounted} from "vue";
+  import {useRouter} from "vue-router";
+  import {Refresh, Search, Document, ArrowDown, ArrowRight, User, CircleCheck, WarningFilled, Sort, ZoomIn} from "@element-plus/icons-vue";
+  import type {ClassDTO, StudentAssignmentStatusDTO} from "@/types/dto";
+  import type {CourseVO, IAssignment} from "@/types/vo";
   import "./CoursePage.scss"
-
-  const apis = useApis()
+  import {useStore} from "@/store";
   const store = useStore()
-  const doRefresh:Function = inject("reload")
+  const router = useRouter()
 
-  let courseName = ref('')
+  const apis = useApis()
   const selectedAssignment = ref(null)
   
-  // 假数据 - 课程和作业列表
-  const courseList = reactive([
-    {
-      id: 1,
-      name: '课程1',
-      expanded: true,
-      assignments: [
-        { id: 1, name: '作业1', active: false },
-        { id: 2, name: '作业2', active: false },
-        { id: 3, name: '作业3', active: false }
-      ]
-    },
-    {
-      id: 2,
-      name: '课程2',
-      expanded: false,
-      assignments: [
-        { id: 4, name: '作业1', active: false },
-        { id: 5, name: '作业2', active: false }
-      ]
-    },
-    {
-      id: 3,
-      name: '课程3',
-      expanded: false,
-      assignments: [
-        { id: 6, name: '作业1', active: false },
-        { id: 7, name: '作业2', active: false },
-        { id: 8, name: '作业3', active: false }
-      ]
-    },
-    {
-      id: 4,
-      name: '课程4',
-      expanded: false,
-      assignments: [
-        { id: 9, name: '作业1', active: false }
-      ]
+  // 定义课程和作业的数据结构
+  interface CourseWithAssignments {
+    courseId: number;
+    courseName: string;
+    expanded: boolean;
+    assignments: AssignmentWithStatus[];
+  }
+  
+  interface AssignmentWithStatus {
+    assignmentId: number;
+    assignmentName: string;
+    active: boolean;
+    courseId: number;
+  }
+  
+  // 真实数据 - 课程和作业列表
+  const courseList = reactive<CourseWithAssignments[]>([])
+  
+  // 原始课程数据(从API获取)
+  const rawCourses = reactive<CourseVO[]>([])
+  
+  // 原始作业数据(从API获取)
+  const rawAssignments = reactive<IAssignment[]>([])
+  
+  // 加载状态
+  const loading = ref(false)
+  
+  // 加载所有课程
+  const loadCourses = async () => {
+    try {
+      loading.value = true
+      // 使用正确的CourseQuery来获取所有课程
+      const courseQuery = {
+        courseId: null,
+        teacherId: store.user.id,
+        teacherPid: Number(store.user.pid),
+        studentId: null,
+        courseName: null,
+        semester: null,
+      }
+      const response = await apis.getAllCourse(courseQuery, 1, 1000)
+      
+      if (response.data.code === 200) {
+        // 根据其他代码,数据可能在response.data.data.records中
+        const courseData = response.data.data.records || response.data.data.content || response.data.data
+        console.log('加载到的课程数据 1:', courseData)
+        rawCourses.splice(0, rawCourses.length, ...courseData)
+        await loadAllAssignments()
+        buildCourseTree()
+      }
+    } catch (error) {
+      console.error('加载课程失败 :', error)
+    } finally {
+      loading.value = false
     }
-  ])
+  }
   
-  const handleSearch = () => {
-    // TODO: 实现搜索功能
+  // 加载所有作业
+  const loadAllAssignments = async () => {
+    try {
+      // 使用正确的AssignmentQuery来获取所有作业
+      const assignmentQuery = {
+        assignmentId: null,
+        teacherId: store.user.id,
+        courseId: null,
+        assignmentName: null,
+        status: null,
+        type: null,
+      }
+      const response = await apis.getAssignmentByQuery(assignmentQuery, 1, 1000)
+      
+      if (response.data.code === 200) {
+        // 数据可能在不同的路径中
+        const assignmentData = response.data.data.records || response.data.data.content || response.data.data
+        console.log('加载到的作业数据:', assignmentData)
+        rawAssignments.splice(0, rawAssignments.length, ...assignmentData)
+      }
+    } catch (error) {
+      console.error('加载作业失败:', error)
+    }
   }
   
+  // 构建课程树结构
+  const buildCourseTree = () => {
+    const courseMap = new Map<number, CourseWithAssignments>()
+    
+    console.log('构建课程树 - 课程数量:', rawCourses.length, '作业数量:', rawAssignments.length)
+    
+    // 初始化课程
+    rawCourses.forEach(course => {
+      courseMap.set(course.courseId, {
+        courseId: course.courseId,
+        courseName: course.courseName,
+        expanded: false,
+        assignments: []
+      })
+    })
+    
+    // 添加作业到对应课程
+    rawAssignments.forEach(assignment => {
+      const course = courseMap.get(assignment.courseId)
+      if (course) {
+        course.assignments.push({
+          assignmentId: assignment.assignmentId,
+          assignmentName: assignment.assignmentName,
+          active: false,
+          courseId: assignment.courseId
+        })
+      }
+    })
+    
+    // 更新courseList
+    courseList.splice(0, courseList.length, ...Array.from(courseMap.values()))
+    console.log('构建完成的课程树:', courseList.length, '个课程')
+  }
+
   // 切换课程展开/收起
   const toggleCourse = (courseId: number) => {
-    const course = courseList.find(c => c.id === courseId)
+    const course = courseList.find(c => c.courseId === courseId)
     if (course) {
       course.expanded = !course.expanded
     }
   }
   
   // 选择作业
-  const selectAssignment = (assignmentId: number) => {
+  const selectAssignment = async (assignmentId: number) => {
     // 清除所有作业的active状态
     courseList.forEach(course => {
       course.assignments.forEach(assignment => {
@@ -337,15 +419,22 @@
     
     // 设置选中的作业为active
     courseList.forEach(course => {
-      const assignment = course.assignments.find(a => a.id === assignmentId)
+      const assignment = course.assignments.find(a => a.assignmentId === assignmentId)
       if (assignment) {
         assignment.active = true
         // 设置选中的作业信息
         selectedAssignment.value = {
-          id: assignment.id,
-          name: assignment.name,
-          courseName: course.name
+          assignmentId: assignment.assignmentId,
+          assignmentName: assignment.assignmentName,
+          courseName: course.courseName,
+          courseId: course.courseId
         }
+        
+        // 加载相关数据
+        onAssignmentSelected({
+          assignmentId: assignment.assignmentId,
+          courseId: course.courseId
+        })
       }
     })
   }
@@ -361,25 +450,44 @@
   const statusFilter = ref('')
   const classFilter = ref('')
   
+  // 监听班级筛选变化
+  const handleClassFilterChange = async () => {
+    if (selectedAssignment.value && classFilter.value) {
+      // 重新加载选中班级的学生数据
+      studentList.splice(0, studentList.length)
+      await loadStudentAssignmentStatus(classFilter.value, selectedAssignment.value.assignmentId.toString())
+    } else if (selectedAssignment.value && !classFilter.value) {
+      // 如果选择了"全部",重新加载所有班级的数据
+      await loadAllStudentAssignmentStatus(selectedAssignment.value.assignmentId)
+    }
+  }
+  
   // 排序相关逻辑
   const sortOrder = ref(0) // 0: 原始顺序, 1: 高到低, 2: 低到高
   
-  // 学生数据模拟
-  const studentList = reactive([
-    { id: 1, name: 'student0', className: '软工一班', status: '未提交', score: null },
-    { id: 2, name: 'student1', className: '软工二班', status: '已提交未批改', score: null },
-    { id: 3, name: 'student2', className: '计科一班', status: '已批改', score: 58 },
-    { id: 4, name: 'student3', className: '计科二班', status: '未提交', score: null },
-    { id: 5, name: 'student4', className: '信息与计算科学(强基计划)', status: '已提交未批改', score: null },
-    { id: 6, name: 'student5', className: '软工一班', status: '已批改', score: 77 },
-    { id: 7, name: 'student6', className: '软工二班', status: '已批改', score: 72 },
-    { id: 8, name: 'student7', className: '计科一班', status: '已批改', score: 89 },
-    { id: 9, name: 'student8', className: '计科二班', status: '已批改', score: 93 },
-    { id: 10, name: 'student9', className: '信息与计算科学(强基计划)', status: '已批改', score: 100 },
-    { id: 11, name: 'student10', className: '信息与计算科学(强基计划)', status: '未提交', score: null },
-    { id: 12, name: 'student11', className: '信息与计算科学(强基计划)', status: '未提交', score: null },
-    { id: 13, name: 'student12', className: '信息与计算科学(强基计划)', status: '已提交未批改', score: null }
-  ])
+  // 学生数据
+  const studentList = reactive<StudentAssignmentStatusDTO[]>([])
+  
+  // 班级列表数据
+  const classList = reactive<ClassDTO[]>([])
+  
+  // 统计卡片数据
+  const statsData = reactive({
+    totalStudents: 0,
+    correctedCount: 0,
+    submittedNotCorrectedCount: 0,
+    notSubmittedCount: 0
+  })
+  
+  // 学生班级映射数据(用于存储学生ID到班级名称的映射)
+  const studentClassMap = reactive(new Map<number, string>())
+  
+  // 状态映射
+  const statusMap = {
+    'NOT_SUBMITTED': '未提交',
+    'SUBMITTED': '已提交未批改', 
+    'CORRECTED': '已批改'
+  }
   
   // 当前页码
   const currentPage = ref(1)
@@ -393,16 +501,18 @@
     // 筛选逻辑
     if (filterQuery.value) {
       filtered = filtered.filter(student => 
-        student.name.toLowerCase().includes(filterQuery.value.toLowerCase())
+        student.stuName.toLowerCase().includes(filterQuery.value.toLowerCase())
       )
     }
     
     if (statusFilter.value) {
-      filtered = filtered.filter(student => student.status === statusFilter.value)
+      filtered = filtered.filter(student => statusMap[student.status] === statusFilter.value)
     }
     
     if (classFilter.value) {
-      filtered = filtered.filter(student => student.className === classFilter.value)
+      // 根据选中的班级ID重新加载数据
+      // 这里可以实现按班级筛选的逻辑
+      // 暂时保持原有的筛选逻辑
     }
     
     // 排序逻辑
@@ -422,9 +532,6 @@
       })
     }
     // sortOrder.value === 0 时保持原始顺序
-
-    // 计算总页数
-    totalPages.value = Math.ceil(filtered.length / pageSize)
     
     // 分页逻辑
     const startIndex = (currentPage.value - 1) * pageSize
@@ -432,22 +539,46 @@
     return filtered.slice(startIndex, endIndex)
   })
 
-  // 总页数
-  const totalPages = ref(1)
+  // 单独的计算属性来获取总页数
+  const totalPages = computed(() => {
+    let filtered = [...studentList]
+    
+    if (filterQuery.value) {
+      filtered = filtered.filter(student => 
+        student.stuName.toLowerCase().includes(filterQuery.value.toLowerCase())
+      )
+    }
+    
+    if (statusFilter.value) {
+      filtered = filtered.filter(student => statusMap[student.status] === statusFilter.value)
+    }
+    
+    if (classFilter.value) {
+      // 根据选中的班级ID重新加载数据
+      // 这里可以实现按班级筛选的逻辑
+      // 暂时保持原有的筛选逻辑
+    }
+    
+    return Math.ceil(filtered.length / pageSize)
+  })
+
+
 
   // 总条目数
   const total = computed(() => {
     let filtered = [...studentList]
     if (filterQuery.value) {
       filtered = filtered.filter(student => 
-        student.name.toLowerCase().includes(filterQuery.value.toLowerCase())
+        student.stuName.toLowerCase().includes(filterQuery.value.toLowerCase())
       )
     }
     if (statusFilter.value) {
-      filtered = filtered.filter(student => student.status === statusFilter.value)
+      filtered = filtered.filter(student => statusMap[student.status] === statusFilter.value)
     }
     if (classFilter.value) {
-      filtered = filtered.filter(student => student.className === classFilter.value)
+      // 根据选中的班级ID重新加载数据
+      // 这里可以实现按班级筛选的逻辑
+      // 暂时保持原有的筛选逻辑
     }
     return filtered.length
   })
@@ -459,6 +590,11 @@
     classFilter.value = ''
     sortOrder.value = 0
     currentPage.value = 1 // 重置页码
+    
+    // 重新加载所有数据并更新统计
+    if (selectedAssignment.value) {
+      loadAllStudentAssignmentStatus(selectedAssignment.value.assignmentId)
+    }
   }
 
   // 处理页码改变
@@ -467,10 +603,10 @@
   }
   
   // 获取用于排序的分数值
-  const getScoreForSort = (student) => {
-    if (student.status === '已批改' && student.score !== null) {
+  const getScoreForSort = (student: StudentAssignmentStatusDTO) => {
+    if (student.status === 'CORRECTED' && student.score !== null) {
       return student.score
-    } else if (student.status === '已提交未批改') {
+    } else if (student.status === 'SUBMITTED') {
       return -1 // 未批改排在未提交前面
     } else {
       return -2 // 未提交排在最后
@@ -492,30 +628,126 @@
   }
   
   // 获取状态样式类
-  const getStatusClass = (status) => {
-    return `status-${status.replace(/[^a-zA-Z0-9]/g, '')}`
+  const getStatusClass = (status: string) => {
+    const mappedStatus = statusMap[status] || status
+    return `status-${mappedStatus.replace(/[^a-zA-Z0-9]/g, '')}`
   }
   
   // 获取分数样式类
-  const getScoreClass = (row) => {
-    if (row.status === '未提交') return 'score-not-submitted'
-    if (row.status === '已提交未批改') return 'score-not-graded'
-    if (row.score !== null) {
+  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) {
       return row.score < 60 ? 'score-low' : 'score-high'
     }
     return ''
   }
   
   // 获取分数显示内容
-  const getScoreDisplay = (row) => {
-    if (row.status === '未提交') return '未提交'
-    if (row.status === '已提交未批改') return '未批改'
+  const getScoreDisplay = (row: StudentAssignmentStatusDTO) => {
+    if (row.status === 'NOT_SUBMITTED') return '未提交'
+    if (row.status === 'SUBMITTED') return '未批改'
     return row.score !== null ? row.score : '未批改'
   }
   
   // 处理批改操作
-  const handleCorrect = (row) => {
+  const handleCorrect = (row: StudentAssignmentStatusDTO) => {
     console.log('批改学生作业:', row)
+    
+    // 跳转到批改页面,路径为 home/assignment/:assignmentId/correct,并传递studentId参数
+    if (selectedAssignment.value) {
+      router.push({
+        path: `/home/assignment/${selectedAssignment.value.assignmentId}/correct`,
+        query: {
+          studentId: row.studentId.toString()
+        }
+      })
+    }
+  }
+  
+  // 加载班级列表
+  const loadClassList = async (courseId: number) => {
+    try {
+      const response = await apis.getClassesByCourse(courseId)
+      if (response.data.code === 200) {
+        classList.splice(0, classList.length, ...response.data.data)
+      }
+    } catch (error) {
+      console.error('加载班级列表失败:', error)
+    }
+  }
+  
+  // 加载学生作业状态
+  const loadStudentAssignmentStatus = async (classId: string, assignmentId: string) => {
+    try {
+      const response = await apis.getAssignmentStatusByClass(classId, assignmentId)
+      if (response.data.code === 200) {
+        // 获取班级名称
+        const classItem = classList.find(c => c.classId.toString() === classId)
+        const className = classItem ? classItem.className : '未知班级'
+        
+        // 为每个学生建立班级映射关系
+        response.data.data.forEach((student: StudentAssignmentStatusDTO) => {
+          studentClassMap.set(student.studentId, className)
+        })
+        
+        // 追加数据而不是替换
+        studentList.push(...response.data.data)
+      }
+    } catch (error) {
+      console.error('加载学生作业状态失败:', error)
+    }
+  }
+  
+  // 当选择作业时加载相关数据
+  const onAssignmentSelected = async (assignment: any) => {
+    if (assignment && assignment.courseId) {
+      // 首先加载班级列表
+      await loadClassList(assignment.courseId)
+      
+      // 加载所有班级的学生作业状态
+      if (classList.length > 0) {
+        await loadAllStudentAssignmentStatus(assignment.assignmentId)
+      }
+    }
+  }
+  
+  // 加载所有班级的学生作业状态
+  const loadAllStudentAssignmentStatus = async (assignmentId: number) => {
+    try {
+      // 清空现有学生数据
+      studentList.splice(0, studentList.length)
+      
+      // 遍历所有班级,加载每个班级的学生数据
+      for (const classItem of classList) {
+        await loadStudentAssignmentStatus(classItem.classId.toString(), assignmentId.toString())
+      }
+      
+      // 更新统计数据
+      updateStatsData()
+    } catch (error) {
+      console.error('加载所有学生作业状态失败:', error)
+    }
+  }
+  
+  // 获取学生班级名称
+  const getStudentClassName = (student: StudentAssignmentStatusDTO) => {
+    // 由于StudentAssignmentStatusDTO中没有班级信息,我们需要通过其他方式获取
+    // 这里暂时返回一个默认值,实际项目中可能需要通过API获取学生班级信息
+    return studentClassMap.get(student.studentId) || '未知班级'
+  }
+  
+  // 更新统计数据
+  const updateStatsData = () => {
+    const total = studentList.length
+    const corrected = studentList.filter(student => student.status === 'CORRECTED').length
+    const submittedNotCorrected = studentList.filter(student => student.status === 'SUBMITTED').length
+    const notSubmitted = studentList.filter(student => student.status === 'NOT_SUBMITTED').length
+    
+    statsData.totalStudents = total
+    statsData.correctedCount = corrected
+    statsData.submittedNotCorrectedCount = submittedNotCorrected
+    statsData.notSubmittedCount = notSubmitted
   }
   
 
@@ -548,21 +780,21 @@
     // 搜索课程和作业
     courseList.forEach(course => {
       // 搜索课程
-      if (course.name.toLowerCase().includes(query)) {
+      if (course.courseName.toLowerCase().includes(query)) {
         results.push({
-          id: course.id,
-          name: course.name,
+          id: course.courseId,
+          name: course.courseName,
           type: 'course'
         })
       }
       
       // 搜索作业
       course.assignments.forEach(assignment => {
-        if (assignment.name.toLowerCase().includes(query)) {
+        if (assignment.assignmentName.toLowerCase().includes(query)) {
           results.push({
-            id: assignment.id,
-            name: assignment.name,
-            courseName: course.name,
+            id: assignment.assignmentId,
+            name: assignment.assignmentName,
+            courseName: course.courseName,
             type: 'assignment'
           })
         }
@@ -575,14 +807,14 @@
   const handleSearchResultClick = (result) => {
     if (result.type === 'course') {
       // 展开对应的课程
-      const course = courseList.find(c => c.id === result.id)
+      const course = courseList.find(c => c.courseId === result.id)
       if (course) {
         course.expanded = true
       }
     } else {
       // 选中对应的作业并展开对应课程
       courseList.forEach(course => {
-        const assignment = course.assignments.find(a => a.id === result.id)
+        const assignment = course.assignments.find(a => a.assignmentId === result.id)
         if (assignment) {
           course.expanded = true
         }
@@ -594,6 +826,11 @@
     searchQuery.value = ''
     searchResults.value = []
   }
+  
+  // 组件挂载时加载数据
+  onMounted(() => {
+    loadCourses()
+  })
 </script>
 
 <script lang="ts">
@@ -610,10 +847,8 @@ export default {
 }
 
 .left-sidebar {
-  min-width: 320px;
-  max-width: 320px;
-  width: 320px;
-  background-color: white;
+  width: 280px;
+  background-color: #F0F2F5;
   border-right: 1px solid #e8e8e8;
   display: flex;
   flex-direction: column;
@@ -781,6 +1016,20 @@ export default {
   font-weight: 500;
 }
 
+/* 加载状态样式 */
+.loading-container {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  padding: 20px;
+}
+
+.loading-text {
+  color: #606266;
+  font-size: 14px;
+  font-family: "Noto Sans SC", sans-serif;
+}
+
 .right-content {
   flex: 1;
   background-color: white;