You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

188 lines
4.7 KiB

2 years ago
<script lang="tsx">
import type { CSSProperties } from 'vue'
import { computed, defineComponent, toRef, unref } from 'vue'
import { useSplitMenu } from './useLayoutMenu'
2 years ago
import { BasicMenu } from '@/components/Menu'
import { SimpleMenu } from '@/components/SimpleMenu'
import { AppLogo } from '@/components/Application'
import { MenuModeEnum, MenuSplitTyeEnum } from '@/enums/menuEnum'
import { useMenuSetting } from '@/hooks/setting/useMenuSetting'
import { ScrollContainer } from '@/components/Container'
import { useGo } from '@/hooks/web/usePage'
import { openWindow } from '@/utils'
import { propTypes } from '@/utils/propTypes'
import { isUrl } from '@/utils/is'
import { useRootSetting } from '@/hooks/setting/useRootSetting'
import { useAppInject } from '@/hooks/web/useAppInject'
import { useDesign } from '@/hooks/web/useDesign'
export default defineComponent({
name: 'LayoutMenu',
props: {
theme: propTypes.oneOf(['light', 'dark']),
splitType: {
type: Number as PropType<MenuSplitTyeEnum>,
default: MenuSplitTyeEnum.NONE,
2 years ago
},
isHorizontal: propTypes.bool,
// menu Mode
menuMode: {
type: [String] as PropType<Nullable<MenuModeEnum>>,
default: '',
},
2 years ago
},
setup(props) {
const go = useGo()
const {
getMenuMode,
getMenuType,
getMenuTheme,
getCollapsed,
getCollapsedShowTitle,
getAccordion,
getIsHorizontal,
getIsSidebarType,
getSplit,
2 years ago
} = useMenuSetting()
const { getShowLogo } = useRootSetting()
const { prefixCls } = useDesign('layout-menu')
const { menusRef } = useSplitMenu(toRef(props, 'splitType'))
const { getIsMobile } = useAppInject()
const getComputedMenuMode = computed(() => (unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)))
const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme))
const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType))
const getUseScroll = computed(() => {
return (
!unref(getIsHorizontal)
&& (unref(getIsSidebarType) || props.splitType === MenuSplitTyeEnum.LEFT || props.splitType === MenuSplitTyeEnum.NONE)
2 years ago
)
})
const getWrapperStyle = computed((): CSSProperties => {
return {
height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
2 years ago
}
})
const getLogoClass = computed(() => {
return [
`${prefixCls}-logo`,
unref(getComputedMenuTheme),
{
[`${prefixCls}--mobile`]: unref(getIsMobile),
},
2 years ago
]
})
const getCommonProps = computed(() => {
const menus = unref(menusRef)
return {
menus,
beforeClickFn: beforeMenuClickFn,
items: menus,
theme: unref(getComputedMenuTheme),
accordion: unref(getAccordion),
collapse: unref(getCollapsed),
collapsedShowTitle: unref(getCollapsedShowTitle),
onMenuClick: handleMenuClick,
2 years ago
}
})
/**
* click menu
2 years ago
* @param path
2 years ago
*/
function handleMenuClick(path: string) {
go(path)
}
/**
* before click menu
2 years ago
* @param path
2 years ago
*/
async function beforeMenuClickFn(path: string) {
if (!isUrl(path))
2 years ago
return true
2 years ago
openWindow(path)
return false
}
function renderHeader() {
if (!unref(getIsShowLogo) && !unref(getIsMobile))
return null
2 years ago
return <AppLogo showTitle={!unref(getCollapsed)} class={unref(getLogoClass)} theme={unref(getComputedMenuTheme)} />
}
function renderMenu() {
const { menus, ...menuProps } = unref(getCommonProps)
if (!menus || !menus.length)
return null
return !props.isHorizontal
? (
2 years ago
<SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menus} />
)
: (
2 years ago
<BasicMenu
{...(menuProps as any)}
isHorizontal={props.isHorizontal}
type={unref(getMenuType)}
showLogo={unref(getIsShowLogo)}
mode={unref(getComputedMenuMode as any)}
items={menus}
/>
)
2 years ago
}
return () => {
return (
<>
{renderHeader()}
{unref(getUseScroll) ? <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer> : renderMenu()}
</>
)
}
},
2 years ago
})
</script>
2 years ago
<style lang="less">
@prefix-cls: ~'@{namespace}-layout-menu';
@logo-prefix-cls: ~'@{namespace}-app-logo';
.@{prefix-cls} {
&-logo {
height: @header-height;
padding: 10px 4px 10px 10px;
img {
width: @logo-width;
height: @logo-width;
}
}
&--mobile {
.@{logo-prefix-cls} {
&__title {
opacity: 1;
2 years ago
}
}
}
}
</style>