diff --git a/packages/core/client/src/application/CustomRouterContextProvider.tsx b/packages/core/client/src/application/CustomRouterContextProvider.tsx index e9c2111bf5..c326b60f13 100644 --- a/packages/core/client/src/application/CustomRouterContextProvider.tsx +++ b/packages/core/client/src/application/CustomRouterContextProvider.tsx @@ -8,7 +8,16 @@ */ import React, { FC, useEffect } from 'react'; -import { Location, NavigateFunction, NavigateOptions, useLocation, useNavigate } from 'react-router-dom'; +import { + Location, + NavigateFunction, + NavigateOptions, + PathMatch, + useLocation, + useMatch, + useNavigate, + useParams, +} from 'react-router-dom'; const NavigateNoUpdateContext = React.createContext(null); NavigateNoUpdateContext.displayName = 'NavigateNoUpdateContext'; @@ -22,12 +31,36 @@ LocationSearchContext.displayName = 'LocationSearchContext'; const IsAdminPageContext = React.createContext(false); IsAdminPageContext.displayName = 'IsAdminPageContext'; +const CurrentPageUidContext = React.createContext(''); +CurrentPageUidContext.displayName = 'CurrentPageUidContext'; + +const MatchAdminContext = React.createContext | null>(null); +MatchAdminContext.displayName = 'MatchAdminContext'; + +const MatchAdminNameContext = React.createContext | null>(null); +MatchAdminNameContext.displayName = 'MatchAdminNameContext'; + +const MatchAdminProvider: FC = ({ children }) => { + const matchAdmin = useMatch('/admin'); + return {children}; +}; + +const MatchAdminNameProvider: FC = ({ children }) => { + const matchAdminName = useMatch('/admin/:name'); + return {children}; +}; + const IsAdminPageProvider: FC = ({ children }) => { const location = useLocation(); const isAdminPage = location.pathname.startsWith('/admin'); return {children}; }; +const CurrentPageUidProvider: FC = ({ children }) => { + const params = useParams(); + return {children}; +}; + /** * When the URL changes, components that use `useNavigate` will re-render. * This provider provides a `navigateNoUpdate` method that can avoid re-rendering. @@ -96,12 +129,30 @@ export const useIsAdminPage = () => { return React.useContext(IsAdminPageContext); }; +export const useCurrentPageUid = () => { + return React.useContext(CurrentPageUidContext); +}; + +export const useMatchAdmin = () => { + return React.useContext(MatchAdminContext); +}; + +export const useMatchAdminName = () => { + return React.useContext(MatchAdminNameContext); +}; + export const CustomRouterContextProvider: FC = ({ children }) => { return ( - {children} + + + + {children} + + + diff --git a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx index 2557af79b6..87370f53d2 100644 --- a/packages/core/client/src/route-switch/antd/admin-layout/index.tsx +++ b/packages/core/client/src/route-switch/antd/admin-layout/index.tsx @@ -12,7 +12,7 @@ import { useSessionStorageState } from 'ahooks'; import { App, ConfigProvider, Divider, Layout } from 'antd'; import { createGlobalStyle } from 'antd-style'; import React, { FC, createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; -import { Link, Outlet, useMatch, useParams } from 'react-router-dom'; +import { Link, Outlet, useParams } from 'react-router-dom'; import { ACLRolesCheckProvider, CurrentAppInfoProvider, @@ -33,7 +33,13 @@ import { useSystemSettings, useToken, } from '../../../'; -import { useLocationNoUpdate, useNavigateNoUpdate } from '../../../application/CustomRouterContextProvider'; +import { + useCurrentPageUid, + useLocationNoUpdate, + useMatchAdmin, + useMatchAdminName, + useNavigateNoUpdate, +} from '../../../application/CustomRouterContextProvider'; import { Plugin } from '../../../application/Plugin'; import { useAppSpin } from '../../../application/hooks/useAppSpin'; import { useMenuTranslation } from '../../../schema-component/antd/menu/locale'; @@ -82,12 +88,11 @@ const MenuEditor = (props) => { const { setTitle: _setTitle } = useDocumentTitle(); const setTitle = useCallback((title) => _setTitle(t(title)), []); const navigate = useNavigateNoUpdate(); - const params = useParams(); const location = useLocationNoUpdate(); - const isMatchAdmin = useMatch('/admin'); - const isMatchAdminName = useMatch('/admin/:name'); - const defaultSelectedUid = params.name; - const isDynamicPage = !!defaultSelectedUid; + const isMatchAdmin = useMatchAdmin(); + const isMatchAdminName = useMatchAdminName(); + const currentPageUid = useCurrentPageUid(); + const isDynamicPage = !!currentPageUid; const { sideMenuRef } = props; const ctx = useACLRoleContext(); const [current, setCurrent] = useState(null); @@ -126,7 +131,7 @@ const MenuEditor = (props) => { if (!isMatchAdminName || !isDynamicPage) return; // url 为 `admin/xxx` 的情况 - const s = findByUid(schema, defaultSelectedUid); + const s = findByUid(schema, currentPageUid); if (s) { setTitle(s.title); } else { @@ -147,7 +152,9 @@ const MenuEditor = (props) => { if (sideMenuRef.current) { const pageType = properties && - Object.values(properties).find((item) => item['x-uid'] === params.name && item['x-component'] === 'Menu.Item'); + Object.values(properties).find( + (item) => item['x-uid'] === currentPageUid && item['x-component'] === 'Menu.Item', + ); const isSettingPage = location?.pathname.includes('/settings'); if (pageType || isSettingPage) { sideMenuRef.current.style.display = 'none'; @@ -155,7 +162,7 @@ const MenuEditor = (props) => { sideMenuRef.current.style.display = 'block'; } } - }, [data?.data, params.name, sideMenuRef, location?.pathname]); + }, [data?.data, currentPageUid, sideMenuRef, location?.pathname]); const schema = useMemo(() => { const s = filterByACL(data?.data, ctx); @@ -167,12 +174,12 @@ const MenuEditor = (props) => { useEffect(() => { if (isMatchAdminName) { - const s = findByUid(schema, defaultSelectedUid); + const s = findByUid(schema, currentPageUid); if (s) { setTitle(s.title); } } - }, [defaultSelectedUid, isMatchAdmin, isMatchAdminName, schema, setTitle]); + }, [currentPageUid, isMatchAdmin, isMatchAdminName, schema, setTitle]); useRequest( { @@ -213,14 +220,14 @@ const MenuEditor = (props) => { ); const scope = useMemo(() => { - return { useMenuProps, onSelect, sideMenuRef, defaultSelectedUid }; + return { useMenuProps, onSelect, sideMenuRef, defaultSelectedUid: currentPageUid }; }, []); if (loading) { return render(); } return ( - + );