oak-cli/template/web/src/AppRouter.tsx

100 lines
2.9 KiB
TypeScript

import React from 'react';
import { Routes, Route, Outlet, useLocation } from 'react-router-dom';
import { IRouter, IBrowserRouterProps, IMeta } from './types/router';
import routers from './app/routers';
import Loading from './app/components/Loading';
import useFeatures from '@project/hooks/useFeatures';
type TRenderRoutes = (
routes?: IRouter[],
breadcrumbs?: string[]
) => React.ReactNode[] | null;
/**
* 渲染应用路由
* @param routes
* @param breadcrumb
*/
const renderRoutes: TRenderRoutes = (routes = [], breadcrumb = []) => {
if (routes.length === 0) return null;
return routes.map((route, index: number) => {
const { Component, children, namespace, meta, isFirst, customRouter } =
route;
let currentBreadcrumb = breadcrumb;
let props = {};
if (isFirst) {
props = {
index: true,
};
} else {
props = {
path: route.path,
};
}
return (
<Route
{...props}
key={index}
element={
<Guard
Component={Component}
meta={meta}
breadcrumb={currentBreadcrumb}
namespace={namespace}
customRouter={customRouter}
/>
}
>
{renderRoutes(children, currentBreadcrumb)}
</Route>
);
});
};
const Guard = React.memo(
(props: {
Component?: React.FC<IBrowserRouterProps> | (() => any);
namespace?: string;
meta?: IMeta;
breadcrumb: string[];
customRouter?: boolean;
}) => {
const { Component, namespace, meta, breadcrumb, customRouter } = props;
const features = useFeatures();
const location = useLocation();
const { pathname } = location;
const path = namespace ? pathname.slice(namespace.length) : pathname;
const i18nNs = `taicang-p-${
path.startsWith('/')
? path.slice(1).replaceAll(/\//g, '-')
: path.replaceAll(/\//g, '-')
}`;
if (i18nNs) {
const windowTitle = features.locales.hasKey(`${i18nNs}.pageTitle`);
if (windowTitle) {
breadcrumb.push(windowTitle);
window.document.title = windowTitle;
}
}
return Component ? (
<React.Suspense fallback={<Loading />}>
<Component
oakDisablePulldownRefresh={meta?.oakDisablePulldownRefresh}
namespace={namespace || ''}
customRouter={customRouter}
/>
</React.Suspense>
) : (
<Outlet />
);
}
);
const AppRouter = React.memo(() => (
<Routes>{renderRoutes(routers)}</Routes>
));
export default AppRouter;