fix: 修复左侧菜单收起时无法展开子菜单的bug

This commit is contained in:
xiaojunnuo
2024-12-24 17:09:06 +08:00
parent 8ebf95a222
commit 005622307e
21 changed files with 367 additions and 172 deletions
@@ -0,0 +1,118 @@
<template>
<a-menu v-model:open-keys="openKeys" v-model:selected-keys="selectedKeys" class="fs-menu" mode="inline" theme="light" :items="items" @click="onClick" />
</template>
<script lang="tsx" setup>
import { ref, watch, defineOptions } from "vue";
import { routerUtils } from "/@/utils/util.router";
import { useRoute } from "vue-router";
import { utils } from "@fast-crud/fast-crud";
import * as _ from "lodash-es";
defineOptions({
name: "FsMenu"
});
const props = defineProps<{
menus: any[];
expandSelected: boolean;
}>();
const items = ref([]);
function buildItemMenus(menus: any) {
if (menus == null) {
return;
}
const list: any = [];
for (const sub of menus) {
const item: any = {
key: sub.path,
label: sub.title,
title: sub.title,
icon: () => {
return <fsIcon icon={sub.icon ?? sub.meta?.icon} />;
}
};
list.push(item);
if (sub.children && sub.children.length > 0) {
item.children = buildItemMenus(sub.children);
}
}
return list;
}
watch(
() => props.menus,
(menus) => {
items.value = buildItemMenus(menus);
},
{ immediate: true }
);
async function onClick(item: any) {
await routerUtils.open(item.key);
}
const route = useRoute();
const selectedKeys = ref([]);
const openKeys = ref([]);
function openSelectedParents(fullPath: any) {
if (!props.expandSelected) {
return;
}
if (props.menus == null) {
return;
}
const keys: any = [];
let changed = false;
utils.deepdash.forEachDeep(props.menus, (value: any, key: any, parent: any, context: any) => {
if (value == null) {
return;
}
if (value.path === fullPath) {
_.forEach(context.parents, (item) => {
if (item.value instanceof Array) {
return;
}
keys.push(item.value.path);
});
}
});
if (keys.length > 0) {
for (const key of keys) {
if (openKeys.value.indexOf(key) === -1) {
openKeys.value.push(key);
changed = true;
}
}
}
return changed;
}
watch(
() => {
return route.fullPath;
},
(path) => {
// path = route.fullPath;
selectedKeys.value = [path];
const changed = openSelectedParents(path);
if (changed) {
// onOpenChange();
}
},
{
immediate: true
}
);
</script>
<style lang="less">
.fs-menu {
height: 100%;
overflow-y: auto;
.fs-icon {
font-size: 16px !important;
min-width: 16px !important;
}
}
</style>
@@ -6,60 +6,8 @@ import "./index.less";
import { utils } from "@fast-crud/fast-crud";
import { routerUtils } from "/@/utils/util.router";
function useBetterScroll(enabled = true) {
const bsRef = ref(null);
const asideMenuRef = ref();
defineOptions()
let onOpenChange = () => {};
if (enabled) {
function bsInit() {
if (asideMenuRef.value == null) {
return;
}
bsRef.value = new BScroll(asideMenuRef.value, {
mouseWheel: true,
click: true,
momentum: false,
// 如果你愿意可以打开显示滚动条
scrollbar: {
fade: true,
interactive: false
},
bounce: false
});
}
function bsDestroy() {
if (bsRef.value != null && bsRef.value.destroy) {
try {
bsRef.value.destroy();
} catch (e) {
// console.error(e);
} finally {
bsRef.value = null;
}
}
}
onMounted(() => {
bsInit();
});
onUnmounted(() => {
bsDestroy();
});
onOpenChange = async () => {
console.log("onOpenChange");
setTimeout(() => {
bsRef.value?.refresh();
}, 300);
};
}
return {
onOpenChange,
asideMenuRef
};
}
export default defineComponent({
name: "FsMenu",
inheritAttrs: true,
@@ -75,6 +23,31 @@ export default defineComponent({
await routerUtils.open(item.key);
}
const items = ref([]);
function buildItemMenus(menus: any) {
if (menus == null) {
return;
}
const list: any = [];
for (const sub of menus) {
const item: any = {
key: sub.path,
label: sub.title,
title: sub.title,
icon: () => {
return <fsIcon icon={sub.icon ?? sub.meta?.icon} />;
}
};
list.push(item);
if (sub.children && sub.children.length > 0) {
item.children = buildItemMenus(sub.children);
}
}
return list;
}
items.value = buildItemMenus(props.menus);
console.log("items", items.value);
const fsIcon = resolveComponent("FsIcon");
const buildMenus = (children: any) => {
@@ -114,7 +87,7 @@ export default defineComponent({
open(sub.path);
}
}
slots.push(<a-sub-menu key={sub.path} v-slots={subSlots} onTitleClick={onTitleClick} />);
slots.push(<a-sub-menu key={sub.path} v-slots={subSlots} />);
} else {
slots.push(
<a-menu-item key={sub.path} title={sub.title}>
@@ -132,6 +105,7 @@ export default defineComponent({
};
const selectedKeys = ref([]);
const openKeys = ref([]);
const route = useRoute();
const router = useRouter();
@@ -168,7 +142,7 @@ export default defineComponent({
return changed;
}
const { asideMenuRef, onOpenChange } = useBetterScroll(props.scroll as any);
// const { asideMenuRef, onOpenChange } = useBetterScroll(props.scroll as any);
watch(
() => {
@@ -179,7 +153,7 @@ export default defineComponent({
selectedKeys.value = [path];
const changed = openSelectedParents(path);
if (changed) {
onOpenChange();
// onOpenChange();
}
},
{
@@ -191,22 +165,19 @@ export default defineComponent({
<a-menu
mode={"inline"}
theme={"light"}
v-slots={slots}
onClick={onSelect}
onOpenChange={onOpenChange}
// v-slots={slots}
// onClick={onSelect}
// onOpenChange={onOpenChange}
v-models={[
[openKeys.value, "openKeys"],
[selectedKeys.value, "selectedKeys"]
]}
{...ctx.attrs}
items={items.value}
inlineCollapsed={!props.expandSelected}
/>
);
const classNames = { "fs-menu-wrapper": true, "fs-menu-better-scroll": props.scroll };
return (
<div ref={asideMenuRef} class={classNames}>
{menu}
</div>
);
return <div>{menu}</div>;
};
}
});
@@ -106,7 +106,7 @@
<script lang="ts" setup>
import { computed, onErrorCaptured, onMounted, ref } from "vue";
import FsMenu from "./components/menu/index.jsx";
import FsMenu from "./components/menu/index.vue";
import FsLocale from "./components/locale/index.vue";
import FsUserInfo from "./components/user-info/index.vue";
import FsTabs from "./components/tabs/index.vue";