Files
schoolNews/schoolNewsWeb/src/components/base/FloatingSidebar.vue
2025-12-09 16:04:36 +08:00

305 lines
5.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<aside class="floating-sidebar">
<!-- 侧边栏内容 -->
<div class="sidebar-content">
<!-- 菜单列表 -->
<nav class="sidebar-nav">
<div
v-for="menu in menus"
:key="menu.menuID || menu.url"
class="sidebar-item"
:class="{
active: isActive(menu),
'theme-resource': props.theme === 'resource'
}"
@click="handleClick(menu)"
>
<div class="sidebar-link">
<span class="link-text">{{ menu.name }}</span>
</div>
</div>
</nav>
</div>
</aside>
</template>
<script setup lang="ts">
import type { SysMenu } from '@/types';
import { useRouter, useRoute } from 'vue-router';
// Props
interface Props {
menus: SysMenu[];
activePath?: string;
theme?: 'default' | 'resource'; // 新增主题属性
}
const props = withDefaults(defineProps<Props>(), {
theme: 'default'
});
// Emits
const emit = defineEmits<{
'menu-click': [menu: SysMenu];
}>();
const router = useRouter();
const route = useRoute();
// 检查菜单是否激活
function isActive(menu: SysMenu): boolean {
if (props.activePath) {
return props.activePath === menu.url;
}
if (!menu.url) return false;
return route.path === menu.url;
}
// 处理点击
function handleClick(menu: SysMenu) {
// 触发点击事件
emit('menu-click', menu);
// 如果有URL进行路由跳转
if (menu.url) {
router.push(menu.url);
}
}
</script>
<style lang="scss" scoped>
.floating-sidebar {
width: 180px;
background: #FFFFFF;
border-radius: 10px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
flex-shrink: 0;
display: flex;
flex-direction: column;
position: relative;
}
.sidebar-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
.sidebar-nav {
flex: 1;
overflow-y: auto;
padding: 20px 0;
display: flex;
flex-direction: column;
gap: 20px;
/* 滚动条样式 */
&::-webkit-scrollbar {
width: 4px;
}
&::-webkit-scrollbar-track {
background: transparent;
}
&::-webkit-scrollbar-thumb {
background: #ddd;
border-radius: 2px;
&:hover {
background: #bbb;
}
}
}
.sidebar-item {
position: relative;
height: 54px;
display: flex;
align-items: center;
cursor: pointer;
transition: all 0.3s;
&::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 20px;
background: transparent;
transition: background 0.2s;
}
&.active {
&::before {
background: #C62828;
}
.sidebar-link {
color: #C62828;
}
}
&:hover {
.sidebar-link {
color: #C62828;
}
}
// Resource theme - 红色背景高亮
&.theme-resource {
padding: 0 10px;
&:hover {
background: rgba(198, 40, 40, 0.05);
}
&.active {
background: #C62828;
border-radius: 8px;
margin: 5px 10px;
height: 44px;
&::before {
display: none; // 隐藏左侧指示条
}
.sidebar-link {
color: #FFFFFF;
}
&::after {
content: '';
position: absolute;
right: -103px;
top: 3px;
width: 48.53px;
height: 50.54px;
background: linear-gradient(134deg, rgba(255, 255, 255, 1) 26%, rgba(255, 255, 255, 0) 86%);
opacity: 0.23;
pointer-events: none;
}
}
}
}
.sidebar-link {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 0 16px;
color: #334155;
font-size: 16px;
font-weight: 500;
font-family: 'Source Han Sans SC', sans-serif;
line-height: 1.5;
transition: color 0.3s;
user-select: none;
.link-text {
text-align: center;
}
.theme-resource & {
margin-left: 32px; // Resource theme 文字左移
}
}
/* 移动端响应式设计 - 水平标签栏 */
@media (max-width: 768px) {
.floating-sidebar {
width: 100%;
height: auto;
flex-direction: row;
border-radius: 0 0 8px 8px; // 顶部圆角移除与main-content连接
}
.sidebar-content {
width: 100%;
flex-direction: row;
}
.sidebar-nav {
flex-direction: row;
padding: 10px 0;
gap: 0;
overflow-x: auto;
overflow-y: hidden;
/* 水平滚动条样式 */
&::-webkit-scrollbar {
height: 4px;
width: auto;
}
}
.sidebar-item {
flex: 1;
min-width: 60px;
height: 44px;
justify-content: center;
&::before {
display: none; // 移动端隐藏左侧指示条
}
&.active::after {
content: '';
position: absolute;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 3px;
background: #C62828;
border-radius: 2px;
}
// Resource theme 在移动端的特殊样式
&.theme-resource {
padding: 0 5px;
margin: 0;
&.active {
background: transparent;
border-radius: 0;
margin: 0;
height: 44px;
&::after {
right: auto;
top: auto;
width: 20px;
height: 3px;
background: #C62828;
opacity: 1;
bottom: -10px;
left: 50%;
transform: translateX(-50%);
border-radius: 2px;
}
.sidebar-link {
color: #C62828;
}
}
}
}
.sidebar-link {
padding: 0 8px;
font-size: 14px;
justify-content: center;
.theme-resource & {
margin-left: 0; // 移动端取消左边距
}
}
}
</style>