From 44861303b0c236ec36f3bb55f469229e23116e5d Mon Sep 17 00:00:00 2001 From: SheRunFeng <541899641@qq.com> Date: Mon, 26 Sep 2022 12:28:10 +0800 Subject: [PATCH] feat(): support router if condition --- etc/brick-types.api.md | 1 + .../brick-kit/src/core/LocationContext.ts | 2 + packages/brick-types/src/manifest.ts | 4 ++ packages/brick-utils/src/matchPath.spec.ts | 37 +++++++++++++++---- packages/brick-utils/src/matchPath.ts | 27 ++++++++++++-- 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/etc/brick-types.api.md b/etc/brick-types.api.md index 4c33ca3cff..241ecd0d56 100644 --- a/etc/brick-types.api.md +++ b/etc/brick-types.api.md @@ -114,6 +114,7 @@ export interface BaseRouteConf { documentId?: string; exact?: boolean; hybrid?: boolean; + if?: string | boolean; menu?: MenuConf; path: string; permissionsPreCheck?: string[]; diff --git a/packages/brick-kit/src/core/LocationContext.ts b/packages/brick-kit/src/core/LocationContext.ts index 53e83c3dd6..690e6ead17 100644 --- a/packages/brick-kit/src/core/LocationContext.ts +++ b/packages/brick-kit/src/core/LocationContext.ts @@ -222,6 +222,8 @@ export class LocationContext { const match = matchPath(this.location.pathname, { path: computedPath, exact: route.exact, + checkIf: (context) => looseCheckIf(route, context), + getContext: (match) => this.getContext({ match }), }); if (match !== null) { if (app.noAuthGuard || route.public || isLoggedIn()) { diff --git a/packages/brick-types/src/manifest.ts b/packages/brick-types/src/manifest.ts index 537f6df050..d6b5bbb4b5 100644 --- a/packages/brick-types/src/manifest.ts +++ b/packages/brick-types/src/manifest.ts @@ -353,6 +353,10 @@ export interface RouteConfOfRedirect extends BaseRouteConf { * 路由的基本配置信息。 */ export interface BaseRouteConf { + /** + * 条件配置,根据 `if` 的计算结果来决定是否展示路由 + */ + if?: string | boolean; /** * 路由地址,通常应使用 `${APP.homepage}` 开头。 */ diff --git a/packages/brick-utils/src/matchPath.spec.ts b/packages/brick-utils/src/matchPath.spec.ts index 4c55f8f489..7bcebdacd8 100644 --- a/packages/brick-utils/src/matchPath.spec.ts +++ b/packages/brick-utils/src/matchPath.spec.ts @@ -1,12 +1,8 @@ -import { matchPath, toPath } from "./matchPath"; -import { - MatchOptions, - CompileOptions, - MatchResult, -} from "@next-core/brick-types"; +import { matchPath, MatchPathOptions, toPath } from "./matchPath"; +import { MatchResult } from "@next-core/brick-types"; describe("matchPath", () => { - it.each<[string, MatchOptions & CompileOptions, MatchResult]>([ + it.each<[string, MatchPathOptions, MatchResult]>([ [ "/", { @@ -72,6 +68,33 @@ describe("matchPath", () => { }, null, ], + [ + "/next", + { + path: ["/:id", "/before"], + exact: true, + checkIf: () => true, + getContext: () => ({} as any), + }, + { + path: "/:id", + url: "/next", + isExact: true, + params: { + id: "next", + }, + }, + ], + [ + "/next", + { + path: ["/:id", "/before"], + exact: true, + checkIf: () => false, + getContext: () => ({} as any), + }, + null, + ], ])("matchPath('%s', %j) should return %j", (pathname, options, result) => { expect(matchPath(pathname, options)).toEqual(result); }); diff --git a/packages/brick-utils/src/matchPath.ts b/packages/brick-utils/src/matchPath.ts index a36bd48fe1..c6546ffa03 100644 --- a/packages/brick-utils/src/matchPath.ts +++ b/packages/brick-utils/src/matchPath.ts @@ -6,8 +6,15 @@ import { MatchOptions, MatchResult, MatchParams, + PluginRuntimeContext, } from "@next-core/brick-types"; +export type MatchPathOptions = MatchOptions & + CompileOptions & { + checkIf?: (context: PluginRuntimeContext) => boolean; + getContext?: (match: any) => PluginRuntimeContext; + }; + const cache: Map> = new Map(); const cacheLimit = 10000; let cacheCount = 0; @@ -40,9 +47,16 @@ function compilePath(path: string, options: CompileOptions): CompileResult { */ export function matchPath( pathname: string, - options: MatchOptions & CompileOptions + options: MatchPathOptions ): MatchResult { - const { path: p, exact = false, strict = false, sensitive = true } = options; + const { + path: p, + exact = false, + strict = false, + sensitive = true, + checkIf, + getContext, + } = options; const paths = Array.isArray(p) ? p : [p]; @@ -69,8 +83,7 @@ export function matchPath( } const initialParams: MatchParams = {}; - - return { + const result = { path, // the path used to match url: path === "/" && url === "" ? "/" : url, // the matched portion of the URL isExact, // whether or not we matched exactly @@ -79,6 +92,12 @@ export function matchPath( return memo; }, initialParams), }; + + if (checkIf && !checkIf(getContext(result))) { + return null; + } + + return result; }, null); }