|
|
@@ -4,170 +4,596 @@
|
|
|
Created Date: 2024-7-25
|
|
|
-->
|
|
|
<template>
|
|
|
- <el-card class="course-card-contain" shadow="never">
|
|
|
- <div class="title">
|
|
|
- <span>课程列表</span>
|
|
|
+ <div class="course-page">
|
|
|
+ <!-- 左侧菜单栏 -->
|
|
|
+ <div class="left-sidebar">
|
|
|
+ <!-- EAI平台装饰栏 -->
|
|
|
+ <div class="platform-header">
|
|
|
+ <div class="platform-name">EAI专业英语平台</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索框 -->
|
|
|
+ <div class="search-section">
|
|
|
+ <div class="search-input-container" @click="openSearchDialog">
|
|
|
+ <el-icon class="search-icon"><Search /></el-icon>
|
|
|
+ <input type="text" placeholder="搜索" class="search-input" readonly />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 菜单列表 -->
|
|
|
+ <div class="menu-section">
|
|
|
+ <div class="menu-item" v-for="course in courseList" :key="course.id">
|
|
|
+ <div class="course-header" @click="toggleCourse(course.id)">
|
|
|
+ <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>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 作业子菜单 -->
|
|
|
+ <div class="assignment-list" v-if="course.expanded">
|
|
|
+ <div
|
|
|
+ class="assignment-item"
|
|
|
+ v-for="assignment in course.assignments"
|
|
|
+ :key="assignment.id"
|
|
|
+ :class="{ 'active': assignment.active }"
|
|
|
+ @click="selectAssignment(assignment.id)"
|
|
|
+ >
|
|
|
+ <el-icon class="assignment-icon" :class="{ 'active-icon': assignment.active }">
|
|
|
+ <Document />
|
|
|
+ </el-icon>
|
|
|
+ <span class="assignment-name">{{ assignment.name }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
-
|
|
|
- <el-button :icon="Refresh" circle @click="doRefresh"></el-button>
|
|
|
- <el-input v-model="courseName" placeholder="请输入课程名称" clearable class="search-input"/>
|
|
|
- <el-button color="#597D3B" @click="handleSearch">
|
|
|
- <el-icon style="margin-right: 3px"><Search/></el-icon>
|
|
|
- 查询
|
|
|
- </el-button>
|
|
|
-
|
|
|
- <el-table :data="pageInfo.records" style="width: 100%; max-height: 70vh" height="100%" :row-style="{height: '30px'}" show-overflow-tooltip>
|
|
|
- <template #empty>
|
|
|
- 暂无课程
|
|
|
- </template>
|
|
|
- <el-table-column type="index"/>
|
|
|
- <el-table-column prop="courseName" label="课程名称" width="280"/>
|
|
|
- <el-table-column prop="description" label="描述" width="420"/>
|
|
|
- <el-table-column prop="endTime" label="截止时间" sortable/>
|
|
|
-<!-- <el-table-column prop="endTime" label="状态" sortable/>-->
|
|
|
- <el-table-column label="操作">
|
|
|
- <template #default="scope">
|
|
|
- <el-button @click="handleCorrect(scope.row.courseId, scope.row.courseName)" style="margin-right: 0; margin-left: 0;padding-left: 10px; padding-right: 10px" color="#597D3B">
|
|
|
- <el-icon style="margin-right: 3px" ><ZoomIn/></el-icon>
|
|
|
- 批改作业
|
|
|
- </el-button>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
- </el-table>
|
|
|
-
|
|
|
- <el-pagination
|
|
|
- small
|
|
|
- style="font-size: 16px;margin-top: 10px;margin-left: 450px"
|
|
|
- :page-sizes="[5, 10, 15]"
|
|
|
- @current-change="handleCurrentChange"
|
|
|
- @size-change="handleSizeChange"
|
|
|
- :current-page="queryInfo.pageNow"
|
|
|
- :page-size="queryInfo.pageSize"
|
|
|
- layout="total, sizes, prev, pager, next, jumper"
|
|
|
- :total="pageInfo.total">
|
|
|
- </el-pagination>
|
|
|
-
|
|
|
- </el-card>
|
|
|
-
|
|
|
+
|
|
|
+ <!-- 右侧内容区域 -->
|
|
|
+ <div class="right-content">
|
|
|
+ <!-- 当没有选中作业时显示空白状态 -->
|
|
|
+ <div v-if="!selectedAssignment" class="empty-state">
|
|
|
+ <div class="empty-content">
|
|
|
+ <el-icon class="empty-icon"><Document /></el-icon>
|
|
|
+ <div class="empty-text">请选择一个作业开始批改</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 当选中作业时显示内容 -->
|
|
|
+ <div v-else class="assignment-content">
|
|
|
+ <!-- 右上角数据看板按钮 -->
|
|
|
+ <div class="top-actions">
|
|
|
+ <el-button type="primary" class="dashboard-button">数据看板</el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 统计卡片区域 -->
|
|
|
+ <div class="stats-container">
|
|
|
+ <div class="stats-card">
|
|
|
+ <div class="stats-icon user-icon">
|
|
|
+ <el-icon><User /></el-icon>
|
|
|
+ </div>
|
|
|
+ <div class="stats-content">
|
|
|
+ <div class="stats-label">作业总人数</div>
|
|
|
+ <div class="stats-value">32</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="stats-card">
|
|
|
+ <div class="stats-icon completed-icon">
|
|
|
+ <el-icon><CircleCheck /></el-icon>
|
|
|
+ </div>
|
|
|
+ <div class="stats-content">
|
|
|
+ <div class="stats-label">已批改人数</div>
|
|
|
+ <div class="stats-value">10</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="stats-card">
|
|
|
+ <div class="stats-icon pending-icon">
|
|
|
+ <el-icon><Document /></el-icon>
|
|
|
+ </div>
|
|
|
+ <div class="stats-content">
|
|
|
+ <div class="stats-label">已提交未批改人数</div>
|
|
|
+ <div class="stats-value">12</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="stats-card">
|
|
|
+ <div class="stats-icon not-submitted-icon">
|
|
|
+ <el-icon><WarningFilled /></el-icon>
|
|
|
+ </div>
|
|
|
+ <div class="stats-content">
|
|
|
+ <div class="stats-label">未提交人数</div>
|
|
|
+ <div class="stats-value">10</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="assignment-body">
|
|
|
+ <!-- 课程作业标题 -->
|
|
|
+ <div class="assignment-title-section">
|
|
|
+ <h3 class="assignment-full-title">{{ selectedAssignment.courseName }}:{{ selectedAssignment.name }}</h3>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索筛选栏 -->
|
|
|
+ <div class="filter-section">
|
|
|
+ <div class="filter-controls">
|
|
|
+ <el-icon class="reset-icon" @click="resetFilters"><Refresh /></el-icon>
|
|
|
+ <div class="search-input-wrapper">
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ placeholder="请输入内容"
|
|
|
+ class="filter-search-input"
|
|
|
+ v-model="filterQuery"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <el-select v-model="statusFilter" placeholder="状态" class="filter-select">
|
|
|
+ <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">
|
|
|
+ <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-select>
|
|
|
+ <el-button type="primary" class="search-button">搜索</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 学生作业表格 -->
|
|
|
+ <div class="table-section">
|
|
|
+ <el-table :data="filteredStudentList" class="student-table" stripe>
|
|
|
+ <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 }}
|
|
|
+ </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="score" label="得分" width="290">
|
|
|
+ <template #header>
|
|
|
+ <div class="score-header" @click="toggleSort">
|
|
|
+ <span>得分</span>
|
|
|
+ <el-icon class="sort-icon" :class="getSortIconClass()">
|
|
|
+ <Sort />
|
|
|
+ </el-icon>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #default="scope">
|
|
|
+ <span :class="getScoreClass(scope.row)" class="score-badge">
|
|
|
+ {{ getScoreDisplay(scope.row) }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" width="200">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ class="action-button"
|
|
|
+ @click="handleCorrect(scope.row)"
|
|
|
+ >
|
|
|
+ <el-icon><View /></el-icon>
|
|
|
+ 批改
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="example-pagination-block">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="currentPage"
|
|
|
+ :page-size="pageSize"
|
|
|
+ layout="total, prev, pager, next"
|
|
|
+ :total="total"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="searchDialogVisible"
|
|
|
+ title="搜索课程和作业"
|
|
|
+ width="50%"
|
|
|
+ :before-close="handleCloseSearchDialog"
|
|
|
+ class="search-dialog"
|
|
|
+ >
|
|
|
+ <div class="search-dialog-container">
|
|
|
+ <!-- 搜索框部分 -->
|
|
|
+ <div class="dialog-search-section">
|
|
|
+ <div class="dialog-search-input-container">
|
|
|
+ <el-icon class="dialog-search-icon"><Search /></el-icon>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ placeholder="输入课程或作业名称..."
|
|
|
+ class="dialog-search-input"
|
|
|
+ v-model="searchQuery"
|
|
|
+ @input="performSearch"
|
|
|
+ ref="dialogSearchInput"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 搜索结果部分 -->
|
|
|
+ <div class="search-results-section">
|
|
|
+ <div v-if="searchResults.length === 0" class="no-results">
|
|
|
+ <span>{{ searchQuery ? '没有找到相关结果' : '请输入搜索内容' }}</span>
|
|
|
+ </div>
|
|
|
+ <div v-else class="search-results-list">
|
|
|
+ <div
|
|
|
+ v-for="result in searchResults"
|
|
|
+ :key="result.id"
|
|
|
+ class="search-result-item"
|
|
|
+ @click="handleSearchResultClick(result)"
|
|
|
+ >
|
|
|
+ <el-icon class="result-icon" v-if="result.type === 'course'">
|
|
|
+ <Document />
|
|
|
+ </el-icon>
|
|
|
+ <el-icon class="result-icon assignment-result-icon" v-else>
|
|
|
+ <Document />
|
|
|
+ </el-icon>
|
|
|
+ <div class="result-content">
|
|
|
+ <div class="result-title">{{ result.name }}</div>
|
|
|
+ <div class="result-path" v-if="result.type === 'assignment'">
|
|
|
+ 课程: {{ result.courseName }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
import useApis from "@/apis";
|
|
|
import {useStore} from "@/store";
|
|
|
- import {inject, onMounted, reactive, ref} from "vue";
|
|
|
- import type {CourseVO} from "@/types/vo";
|
|
|
- import {Refresh, Search, ZoomIn} from "@element-plus/icons-vue";
|
|
|
- import router from "@/router";
|
|
|
- import type {CourseDTO} from "@/types/dto";
|
|
|
+ import {inject, ref, reactive, computed} from "vue";
|
|
|
+ import {Refresh, Search, Document, ArrowDown, ArrowRight, User, CircleCheck, WarningFilled, View, Sort} from "@element-plus/icons-vue";
|
|
|
import "./CoursePage.scss"
|
|
|
- import type {CourseQuery} from "@/types/query";
|
|
|
- import {useFormatDate} from "@/hooks/useFormatDate";
|
|
|
|
|
|
const apis = useApis()
|
|
|
const store = useStore()
|
|
|
const doRefresh:Function = inject("reload")
|
|
|
- const {formatDate} = useFormatDate()
|
|
|
-
|
|
|
- const queryInfo = reactive({
|
|
|
- pageNow: 1,
|
|
|
- pageSize: 10,
|
|
|
- })
|
|
|
-
|
|
|
- let pageInfo = reactive<{
|
|
|
- records: CourseVO[],
|
|
|
- current: number,// 当前页码
|
|
|
- size: number, // 分页大小
|
|
|
- pages: number, // 总页数
|
|
|
- total: number
|
|
|
- }>({
|
|
|
- records: null,
|
|
|
- current: null,
|
|
|
- size: null,
|
|
|
- pages: null,
|
|
|
- total: null,
|
|
|
- })
|
|
|
-
|
|
|
- const query = reactive<CourseQuery>({
|
|
|
- courseId:null,
|
|
|
- teacherId:store.user.id,
|
|
|
- studentId:null,
|
|
|
- courseName:null,
|
|
|
- semester:null,
|
|
|
- teacherPid:Number(store.user.pid)
|
|
|
- })
|
|
|
|
|
|
let courseName = ref('')
|
|
|
+ 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 }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ])
|
|
|
+
|
|
|
const handleSearch = () => {
|
|
|
- Object.assign(query, {
|
|
|
- courseId:null,
|
|
|
- teacherId:store.user.id,
|
|
|
- studentId:null,
|
|
|
- courseName:courseName.value,
|
|
|
- semester:null,
|
|
|
- })
|
|
|
- fetchData(query)
|
|
|
+ // TODO: 实现搜索功能
|
|
|
}
|
|
|
-
|
|
|
- /*
|
|
|
- 路由跳转到作业界面
|
|
|
- */
|
|
|
- const handleCorrect = (courseId:number, courseName:string) => {
|
|
|
- router.replace({
|
|
|
- path:`/home/myCorrect/assignment`,
|
|
|
- query: {
|
|
|
- courseId: courseId,
|
|
|
- }
|
|
|
+
|
|
|
+ // 切换课程展开/收起
|
|
|
+ const toggleCourse = (courseId: number) => {
|
|
|
+ const course = courseList.find(c => c.id === courseId)
|
|
|
+ if (course) {
|
|
|
+ course.expanded = !course.expanded
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 选择作业
|
|
|
+ const selectAssignment = (assignmentId: number) => {
|
|
|
+ // 清除所有作业的active状态
|
|
|
+ courseList.forEach(course => {
|
|
|
+ course.assignments.forEach(assignment => {
|
|
|
+ assignment.active = false
|
|
|
+ })
|
|
|
})
|
|
|
- .then(() => {
|
|
|
- window.location.reload() // 强制刷新页面
|
|
|
+
|
|
|
+ // 设置选中的作业为active
|
|
|
+ courseList.forEach(course => {
|
|
|
+ const assignment = course.assignments.find(a => a.id === assignmentId)
|
|
|
+ if (assignment) {
|
|
|
+ assignment.active = true
|
|
|
+ // 设置选中的作业信息
|
|
|
+ selectedAssignment.value = {
|
|
|
+ id: assignment.id,
|
|
|
+ name: assignment.name,
|
|
|
+ courseName: course.name
|
|
|
+ }
|
|
|
+ }
|
|
|
})
|
|
|
}
|
|
|
+
|
|
|
+ // 搜索弹窗相关逻辑
|
|
|
+ const searchDialogVisible = ref(false)
|
|
|
+ const searchQuery = ref('')
|
|
|
+ const searchResults = ref([])
|
|
|
+ const dialogSearchInput = ref(null)
|
|
|
+
|
|
|
+ // 筛选相关逻辑
|
|
|
+ const filterQuery = ref('')
|
|
|
+ const statusFilter = ref('')
|
|
|
+ const classFilter = ref('')
|
|
|
+
|
|
|
+ // 排序相关逻辑
|
|
|
+ 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 currentPage = ref(1)
|
|
|
+ // 每页显示条数
|
|
|
+ const pageSize = 10
|
|
|
|
|
|
- const fetchData = (query: CourseQuery) => {
|
|
|
- apis.getAllCourse(query, queryInfo.pageNow, queryInfo.pageSize)
|
|
|
- .then((res: any) => {
|
|
|
- let data = res.data.data
|
|
|
- Object.assign(pageInfo, {...data})
|
|
|
- processData()
|
|
|
- })
|
|
|
- .catch((err: any) => {
|
|
|
- console.error(err);
|
|
|
- })
|
|
|
- .finally(() => {
|
|
|
- });
|
|
|
- }
|
|
|
+ // 计算筛选后的学生列表(包含分页)
|
|
|
+ const filteredStudentList = computed(() => {
|
|
|
+ let filtered = [...studentList]
|
|
|
+
|
|
|
+ // 筛选逻辑
|
|
|
+ if (filterQuery.value) {
|
|
|
+ filtered = filtered.filter(student =>
|
|
|
+ student.name.toLowerCase().includes(filterQuery.value.toLowerCase())
|
|
|
+ )
|
|
|
+ }
|
|
|
+
|
|
|
+ if (statusFilter.value) {
|
|
|
+ filtered = filtered.filter(student => student.status === statusFilter.value)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (classFilter.value) {
|
|
|
+ filtered = filtered.filter(student => student.className === classFilter.value)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 排序逻辑
|
|
|
+ if (sortOrder.value === 1) {
|
|
|
+ // 高到低排序
|
|
|
+ filtered.sort((a, b) => {
|
|
|
+ const scoreA = getScoreForSort(a)
|
|
|
+ const scoreB = getScoreForSort(b)
|
|
|
+ return scoreB - scoreA
|
|
|
+ })
|
|
|
+ } else if (sortOrder.value === 2) {
|
|
|
+ // 低到高排序
|
|
|
+ filtered.sort((a, b) => {
|
|
|
+ const scoreA = getScoreForSort(a)
|
|
|
+ const scoreB = getScoreForSort(b)
|
|
|
+ return scoreA - scoreB
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // sortOrder.value === 0 时保持原始顺序
|
|
|
+
|
|
|
+ // 计算总页数
|
|
|
+ totalPages.value = Math.ceil(filtered.length / pageSize)
|
|
|
+
|
|
|
+ // 分页逻辑
|
|
|
+ const startIndex = (currentPage.value - 1) * pageSize
|
|
|
+ const endIndex = startIndex + pageSize
|
|
|
+ return filtered.slice(startIndex, endIndex)
|
|
|
+ })
|
|
|
+
|
|
|
+ // 总页数
|
|
|
+ const totalPages = ref(1)
|
|
|
|
|
|
- const processData = () => {
|
|
|
- for(let i = 0; i < pageInfo.records.length; i++){
|
|
|
- pageInfo.records[i].endTime = formatDate(pageInfo.records[i].endTime)
|
|
|
+ // 总条目数
|
|
|
+ const total = computed(() => {
|
|
|
+ let filtered = [...studentList]
|
|
|
+ if (filterQuery.value) {
|
|
|
+ filtered = filtered.filter(student =>
|
|
|
+ student.name.toLowerCase().includes(filterQuery.value.toLowerCase())
|
|
|
+ )
|
|
|
}
|
|
|
+ if (statusFilter.value) {
|
|
|
+ filtered = filtered.filter(student => student.status === statusFilter.value)
|
|
|
+ }
|
|
|
+ if (classFilter.value) {
|
|
|
+ filtered = filtered.filter(student => student.className === classFilter.value)
|
|
|
+ }
|
|
|
+ return filtered.length
|
|
|
+ })
|
|
|
+
|
|
|
+ // 重置筛选条件
|
|
|
+ const resetFilters = () => {
|
|
|
+ filterQuery.value = ''
|
|
|
+ statusFilter.value = ''
|
|
|
+ classFilter.value = ''
|
|
|
+ sortOrder.value = 0
|
|
|
+ currentPage.value = 1 // 重置页码
|
|
|
}
|
|
|
|
|
|
- const handleCurrentChange =(index:number)=>{
|
|
|
- queryInfo.pageNow=index;
|
|
|
- fetchData(query);
|
|
|
+ // 处理页码改变
|
|
|
+ const handleCurrentChange = (val: number) => {
|
|
|
+ currentPage.value = val
|
|
|
}
|
|
|
- const handleSizeChange = (pageSize: number) => {
|
|
|
- queryInfo.pageSize = pageSize
|
|
|
- fetchData(query)
|
|
|
+
|
|
|
+ // 获取用于排序的分数值
|
|
|
+ const getScoreForSort = (student) => {
|
|
|
+ if (student.status === '已批改' && student.score !== null) {
|
|
|
+ return student.score
|
|
|
+ } else if (student.status === '已提交未批改') {
|
|
|
+ return -1 // 未批改排在未提交前面
|
|
|
+ } else {
|
|
|
+ return -2 // 未提交排在最后
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ // 切换排序状态
|
|
|
+ const toggleSort = () => {
|
|
|
+ sortOrder.value = (sortOrder.value + 1) % 3
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取排序图标样式
|
|
|
+ const getSortIconClass = () => {
|
|
|
+ return {
|
|
|
+ 'sort-asc': sortOrder.value === 2,
|
|
|
+ 'sort-desc': sortOrder.value === 1,
|
|
|
+ 'sort-default': sortOrder.value === 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取状态样式类
|
|
|
+ const getStatusClass = (status) => {
|
|
|
+ return `status-${status.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) {
|
|
|
+ return row.score < 60 ? 'score-low' : 'score-high'
|
|
|
+ }
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取分数显示内容
|
|
|
+ const getScoreDisplay = (row) => {
|
|
|
+ if (row.status === '未提交') return '未提交'
|
|
|
+ if (row.status === '已提交未批改') return '未批改'
|
|
|
+ return row.score !== null ? row.score : '未批改'
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理批改操作
|
|
|
+ const handleCorrect = (row) => {
|
|
|
+ console.log('批改学生作业:', row)
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
- onMounted(() => {
|
|
|
- fetchData(query)
|
|
|
- })
|
|
|
-
|
|
|
- // TODO:状态选择
|
|
|
- let state = ref(null)
|
|
|
- const stateOptions = [
|
|
|
- {
|
|
|
- value: 0,
|
|
|
- label: "已结课"
|
|
|
- },
|
|
|
- {
|
|
|
- value: 1,
|
|
|
- label: "未结课"
|
|
|
- },
|
|
|
- ]
|
|
|
+
|
|
|
+ const openSearchDialog = () => {
|
|
|
+ searchDialogVisible.value = true
|
|
|
+ // 延迟聚焦,确保对话框渲染完成
|
|
|
+ setTimeout(() => {
|
|
|
+ if (dialogSearchInput.value) {
|
|
|
+ dialogSearchInput.value.focus()
|
|
|
+ }
|
|
|
+ }, 100)
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleCloseSearchDialog = (done) => {
|
|
|
+ searchQuery.value = ''
|
|
|
+ searchResults.value = []
|
|
|
+ done()
|
|
|
+ }
|
|
|
+
|
|
|
+ const performSearch = () => {
|
|
|
+ const query = searchQuery.value.trim().toLowerCase()
|
|
|
+ if (!query) {
|
|
|
+ searchResults.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const results = []
|
|
|
+
|
|
|
+ // 搜索课程和作业
|
|
|
+ courseList.forEach(course => {
|
|
|
+ // 搜索课程
|
|
|
+ if (course.name.toLowerCase().includes(query)) {
|
|
|
+ results.push({
|
|
|
+ id: course.id,
|
|
|
+ name: course.name,
|
|
|
+ type: 'course'
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 搜索作业
|
|
|
+ course.assignments.forEach(assignment => {
|
|
|
+ if (assignment.name.toLowerCase().includes(query)) {
|
|
|
+ results.push({
|
|
|
+ id: assignment.id,
|
|
|
+ name: assignment.name,
|
|
|
+ courseName: course.name,
|
|
|
+ type: 'assignment'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ searchResults.value = results
|
|
|
+ }
|
|
|
+
|
|
|
+ const handleSearchResultClick = (result) => {
|
|
|
+ if (result.type === 'course') {
|
|
|
+ // 展开对应的课程
|
|
|
+ const course = courseList.find(c => c.id === result.id)
|
|
|
+ if (course) {
|
|
|
+ course.expanded = true
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 选中对应的作业并展开对应课程
|
|
|
+ courseList.forEach(course => {
|
|
|
+ const assignment = course.assignments.find(a => a.id === result.id)
|
|
|
+ if (assignment) {
|
|
|
+ course.expanded = true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ selectAssignment(result.id)
|
|
|
+ }
|
|
|
+ // 关闭弹窗
|
|
|
+ searchDialogVisible.value = false
|
|
|
+ searchQuery.value = ''
|
|
|
+ searchResults.value = []
|
|
|
+ }
|
|
|
</script>
|
|
|
|
|
|
<script lang="ts">
|
|
|
@@ -175,3 +601,602 @@ export default {
|
|
|
name: "CoursePage"
|
|
|
}
|
|
|
</script>
|
|
|
+<style scoped>
|
|
|
+.course-page {
|
|
|
+ display: flex;
|
|
|
+ height: 95vh;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.left-sidebar {
|
|
|
+ width: 320px;
|
|
|
+ background-color: white;
|
|
|
+ border-right: 1px solid #e8e8e8;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 100vh;
|
|
|
+}
|
|
|
+
|
|
|
+.platform-header {
|
|
|
+ height: 60px;
|
|
|
+ background-color: #F0F2F5;
|
|
|
+ border-bottom: 1px solid #e8e8e8;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 0 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.platform-name {
|
|
|
+ color: #606266;
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: 400;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.search-section {
|
|
|
+ padding: 16px 20px;
|
|
|
+ border-bottom: 1px solid #e8e8e8;
|
|
|
+ background-color: #F0F2F5;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input-container {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.search-icon {
|
|
|
+ position: absolute;
|
|
|
+ left: 12px;
|
|
|
+ color: #999;
|
|
|
+ font-size: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input {
|
|
|
+ width: 100%;
|
|
|
+ height: 36px;
|
|
|
+ padding: 0 12px 0 36px;
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
+ border-radius: 6px;
|
|
|
+ font-size: 14px;
|
|
|
+ outline: none;
|
|
|
+ background-color: #FFFFFF;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.search-input:focus {
|
|
|
+ border-color: #1890ff;
|
|
|
+ background-color: white;
|
|
|
+}
|
|
|
+
|
|
|
+.menu-section {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+ padding: 0;
|
|
|
+ height: calc(100vh - 120px);
|
|
|
+}
|
|
|
+
|
|
|
+.menu-item {
|
|
|
+ margin-bottom: 0px;
|
|
|
+}
|
|
|
+
|
|
|
+.course-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 12px 20px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: background-color 0.2s;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ background-color: #F0F2F5;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+
|
|
|
+.course-header:hover {
|
|
|
+ background-color: #FFFFFF;
|
|
|
+}
|
|
|
+
|
|
|
+.expand-icon {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
+ margin-right: 8px;
|
|
|
+ transition: transform 0.2s;
|
|
|
+}
|
|
|
+
|
|
|
+.expand-icon.expanded {
|
|
|
+ transform: rotate(0deg);
|
|
|
+}
|
|
|
+
|
|
|
+.course-icon {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #666;
|
|
|
+ margin-right: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.course-name {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ font-weight: 500;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-list {
|
|
|
+ background-color: #fafafa;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8px 20px 8px 48px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: background-color 0.2s;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ background-color: #F0F2F5;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-item:hover {
|
|
|
+ background-color: #FFFFFF;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-item.active {
|
|
|
+ background-color: rgba(112, 187, 219, 0.50);
|
|
|
+ border-radius: 10px;
|
|
|
+ opacity: 0.8;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-icon {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ margin-right: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-icon.active-icon {
|
|
|
+ color: #435FE9;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-name {
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #606266;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-item.active .assignment-name {
|
|
|
+ color: #435FE9;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.right-content {
|
|
|
+ flex: 1;
|
|
|
+ background-color: white;
|
|
|
+ padding: 20px;
|
|
|
+ height: 100vh;
|
|
|
+}
|
|
|
+
|
|
|
+/* 空白状态样式 */
|
|
|
+.empty-state {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-content {
|
|
|
+ text-align: center;
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-icon {
|
|
|
+ font-size: 64px;
|
|
|
+ color: #d9d9d9;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.empty-text {
|
|
|
+ font-size: 16px;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+ /* 作业内容样式 */
|
|
|
+ .assignment-content {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 右上角按钮样式 */
|
|
|
+ .top-actions {
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dashboard-button {
|
|
|
+ background-color: #4A90C4;
|
|
|
+ border-color: #4A90C4;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 6px 12px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 统计卡片区域样式 */
|
|
|
+ .stats-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ padding: 0;
|
|
|
+ gap: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stats-card {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background: white;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 16px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
+ min-width: 180px;
|
|
|
+ max-width: 220px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stats-icon {
|
|
|
+ width: 48px;
|
|
|
+ height: 48px;
|
|
|
+ border-radius: 8px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-right: 12px;
|
|
|
+ font-size: 24px;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ .user-icon {
|
|
|
+ background-color: #70BBD9;
|
|
|
+ }
|
|
|
+
|
|
|
+ .completed-icon {
|
|
|
+ background-color: #90D7B4;
|
|
|
+ }
|
|
|
+
|
|
|
+ .pending-icon {
|
|
|
+ background-color: #B8B8B8;
|
|
|
+ }
|
|
|
+
|
|
|
+ .not-submitted-icon {
|
|
|
+ background-color: #F5A658;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stats-content {
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stats-label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666;
|
|
|
+ margin-bottom: 4px;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ .stats-value {
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ .assignment-body {
|
|
|
+ flex: 1;
|
|
|
+ padding: 20px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 作业标题区域 */
|
|
|
+ .assignment-title-section {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .assignment-full-title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #333;
|
|
|
+ margin: 0;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 筛选区域样式 */
|
|
|
+ .filter-section {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-controls {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .reset-icon {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #666;
|
|
|
+ cursor: pointer;
|
|
|
+ padding: 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+ transition: background-color 0.2s;
|
|
|
+ }
|
|
|
+
|
|
|
+ .reset-icon:hover {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .search-input-wrapper {
|
|
|
+ flex: 1;
|
|
|
+ max-width: 300px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-search-input {
|
|
|
+ width: 90%;
|
|
|
+ height: 32px;
|
|
|
+ padding: 0 12px;
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ outline: none;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-search-input:focus {
|
|
|
+ border-color: #4A90C4;
|
|
|
+ }
|
|
|
+
|
|
|
+ .filter-select {
|
|
|
+ width: 120px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .search-button {
|
|
|
+ background-color: #4A90C4;
|
|
|
+ border-color: #4A90C4;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 表格区域样式 */
|
|
|
+ .table-section {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .student-table {
|
|
|
+ width: 100%;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 状态标签样式 */
|
|
|
+ .status-badge {
|
|
|
+ padding: 4px 8px;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 500;
|
|
|
+ display: inline-block;
|
|
|
+ width: 100%;
|
|
|
+ text-align: left;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 状态列单元格左对齐 */
|
|
|
+ .student-table .el-table__cell {
|
|
|
+ text-align: left !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .student-table .el-table__header-wrapper .el-table__cell {
|
|
|
+ text-align: left !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-未提交 {
|
|
|
+ background-color: #F4A261;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-已提交未批改 {
|
|
|
+ background-color: #D9D9D9;
|
|
|
+ color: #666;
|
|
|
+ }
|
|
|
+
|
|
|
+ .status-已批改 {
|
|
|
+ background-color: #7ADBB0;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 分数标签样式 */
|
|
|
+ .score-badge {
|
|
|
+ padding: 4px 8px;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-not-submitted {
|
|
|
+ background-color: #F4A261;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-not-graded {
|
|
|
+ background-color: #D9D9D9;
|
|
|
+ color: #666;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-low {
|
|
|
+ background-color: #F0C05A;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-high {
|
|
|
+ background-color: #7ADBB0;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 操作按钮样式 */
|
|
|
+ .action-button {
|
|
|
+ background-color: #4A90C4;
|
|
|
+ border-color: #4A90C4;
|
|
|
+ padding: 4px 8px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 排序头部样式 */
|
|
|
+ .score-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ cursor: pointer;
|
|
|
+ user-select: none;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sort-icon {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #999;
|
|
|
+ transition: color 0.2s;
|
|
|
+ }
|
|
|
+
|
|
|
+ .sort-icon.sort-asc {
|
|
|
+ color: #4A90C4;
|
|
|
+ transform: rotate(0deg);
|
|
|
+ }
|
|
|
+
|
|
|
+ .sort-icon.sort-desc {
|
|
|
+ color: #4A90C4;
|
|
|
+ transform: rotate(180deg);
|
|
|
+ }
|
|
|
+
|
|
|
+ .sort-icon.sort-default {
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-header:hover .sort-icon {
|
|
|
+ color: #4A90C4;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/* 搜索弹窗样式 */
|
|
|
+.search-dialog-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ height: 60vh;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-search-section {
|
|
|
+ padding-bottom: 16px;
|
|
|
+ border-bottom: 1px solid #e8e8e8;
|
|
|
+ margin-bottom: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-search-input-container {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-search-icon {
|
|
|
+ position: absolute;
|
|
|
+ left: 12px;
|
|
|
+ color: #999;
|
|
|
+ font-size: 18px;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-search-input {
|
|
|
+ width: 100%;
|
|
|
+ height: 40px;
|
|
|
+ padding: 0 12px 0 40px;
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
+ border-radius: 6px;
|
|
|
+ font-size: 16px;
|
|
|
+ outline: none;
|
|
|
+ background-color: #FFFFFF;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.dialog-search-input:focus {
|
|
|
+ border-color: #1890ff;
|
|
|
+}
|
|
|
+
|
|
|
+.search-results-section {
|
|
|
+ flex: 1;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.no-results {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ color: #999;
|
|
|
+ font-size: 14px;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.search-results-list {
|
|
|
+ height: 100%;
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.search-result-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 12px 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ border-bottom: 1px solid #e8e8e8;
|
|
|
+ transition: background-color 0.2s;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.search-result-item:hover {
|
|
|
+ background-color: #F0F2F5;
|
|
|
+}
|
|
|
+
|
|
|
+.result-icon {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #606266;
|
|
|
+ margin-right: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.assignment-result-icon {
|
|
|
+ font-size: 16px;
|
|
|
+ margin-left: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.result-content {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+
|
|
|
+.result-title {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #606266;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.result-path {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #999;
|
|
|
+ margin-top: 4px;
|
|
|
+ font-family: "Noto Sans SC", sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+.example-pagination-block {
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+</style>
|
|
|
+
|