mirror of
https://github.com/XiaoDaiGua-Ray/ray-template.git
synced 2025-04-04 22:28:40 +08:00
141 lines
4.3 KiB
TypeScript
141 lines
4.3 KiB
TypeScript
import './index.scss'
|
|
|
|
import { NMenu, NLayoutSider, NDrawer } from 'naive-ui'
|
|
import SiderBarLogo from './components/SiderBarLogo'
|
|
|
|
import { LAYOUT_SIDER_REF } from '@/app-config'
|
|
import { useDevice } from '@/hooks'
|
|
import { getVariableToRefs, setVariable } from '@/global-variable'
|
|
import { useMenuGetters, useMenuActions, useSettingGetters } from '@/store'
|
|
|
|
import type { MenuInst } from 'naive-ui'
|
|
import type { NaiveMenuOptions } from '@/types'
|
|
import type { AppMenuOption } from '@/types'
|
|
|
|
export default defineComponent({
|
|
name: 'AppMenu',
|
|
setup() {
|
|
const menuRef = ref<MenuInst | null>(null)
|
|
|
|
const { changeMenuModelValue, collapsedMenu, updateMenuState } =
|
|
useMenuActions()
|
|
const { getMenuConfig } = useSettingGetters()
|
|
const { getMenuOptions, getCollapsed, getMenuKey } = useMenuGetters()
|
|
const modelMenuKey = computed({
|
|
get: () => {
|
|
// eslint-disable-next-line vue/no-async-in-computed-properties
|
|
setTimeout(() => {
|
|
/**
|
|
*
|
|
* @description
|
|
* 禁用该 eslint 规则,因为在 computed 中使用了异步操作。
|
|
* 该规则只是为了避免异步的 computed get 获取值出现问题;
|
|
* 但是,在这里获取值的操作是同步行为,只是为了在获取值以后将对应菜单项展开;
|
|
* 所以,这里不会出现异步获取值的问题,所以可以禁用该规则。
|
|
*/
|
|
showMenuOption()
|
|
}, 300)
|
|
|
|
return getMenuKey.value
|
|
},
|
|
set: () => {
|
|
if (isTabletOrSmaller.value) {
|
|
setVariable('globalDrawerValue', false)
|
|
}
|
|
},
|
|
})
|
|
const { isTabletOrSmaller } = useDevice({
|
|
observer: (isSmaller) => {
|
|
if (isSmaller) {
|
|
// 避免菜单折叠时,在小尺寸屏幕导致菜单显示不完整
|
|
updateMenuState('collapsed', false)
|
|
}
|
|
},
|
|
})
|
|
const modelGlobalDrawerValue = computed({
|
|
get: () => getVariableToRefs('globalDrawerValue').value,
|
|
set: (val) => {
|
|
setVariable('globalDrawerValue', val)
|
|
},
|
|
})
|
|
|
|
/**
|
|
*
|
|
* @description
|
|
* 手动展开当前激活菜单项。
|
|
*/
|
|
const showMenuOption = () => {
|
|
const key = modelMenuKey.value
|
|
|
|
if (key !== void 0 && key !== null) {
|
|
nextTick(() => menuRef.value?.showOption?.(key))
|
|
}
|
|
}
|
|
|
|
const BasicMenu = () => (
|
|
<NLayoutSider
|
|
class="app-menu__sider"
|
|
showTrigger={!isTabletOrSmaller.value}
|
|
collapseMode={getMenuConfig.value.collapsedMode}
|
|
collapsedWidth={getMenuConfig.value.collapsedWidth}
|
|
onUpdateCollapsed={collapsedMenu.bind(this)}
|
|
width={getMenuConfig.value.menuWidth}
|
|
nativeScrollbar={getMenuConfig.value.nativeScrollbar}
|
|
ref={LAYOUT_SIDER_REF}
|
|
collapsed={getCollapsed.value}
|
|
onExpand={() => {
|
|
updateMenuState('collapsed', false)
|
|
}}
|
|
onCollapse={() => {
|
|
updateMenuState('collapsed', true)
|
|
}}
|
|
inverted={getMenuConfig.value.inverted}
|
|
>
|
|
{getMenuConfig.value.menuSiderBarLogo ? (
|
|
<SiderBarLogo collapsed={getCollapsed.value} />
|
|
) : null}
|
|
<NMenu
|
|
ref={menuRef}
|
|
class="r-menu--app"
|
|
keyField="fullPath"
|
|
v-model:value={modelMenuKey.value}
|
|
options={getMenuOptions.value as NaiveMenuOptions[]}
|
|
indent={getMenuConfig.value.collapsedIndent}
|
|
collapsed={getCollapsed.value}
|
|
collapsedIconSize={getMenuConfig.value.collapsedIconSize}
|
|
collapsedWidth={getMenuConfig.value.collapsedWidth}
|
|
onUpdateValue={(key, op) => {
|
|
changeMenuModelValue(key, op as unknown as AppMenuOption)
|
|
}}
|
|
accordion={getMenuConfig.value.accordion}
|
|
iconSize={getMenuConfig.value.iconSize}
|
|
inverted={getMenuConfig.value.inverted}
|
|
/>
|
|
</NLayoutSider>
|
|
)
|
|
|
|
return {
|
|
isTabletOrSmaller,
|
|
BasicMenu,
|
|
modelGlobalDrawerValue,
|
|
}
|
|
},
|
|
render() {
|
|
const { isTabletOrSmaller, BasicMenu } = this
|
|
|
|
return !isTabletOrSmaller ? (
|
|
<BasicMenu />
|
|
) : (
|
|
<NDrawer
|
|
class="app-menu__drawer"
|
|
v-model:show={this.modelGlobalDrawerValue}
|
|
placement="left"
|
|
displayDirective="show"
|
|
autoFocus={false}
|
|
>
|
|
<BasicMenu />
|
|
</NDrawer>
|
|
)
|
|
},
|
|
})
|