494 lines
11 KiB
Vue
Raw Normal View History

2025-08-20 14:10:48 +08:00
<template>
<div class="admin-dashboard">
<!-- 顶部图片 -->
2025-08-21 19:39:07 +08:00
<div class="top-image-container">
<img src="/images/teacher/顶部.png" alt="顶部图片" class="top-image">
2025-08-21 19:39:07 +08:00
</div>
2025-08-20 14:10:48 +08:00
<div class="main-content">
<!-- 侧边栏 -->
2025-08-25 10:39:24 +08:00
<div class="sidebar-container" v-if="!hideSidebar">
2025-08-21 19:39:07 +08:00
<!-- 头像 -->
<div class="avatar-container">
<img src="https://picsum.photos/200/200" alt="头像" class="avatar">
<div class="avatar-text">
用户昵称~
</div>
</div>
<!-- 导航栏 -->
<div class="nav-container">
<router-link to="/teacher/course-management" class="nav-item" :class="{ active: activeNavItem === 0 }"
@click="setActiveNavItem(0)">
<img :src="activeNavItem === 0 ? '/images/teacher/课程管理(选中).png' : '/images/teacher/课程管理.png'" alt="">
<span>课程管理</span>
</router-link>
<router-link to="/teacher/student-management" class="nav-item" :class="{ active: activeNavItem === 1 }"
@click="setActiveNavItem(1)">
<img :src="activeNavItem === 1 ? '/images/teacher/学院管理(选中).png' : '/images/teacher/学员管理.png'" alt="">
<span>学员管理</span>
</router-link>
<router-link to="/teacher/my-resources" class="nav-item" :class="{ active: activeNavItem === 2 }"
@click="setActiveNavItem(2)">
<img :src="activeNavItem === 2 ? '/images/teacher/我的资源(选中).png' : '/images/teacher/我的资源.png'" alt="">
<span>我的资源</span>
</router-link>
<router-link to="/teacher/personal-center" class="nav-item" :class="{ active: activeNavItem === 3 }"
@click="setActiveNavItem(3)">
<img :src="activeNavItem === 3 ? '/images/teacher/个人中心(选中).png' : '/images/teacher/个人中心.png'" alt="">
<span>个人中心</span>
</router-link>
</div>
2025-08-20 14:10:48 +08:00
</div>
<!-- 右侧路由视图 -->
2025-08-25 10:39:24 +08:00
<div class="router-view-container" :class="{ 'full-width': hideSidebar }">
2025-08-20 14:10:48 +08:00
<!-- 面包屑 -->
<div class="breadcrumb">
2025-08-21 19:39:07 +08:00
<span class="breadcrumb-separator"></span>
<n-breadcrumb>
2025-08-25 10:39:24 +08:00
<n-breadcrumb-item v-for="(item, index) in breadcrumbItems" :key="index"
@click="handleBreadcrumbClick(item.path)" :class="{ 'clickable': index < breadcrumbItems.length - 1 }">
2025-08-21 19:39:07 +08:00
{{ item.title }}
</n-breadcrumb-item>
</n-breadcrumb>
2025-08-20 14:10:48 +08:00
</div>
<router-view></router-view>
</div>
</div>
</div>
</template>
<script setup lang="ts">
2025-08-20 22:30:37 +08:00
import { ref, onMounted, computed, watch } from 'vue'
2025-08-25 10:39:24 +08:00
import { useRoute, useRouter } from 'vue-router'
2025-08-20 14:10:48 +08:00
const width = window.innerWidth;
const height = window.innerHeight;
console.log(`当前屏幕宽度: ${width}px, 高度: ${height}px`);
// 添加导航项激活状态管理
2025-08-23 19:20:14 +08:00
const activeNavItem = ref(0); // 0: 课程管理, 1: 学员管理, 2: 我的资源, 3: 个人中心
2025-08-20 14:10:48 +08:00
const route = useRoute();
2025-08-25 10:39:24 +08:00
const router = useRouter();
2025-08-20 14:10:48 +08:00
const setActiveNavItem = (index: number) => {
activeNavItem.value = index;
}
2025-08-25 10:39:24 +08:00
// 处理面包屑点击
const handleBreadcrumbClick = (path: string) => {
console.log('面包屑点击,跳转到:', path);
router.push(path);
}
// 判断是否隐藏左侧侧边栏
const hideSidebar = computed(() => {
const currentPath = route.path
// 当进入课程管理相关页面时隐藏侧边栏
return currentPath.includes('course-editor')
})
2025-08-20 14:10:48 +08:00
// 动态生成面包屑
const breadcrumbItems = computed(() => {
2025-08-25 10:39:24 +08:00
const currentPath = route.path;
2025-08-21 19:39:07 +08:00
2025-08-25 10:39:24 +08:00
// 如果在课程编辑器相关页面,强制添加课程管理面包屑
if (currentPath.includes('course-editor')) {
let breadcrumbs = [
{
title: '课程管理',
path: '/teacher/course-management'
}
];
// 根据当前路径添加子页面标题
if (currentPath.includes('courseware')) {
breadcrumbs.push({
title: '课件管理',
path: currentPath
});
} else if (currentPath.includes('question-bank')) {
breadcrumbs.push({
title: '题库管理',
path: currentPath
});
} else if (currentPath.includes('add-question')) {
breadcrumbs.push(
{
title: '题库管理',
path: currentPath.replace('/add-question', '/question-bank')
},
{
title: '新增试题',
path: currentPath
}
);
} else if (currentPath.includes('chapters')) {
breadcrumbs.push({
title: '章节管理',
path: currentPath
});
} else if (currentPath.includes('homework')) {
breadcrumbs.push({
title: '作业管理',
path: currentPath
});
} else if (currentPath.includes('practice')) {
breadcrumbs.push({
title: '练考通',
path: currentPath
});
} else if (currentPath.includes('certificate')) {
breadcrumbs.push({
title: '证书管理',
path: currentPath
});
} else if (currentPath.includes('discussion')) {
breadcrumbs.push({
title: '讨论管理',
path: currentPath
});
} else if (currentPath.includes('statistics')) {
breadcrumbs.push({
title: '统计管理',
path: currentPath
});
} else if (currentPath.includes('notification')) {
breadcrumbs.push({
title: '通知管理',
path: currentPath
});
} else if (currentPath.includes('management')) {
breadcrumbs.push({
title: '综合管理',
path: currentPath
});
}
console.log('课程编辑器页面面包屑:', breadcrumbs);
return breadcrumbs;
}
// 其他页面的面包屑逻辑
const matchedRoutes = route.matched;
2025-08-24 18:20:16 +08:00
let breadcrumbs = matchedRoutes
2025-08-25 10:39:24 +08:00
.filter((item: any) => item.meta.title !== '管理后台')
.map((item: any) => ({
2025-08-20 14:10:48 +08:00
title: item.meta.title || '未知页面',
path: item.path
}));
2025-08-24 18:20:16 +08:00
2025-08-25 10:39:24 +08:00
console.log('其他页面面包屑:', breadcrumbs);
2025-08-24 18:20:16 +08:00
return breadcrumbs;
2025-08-20 14:10:48 +08:00
});
// 监听路由变化,更新激活的导航项
onMounted(() => {
// 初始设置
updateActiveNavItem();
});
// 使用watch监听路由变化
2025-08-20 22:30:37 +08:00
watch(route, () => {
2025-08-20 14:10:48 +08:00
updateActiveNavItem();
});
// 更新激活的导航项
const updateActiveNavItem = () => {
const path = route.path;
if (path.includes('course-management')) {
2025-08-21 19:39:07 +08:00
activeNavItem.value = 0; // 课程管理
2025-08-20 14:10:48 +08:00
} else if (path.includes('student-management')) {
2025-08-21 19:39:07 +08:00
activeNavItem.value = 1; // 学员管理
2025-08-20 14:10:48 +08:00
} else if (path.includes('my-resources')) {
2025-08-21 19:39:07 +08:00
activeNavItem.value = 2; // 我的资源
2025-08-20 14:10:48 +08:00
} else if (path.includes('personal-center')) {
2025-08-21 19:39:07 +08:00
activeNavItem.value = 3; // 个人中心
2025-08-20 14:10:48 +08:00
}
}
</script>
<style scoped>
2025-08-24 18:20:16 +08:00
.admin-dashboard {
min-height: 100vh;
}
2025-08-25 10:39:24 +08:00
2025-08-20 14:10:48 +08:00
.top-image-container {
position: relative;
width: 100%;
height: 130px;
overflow: hidden;
}
2025-08-22 19:52:05 +08:00
/* 响应式调整 */
@media screen and (max-width: 768px) {
.top-image-container {
height: 100px;
}
}
@media screen and (max-width: 480px) {
.top-image-container {
height: 80px;
}
}
2025-08-20 14:10:48 +08:00
.top-image {
2025-08-22 19:52:05 +08:00
width: 100%;
height: 100%;
2025-08-20 14:10:48 +08:00
position: absolute;
left: 0px;
2025-08-22 19:52:05 +08:00
top: 0px;
2025-08-20 14:10:48 +08:00
opacity: 100%;
object-fit: cover;
}
.main-content {
display: flex;
}
2025-08-22 19:52:05 +08:00
@media screen and (max-width: 768px) {
.main-content {
flex-direction: column;
}
2025-08-25 10:39:24 +08:00
2025-08-22 19:52:05 +08:00
.sidebar-container {
width: 100%;
height: auto;
min-height: 300px;
}
2025-08-25 10:39:24 +08:00
2025-08-22 19:52:05 +08:00
.router-view-container {
height: auto;
min-height: calc(100vh - var(--top-height, 100px) - 300px);
}
}
2025-08-21 19:39:07 +08:00
.sidebar-container {
2025-08-23 19:20:14 +08:00
width: 240px;
2025-08-22 19:52:05 +08:00
height: calc(100vh - var(--top-height, 130px));
2025-08-21 19:39:07 +08:00
background: #FFFFFF;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
2025-08-20 14:10:48 +08:00
}
2025-08-21 19:39:07 +08:00
2025-08-22 19:52:05 +08:00
@media screen and (max-width: 768px) {
.sidebar-container {
--top-height: 100px;
}
}
@media screen and (max-width: 480px) {
.sidebar-container {
--top-height: 80px;
2025-08-23 19:20:14 +08:00
width: 200px;
2025-08-22 19:52:05 +08:00
}
}
2025-08-21 19:39:07 +08:00
.avatar-container {
height: 230px;
position: relative;
/* 移除原来的边框 */
2025-08-20 14:10:48 +08:00
}
/* 添加带间距的横线 */
.avatar-container::after {
2025-08-21 19:39:07 +08:00
content: '';
position: absolute;
bottom: 0;
2025-08-23 19:20:14 +08:00
left: 15px;
2025-08-25 10:39:24 +08:00
right: 15px;
height: 1px;
background-color: #E6E6E6;
}
.avatar-container img {
width: 80px;
height: 80px;
/* 圆角 */
border-radius: 50%;
margin-top: 55px;
margin-left: 80px;
margin-right: 80px;
}
.avatar-text {
margin-left: 80px;
height: 31px;
font-family: AppleSystemUIFont;
font-size: 20px;
color: #000000;
line-height: 26px;
text-align: left;
font-style: normal;
text-transform: none;
}
@media screen and (max-width: 768px) {
.avatar-container {
height: 180px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
2025-08-22 19:52:05 +08:00
}
2025-08-25 10:39:24 +08:00
2025-08-22 19:52:05 +08:00
.avatar-container img {
2025-08-25 10:39:24 +08:00
margin: 0 0 15px 0;
2025-08-22 19:52:05 +08:00
}
2025-08-25 10:39:24 +08:00
2025-08-22 19:52:05 +08:00
.avatar-text {
2025-08-25 10:39:24 +08:00
margin: 0;
text-align: center;
2025-08-22 19:52:05 +08:00
}
2025-08-25 10:39:24 +08:00
}
@media screen and (max-width: 480px) {
.avatar-container {
height: 150px;
2025-08-22 19:52:05 +08:00
}
2025-08-25 10:39:24 +08:00
.avatar-container img {
width: 80px;
height: 80px;
2025-08-22 19:52:05 +08:00
}
2025-08-25 10:39:24 +08:00
.avatar-text {
font-size: 18px;
2025-08-22 19:52:05 +08:00
}
2025-08-25 10:39:24 +08:00
}
.nav-container {
margin-top: 30px;
/* 鼠标变小手 */
cursor: pointer;
}
.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) {
.nav-container {
2025-08-23 19:20:14 +08:00
display: flex;
2025-08-25 10:39:24 +08:00
flex-wrap: wrap;
justify-content: center;
margin-top: 15px;
2025-08-22 19:52:05 +08:00
}
2025-08-25 10:39:24 +08:00
.nav-container .nav-item {
width: 200px;
margin: 0 10px 15px;
}
2025-08-25 10:39:24 +08:00
}
@media screen and (max-width: 480px) {
.nav-container .nav-item {
width: 150px;
height: 45px;
margin: 0 5px 10px;
}
2025-08-25 10:39:24 +08:00
2025-08-23 19:20:14 +08:00
.nav-container .nav-item img {
2025-08-25 10:39:24 +08:00
margin-left: 20px;
}
2025-08-25 10:39:24 +08:00
}
.nav-container .nav-item:hover {
background: rgba(102, 183, 227, 0.05);
}
/* 添加激活状态样式 */
.nav-container .nav-item.active {
background: rgba(102, 183, 227, 0.1);
}
.nav-container .nav-item.active span {
color: #0C99DA;
}
.nav-container .nav-item img {
height: 18px;
margin-left: 40px;
margin-top: 0;
margin-right: 5px;
}
.nav-container .nav-item span {
height: 26px;
2025-08-21 19:39:07 +08:00
font-family: AppleSystemUIFont;
2025-08-23 19:20:14 +08:00
font-size: 18px;
2025-08-21 19:39:07 +08:00
color: #666666;
line-height: 23px;
text-align: left;
font-style: normal;
text-transform: none;
2025-08-20 14:10:48 +08:00
}
.router-view-container {
2025-08-21 19:39:07 +08:00
flex: 1;
2025-08-23 19:20:14 +08:00
padding: 10px 25px;
2025-08-21 19:39:07 +08:00
background: #F5F7FA;
2025-08-22 19:52:05 +08:00
height: calc(100vh - var(--top-height, 130px));
2025-08-23 19:20:14 +08:00
overflow-y: auto;
2025-08-20 14:10:48 +08:00
}
2025-08-25 10:39:24 +08:00
/* 全宽显示(隐藏侧边栏时) */
.router-view-container.full-width {
width: 100%;
margin-left: 0;
}
2025-08-22 19:52:05 +08:00
@media screen and (max-width: 768px) {
.router-view-container {
--top-height: 100px;
padding: 15px;
}
}
@media screen and (max-width: 480px) {
.router-view-container {
--top-height: 80px;
padding: 10px;
}
}
2025-08-20 14:10:48 +08:00
.breadcrumb {
display: flex;
align-items: center;
}
.breadcrumb-separator {
2025-08-21 19:39:07 +08:00
width: 4px;
height: 17px;
margin-right: 10px;
background-color: #0C99DA;
2025-08-20 14:10:48 +08:00
}
2025-08-25 10:39:24 +08:00
/* 可点击的面包屑项样式 */
.breadcrumb :deep(.n-breadcrumb-item.clickable) {
cursor: pointer;
color: #0C99DA;
}
.breadcrumb :deep(.n-breadcrumb-item.clickable:hover) {
color: #0277BD;
text-decoration: underline;
}
2025-08-20 14:10:48 +08:00
</style>