style: 题库首页,课件弹框
This commit is contained in:
parent
844d5721b7
commit
4d9b5eec2b
BIN
public/images/teacher/fj.png
Normal file
BIN
public/images/teacher/fj.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
BIN
public/images/teacher/上传2.png
Normal file
BIN
public/images/teacher/上传2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 554 B |
BIN
public/images/teacher/搜索.png
Normal file
BIN
public/images/teacher/搜索.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 515 B |
BIN
public/images/teacher/箭头-灰.png
Normal file
BIN
public/images/teacher/箭头-灰.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 552 B |
@ -3,9 +3,9 @@
|
||||
<!-- 顶部 -->
|
||||
<div class="top">
|
||||
<div class="nav-links">
|
||||
<a href="" class="active">全部</a>
|
||||
<a href="">发布中</a>
|
||||
<a href="">下架中</a>
|
||||
<a href="" class="active">进行中</a>
|
||||
<a href="">已结束</a>
|
||||
<a href="">草稿箱</a>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
@ -31,15 +31,13 @@
|
||||
<div class="options-menu">
|
||||
<template v-if="course.status === '发布中'">
|
||||
<a href="#" class="option-item"><img src="/images/teacher/下架.png" alt="">下架</a>
|
||||
<a href="javascript:void(0)" class="option-item"><img
|
||||
src="/images/teacher/小编辑.png" alt="">编辑</a>
|
||||
<a href="javascript:void(0)" class="option-item"><img src="/images/teacher/小编辑.png" alt="">编辑</a>
|
||||
<a href="#" class="option-item"><img src="/images/teacher/移动.png" alt="">移动</a>
|
||||
<a href="#" class="option-item"><img src="/images/teacher/删除.png" alt="">删除</a>
|
||||
</template>
|
||||
<template v-else-if="course.status === '下架中'">
|
||||
<a href="#" class="option-item"><img src="/images/teacher/加号.png" alt="">发布</a>
|
||||
<a href="javascript:void(0)" class="option-item"><img
|
||||
src="/images/teacher/小编辑.png" alt="">编辑</a>
|
||||
<a href="javascript:void(0)" class="option-item"><img src="/images/teacher/小编辑.png" alt="">编辑</a>
|
||||
<a href="#" class="option-item"><img src="/images/teacher/移动.png" alt="">移动</a>
|
||||
<a href="#" class="option-item"><img src="/images/teacher/删除.png" alt="">删除</a>
|
||||
</template>
|
||||
@ -85,18 +83,18 @@ const router = useRouter();
|
||||
|
||||
// 模拟课程数据
|
||||
const courseList = ref([
|
||||
{ id: 1, name: '前端开发基础课程', status: '发布中', image: 'https://picsum.photos/200/200?random=1' },
|
||||
{ id: 2, name: 'Vue.js 实战教程', status: '发布中', image: 'https://picsum.photos/200/200?random=2' },
|
||||
{ id: 3, name: 'React 入门到精通', status: '发布中', image: 'https://picsum.photos/200/200?random=3' },
|
||||
{ id: 4, name: 'Node.js 后端开发', status: '下架中', image: 'https://picsum.photos/200/200?random=4' },
|
||||
{ id: 5, name: 'TypeScript 高级教程', status: '发布中', image: 'https://picsum.photos/200/200?random=5' },
|
||||
{ id: 6, name: 'JavaScript 设计模式', status: '发布中', image: 'https://picsum.photos/200/200?random=6' },
|
||||
{ id: 7, name: 'CSS 动画与特效', status: '下架中', image: 'https://picsum.photos/200/200?random=7' },
|
||||
{ id: 8, name: 'HTML5 新特性详解', status: '发布中', image: 'https://picsum.photos/200/200?random=8' },
|
||||
{ id: 9, name: 'Web 性能优化指南', status: '发布中', image: 'https://picsum.photos/200/200?random=9' },
|
||||
{ id: 10, name: '移动端适配实战', status: '发布中', image: 'https://picsum.photos/200/200?random=10' },
|
||||
{ id: 11, name: '微信小程序开发', status: '下架中', image: 'https://picsum.photos/200/200?random=11' },
|
||||
{ id: 12, name: 'Flutter 跨平台开发', status: '发布中', image: 'https://picsum.photos/200/200?random=12' },
|
||||
{ id: 1, name: '前端开发基础课程', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
{ id: 2, name: 'Vue.js 实战教程', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
{ id: 3, name: 'React 入门到精通', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
{ id: 4, name: 'Node.js 后端开发', status: '下架中', image: '/images/teacher/fj.png' },
|
||||
{ id: 5, name: 'TypeScript 高级教程', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
{ id: 6, name: 'JavaScript 设计模式', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
{ id: 7, name: 'CSS 动画与特效', status: '下架中', image: '/images/teacher/fj.png' },
|
||||
{ id: 8, name: 'HTML5 新特性详解', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
{ id: 9, name: 'Web 性能优化指南', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
{ id: 10, name: '移动端适配实战', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
{ id: 11, name: '微信小程序开发', status: '下架中', image: '/images/teacher/fj.png' },
|
||||
{ id: 12, name: 'Flutter 跨平台开发', status: '发布中', image: '/images/teacher/fj.png' },
|
||||
]);
|
||||
|
||||
|
||||
@ -108,40 +106,49 @@ const navigateToCreateCourse = () => {
|
||||
|
||||
|
||||
<style scoped>
|
||||
.course-category{
|
||||
.course-category {
|
||||
background-color: #ffffff;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
min-height: 1181px;
|
||||
margin: 0; /* 移除所有边距 */
|
||||
margin: 0;
|
||||
/* 移除所有边距 */
|
||||
box-sizing: border-box;
|
||||
padding: 5px; /* 减少内边距 */
|
||||
position: relative; /* 添加相对定位,使分页按钮的绝对定位基于此容器 */
|
||||
overflow-x: hidden; /* 防止水平滚动 */
|
||||
/* 减少内边距 */
|
||||
position: relative;
|
||||
/* 添加相对定位,使分页按钮的绝对定位基于此容器 */
|
||||
overflow-x: hidden;
|
||||
/* 防止水平滚动 */
|
||||
}
|
||||
|
||||
.top {
|
||||
white-space: nowrap; /* 防止链接换行 */
|
||||
padding: 0 8px; /* 进一步减少左右padding */
|
||||
padding: 20px;
|
||||
white-space: nowrap;
|
||||
/* 进一步减少左右padding */
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
width: 100%; /* 确保宽度充满父容器 */
|
||||
width: 100%;
|
||||
/* 确保宽度充满父容器 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.top a{
|
||||
|
||||
.top a {
|
||||
margin-right: 74px;
|
||||
display: inline-block;
|
||||
height: 60px;
|
||||
@ -152,9 +159,11 @@ const navigateToCreateCourse = () => {
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.top a.active {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.top a.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@ -164,39 +173,46 @@ const navigateToCreateCourse = () => {
|
||||
height: 3px;
|
||||
background-color: #1890ff;
|
||||
}
|
||||
|
||||
.create-btn {
|
||||
background-color: #1890ff;
|
||||
background-color: #0288D1;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 6px 16px;
|
||||
border-radius: 4px;
|
||||
padding: 7px 16px;
|
||||
border-radius: 2px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
margin-right: 24px; /* 增加按钮与搜索框间距 */
|
||||
margin-right: 24px;
|
||||
/* 增加按钮与搜索框间距 */
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.create-btn:hover {
|
||||
background-color: #40a9ff;
|
||||
}
|
||||
|
||||
.search-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.search-container input {
|
||||
border: none;
|
||||
padding: 6px 12px;
|
||||
padding: 7px 12px;
|
||||
outline: none;
|
||||
font-size: 14px;
|
||||
width: 240px; /* 增加搜索框宽度 */
|
||||
width: 240px;
|
||||
/* 增加搜索框宽度 */
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
background-color: #0288D1;
|
||||
border: none;
|
||||
border-left: 1px solid #d9d9d9;
|
||||
padding: 6px 16px;
|
||||
padding: 8px 16px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
color: #FFFFFF;
|
||||
@ -206,27 +222,29 @@ const navigateToCreateCourse = () => {
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.search-btn:hover {
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.course-container{
|
||||
.course-container {
|
||||
width: 100%;
|
||||
|
||||
margin-top: 30px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.course-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr); /* 默认4列,确保100%缩放下不被截断 */
|
||||
gap: 12px; /* 进一步减少间距 */
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
/* 默认4列,确保100%缩放下不被截断 */
|
||||
gap: 12px;
|
||||
/* 进一步减少间距 */
|
||||
margin-bottom: 20px;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 0 3px; /* 减少内边距 */
|
||||
padding: 0 3px;
|
||||
/* 减少内边距 */
|
||||
}
|
||||
|
||||
.course-card {
|
||||
@ -245,6 +263,7 @@ const navigateToCreateCourse = () => {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.course-image-container {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
@ -278,6 +297,7 @@ const navigateToCreateCourse = () => {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.more-icon {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
@ -287,6 +307,7 @@ const navigateToCreateCourse = () => {
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.course-image-container img {
|
||||
width: 13px;
|
||||
height: 13px;
|
||||
@ -315,7 +336,7 @@ const navigateToCreateCourse = () => {
|
||||
background: white;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||
display: none;
|
||||
z-index: 10;
|
||||
width: auto;
|
||||
@ -341,10 +362,14 @@ const navigateToCreateCourse = () => {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.icon-edit, .icon-view, .icon-delete, .icon-more {
|
||||
.icon-edit,
|
||||
.icon-view,
|
||||
.icon-delete,
|
||||
.icon-more {
|
||||
margin-right: 4px;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.icon-view {
|
||||
color: #52c41a;
|
||||
}
|
||||
@ -356,6 +381,7 @@ const navigateToCreateCourse = () => {
|
||||
.icon-more {
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.option-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
@ -373,19 +399,21 @@ const navigateToCreateCourse = () => {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
}
|
||||
.course-info img{
|
||||
|
||||
.course-info img {
|
||||
width: 80%;
|
||||
height: auto;
|
||||
aspect-ratio: 150 / 105;
|
||||
/* 居中 */
|
||||
display: block;
|
||||
margin: 5px auto 20px; /* 增加图片下方间距从10px到20px */
|
||||
margin: 8px auto 10px;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
top: -5px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
.course-name{
|
||||
|
||||
.course-name {
|
||||
width: 80%;
|
||||
height: 20px;
|
||||
font-family: AppleSystemUIFont;
|
||||
@ -395,11 +423,16 @@ const navigateToCreateCourse = () => {
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
white-space: nowrap; /* 强制文本在一行显示 */
|
||||
overflow: hidden; /* 隐藏超出容器的文本 */
|
||||
text-overflow: ellipsis; /* 溢出部分用省略号表示 */
|
||||
margin-top: 0; /* 移除负边距,让文字与图片保持正常距离 */
|
||||
margin-bottom: 15px; /* 添加底部边距,让文字不挨着底部 */
|
||||
white-space: nowrap;
|
||||
/* 强制文本在一行显示 */
|
||||
overflow: hidden;
|
||||
/* 隐藏超出容器的文本 */
|
||||
text-overflow: ellipsis;
|
||||
/* 溢出部分用省略号表示 */
|
||||
margin-top: 0px;
|
||||
/* 文字往上移动:添加负上边距 */
|
||||
margin-bottom: 10px;
|
||||
/* 减小底部边距从15px到10px */
|
||||
}
|
||||
|
||||
/* 分页样式 */
|
||||
@ -432,7 +465,8 @@ const navigateToCreateCourse = () => {
|
||||
justify-content: center;
|
||||
gap: 0;
|
||||
width: 100%;
|
||||
white-space: nowrap; /* 确保所有页码在一行显示 */
|
||||
white-space: nowrap;
|
||||
/* 确保所有页码在一行显示 */
|
||||
}
|
||||
|
||||
.page-number {
|
||||
@ -490,8 +524,7 @@ const navigateToCreateCourse = () => {
|
||||
.course-category {
|
||||
max-width: 1800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #f5f5f5;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@ -506,7 +539,9 @@ const navigateToCreateCourse = () => {
|
||||
|
||||
.course-info img {
|
||||
width: 85%;
|
||||
margin: 8px auto 25px;
|
||||
margin: 12px auto 8px;
|
||||
/* 图片往下移动,文字往上移动 */
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
@ -514,7 +549,10 @@ const navigateToCreateCourse = () => {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
width: 85%;
|
||||
margin-bottom: 18px;
|
||||
margin-top: 1px;
|
||||
/* 文字往上移动 */
|
||||
margin-bottom: 10px;
|
||||
/* 减小底部间距 */
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@ -533,7 +571,6 @@ const navigateToCreateCourse = () => {
|
||||
.course-category {
|
||||
max-width: 1500px;
|
||||
margin: 0 auto;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.course-grid {
|
||||
@ -543,7 +580,9 @@ const navigateToCreateCourse = () => {
|
||||
|
||||
.course-info img {
|
||||
width: 82%;
|
||||
margin: 6px auto 22px;
|
||||
margin: 10px auto 6px;
|
||||
/* 图片往下移动,文字往上移动 */
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
@ -551,7 +590,10 @@ const navigateToCreateCourse = () => {
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
width: 82%;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -1px;
|
||||
/* 文字往上移动 */
|
||||
margin-bottom: 10px;
|
||||
/* 减小底部间距 */
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@ -590,12 +632,18 @@ const navigateToCreateCourse = () => {
|
||||
|
||||
.course-info img {
|
||||
width: 80%;
|
||||
margin: 8px auto 5px;
|
||||
/* 图片往下移动,文字往上移动 */
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
font-size: 14px;
|
||||
width: 80%;
|
||||
margin-bottom: 15px;
|
||||
margin-top: -5px;
|
||||
/* 文字往上移动 */
|
||||
margin-bottom: 10px;
|
||||
/* 减小底部间距 */
|
||||
}
|
||||
}
|
||||
|
||||
@ -612,7 +660,9 @@ const navigateToCreateCourse = () => {
|
||||
|
||||
.course-info img {
|
||||
width: 78%;
|
||||
margin: 5px auto 18px;
|
||||
margin: 8px auto 5px;
|
||||
/* 图片往下移动,文字往上移动 */
|
||||
top: -3px;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
@ -620,7 +670,10 @@ const navigateToCreateCourse = () => {
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
width: 78%;
|
||||
margin-bottom: 14px;
|
||||
margin-top: -5px;
|
||||
/* 文字往上移动 */
|
||||
margin-bottom: 10px;
|
||||
/* 减小底部间距 */
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@ -647,7 +700,9 @@ const navigateToCreateCourse = () => {
|
||||
|
||||
.course-info img {
|
||||
width: 75%;
|
||||
margin: 4px auto 15px;
|
||||
margin: 6px auto 4px;
|
||||
/* 图片往下移动,文字往上移动 */
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
@ -655,7 +710,10 @@ const navigateToCreateCourse = () => {
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
width: 75%;
|
||||
margin-bottom: 12px;
|
||||
margin-top: -4px;
|
||||
/* 文字往上移动 */
|
||||
margin-bottom: 8px;
|
||||
/* 减小底部间距 */
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@ -705,7 +763,9 @@ const navigateToCreateCourse = () => {
|
||||
|
||||
.course-info img {
|
||||
width: 70%;
|
||||
margin: 3px auto 12px;
|
||||
margin: 5px auto 3px;
|
||||
/* 图片往下移动,文字往上移动 */
|
||||
top: -2px;
|
||||
}
|
||||
|
||||
.course-name {
|
||||
@ -713,7 +773,10 @@ const navigateToCreateCourse = () => {
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
width: 70%;
|
||||
margin-bottom: 10px;
|
||||
margin-top: -3px;
|
||||
/* 文字往上移动 */
|
||||
margin-bottom: 6px;
|
||||
/* 减小底部间距 */
|
||||
}
|
||||
|
||||
.section-title {
|
||||
@ -782,5 +845,4 @@ const navigateToCreateCourse = () => {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -2,7 +2,9 @@
|
||||
<div class="course-management-container">
|
||||
<!-- 左侧导航栏 -->
|
||||
<div class="nav-container">
|
||||
<router-link to="/teacher/course-management" class="nav-item"
|
||||
<!-- 全部课程可折叠项 -->
|
||||
<div class="nav-group">
|
||||
<router-link to="/teacher/course-management" class="nav-item nav-header"
|
||||
:class="{ active: $route.path === '/teacher/course-management' }">
|
||||
<span>全部课程</span><i>(10)</i>
|
||||
<div class="icon-container">
|
||||
@ -10,8 +12,16 @@
|
||||
<span class="icon icon-status icon-edit"></span>
|
||||
<span class="icon icon-status icon-delete"></span>
|
||||
</div>
|
||||
<div class="arrow-container" @click.prevent="toggleMainNav">
|
||||
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" class="collapse-arrow"
|
||||
:style="{ transform: isMainNavExpanded ? 'rotate(-90deg)' : 'rotate(90deg)' }">
|
||||
<path
|
||||
d="M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</router-link>
|
||||
<div class="sub-nav-container">
|
||||
<div class="sub-nav-container" v-show="isMainNavExpanded">
|
||||
<router-link to="/teacher/course-management/course-category" class="nav-item sub-nav-item"
|
||||
:class="{ active: $route.path === '/teacher/course-management/course-category' }">
|
||||
<span>课程分类</span>
|
||||
@ -32,7 +42,7 @@
|
||||
</router-link>
|
||||
<router-link to="/teacher/course-management/course-analysis" class="nav-item sub-nav-item"
|
||||
:class="{ active: $route.path === '/teacher/course-management/course-analysis' }">
|
||||
<span>资料分类</span>
|
||||
<span>资料分析</span>
|
||||
<div class="icon-container">
|
||||
<span class="icon icon-status icon-add"></span>
|
||||
<span class="icon icon-status icon-edit"></span>
|
||||
@ -41,6 +51,7 @@
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧内容区域 -->
|
||||
<div class="content-container">
|
||||
@ -55,7 +66,16 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import CourseCategory from './CourseComponents/CourseCategory.vue'
|
||||
|
||||
// 主导航展开状态
|
||||
const isMainNavExpanded = ref(true)
|
||||
|
||||
// 切换主导航展开状态
|
||||
const toggleMainNav = () => {
|
||||
isMainNavExpanded.value = !isMainNavExpanded.value
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -65,19 +85,49 @@ import CourseCategory from './CourseComponents/CourseCategory.vue'
|
||||
}
|
||||
|
||||
.nav-container {
|
||||
margin-top: 20px;
|
||||
margin-top: 8px;
|
||||
padding: 15px;
|
||||
width: 274px;
|
||||
width: 220px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.nav-group {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nav-header {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.arrow-container {
|
||||
position: absolute;
|
||||
right: 50%;
|
||||
bottom: 4%;
|
||||
transform: translateX(50%);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.collapse-arrow {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: #666;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.collapse-arrow:hover {
|
||||
color: #0288D1;
|
||||
}
|
||||
.sub-nav-container {
|
||||
margin-left: 10px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.nav-container .nav-item {
|
||||
width: 240px;
|
||||
height: 54px;
|
||||
width: 190px;
|
||||
height: 50px;
|
||||
margin-top: 5px;
|
||||
margin-bottom: 13px;
|
||||
display: flex;
|
||||
@ -88,12 +138,12 @@ import CourseCategory from './CourseComponents/CourseCategory.vue'
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s ease;
|
||||
font-size: 18px;
|
||||
}
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.sub-nav-item {
|
||||
width: 220px !important;
|
||||
font-size: 16px !important;
|
||||
.sub-nav-item {
|
||||
width: 170px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
.nav-container .nav-item:hover {
|
||||
@ -142,7 +192,7 @@ import CourseCategory from './CourseComponents/CourseCategory.vue'
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
margin-left: 4px;
|
||||
opacity: 0; /* 默认不显示图标 */
|
||||
transition: opacity 0.3s ease, background-image 0.3s ease;
|
||||
}
|
||||
|
@ -278,7 +278,7 @@ const confirmBatchSet = () => {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
|
@ -1,10 +1,6 @@
|
||||
<template>
|
||||
<n-modal v-model:show="showModal" class="exam-settings-modal" preset="card" :mask-closable="false"
|
||||
:closable="false" :style="{ width: '1000px' }">
|
||||
<div class="header">
|
||||
<span class="header-title">试卷设置</span>
|
||||
</div>
|
||||
<n-divider />
|
||||
<n-modal v-model:show="showModal" class="exam-settings-modal" preset="dialog" title="试卷设置" :mask-closable="false"
|
||||
:closable="true" :style="{ width: '1000px' }">
|
||||
|
||||
<div class="exam-settings-content">
|
||||
<!-- 试卷名称 -->
|
||||
@ -25,12 +21,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 考试人数 -->
|
||||
<div class="setting-row">
|
||||
<label class="setting-label">考试人数</label>
|
||||
<n-input v-model:value="formData.examCount" placeholder="请输入考试人数" class="setting-input" />
|
||||
</div>
|
||||
|
||||
<!-- 试卷分类 -->
|
||||
<div class="setting-row">
|
||||
<label class="setting-label">试卷分类</label>
|
||||
@ -268,10 +258,12 @@
|
||||
</div>
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<template #action>
|
||||
<div class="modal-actions">
|
||||
<n-button @click="cancelSettings">取消</n-button>
|
||||
<n-button type="primary" @click="confirmSettings">确定</n-button>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
@ -298,7 +290,6 @@ interface ExamSettings {
|
||||
participants: 'all' | 'by_school';
|
||||
selectedClasses: string[];
|
||||
instructions: string;
|
||||
examCount: number;
|
||||
|
||||
// 考试模式专用
|
||||
enforceOrder: boolean;
|
||||
@ -372,7 +363,6 @@ const formData = ref<ExamSettings>({
|
||||
participants: 'all',
|
||||
selectedClasses: [],
|
||||
instructions: '',
|
||||
examCount: 0,
|
||||
|
||||
// 考试模式专用
|
||||
enforceOrder: false,
|
||||
@ -464,12 +454,6 @@ const confirmSettings = () => {
|
||||
--n-color: #ffffff;
|
||||
}
|
||||
|
||||
.header-title{
|
||||
color: #000;
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.exam-settings-content {
|
||||
max-height: 800px;
|
||||
overflow-y: auto;
|
||||
@ -729,7 +713,6 @@ const confirmSettings = () => {
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
|
@ -29,15 +29,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { defineProps, defineEmits } from 'vue'
|
||||
import { defineEmits } from 'vue'
|
||||
|
||||
// 定义props
|
||||
const props = defineProps({
|
||||
show: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
// const props = defineProps({
|
||||
// show: {
|
||||
// type: Boolean,
|
||||
// required: true
|
||||
// }
|
||||
// })
|
||||
|
||||
// 定义emits
|
||||
const emit = defineEmits(['confirm', 'cancel'])
|
||||
|
@ -24,44 +24,6 @@
|
||||
<img :src="activeNavItem === 0 ? '/images/teacher/课程管理(选中).png' : '/images/teacher/课程管理.png'" alt="">
|
||||
<span>课程管理</span>
|
||||
</router-link>
|
||||
|
||||
<!-- 考试管理 - 可展开菜单 -->
|
||||
<div class="nav-item" :class="{ active: activeNavItem === 4 }" @click="toggleExamMenu">
|
||||
<img :src="activeNavItem === 4 ? '/images/teacher/练考通-选中.png' : '/images/teacher/练考通.png'" alt="">
|
||||
<span>考试管理</span>
|
||||
<n-icon class="expand-icon" :class="{ expanded: examMenuExpanded }">
|
||||
<ChevronDownOutline />
|
||||
</n-icon>
|
||||
</div>
|
||||
|
||||
<!-- 考试管理子菜单 -->
|
||||
<div class="submenu-container" :class="{ expanded: examMenuExpanded }">
|
||||
<router-link
|
||||
to="/teacher/exam-management/question-management"
|
||||
class="submenu-item"
|
||||
:class="{ active: activeSubNavItem === 'question-management' }"
|
||||
@click="setActiveSubNavItem('question-management')"
|
||||
>
|
||||
<span>试题管理</span>
|
||||
</router-link>
|
||||
<router-link
|
||||
to="/teacher/exam-management/exam-library"
|
||||
class="submenu-item"
|
||||
:class="{ active: activeSubNavItem === 'exam-library' }"
|
||||
@click="setActiveSubNavItem('exam-library')"
|
||||
>
|
||||
<span>试卷管理</span>
|
||||
</router-link>
|
||||
<router-link
|
||||
to="/teacher/exam-management/marking-center"
|
||||
class="submenu-item"
|
||||
:class="{ active: activeSubNavItem === 'marking-center' }"
|
||||
@click="setActiveSubNavItem('marking-center')"
|
||||
>
|
||||
<span>阅卷中心</span>
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<router-link to="/teacher/student-management" class="nav-item" :class="{ active: activeNavItem === 1 }"
|
||||
@click="setActiveNavItem(1)">
|
||||
|
||||
@ -88,7 +50,7 @@
|
||||
<div class="breadcrumb">
|
||||
<span class="breadcrumb-separator"></span>
|
||||
<n-breadcrumb>
|
||||
<n-breadcrumb-item v-for="(item, index) in breadcrumbItems" :key="index" :href="item.path">
|
||||
<n-breadcrumb-item v-for="(item, index) in breadcrumbItems" :key="index" :to="item.path">
|
||||
{{ item.title }}
|
||||
</n-breadcrumb-item>
|
||||
</n-breadcrumb>
|
||||
@ -103,43 +65,17 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, watch } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ChevronDownOutline } from '@vicons/ionicons5'
|
||||
|
||||
const width = window.innerWidth;
|
||||
const height = window.innerHeight;
|
||||
console.log(`当前屏幕宽度: ${width}px, 高度: ${height}px`);
|
||||
|
||||
// 添加导航项激活状态管理
|
||||
const activeNavItem = ref(0); // 0: 课程管理, 1: 学员管理, 2: 我的资源, 3: 个人中心, 4: 考试管理
|
||||
const activeSubNavItem = ref(''); // 子菜单激活状态
|
||||
const examMenuExpanded = ref(false); // 考试管理菜单展开状态
|
||||
const activeNavItem = ref(0); // 0: 课程管理, 1: 学员管理, 2: 我的资源, 3: 个人中心
|
||||
const route = useRoute();
|
||||
|
||||
const setActiveNavItem = (index: number) => {
|
||||
activeNavItem.value = index;
|
||||
// 如果不是考试管理,关闭考试管理子菜单
|
||||
if (index !== 4) {
|
||||
examMenuExpanded.value = false;
|
||||
activeSubNavItem.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
// 考试管理菜单切换
|
||||
const toggleExamMenu = () => {
|
||||
examMenuExpanded.value = !examMenuExpanded.value;
|
||||
activeNavItem.value = 4;
|
||||
|
||||
// 如果展开且没有选中子菜单,默认选中第一个
|
||||
if (examMenuExpanded.value && !activeSubNavItem.value) {
|
||||
activeSubNavItem.value = 'question-management';
|
||||
}
|
||||
}
|
||||
|
||||
// 设置子菜单激活状态
|
||||
const setActiveSubNavItem = (subItem: string) => {
|
||||
activeSubNavItem.value = subItem;
|
||||
activeNavItem.value = 4;
|
||||
examMenuExpanded.value = true;
|
||||
}
|
||||
|
||||
// 动态生成面包屑
|
||||
@ -172,35 +108,12 @@ const updateActiveNavItem = () => {
|
||||
const path = route.path;
|
||||
if (path.includes('course-management')) {
|
||||
activeNavItem.value = 0; // 课程管理
|
||||
examMenuExpanded.value = false;
|
||||
activeSubNavItem.value = '';
|
||||
} else if (path.includes('student-management')) {
|
||||
activeNavItem.value = 1; // 学员管理
|
||||
examMenuExpanded.value = false;
|
||||
activeSubNavItem.value = '';
|
||||
} else if (path.includes('my-resources')) {
|
||||
activeNavItem.value = 2; // 我的资源
|
||||
examMenuExpanded.value = false;
|
||||
activeSubNavItem.value = '';
|
||||
} else if (path.includes('personal-center')) {
|
||||
activeNavItem.value = 3; // 个人中心
|
||||
examMenuExpanded.value = false;
|
||||
activeSubNavItem.value = '';
|
||||
} else if (path.includes('exam-management')) {
|
||||
activeNavItem.value = 4; // 考试管理
|
||||
examMenuExpanded.value = true;
|
||||
|
||||
// 根据具体路径设置子菜单激活状态
|
||||
if (path.includes('question-management')) {
|
||||
activeSubNavItem.value = 'question-management';
|
||||
} else if (path.includes('exam-library')) {
|
||||
activeSubNavItem.value = 'exam-library';
|
||||
} else if (path.includes('marking-center')) {
|
||||
activeSubNavItem.value = 'marking-center';
|
||||
} else {
|
||||
// 默认选中第一个子菜单
|
||||
activeSubNavItem.value = 'question-management';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,7 +172,7 @@ const updateActiveNavItem = () => {
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
width: 294px;
|
||||
width: 240px;
|
||||
height: calc(100vh - var(--top-height, 130px));
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
@ -274,7 +187,7 @@ const updateActiveNavItem = () => {
|
||||
@media screen and (max-width: 480px) {
|
||||
.sidebar-container {
|
||||
--top-height: 80px;
|
||||
width: 240px;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -289,35 +202,35 @@ const updateActiveNavItem = () => {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
left: 15px;
|
||||
right: 15px;
|
||||
height: 1px;
|
||||
background-color: #E6E6E6;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-container img {
|
||||
width: 95px;
|
||||
height: 95px;
|
||||
.avatar-container img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
/* 圆角 */
|
||||
border-radius: 50%;
|
||||
margin-top: 55px;
|
||||
margin-left: 100px;
|
||||
margin-right: 99;
|
||||
}
|
||||
margin-left: 80px;
|
||||
margin-right: 80px;
|
||||
}
|
||||
|
||||
.avatar-text {
|
||||
margin-left: 98px;
|
||||
.avatar-text {
|
||||
margin-left: 80px;
|
||||
height: 31px;
|
||||
font-family: AppleSystemUIFont;
|
||||
font-size: 22px;
|
||||
font-size: 20px;
|
||||
color: #000000;
|
||||
line-height: 26px;
|
||||
text-align: left;
|
||||
font-style: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
@media screen and (max-width: 768px) {
|
||||
.avatar-container {
|
||||
height: 180px;
|
||||
display: flex;
|
||||
@ -334,9 +247,9 @@ const updateActiveNavItem = () => {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
@media screen and (max-width: 480px) {
|
||||
.avatar-container {
|
||||
height: 150px;
|
||||
}
|
||||
@ -349,29 +262,29 @@ const updateActiveNavItem = () => {
|
||||
.avatar-text {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-container {
|
||||
.nav-container {
|
||||
margin-top: 30px;
|
||||
/* 鼠标变小手 */
|
||||
cursor: pointer;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.nav-container .nav-item {
|
||||
margin-left: 20px;
|
||||
width: 254px;
|
||||
height: 54px;
|
||||
margin-bottom: 20px;
|
||||
.nav-container .nav-item {
|
||||
margin-left: 15px;
|
||||
width: 210px;
|
||||
height: 50px;
|
||||
margin-bottom: 15px;
|
||||
/* 圆角 */
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.3s ease;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
@media screen and (max-width: 768px) {
|
||||
.nav-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@ -383,20 +296,9 @@ const updateActiveNavItem = () => {
|
||||
width: 200px;
|
||||
margin: 0 10px 15px;
|
||||
}
|
||||
|
||||
.submenu-container {
|
||||
margin-left: 10px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.submenu-item {
|
||||
margin-left: 20px;
|
||||
padding-left: 30px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
@media screen and (max-width: 480px) {
|
||||
.nav-container .nav-item {
|
||||
width: 150px;
|
||||
height: 45px;
|
||||
@ -406,49 +308,32 @@ const updateActiveNavItem = () => {
|
||||
.nav-container .nav-item img {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.submenu-container {
|
||||
margin-left: 5px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.submenu-item {
|
||||
margin-left: 10px;
|
||||
padding-left: 25px;
|
||||
font-size: 13px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.expand-icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-container .nav-item:hover {
|
||||
.nav-container .nav-item:hover {
|
||||
background: rgba(102, 183, 227, 0.05);
|
||||
}
|
||||
}
|
||||
|
||||
/* 添加激活状态样式 */
|
||||
.nav-container .nav-item.active {
|
||||
/* 添加激活状态样式 */
|
||||
.nav-container .nav-item.active {
|
||||
background: rgba(102, 183, 227, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.nav-container .nav-item.active span {
|
||||
.nav-container .nav-item.active span {
|
||||
color: #0C99DA;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-container .nav-item img {
|
||||
height: 20px;
|
||||
margin-left: 50px;
|
||||
.nav-container .nav-item img {
|
||||
height: 18px;
|
||||
margin-left: 40px;
|
||||
margin-top: 0;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-container .nav-item span {
|
||||
width: 80px;
|
||||
height: 28px;
|
||||
.nav-container .nav-item span {
|
||||
height: 26px;
|
||||
font-family: AppleSystemUIFont;
|
||||
font-size: 20px;
|
||||
font-size: 18px;
|
||||
color: #666666;
|
||||
line-height: 23px;
|
||||
text-align: left;
|
||||
@ -456,77 +341,12 @@ const updateActiveNavItem = () => {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/* 展开图标样式 */
|
||||
.expand-icon {
|
||||
margin-left: auto;
|
||||
margin-right: 20px;
|
||||
transition: transform 0.3s ease;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.expand-icon.expanded {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* 子菜单容器 */
|
||||
.submenu-container {
|
||||
overflow: hidden;
|
||||
max-height: 0;
|
||||
transition: max-height 0.3s ease-out;
|
||||
margin-left: 20px;
|
||||
width: 254px;
|
||||
}
|
||||
|
||||
.submenu-container.expanded {
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
/* 子菜单项样式 */
|
||||
.submenu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 40px;
|
||||
margin-bottom: 8px;
|
||||
margin-left: 30px;
|
||||
padding-left: 40px;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
color: #666;
|
||||
font-size: 16px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.submenu-item:hover {
|
||||
background: rgba(102, 183, 227, 0.05);
|
||||
}
|
||||
|
||||
.submenu-item.active {
|
||||
background: rgba(102, 183, 227, 0.1);
|
||||
color: #0C99DA;
|
||||
}
|
||||
|
||||
/* 子菜单项前的小圆点 */
|
||||
.submenu-item::before {
|
||||
content: '';
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background-color: #ccc;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.submenu-item.active::before {
|
||||
background-color: #0C99DA;
|
||||
}
|
||||
|
||||
.router-view-container {
|
||||
flex: 1;
|
||||
padding: 20px;
|
||||
padding: 10px 25px;
|
||||
background: #F5F7FA;
|
||||
height: calc(100vh - var(--top-height, 130px));
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
|
@ -440,6 +440,7 @@ const handleConfirm = () => {
|
||||
/* 字体居中 */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
/* 小手 */
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="course-editor">
|
||||
<!-- 左侧导航菜单 -->
|
||||
<div class="sidebar" v-if="showSidebar">
|
||||
<div class="sidebar">
|
||||
<router-link :to="`/teacher/course-editor/${courseId}/courseware`" class="menu-item"
|
||||
:class="{ active: $route.path.includes('courseware') }">
|
||||
<img :src="$route.path.includes('courseware') ? '/images/teacher/课件-选中.png' : '/images/teacher/课件.png'"
|
||||
@ -16,11 +16,11 @@
|
||||
</router-link>
|
||||
<!-- 作业二级导航 -->
|
||||
<div class="menu-group">
|
||||
<div class="menu-header" @click="toggleHomework('homework')">
|
||||
<div class="menu-header" @click="toggleHomework">
|
||||
<img :src="$route.path.includes('homework') ? '/images/teacher/作业-选中.png' : '/images/teacher/作业.png'"
|
||||
alt="作业" />
|
||||
<span>作业</span>
|
||||
<i class="n-base-icon" :class="{ 'expanded': subMenuArr.homework }">
|
||||
<i class="n-base-icon" :class="{ 'expanded': homeworkExpanded }">
|
||||
<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M5.64645 3.14645C5.45118 3.34171 5.45118 3.65829 5.64645 3.85355L9.79289 8L5.64645 12.1464C5.45118 12.3417 5.45118 12.6583 5.64645 12.8536C5.84171 13.0488 6.15829 13.0488 6.35355 12.8536L10.8536 8.35355C11.0488 8.15829 11.0488 7.84171 10.8536 7.64645L6.35355 3.14645C6.15829 2.95118 5.84171 2.95118 5.64645 3.14645Z"
|
||||
@ -28,7 +28,7 @@
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
<div class="submenu" v-show="subMenuArr.homework">
|
||||
<div class="submenu" v-show="homeworkExpanded">
|
||||
<router-link :to="`/teacher/course-editor/${courseId}/homework/library`" class="submenu-item"
|
||||
:class="{ active: $route.path.includes('homework/library') }">
|
||||
<span>作业库</span>
|
||||
@ -42,10 +42,9 @@
|
||||
<router-link :to="`/teacher/course-editor/${courseId}/practice`" class="menu-item"
|
||||
:class="{ active: $route.path.includes('practice') }">
|
||||
<img :src="$route.path.includes('practice') ? '/images/teacher/练考通-选中.png' : '/images/teacher/练考通.png'"
|
||||
alt="考试管理" />
|
||||
<span>考试管理</span>
|
||||
alt="练考通" />
|
||||
<span>练考通</span>
|
||||
</router-link>
|
||||
|
||||
<router-link :to="`/teacher/course-editor/${courseId}/question-bank`" class="menu-item"
|
||||
:class="{ active: $route.path.includes('question-bank') }">
|
||||
<img :src="$route.path.includes('question-bank') ? '/images/teacher/题库-选中.png' : '/images/teacher/题库.png'"
|
||||
@ -93,38 +92,20 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useRoute } from 'vue-router'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
// 获取课程ID
|
||||
const courseId = route.params.id
|
||||
|
||||
// 二级菜单展开状态
|
||||
const subMenuArr = ref({
|
||||
homework: false,
|
||||
practice: false
|
||||
})
|
||||
// 作业菜单展开状态
|
||||
const homeworkExpanded = ref(false)
|
||||
|
||||
// 切换作业菜单展开/收起
|
||||
const toggleHomework = (e: 'homework' | 'practice') => {
|
||||
subMenuArr.value[e] = !subMenuArr.value[e]
|
||||
const toggleHomework = () => {
|
||||
homeworkExpanded.value = !homeworkExpanded.value
|
||||
}
|
||||
|
||||
// 监听路由变化,如果当前路由是子菜单,自动展开父菜单
|
||||
watch(() => route.path, (newPath) => {
|
||||
if (newPath.includes('practice')) {
|
||||
subMenuArr.value.practice = true
|
||||
}else if (newPath.includes('homework')) {
|
||||
subMenuArr.value.homework = true
|
||||
}
|
||||
}, { immediate: true })
|
||||
|
||||
|
||||
// 判断是否显示侧边菜单栏
|
||||
const showSidebar = computed(() => {
|
||||
return route.meta.hideSidebar !== true
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -137,7 +118,7 @@ const showSidebar = computed(() => {
|
||||
|
||||
/* 左侧导航 */
|
||||
.sidebar {
|
||||
width: 273px;
|
||||
width: 220px;
|
||||
background: #fff;
|
||||
border-right: 1px solid #e8e8e8;
|
||||
padding: 20px 15px;
|
||||
@ -147,14 +128,14 @@ const showSidebar = computed(() => {
|
||||
.menu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
padding: 12px 15px;
|
||||
margin-bottom: 5px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border-left: 3px solid transparent;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
border-radius: 5px;
|
||||
}
|
||||
@ -173,15 +154,15 @@ const showSidebar = computed(() => {
|
||||
}
|
||||
|
||||
.menu-item img {
|
||||
margin-left: 40px;
|
||||
margin-left: 30px;
|
||||
margin-top: 1px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 14px;
|
||||
}
|
||||
|
||||
.menu-item span {
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
@ -193,11 +174,11 @@ const showSidebar = computed(() => {
|
||||
.menu-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
padding: 12px 15px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border-left: 3px solid transparent;
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
@ -208,15 +189,15 @@ const showSidebar = computed(() => {
|
||||
}
|
||||
|
||||
.menu-header img {
|
||||
margin-left: 40px;
|
||||
margin-left: 30px;
|
||||
margin-top: 1px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-right: 10px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 14px;
|
||||
}
|
||||
|
||||
.menu-header span {
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
flex: 1;
|
||||
}
|
||||
@ -239,24 +220,24 @@ const showSidebar = computed(() => {
|
||||
.submenu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 12px 20px;
|
||||
padding: 10px 15px;
|
||||
margin-bottom: 2px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
border-left: 3px solid transparent;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.submenu-item::before {
|
||||
content: '';
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin-left: 40px;
|
||||
margin-right: 10px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 30px;
|
||||
margin-right: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@ -274,12 +255,10 @@ const showSidebar = computed(() => {
|
||||
}
|
||||
|
||||
.submenu-item span {
|
||||
font-size: 16px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 右侧内容区域 */
|
||||
.content-area {
|
||||
flex: 1;
|
||||
|
@ -21,7 +21,7 @@
|
||||
<n-config-provider :locale="zhCN" :date-locale="dateZhCN">
|
||||
<n-data-table :columns="columns" :data="paginatedFiles" :row-key="rowKey" :checked-row-keys="selectedFiles"
|
||||
@update:checked-row-keys="handleCheck" :bordered="false" :single-line="false" size="medium"
|
||||
class="file-data-table" :row-class-name="rowClassName" />
|
||||
class="file-data-table" :row-class-name="rowClassName" style="width: 100%" />
|
||||
</n-config-provider>
|
||||
|
||||
<!-- 自定义分页器 -->
|
||||
@ -69,12 +69,8 @@
|
||||
</div>
|
||||
|
||||
<!-- 删除确认模态框 -->
|
||||
<DeleteFolderConfirmModal
|
||||
v-if="showDeleteConfirmModal"
|
||||
:show="showDeleteConfirmModal"
|
||||
@confirm="confirmDelete"
|
||||
@cancel="cancelDelete"
|
||||
/>
|
||||
<DeleteFolderConfirmModal v-if="showDeleteConfirmModal" :show="showDeleteConfirmModal" @confirm="confirmDelete"
|
||||
@cancel="cancelDelete" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -411,48 +407,48 @@ const handleResize = () => {
|
||||
}
|
||||
|
||||
// 响应式列配置计算属性
|
||||
const responsiveColumns = computed(() => {
|
||||
const width = screenWidth.value
|
||||
// const responsiveColumns = computed(() => {
|
||||
// const width = screenWidth.value
|
||||
|
||||
// 基础列宽配置
|
||||
const baseColumns = {
|
||||
selection: 40,
|
||||
index: 80,
|
||||
name: 270,
|
||||
size: 100,
|
||||
creator: 120,
|
||||
createTime: 180,
|
||||
actions: 320
|
||||
}
|
||||
// // 基础列宽配置 - 根据内容合理分配
|
||||
// const baseColumns = {
|
||||
// selection: 50,
|
||||
// index: 70,
|
||||
// name: 400, // 名称列需要更宽,因为文件名可能很长
|
||||
// size: 80, // 大小列缩小
|
||||
// creator: 100, // 创建人列缩小
|
||||
// createTime: 160, // 创建时间列稍微缩小
|
||||
// actions: 300 // 操作列稍微缩小
|
||||
// }
|
||||
|
||||
// 根据屏幕宽度调整列宽
|
||||
if (width < 1200) {
|
||||
// 小屏幕:减少各列宽度
|
||||
return {
|
||||
selection: 35,
|
||||
index: 60,
|
||||
name: Math.max(200, width * 0.25),
|
||||
size: 80,
|
||||
creator: 100,
|
||||
createTime: 140,
|
||||
actions: Math.max(280, width * 0.3)
|
||||
}
|
||||
} else if (width < 1600) {
|
||||
// 中等屏幕:保持基础宽度
|
||||
return baseColumns
|
||||
} else {
|
||||
// 大屏幕:适当增加宽度
|
||||
return {
|
||||
selection: 45,
|
||||
index: 90,
|
||||
name: 320,
|
||||
size: 110,
|
||||
creator: 130,
|
||||
createTime: 200,
|
||||
actions: 360
|
||||
}
|
||||
}
|
||||
})
|
||||
// // 根据屏幕宽度调整列宽
|
||||
// if (width < 1200) {
|
||||
// // 小屏幕:减少各列宽度,但保持比例
|
||||
// return {
|
||||
// selection: 40,
|
||||
// index: 60,
|
||||
// name: Math.max(250, width * 0.35), // 名称列保持较大比例
|
||||
// size: 70,
|
||||
// creator: 80,
|
||||
// createTime: 130,
|
||||
// actions: Math.max(250, width * 0.25)
|
||||
// }
|
||||
// } else if (width < 1600) {
|
||||
// // 中等屏幕:保持基础宽度
|
||||
// return baseColumns
|
||||
// } else {
|
||||
// // 大屏幕:适当增加宽度,但保持合理比例
|
||||
// return {
|
||||
// selection: 50,
|
||||
// index: 80,
|
||||
// name: 500, // 名称列在大屏幕上更宽
|
||||
// size: 90,
|
||||
// creator: 120,
|
||||
// createTime: 180,
|
||||
// actions: 350
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
// 在组件挂载时添加事件监听器
|
||||
onMounted(() => {
|
||||
@ -468,18 +464,18 @@ onUnmounted(() => {
|
||||
const columns = computed((): DataTableColumns<FileItem> => [
|
||||
{
|
||||
type: 'selection',
|
||||
width: responsiveColumns.value.selection
|
||||
width: 50 // 选择框固定宽度
|
||||
},
|
||||
{
|
||||
title: '序号',
|
||||
key: 'index',
|
||||
width: responsiveColumns.value.index,
|
||||
width: 70, // 序号固定宽度
|
||||
render: (_row: FileItem, index: number) => index + 1
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
key: 'name',
|
||||
width: responsiveColumns.value.name,
|
||||
// 不设置宽度,让这列自动占用剩余空间
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
},
|
||||
@ -524,22 +520,22 @@ const columns = computed((): DataTableColumns<FileItem> => [
|
||||
{
|
||||
title: '大小',
|
||||
key: 'size',
|
||||
width: responsiveColumns.value.size
|
||||
width: 80 // 大小列固定较小宽度
|
||||
},
|
||||
{
|
||||
title: '创建人',
|
||||
key: 'creator',
|
||||
width: responsiveColumns.value.creator
|
||||
width: 100 // 创建人列固定较小宽度
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
width: responsiveColumns.value.createTime
|
||||
width: 160 // 创建时间列固定宽度
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: responsiveColumns.value.actions,
|
||||
width: 300, // 操作列固定宽度
|
||||
render: (row: FileItem) => {
|
||||
const buttons = []
|
||||
|
||||
@ -891,6 +887,23 @@ const toggleFolder = (folder: FileItem) => {
|
||||
padding: 40px;
|
||||
}
|
||||
|
||||
/* 表格自适应布局 */
|
||||
:deep(.file-data-table .n-data-table-wrapper) {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
:deep(.file-data-table .n-data-table-base-table) {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
/* 名称列自动占用剩余空间 */
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="name"]),
|
||||
:deep(.file-data-table .n-data-table-th[data-col-key="name"]) {
|
||||
max-width: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* 表格头部样式 */
|
||||
:deep(.file-data-table .n-data-table-thead) {
|
||||
background: #fafafa;
|
||||
@ -914,9 +927,30 @@ const toggleFolder = (folder: FileItem) => {
|
||||
padding: 12px 8px;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
/* 名称列左对齐 */
|
||||
/* 序号列居中对齐 */
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="index"]) {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
/* 隐藏序号列的展开占位符,避免影响居中 */
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="index"] .n-data-table-expand-placeholder) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 确保序号列的展开触发器也居中 */
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="index"] .n-data-table-expand-trigger) {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
:deep(.file-data-table .n-data-table-th[data-col-key="index"]) {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
/* 名称列居中对齐 */
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="name"]) {
|
||||
text-align: center;
|
||||
}
|
||||
@ -925,6 +959,21 @@ const toggleFolder = (folder: FileItem) => {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 其他列居中对齐 */
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="size"]),
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="creator"]),
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="createTime"]),
|
||||
:deep(.file-data-table .n-data-table-td[data-col-key="actions"]) {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
:deep(.file-data-table .n-data-table-th[data-col-key="size"]),
|
||||
:deep(.file-data-table .n-data-table-th[data-col-key="creator"]),
|
||||
:deep(.file-data-table .n-data-table-th[data-col-key="createTime"]),
|
||||
:deep(.file-data-table .n-data-table-th[data-col-key="actions"]) {
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
:deep(.file-data-table .n-data-table-tr:hover) {
|
||||
background: #fafafa;
|
||||
}
|
||||
@ -1212,6 +1261,11 @@ const toggleFolder = (folder: FileItem) => {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* 确保表格横向滚动正常 */
|
||||
:deep(.file-data-table .n-data-table-wrapper) {
|
||||
overflow-x: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
/* 操作按钮在小屏幕下换行 */
|
||||
:deep(.file-data-table .n-data-table-td:last-child .n-button) {
|
||||
margin: 2px;
|
||||
|
1544
src/views/teacher/course/ExamPages/AddExam.vue
Normal file
1544
src/views/teacher/course/ExamPages/AddExam.vue
Normal file
File diff suppressed because it is too large
Load Diff
210
src/views/teacher/course/ExamPages/ExamLibrary.vue
Normal file
210
src/views/teacher/course/ExamPages/ExamLibrary.vue
Normal file
@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="exam-library-container">
|
||||
<div class="header-section">
|
||||
<h1 class="title">试卷库</h1>
|
||||
<n-space class="actions-group">
|
||||
<n-button type="primary" @click="handleAddExam">添加试卷</n-button>
|
||||
<n-button ghost>导入</n-button>
|
||||
<n-button ghost>导出</n-button>
|
||||
<n-button type="error" ghost>删除</n-button>
|
||||
<n-input placeholder="请输入想要搜索的内容" />
|
||||
<n-button type="primary">搜索</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
|
||||
<n-data-table :columns="columns" :data="examData" :row-key="(row: Exam) => row.id"
|
||||
@update:checked-row-keys="handleCheck" class="exam-table" :single-line="false" />
|
||||
|
||||
<div class="pagination-container">
|
||||
<n-pagination v-model:page="currentPage" :page-count="totalPages" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h, ref, VNode } from 'vue';
|
||||
import { NButton, NSpace, useMessage, NDataTable, NPagination, NInput } from 'naive-ui';
|
||||
import type { DataTableColumns } from 'naive-ui';
|
||||
import { useRouter } from 'vue-router';
|
||||
const router = useRouter();
|
||||
|
||||
// 定义考试条目的数据类型
|
||||
type Exam = {
|
||||
id: number;
|
||||
name: string;
|
||||
category: '练习' | '考试';
|
||||
questionCount: number;
|
||||
chapter: string;
|
||||
totalScore: number;
|
||||
difficulty: '易' | '中' | '难';
|
||||
status: '发布中' | '未发布' | '已结束';
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
creator: string;
|
||||
creationTime: string;
|
||||
};
|
||||
|
||||
// 主题颜色已在全局配置中统一设置
|
||||
|
||||
|
||||
const message = useMessage();
|
||||
|
||||
// 创建表格列的函数
|
||||
const createColumns = ({
|
||||
handleAction,
|
||||
}: {
|
||||
handleAction: (action: string, rowData: Exam) => void;
|
||||
}): DataTableColumns<Exam> => {
|
||||
return [
|
||||
{
|
||||
type: 'selection',
|
||||
},
|
||||
{
|
||||
title: '序号',
|
||||
key: 'id',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '试卷名称',
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
key: 'category',
|
||||
},
|
||||
{
|
||||
title: '题量',
|
||||
key: 'questionCount',
|
||||
},
|
||||
{
|
||||
title: '所属章节',
|
||||
key: 'chapter',
|
||||
},
|
||||
{
|
||||
title: '总分',
|
||||
key: 'totalScore',
|
||||
},
|
||||
{
|
||||
title: '难度',
|
||||
key: 'difficulty',
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
},
|
||||
{
|
||||
title: '起止时间',
|
||||
key: 'startTime',
|
||||
render(row) {
|
||||
return `${row.startTime} - ${row.endTime}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '创建人',
|
||||
key: 'creator',
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'creationTime',
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
render(row) {
|
||||
const buttons: VNode[] = [];
|
||||
if (row.status === '发布中') {
|
||||
buttons.push(
|
||||
h(NButton, { size: 'small', type: 'primary', ghost: true, style: 'margin: 0 3px;', onClick: () => handleAction('批阅', row) }, { default: () => '批阅' })
|
||||
);
|
||||
} else if (row.status === '未发布') {
|
||||
buttons.push(
|
||||
h(NButton, { size: 'small', type: 'primary', style: 'margin: 0 3px;', onClick: () => handleAction('发布', row) }, { default: () => '发布' })
|
||||
);
|
||||
}
|
||||
|
||||
buttons.push(
|
||||
h(NButton, { size: 'small', type: 'primary', ghost: true, style: 'margin: 0 3px;', onClick: () => handleAction('编辑', row) }, { default: () => '编辑' })
|
||||
);
|
||||
buttons.push(
|
||||
h(NButton, { size: 'small', type: 'error', ghost: true, style: 'margin: 0 3px;', onClick: () => handleAction('删除', row) }, { default: () => '删除' })
|
||||
);
|
||||
return h(NSpace, {}, { default: () => buttons });
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
// 模拟数据
|
||||
const examData = ref<Exam[]>([
|
||||
{ id: 1, name: '试卷名称试卷名称', category: '练习', questionCount: 100, chapter: '第一节 开课前准备', totalScore: 150, difficulty: '易', status: '发布中', startTime: '2025.07.25 09:20', endTime: '2025.07.25 09:20', creator: '王建国', creationTime: '2025.07.25 9:20' },
|
||||
{ id: 2, name: '试卷名称试卷名称', category: '考试', questionCount: 100, chapter: '第一节 开课前准备', totalScore: 150, difficulty: '易', status: '未发布', startTime: '2025.07.25 09:20', endTime: '2025.07.25 09:20', creator: '王建国', creationTime: '2025.07.25 9:20' },
|
||||
{ id: 3, name: '试卷名称试卷名称', category: '练习', questionCount: 100, chapter: '第一节 开课前准备', totalScore: 150, difficulty: '易', status: '发布中', startTime: '2025.07.25 09:20', endTime: '2025.07.25 09:20', creator: '王建国', creationTime: '2025.07.25 9:20' },
|
||||
{ id: 4, name: '试卷名称试卷名称', category: '考试', questionCount: 100, chapter: '第一节 开课前准备', totalScore: 150, difficulty: '易', status: '发布中', startTime: '2025.07.25 09:20', endTime: '2025.07.25 09:20', creator: '王建国', creationTime: '2025.07.25 9:20' },
|
||||
{ id: 5, name: '试卷名称试卷名称', category: '练习', questionCount: 100, chapter: '第一节 开课前准备', totalScore: 150, difficulty: '易', status: '发布中', startTime: '2025.07.25 09:20', endTime: '2025.07.25 09:20', creator: '王建国', creationTime: '2025.07.25 9:20' },
|
||||
{ id: 6, name: '试卷名称试卷名称', category: '考试', questionCount: 100, chapter: '第一节 开课前准备', totalScore: 150, difficulty: '易', status: '未发布', startTime: '2025.07.25 09:20', endTime: '2025.07.25 09:20', creator: '王建国', creationTime: '2025.07.25 9:20' },
|
||||
{ id: 7, name: '试卷名称试卷名称', category: '练习', questionCount: 100, chapter: '第一节 开课前准备', totalScore: 150, difficulty: '易', status: '发布中', startTime: '2025.07.25 09:20', endTime: '2025.07.25 09:20', creator: '王建国', creationTime: '2025.07.25 9:20' },
|
||||
{ id: 8, name: '试卷名称试卷名称', category: '考试', questionCount: 100, chapter: '第一节 开课前准备', totalScore: 150, difficulty: '易', status: '未发布', startTime: '2025.07.25 09:20', endTime: '2025.07.25 09:20', creator: '王建国', creationTime: '2025.07.25 9:20' },
|
||||
]);
|
||||
|
||||
const columns = createColumns({
|
||||
handleAction: (action, row) => {
|
||||
message.info(`执行操作: ${action} on row ${row.id}`);
|
||||
},
|
||||
});
|
||||
|
||||
const checkedRowKeys = ref<Array<string | number>>([]);
|
||||
const handleCheck = (rowKeys: Array<string | number>) => {
|
||||
checkedRowKeys.value = rowKeys;
|
||||
};
|
||||
|
||||
// 分页状态
|
||||
const currentPage = ref(1);
|
||||
const totalPages = ref(29); // 来自图片
|
||||
|
||||
const handleAddExam = () => {
|
||||
// 这里可以添加导航到添加试卷页面的逻辑
|
||||
router.push({ name: 'AddExam' });
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.exam-library-container {
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.header-section {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #E6E6E6;
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.actions-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.exam-table {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.pagination-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
11
src/views/teacher/course/ExamPages/MarkingCenter.vue
Normal file
11
src/views/teacher/course/ExamPages/MarkingCenter.vue
Normal file
@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>阅卷中心</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
@ -19,7 +19,7 @@
|
||||
<n-config-provider :locale="zhCN" :date-locale="dateZhCN">
|
||||
<n-data-table :columns="columns" :data="sortedHomeworkList" :row-key="rowKey"
|
||||
:checked-row-keys="selectedHomework" @update:checked-row-keys="handleCheck" :bordered="false"
|
||||
:single-line="false" size="medium" class="homework-data-table" />
|
||||
:single-line="false" size="medium" class="homework-data-table" scroll-x="true" />
|
||||
</n-config-provider>
|
||||
</div>
|
||||
|
||||
@ -94,51 +94,51 @@ const handleResize = () => {
|
||||
}
|
||||
|
||||
// 响应式列配置计算属性
|
||||
const responsiveColumns = computed(() => {
|
||||
const width = screenWidth.value
|
||||
// const responsiveColumns = computed(() => {
|
||||
// const width = screenWidth.value
|
||||
|
||||
// 基础列宽配置
|
||||
const baseColumns = {
|
||||
selection: 50,
|
||||
index: 80,
|
||||
name: 200,
|
||||
chapter: 180,
|
||||
class: 150,
|
||||
creator: 120,
|
||||
createTime: 180,
|
||||
actions: 200
|
||||
}
|
||||
// // 基础列宽配置
|
||||
// const baseColumns = {
|
||||
// selection: 50,
|
||||
// index: 80,
|
||||
// name: 200,
|
||||
// chapter: 180,
|
||||
// class: 150,
|
||||
// creator: 120,
|
||||
// createTime: 180,
|
||||
// actions: 200
|
||||
// }
|
||||
|
||||
// 根据屏幕宽度调整列宽
|
||||
if (width < 1200) {
|
||||
// 小屏幕:减少各列宽度
|
||||
return {
|
||||
selection: 40,
|
||||
index: 60,
|
||||
name: Math.max(150, width * 0.2),
|
||||
chapter: Math.max(120, width * 0.15),
|
||||
class: Math.max(100, width * 0.12),
|
||||
creator: 80,
|
||||
createTime: 140,
|
||||
actions: Math.max(160, width * 0.2)
|
||||
}
|
||||
} else if (width < 1600) {
|
||||
// 中等屏幕:保持基础宽度
|
||||
return baseColumns
|
||||
} else {
|
||||
// 大屏幕:适当增加宽度
|
||||
return {
|
||||
selection: 55,
|
||||
index: 90,
|
||||
name: 250,
|
||||
chapter: 220,
|
||||
class: 180,
|
||||
creator: 140,
|
||||
createTime: 200,
|
||||
actions: 240
|
||||
}
|
||||
}
|
||||
})
|
||||
// // 根据屏幕宽度调整列宽
|
||||
// if (width < 1200) {
|
||||
// // 小屏幕:减少各列宽度
|
||||
// return {
|
||||
// selection: 40,
|
||||
// index: 60,
|
||||
// name: Math.max(150, width * 0.2),
|
||||
// chapter: Math.max(120, width * 0.15),
|
||||
// class: Math.max(100, width * 0.12),
|
||||
// creator: 80,
|
||||
// createTime: 140,
|
||||
// actions: Math.max(160, width * 0.2)
|
||||
// }
|
||||
// } else if (width < 1600) {
|
||||
// // 中等屏幕:保持基础宽度
|
||||
// return baseColumns
|
||||
// } else {
|
||||
// // 大屏幕:适当增加宽度
|
||||
// return {
|
||||
// selection: 55,
|
||||
// index: 90,
|
||||
// name: 250,
|
||||
// chapter: 220,
|
||||
// class: 180,
|
||||
// creator: 140,
|
||||
// createTime: 200,
|
||||
// actions: 240
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
// 在组件挂载时添加事件监听器
|
||||
onMounted(() => {
|
||||
@ -272,22 +272,24 @@ const handleCheck = (keys: number[]) => {
|
||||
selectedHomework.value = keys
|
||||
}
|
||||
|
||||
// 表格列定义
|
||||
// 表格列定义 - 使用 minWidth 实现响应式
|
||||
const columns = computed((): DataTableColumns<HomeworkItem> => [
|
||||
{
|
||||
type: 'selection',
|
||||
width: responsiveColumns.value.selection
|
||||
minWidth: 50
|
||||
},
|
||||
{
|
||||
title: '序号',
|
||||
key: 'index',
|
||||
width: responsiveColumns.value.index,
|
||||
minWidth: 60,
|
||||
width: 60,
|
||||
render: (_, index) => index + 1
|
||||
},
|
||||
{
|
||||
title: '作业名称',
|
||||
key: 'name',
|
||||
width: responsiveColumns.value.name,
|
||||
minWidth: 300,
|
||||
width: 300,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
},
|
||||
@ -301,7 +303,8 @@ const columns = computed((): DataTableColumns<HomeworkItem> => [
|
||||
{
|
||||
title: '所属章节',
|
||||
key: 'chapter',
|
||||
width: responsiveColumns.value.chapter,
|
||||
minWidth: 200,
|
||||
width: 200,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
}
|
||||
@ -309,7 +312,8 @@ const columns = computed((): DataTableColumns<HomeworkItem> => [
|
||||
{
|
||||
title: '绑定班级',
|
||||
key: 'class',
|
||||
width: responsiveColumns.value.class,
|
||||
minWidth: 150,
|
||||
width: 150,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
}
|
||||
@ -317,29 +321,34 @@ const columns = computed((): DataTableColumns<HomeworkItem> => [
|
||||
{
|
||||
title: '创建人',
|
||||
key: 'creator',
|
||||
width: responsiveColumns.value.creator
|
||||
minWidth: 100,
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
width: responsiveColumns.value.createTime
|
||||
minWidth: 140,
|
||||
width: 140
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: responsiveColumns.value.actions,
|
||||
minWidth: 200,
|
||||
width: 200,
|
||||
render: (row) => {
|
||||
return h('div', { style: 'display: flex; gap: 8px; align-items: center;' }, [
|
||||
return h('div', { style: 'display: flex; gap: 6px; align-items: center; justify-content: center; flex-wrap: wrap;' }, [
|
||||
h(NButton, {
|
||||
size: 'small',
|
||||
type: 'info',
|
||||
secondary: true,
|
||||
style: 'min-width: 50px;',
|
||||
onClick: () => editHomework(row.id)
|
||||
}, { default: () => '编辑' }),
|
||||
h(NButton, {
|
||||
size: 'small',
|
||||
type: 'error',
|
||||
secondary: true,
|
||||
style: 'min-width: 50px;',
|
||||
onClick: () => deleteHomework(row.id)
|
||||
}, { default: () => '删除' }),
|
||||
h(NDropdown, {
|
||||
@ -371,7 +380,8 @@ const columns = computed((): DataTableColumns<HomeworkItem> => [
|
||||
default: () => h(NButton, {
|
||||
size: 'small',
|
||||
type: 'info',
|
||||
secondary: true
|
||||
secondary: true,
|
||||
style: 'min-width: 50px;'
|
||||
}, { default: () => '更多' })
|
||||
})
|
||||
])
|
||||
|
@ -1,40 +1,12 @@
|
||||
<template>
|
||||
<div class="practice-management">
|
||||
<div class="content-placeholder">
|
||||
<h2>考试管理</h2>
|
||||
<p>考试管理功能正在修改中...</p>
|
||||
<h2>练考通管理</h2>
|
||||
<p>练考通管理功能正在开发中...</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.practice-management {
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content-placeholder {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
}
|
||||
|
||||
.content-placeholder h2 {
|
||||
font-size: 24px;
|
||||
color: #333;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.content-placeholder p {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<script setup lang="ts">
|
||||
// 练考通管理逻辑
|
||||
</script>
|
||||
|
@ -1,36 +1,850 @@
|
||||
<template>
|
||||
<div class="question-bank-management">
|
||||
<div class="content-placeholder">
|
||||
<h2>题库管理</h2>
|
||||
<p>题库管理功能正在开发中...</p>
|
||||
<!-- 顶部操作栏 -->
|
||||
<div class="toolbar">
|
||||
<h2>全部试题</h2>
|
||||
<div class="toolbar-actions">
|
||||
<button class="btn btn-primary" @click="addQuestion">添加试题</button>
|
||||
<button class="btn btn-new" @click="importQuestions">导入</button>
|
||||
<div class="dropdown-container">
|
||||
<button class="btn btn-new" @click="toggleMoreDropdown">更多</button>
|
||||
<div v-if="showMoreDropdown" class="more-dropdown">
|
||||
<div class="dropdown-item" @click="categorySettings">分类设置</div>
|
||||
<div class="dropdown-item" @click="exportQuestions">导出试题</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-danger" @click="deleteSelected">删除</button>
|
||||
<select v-model="selectedCategory" class="category-select" @change="filterByCategory">
|
||||
<option value="">分类</option>
|
||||
<option value="试题分类">试题分类</option>
|
||||
<option value="分类设置">分类设置</option>
|
||||
</select>
|
||||
<div class="search-box">
|
||||
<input type="text" placeholder="请输入关键词" v-model="searchKeyword" @keyup.enter="searchQuestions" />
|
||||
<button class="btn btn-search" @click="searchQuestions">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 题目列表表格 -->
|
||||
<div class="table-box">
|
||||
<n-config-provider :locale="zhCN" :date-locale="dateZhCN">
|
||||
<n-data-table :columns="columns" :data="filteredQuestions" :row-key="rowKey"
|
||||
:checked-row-keys="selectedQuestions" @update:checked-row-keys="handleCheck" :bordered="false"
|
||||
:single-line="false" size="medium" class="question-data-table" :row-class-name="rowClassName" />
|
||||
</n-config-provider>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
// 题库管理逻辑
|
||||
import { ref, computed, h, onMounted, onUnmounted } from 'vue'
|
||||
import {
|
||||
NButton,
|
||||
NDataTable,
|
||||
NConfigProvider,
|
||||
NTag,
|
||||
useMessage,
|
||||
zhCN,
|
||||
dateZhCN
|
||||
} from 'naive-ui'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
|
||||
const message = useMessage()
|
||||
|
||||
// 题目类型定义
|
||||
interface Question {
|
||||
id: number
|
||||
content: string
|
||||
type: '单选题' | '填空题' | '多选题' | '判断题' | '简答题'
|
||||
category: string
|
||||
difficulty: '易' | '中' | '难'
|
||||
score: number
|
||||
creator: string
|
||||
createTime: string
|
||||
}
|
||||
|
||||
// 响应式数据
|
||||
const screenWidth = ref(window.innerWidth)
|
||||
const searchKeyword = ref('')
|
||||
const selectedCategory = ref('')
|
||||
const selectedQuestions = ref<number[]>([])
|
||||
const showMoreDropdown = ref(false)
|
||||
|
||||
// 模拟题目数据
|
||||
const questionList = ref<Question[]>([
|
||||
{
|
||||
id: 1,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '单选题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '填空题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '单选题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '填空题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '单选题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '填空题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '单选题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '填空题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '单选题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '填空题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '单选题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '填空题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '单选题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '填空题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
content: '在数据库的三级模式结构中,内模式有...',
|
||||
type: '单选题',
|
||||
category: '试题分类',
|
||||
difficulty: '易',
|
||||
score: 10,
|
||||
creator: '王建国',
|
||||
createTime: '2025.08.20 09:20'
|
||||
}
|
||||
])
|
||||
|
||||
// 响应式列宽配置
|
||||
const responsiveColumns = computed(() => {
|
||||
if (screenWidth.value < 1200) {
|
||||
return {
|
||||
selection: 40,
|
||||
index: 60,
|
||||
content: 200,
|
||||
type: 80,
|
||||
category: 100,
|
||||
difficulty: 60,
|
||||
score: 60,
|
||||
creator: 80,
|
||||
createTime: 120,
|
||||
actions: 120
|
||||
}
|
||||
} else if (screenWidth.value < 1600) {
|
||||
return {
|
||||
selection: 50,
|
||||
index: 80,
|
||||
content: 280,
|
||||
type: 100,
|
||||
category: 120,
|
||||
difficulty: 80,
|
||||
score: 80,
|
||||
creator: 100,
|
||||
createTime: 150,
|
||||
actions: 160
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
selection: 50,
|
||||
index: 80,
|
||||
content: 350,
|
||||
type: 120,
|
||||
category: 140,
|
||||
difficulty: 100,
|
||||
score: 100,
|
||||
creator: 120,
|
||||
createTime: 180,
|
||||
actions: 200
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 窗口大小监听
|
||||
const handleResize = () => {
|
||||
screenWidth.value = window.innerWidth
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize)
|
||||
})
|
||||
|
||||
// 表格列配置
|
||||
const columns = computed((): DataTableColumns<Question> => [
|
||||
{
|
||||
type: 'selection',
|
||||
width: responsiveColumns.value.selection
|
||||
},
|
||||
{
|
||||
title: '序号',
|
||||
key: 'index',
|
||||
width: responsiveColumns.value.index,
|
||||
render: (_row: Question, index: number) => index + 1
|
||||
},
|
||||
{
|
||||
title: '试题内容',
|
||||
key: 'content',
|
||||
width: responsiveColumns.value.content,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '题型',
|
||||
key: 'type',
|
||||
width: responsiveColumns.value.type,
|
||||
render: (row: Question) => {
|
||||
return h(NTag, {
|
||||
type: 'info',
|
||||
style: {
|
||||
backgroundColor: 'transparent !important',
|
||||
color: '#062333 !important',
|
||||
fontSize: '12px !important',
|
||||
border: 'none !important',
|
||||
'--n-border': 'none !important',
|
||||
'--n-color': 'transparent !important'
|
||||
}
|
||||
}, () => row.type)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '分类',
|
||||
key: 'category',
|
||||
width: responsiveColumns.value.category,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '难度',
|
||||
key: 'difficulty',
|
||||
width: responsiveColumns.value.difficulty,
|
||||
render: (row: Question) => {
|
||||
return h(NTag, {
|
||||
type: 'info',
|
||||
style: {
|
||||
backgroundColor: 'transparent !important',
|
||||
color: '#062333 !important',
|
||||
fontSize: '12px !important',
|
||||
border: 'none !important',
|
||||
'--n-border': 'none !important',
|
||||
'--n-color': 'transparent !important'
|
||||
}
|
||||
}, () => row.difficulty)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '分值',
|
||||
key: 'score',
|
||||
width: responsiveColumns.value.score
|
||||
},
|
||||
{
|
||||
title: '创建人',
|
||||
key: 'creator',
|
||||
width: responsiveColumns.value.creator,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
width: responsiveColumns.value.createTime,
|
||||
ellipsis: {
|
||||
tooltip: true
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'actions',
|
||||
width: responsiveColumns.value.actions,
|
||||
render: (row: Question) => {
|
||||
return h('div', { style: { display: 'flex', gap: '8px' } }, [
|
||||
h(NButton, {
|
||||
size: 'small',
|
||||
type: 'info',
|
||||
ghost: true,
|
||||
onClick: () => editQuestion(row)
|
||||
}, () => '编辑'),
|
||||
h(NButton, {
|
||||
size: 'small',
|
||||
type: 'error',
|
||||
ghost: true,
|
||||
onClick: () => deleteQuestion(row)
|
||||
}, () => '删除')
|
||||
])
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
// 过滤后的题目列表
|
||||
const filteredQuestions = computed(() => {
|
||||
let filtered = questionList.value
|
||||
|
||||
// 按分类过滤
|
||||
if (selectedCategory.value) {
|
||||
filtered = filtered.filter(q => q.category === selectedCategory.value)
|
||||
}
|
||||
|
||||
// 按关键词搜索
|
||||
if (searchKeyword.value) {
|
||||
filtered = filtered.filter(q =>
|
||||
q.content.includes(searchKeyword.value) ||
|
||||
q.creator.includes(searchKeyword.value)
|
||||
)
|
||||
}
|
||||
|
||||
return filtered
|
||||
})
|
||||
|
||||
// 不再需要分页数据
|
||||
|
||||
// 不再需要分页相关的computed属性
|
||||
|
||||
// 行键
|
||||
const rowKey = (row: Question) => row.id
|
||||
|
||||
// 行样式
|
||||
const rowClassName = (row: Question) => {
|
||||
return selectedQuestions.value.includes(row.id) ? 'selected-row' : ''
|
||||
}
|
||||
|
||||
// 事件处理
|
||||
const handleCheck = (keys: number[]) => {
|
||||
selectedQuestions.value = keys
|
||||
}
|
||||
|
||||
// 不再需要分页方法
|
||||
|
||||
const filterByCategory = () => {
|
||||
// 分类筛选
|
||||
}
|
||||
|
||||
const searchQuestions = () => {
|
||||
message.info('搜索: ' + searchKeyword.value)
|
||||
}
|
||||
|
||||
const addQuestion = () => {
|
||||
message.info('添加试题功能')
|
||||
}
|
||||
|
||||
const importQuestions = () => {
|
||||
message.info('导入试题功能')
|
||||
}
|
||||
|
||||
const toggleMoreDropdown = () => {
|
||||
showMoreDropdown.value = !showMoreDropdown.value
|
||||
}
|
||||
|
||||
const categorySettings = () => {
|
||||
showMoreDropdown.value = false
|
||||
message.info('分类设置功能')
|
||||
}
|
||||
|
||||
const exportQuestions = () => {
|
||||
showMoreDropdown.value = false
|
||||
message.info('导出试题功能')
|
||||
}
|
||||
|
||||
const deleteSelected = () => {
|
||||
if (selectedQuestions.value.length === 0) return
|
||||
if (confirm(`确定要删除选中的 ${selectedQuestions.value.length} 道试题吗?`)) {
|
||||
selectedQuestions.value.forEach((id: number) => {
|
||||
const index = questionList.value.findIndex((q: Question) => q.id === id)
|
||||
if (index > -1) {
|
||||
questionList.value.splice(index, 1)
|
||||
}
|
||||
})
|
||||
selectedQuestions.value = []
|
||||
message.success('删除成功')
|
||||
}
|
||||
}
|
||||
|
||||
const editQuestion = (question: Question) => {
|
||||
message.info('编辑试题: ' + question.content.substring(0, 20) + '...')
|
||||
}
|
||||
|
||||
const deleteQuestion = (question: Question) => {
|
||||
if (confirm('确定要删除这道试题吗?')) {
|
||||
const index = questionList.value.findIndex(q => q.id === question.id)
|
||||
if (index > -1) {
|
||||
questionList.value.splice(index, 1)
|
||||
message.success('删除成功')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.question-bank-management {
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content-placeholder {
|
||||
text-align: center;
|
||||
padding: 60px 20px;
|
||||
/* 顶部工具栏 */
|
||||
.toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding: 15px 0 30px 20px;
|
||||
background: #fff;
|
||||
border-bottom: 2px solid #F5F7FA;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.content-placeholder h2 {
|
||||
font-size: 24px;
|
||||
.toolbar h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.category-select {
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #F1F3F4;
|
||||
border-radius: 4px;
|
||||
background: white;
|
||||
font-size: 14px;
|
||||
min-width: 160px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.category-select:focus {
|
||||
border-color: #0088D1;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* 更多下拉菜单样式 */
|
||||
.dropdown-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.more-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
background: white;
|
||||
min-width: 60px;
|
||||
z-index: 1000;
|
||||
margin-top: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
padding: 8px 8px;
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
color: #333;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.dropdown-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 表格容器 */
|
||||
.table-box {
|
||||
background: #fff;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.question-data-table {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.content-placeholder p {
|
||||
font-size: 16px;
|
||||
/* 按钮样式 */
|
||||
.btn {
|
||||
padding: 6px 16px;
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
transition: all 0.3s ease;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: #0088D1;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover:not(:disabled) {
|
||||
background: #0077BB;
|
||||
}
|
||||
|
||||
.btn-new {
|
||||
background: #fff;
|
||||
color: #0288D1;
|
||||
border: 1px solid #0288D1;
|
||||
}
|
||||
|
||||
.btn-new:hover:not(:disabled) {
|
||||
border-color: #0088D1;
|
||||
color: #0088D1;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
background: #fff;
|
||||
color: #666;
|
||||
border: 1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
.btn-default:hover:not(:disabled) {
|
||||
border-color: #0088D1;
|
||||
color: #0088D1;
|
||||
}
|
||||
|
||||
.btn-default:disabled {
|
||||
background: #f5f5f5;
|
||||
color: #bfbfbf;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background: white;
|
||||
color: #FF4D4F;
|
||||
border: 1px solid #FF4D4F;
|
||||
}
|
||||
|
||||
.btn-danger:hover:not(:disabled) {
|
||||
background: #ff7875;
|
||||
}
|
||||
|
||||
.btn-danger:disabled {
|
||||
background: #f5f5f5;
|
||||
color: #bfbfbf;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-search {
|
||||
background: #0088D1;
|
||||
color: white;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.btn-search:hover {
|
||||
background: #0077BB;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 搜索框 */
|
||||
.search-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-right: none;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
font-size: 14px;
|
||||
outline: none;
|
||||
min-width: 200px;
|
||||
}
|
||||
|
||||
.search-box input:focus {
|
||||
border-color: #0088D1;
|
||||
}
|
||||
|
||||
/* 不再需要分页器样式 */
|
||||
|
||||
|
||||
|
||||
/* 响应式布局 */
|
||||
@media (max-width: 1200px) {
|
||||
.toolbar {
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.toolbar-actions {
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
/* 表格在小屏幕下的优化 */
|
||||
:deep(.question-data-table) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* 操作按钮在小屏幕下换行 */
|
||||
:deep(.question-data-table .n-data-table-td:last-child .n-button) {
|
||||
margin: 2px;
|
||||
font-size: 11px;
|
||||
padding: 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.question-bank-management {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.toolbar h2 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
width: 120px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.table-box {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
/* 表格在移动端的优化 */
|
||||
:deep(.question-data-table) {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* 隐藏某些列在移动端 */
|
||||
:deep(.question-data-table .n-data-table-th[data-col-key="creator"]),
|
||||
:deep(.question-data-table .n-data-table-td[data-col-key="creator"]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 操作按钮在移动端垂直排列 */
|
||||
:deep(.question-data-table .n-data-table-td:last-child > div) {
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
:deep(.question-data-table .n-data-table-td:last-child .n-button) {
|
||||
width: 100%;
|
||||
margin: 1px 0;
|
||||
}
|
||||
|
||||
/* 不再需要分页器移动端样式 */
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.toolbar-actions {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-box {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search-box input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.category-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 进一步隐藏列 */
|
||||
:deep(.question-data-table .n-data-table-th[data-col-key="createTime"]),
|
||||
:deep(.question-data-table .n-data-table-td[data-col-key="createTime"]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 表格内容在超小屏幕下的优化 */
|
||||
:deep(.question-data-table .n-data-table-td) {
|
||||
padding: 8px 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
:deep(.question-data-table .n-data-table-th) {
|
||||
padding: 8px 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 表格行样式 */
|
||||
:deep(.selected-row) {
|
||||
background-color: #f0f8ff;
|
||||
}
|
||||
|
||||
/* 表格横向滚动优化 */
|
||||
:deep(.question-data-table .n-data-table-wrapper) {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
:deep(.question-data-table .n-data-table-base-table) {
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
/* 确保表格内容不会溢出 */
|
||||
:deep(.question-data-table .n-data-table-td) {
|
||||
word-break: break-word;
|
||||
white-space: normal;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #062333;
|
||||
}
|
||||
|
||||
/* 表头居中对齐 */
|
||||
:deep(.question-data-table .n-data-table-th) {
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #062333;
|
||||
}
|
||||
|
||||
/* 内容列文本溢出处理 */
|
||||
:deep(.question-data-table .n-data-table-td[data-col-key="content"] span) {
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* 操作列按钮居中 */
|
||||
:deep(.question-data-table .n-data-table-td[data-col-key="actions"] > div) {
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
|
384
src/views/teacher/course/ResourceSelectionModal.vue
Normal file
384
src/views/teacher/course/ResourceSelectionModal.vue
Normal file
@ -0,0 +1,384 @@
|
||||
<template>
|
||||
<n-modal :show="show" @update:show="handleUpdateShow" preset="card" title="我的资源" style="width: 900px; max-width: 90vw;" :closable="false">
|
||||
<div class="resource-modal-content">
|
||||
<!-- 筛选和搜索栏 -->
|
||||
<div class="filter-search-bar">
|
||||
<div class="filter-section">
|
||||
<span class="filter-label">类型:</span>
|
||||
<n-select v-model:value="selectedFileType" :options="fileTypeOptions" placeholder="全部" style="width: 120px;" />
|
||||
</div>
|
||||
<div class="search-section">
|
||||
<span class="search-label">搜索:</span>
|
||||
<n-input v-model:value="searchKeyword" placeholder="请输入文档名称" style="width: 200px;">
|
||||
<template #suffix>
|
||||
<img src="/public/images/teacher/搜索.png" alt="搜索" class="search-icon" @click="searchFiles" />
|
||||
</template>
|
||||
</n-input>
|
||||
</div>
|
||||
<div class="file-info">
|
||||
<span class="file-count">已全部加载,共{{ filteredFiles.length }}个文件</span>
|
||||
<n-button type="primary" size="small" @click="uploadNewFile" class="upload-new-file-btn">
|
||||
<img src="/public/images/teacher/上传2.png" alt="上传" class="upload-icon" />
|
||||
上传新文件
|
||||
</n-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 文件网格 -->
|
||||
<div class="file-grid">
|
||||
<div v-for="file in filteredFiles" :key="file.id" class="file-item" @click="selectFile(file, $event)">
|
||||
<div class="file-thumbnail">
|
||||
<img :src="file.thumbnail" :alt="file.name" />
|
||||
</div>
|
||||
<div class="file-name">{{ file.name }}</div>
|
||||
<div class="file-options">
|
||||
<n-dropdown :options="fileMenuOptions" @select="(key: string) => handleFileMenuSelect(key, file)">
|
||||
<n-button quaternary size="small" class="file-menu-btn">
|
||||
<template #icon>
|
||||
<n-icon size="16">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
|
||||
</svg>
|
||||
</n-icon>
|
||||
</template>
|
||||
</n-button>
|
||||
</n-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<div class="modal-footer">
|
||||
<n-button @click="handleCancel">取消</n-button>
|
||||
<n-button type="primary" @click="handleConfirm" :disabled="!selectedFile">确定</n-button>
|
||||
</div>
|
||||
</template>
|
||||
</n-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
|
||||
// Props
|
||||
interface Props {
|
||||
show: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
'update:show': [value: boolean]
|
||||
'select': [file: any]
|
||||
}>()
|
||||
|
||||
// 处理模态框显示状态更新
|
||||
const handleUpdateShow = (value: boolean) => {
|
||||
emit('update:show', value)
|
||||
}
|
||||
|
||||
// 文件类型筛选
|
||||
const selectedFileType = ref('all')
|
||||
const fileTypeOptions = [
|
||||
{ label: '全部', value: 'all' },
|
||||
{ label: '文档', value: 'document' },
|
||||
{ label: '视频', value: 'video' },
|
||||
{ label: '音频', value: 'audio' },
|
||||
{ label: '其他', value: 'other' }
|
||||
]
|
||||
|
||||
// 搜索关键词
|
||||
const searchKeyword = ref('')
|
||||
|
||||
// 文件数据
|
||||
const files = ref([
|
||||
{ id: 1, name: '开课彩蛋:新开始.pptx', type: 'document', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 2, name: '课程定位与目标.pdf', type: 'document', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 3, name: '教学安排及学习建议.docx', type: 'document', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 4, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 5, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 6, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 7, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 8, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 9, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 10, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 11, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 12, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 13, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 14, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 15, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 16, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 17, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
{ id: 18, name: '风景.mp4', type: 'video', thumbnail: '/images/teacher/fj.png' },
|
||||
])
|
||||
|
||||
// 计算属性:根据筛选条件过滤文件
|
||||
const filteredFiles = computed(() => {
|
||||
let result = files.value
|
||||
|
||||
// 按文件类型筛选
|
||||
if (selectedFileType.value !== 'all') {
|
||||
result = result.filter(file => file.type === selectedFileType.value)
|
||||
}
|
||||
|
||||
// 按搜索关键词筛选
|
||||
if (searchKeyword.value.trim()) {
|
||||
const keyword = searchKeyword.value.toLowerCase()
|
||||
result = result.filter(file => file.name.toLowerCase().includes(keyword))
|
||||
}
|
||||
|
||||
return result
|
||||
})
|
||||
|
||||
// 当前选中的文件
|
||||
const selectedFile = ref<any>(null)
|
||||
|
||||
// 文件菜单选项
|
||||
const fileMenuOptions = [
|
||||
{ label: '重命名', key: 'rename' },
|
||||
{ label: '删除', key: 'delete' }
|
||||
]
|
||||
|
||||
// 搜索文件
|
||||
const searchFiles = () => {
|
||||
console.log('搜索文件')
|
||||
}
|
||||
|
||||
// 上传新文件
|
||||
const uploadNewFile = () => {
|
||||
console.log('上传新文件')
|
||||
const newFile = {
|
||||
id: files.value.length + 1,
|
||||
name: '新文件.pdf',
|
||||
type: 'document',
|
||||
thumbnail: '/images/teacher/document.png'
|
||||
}
|
||||
files.value.push(newFile)
|
||||
}
|
||||
|
||||
// 选择文件
|
||||
const selectFile = (file: any, event?: Event) => {
|
||||
selectedFile.value = file
|
||||
if (event && event.target) {
|
||||
const target = event.target as HTMLElement
|
||||
const fileItem = target.closest('.file-item')
|
||||
if (fileItem) {
|
||||
document.querySelectorAll('.file-item').forEach(item => {
|
||||
item.classList.remove('selected')
|
||||
})
|
||||
fileItem.classList.add('selected')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理文件菜单选择
|
||||
const handleFileMenuSelect = (key: string, file: any) => {
|
||||
if (key === 'delete') {
|
||||
console.log('删除文件:', file)
|
||||
files.value = files.value.filter(f => f.id !== file.id)
|
||||
if (selectedFile.value && selectedFile.value.id === file.id) {
|
||||
selectedFile.value = null
|
||||
}
|
||||
} else if (key === 'rename') {
|
||||
console.log('重命名文件:', file)
|
||||
}
|
||||
}
|
||||
|
||||
// 处理取消按钮
|
||||
const handleCancel = () => {
|
||||
emit('update:show', false)
|
||||
selectedFile.value = null
|
||||
}
|
||||
|
||||
// 处理确定按钮
|
||||
const handleConfirm = () => {
|
||||
if (selectedFile.value) {
|
||||
emit('select', selectedFile.value)
|
||||
emit('update:show', false)
|
||||
selectedFile.value = null
|
||||
}
|
||||
}
|
||||
|
||||
// 监听show变化,重置选择状态
|
||||
watch(() => props.show, (newVal) => {
|
||||
if (!newVal) {
|
||||
selectedFile.value = null
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 资源选择模态框样式 */
|
||||
.resource-modal-content {
|
||||
border-top: 1.5px solid #E6E6E6;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.filter-search-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 20px;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.filter-section, .search-section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.filter-label, .search-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.file-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 16px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.file-count {
|
||||
font-size: 10px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.file-grid {
|
||||
padding: 10px 0;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||
gap: 16px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
min-height: 200px;
|
||||
background: white;
|
||||
border: 1.5px solid #D8D8D8;
|
||||
border-radius: 2px;
|
||||
padding: 18px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.file-item:hover {
|
||||
border-color: #0288D1;
|
||||
box-shadow: 0 2px 8px rgba(2, 136, 209, 0.15);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.file-item.selected {
|
||||
border-color: #0288D1;
|
||||
background: rgba(2, 136, 209, 0.05);
|
||||
}
|
||||
|
||||
.file-thumbnail {
|
||||
height: 105px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.file-thumbnail img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.file-name {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.file-options {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
opacity: 1;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.file-item:hover .file-options {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.file-menu-btn {
|
||||
width: 32px !important;
|
||||
height: 32px !important;
|
||||
padding: 0 !important;
|
||||
background: rgba(255, 255, 255, 0.9) !important;
|
||||
border: none !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.upload-new-file-btn {
|
||||
border-radius: 0;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
padding-top: 16px;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.filter-search-bar {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.file-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.file-thumbnail {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -8,21 +8,13 @@
|
||||
<!-- 下拉选项 -->
|
||||
<div v-show="showDropdown" class="upload-methods flex-col">
|
||||
<label class="local-upload">
|
||||
<input
|
||||
type="file"
|
||||
@change="handleLocalUpload"
|
||||
style="display: none;"
|
||||
accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.mp3,.mp4"
|
||||
/>
|
||||
<input type="file" @change="handleLocalUpload" style="display: none;"
|
||||
accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.mp3,.mp4" />
|
||||
本地上传
|
||||
</label>
|
||||
<label class="resource-upload">
|
||||
<input
|
||||
type="file"
|
||||
@change="handleResourceUpload"
|
||||
style="display: none;"
|
||||
accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.mp3,.mp4"
|
||||
/>
|
||||
<label class="resource-upload" @click="openResourceModal">
|
||||
<!-- <input type="file" @change="handleResourceUpload" style="display: none;"
|
||||
accept=".doc,.docx,.pdf,.xls,.xlsx,.ppt,.pptx,.mp3,.mp4" /> -->
|
||||
资源上传
|
||||
</label>
|
||||
</div>
|
||||
@ -47,11 +39,15 @@
|
||||
<span class="confirm-btn-text">确定</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 资源选择模态框 -->
|
||||
<ResourceSelectionModal v-model:show="showResourceModal" @select="handleResourceSelection" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import ResourceSelectionModal from './ResourceSelectionModal.vue'
|
||||
|
||||
// 控制下拉菜单显示
|
||||
const showDropdown = ref(false)
|
||||
@ -73,14 +69,31 @@ const handleLocalUpload = (event: Event) => {
|
||||
}
|
||||
|
||||
// 处理资源上传
|
||||
const handleResourceUpload = (event: Event) => {
|
||||
const target = event.target as HTMLInputElement
|
||||
const files = target.files
|
||||
if (files && files.length > 0) {
|
||||
console.log('资源上传文件:', files[0])
|
||||
// 这里处理资源文件上传逻辑
|
||||
showDropdown.value = false
|
||||
}
|
||||
// const handleResourceUpload = (event: Event) => {
|
||||
// const target = event.target as HTMLInputElement
|
||||
// const files = target.files
|
||||
// if (files && files.length > 0) {
|
||||
// console.log('资源上传文件:', files[0])
|
||||
// // 这里处理资源文件上传逻辑
|
||||
// showDropdown.value = false
|
||||
// }
|
||||
// }
|
||||
|
||||
// 打开资源选择模态框
|
||||
const openResourceModal = () => {
|
||||
console.log('打开资源选择模态框')
|
||||
showResourceModal.value = true // 打开资源选择模态框
|
||||
showDropdown.value = false // 关闭下拉菜单
|
||||
}
|
||||
|
||||
// 控制资源选择模态框的显示
|
||||
const showResourceModal = ref(false)
|
||||
|
||||
// 处理资源选择
|
||||
const handleResourceSelection = (selectedResource: any) => {
|
||||
console.log('资源选择:', selectedResource)
|
||||
// 这里可以添加处理资源选择的逻辑
|
||||
showResourceModal.value = false
|
||||
}
|
||||
|
||||
// 定义事件发射器
|
||||
|
Loading…
x
Reference in New Issue
Block a user