菜单组件
parent
4b65fb8d5f
commit
e2d1e04b38
|
|
@ -11,6 +11,12 @@ import { elIcons } from '@/common/element/element.ts'
|
|||
import AIcon from '@/components/a-icon/AIcon.vue'
|
||||
import type { IconName } from '@/components/a-icon/iconfont.ts'
|
||||
import styles from '@/pages/a-frame/aaside.module.styl'
|
||||
import { useAppSettingStore } from '@/common/app/app-setting-store.ts'
|
||||
import Colls from '@/common/utils/colls.ts'
|
||||
import { MenuCategory } from '@/common/app/constants.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { computed } from 'vue'
|
||||
import Nav from '@/common/router/nav.ts'
|
||||
|
||||
export interface Menu extends G.TreeNode {
|
||||
// Id
|
||||
|
|
@ -32,43 +38,42 @@ export interface Menu extends G.TreeNode {
|
|||
// 面包路径
|
||||
breadcrumb: string[];
|
||||
// 类型
|
||||
menuCategory: "Catalog" | "Group" | "Page" | "SubPage" | "Btn";
|
||||
menuCategory: 'Catalog' | 'Group' | 'Page' | 'SubPage' | 'Btn';
|
||||
// 子菜单
|
||||
children?: Menu[];
|
||||
}
|
||||
|
||||
export default defineComponent(
|
||||
(props, { emit }) => {
|
||||
let defaultId = "";
|
||||
let path: any = props.defaultPath.split("/");
|
||||
path = path[path.length - 1];
|
||||
props.menus.forEach((item) => {
|
||||
if (item.routeName == path) {
|
||||
defaultId = item.id;
|
||||
} else if (item.children && item.children.length) {
|
||||
item.children.forEach((item2) => {
|
||||
if (item2.routeName == path) {
|
||||
defaultId = item2.id;
|
||||
} else if (item2.children && item2.children.length) {
|
||||
item2.children.forEach((item3) => {
|
||||
if (item3.routeName == path) {
|
||||
defaultId = item3.id;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
() => {
|
||||
const router = useRouter()
|
||||
const appSettingStore = useAppSettingStore()
|
||||
const defaultActive = ref('')
|
||||
const isCollapse = ref(false)
|
||||
|
||||
const onMenuClick = (it: MenuItemRegistered) => emit("menuClick", it.index);
|
||||
const renderMenu = (it: Menu) => {
|
||||
let renderChildNode: (() => VNode[] | undefined) | undefined = undefined;
|
||||
if (it.children != null && it.children.length > 0) {
|
||||
renderChildNode = () => it.children?.map(renderMenu);
|
||||
onMounted(() => {
|
||||
const currentRouteName = router.currentRoute.value.name
|
||||
defaultActive.value = appSettingStore.menus.find(it => it.routeName === currentRouteName)?.id
|
||||
})
|
||||
|
||||
const menuTree = computed(() => {
|
||||
return Colls.toTree(appSettingStore.menus.filter((it) => it.menuCategory === MenuCategory.Page || it.menuCategory === MenuCategory.Group || it.menuCategory === MenuCategory.Catalog).sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0)))
|
||||
})
|
||||
|
||||
const onMenuClick = (menuItem: MenuItemRegistered) => {
|
||||
const menu = appSettingStore.menus.find(it => it.id === menuItem.index)
|
||||
Nav.open({
|
||||
insId: menu?.routeName ?? '',
|
||||
routeName: menu?.routeName ?? '',
|
||||
})
|
||||
}
|
||||
let currentNode: VNode;
|
||||
const renderMenu = (it: Menu) => {
|
||||
let renderChildNode: (() => VNode[] | undefined) | undefined = undefined
|
||||
if (it.children != null && it.children.length > 0) {
|
||||
renderChildNode = () => it.children?.map(renderMenu)
|
||||
}
|
||||
let currentNode: VNode
|
||||
switch (it.menuCategory) {
|
||||
case "Catalog": {
|
||||
case 'Catalog': {
|
||||
currentNode = (
|
||||
<ElSubMenu index={it.id}>
|
||||
{{
|
||||
|
|
@ -81,20 +86,20 @@ export default defineComponent(
|
|||
default: renderChildNode,
|
||||
}}
|
||||
</ElSubMenu>
|
||||
);
|
||||
break;
|
||||
)
|
||||
break
|
||||
}
|
||||
case "Group": {
|
||||
case 'Group': {
|
||||
currentNode = (
|
||||
<ElMenuItemGroup title={it.title}>
|
||||
{{
|
||||
default: renderChildNode,
|
||||
}}
|
||||
</ElMenuItemGroup>
|
||||
);
|
||||
break;
|
||||
)
|
||||
break
|
||||
}
|
||||
case "Page": {
|
||||
case 'Page': {
|
||||
currentNode = (
|
||||
<ElMenuItem index={it.id} onClick={onMenuClick}>
|
||||
{{
|
||||
|
|
@ -102,49 +107,34 @@ export default defineComponent(
|
|||
default: () => <AIcon class={styles.aIcon} name={it.icon as IconName}/>,
|
||||
}}
|
||||
</ElMenuItem>
|
||||
);
|
||||
break;
|
||||
)
|
||||
break
|
||||
}
|
||||
default:
|
||||
currentNode = <></>;
|
||||
currentNode = <></>
|
||||
}
|
||||
return currentNode
|
||||
}
|
||||
return currentNode;
|
||||
};
|
||||
const isCollapse = ref(false);
|
||||
|
||||
return () => (
|
||||
<>
|
||||
<ElMenu default-active={defaultId} collapse={isCollapse.value} style={{ height: "100%", overflow: "auto", "--el-menu-base-level-padding": "10px" }} class={[styles.aMenus, "menus"]}>
|
||||
<ElMenu default-active={defaultActive.value} collapse={isCollapse.value} style={{height: '100%', overflow: 'auto', '--el-menu-base-level-padding': '10px'}} class={[ styles.aMenus, 'menus' ]}>
|
||||
{{
|
||||
default: () => props.menus.map(renderMenu),
|
||||
default: () => menuTree.value.map(renderMenu),
|
||||
}}
|
||||
</ElMenu>
|
||||
<ElButton
|
||||
style={{ position: "absolute", right: "6px", bottom: "6px", width: "32px", height: "32px" }}
|
||||
style={{position: 'absolute', right: '6px', bottom: '6px', width: '32px', height: '32px'}}
|
||||
onClick={() => {
|
||||
isCollapse.value = !isCollapse.value;
|
||||
isCollapse.value = !isCollapse.value
|
||||
}}
|
||||
>
|
||||
<ElIcon style={{ cursor: "pointer" }}>{isCollapse.value ? <elIcons.Fold /> : <elIcons.Expand />}</ElIcon>
|
||||
<ElIcon style={{cursor: 'pointer'}}>{isCollapse.value ? <elIcons.Fold/> : <elIcons.Expand/>}</ElIcon>
|
||||
</ElButton>
|
||||
</>
|
||||
);
|
||||
)
|
||||
},
|
||||
{
|
||||
props: {
|
||||
menus: {
|
||||
type: Object as PropType<Menu[]>,
|
||||
required: true,
|
||||
validator: (value: Menu[]) => value != null && value.length > 0,
|
||||
name: 'AAside',
|
||||
},
|
||||
defaultPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: {
|
||||
menuClick: (id: string) => id != null,
|
||||
},
|
||||
name: "AAside",
|
||||
}
|
||||
);
|
||||
)
|
||||
|
|
|
|||
|
|
@ -112,15 +112,7 @@ function logoutHandler() {
|
|||
.el-tabs__nav {
|
||||
width 100%
|
||||
justify-content space-around
|
||||
position relative /*&::before {
|
||||
content ''
|
||||
position absolute
|
||||
left 50%
|
||||
background-color #D3D7DE
|
||||
width 2px
|
||||
height 100%
|
||||
box-sizing border-box
|
||||
}*/
|
||||
position relative
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,44 +2,15 @@
|
|||
import AAside from '@/pages/a-frame/AAside.tsx'
|
||||
import AAvatar from '@/pages/a-frame/AAvatar.vue'
|
||||
import { appName } from '@/common'
|
||||
import Colls from '@/common/utils/colls.ts'
|
||||
import { MenuCategory } from '@/common/app/constants.ts'
|
||||
import { useAppSettingStore } from '@/common/app/app-setting-store.ts'
|
||||
import Nav from '@/common/router/nav.ts'
|
||||
import Evt from '@/common/utils/evt.ts'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const appSettingStore = useAppSettingStore();
|
||||
const id_menu_map = computed(() => {
|
||||
return Colls.keyObj(
|
||||
appSettingStore.menus.filter((it) => it.menuCategory === MenuCategory.Page || it.menuCategory === MenuCategory.Group || it.menuCategory === MenuCategory.Catalog),
|
||||
(it) => it.id,
|
||||
(it) => it
|
||||
);
|
||||
});
|
||||
|
||||
function onMenuClick(id: string) {
|
||||
const menu = id_menu_map.value[id];
|
||||
Nav.open({
|
||||
insId: menu?.routeName ?? "",
|
||||
routeName: menu?.routeName ?? "",
|
||||
});
|
||||
}
|
||||
|
||||
const menuTree = computed(() => {
|
||||
return Colls.toTree(appSettingStore.menus.filter((it) => it.menuCategory === MenuCategory.Page || it.menuCategory === MenuCategory.Group || it.menuCategory === MenuCategory.Catalog).sort((a, b) => (a.sort ?? 0) - (b.sort ?? 0)));
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
const defaultPath= ref<string>(router.currentRoute.value.path);
|
||||
|
||||
onMounted(() => {
|
||||
Evt.emit("connect_ws");
|
||||
});
|
||||
Evt.emit('connect_ws')
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
Evt.emit("disconnect_ws");
|
||||
});
|
||||
Evt.emit('disconnect_ws')
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -53,7 +24,7 @@ onUnmounted(() => {
|
|||
</ElHeader>
|
||||
<ElContainer>
|
||||
<ElAside>
|
||||
<AAside :defaultPath="defaultPath" :menus="menuTree" @menu-click="onMenuClick" />
|
||||
<AAside/>
|
||||
</ElAside>
|
||||
<ElMain>
|
||||
<RouterView #="{ Component }">
|
||||
|
|
@ -80,6 +51,7 @@ onUnmounted(() => {
|
|||
border-bottom 1px solid #E5E7EB;
|
||||
height 60px
|
||||
background-color white
|
||||
|
||||
& > div:first-child {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
|
@ -115,7 +87,6 @@ onUnmounted(() => {
|
|||
padding 5px
|
||||
overflow auto
|
||||
background-color #F7F9FC
|
||||
//box-shadow: inset rgba(0, 0, 0, 0.12) 0px 0px 12px 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue