197 lines
5.8 KiB
Vue
197 lines
5.8 KiB
Vue
<script lang="tsx">
|
||
import type { PropType, CSSProperties } from 'vue';
|
||
|
||
import { computed, defineComponent, unref, toRef } from 'vue';
|
||
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 { useSplitMenu } from './useLayoutMenu';
|
||
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';
|
||
import { useLocaleStore } from '/@/store/modules/locale';
|
||
|
||
export default defineComponent({
|
||
name: 'LayoutMenu',
|
||
props: {
|
||
theme: propTypes.oneOf(['light', 'dark']),
|
||
|
||
splitType: {
|
||
type: Number as PropType<MenuSplitTyeEnum>,
|
||
default: MenuSplitTyeEnum.NONE,
|
||
},
|
||
|
||
isHorizontal: propTypes.bool,
|
||
// menu Mode
|
||
menuMode: {
|
||
type: [String] as PropType<Nullable<MenuModeEnum>>,
|
||
default: '',
|
||
},
|
||
},
|
||
setup(props) {
|
||
const go = useGo();
|
||
|
||
const {
|
||
getMenuMode,
|
||
getMenuType,
|
||
getMenuTheme,
|
||
getCollapsed,
|
||
getCollapsedShowTitle,
|
||
getAccordion,
|
||
getIsHorizontal,
|
||
getIsSidebarType,
|
||
getSplit,
|
||
} = 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)
|
||
);
|
||
});
|
||
|
||
const getWrapperStyle = computed((): CSSProperties => {
|
||
return {
|
||
height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
|
||
};
|
||
});
|
||
|
||
const getLogoClass = computed(() => {
|
||
return [
|
||
`${prefixCls}-logo`,
|
||
unref(getComputedMenuTheme),
|
||
{
|
||
[`${prefixCls}--mobile`]: unref(getIsMobile),
|
||
},
|
||
];
|
||
});
|
||
|
||
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,
|
||
};
|
||
});
|
||
/**
|
||
* click menu
|
||
* @param menu
|
||
*/
|
||
//update-begin-author:taoyan date:2022-6-1 for: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
|
||
const localeStore = useLocaleStore();
|
||
function handleMenuClick(path: string, item) {
|
||
if (item) {
|
||
localeStore.setPathTitle(path, item.title || '');
|
||
}
|
||
go(path);
|
||
}
|
||
//update-end-author:taoyan date:2022-6-1 for: VUEN-1144 online 配置成菜单后,打开菜单,显示名称未展示为菜单名称
|
||
|
||
/**
|
||
* before click menu
|
||
* @param menu
|
||
*/
|
||
async function beforeMenuClickFn(path: string) {
|
||
if (!isUrl(path)) {
|
||
return true;
|
||
}
|
||
openWindow(path);
|
||
return false;
|
||
}
|
||
|
||
function renderHeader() {
|
||
if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null;
|
||
|
||
return <AppLogo showTitle={!unref(getCollapsed)} class={unref(getLogoClass)} theme={unref(getComputedMenuTheme)} />;
|
||
}
|
||
|
||
function renderMenu() {
|
||
const { menus, ...menuProps } = unref(getCommonProps);
|
||
// console.log(menus);
|
||
if (!menus || !menus.length) return null;
|
||
return !props.isHorizontal ? (
|
||
<SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menus} />
|
||
) : (
|
||
<BasicMenu
|
||
{...(menuProps as any)}
|
||
isHorizontal={props.isHorizontal}
|
||
type={unref(getMenuType)}
|
||
showLogo={unref(getIsShowLogo)}
|
||
mode={unref(getComputedMenuMode as any)}
|
||
items={menus}
|
||
/>
|
||
);
|
||
}
|
||
|
||
return () => {
|
||
return (
|
||
<>
|
||
{renderHeader()}
|
||
{unref(getUseScroll) ? <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer> : renderMenu()}
|
||
</>
|
||
);
|
||
};
|
||
},
|
||
});
|
||
</script>
|
||
<style lang="less" scoped>
|
||
// update-begin--author:liaozhiyang---date:20230803---for:【QQYUN-5872】菜单优化,上下滚动条去掉
|
||
.scroll-container :deep(.scrollbar__bar) {
|
||
display: none;
|
||
}
|
||
// update-end--author:liaozhiyang---date:20230803---for:【QQYUN-5872】菜单优化,上下滚动条去掉
|
||
</style>
|
||
<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;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|