mirror of
http://112.124.100.131/ebiz-ai/ebiz-ai-knowledge-manage.git
synced 2025-12-08 10:26:48 +08:00
362 lines
8.7 KiB
Vue
362 lines
8.7 KiB
Vue
<template>
|
|
<div :class="{ 'has-logo': showLogo }" class="sidebar-container">
|
|
<div class="sidebar-layout">
|
|
<!-- Left side - Primary menu -->
|
|
<div class="primary-menu">
|
|
<div>
|
|
<logo class="logo" v-if="showLogo" :collapse="isCollapse" />
|
|
<div
|
|
v-for="route in menuList"
|
|
:key="route.id"
|
|
class="primary-menu-item"
|
|
:class="{ active: activeParent === route.url }"
|
|
@click="selectParentMenu(route)"
|
|
>
|
|
<i
|
|
v-if="route.icon"
|
|
:class="[
|
|
route.icon,
|
|
{ iconfont: !route.icon.includes('el-icon') },
|
|
{ mb5: route.icon.includes('el-icon') }
|
|
]"
|
|
class=" fs22"
|
|
></i>
|
|
<img
|
|
v-else
|
|
:src="activeParent === route.url ? knowledgeActive : knowledge"
|
|
alt=""
|
|
class="mb5"
|
|
style="width: 20px"
|
|
/>
|
|
<span class="menu-title">{{ route.menuName }}</span>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<personal />
|
|
</div>
|
|
</div>
|
|
<!-- Right side - Submenu -->
|
|
<div class="submenu-container" v-if="currentSubmenu.length">
|
|
<!-- <div class="submenu-header">-->
|
|
<!-- <span>{{ currentParentTitle }}</span>-->
|
|
<!-- </div>-->
|
|
<el-scrollbar wrap-class="scrollbar-wrapper">
|
|
<div class="submenu-list">
|
|
<pre style="font-size: 12px; padding: 10px; display: none;">{{
|
|
JSON.stringify(currentSubmenu, null, 2)
|
|
}}</pre>
|
|
<div
|
|
v-for="subItem in currentSubmenu"
|
|
:key="subItem.id"
|
|
class="submenu-item"
|
|
:class="{ active: activeMenu === subItem.url }"
|
|
@click="navigateTo(subItem.url)"
|
|
>
|
|
<i
|
|
v-if="subItem.icon"
|
|
class="mr10"
|
|
:class="[
|
|
subItem.icon,
|
|
{ iconfont: !subItem.icon.includes('el-icon') }
|
|
]"
|
|
/>
|
|
<span>{{ subItem.menuName }}</span>
|
|
</div>
|
|
</div>
|
|
</el-scrollbar>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters, mapActions } from 'vuex'
|
|
import Logo from './Logo'
|
|
import variables from '@/assets/sass/variables.scss'
|
|
import Personal from '@/views/app/layout/components/Sidebar/personal.vue'
|
|
import knowledge from '@/assets/images/knowledge.png'
|
|
import knowledgeActive from '@/assets/images/knowledgeActive.png'
|
|
|
|
export default {
|
|
components: { Personal, Logo },
|
|
computed: {
|
|
knowledge() {
|
|
return knowledge
|
|
},
|
|
knowledgeActive() {
|
|
return knowledgeActive
|
|
},
|
|
...mapGetters(['sidebar', 'sidebarList']),
|
|
routes() {
|
|
return this.$router.options.routes
|
|
},
|
|
activeMenu() {
|
|
const route = this.$route
|
|
const { meta, path } = route
|
|
// if set path, the sidebar will highlight the path you set
|
|
if (meta.activeMenu) {
|
|
return meta.activeMenu
|
|
}
|
|
return path
|
|
},
|
|
showLogo() {
|
|
return this.$store.state.settings.sidebarLogo
|
|
},
|
|
variables() {
|
|
return variables
|
|
},
|
|
isCollapse() {
|
|
return !this.sidebar.opened
|
|
},
|
|
currentSubmenu() {
|
|
if (!this.activeParent) return []
|
|
const parent = this.menuList.find(item => item.url === this.activeParent)
|
|
return parent ? parent.children || [] : []
|
|
},
|
|
currentParentTitle() {
|
|
if (!this.activeParent) return ''
|
|
const parent = this.menuList.find(item => item.url === this.activeParent)
|
|
return parent && parent.meta ? parent.meta.title : ''
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
menuList: [],
|
|
activeParent: null
|
|
}
|
|
},
|
|
methods: {
|
|
...mapActions({
|
|
setSidebarList: 'app/setSidebarList'
|
|
}),
|
|
formatList(menu, state, parentPath = null) {
|
|
menu.map(item => {
|
|
if (parentPath) {
|
|
item.url = '/' + parentPath + '/' + item.url
|
|
}
|
|
if (item.otherInfo1 == 0) {
|
|
item.name = item.menuName
|
|
item.alwaysShow = state
|
|
item.meta = {
|
|
title: item.menuName,
|
|
icon: item.img
|
|
}
|
|
if (item.children != null) {
|
|
this.formatList(item.children, undefined, item.url)
|
|
} else {
|
|
item.children = []
|
|
}
|
|
} else {
|
|
item.children = []
|
|
}
|
|
})
|
|
return menu
|
|
},
|
|
selectParentMenu(route) {
|
|
this.activeParent = route.url
|
|
// this.$store.dispatch('app/toggleSideBar')
|
|
// If this parent has children, don't navigate
|
|
if (route.children && route.children.length > 0) {
|
|
// Optionally navigate to the first child
|
|
this.navigateTo(route.children[0].url)
|
|
} else {
|
|
// If no children, navigate to the parent route
|
|
this.navigateTo(route.url)
|
|
}
|
|
},
|
|
navigateTo(url) {
|
|
if (url && url !== this.$route.path) {
|
|
this.$router.push(url)
|
|
}
|
|
},
|
|
findParentForCurrentRoute() {
|
|
const currentPath = this.$route.path
|
|
|
|
// Try to find the parent menu that contains the current route
|
|
for (const parent of this.menuList) {
|
|
// Check if current route is the parent itself
|
|
if (parent.url === currentPath) {
|
|
this.activeParent = parent.url
|
|
return
|
|
}
|
|
|
|
// Check if current route is one of the children
|
|
if (parent.children && parent.children.length) {
|
|
const childMatch = parent.children.find(
|
|
child =>
|
|
child.url === currentPath ||
|
|
currentPath.startsWith(child.url + '/')
|
|
)
|
|
|
|
if (childMatch) {
|
|
this.activeParent = parent.url
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// If no match found, default to first menu item if available
|
|
if (this.menuList.length > 0 && !this.activeParent) {
|
|
this.activeParent = this.menuList[0].url
|
|
}
|
|
}
|
|
},
|
|
created() {
|
|
if (sessionStorage.token !== 'MockToken') {
|
|
// 获取路由数据
|
|
|
|
this.menuList = this.$store.state.app.sidebarList
|
|
} else {
|
|
// 从路由配置中获取顶级路由
|
|
this.menuList = this.routes.filter(route => {
|
|
// 只显示有 meta 和 children 的路由,并且不是隐藏的
|
|
return route.meta && route.children && !route.hidden
|
|
})
|
|
}
|
|
|
|
// 根据当前路由设置活动的父菜单
|
|
this.$nextTick(() => {
|
|
this.findParentForCurrentRoute()
|
|
})
|
|
},
|
|
watch: {
|
|
$route() {
|
|
// Update active parent when route changes
|
|
this.findParentForCurrentRoute()
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style scoped lang="scss">
|
|
.sidebar-container {
|
|
height: 100%;
|
|
background-color: #fff;
|
|
border-right: 1px solid #e6e6e6;
|
|
overflow: hidden;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.sidebar-layout {
|
|
display: flex;
|
|
flex: 1;
|
|
overflow: hidden;
|
|
background-color: #fff;
|
|
border-radius: 6px;
|
|
}
|
|
|
|
.primary-menu {
|
|
width: 95px;
|
|
height: 100%;
|
|
position: relative;
|
|
overflow-y: auto;
|
|
background-color: #fff;
|
|
text-align: center;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding-bottom: 16px;
|
|
.logo {
|
|
margin-top: 30px;
|
|
margin-bottom: 40px;
|
|
}
|
|
&:after {
|
|
content: ' ';
|
|
position: absolute;
|
|
border-right: 1px solid #ebeef2;
|
|
height: 100%;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
transform: scaleX(0.5);
|
|
}
|
|
}
|
|
.primary-menu-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 58px;
|
|
width: 68px;
|
|
padding: 10px 0;
|
|
cursor: pointer;
|
|
color: #606266;
|
|
margin-top: 10px;
|
|
|
|
&:hover,
|
|
&.active {
|
|
color: #4d64ff;
|
|
background-color: #f8f8fa;
|
|
}
|
|
&.active span {
|
|
color: #000;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.svg-icon {
|
|
font-size: 24px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.menu-title {
|
|
font-size: 14px;
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
.submenu-container {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
padding: 23px 10px;
|
|
width: 160px;
|
|
}
|
|
|
|
.submenu-header {
|
|
height: 50px;
|
|
line-height: 50px;
|
|
padding: 0 20px;
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
|
|
.submenu-list {
|
|
padding: 10px 0;
|
|
}
|
|
|
|
.submenu-item {
|
|
height: 40px;
|
|
line-height: 40px;
|
|
padding: 0 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: flex-start;
|
|
cursor: pointer;
|
|
color: #000;
|
|
margin-bottom: 5px;
|
|
border-radius: 4px;
|
|
font-size: 14px;
|
|
|
|
&:hover,
|
|
&.active {
|
|
color: #4d64ff;
|
|
background-color: #f8f8fa;
|
|
}
|
|
&.active span {
|
|
color: #000;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.svg-icon {
|
|
margin-right: 10px;
|
|
}
|
|
}
|
|
|
|
.scrollbar-wrapper {
|
|
height: 100%;
|
|
}
|
|
</style>
|