Commit f9accd25 authored by Sendya's avatar Sendya

fix: menu selectedKeys abort

parent 17e764ca
......@@ -5,7 +5,6 @@
v-model:openKeys="baseState.openKeys"
v-bind="state"
:loading="loading"
:collapsed-button-render="false"
:breadcrumb="{ routes: breadcrumb }"
>
<!-- only work layout `Side` -->
......@@ -29,6 +28,23 @@
{{ route.breadcrumbName }}
</router-link>
</template>
<!-- custom menu-item -->
<template #menuItemRender="{ item, icon }">
<a-menu-item
:key="item.path"
:disabled="item.meta?.disabled"
:danger="item.meta?.danger"
:icon="icon"
>
<router-link :to="{ path: item.path }">
<div class="a-menu-item-title">
<a-badge count="5" dot>
{{ item.meta.title }}
</a-badge>
</div>
</router-link>
</a-menu-item>
</template>
<!-- content begin -->
<router-view />
<!-- content end -->
......@@ -61,7 +77,7 @@
<script lang="ts">
import { computed, defineComponent, reactive, ref, watchEffect } from 'vue';
import { useRouter } from 'vue-router';
import { Button, Switch, Select, Space } from 'ant-design-vue';
import { Button, Switch, Select, Space, Badge, Menu } from 'ant-design-vue';
import { getMenuData, clearMenuItem, FooterToolbar } from '@ant-design-vue/pro-layout';
import type { RouteContextProps } from '@ant-design-vue/pro-layout';
......@@ -76,6 +92,9 @@ export default defineComponent({
[Select.name]: Select,
[Select.Option.displayName!]: Select.Option,
[Space.name]: Space,
[Badge.name]: Badge,
[Menu.Item.name]: Menu.Item,
},
setup() {
const loading = ref(false);
......
import { computed, reactive, unref, provide, defineComponent, toRefs, watch } from 'vue';
import { computed, reactive, unref, provide, defineComponent, toRefs } from 'vue';
import type { CSSProperties, PropType, ExtractPropTypes } from 'vue';
import 'ant-design-vue/es/layout/style';
......@@ -14,12 +14,12 @@ import { default as SiderMenuWrapper, siderMenuProps } from './SiderMenu';
import { WrapContent } from './WrapContent';
import globalHeaderProps from './GlobalHeader/headerProps';
import { HeaderView as Header, headerViewProps } from './Header';
import { getPropsSlot, PropTypes } from './utils';
import { getPropsSlot, getPropsSlotfn, PropTypes } from './utils';
import type { CustomRender, FormatMessage, WithFalse } from './typings';
import './BasicLayout.less';
import PageLoading from '@/PageLoading';
import PageLoading from './PageLoading';
export const basicLayoutProps = {
...defaultSettingProps,
......@@ -172,13 +172,20 @@ const ProLayout = defineComponent({
const customHeaderRender = getPropsSlot(slots, props, 'headerRender');
const menuHeaderRender = getPropsSlot(slots, props, 'menuHeaderRender');
const footerRender = getPropsSlot(slots, props, 'footerRender');
// const menuRender = getPropsSlot(slots, props, 'menuRender');
const breadcrumbRender = props.breadcrumbRender || slots.breadcrumbRender;
const breadcrumbRender = getPropsSlotfn(slots, props, 'breadcrumbRender');
// menu render
const menuItemRender = getPropsSlotfn(slots, props, 'menuItemRender');
const subMenuItemRender = getPropsSlotfn(slots, props, 'subMenuItemRender');
const menuRenders = {
menuItemRender,
subMenuItemRender,
};
const headerDom = computed(() =>
headerRender(
{
...props,
...menuRenders,
hasSiderMenu: !isTop.value,
menuData: props.menuData,
isMobile: unref(isMobile),
......@@ -235,6 +242,7 @@ const ProLayout = defineComponent({
{!isTop.value && (
<SiderMenuWrapper
{...restProps.value}
{...menuRenders}
isMobile={isMobile.value}
menuHeaderRender={menuHeaderRender}
collapsedButtonRender={collapsedButtonRender}
......
......@@ -8,6 +8,7 @@ import {
PropType,
isVNode,
ExtractPropTypes,
ConcreteComponent,
} from 'vue';
import { createFromIconfontCN } from '@ant-design/icons-vue';
import 'ant-design-vue/es/menu/style';
......@@ -30,8 +31,12 @@ export function useRootSubmenuKeys(menus: MenuDataItem[]): ComputedRef<string[]>
}
export interface CustomMenuRender {
menuItemRender?: WithFalse<(item: MenuDataItem) => CustomRender>;
subMenuItemRender?: WithFalse<(item: MenuDataItem, children?: CustomRender[]) => CustomRender>;
menuItemRender?: WithFalse<
(args: { item: MenuDataItem; title?: JSX.Element; icon?: JSX.Element }) => CustomRender
>;
subMenuItemRender?: WithFalse<
(args: { item: MenuDataItem; children?: CustomRender[] }) => CustomRender
>;
}
// vue props
......@@ -130,9 +135,12 @@ LazyIcon.props = {
class MenuUtil {
props: BaseMenuProps;
RouterLink: ConcreteComponent;
constructor(props: BaseMenuProps) {
this.props = props;
this.RouterLink = resolveComponent('router-link') as ConcreteComponent;
}
getNavMenuItems = (menusData: MenuDataItem[] = []) => {
......@@ -147,7 +155,10 @@ class MenuUtil {
!item?.meta?.hideChildrenInMenu
) {
if (this.props.subMenuItemRender) {
return this.props.subMenuItemRender(item, this.getNavMenuItems(item.children)) as VNode;
return this.props.subMenuItemRender({
item,
children: this.getNavMenuItems(item.children),
}) as VNode;
}
const { prefixCls, locale } = this.props;
const menuTitle = (locale && locale(item.meta?.title)) || item.meta?.title;
......@@ -176,7 +187,8 @@ class MenuUtil {
const [title, icon] = this.getMenuItem(item);
return (
((this.props.menuItemRender && this.props.menuItemRender(item)) as VNode) || (
((this.props.menuItemRender &&
this.props.menuItemRender({ item, title, icon })) as VNode) || (
<Menu.Item
disabled={item.meta?.disabled}
danger={item.meta?.danger}
......@@ -193,7 +205,7 @@ class MenuUtil {
const meta = { ...item.meta };
const target = (meta.target || null) as string | null;
const hasUrl = isUrl(item.path);
const CustomTag: any = (target && 'a') || resolveComponent('router-link');
const CustomTag: any = (target && 'a') || this.RouterLink;
const props = { to: { name: item.name } };
const attrs = hasUrl || target ? { ...item.meta, href: item.path, target } : {};
......@@ -209,13 +221,7 @@ class MenuUtil {
</CustomTag>
);
const icon =
(item.meta?.icon && (
<CustomTag {...attrs} {...props} class={`${prefixCls}-menu-item`}>
<LazyIcon icon={item.meta.icon} />
</CustomTag>
)) ||
null;
const icon = (item.meta?.icon && <LazyIcon icon={item.meta.icon} />) || undefined;
return [defaultTitle, icon];
};
......
......@@ -4,6 +4,7 @@ import {
ExtractPropTypes,
PropType,
CSSProperties,
unref,
} from 'vue';
import 'ant-design-vue/es/layout/style';
import Layout from 'ant-design-vue/es/layout';
......@@ -161,8 +162,9 @@ const SiderMenu: FC<SiderMenuProps> = (props: SiderMenuProps) => {
const context = useRouteContext();
const { getPrefixCls } = context;
const baseClassName = getPrefixCls('sider');
// const isMix = computed(() => props.layout === 'mix');
// const fixed = computed(() => context.fixSiderbar);
const hasSplitMenu = computed(() => props.layout === 'mix' && props.splitMenus);
const hasSide = computed(() => props.layout === 'mix' || props.layout === 'side' || false);
const sTheme = computed(() => (props.layout === 'mix' && 'light') || props.navTheme);
const sSideWidth = computed(() => (props.collapsed ? props.collapsedWidth : props.siderWidth));
const classNames = computed(() => {
......@@ -173,13 +175,18 @@ const SiderMenu: FC<SiderMenuProps> = (props: SiderMenuProps) => {
[`${baseClassName}-fixed`]: context.fixSiderbar,
};
});
const hasSide = computed(
() => ((props.layout === 'mix' || props.layout === 'side') && props.splitMenus) || false,
const flatMenuData = computed(
() => (hasSide.value && getMenuFirstChildren(context.menuData, context.selectedKeys[0])) || [],
);
const flatMenuData = computed(() => {
console.log('context.selectedKeys[0]', context.selectedKeys[0]);
return (hasSide.value && getMenuFirstChildren(context.menuData, context.selectedKeys[0])) || [];
});
const handleSelect = ($event: string[]) => {
if (props.onSelect) {
if (unref(hasSplitMenu)) {
props.onSelect([context.selectedKeys[0], ...$event]);
return;
}
props.onSelect($event);
}
};
// call menuHeaderRender
const headerDom = defaultRenderLogoAndTitle(props);
const extraDom = menuExtraRender && menuExtraRender(props);
......@@ -192,7 +199,7 @@ const SiderMenu: FC<SiderMenuProps> = (props: SiderMenuProps) => {
locale={props.locale || context.locale}
theme={sTheme.value === 'realDark' ? 'dark' : sTheme.value}
mode="inline"
menuData={hasSide.value ? flatMenuData.value : context.menuData}
menuData={hasSplitMenu.value ? flatMenuData.value : context.menuData}
collapsed={props.collapsed}
openKeys={context.openKeys}
selectedKeys={context.selectedKeys}
......@@ -205,7 +212,7 @@ const SiderMenu: FC<SiderMenuProps> = (props: SiderMenuProps) => {
class={`${baseClassName}-menu`}
{...{
'onUpdate:openKeys': ($event: string[]) => onOpenKeys && onOpenKeys($event),
'onUpdate:selectedKeys': ($event: string[]) => onSelect && onSelect($event),
'onUpdate:selectedKeys': handleSelect,
}}
/>
);
......
......@@ -27,5 +27,3 @@ export type { WaterMarkProps } from './WaterMark';
export { default } from './BasicLayout';
// export { default as ProLayout } from './BasicLayout';
export type { BasicLayoutProps } from './BasicLayout';
export { default as PageLoading } from './Pageloading';
......@@ -71,6 +71,10 @@ export function getPropsSlot(slots: Slots, props: Record<string, any>, prop = 'd
return props[prop] || slots[prop]?.();
}
export function getPropsSlotfn(slots: Slots, props: Record<string, any>, prop = 'default') {
return props[prop] || slots[prop];
}
export const PropRenderType = {
type: [Function, Boolean],
default: () => undefined,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment