update
init
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
<script lang="tsx">
|
||||
import type { CSSProperties, PropType } from 'vue';
|
||||
import { computed, defineComponent, toRef, unref } from 'vue';
|
||||
import { BasicMenu1, BasicMenu2 } 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';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { usePermissionStore, usePermissionStoreWithOut } from '/@/store/modules/permission';
|
||||
import { isShowNewLayout, isYT } from '/@/utils/getEnv';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
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: '',
|
||||
},
|
||||
isLeft: {
|
||||
type: String,
|
||||
default: () => '0',
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const go = useGo();
|
||||
|
||||
const {
|
||||
getMenuMode,
|
||||
getMenuType,
|
||||
getMenuTheme,
|
||||
getCollapsed,
|
||||
getCollapsedShowTitle,
|
||||
getAccordion,
|
||||
getIsHorizontal,
|
||||
getIsSidebarType,
|
||||
getSplit,
|
||||
} = useMenuSetting();
|
||||
const { getShowLogo } = useRootSetting();
|
||||
|
||||
const { prefixCls } = useDesign('layout-menu');
|
||||
|
||||
let { 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) ? '80px' : '0px'})`,
|
||||
};
|
||||
});
|
||||
|
||||
const getLogoClass = computed(() => {
|
||||
return [
|
||||
`${prefixCls}-logo`,
|
||||
unref(getComputedMenuTheme),
|
||||
{
|
||||
[`${prefixCls}--mobile`]: unref(getIsMobile),
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const useStore = useUserStore();
|
||||
const getCommonProps = computed(() => {
|
||||
let menus = unref(menusRef);
|
||||
if (props.isLeft === '1') {
|
||||
let m = usePermissionStore().getBackMenuList;
|
||||
if (isShowNewLayout(useStore.getSpecialPath)) {
|
||||
// if (useStore.getSpecialDownPath) {
|
||||
menus =
|
||||
(
|
||||
m.find((item) => {
|
||||
return item.path === useStore.getSpecialPath;
|
||||
})?.children || []
|
||||
).find((item) => {
|
||||
return item.path === useStore.getSpecialDownPath;
|
||||
})?.children || [];
|
||||
|
||||
menus = menus.filter((it) => {
|
||||
return !it.hasOwnProperty('hideMenu') || it.hideMenu === false;
|
||||
});
|
||||
// } else {
|
||||
// menus = [];
|
||||
// }
|
||||
}
|
||||
// else {
|
||||
// menus =
|
||||
// m.find((item) => {
|
||||
// return item.path === useStore.getSpecialPath;
|
||||
// })?.children || [];
|
||||
// }
|
||||
}
|
||||
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();
|
||||
const router = useRouter();
|
||||
function handleMenuClick(path: string, item) {
|
||||
if (isYT()) {
|
||||
const list = usePermissionStore().getBackMenuList as Array<any>;
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].path.indexOf(path) > -1) {
|
||||
router.push(path + '/pageIndexOne');
|
||||
useUserStore().setSpecialPath(path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// useUserStore().setSpecialDownPath('');
|
||||
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 || []} />
|
||||
) : isYT() ? (
|
||||
<BasicMenu1
|
||||
{...(menuProps as any)}
|
||||
isHorizontal={props.isHorizontal}
|
||||
type={unref(getMenuType)}
|
||||
showLogo={unref(getIsShowLogo)}
|
||||
mode={unref(getComputedMenuMode as any)}
|
||||
items={menus || []}
|
||||
/>
|
||||
) : (
|
||||
<BasicMenu2
|
||||
{...(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">
|
||||
@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>
|
||||
@@ -0,0 +1,130 @@
|
||||
import type { Menu } from '/@/router/types';
|
||||
import type { Ref } from 'vue';
|
||||
import { computed, ref, unref, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { MenuSplitTyeEnum } from '/@/enums/menuEnum';
|
||||
import { useThrottleFn } from '@vueuse/core';
|
||||
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
|
||||
import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '/@/router/menus';
|
||||
import { usePermissionStore, usePermissionStoreWithOut } from '/@/store/modules/permission';
|
||||
import { useAppInject } from '/@/hooks/web/useAppInject';
|
||||
import { listenerMixTopClick } from '/@/logics/mitt/mixTopClick';
|
||||
|
||||
export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
|
||||
// Menu array
|
||||
const menusRef = ref<Menu[]>([]);
|
||||
const { currentRoute } = useRouter();
|
||||
const { getIsMobile } = useAppInject();
|
||||
const permissionStore = usePermissionStore();
|
||||
const { setMenuSetting, getIsHorizontal, getSplit } = useMenuSetting();
|
||||
|
||||
const throttleHandleSplitLeftMenu = useThrottleFn(handleSplitLeftMenu, 50);
|
||||
|
||||
const splitNotLeft = computed(() => unref(splitType) !== MenuSplitTyeEnum.LEFT && !unref(getIsHorizontal));
|
||||
|
||||
const getSplitLeft = computed(() => !unref(getSplit) || unref(splitType) !== MenuSplitTyeEnum.LEFT);
|
||||
|
||||
const getSpiltTop = computed(() => unref(splitType) === MenuSplitTyeEnum.TOP);
|
||||
|
||||
const normalType = computed(() => {
|
||||
return unref(splitType) === MenuSplitTyeEnum.NONE || !unref(getSplit);
|
||||
});
|
||||
|
||||
watch(
|
||||
[() => unref(currentRoute).path, () => unref(splitType)],
|
||||
async ([path]: [string, MenuSplitTyeEnum]) => {
|
||||
if (unref(splitNotLeft) || unref(getIsMobile)) return;
|
||||
|
||||
const { meta } = unref(currentRoute);
|
||||
const currentActiveMenu = meta.currentActiveMenu as string;
|
||||
let parentPath = await getCurrentParentPath(path);
|
||||
if (!parentPath) {
|
||||
parentPath = await getCurrentParentPath(currentActiveMenu);
|
||||
}
|
||||
parentPath && throttleHandleSplitLeftMenu(parentPath);
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
// Menu changes
|
||||
watch(
|
||||
[() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList],
|
||||
() => {
|
||||
genMenus();
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
// split Menu changes
|
||||
watch(
|
||||
() => getSplit.value,
|
||||
() => {
|
||||
if (unref(splitNotLeft)) return;
|
||||
genMenus();
|
||||
}
|
||||
);
|
||||
|
||||
// Handle left menu split
|
||||
async function handleSplitLeftMenu(parentPath: string) {
|
||||
if (unref(getSplitLeft) || unref(getIsMobile)) return;
|
||||
// spilt mode left
|
||||
const children = await getChildrenMenus(parentPath);
|
||||
|
||||
if (!children || !children.length) {
|
||||
setMenuSetting({ hidden: true });
|
||||
menusRef.value = [];
|
||||
return;
|
||||
}
|
||||
|
||||
setMenuSetting({ hidden: false });
|
||||
menusRef.value = children;
|
||||
}
|
||||
|
||||
listenerMixTopClick((menu) => {
|
||||
if (!unref(getSplitLeft)) {
|
||||
menusRef.value = menu?.children || [];
|
||||
}
|
||||
});
|
||||
|
||||
// get menus
|
||||
async function genMenus() {
|
||||
// normal mode
|
||||
if (unref(normalType) || unref(getIsMobile)) {
|
||||
menusRef.value = await getMenus();
|
||||
return;
|
||||
}
|
||||
|
||||
// split-top
|
||||
if (unref(getSpiltTop)) {
|
||||
const shallowMenus = await getShallowMenus();
|
||||
|
||||
menusRef.value = shallowMenus;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return { menusRef };
|
||||
}
|
||||
|
||||
export function findRouteMenu(path: string, onlyRoot = false): Menu | undefined {
|
||||
const permissionStore = usePermissionStoreWithOut();
|
||||
function findChildren(menus: Menu[]): Menu | undefined {
|
||||
for (const menu of menus) {
|
||||
if (menu.path === path) {
|
||||
return menu;
|
||||
}
|
||||
if (!onlyRoot && menu.children && menu.children.length) {
|
||||
const result = findChildren(menu.children);
|
||||
if (result !== undefined) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
return findChildren(permissionStore.getBackMenuList);
|
||||
}
|
||||
Reference in New Issue
Block a user