783 lines
24 KiB
Vue
783 lines
24 KiB
Vue
<template>
|
||
<div>
|
||
<h2>我添加的课程</h2>
|
||
|
||
<!-- 加载状态 -->
|
||
<div v-if="!isLoaded" class="loading-message">
|
||
加载中,请稍后...
|
||
</div>
|
||
|
||
<!-- 无课程记录时的提示 -->
|
||
<div v-else-if="submissions.length === 0" class="empty-message">
|
||
您还没有添加任何课程。
|
||
</div>
|
||
|
||
<!-- 课程投稿记录表格 -->
|
||
<div v-else class="course-table">
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>课程名</th>
|
||
<th>分类</th>
|
||
<th>教师</th>
|
||
<th>开课院系</th> <!-- 新增列 -->
|
||
<th>提交时间</th>
|
||
<th>状态更新时间</th>
|
||
<th>审核状态</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr v-for="submission in paginatedSubmissions" :key="submission.submit_id">
|
||
<td>
|
||
<span v-if="submission.course_id === 0">{{ submission.course_name }}</span>
|
||
<span v-else class="clickable-text" @click="loadCourseDetail(submission.course_id)">
|
||
{{ submission.course_name }}
|
||
</span>
|
||
</td>
|
||
|
||
<td>{{ getCategoryName(submission.category_id) }}</td>
|
||
<td>{{ submission.teachers }}</td>
|
||
<td>{{ getCollegeName(submission.college) }}</td> <!-- 显示院系名称 -->
|
||
<td>{{ formatTime(submission.create_time) }}</td>
|
||
<td>{{ formatTime(submission.status_update_time) }}</td>
|
||
<td>{{ submission.status }}</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<!-- 页码栏 -->
|
||
<div class="pagination-bar">
|
||
<button v-for="page in totalPages" :key="page" @click="goToPage(page)" :class="{ active: currentPage === page }">
|
||
{{ page }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 添加课程区域 -->
|
||
<div class="add-course">
|
||
<div class="section-header">
|
||
<h2>我要添加课程</h2>
|
||
<button class="help-btn" @click="showHelp = true">
|
||
<span class="help-icon">?</span>
|
||
帮助
|
||
</button>
|
||
</div>
|
||
|
||
<div class="input-section">
|
||
<input v-model="newCourseName" type="text" placeholder="请输入课程名称" />
|
||
<select v-model="newCategoryId">
|
||
<option value="" disabled>请选择课程类别</option>
|
||
<option value="1">选修课-通识选修类</option>
|
||
<option value="2">选修课-人文选修类</option>
|
||
<option value="3">选修课-专业方向类</option>
|
||
<option value="4">选修课-体育类</option>
|
||
<option value="5">选修课-学科基础类</option>
|
||
<option value="6">选修课-暑期国际课</option>
|
||
<option value="7">选修课-数学与自然科学类</option>
|
||
<option value="8">选修课-重修专栏</option>
|
||
<option value="9">必修课-数学与自然科学类</option>
|
||
<option value="10">必修课-人文社会科学类</option>
|
||
<option value="11">必修课-学科基础类</option>
|
||
<option value="12">必修课-专业方向类</option>
|
||
<option value="13">必修课-实践类</option>
|
||
</select>
|
||
|
||
<!-- 新增选择开课院系下拉框 -->
|
||
<select v-model="newCollege">
|
||
<option value="" disabled>请选择开课院系</option>
|
||
<option v-for="(name, id) in filteredColleges" :key="id" :value="id">
|
||
{{ name }}
|
||
</option>
|
||
</select>
|
||
|
||
<input v-model="newTeachers" type="text" placeholder="请输入任课教师(多个教师之间用英文逗号,隔开)" />
|
||
<button @click="submitCourse">提交</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 调用 CourseDetailModal 组件,传入选中的课程 -->
|
||
<CourseDetailModal
|
||
:isVisible="showDetail"
|
||
:course="selectedCourse"
|
||
@close="closeCourseDetail"
|
||
/>
|
||
|
||
<!-- 添加帮助模态框 -->
|
||
<div v-if="showHelp" class="help-modal">
|
||
<div class="help-modal-content">
|
||
<div class="help-modal-header">
|
||
<h3>关于本系统课程信息的说明</h3>
|
||
<button class="close-btn" @click="showHelp = false">×</button>
|
||
</div>
|
||
<div class="help-modal-body">
|
||
<h3>一些说明</h3>
|
||
<div class="help-section">
|
||
<p>
|
||
<strong>本系统中,课程分为两大类:选修课和必修课。</strong>选修课有8个小类:通识选修、人文选修、专业方向、体育、学科基础、暑期国际课、数学与自然科学、重修专栏。<strong>人文选修类包括采用“抢选”方式进行选课的所有选修课,以及“改革开放史”和“社会主义发展史”两门人文社会科学类的选修课。</strong>体育课单独作为一类,不属于人文选修类。<strong>重修课程的选课归为选修课的“重修专栏”类别,不属于必修课范畴。</strong>重修专栏可以分享<strong>任何类别课程</strong>,但<strong>仅限分享重修体验</strong>。
|
||
</p>
|
||
<p>
|
||
必修课有5个小类:数学与自然科学、人文社会科学、学科基础、专业方向、实践。<strong>如上所述,本系统中重修的必修课程也属于选修课范畴。</strong>特别说明:<strong>军训课程属于实践类,系辅导员给分,在创建课程时课程教师请填写辅导员。</strong>
|
||
</p>
|
||
<p>
|
||
在创建课程时,请先了解课程的类别,以及课程的<strong>开课院系(详见下文)</strong>。<strong>如果同一课程的任课教师不同,用户可以创建多个同名课程,例如“A老师-篮球”和“B老师-篮球”将被视为两个不同的课程。</strong>创建的课程卡片<strong>需经过管理员审核</strong>,审核进度可在“我的课程”中实时查看。
|
||
</p>
|
||
</div>
|
||
|
||
<h3>如何查看课程类别和开课院系?</h3>
|
||
<div class="help-section">
|
||
<h4>1. 本人课程</h4>
|
||
<p>在教务系统选择“我的考试”,选择对应的学期后,即可查看当前学期的课程类别和开课院系。</p>
|
||
<img src="https://download.东北大学.com/course_system/coursehelp.png" width="98%">
|
||
</div>
|
||
<div class="help-section">
|
||
<h4>2. 非本人课程</h4>
|
||
<p>在教务系统选择“公共课表查询”,课表类型选择“班级课表”,再选好要查询的学期,并填写要查询的班级名称,点击查询按钮。</p>
|
||
<img src="https://download.东北大学.com/course_system/other1.png" width="98%">
|
||
<p>进入班级课表后,即可对应课程的开课院系。然后记下老师的姓名。</p>
|
||
<img src="https://download.东北大学.com/course_system/other2.png" width="98%">
|
||
<p>然后回到公共课表查询页面,课表类型选择“教师课表”,同样选好要查询的学期,并填写要查询的教师姓名,点击查询按钮。</p>
|
||
<img src="https://download.东北大学.com/course_system/other3.png" width="98%">
|
||
<p>进入教师课表后,找到此课程,即可查看课程类别。</p>
|
||
<img src="https://download.东北大学.com/course_system/other4.png" width="98%">
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
|
||
<script>
|
||
// 引入 CourseDetailModal 组件
|
||
import CourseDetailModal from './CourseDetailModal.vue';
|
||
|
||
export default {
|
||
components: {
|
||
CourseDetailModal
|
||
},
|
||
data() {
|
||
return {
|
||
submissions: [], // 存储用户提交的课程数据
|
||
newCourseName: '', // 新提交的课程名
|
||
newCategoryId: '', // 新提交的课程分类
|
||
newTeachers: '', // 新提交的任课教师
|
||
newCollege: '', // 新提交的课程院系,默认空字符串
|
||
currentPage: 1, // 当前页
|
||
itemsPerPage: 10, // 每页显示的条目数
|
||
totalPages: 1, // 总页数
|
||
isLoaded: false, // 控制页面加载状态
|
||
selectedCourse: null, // 存储选中的课程详情
|
||
showDetail: false, // 控制模态框显示
|
||
cachedEmail: null, // 缓存的邮箱信息
|
||
collegeMap: {
|
||
59: '未填写',
|
||
1: '材料科学与工程学院',
|
||
2: '创新创业学院',
|
||
3: '档案馆',
|
||
4: '党委宣传部',
|
||
5: '党委组织部',
|
||
6: '发展规划与学科建设处',
|
||
7: '佛山研究生创新学院',
|
||
8: '工程训练中心',
|
||
9: '工会',
|
||
10: '工商管理学院',
|
||
11: '国防教育学院',
|
||
12: '国际教育学院',
|
||
13: '后勤服务中心',
|
||
14: '后勤管理处',
|
||
15: '浑南管委会',
|
||
16: '江河建筑学院',
|
||
17: '尖子班',
|
||
18: '教务处',
|
||
19: '基础学院',
|
||
20: '计划财经处',
|
||
21: '机器人科学与工程学院',
|
||
22: '计算机科学与工程学院',
|
||
23: '计算中心',
|
||
24: '纪委',
|
||
25: '机械工程与自动化学院',
|
||
26: '继续教育学院',
|
||
27: '科技产业集团',
|
||
28: '科学技术研究院',
|
||
29: '理学院',
|
||
30: '马克思主义学院',
|
||
31: '民族教育学院',
|
||
33: '人事处',
|
||
34: '人文选修课群',
|
||
35: '软件学院',
|
||
36: '生命科学与健康学院',
|
||
37: '体育部',
|
||
38: '体育场馆管理中心',
|
||
39: '团委',
|
||
40: '图书馆',
|
||
41: '外国语学院',
|
||
42: '外联处',
|
||
43: '网络教育学院',
|
||
44: '未来技术学院',
|
||
45: '文法学院',
|
||
46: '校长办公室',
|
||
47: '信息科学与工程学院',
|
||
48: '新知识课群',
|
||
49: '学生处',
|
||
50: '学生创新中心',
|
||
51: '学生指导服务中心',
|
||
52: '研究生院',
|
||
53: '冶金学院',
|
||
54: '艺术学院',
|
||
55: '医学与生物信息工程学院',
|
||
56: '医院',
|
||
57: '资产与实验室管理处',
|
||
58: '资源与土木工程学院'
|
||
},
|
||
showHelp: false // 添加这一行来控制帮助模态框的显示
|
||
};
|
||
},
|
||
computed: {
|
||
// 计算当前页展示的投稿数据
|
||
paginatedSubmissions() {
|
||
const start = (this.currentPage - 1) * this.itemsPerPage;
|
||
const end = start + this.itemsPerPage;
|
||
return this.submissions.slice(start, end);
|
||
},
|
||
|
||
// 过滤掉 "不限院系" 的选项
|
||
filteredColleges() {
|
||
return Object.fromEntries(Object.entries(this.collegeMap).filter(([id]) => id !== '59'));
|
||
}
|
||
},
|
||
mounted() {
|
||
// 页面加载时,延迟0.3秒加载数据
|
||
setTimeout(async () => {
|
||
this.isLoaded = true;
|
||
|
||
// 首先获取并缓存邮箱
|
||
await this.fetchAndCacheEmail();
|
||
|
||
// 然后获取投稿记录
|
||
this.fetchSubmissions();
|
||
}, 300);
|
||
|
||
// 检查 URL 参数,如果 m=true 则打开帮助模态框
|
||
if (this.$route.query.m === 'true') {
|
||
this.showHelp = true;
|
||
}
|
||
|
||
// 在组件挂载后获取查询参数并处理
|
||
const encodedParam = this.$route.query.c;
|
||
if (encodedParam) {
|
||
// 尝试解码并验证
|
||
try {
|
||
// Base64 URL 解码
|
||
const decodedString = atob(encodedParam);
|
||
|
||
// 检查是否为正整数
|
||
if (this.isPositiveInteger(decodedString)) {
|
||
this.decodedParam = decodedString;
|
||
this.isValid = true;
|
||
// console.log('Valid Param:', this.decodedParam);
|
||
// 打开课程模态框
|
||
this.loadCourseDetail(this.decodedParam);
|
||
} else {
|
||
// console.warn('Decoded param is not a valid positive integer.');
|
||
}
|
||
} catch (error) {
|
||
// console.error('Error decoding Base64 URL param:', error);
|
||
}
|
||
} else {
|
||
// console.warn('No parameter provided.');
|
||
}
|
||
},
|
||
|
||
methods: {
|
||
// 检查是否为正整数
|
||
isPositiveInteger(value) {
|
||
// 检查value是否是正整数
|
||
const num = Number(value);
|
||
return Number.isInteger(num) && num > 0;
|
||
},
|
||
|
||
// 统一的函数,用于从JWT获取并缓存邮箱
|
||
async fetchAndCacheEmail() {
|
||
if (this.cachedEmail) {
|
||
return; // 如果已经缓存了邮箱,则不需要再次请求
|
||
}
|
||
|
||
const cookies = document.cookie.split('; ');
|
||
const tokenCookie = cookies.find(cookie => cookie.startsWith('token='));
|
||
const token = tokenCookie ? tokenCookie.split('=')[1] : '';
|
||
|
||
if (!token) {
|
||
console.error('未找到JWT信息');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 发送请求到后端验证JWT并获取邮箱
|
||
const response = await fetch('https://userlogin.xn--xhq44jb2fzpc.com/verifyToken', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Authorization': token
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.ok && result.email) {
|
||
this.cachedEmail = result.email; // 缓存邮箱信息
|
||
} else {
|
||
console.error('JWT验证失败或未找到邮箱');
|
||
}
|
||
} catch (error) {
|
||
console.error('JWT验证时出错:', error);
|
||
}
|
||
},
|
||
|
||
// 获取用户投稿
|
||
// 获取用户投稿
|
||
async fetchSubmissions() {
|
||
// 从 Cookie 中获取 JWT token
|
||
const token = this.getCookie('token');
|
||
|
||
if (!token) {
|
||
alert('无法获取JWT,请重新登录。');
|
||
return;
|
||
}
|
||
|
||
// 调用查询投稿记录的接口,并添加 Authorization 头
|
||
const response = await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/user/user-submissions`, {
|
||
method: 'GET',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Authorization': token // 添加 JWT 到 Authorization 头
|
||
}
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (response.status !== 200) {
|
||
alert(result.error || '查询投稿记录失败');
|
||
return;
|
||
}
|
||
|
||
// 存储查询结果
|
||
this.submissions = result;
|
||
this.totalPages = Math.ceil(this.submissions.length / this.itemsPerPage);
|
||
},
|
||
|
||
|
||
|
||
// 读取 cookie 的辅助函数
|
||
getCookie(name) {
|
||
const cookies = document.cookie.split(';');
|
||
for (let cookie of cookies) {
|
||
const [key, value] = cookie.trim().split('=');
|
||
if (key === name) {
|
||
return value;
|
||
}
|
||
}
|
||
return null;
|
||
},
|
||
|
||
|
||
|
||
// 分页功能
|
||
goToPage(page) {
|
||
this.currentPage = page;
|
||
},
|
||
|
||
// 提交新课程
|
||
async submitCourse() {
|
||
if (!this.newCourseName || !this.newCategoryId || !this.newTeachers || !this.newCollege) {
|
||
alert('请填写所有字段后提交!');
|
||
return;
|
||
}
|
||
|
||
if (confirm('确认提交审核吗?')) {
|
||
// 从 Cookie 中获取 JWT token
|
||
const token = this.getCookie('token');
|
||
|
||
if (!token) {
|
||
alert('无法获取JWT,请重新登录。');
|
||
return;
|
||
}
|
||
|
||
const newSubmission = {
|
||
course_name: this.newCourseName,
|
||
category_id: this.newCategoryId,
|
||
teachers: this.newTeachers,
|
||
college: this.newCollege
|
||
};
|
||
|
||
await fetch('https://coursesystem.xn--xhq44jb2fzpc.com/user/submit-course', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'Authorization': token // 添加 JWT 到 Authorization 头
|
||
},
|
||
body: JSON.stringify(newSubmission)
|
||
});
|
||
|
||
// 清空输入框并重新加载投稿记录
|
||
this.newCourseName = '';
|
||
this.newCategoryId = '';
|
||
this.newTeachers = '';
|
||
this.newCollege = '';
|
||
this.fetchSubmissions();
|
||
}
|
||
},
|
||
|
||
|
||
// 获取分类名称
|
||
getCategoryName(categoryId) {
|
||
const categoryMap = {
|
||
1: '选修课-通识选修类',
|
||
2: '选修课-人文选修类',
|
||
3: '选修课-专业方向类',
|
||
4: '选修课-体育类',
|
||
5: '选修课-学科基础类',
|
||
6: '选修课-暑期国际课',
|
||
7: '选修课-数学与自然科学类',
|
||
8: '选修课-重修专栏',
|
||
9: '必修课-数学与自然科学类',
|
||
10: '必修课-人文社会科学类',
|
||
11: '必修课-学科基础类',
|
||
12: '必修课-专业方向类',
|
||
13: '必修课-实践类'
|
||
};
|
||
return categoryMap[categoryId] || '未知分类';
|
||
},
|
||
|
||
// 格式化时间
|
||
formatTime(time) {
|
||
const date = new Date(time);
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
const hours = String(date.getHours()).padStart(2, '0');
|
||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||
},
|
||
|
||
// 打开课程详情模态框
|
||
async loadCourseDetail(courseId) {
|
||
try {
|
||
const response = await fetch(`https://coursesystem.xn--xhq44jb2fzpc.com/course-detail?course_id=${courseId}`);
|
||
const course = await response.json();
|
||
this.selectedCourse = course;
|
||
this.showDetail = true;
|
||
} catch (error) {
|
||
console.error('Error loading course details:', error);
|
||
}
|
||
},
|
||
|
||
// 关闭课程详情模态框
|
||
closeCourseDetail() {
|
||
this.showDetail = false;
|
||
this.selectedCourse = null;
|
||
},
|
||
|
||
getCollegeName(collegeId) {
|
||
const collegeMap = {
|
||
59: '未填写',
|
||
1: '材料科学与工程学院',
|
||
2: '创新创业学院',
|
||
3: '档案馆',
|
||
4: '党委宣传部',
|
||
5: '党委组织部',
|
||
6: '发展规划与学科建设处',
|
||
7: '佛山研究生创新学院',
|
||
8: '工程训练中心',
|
||
9: '工会',
|
||
10: '工商管理学院',
|
||
11: '国防教育学院',
|
||
12: '国际教育学院',
|
||
13: '后勤服务中心',
|
||
14: '后勤管理处',
|
||
15: '浑南管委会',
|
||
16: '江河建筑学院',
|
||
17: '尖子班',
|
||
18: '教务处',
|
||
19: '基础学院',
|
||
20: '计划财经处',
|
||
21: '机器人科学与工程学院',
|
||
22: '计算机科学与工程学院',
|
||
23: '计算中心',
|
||
24: '纪委',
|
||
25: '机械工程与自动化学院',
|
||
26: '继续教育学院',
|
||
27: '科技产业集团',
|
||
28: '科学技术研究院',
|
||
29: '理学院',
|
||
30: '马克思主义学院',
|
||
31: '民族教育学院',
|
||
33: '人事处',
|
||
34: '人文选修课群',
|
||
35: '软件学院',
|
||
36: '生命科学与健康学院',
|
||
37: '体育部',
|
||
38: '体育场馆管理中心',
|
||
39: '团委',
|
||
40: '图书馆',
|
||
41: '外国语学院',
|
||
42: '外联处',
|
||
43: '网络教育学院',
|
||
44: '未来技术学院',
|
||
45: '文法学院',
|
||
46: '校长办公室',
|
||
47: '信息科学与工程学院',
|
||
48: '新知识课群',
|
||
49: '学生处',
|
||
50: '学生创新中心',
|
||
51: '学生指导服务中心',
|
||
52: '研究生院',
|
||
53: '冶金学院',
|
||
54: '艺术学院',
|
||
55: '医学与生物信息工程学院',
|
||
56: '医院',
|
||
57: '资产与实验室管理处',
|
||
58: '资源与土木工程学院'
|
||
};
|
||
return collegeMap[collegeId] || '未知院系';
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
|
||
<style scoped>
|
||
.loading-message {
|
||
font-size: 16px;
|
||
color: #666;
|
||
text-align: center;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
/* 美化表格,线表样式 */
|
||
.course-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
max-height: 270px; /* 设置最大高度,你可以根据需要调整 */
|
||
overflow-y: auto; /* 当内容超过最大高度时允许垂直滚动 */
|
||
}
|
||
|
||
.course-table thead {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 1;
|
||
}
|
||
|
||
.course-table th, .course-table td {
|
||
padding: 10px;
|
||
border-bottom: 1px solid #ddd; /* 只保留水平线 */
|
||
text-align: left;
|
||
}
|
||
|
||
.course-table th {
|
||
background-color: #f1f1f1;
|
||
font-weight: bold;
|
||
padding: 10px;
|
||
border-bottom: 1px solid #ddd;
|
||
text-align: left;
|
||
/* 确保表头背景色完全不透明 */
|
||
box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.course-table tr:hover {
|
||
background-color: #f9f9f9; /* 鼠标悬停时的背景颜色 */
|
||
}
|
||
|
||
/* 表单部分的输入框 */
|
||
.input-section input, .input-section select {
|
||
display: block;
|
||
margin: 10px 0;
|
||
padding: 10px;
|
||
width: 100%;
|
||
max-width: 400px;
|
||
border: 1px solid #ccc;
|
||
border-radius: 4px; /* 圆角 */
|
||
font-size: 16px;
|
||
transition: all 0.3s ease; /* 添加过渡效果 */
|
||
}
|
||
|
||
.input-section input:focus, .input-section select:focus {
|
||
border-color: #007bff;
|
||
outline: none;
|
||
box-shadow: 0 0 8px rgba(0, 123, 255, 0.5); /* 焦点效果 */
|
||
}
|
||
|
||
/* 美化按钮,添加圆角和缩放动画 */
|
||
.input-section button {
|
||
padding: 10px 20px;
|
||
background-color: #007bff;
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 8px; /* 圆角 */
|
||
cursor: pointer;
|
||
transition: transform 0.2s ease, background-color 0.3s ease; /* 添加缩放动画和过渡效果 */
|
||
}
|
||
|
||
.input-section button:hover {
|
||
background-color: #0056b3;
|
||
transform: scale(1.05); /* 放大效果 */
|
||
}
|
||
|
||
.input-section button:active {
|
||
transform: scale(0.95); /* 点击时缩小效果 */
|
||
}
|
||
|
||
/* 分页栏样式美化 */
|
||
.pagination-bar {
|
||
margin-top: 20px;
|
||
text-align: center;
|
||
}
|
||
|
||
.pagination-bar button {
|
||
margin: 0 5px;
|
||
padding: 5px 10px;
|
||
cursor: pointer;
|
||
border: 1px solid #ddd;
|
||
border-radius: 4px;
|
||
background-color: #ffffff;
|
||
transition: all 0.3s ease; /* 添加过渡效果 */
|
||
}
|
||
|
||
.pagination-bar button:hover {
|
||
background-color: #0400f9;
|
||
border-color: #0400f9;
|
||
color: white;
|
||
}
|
||
|
||
.pagination-bar .active {
|
||
background-color: #007bff;
|
||
color: white;
|
||
border-color: #007bff;
|
||
}
|
||
|
||
.clickable-text {
|
||
color: #007bff;
|
||
cursor: pointer;
|
||
text-decoration: none;
|
||
transition: color 0.2s ease; /* 鼠标悬浮时的过渡效果 */
|
||
}
|
||
|
||
.clickable-text:hover {
|
||
color: darkblue; /* 鼠标悬浮时颜色变化 */
|
||
}
|
||
|
||
.clickable-text:active {
|
||
color: navy; /* 点击时颜色变化 */
|
||
}
|
||
|
||
.empty-message {
|
||
text-align: center;
|
||
padding: 20px;
|
||
color: #666;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 15px;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.help-btn {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
padding: 5px 10px;
|
||
background: #f8f9fa;
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
color: #495057;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.help-btn:hover {
|
||
background: #e9ecef;
|
||
}
|
||
|
||
.help-icon {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 50%;
|
||
background: #6c757d;
|
||
color: white;
|
||
font-size: 12px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.help-modal {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: rgba(0, 0, 0, 0.5);
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 1000;
|
||
}
|
||
|
||
.help-modal-content {
|
||
background: white;
|
||
border-radius: 12px;
|
||
width: 90%;
|
||
max-width: 600px;
|
||
max-height: 80vh;
|
||
overflow-y: auto;
|
||
padding: 20px;
|
||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.help-modal-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 1px solid #dee2e6;
|
||
}
|
||
|
||
.close-btn {
|
||
background: none;
|
||
border: none;
|
||
font-size: 24px;
|
||
cursor: pointer;
|
||
color: #6c757d;
|
||
}
|
||
|
||
.help-section {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.help-modal-header h3 {
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.help-section h4 {
|
||
color: #0056b3;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
|
||
.help-section p {
|
||
color: #495057;
|
||
line-height: 1.6;
|
||
margin-bottom: 8px;
|
||
}
|
||
</style>
|
||
|