|
|
@@ -1,197 +1,227 @@
|
|
|
<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';
|
|
|
-
|
|
|
- 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: '',
|
|
|
- },
|
|
|
+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 { getChildrenMenus } from '/@/router/menus';
|
|
|
+
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: 'LayoutMenu',
|
|
|
+ props: {
|
|
|
+ theme: propTypes.oneOf(['light', 'dark']),
|
|
|
+
|
|
|
+ splitType: {
|
|
|
+ type: Number as PropType<MenuSplitTyeEnum>,
|
|
|
+ default: MenuSplitTyeEnum.NONE,
|
|
|
},
|
|
|
- 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)
|
|
|
+
|
|
|
+ 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 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
|
|
|
- */
|
|
|
-
|
|
|
- function handleMenuClick(path: string) {
|
|
|
- go(path);
|
|
|
+ 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 sjl注释掉的
|
|
|
+ * @param menu
|
|
|
+ */
|
|
|
+
|
|
|
+ // function handleMenuClick(path: string) {
|
|
|
+ // go(path);
|
|
|
+ // }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * before click menu
|
|
|
+ * @param menu
|
|
|
+ */
|
|
|
+ async function beforeMenuClickFn(path: string) {
|
|
|
+ if (!isUrl(path)) {
|
|
|
+ return true;
|
|
|
}
|
|
|
+ openWindow(path);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 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;
|
|
|
|
|
|
- function renderHeader() {
|
|
|
- if (!unref(getIsShowLogo) && !unref(getIsMobile)) return null;
|
|
|
+ return (
|
|
|
+ <AppLogo
|
|
|
+ showTitle={!unref(getCollapsed)}
|
|
|
+ class={unref(getLogoClass)}
|
|
|
+ theme={unref(getComputedMenuTheme)}
|
|
|
+ />
|
|
|
+ );
|
|
|
+ }
|
|
|
|
|
|
- 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}
|
|
|
+ isHorizontal={props.isHorizontal}
|
|
|
+ type={unref(getMenuType)}
|
|
|
+ showLogo={unref(getIsShowLogo)}
|
|
|
+ mode={unref(getComputedMenuMode)}
|
|
|
+ items={menus}
|
|
|
+ />
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ const projectStore = useMenuSetting();
|
|
|
+ const IS_DIR_MENU_TYPE = '0';
|
|
|
+ /**
|
|
|
+ * click menu
|
|
|
+ * @param menu
|
|
|
+ */
|
|
|
+ async function handleMenuClick(path: string) {
|
|
|
+ const currentMenu = unref(menusRef).find((item) => item.path === path);
|
|
|
+
|
|
|
+ if (unref(projectStore.getIsMixMode) && currentMenu?.meta?.menuType === IS_DIR_MENU_TYPE) {
|
|
|
+ const children = await getChildrenMenus(path);
|
|
|
+ if (children && children.length) {
|
|
|
+ goFirst(children);
|
|
|
+ return;
|
|
|
+ }
|
|
|
}
|
|
|
+ go(path);
|
|
|
+ }
|
|
|
|
|
|
- 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}
|
|
|
- isHorizontal={props.isHorizontal}
|
|
|
- type={unref(getMenuType)}
|
|
|
- showLogo={unref(getIsShowLogo)}
|
|
|
- mode={unref(getComputedMenuMode)}
|
|
|
- items={menus}
|
|
|
- />
|
|
|
- );
|
|
|
+ function goFirst(children) {//sjl,默认打开第一个菜单
|
|
|
+ const item = children[0];
|
|
|
+ if (item && item.children && item.children.length) {
|
|
|
+ goFirst(item.children);
|
|
|
+ } else {
|
|
|
+ go(item.path);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- return () => {
|
|
|
- return (
|
|
|
- <>
|
|
|
- {renderHeader()}
|
|
|
- {unref(getUseScroll) ? (
|
|
|
- <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer>
|
|
|
- ) : (
|
|
|
- renderMenu()
|
|
|
- )}
|
|
|
- </>
|
|
|
- );
|
|
|
- };
|
|
|
- },
|
|
|
- });
|
|
|
+ return () => {
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ {renderHeader()}
|
|
|
+ {unref(getUseScroll) ? (
|
|
|
+ <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer>
|
|
|
+ ) : (
|
|
|
+ renderMenu()
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ );
|
|
|
+ };
|
|
|
+ },
|
|
|
+});
|
|
|
</script>
|
|
|
<style lang="less">
|
|
|
- @prefix-cls: ~'@{namespace}-layout-menu';
|
|
|
- @logo-prefix-cls: ~'@{namespace}-app-logo';
|
|
|
+@prefix-cls: ~'@{namespace}-layout-menu';
|
|
|
+@logo-prefix-cls: ~'@{namespace}-app-logo';
|
|
|
|
|
|
- .@{prefix-cls} {
|
|
|
- &-logo {
|
|
|
- height: @header-height;
|
|
|
- padding: 10px 4px 10px 10px;
|
|
|
+.@{prefix-cls} {
|
|
|
+ &-logo {
|
|
|
+ height: @header-height;
|
|
|
+ padding: 10px 4px 10px 10px;
|
|
|
|
|
|
- img {
|
|
|
- width: @logo-width;
|
|
|
- height: @logo-width;
|
|
|
- }
|
|
|
+ img {
|
|
|
+ width: @logo-width;
|
|
|
+ height: @logo-width;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- &--mobile {
|
|
|
- .@{logo-prefix-cls} {
|
|
|
- &__title {
|
|
|
- opacity: 1;
|
|
|
- }
|
|
|
+ &--mobile {
|
|
|
+ .@{logo-prefix-cls} {
|
|
|
+ &__title {
|
|
|
+ opacity: 1;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
</style>
|