Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
B
basic-vue-admin
概览
概览
详情
活动
周期分析
版本库
存储库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
Basic
basic-vue-admin
Commits
cbcd9098
提交
cbcd9098
authored
12月 14, 2020
作者:
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wip(menu): perf menu
上级
f81c4019
隐藏空白字符变更
内嵌
并排
正在显示
13 个修改的文件
包含
411 行增加
和
351 行删除
+411
-351
AppLogo.vue
src/components/Application/src/AppLogo.vue
+2
-1
index.ts
src/components/Menu/index.ts
+3
-1
BasicMenu.vue
src/components/Menu/src/BasicMenu.vue
+196
-254
BasicMenuItem.vue
src/components/Menu/src/components/BasicMenuItem.vue
+39
-0
BasicSubMenuItem.vue
src/components/Menu/src/components/BasicSubMenuItem.vue
+53
-0
ExpandIcon.vue
src/components/Menu/src/components/ExpandIcon.vue
+43
-0
helper.ts
src/components/Menu/src/helper.ts
+0
-12
index.less
src/components/Menu/src/index.less
+42
-41
props.ts
src/components/Menu/src/props.ts
+22
-32
types.ts
src/components/Menu/src/types.ts
+6
-6
appEnum.ts
src/enums/appEnum.ts
+1
-1
index.less
src/layouts/default/tabs/index.less
+3
-3
menuHelper.ts
src/router/helper/menuHelper.ts
+1
-0
没有找到文件。
src/components/Application/src/AppLogo.vue
浏览文件 @
cbcd9098
...
...
@@ -66,8 +66,9 @@
.@
{
prefix-cls
}
{
display
:
flex
;
align-items
:
center
;
padding-left
:
12
px
;
padding-left
:
7
px
;
cursor
:
pointer
;
transition
:
all
0.2s
ease
;
&.collapsed-show-title
{
padding-left
:
20px
;
...
...
src/components/Menu/index.ts
浏览文件 @
cbcd9098
...
...
@@ -2,6 +2,8 @@ import { withInstall } from '../util';
import
{
createAsyncComponent
}
from
'/@/utils/factory/createAsyncComponent'
;
export
const
BasicMenu
=
createAsyncComponent
(()
=>
import
(
'./src/BasicMenu'
),
{
loading
:
false
});
export
const
BasicMenu
=
createAsyncComponent
(()
=>
import
(
'./src/BasicMenu.vue'
),
{
loading
:
false
,
});
withInstall
(
BasicMenu
);
src/components/Menu/src/BasicMenu.
tsx
→
src/components/Menu/src/BasicMenu.
vue
浏览文件 @
cbcd9098
import
'./index.less'
;
import
type
{
MenuState
}
from
'./types'
;
import
type
{
Menu
as
MenuType
}
from
'/@/router/types'
;
import
{
computed
,
defineComponent
,
unref
,
reactive
,
watch
,
toRefs
,
ComputedRef
,
ref
,
CSSProperties
,
}
from
'vue'
;
import
{
Menu
}
from
'ant-design-vue'
;
import
MenuContent
from
'./MenuContent'
;
// import { ScrollContainer } from '/@/components/Container';
// import { BasicArrow } from '/@/components/Basic';
import
{
MenuModeEnum
,
MenuTypeEnum
}
from
'/@/enums/menuEnum'
;
import
{
ThemeEnum
}
from
'/@/enums/appEnum'
;
import
{
appStore
}
from
'/@/store/modules/app'
;
import
{
useOpenKeys
}
from
'./useOpenKeys'
;
import
{
useRouter
}
from
'vue-router'
;
import
{
isFunction
}
from
'/@/utils/is'
;
import
{
getSlot
}
from
'/@/utils/helper/tsxHelper'
;
import
{
menuHasChildren
}
from
'./helper'
;
import
{
getCurrentParentPath
}
from
'/@/router/menus'
;
import
{
basicProps
}
from
'./props'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
REDIRECT_NAME
}
from
'/@/router/constant'
;
import
{
tabStore
}
from
'/@/store/modules/tab'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
export
default
defineComponent
({
name
:
'BasicMenu'
,
props
:
basicProps
,
emits
:
[
'menuClick'
],
setup
(
props
,
{
slots
,
emit
})
{
const
currentParentPath
=
ref
(
''
);
const
isClickGo
=
ref
(
false
);
const
menuState
=
reactive
<
MenuState
>
({
defaultSelectedKeys
:
[],
mode
:
props
.
mode
,
theme
:
computed
(()
=>
props
.
theme
)
as
ComputedRef
<
ThemeEnum
>
,
openKeys
:
[],
selectedKeys
:
[],
collapsedOpenKeys
:
[],
});
const
{
prefixCls
}
=
useDesign
(
'basic-menu'
);
const
{
items
,
mode
,
accordion
}
=
toRefs
(
props
);
const
{
getCollapsed
,
getIsHorizontal
,
getTopMenuAlign
,
getSplit
}
=
useMenuSetting
();
<
template
>
<slot
name=
"header"
v-if=
"!getIsHorizontal"
/>
<ScrollContainer
:class=
"`$
{prefixCls}-wrapper`" :style="getWrapperStyle">
<Menu
:selectedKeys=
"selectedKeys"
:defaultSelectedKeys=
"defaultSelectedKeys"
:mode=
"mode"
:openKeys=
"getOpenKeys"
:inlineIndent=
"inlineIndent"
:theme=
"theme"
@
openChange=
"handleOpenChange"
:class=
"getMenuClass"
@
click=
"handleMenuClick"
:subMenuOpenDelay=
"0.2"
v-bind=
"getInlineCollapseOptions"
>
<template
v-for=
"item in items"
:key=
"item.path"
>
<BasicSubMenuItem
:item=
"item"
:theme=
"theme"
:level=
"1"
:appendClass=
"appendClass"
:parentPath=
"currentParentPath"
:showTitle=
"showTitle"
:isHorizontal=
"isHorizontal"
/>
</
template
>
</Menu>
</ScrollContainer>
</template>
<
script
lang=
"ts"
>
import
type
{
MenuState
}
from
'./types'
;
import
{
computed
,
defineComponent
,
unref
,
reactive
,
watch
,
toRefs
,
ref
,
CSSProperties
,
}
from
'vue'
;
import
{
Menu
}
from
'ant-design-vue'
;
import
BasicSubMenuItem
from
'./components/BasicSubMenuItem.vue'
;
import
{
ScrollContainer
}
from
'/@/components/Container'
;
import
{
MenuModeEnum
,
MenuTypeEnum
}
from
'/@/enums/menuEnum'
;
import
{
appStore
}
from
'/@/store/modules/app'
;
import
{
useOpenKeys
}
from
'./useOpenKeys'
;
import
{
useRouter
}
from
'vue-router'
;
import
{
isFunction
}
from
'/@/utils/is'
;
import
{
getCurrentParentPath
}
from
'/@/router/menus'
;
import
{
basicProps
}
from
'./props'
;
import
{
useMenuSetting
}
from
'/@/hooks/setting/useMenuSetting'
;
import
{
REDIRECT_NAME
}
from
'/@/router/constant'
;
import
{
tabStore
}
from
'/@/store/modules/tab'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export
default
defineComponent
({
name
:
'BasicMenu'
,
components
:
{
Menu
,
ScrollContainer
,
BasicSubMenuItem
,
// BasicSubMenuItem: createAsyncComponent(() => import('./components/BasicSubMenuItem.vue')),
},
props
:
basicProps
,
emits
:
[
'menuClick'
],
setup
(
props
,
{
emit
})
{
const
currentParentPath
=
ref
(
''
);
const
isClickGo
=
ref
(
false
);
const
menuState
=
reactive
<
MenuState
>
({
defaultSelectedKeys
:
[],
openKeys
:
[],
selectedKeys
:
[],
collapsedOpenKeys
:
[],
});
const
{
prefixCls
}
=
useDesign
(
'basic-menu'
);
const
{
items
,
mode
,
accordion
}
=
toRefs
(
props
);
const
{
getCollapsed
,
getIsHorizontal
,
getTopMenuAlign
,
getSplit
}
=
useMenuSetting
();
const
{
currentRoute
}
=
useRouter
();
const
{
handleOpenChange
,
setOpenKeys
,
getOpenKeys
}
=
useOpenKeys
(
menuState
,
items
,
mode
,
accordion
);
const
{
currentRoute
}
=
useRouter
();
const
getMenuClass
=
computed
(()
=>
{
const
{
type
,
mode
}
=
props
;
return
[
prefixCls
,
`justify-
${
unref
(
getTopMenuAlign
)}
`
,
{
[
`
${
prefixCls
}
--hide-title`
]:
!
unref
(
showTitle
),
[
`
${
prefixCls
}
--collapsed-show-title`
]:
props
.
collapsedShowTitle
,
[
`
${
prefixCls
}
__second`
]:
!
props
.
isHorizontal
&&
appStore
.
getProjectConfig
.
menuSetting
.
split
,
[
`
${
prefixCls
}
__sidebar-hor`
]:
type
===
MenuTypeEnum
.
TOP_MENU
&&
mode
===
MenuModeEnum
.
HORIZONTAL
,
},
];
});
const
showTitle
=
computed
(()
=>
props
.
collapsedShowTitle
&&
unref
(
getCollapsed
));
const
getInlineCollapseOptions
=
computed
(()
=>
{
const
isInline
=
props
.
mode
===
MenuModeEnum
.
INLINE
;
const
inlineCollapseOptions
:
{
inlineCollapsed
?:
boolean
}
=
{};
if
(
isInline
)
{
inlineCollapseOptions
.
inlineCollapsed
=
unref
(
getCollapsed
);
}
return
inlineCollapseOptions
;
});
const
getWrapperStyle
=
computed
(
():
CSSProperties
=>
{
return
{
height
:
`calc(100% -
${
props
.
showLogo
?
'48px'
:
'0px'
}
)`
,
overflowY
:
'hidden'
,
};
}
);
const
{
handleOpenChange
,
setOpenKeys
,
getOpenKeys
}
=
useOpenKeys
(
menuState
,
items
,
mode
,
accordion
);
watch
(
()
=>
tabStore
.
getCurrentTab
,
()
=>
{
if
(
unref
(
currentRoute
).
name
===
REDIRECT_NAME
)
return
;
handleMenuChange
();
unref
(
getSplit
)
&&
getParentPath
();
}
);
const
getMenuClass
=
computed
(()
=>
{
const
{
type
}
=
props
;
const
{
mode
}
=
menuState
;
return
[
prefixCls
,
`justify-
${
unref
(
getTopMenuAlign
)}
`
,
{
[
`
${
prefixCls
}
--hide-title`
]:
!
unref
(
showTitle
),
[
`
${
prefixCls
}
--collapsed-show-title`
]:
props
.
collapsedShowTitle
,
[
`
${
prefixCls
}
__second`
]:
!
props
.
isHorizontal
&&
appStore
.
getProjectConfig
.
menuSetting
.
split
,
[
`
${
prefixCls
}
__sidebar-hor`
]:
type
===
MenuTypeEnum
.
TOP_MENU
&&
mode
===
MenuModeEnum
.
HORIZONTAL
,
watch
(
()
=>
props
.
items
,
()
=>
{
handleMenuChange
();
},
];
});
const
showTitle
=
computed
(()
=>
props
.
collapsedShowTitle
&&
unref
(
getCollapsed
));
const
getInlineCollapseOptions
=
computed
(()
=>
{
const
isInline
=
props
.
mode
===
MenuModeEnum
.
INLINE
;
const
inlineCollapseOptions
:
{
inlineCollapsed
?:
boolean
}
=
{};
if
(
isInline
)
{
inlineCollapseOptions
.
inlineCollapsed
=
unref
(
getCollapsed
);
}
return
inlineCollapseOptions
;
});
const
getWrapperStyle
=
computed
(
():
CSSProperties
=>
{
const
isHorizontal
=
unref
(
getIsHorizontal
)
||
getSplit
.
value
;
{
immediate
:
true
,
}
);
return
{
height
:
isHorizontal
?
'100%'
:
`calc(100% -
${
props
.
showLogo
?
'48px'
:
'0px'
}
)`
,
overflowY
:
isHorizontal
?
'hidden'
:
'auto'
,
};
}
);
getParentPath
();
watch
(
()
=>
tabStore
.
getCurrentTab
,
()
=>
{
if
(
unref
(
currentRoute
).
name
===
REDIRECT_NAME
)
return
;
handleMenuChange
();
unref
(
getSplit
)
&&
getParentPath
();
}
);
async
function
getParentPath
()
{
const
{
appendClass
}
=
props
;
if
(
!
appendClass
)
return
''
;
const
parentPath
=
await
getCurrentParentPath
(
unref
(
currentRoute
).
path
);
watch
(
()
=>
props
.
items
,
()
=>
{
handleMenuChange
();
},
{
immediate
:
true
,
currentParentPath
.
value
=
parentPath
;
}
);
getParentPath
();
async
function
getParentPath
()
{
const
{
appendClass
}
=
props
;
if
(
!
appendClass
)
return
''
;
const
parentPath
=
await
getCurrentParentPath
(
unref
(
currentRoute
).
path
);
currentParentPath
.
value
=
parentPath
;
}
async
function
handleMenuClick
({
key
,
keyPath
}:
{
key
:
string
;
keyPath
:
string
[]
})
{
const
{
beforeClickFn
}
=
props
;
if
(
beforeClickFn
&&
isFunction
(
beforeClickFn
))
{
const
flag
=
await
beforeClickFn
(
key
);
if
(
!
flag
)
return
;
async
function
handleMenuClick
({
key
,
keyPath
}:
{
key
:
string
;
keyPath
:
string
[]
})
{
const
{
beforeClickFn
}
=
props
;
if
(
beforeClickFn
&&
isFunction
(
beforeClickFn
))
{
const
flag
=
await
beforeClickFn
(
key
);
if
(
!
flag
)
return
;
}
emit
(
'menuClick'
,
key
);
isClickGo
.
value
=
true
;
menuState
.
openKeys
=
keyPath
;
menuState
.
selectedKeys
=
[
key
];
}
emit
(
'menuClick'
,
key
);
isClickGo
.
value
=
true
;
menuState
.
openKeys
=
keyPath
;
menuState
.
selectedKeys
=
[
key
];
}
function
handleMenuChange
()
{
if
(
unref
(
isClickGo
))
{
isClickGo
.
value
=
false
;
return
;
}
const
path
=
unref
(
currentRoute
).
path
;
if
(
menuState
.
mode
!==
MenuModeEnum
.
HORIZONTAL
)
{
setOpenKeys
(
path
);
function
handleMenuChange
()
{
if
(
unref
(
isClickGo
))
{
isClickGo
.
value
=
false
;
return
;
}
const
path
=
unref
(
currentRoute
).
path
;
if
(
props
.
mode
!==
MenuModeEnum
.
HORIZONTAL
)
{
setOpenKeys
(
path
);
}
menuState
.
selectedKeys
=
[
path
];
}
menuState
.
selectedKeys
=
[
path
];
}
// function renderExpandIcon({ key }: { key: string }) {
// const isOpen = getOpenKeys.value.includes(key);
// const collapsed = unref(getCollapsed);
// return (
// <BasicArrow
// expand={isOpen}
// bottom
// inset
// class={[
// `${prefixCls}__expand-icon`,
// {
// [`${prefixCls}__expand-icon--collapsed`]: collapsed,
// },
// ]}
// />
// );
// }
function
renderItem
(
menu
:
MenuType
,
level
=
1
)
{
return
!
menuHasChildren
(
menu
)
?
renderMenuItem
(
menu
,
level
)
:
renderSubMenu
(
menu
,
level
);
}
function
renderMenuItem
(
menu
:
MenuType
,
level
:
number
)
{
const
{
appendClass
}
=
props
;
const
isAppendActiveCls
=
appendClass
&&
level
===
1
&&
menu
.
path
===
unref
(
currentParentPath
);
const
levelCls
=
[
`
${
prefixCls
}
-item__level
${
level
}
`
,
`
${
menuState
.
theme
}
`
,
{
'top-active-menu'
:
isAppendActiveCls
,
},
];
return
(
<
Menu
.
Item
key=
{
menu
.
path
}
class=
{
levelCls
}
>
{
()
=>
[
<
MenuContent
item=
{
menu
}
showTitle=
{
unref
(
showTitle
)
}
isHorizontal=
{
props
.
isHorizontal
}
/>,
]
}
</
Menu
.
Item
>
);
}
function
renderSubMenu
(
menu
:
MenuType
,
level
:
number
)
{
const
levelCls
=
`
${
prefixCls
}
-item__level
${
level
}
${
menuState
.
theme
}
`
;
return
(
<
Menu
.
SubMenu
key=
{
menu
.
path
}
class=
{
levelCls
}
>
{
{
title
:
()
=>
[
<
MenuContent
showTitle=
{
unref
(
showTitle
)
}
item=
{
menu
}
isHorizontal=
{
props
.
isHorizontal
}
/>,
],
// expandIcon: renderExpandIcon,
default
:
()
=>
(
menu
.
children
||
[]).
map
((
item
)
=>
renderItem
(
item
,
level
+
1
)),
}
}
</
Menu
.
SubMenu
>
);
}
function
renderMenu
()
{
const
{
selectedKeys
,
defaultSelectedKeys
,
mode
,
theme
}
=
menuState
;
return
(
<
Menu
selectedKeys=
{
selectedKeys
}
defaultSelectedKeys=
{
defaultSelectedKeys
}
mode=
{
mode
}
openKeys=
{
unref
(
getOpenKeys
)
}
inlineIndent=
{
props
.
inlineIndent
}
theme=
{
unref
(
theme
)
}
onOpenChange=
{
handleOpenChange
}
class=
{
unref
(
getMenuClass
)
}
onClick=
{
handleMenuClick
}
subMenuOpenDelay=
{
0.2
}
{
...
unref
(
getInlineCollapseOptions
)}
>
{
{
default
:
()
=>
unref
(
items
).
map
((
item
)
=>
renderItem
(
item
)),
}
}
</
Menu
>
);
}
return
()
=>
{
return
(
<>
{
!
unref
(
getIsHorizontal
)
&&
getSlot
(
slots
,
'header'
)
}
<
div
class=
{
`${prefixCls}-wrapper`
}
style=
{
unref
(
getWrapperStyle
)
}
>
{
renderMenu
()
}
</
div
>
</>
);
};
},
});
return
{
prefixCls
,
getIsHorizontal
,
getWrapperStyle
,
handleMenuClick
,
getInlineCollapseOptions
,
getMenuClass
,
handleOpenChange
,
getOpenKeys
,
currentParentPath
,
showTitle
,
...
toRefs
(
menuState
),
};
},
});
</
script
>
<
style
lang=
"less"
>
@import
'./index.less'
;
</
style
>
src/components/Menu/src/components/BasicMenuItem.vue
0 → 100644
浏览文件 @
cbcd9098
<
template
>
<MenuItem
:class=
"getLevelClass"
>
<MenuContent
v-bind=
"$props"
:item=
"item"
/>
</MenuItem>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
computed
}
from
'vue'
;
import
{
Menu
}
from
'ant-design-vue'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
itemProps
}
from
'../props'
;
import
MenuContent
from
'../MenuContent'
;
export
default
defineComponent
({
name
:
'BasicMenuItem'
,
components
:
{
MenuItem
:
Menu
.
Item
,
MenuContent
},
props
:
itemProps
,
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'basic-menu-item'
);
const
getLevelClass
=
computed
(()
=>
{
const
{
appendClass
,
level
,
item
,
parentPath
,
theme
}
=
props
;
const
isAppendActiveCls
=
appendClass
&&
level
===
1
&&
item
.
path
===
parentPath
;
const
levelCls
=
[
`
${
prefixCls
}
__level
${
level
}
`
,
theme
,
{
'top-active-menu'
:
isAppendActiveCls
,
},
];
return
levelCls
;
});
return
{
prefixCls
,
getLevelClass
,
};
},
});
</
script
>
src/components/Menu/src/components/BasicSubMenuItem.vue
0 → 100644
浏览文件 @
cbcd9098
<
template
>
<BasicMenuItem
v-if=
"!menuHasChildren(item)"
v-bind=
"$props"
/>
<SubMenu
v-else
:class=
"[`$
{prefixCls}__level${level}`, theme]">
<template
#
title
>
<MenuContent
v-bind=
"$props"
:item=
"item"
/>
</
template
>
<!-- <template #expandIcon="{ key }">
<ExpandIcon :key="key" />
</template> -->
<
template
v-for=
"childrenItem in item.children || []"
:key=
"childrenItem.path"
>
<BasicSubMenuItem
v-bind=
"$props"
:item=
"childrenItem"
:level=
"level + 1"
/>
</
template
>
</SubMenu>
</template>
<
script
lang=
"ts"
>
import
type
{
Menu
as
MenuType
}
from
'/@/router/types'
;
import
{
defineComponent
}
from
'vue'
;
import
{
Menu
}
from
'ant-design-vue'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
itemProps
}
from
'../props'
;
import
BasicMenuItem
from
'./BasicMenuItem.vue'
;
import
MenuContent
from
'../MenuContent'
;
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export
default
defineComponent
({
name
:
'BasicSubMenuItem'
,
components
:
{
BasicMenuItem
,
SubMenu
:
Menu
.
SubMenu
,
MenuItem
:
Menu
.
Item
,
MenuContent
,
// ExpandIcon: createAsyncComponent(() => import('./ExpandIcon.vue')),
},
props
:
itemProps
,
setup
()
{
const
{
prefixCls
}
=
useDesign
(
'basic-menu-item'
);
function
menuHasChildren
(
menuTreeItem
:
MenuType
):
boolean
{
return
(
Reflect
.
has
(
menuTreeItem
,
'children'
)
&&
!!
menuTreeItem
.
children
&&
menuTreeItem
.
children
.
length
>
0
);
}
return
{
prefixCls
,
menuHasChildren
,
};
},
});
</
script
>
src/components/Menu/src/components/ExpandIcon.vue
0 → 100644
浏览文件 @
cbcd9098
<
template
>
<BasicArrow
:expand=
"getIsOpen"
bottom
inset
:class=
"getWrapperClass"
/>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
,
PropType
,
computed
}
from
'vue'
;
import
{
useDesign
}
from
'/@/hooks/web/useDesign'
;
import
{
BasicArrow
}
from
'/@/components/Basic'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
export
default
defineComponent
({
name
:
'BasicMenuItem'
,
components
:
{
BasicArrow
},
props
:
{
key
:
propTypes
.
string
,
openKeys
:
{
type
:
Array
as
PropType
<
string
[]
>
,
default
:
[],
},
collapsed
:
propTypes
.
bool
,
},
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'basic-menu'
);
const
getIsOpen
=
computed
(()
=>
{
return
props
.
openKeys
.
includes
(
props
.
key
);
});
const
getWrapperClass
=
computed
(()
=>
{
return
[
`
${
prefixCls
}
__expand-icon`
,
{
[
`
${
prefixCls
}
__expand-icon--collapsed`
]:
props
.
collapsed
,
},
];
});
return
{
prefixCls
,
getIsOpen
,
getWrapperClass
,
};
},
});
</
script
>
src/components/Menu/src/helper.ts
deleted
100644 → 0
浏览文件 @
f81c4019
import
type
{
Menu
as
MenuType
}
from
'/@/router/types'
;
/**
* @description: Whether the menu has child nodes
*/
export
function
menuHasChildren
(
menuTreeItem
:
MenuType
):
boolean
{
return
(
Reflect
.
has
(
menuTreeItem
,
'children'
)
&&
!!
menuTreeItem
.
children
&&
menuTreeItem
.
children
.
length
>
0
);
}
src/components/Menu/src/index.less
浏览文件 @
cbcd9098
...
...
@@ -4,6 +4,7 @@
.active-style() {
color: @white;
// background: @primary-color !important;
background: linear-gradient(
118deg,
rgba(@primary-color, 0.8),
...
...
@@ -27,6 +28,7 @@
// right: 16px;
// width: 10px;
// transform-origin: none;
// opacity: 0.45;
// span[role='img'] {
// margin-right: 0;
...
...
@@ -52,9 +54,9 @@
> .ant-menu-item-group-list
> .ant-menu-submenu
> .ant-menu-submenu-title,
&.ant-menu-inline-collapsed
> .ant-menu-submenu >
.ant-menu-submenu-title {
padding-right:
20
px !important;
padding-left:
20
px !important;
&.ant-menu-inline-collapsed .ant-menu-submenu-title {
padding-right:
16
px !important;
padding-left:
16
px !important;
}
}
...
...
@@ -87,32 +89,33 @@
}
}
//
.ant-menu-item {
//
transition: unset;
//
}
.ant-menu-item {
transition: unset;
}
// scrollbar -s tart
&-wrapper {
/* 滚动槽 */
&::-webkit-scrollbar {
width: 5px;
height: 5px;
}
// &-wrapper {
&::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0);
}
/* 滚动槽 */
// &::-webkit-scrollbar {
// width: 5px;
// height: 5px;
// }
&::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
}
// &::-webkit-scrollbar-track {
// background: rgba(0, 0, 0, 0);
// }
::-webkit-scrollbar-thumb:hover {
background: @border-color-dark;
}
}
// &::-webkit-scrollbar-thumb {
// background: rgba(255, 255, 255, 0.2);
// border-radius: 3px;
// box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
// }
// ::-webkit-scrollbar-thumb:hover {
// background: @border-color-dark;
// }
// }
// scrollbar end
...
...
@@ -225,14 +228,6 @@
}
}
&:not(.@{basic-menu-prefix-cls}__sidebar-hor).ant-menu-inline-collapsed {
.@{basic-menu-prefix-cls}-item__level1 {
> div {
align-items: center;
}
}
}
&.ant-menu-dark:not(.@{basic-menu-prefix-cls}__sidebar-hor):not(.@{basic-menu-prefix-cls}__second) {
// Reset menu item row height
.ant-menu-item:not(.@{basic-menu-prefix-cls}-item__level1),
...
...
@@ -255,10 +250,6 @@
background: @sider-dark-bg-color;
.active-menu-style();
// .menu-item-icon.app-iconify {
// display: inline-block !important;
// }
.ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
.ant-menu-submenu-selected.@{basic-menu-prefix-cls}-menu-item__level1 {
color: @white;
...
...
@@ -304,10 +295,6 @@
overflow: hidden;
border-right: none;
// .menu-item-icon.app-iconify {
// display: inline-block !important;
// }
.ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
.ant-menu-submenu-selected.@{basic-menu-prefix-cls}-menu-item__level1 {
color: @primary-color;
...
...
@@ -332,6 +319,7 @@
align-items: center;
}
}
.@{basic-menu-prefix-cls}__tag {
position: absolute;
top: calc(50% - 8px);
...
...
@@ -368,6 +356,20 @@
background: @warning-color;
}
}
.ant-menu-submenu,
.ant-menu-submenu-inline {
transition: unset;
}
// .ant-menu-submenu-arrow {
// transition: all 0.15s ease 0s;
// }
.ant-menu-inline.ant-menu-sub {
box-shadow: unset !important;
transition: unset;
}
}
.ant-menu-dark {
...
...
@@ -375,7 +377,6 @@
> ul {
background: @sider-dark-bg-color;
}
.active-menu-style();
}
}
...
...
src/components/Menu/src/props.ts
浏览文件 @
cbcd9098
...
...
@@ -3,57 +3,47 @@ import type { PropType } from 'vue';
import
{
MenuModeEnum
,
MenuTypeEnum
}
from
'/@/enums/menuEnum'
;
import
{
ThemeEnum
}
from
'/@/enums/appEnum'
;
import
{
propTypes
}
from
'/@/utils/propTypes'
;
export
const
basicProps
=
{
items
:
{
type
:
Array
as
PropType
<
Menu
[]
>
,
default
:
()
=>
[],
},
appendClass
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
appendClass
:
propTypes
.
bool
,
collapsedShowTitle
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
collapsedShowTitle
:
propTypes
.
bool
,
// 最好是4 倍数
inlineIndent
:
{
type
:
Number
as
PropType
<
number
>
,
default
:
20
,
},
inlineIndent
:
propTypes
.
number
.
def
(
20
),
// 菜单组件的mode属性
mode
:
{
type
:
String
as
PropType
<
MenuModeEnum
>
,
default
:
MenuModeEnum
.
INLINE
,
},
showLogo
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
showLogo
:
propTypes
.
bool
,
type
:
{
type
:
String
as
PropType
<
MenuTypeEnum
>
,
default
:
MenuTypeEnum
.
MIX
,
},
theme
:
{
type
:
String
as
PropType
<
string
>
,
default
:
ThemeEnum
.
DARK
,
},
inlineCollapsed
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
theme
:
propTypes
.
string
.
def
(
ThemeEnum
.
DARK
),
inlineCollapsed
:
propTypes
.
bool
,
isHorizontal
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
accordion
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
true
,
},
isHorizontal
:
propTypes
.
bool
,
accordion
:
propTypes
.
bool
.
def
(
true
),
beforeClickFn
:
{
type
:
Function
as
PropType
<
(
key
:
string
)
=>
Promise
<
boolean
>>
,
},
};
export
const
itemProps
=
{
item
:
{
type
:
Object
as
PropType
<
Menu
>
,
default
:
{},
},
level
:
propTypes
.
number
,
theme
:
propTypes
.
oneOf
([
'dark'
,
'light'
]),
appendClass
:
propTypes
.
bool
,
parentPath
:
propTypes
.
string
,
showTitle
:
propTypes
.
bool
,
isHorizontal
:
propTypes
.
bool
,
};
src/components/Menu/src/types.ts
浏览文件 @
cbcd9098
import
{
ComputedRef
}
from
'vue'
;
import
{
ThemeEnum
}
from
'/@/enums/appEnum'
;
import
{
MenuModeEnum
}
from
'/@/enums/menuEnum'
;
//
import { ComputedRef } from 'vue';
//
import { ThemeEnum } from '/@/enums/appEnum';
//
import { MenuModeEnum } from '/@/enums/menuEnum';
export
interface
MenuState
{
// 默认选中的列表
defaultSelectedKeys
:
string
[];
// 模式
mode
:
MenuModeEnum
;
//
mode: MenuModeEnum;
// 主题
theme
:
ComputedRef
<
ThemeEnum
>
|
ThemeEnum
;
//
//
主题
//
theme: ComputedRef<ThemeEnum> | ThemeEnum;
// 缩进
inlineIndent
?:
number
;
...
...
src/enums/appEnum.ts
浏览文件 @
cbcd9098
export
const
SIDE_BAR_MINI_WIDTH
=
5
8
;
export
const
SIDE_BAR_MINI_WIDTH
=
4
8
;
export
const
SIDE_BAR_SHOW_TIT_MINI_WIDTH
=
80
;
export
enum
ContentEnum
{
...
...
src/layouts/default/tabs/index.less
浏览文件 @
cbcd9098
...
...
@@ -34,9 +34,9 @@
border:
1
px
solid
darken
(
@border-color-light
,
6
%
);
transition:
none
;
&:
not
(.
ant-tabs-tab-active
)
::
before
{
&:
not
(.
ant-tabs-tab-active
)
::
after
{
position:
absolute
;
top
:
-1
px
;
bottom
:
-1
px
;
left:
50
%
;
width:
100
%
;
height:
2
px
;
...
...
@@ -53,7 +53,7 @@
opacity:
1
;
}
&:
not
(.
ant-tabs-tab-active
)
::
before
{
&:
not
(.
ant-tabs-tab-active
)
::
after
{
opacity:
1
;
transform:
translate
(
-50
%,
0
)
scaleX
(
1
);
transition:
all
0.3
s
ease-in-out
;
...
...
src/router/helper/menuHelper.ts
浏览文件 @
cbcd9098
...
...
@@ -42,6 +42,7 @@ export function transformMenuModule(menuModule: MenuModule): Menu {
forEach
(
menuList
,
(
m
)
=>
{
!
isUrl
(
m
.
path
)
&&
joinParentPath
(
menuList
,
m
);
});
return
menuList
[
0
];
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论