2020-09-28 20:19:10 +08:00
|
|
|
import type { PropType } from 'vue';
|
|
|
|
|
import type { Menu } from '/@/router/types';
|
|
|
|
|
|
|
|
|
|
import { computed, defineComponent, unref, ref, onMounted, watch } from 'vue';
|
|
|
|
|
import { BasicMenu } from '/@/components/Menu/index';
|
2020-11-10 23:50:47 +08:00
|
|
|
import Logo from '/@/layouts/logo/index.vue';
|
2020-09-28 20:19:10 +08:00
|
|
|
|
|
|
|
|
import { MenuModeEnum, MenuSplitTyeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
|
|
|
|
|
|
|
|
|
|
// store
|
|
|
|
|
import { appStore } from '/@/store/modules/app';
|
|
|
|
|
import { menuStore } from '/@/store/modules/menu';
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
getMenus,
|
|
|
|
|
getFlatMenus,
|
|
|
|
|
getShallowMenus,
|
|
|
|
|
getChildrenMenus,
|
|
|
|
|
getFlatChildrenMenus,
|
|
|
|
|
getCurrentParentPath,
|
|
|
|
|
} from '/@/router/menus/index';
|
|
|
|
|
import { useRouter } from 'vue-router';
|
|
|
|
|
import { useThrottle } from '/@/hooks/core/useThrottle';
|
|
|
|
|
import { permissionStore } from '/@/store/modules/permission';
|
|
|
|
|
|
2020-11-10 23:50:47 +08:00
|
|
|
import './index.less';
|
2020-09-28 20:19:10 +08:00
|
|
|
export default defineComponent({
|
|
|
|
|
name: 'DefaultLayoutMenu',
|
|
|
|
|
props: {
|
|
|
|
|
theme: {
|
|
|
|
|
type: String as PropType<string>,
|
|
|
|
|
default: '',
|
|
|
|
|
},
|
|
|
|
|
splitType: {
|
|
|
|
|
type: Number as PropType<MenuSplitTyeEnum>,
|
|
|
|
|
default: MenuSplitTyeEnum.NONE,
|
|
|
|
|
},
|
|
|
|
|
parentMenuPath: {
|
|
|
|
|
type: String as PropType<string>,
|
|
|
|
|
default: '',
|
|
|
|
|
},
|
|
|
|
|
showSearch: {
|
|
|
|
|
type: Boolean as PropType<boolean>,
|
|
|
|
|
default: true,
|
|
|
|
|
},
|
2020-10-31 19:51:24 +08:00
|
|
|
isTop: {
|
|
|
|
|
type: Boolean as PropType<boolean>,
|
|
|
|
|
default: false,
|
|
|
|
|
},
|
2020-09-28 20:19:10 +08:00
|
|
|
menuMode: {
|
|
|
|
|
type: [String] as PropType<MenuModeEnum | null>,
|
|
|
|
|
default: '',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
setup(props) {
|
2020-11-10 22:45:39 +08:00
|
|
|
// Menu array
|
2020-09-28 20:19:10 +08:00
|
|
|
const menusRef = ref<Menu[]>([]);
|
2020-11-10 22:45:39 +08:00
|
|
|
// flat menu array
|
2020-09-28 20:19:10 +08:00
|
|
|
const flatMenusRef = ref<Menu[]>([]);
|
2020-10-27 23:08:29 +08:00
|
|
|
const { currentRoute, push } = useRouter();
|
2020-09-28 20:19:10 +08:00
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// get app config
|
2020-09-28 20:19:10 +08:00
|
|
|
const getProjectConfigRef = computed(() => {
|
|
|
|
|
return appStore.getProjectConfig;
|
|
|
|
|
});
|
|
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// get is Horizontal
|
2020-09-28 20:19:10 +08:00
|
|
|
const getIsHorizontalRef = computed(() => {
|
|
|
|
|
return unref(getProjectConfigRef).menuSetting.mode === MenuModeEnum.HORIZONTAL;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const [throttleHandleSplitLeftMenu] = useThrottle(handleSplitLeftMenu, 50);
|
|
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// Route change split menu
|
2020-09-28 20:19:10 +08:00
|
|
|
watch(
|
|
|
|
|
[() => unref(currentRoute).path, () => props.splitType],
|
|
|
|
|
async ([path, splitType]: [string, MenuSplitTyeEnum]) => {
|
|
|
|
|
if (splitType !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontalRef)) return;
|
|
|
|
|
const parentPath = await getCurrentParentPath(path);
|
|
|
|
|
parentPath && throttleHandleSplitLeftMenu(parentPath);
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
immediate: true,
|
|
|
|
|
}
|
|
|
|
|
);
|
2020-11-06 22:41:00 +08:00
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// Menu changes
|
2020-09-28 20:19:10 +08:00
|
|
|
watch(
|
2020-11-10 22:45:39 +08:00
|
|
|
[() => permissionStore.getLastBuildMenuTimeState, () => permissionStore.getBackMenuListState],
|
2020-09-28 20:19:10 +08:00
|
|
|
() => {
|
|
|
|
|
genMenus();
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// split Menu changes
|
2020-09-28 20:19:10 +08:00
|
|
|
watch([() => appStore.getProjectConfig.menuSetting.split], () => {
|
|
|
|
|
if (props.splitType !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontalRef)) return;
|
|
|
|
|
genMenus();
|
|
|
|
|
});
|
|
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// Handle left menu split
|
2020-09-28 20:19:10 +08:00
|
|
|
async function handleSplitLeftMenu(parentPath: string) {
|
|
|
|
|
const isSplitMenu = unref(getProjectConfigRef).menuSetting.split;
|
|
|
|
|
if (!isSplitMenu) return;
|
|
|
|
|
const { splitType } = props;
|
2020-11-10 22:45:39 +08:00
|
|
|
// spilt mode left
|
2020-09-28 20:19:10 +08:00
|
|
|
if (splitType === MenuSplitTyeEnum.LEFT) {
|
|
|
|
|
const children = await getChildrenMenus(parentPath);
|
2020-11-02 23:04:25 +08:00
|
|
|
if (!children) {
|
|
|
|
|
appStore.commitProjectConfigState({
|
|
|
|
|
menuSetting: {
|
2020-11-06 22:41:00 +08:00
|
|
|
hidden: false,
|
2020-11-02 23:04:25 +08:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
flatMenusRef.value = [];
|
|
|
|
|
menusRef.value = [];
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-09-28 20:19:10 +08:00
|
|
|
const flatChildren = await getFlatChildrenMenus(children);
|
2020-11-02 23:04:25 +08:00
|
|
|
appStore.commitProjectConfigState({
|
|
|
|
|
menuSetting: {
|
2020-11-06 22:41:00 +08:00
|
|
|
hidden: true,
|
2020-11-02 23:04:25 +08:00
|
|
|
},
|
|
|
|
|
});
|
2020-09-28 20:19:10 +08:00
|
|
|
flatMenusRef.value = flatChildren;
|
|
|
|
|
menusRef.value = children;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// get menus
|
2020-09-28 20:19:10 +08:00
|
|
|
async function genMenus() {
|
|
|
|
|
const isSplitMenu = unref(getProjectConfigRef).menuSetting.split;
|
|
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// normal mode
|
2020-09-28 20:19:10 +08:00
|
|
|
const { splitType } = props;
|
|
|
|
|
if (splitType === MenuSplitTyeEnum.NONE || !isSplitMenu) {
|
|
|
|
|
flatMenusRef.value = await getFlatMenus();
|
|
|
|
|
menusRef.value = await getMenus();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 22:45:39 +08:00
|
|
|
// split-top
|
2020-09-28 20:19:10 +08:00
|
|
|
if (splitType === MenuSplitTyeEnum.TOP) {
|
|
|
|
|
const parentPath = await getCurrentParentPath(unref(currentRoute).path);
|
|
|
|
|
menuStore.commitCurrentTopSplitMenuPathState(parentPath);
|
|
|
|
|
const shallowMenus = await getShallowMenus();
|
|
|
|
|
|
|
|
|
|
flatMenusRef.value = shallowMenus;
|
|
|
|
|
menusRef.value = shallowMenus;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleMenuClick(menu: Menu) {
|
|
|
|
|
const { path } = menu;
|
|
|
|
|
if (path) {
|
|
|
|
|
const { splitType } = props;
|
2020-11-10 22:45:39 +08:00
|
|
|
// split mode top
|
2020-09-28 20:19:10 +08:00
|
|
|
if (splitType === MenuSplitTyeEnum.TOP) {
|
|
|
|
|
menuStore.commitCurrentTopSplitMenuPathState(path);
|
|
|
|
|
}
|
2020-10-27 23:08:29 +08:00
|
|
|
push(path);
|
2020-09-28 20:19:10 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function beforeMenuClickFn(menu: Menu) {
|
|
|
|
|
const { meta: { externalLink } = {} } = menu;
|
|
|
|
|
|
|
|
|
|
if (externalLink) {
|
|
|
|
|
window.open(externalLink, '_blank');
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleClickSearchInput() {
|
|
|
|
|
if (menuStore.getCollapsedState) {
|
|
|
|
|
menuStore.commitCollapsedState(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const showSearchRef = computed(() => {
|
|
|
|
|
const { showSearch, type, mode } = unref(getProjectConfigRef).menuSetting;
|
|
|
|
|
return (
|
|
|
|
|
showSearch &&
|
|
|
|
|
props.showSearch &&
|
|
|
|
|
!(type === MenuTypeEnum.MIX && mode === MenuModeEnum.HORIZONTAL)
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
2020-11-06 22:41:00 +08:00
|
|
|
onMounted(() => {
|
|
|
|
|
genMenus();
|
|
|
|
|
});
|
|
|
|
|
|
2020-09-28 20:19:10 +08:00
|
|
|
return () => {
|
|
|
|
|
const {
|
|
|
|
|
showLogo,
|
2020-11-03 21:00:14 +08:00
|
|
|
menuSetting: {
|
|
|
|
|
type: menuType,
|
|
|
|
|
mode,
|
|
|
|
|
theme,
|
|
|
|
|
collapsed,
|
|
|
|
|
collapsedShowTitle,
|
|
|
|
|
collapsedShowSearch,
|
2020-11-10 22:45:39 +08:00
|
|
|
accordion,
|
2020-11-03 21:00:14 +08:00
|
|
|
},
|
2020-09-28 20:19:10 +08:00
|
|
|
} = unref(getProjectConfigRef);
|
|
|
|
|
|
|
|
|
|
const isSidebarType = menuType === MenuTypeEnum.SIDEBAR;
|
|
|
|
|
const isShowLogo = showLogo && isSidebarType;
|
|
|
|
|
const themeData = props.theme || theme;
|
|
|
|
|
return (
|
|
|
|
|
<BasicMenu
|
|
|
|
|
beforeClickFn={beforeMenuClickFn}
|
|
|
|
|
onMenuClick={handleMenuClick}
|
|
|
|
|
type={menuType}
|
|
|
|
|
mode={props.menuMode || mode}
|
|
|
|
|
class="layout-menu"
|
2020-10-19 22:47:44 +08:00
|
|
|
collapsedShowTitle={collapsedShowTitle}
|
2020-09-28 20:19:10 +08:00
|
|
|
theme={themeData}
|
|
|
|
|
showLogo={isShowLogo}
|
2020-11-03 21:00:14 +08:00
|
|
|
search={unref(showSearchRef) && (collapsedShowSearch ? true : !collapsed)}
|
2020-09-28 20:19:10 +08:00
|
|
|
items={unref(menusRef)}
|
|
|
|
|
flatItems={unref(flatMenusRef)}
|
|
|
|
|
onClickSearchInput={handleClickSearchInput}
|
|
|
|
|
appendClass={props.splitType === MenuSplitTyeEnum.TOP}
|
2020-10-31 19:51:24 +08:00
|
|
|
isTop={props.isTop}
|
2020-11-10 22:45:39 +08:00
|
|
|
accordion={accordion}
|
2020-09-28 20:19:10 +08:00
|
|
|
>
|
|
|
|
|
{{
|
|
|
|
|
header: () =>
|
|
|
|
|
isShowLogo && (
|
2020-11-06 22:41:00 +08:00
|
|
|
<Logo
|
|
|
|
|
showTitle={!collapsed}
|
|
|
|
|
class={[`layout-menu__logo`, themeData]}
|
|
|
|
|
theme={themeData}
|
|
|
|
|
/>
|
2020-09-28 20:19:10 +08:00
|
|
|
),
|
|
|
|
|
}}
|
|
|
|
|
</BasicMenu>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
});
|