2023-01-29 15:26:45 +08:00
|
|
|
import { useRoute, useRouter } from "vue-router";
|
|
|
|
|
import { ref, watch, onMounted, onUnmounted, resolveComponent, nextTick, defineComponent } from "vue";
|
2024-11-08 23:43:19 +08:00
|
|
|
import * as _ from "lodash-es";
|
2023-01-29 15:26:45 +08:00
|
|
|
import BScroll from "better-scroll";
|
|
|
|
|
import "./index.less";
|
2023-03-16 19:24:01 +00:00
|
|
|
import { utils } from "@fast-crud/fast-crud";
|
2024-10-20 03:00:55 +08:00
|
|
|
import { routerUtils } from "/@/utils/util.router";
|
2023-01-29 15:26:45 +08:00
|
|
|
|
2025-06-29 14:09:09 +08:00
|
|
|
defineOptions();
|
2023-01-29 15:26:45 +08:00
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
|
name: "FsMenu",
|
|
|
|
|
inheritAttrs: true,
|
|
|
|
|
props: {
|
|
|
|
|
menus: {},
|
|
|
|
|
expandSelected: {
|
2025-06-29 14:09:09 +08:00
|
|
|
default: false,
|
2023-01-29 15:26:45 +08:00
|
|
|
},
|
2025-06-29 14:09:09 +08:00
|
|
|
scroll: {},
|
2023-01-29 15:26:45 +08:00
|
|
|
},
|
|
|
|
|
setup(props, ctx) {
|
2024-10-20 03:00:55 +08:00
|
|
|
async function onSelect(item: any) {
|
|
|
|
|
await routerUtils.open(item.key);
|
2023-01-29 15:26:45 +08:00
|
|
|
}
|
|
|
|
|
|
2024-12-24 17:09:06 +08:00
|
|
|
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} />;
|
2025-06-29 14:09:09 +08:00
|
|
|
},
|
2024-12-24 17:09:06 +08:00
|
|
|
};
|
|
|
|
|
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);
|
2023-03-16 19:24:01 +00:00
|
|
|
const fsIcon = resolveComponent("FsIcon");
|
2023-01-29 15:26:45 +08:00
|
|
|
|
2023-03-16 19:24:01 +00:00
|
|
|
const buildMenus = (children: any) => {
|
|
|
|
|
const slots: any = [];
|
2023-01-29 15:26:45 +08:00
|
|
|
if (children == null) {
|
|
|
|
|
return slots;
|
|
|
|
|
}
|
2023-03-16 19:24:01 +00:00
|
|
|
for (const sub of children) {
|
2024-10-05 01:46:25 +08:00
|
|
|
if (sub.meta?.show != null) {
|
|
|
|
|
if (sub.meta.show === false || (typeof sub.meta.show === "function" && !sub.meta.show())) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-16 19:24:01 +00:00
|
|
|
const title: any = () => {
|
2024-10-27 02:51:56 +08:00
|
|
|
const icon = sub.icon || sub?.meta?.icon;
|
|
|
|
|
if (icon) {
|
2024-12-01 02:10:40 +08:00
|
|
|
// @ts-ignore , anticon必须要有,不然不能折叠
|
2023-01-29 15:26:45 +08:00
|
|
|
return (
|
|
|
|
|
<div class={"menu-item-title"}>
|
2024-10-27 02:51:56 +08:00
|
|
|
<fsIcon class={"anticon"} icon={icon} />
|
2023-01-29 15:26:45 +08:00
|
|
|
<span>{sub.title}</span>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return sub.title;
|
|
|
|
|
};
|
|
|
|
|
if (sub.children && sub.children.length > 0) {
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
|
|
const subSlots = {
|
|
|
|
|
default: () => {
|
|
|
|
|
return buildMenus(sub.children);
|
|
|
|
|
},
|
2025-06-29 14:09:09 +08:00
|
|
|
title,
|
2023-01-29 15:26:45 +08:00
|
|
|
};
|
|
|
|
|
function onTitleClick() {
|
|
|
|
|
if (sub.path && ctx.attrs.mode === "horizontal") {
|
|
|
|
|
open(sub.path);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-12-24 17:09:06 +08:00
|
|
|
slots.push(<a-sub-menu key={sub.path} v-slots={subSlots} />);
|
2023-01-29 15:26:45 +08:00
|
|
|
} else {
|
|
|
|
|
slots.push(
|
|
|
|
|
<a-menu-item key={sub.path} title={sub.title}>
|
|
|
|
|
{title}
|
|
|
|
|
</a-menu-item>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return slots;
|
|
|
|
|
};
|
|
|
|
|
const slots = {
|
|
|
|
|
default() {
|
|
|
|
|
return buildMenus(props.menus);
|
2025-06-29 14:09:09 +08:00
|
|
|
},
|
2023-01-29 15:26:45 +08:00
|
|
|
};
|
|
|
|
|
const selectedKeys = ref([]);
|
|
|
|
|
const openKeys = ref([]);
|
2024-12-24 17:09:06 +08:00
|
|
|
|
2023-01-29 15:26:45 +08:00
|
|
|
const route = useRoute();
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
|
2023-03-16 19:24:01 +00:00
|
|
|
function openSelectedParents(fullPath: any) {
|
2023-01-29 15:26:45 +08:00
|
|
|
if (!props.expandSelected) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (props.menus == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-03-16 19:24:01 +00:00
|
|
|
const keys: any = [];
|
2023-01-29 15:26:45 +08:00
|
|
|
let changed = false;
|
2023-03-16 19:24:01 +00:00
|
|
|
utils.deepdash.forEachDeep(props.menus, (value: any, key: any, parent: any, context: any) => {
|
2023-01-29 15:26:45 +08:00
|
|
|
if (value == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (value.path === fullPath) {
|
2025-06-29 14:09:09 +08:00
|
|
|
_.forEach(context.parents, item => {
|
2023-01-29 15:26:45 +08:00
|
|
|
if (item.value instanceof Array) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-12-23 00:24:31 +08:00
|
|
|
keys.push(item.value.path);
|
2023-01-29 15:26:45 +08:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
if (keys.length > 0) {
|
2023-03-16 19:24:01 +00:00
|
|
|
for (const key of keys) {
|
2023-01-29 15:26:45 +08:00
|
|
|
if (openKeys.value.indexOf(key) === -1) {
|
|
|
|
|
openKeys.value.push(key);
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return changed;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-24 17:09:06 +08:00
|
|
|
// const { asideMenuRef, onOpenChange } = useBetterScroll(props.scroll as any);
|
2023-01-29 15:26:45 +08:00
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
() => {
|
|
|
|
|
return route.fullPath;
|
|
|
|
|
},
|
2025-06-29 14:09:09 +08:00
|
|
|
path => {
|
2023-01-29 15:26:45 +08:00
|
|
|
// path = route.fullPath;
|
|
|
|
|
selectedKeys.value = [path];
|
|
|
|
|
const changed = openSelectedParents(path);
|
|
|
|
|
if (changed) {
|
2024-12-24 17:09:06 +08:00
|
|
|
// onOpenChange();
|
2023-01-29 15:26:45 +08:00
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
2025-06-29 14:09:09 +08:00
|
|
|
immediate: true,
|
2023-01-29 15:26:45 +08:00
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
return () => {
|
|
|
|
|
const menu = (
|
|
|
|
|
<a-menu
|
|
|
|
|
mode={"inline"}
|
|
|
|
|
theme={"light"}
|
2024-12-24 17:09:06 +08:00
|
|
|
// v-slots={slots}
|
|
|
|
|
// onClick={onSelect}
|
|
|
|
|
// onOpenChange={onOpenChange}
|
2023-01-29 15:26:45 +08:00
|
|
|
v-models={[
|
|
|
|
|
[openKeys.value, "openKeys"],
|
2025-06-29 14:09:09 +08:00
|
|
|
[selectedKeys.value, "selectedKeys"],
|
2023-01-29 15:26:45 +08:00
|
|
|
]}
|
2024-12-24 17:09:06 +08:00
|
|
|
items={items.value}
|
|
|
|
|
inlineCollapsed={!props.expandSelected}
|
2023-01-29 15:26:45 +08:00
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
const classNames = { "fs-menu-wrapper": true, "fs-menu-better-scroll": props.scroll };
|
2024-12-24 17:09:06 +08:00
|
|
|
return <div>{menu}</div>;
|
2023-01-29 15:26:45 +08:00
|
|
|
};
|
2025-06-29 14:09:09 +08:00
|
|
|
},
|
2023-01-29 15:26:45 +08:00
|
|
|
});
|