@ -1,54 +1,54 @@
< template >
< div class = "layout-columns-aside" >
< el -scrollbar >
< ul @mouseleave ="onColumnsAsideMenuMouseleave()" >
< li
v - for = "(v, k) in state.columnsAsideList"
: key = "k"
@ click = "onColumnsAsideMenuClick(v, k)"
@ mouseenter = "onColumnsAsideMenuMouseenter(v, k)"
: ref = "
< div class = "layout-columns-aside" >
< el -scrollbar >
< ul @mouseleave ="onColumnsAsideMenuMouseleave()" >
< li
v - for = "(v, k) in state.columnsAsideList"
: key = "k"
@ click = "onColumnsAsideMenuClick(v, k)"
@ mouseenter = "onColumnsAsideMenuMouseenter(v, k)"
: ref = "
( el ) => {
if ( el ) columnsAsideOffsetTopRefs [ k ] = el ;
}
"
: class = "{ 'layout-columns-active': state.liIndex === k, 'layout-columns-hover': state.liHoverIndex === k }"
: title = "$t(v.name)"
>
< div :class ="themeConfig.columnsAsideLayout" v-if ="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)" >
< SvgIcon :name ="v.meta.icon" / >
< div class = "columns-vertical-title font12" >
{ {
$t ( v . name ) && $t ( v . name ) . length >= 4
? $t ( v . name ) . substr ( 0 , themeConfig . columnsAsideLayout === 'columns-vertical' ? 4 : 3 )
: $t ( v . name )
} }
< / div >
< / div >
< div :class ="themeConfig.columnsAsideLayout" v-else >
< a :href ="v.meta.isLink" target = "_blank" >
< SvgIcon :name ="v.meta.icon" / >
< div class = "columns-vertical-title font12" >
{ {
$t ( v . name ) && $t ( v . name ) . length >= 4
? $t ( v . name ) . substr ( 0 , themeConfig . columnsAsideLayout === 'columns-vertical' ? 4 : 3 )
: $t ( v . name )
} }
< / div >
< / a >
< / div >
< / li >
< div ref = "columnsAsideActiveRef" :class ="themeConfig.columnsAsideStyle" > < / div >
< / ul >
< / e l - s c r o l l b a r >
< / div >
: class = "{ 'layout-columns-active': state.liIndex === k, 'layout-columns-hover': state.liHoverIndex === k }"
: title = "$t(v.name)"
>
< div :class ="themeConfig.columnsAsideLayout" v-if ="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)" >
< SvgIcon :name ="v.meta.icon" / >
< div class = "columns-vertical-title font12" >
{ {
$t ( v . name ) && $t ( v . name ) . length >= 4
? $t ( v . name ) . substr ( 0 , themeConfig . columnsAsideLayout === 'columns-vertical' ? 4 : 3 )
: $t ( v . name )
} }
< / div >
< / div >
< div :class ="themeConfig.columnsAsideLayout" v-else >
< a :href ="v.meta.isLink" target = "_blank" >
< SvgIcon :name ="v.meta.icon" / >
< div class = "columns-vertical-title font12" >
{ {
$t ( v . name ) && $t ( v . name ) . length >= 4
? $t ( v . name ) . substr ( 0 , themeConfig . columnsAsideLayout === 'columns-vertical' ? 4 : 3 )
: $t ( v . name )
} }
< / div >
< / a >
< / div >
< / li >
< div ref = "columnsAsideActiveRef" :class ="themeConfig.columnsAsideStyle" > < / div >
< / ul >
< / e l - s c r o l l b a r >
< / div >
< / template >
< script setup lang = "ts" name = "layoutColumnsAside" >
import { RouteRecordRaw } from 'vue-router' ;
import { RouteRecordRaw } from 'vue-router' ;
import pinia from '/@/stores/index' ;
import { useRoutesList } from '/@/stores/routesList' ;
import { useThemeConfig } from '/@/stores/themeConfig' ;
import { useRoutesList } from '/@/stores/routesList' ;
import { useThemeConfig } from '/@/stores/themeConfig' ;
import mittBus from '/@/utils/mitt' ;
/ / 定 义 变 量 内 容
@ -56,246 +56,245 @@ const columnsAsideOffsetTopRefs = ref<RefType>([]);
const columnsAsideActiveRef = ref ( ) ;
const stores = useRoutesList ( ) ;
const storesThemeConfig = useThemeConfig ( ) ;
const { routesList , isColumnsMenuHover , isColumnsNavHover } = storeToRefs ( stores ) ;
const { themeConfig } = storeToRefs ( storesThemeConfig ) ;
const { routesList , isColumnsMenuHover , isColumnsNavHover } = storeToRefs ( stores ) ;
const { themeConfig } = storeToRefs ( storesThemeConfig ) ;
const route = useRoute ( ) ;
const router = useRouter ( ) ;
const state = reactive < ColumnsAsideState > ( {
columnsAsideList : [ ] ,
liIndex : 0 ,
liOldIndex : null ,
liHoverIndex : null ,
liOldPath : null ,
difference : 0 ,
routeSplit : [ ] ,
columnsAsideList : [ ] ,
liIndex : 0 ,
liOldIndex : null ,
liHoverIndex : null ,
liOldPath : null ,
difference : 0 ,
routeSplit : [ ] ,
} ) ;
/ / 设 置 菜 单 高 亮 位 置 移 动
const setColumnsAsideMove = ( k : number ) => {
state . liIndex = k ;
columnsAsideActiveRef . value . style . top = ` ${ columnsAsideOffsetTopRefs . value [ k ] . offsetTop + state . difference } px ` ;
state . liIndex = k ;
columnsAsideActiveRef . value . style . top = ` ${ columnsAsideOffsetTopRefs . value [ k ] . offsetTop + state . difference } px ` ;
} ;
/ / 菜 单 高 亮 点 击 事 件
const onColumnsAsideMenuClick = ( v : RouteItem , k : number ) => {
setColumnsAsideMove ( k ) ;
let { path , redirect } = v ;
if ( redirect ) router . push ( redirect ) ;
else router . push ( path ) ;
setColumnsAsideMove ( k ) ;
let { path , redirect } = v ;
if ( redirect ) router . push ( redirect ) ;
else router . push ( path ) ;
} ;
/ / 鼠 标 移 入 时 , 显 示 当 前 的 子 级 菜 单
const onColumnsAsideMenuMouseenter = ( v : RouteRecordRaw , k : number ) => {
if ( ! themeConfig . value . isColumnsMenuHoverPreload ) return false ;
let { path } = v ;
state . liOldPath = path ;
state . liOldIndex = k ;
state . liHoverIndex = k ;
mittBus . emit ( 'setSendColumnsChildren' , setSendChildren ( path ) ) ;
stores . setColumnsMenuHover ( false ) ;
stores . setColumnsNavHover ( true ) ;
if ( ! themeConfig . value . isColumnsMenuHoverPreload ) return false ;
let { path } = v ;
state . liOldPath = path ;
state . liOldIndex = k ;
state . liHoverIndex = k ;
mittBus . emit ( 'setSendColumnsChildren' , setSendChildren ( path ) ) ;
stores . setColumnsMenuHover ( false ) ;
stores . setColumnsNavHover ( true ) ;
} ;
/ / 鼠 标 移 走 时 , 显 示 原 来 的 子 级 菜 单
const onColumnsAsideMenuMouseleave = async ( ) => {
await stores . setColumnsNavHover ( false ) ;
/ / 添 加 延 时 器 , 防 止 拿 到 的 s t o r e . s t a t e . r o u t e s L i s t 值 不 是 最 新 的
setTimeout ( ( ) => {
if ( ! isColumnsMenuHover && ! isColumnsNavHover ) mittBus . emit ( 'restoreDefault' ) ;
} , 100 ) ;
await stores . setColumnsNavHover ( false ) ;
/ / 添 加 延 时 器 , 防 止 拿 到 的 s t o r e . s t a t e . r o u t e s L i s t 值 不 是 最 新 的
setTimeout ( ( ) => {
if ( ! isColumnsMenuHover && ! isColumnsNavHover ) mittBus . emit ( 'restoreDefault' ) ;
} , 100 ) ;
} ;
/ / 设 置 高 亮 动 态 位 置
const onColumnsAsideDown = ( k : number ) => {
nextTick ( ( ) => {
setColumnsAsideMove ( k ) ;
} ) ;
nextTick ( ( ) => {
setColumnsAsideMove ( k ) ;
} ) ;
} ;
/ / 设 置 / 过 滤 路 由 ( 非 静 态 路 由 / 是 否 显 示 在 菜 单 中 )
const setFilterRoutes = ( ) => {
state . columnsAsideList = filterRoutesFun ( routesList . value ) ;
const resData : MittMenu = setSendChildren ( route . path ) ;
if ( Object . keys ( resData ) . length <= 0 ) return false ;
onColumnsAsideDown ( resData . item ? . k ) ;
mittBus . emit ( 'setSendColumnsChildren' , resData ) ;
state . columnsAsideList = filterRoutesFun ( routesList . value ) ;
const resData : MittMenu = setSendChildren ( route . path ) ;
if ( Object . keys ( resData ) . length <= 0 ) return false ;
onColumnsAsideDown ( resData . item ? . k ) ;
mittBus . emit ( 'setSendColumnsChildren' , resData ) ;
} ;
/ / 传 送 当 前 子 级 数 据 到 菜 单 中
const setSendChildren = ( path : string ) => {
const parentRoute = searchParent ( routesList . value , path ) as any ;
let currentData : MittMenu = { children : [ ] } ;
state . columnsAsideList . map ( ( v : RouteItem , k : number ) => {
if ( v . path === parentRoute . path ) {
v [ 'k' ] = k ;
currentData [ 'item' ] = { ... v } ;
currentData [ 'children' ] = [ { ... v } ] ;
if ( v . children ) currentData [ 'children' ] = v . children ;
}
} ) ;
return currentData ;
const parentRoute = searchParent ( routesList . value , path ) as any ;
let currentData : MittMenu = { children : [ ] } ;
state . columnsAsideList . map ( ( v : RouteItem , k : number ) => {
if ( v . path === parentRoute . path ) {
v [ 'k' ] = k ;
currentData [ 'item' ] = { ... v } ;
currentData [ 'children' ] = [ { ... v } ] ;
if ( v . children ) currentData [ 'children' ] = v . children ;
}
} ) ;
return currentData ;
} ;
/ / 路 由 过 滤 递 归 函 数
const filterRoutesFun = < T extends RouteItem > ( arr : T [ ] ) : T [ ] => {
return arr
. filter ( ( item : T ) => ! item . meta ? . isHide )
. map ( ( item : T ) => {
item = Object . assign ( { } , item ) ;
if ( item . children ) item . children = filterRoutesFun ( item . children ) ;
return item ;
} ) ;
return arr
. filter ( ( item : T ) => ! item . meta ? . isHide )
. map ( ( item : T ) => {
item = Object . assign ( { } , item ) ;
if ( item . children ) item . children = filterRoutesFun ( item . children ) ;
return item ;
} ) ;
} ;
/ / t a g s V i e w 点 击 时 , 根 据 路 由 查 找 下 标 c o l u m n s A s i d e L i s t , 实 现 左 侧 菜 单 高 亮
const setColumnsMenuHighlight = ( path : string ) => {
const parentRoute = searchParent ( routesList . value , path ) as any ;
const currentSplitRoute = state . columnsAsideList . find ( ( v : RouteItem ) => v . path === parentRoute . path ) ;
if ( ! currentSplitRoute ) return false ;
/ / 延 迟 拿 值 , 防 止 取 不 到
setTimeout ( ( ) => {
onColumnsAsideDown ( currentSplitRoute . k ) ;
} , 0 ) ;
const parentRoute = searchParent ( routesList . value , path ) as any ;
const currentSplitRoute = state . columnsAsideList . find ( ( v : RouteItem ) => v . path === parentRoute . path ) ;
if ( ! currentSplitRoute ) return false ;
/ / 延 迟 拿 值 , 防 止 取 不 到
setTimeout ( ( ) => {
onColumnsAsideDown ( currentSplitRoute . k ) ;
} , 0 ) ;
} ;
/ / 使 用 递 归 查 询 对 应 的 父 级 路 由
const searchParent = ( routesList : any , path : string ) => {
let route = undefined ;
routesList . forEach ( ( item ) => {
if ( item . path === path ) {
route = item ;
return ;
}
if ( item . children && searchParent ( item . children , path ) ) {
route = item ;
return ;
}
} ) ;
return route ;
let route = undefined ;
routesList . forEach ( ( item ) => {
if ( item . path === path ) {
route = item ;
return ;
}
if ( item . children && searchParent ( item . children , path ) ) {
route = item ;
return ;
}
} ) ;
return route ;
} ;
/ / 页 面 加 载 时
onMounted ( ( ) => {
setFilterRoutes ( ) ;
/ / 销 毁 变 量 , 防 止 鼠 标 再 次 移 入 时 , 保 留 了 上 次 的 记 录
mittBus . on ( 'restoreDefault' , ( ) => {
state . liOldIndex = null ;
state . liOldPath = null ;
} ) ;
setFilterRoutes ( ) ;
/ / 销 毁 变 量 , 防 止 鼠 标 再 次 移 入 时 , 保 留 了 上 次 的 记 录
mittBus . on ( 'restoreDefault' , ( ) => {
state . liOldIndex = null ;
state . liOldPath = null ;
} ) ;
} ) ;
/ / 页 面 卸 载 时
onUnmounted ( ( ) => {
mittBus . off ( 'restoreDefault' , ( ) => {
} ) ;
mittBus . off ( 'restoreDefault' , ( ) => { } ) ;
} ) ;
/ / 路 由 更 新 时
onBeforeRouteUpdate ( ( to ) => {
setColumnsMenuHighlight ( to . path ) ;
mittBus . emit ( 'setSendColumnsChildren' , setSendChildren ( to . path ) ) ;
setColumnsMenuHighlight ( to . path ) ;
mittBus . emit ( 'setSendColumnsChildren' , setSendChildren ( to . path ) ) ;
} ) ;
/ / 监 听 布 局 配 置 信 息 的 变 化 , 动 态 增 加 菜 单 高 亮 位 置 移 动 像 素
watch (
pinia . state ,
( val ) => {
val . themeConfig . themeConfig . columnsAsideStyle === 'columnsRound' ? ( state . difference = 3 ) : ( state . difference = 0 ) ;
if ( ! val . routesList . isColumnsMenuHover && ! val . routesList . isColumnsNavHover ) {
state . liHoverIndex = null ;
mittBus . emit ( 'setSendColumnsChildren' , setSendChildren ( route . path ) ) ;
} else {
state . liHoverIndex = state . liOldIndex ;
if ( ! state . liOldPath ) return false ;
mittBus . emit ( 'setSendColumnsChildren' , setSendChildren ( state . liOldPath ) ) ;
}
} ,
{
deep : true ,
}
pinia . state ,
( val ) => {
val . themeConfig . themeConfig . columnsAsideStyle === 'columnsRound' ? ( state . difference = 3 ) : ( state . difference = 0 ) ;
if ( ! val . routesList . isColumnsMenuHover && ! val . routesList . isColumnsNavHover ) {
state . liHoverIndex = null ;
mittBus . emit ( 'setSendColumnsChildren' , setSendChildren ( route . path ) ) ;
} else {
state . liHoverIndex = state . liOldIndex ;
if ( ! state . liOldPath ) return false ;
mittBus . emit ( 'setSendColumnsChildren' , setSendChildren ( state . liOldPath ) ) ;
}
} ,
{
deep : true ,
}
) ;
< / script >
< style scoped lang = "scss" >
. layout - columns - aside {
width : 70 px ;
height : 100 % ;
background : var ( -- next - bg - columnsMenuBar ) ;
width : 70 px ;
height : 100 % ;
background : var ( -- next - bg - columnsMenuBar ) ;
ul {
position : relative ;
ul {
position : relative ;
. layout - columns - active {
color : var ( -- next - bg - columnsMenuBarColor ) ! important ;
transition : 0.3 s ease - in - out ;
}
. layout - columns - active {
color : var ( -- next - bg - columnsMenuBarColor ) ! important ;
transition : 0.3 s ease - in - out ;
}
. layout - columns - hover {
color : var ( -- el - color - primary ) ;
. layout - columns - hover {
color : var ( -- el - color - primary ) ;
a {
color : var ( -- el - color - primary ) ;
}
}
a {
color : var ( -- el - color - primary ) ;
}
}
li {
color : var ( -- next - bg - columnsMenuBarColor ) ;
width : 100 % ;
height : 50 px ;
text - align : center ;
display : flex ;
cursor : pointer ;
position : relative ;
z - index : 1 ;
li {
color : var ( -- next - bg - columnsMenuBarColor ) ;
width : 100 % ;
height : 50 px ;
text - align : center ;
display : flex ;
cursor : pointer ;
position : relative ;
z - index : 1 ;
& : hover {
@ extend . layout - columns - hover ;
}
& : hover {
@ extend . layout - columns - hover ;
}
. columns - vertical {
margin : auto ;
. columns - vertical {
margin : auto ;
. columns - vertical - title {
padding - top : 1 px ;
}
}
. columns - vertical - title {
padding - top : 1 px ;
}
}
. columns - horizontal {
display : flex ;
height : 50 px ;
width : 100 % ;
align - items : center ;
padding : 0 5 px ;
. columns - horizontal {
display : flex ;
height : 50 px ;
width : 100 % ;
align - items : center ;
padding : 0 5 px ;
i {
margin - right : 3 px ;
}
i {
margin - right : 3 px ;
}
a {
display : flex ;
a {
display : flex ;
. columns - horizontal - title {
padding - top : 1 px ;
}
}
}
. columns - horizontal - title {
padding - top : 1 px ;
}
}
}
a {
text - decoration : none ;
color : var ( -- next - bg - columnsMenuBarColor ) ;
}
}
a {
text - decoration : none ;
color : var ( -- next - bg - columnsMenuBarColor ) ;
}
}
. columns - round {
background : var ( -- el - color - primary ) ;
color : var ( -- el - color - white ) ;
position : absolute ;
left : 50 % ;
top : 2 px ;
height : 44 px ;
width : 65 px ;
transform : translateX ( - 50 % ) ;
z - index : 0 ;
transition : 0.3 s ease - in - out ;
border - radius : 5 px ;
}
. columns - round {
background : var ( -- el - color - primary ) ;
color : var ( -- el - color - white ) ;
position : absolute ;
left : 50 % ;
top : 2 px ;
height : 44 px ;
width : 65 px ;
transform : translateX ( - 50 % ) ;
z - index : 0 ;
transition : 0.3 s ease - in - out ;
border - radius : 5 px ;
}
. columns - card {
@ extend . columns - round ;
top : 0 ;
height : 50 px ;
width : 100 % ;
border - radius : 0 ;
}
}
. columns - card {
@ extend . columns - round ;
top : 0 ;
height : 50 px ;
width : 100 % ;
border - radius : 0 ;
}
}
}
< / style >