openxiangda 1.0.65 → 1.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/packages/sdk/dist/runtime/index.cjs +12 -2
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.mjs +12 -2
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/react.cjs +1 -1
- package/packages/sdk/dist/runtime/react.cjs.map +1 -1
- package/packages/sdk/dist/runtime/react.mjs +1 -1
- package/packages/sdk/dist/runtime/react.mjs.map +1 -1
- package/templates/openxiangda-react-spa/src/app/router.tsx +75 -1
- package/templates/openxiangda-react-spa/src/layouts/AdminShell.tsx +85 -17
|
@@ -333,7 +333,7 @@ var useRuntimeAuth = () => {
|
|
|
333
333
|
if (configuredLoginUrl) {
|
|
334
334
|
return attachCallback(configuredLoginUrl, redirectUri);
|
|
335
335
|
}
|
|
336
|
-
return attachCallback("/login", redirectUri);
|
|
336
|
+
return attachCallback("/platform/login", redirectUri);
|
|
337
337
|
},
|
|
338
338
|
[runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix]
|
|
339
339
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/react/openxiangdaProvider.tsx","../../src/runtime/core/fetch.ts"],"sourcesContent":["import React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\"\nimport { createBoundFetch } from \"../core/fetch\"\n\nexport type RuntimeErrorType =\n | \"unauthenticated\"\n | \"forbidden\"\n | \"network\"\n | \"unknown\"\n\nexport type RuntimeRequestError = Error & {\n type?: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n}\n\nexport interface RuntimeErrorSnapshot {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n payload?: unknown\n}\n\nexport class RuntimeHttpError extends Error {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n\n constructor(snapshot: RuntimeErrorSnapshot) {\n super(snapshot.message)\n this.name = \"RuntimeHttpError\"\n this.type = snapshot.type\n this.status = snapshot.status\n this.code = snapshot.code\n this.payload = snapshot.payload\n }\n}\n\nexport interface RuntimeMenuItem {\n id: string\n name: string\n resourceCode?: string | null\n routeCode?: string | null\n path?: string | null\n type?: string\n formUuid?: string | null\n pageId?: string | null\n parentId?: string | null\n sortOrder?: number\n isHidden?: boolean\n icon?: string | null\n children?: RuntimeMenuItem[]\n [key: string]: unknown\n}\n\nexport interface RuntimePagePermissions {\n appType: string\n hasFullAccess: boolean\n roleCodes: string[]\n roleSource?: string\n menuFormUuids: string[]\n menuCodes: string[]\n routeCodes: string[]\n pathPatterns: string[]\n}\n\nexport interface RuntimeBootstrap {\n appType: string\n app?: Record<string, unknown> | null\n user?: Record<string, unknown> | null\n runtime?: {\n mode?: \"legacy\" | \"react-spa\" | string\n settings?: Record<string, unknown>\n activeReleaseId?: string | null\n activeBuildId?: string | null\n indexUrl?: string | null\n assetBaseUrl?: string | null\n }\n permissions?: RuntimePagePermissions\n menus?: RuntimeMenuItem[]\n servicePrefix?: string\n}\n\nexport interface RouteAccessResult {\n appType: string\n canAccess: boolean\n routeCode?: string\n menuCode?: string\n path?: string\n status?: number\n code?: number | string\n message?: string\n errorType?: RuntimeErrorType\n payload?: unknown\n permissions?: RuntimePagePermissions\n}\n\nexport interface RuntimeRequestState<T> {\n data: T | null\n loading: boolean\n error: RuntimeRequestError | null\n}\n\nexport interface OpenXiangdaProviderProps {\n appType?: string\n servicePrefix?: string\n fetchImpl?: typeof fetch\n children: React.ReactNode\n}\n\ninterface OpenXiangdaRuntimeStore extends RuntimeRequestState<RuntimeBootstrap> {\n appType: string\n servicePrefix: string\n fetchImpl: typeof fetch\n reload: () => Promise<void>\n}\n\nconst OpenXiangdaRuntimeContext =\n createContext<OpenXiangdaRuntimeStore | null>(null)\n\nexport const OpenXiangdaProvider: React.FC<OpenXiangdaProviderProps> = ({\n appType,\n servicePrefix = \"/service\",\n fetchImpl,\n children,\n}) => {\n const resolvedFetch = useMemo(() => createBoundFetch(fetchImpl), [fetchImpl])\n const resolvedAppType = useMemo(\n () => appType || resolveAppTypeFromLocation(),\n [appType],\n )\n const [state, setState] = useState<RuntimeRequestState<RuntimeBootstrap>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const reload = useCallback(async () => {\n if (!resolvedAppType) {\n setState({\n data: null,\n loading: false,\n error: createRuntimeError({\n message: \"appType 不能为空\",\n type: \"unknown\",\n }),\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await resolvedFetch(\n buildServiceUrl(\n servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n resolvedAppType,\n )}/runtime/bootstrap`,\n ),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Runtime bootstrap failed: ${response.status}`,\n )\n }\n setState({\n data: payload?.data || null,\n loading: false,\n error: null,\n })\n } catch (error) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }, [resolvedAppType, resolvedFetch, servicePrefix])\n\n useEffect(() => {\n void reload()\n }, [reload])\n\n const value = useMemo<OpenXiangdaRuntimeStore>(\n () => ({\n ...state,\n appType: resolvedAppType,\n servicePrefix,\n fetchImpl: resolvedFetch,\n reload,\n }),\n [reload, resolvedAppType, resolvedFetch, servicePrefix, state],\n )\n\n return (\n <OpenXiangdaRuntimeContext.Provider value={value}>\n {children}\n </OpenXiangdaRuntimeContext.Provider>\n )\n}\n\nexport const useOpenXiangda = () => {\n const context = useContext(OpenXiangdaRuntimeContext)\n if (!context) {\n throw new Error(\"useOpenXiangda must be used inside OpenXiangdaProvider\")\n }\n return context\n}\n\nexport const useRuntimeBootstrap = () => useOpenXiangda()\n\nexport const useAppMenus = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.menus || [],\n }\n}\n\nexport const usePermission = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.permissions || null,\n }\n}\n\nexport interface UseCanAccessRouteInput {\n routeCode?: string\n menuCode?: string\n path?: string\n}\n\nexport const useCanAccessRoute = (input: UseCanAccessRouteInput) => {\n const runtime = useOpenXiangda()\n const [state, setState] = useState<RuntimeRequestState<RouteAccessResult>>({\n data: null,\n loading: true,\n error: null,\n })\n\n useEffect(() => {\n let disposed = false\n const check = async () => {\n const permissions = runtime.data?.permissions\n if (!runtime.appType || runtime.loading) {\n setState(prev => ({ ...prev, loading: runtime.loading }))\n return\n }\n if (runtime.error && !runtime.data) {\n const snapshot = toRuntimeErrorSnapshot(runtime.error)\n setState({\n data: {\n appType: runtime.appType,\n canAccess: false,\n status: snapshot.status,\n code: snapshot.code,\n message: snapshot.message,\n errorType: snapshot.type,\n payload: snapshot.payload,\n },\n loading: false,\n error: runtime.error,\n })\n return\n }\n if (permissions?.hasFullAccess) {\n setState({\n data: { appType: runtime.appType, canAccess: true, permissions },\n loading: false,\n error: null,\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await runtime.fetchImpl(\n buildServiceUrl(\n runtime.servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n runtime.appType,\n )}/runtime/routes/check`,\n ),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(input),\n },\n )\n const payload = await readJsonPayload(response)\n const code = payload?.code ?? response.status\n const canAccess = Boolean(payload?.data?.canAccess)\n const errorType = canAccess\n ? undefined\n : classifyRuntimeError(response.status, code)\n const data: RouteAccessResult = {\n ...(payload?.data || {\n appType: runtime.appType,\n canAccess: false,\n }),\n appType: payload?.data?.appType || runtime.appType,\n canAccess,\n status: response.status,\n code,\n message: payload?.message,\n errorType,\n payload,\n }\n if (!disposed) {\n const shouldTreatAsError =\n !response.ok || (typeof code === \"number\" && code >= 500)\n setState({\n data,\n loading: false,\n error: shouldTreatAsError\n ? createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Route check failed: ${response.status}`,\n )\n : null,\n })\n }\n } catch (error) {\n if (!disposed) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }\n }\n void check()\n return () => {\n disposed = true\n }\n }, [\n input.menuCode,\n input.path,\n input.routeCode,\n runtime.appType,\n runtime.data?.permissions,\n runtime.fetchImpl,\n runtime.loading,\n runtime.servicePrefix,\n ])\n\n return {\n ...state,\n canAccess: Boolean(state.data?.canAccess),\n }\n}\n\nexport interface PermissionBoundaryProps extends UseCanAccessRouteInput {\n children: React.ReactNode\n fallback?: React.ReactNode | PermissionBoundaryFallback\n loadingFallback?: React.ReactNode | PermissionBoundaryFallback\n}\n\nexport interface PermissionBoundaryFallbackState {\n access: ReturnType<typeof useCanAccessRoute>\n runtime: ReturnType<typeof useOpenXiangda>\n error: RuntimeRequestError | null\n errorType: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n}\n\nexport type PermissionBoundaryFallback = (\n state: PermissionBoundaryFallbackState,\n) => React.ReactNode\n\nexport const PermissionBoundary: React.FC<PermissionBoundaryProps> = ({\n children,\n fallback = null,\n loadingFallback = null,\n routeCode,\n menuCode,\n path,\n}) => {\n const runtime = useOpenXiangda()\n const access = useCanAccessRoute({ routeCode, menuCode, path })\n const fallbackState = createPermissionFallbackState(access, runtime)\n if (access.loading) {\n return <>{renderBoundaryFallback(loadingFallback, fallbackState)}</>\n }\n if (!access.canAccess) {\n return <>{renderBoundaryFallback(fallback, fallbackState)}</>\n }\n return <>{children}</>\n}\n\nexport interface RuntimeResolveLoginOptions {\n redirectUri?: string\n loginUrl?: string\n domain?: string\n}\n\nexport interface RuntimeRedirectLoginOptions extends RuntimeResolveLoginOptions {\n replace?: boolean\n}\n\nexport interface RuntimeLogoutOptions extends RuntimeRedirectLoginOptions {\n continueOnError?: boolean\n}\n\nexport const useRuntimeAuth = () => {\n const runtime = useOpenXiangda()\n\n const resolveLoginUrl = useCallback(\n async (options: RuntimeResolveLoginOptions = {}) => {\n const redirectUri = options.redirectUri || getCurrentHref()\n const domain = options.domain || getCurrentHostname()\n const appTenantId = getRecordString(runtime.data?.app, \"tenantId\")\n\n try {\n const statusUrl = withQuery(\n buildServiceUrl(runtime.servicePrefix, \"/api/sso/status\"),\n { domain },\n )\n const statusResponse = await runtime.fetchImpl(statusUrl, {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n })\n const statusPayload = await readJsonPayload(statusResponse)\n const sso = statusPayload?.data || {}\n const enabled = Boolean(sso.enabled)\n const shouldUseSso = Boolean(\n enabled && (sso.forceLogin ?? sso.autoRedirect ?? true),\n )\n if (shouldUseSso) {\n const loginUrlResponse = await runtime.fetchImpl(\n withQuery(buildServiceUrl(runtime.servicePrefix, \"/api/sso/login-url\"), {\n domain,\n redirectUri,\n ...(sso.tenantId || appTenantId\n ? { tenantId: String(sso.tenantId || appTenantId) }\n : {}),\n ...(sso.protocol ? { protocol: String(sso.protocol) } : {}),\n }),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const loginUrlPayload = await readJsonPayload(loginUrlResponse)\n const loginUrl =\n loginUrlPayload?.data?.loginUrl ||\n loginUrlPayload?.data?.url ||\n loginUrlPayload?.loginUrl ||\n loginUrlPayload?.url\n if (loginUrl) return String(loginUrl)\n }\n } catch {\n // Login resolution must always have a local fallback so logged-out\n // users are not stranded behind a permission state.\n }\n\n const configuredLoginUrl =\n options.loginUrl ||\n getRuntimeEnv(\"OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_BATH_AUTH_URL\") ||\n getRuntimeEnv(\"BATH_AUTH_URL\")\n if (configuredLoginUrl) {\n return attachCallback(configuredLoginUrl, redirectUri)\n }\n return attachCallback(\"/login\", redirectUri)\n },\n [runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix],\n )\n\n const redirectToLogin = useCallback(\n async (options: RuntimeRedirectLoginOptions = {}) => {\n const loginUrl = await resolveLoginUrl(options)\n if (typeof window !== \"undefined\") {\n if (options.replace === false) {\n window.location.assign(loginUrl)\n } else {\n window.location.replace(loginUrl)\n }\n }\n return loginUrl\n },\n [resolveLoginUrl],\n )\n\n const logout = useCallback(async () => {\n const response = await runtime.fetchImpl(\n buildServiceUrl(runtime.servicePrefix, \"/api/auth/logout\"),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Logout failed: ${response.status}`,\n )\n }\n return payload\n }, [runtime.fetchImpl, runtime.servicePrefix])\n\n const logoutAndRedirect = useCallback(\n async (options: RuntimeLogoutOptions = {}) => {\n try {\n await logout()\n } catch (error) {\n if (options.continueOnError === false) throw error\n }\n return redirectToLogin(options)\n },\n [logout, redirectToLogin],\n )\n\n return {\n logout,\n logoutAndRedirect,\n redirectToLogin,\n resolveLoginUrl,\n }\n}\n\nconst buildServiceUrl = (servicePrefix: string, path: string) => {\n const prefix = servicePrefix.endsWith(\"/\")\n ? servicePrefix.slice(0, -1)\n : servicePrefix\n const suffix = path.startsWith(\"/\") ? path : `/${path}`\n return `${prefix}${suffix}`\n}\n\nconst readJsonPayload = async (response: Response) => {\n try {\n return await response.json()\n } catch {\n return null\n }\n}\n\nconst createRuntimeHttpError = (\n response: Response,\n payload: unknown,\n fallbackMessage: string,\n): RuntimeRequestError =>\n createRuntimeError({\n type: classifyRuntimeError(\n response.status,\n getRecordValue(payload, \"code\") as number | string | undefined,\n ),\n status: response.status,\n code: getRecordValue(payload, \"code\") as number | string | undefined,\n message:\n (getRecordValue(payload, \"message\") as string | undefined) ||\n fallbackMessage,\n payload,\n })\n\nconst createRuntimeError = (\n snapshot: RuntimeErrorSnapshot,\n): RuntimeRequestError =>\n new RuntimeHttpError({\n ...snapshot,\n type: snapshot.type || \"unknown\",\n message: snapshot.message || \"Runtime request failed\",\n })\n\nconst normalizeRuntimeError = (error: unknown): RuntimeRequestError => {\n if (error instanceof RuntimeHttpError) return error\n if (error instanceof Error) {\n const runtimeError = error as RuntimeRequestError\n runtimeError.type = runtimeError.type || classifyRuntimeError(runtimeError.status, runtimeError.code)\n return runtimeError\n }\n return createRuntimeError({\n type: \"unknown\",\n message: String(error),\n })\n}\n\nconst toRuntimeErrorSnapshot = (\n error: RuntimeRequestError,\n): RuntimeErrorSnapshot => ({\n type: error.type || classifyRuntimeError(error.status, error.code),\n status: error.status,\n code: error.code,\n message: error.message || \"Runtime request failed\",\n payload: error.payload,\n})\n\nconst classifyRuntimeError = (\n status?: number,\n code?: number | string,\n): RuntimeErrorType => {\n const normalizedCode = typeof code === \"string\" ? Number(code) : code\n if (status === 401 || normalizedCode === 401) return \"unauthenticated\"\n if (status === 403 || normalizedCode === 403) return \"forbidden\"\n if (!status && !normalizedCode) return \"network\"\n return \"unknown\"\n}\n\nconst createPermissionFallbackState = (\n access: ReturnType<typeof useCanAccessRoute>,\n runtime: ReturnType<typeof useOpenXiangda>,\n): PermissionBoundaryFallbackState => {\n const error = access.error || runtime.error\n const accessData = access.data\n const errorType =\n accessData?.errorType ||\n error?.type ||\n (!access.canAccess ? \"forbidden\" : \"unknown\")\n return {\n access,\n runtime,\n error,\n errorType,\n status: accessData?.status || error?.status,\n code: accessData?.code || error?.code,\n message:\n accessData?.message ||\n error?.message ||\n (errorType === \"unauthenticated\"\n ? \"当前账号尚未登录\"\n : \"当前账号没有访问权限\"),\n }\n}\n\nconst renderBoundaryFallback = (\n fallback: React.ReactNode | PermissionBoundaryFallback,\n state: PermissionBoundaryFallbackState,\n) => (typeof fallback === \"function\" ? fallback(state) : fallback)\n\nconst withQuery = (\n url: string,\n params: Record<string, string | number | boolean | undefined>,\n) => {\n const query = new URLSearchParams()\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === \"\") return\n query.set(key, String(value))\n })\n const serialized = query.toString()\n if (!serialized) return url\n return `${url}${url.includes(\"?\") ? \"&\" : \"?\"}${serialized}`\n}\n\nconst attachCallback = (loginUrl: string, callback: string) => {\n if (!callback) return loginUrl\n try {\n const base =\n typeof window !== \"undefined\" ? window.location.origin : \"http://localhost\"\n const parsed = new URL(loginUrl, base)\n if (!parsed.searchParams.has(\"callback\") && !parsed.searchParams.has(\"redirectUri\")) {\n parsed.searchParams.set(\"callback\", callback)\n }\n if (loginUrl.startsWith(\"http://\") || loginUrl.startsWith(\"https://\")) {\n return parsed.toString()\n }\n return `${parsed.pathname}${parsed.search}${parsed.hash}`\n } catch {\n const separator = loginUrl.includes(\"?\") ? \"&\" : \"?\"\n return `${loginUrl}${separator}callback=${encodeURIComponent(callback)}`\n }\n}\n\nconst getCurrentHref = () =>\n typeof window === \"undefined\" ? \"\" : window.location.href\n\nconst getCurrentHostname = () =>\n typeof window === \"undefined\" ? \"\" : window.location.hostname\n\nconst getRuntimeEnv = (key: string) => {\n const env =\n typeof process !== \"undefined\"\n ? (process as unknown as { env?: Record<string, string | undefined> }).env\n : undefined\n return env?.[key]\n}\n\nconst getRecordValue = (value: unknown, key: string) => {\n if (!value || typeof value !== \"object\") return undefined\n return (value as Record<string, unknown>)[key]\n}\n\nconst getRecordString = (value: unknown, key: string) => {\n const result = getRecordValue(value, key)\n return typeof result === \"string\" ? result : undefined\n}\n\nconst resolveAppTypeFromLocation = () => {\n if (typeof window === \"undefined\") return \"\"\n const segments = window.location.pathname.split(\"/\").filter(Boolean)\n const viewIndex = segments[0] === \"view\" ? 1 : 0\n if (segments[viewIndex] === \"submit\") return segments[viewIndex + 1] || \"\"\n if (segments[viewIndex] === \"preview\") return segments[viewIndex + 1] || \"\"\n return segments[viewIndex] || \"\"\n}\n","export const createBoundFetch = (fetchImpl?: typeof fetch): typeof fetch => {\n const baseFetch = fetchImpl || globalThis.fetch;\n return ((input, init) => baseFetch.call(globalThis, input, init)) as typeof fetch;\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/react/openxiangdaProvider.tsx","../../src/runtime/core/fetch.ts"],"sourcesContent":["import React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\"\nimport { createBoundFetch } from \"../core/fetch\"\n\nexport type RuntimeErrorType =\n | \"unauthenticated\"\n | \"forbidden\"\n | \"network\"\n | \"unknown\"\n\nexport type RuntimeRequestError = Error & {\n type?: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n}\n\nexport interface RuntimeErrorSnapshot {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n payload?: unknown\n}\n\nexport class RuntimeHttpError extends Error {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n\n constructor(snapshot: RuntimeErrorSnapshot) {\n super(snapshot.message)\n this.name = \"RuntimeHttpError\"\n this.type = snapshot.type\n this.status = snapshot.status\n this.code = snapshot.code\n this.payload = snapshot.payload\n }\n}\n\nexport interface RuntimeMenuItem {\n id: string\n name: string\n resourceCode?: string | null\n routeCode?: string | null\n path?: string | null\n type?: string\n formUuid?: string | null\n pageId?: string | null\n parentId?: string | null\n sortOrder?: number\n isHidden?: boolean\n icon?: string | null\n children?: RuntimeMenuItem[]\n [key: string]: unknown\n}\n\nexport interface RuntimePagePermissions {\n appType: string\n hasFullAccess: boolean\n roleCodes: string[]\n roleSource?: string\n menuFormUuids: string[]\n menuCodes: string[]\n routeCodes: string[]\n pathPatterns: string[]\n}\n\nexport interface RuntimeBootstrap {\n appType: string\n app?: Record<string, unknown> | null\n user?: Record<string, unknown> | null\n runtime?: {\n mode?: \"legacy\" | \"react-spa\" | string\n settings?: Record<string, unknown>\n activeReleaseId?: string | null\n activeBuildId?: string | null\n indexUrl?: string | null\n assetBaseUrl?: string | null\n }\n permissions?: RuntimePagePermissions\n menus?: RuntimeMenuItem[]\n servicePrefix?: string\n}\n\nexport interface RouteAccessResult {\n appType: string\n canAccess: boolean\n routeCode?: string\n menuCode?: string\n path?: string\n status?: number\n code?: number | string\n message?: string\n errorType?: RuntimeErrorType\n payload?: unknown\n permissions?: RuntimePagePermissions\n}\n\nexport interface RuntimeRequestState<T> {\n data: T | null\n loading: boolean\n error: RuntimeRequestError | null\n}\n\nexport interface OpenXiangdaProviderProps {\n appType?: string\n servicePrefix?: string\n fetchImpl?: typeof fetch\n children: React.ReactNode\n}\n\ninterface OpenXiangdaRuntimeStore extends RuntimeRequestState<RuntimeBootstrap> {\n appType: string\n servicePrefix: string\n fetchImpl: typeof fetch\n reload: () => Promise<void>\n}\n\nconst OpenXiangdaRuntimeContext =\n createContext<OpenXiangdaRuntimeStore | null>(null)\n\nexport const OpenXiangdaProvider: React.FC<OpenXiangdaProviderProps> = ({\n appType,\n servicePrefix = \"/service\",\n fetchImpl,\n children,\n}) => {\n const resolvedFetch = useMemo(() => createBoundFetch(fetchImpl), [fetchImpl])\n const resolvedAppType = useMemo(\n () => appType || resolveAppTypeFromLocation(),\n [appType],\n )\n const [state, setState] = useState<RuntimeRequestState<RuntimeBootstrap>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const reload = useCallback(async () => {\n if (!resolvedAppType) {\n setState({\n data: null,\n loading: false,\n error: createRuntimeError({\n message: \"appType 不能为空\",\n type: \"unknown\",\n }),\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await resolvedFetch(\n buildServiceUrl(\n servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n resolvedAppType,\n )}/runtime/bootstrap`,\n ),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Runtime bootstrap failed: ${response.status}`,\n )\n }\n setState({\n data: payload?.data || null,\n loading: false,\n error: null,\n })\n } catch (error) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }, [resolvedAppType, resolvedFetch, servicePrefix])\n\n useEffect(() => {\n void reload()\n }, [reload])\n\n const value = useMemo<OpenXiangdaRuntimeStore>(\n () => ({\n ...state,\n appType: resolvedAppType,\n servicePrefix,\n fetchImpl: resolvedFetch,\n reload,\n }),\n [reload, resolvedAppType, resolvedFetch, servicePrefix, state],\n )\n\n return (\n <OpenXiangdaRuntimeContext.Provider value={value}>\n {children}\n </OpenXiangdaRuntimeContext.Provider>\n )\n}\n\nexport const useOpenXiangda = () => {\n const context = useContext(OpenXiangdaRuntimeContext)\n if (!context) {\n throw new Error(\"useOpenXiangda must be used inside OpenXiangdaProvider\")\n }\n return context\n}\n\nexport const useRuntimeBootstrap = () => useOpenXiangda()\n\nexport const useAppMenus = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.menus || [],\n }\n}\n\nexport const usePermission = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.permissions || null,\n }\n}\n\nexport interface UseCanAccessRouteInput {\n routeCode?: string\n menuCode?: string\n path?: string\n}\n\nexport const useCanAccessRoute = (input: UseCanAccessRouteInput) => {\n const runtime = useOpenXiangda()\n const [state, setState] = useState<RuntimeRequestState<RouteAccessResult>>({\n data: null,\n loading: true,\n error: null,\n })\n\n useEffect(() => {\n let disposed = false\n const check = async () => {\n const permissions = runtime.data?.permissions\n if (!runtime.appType || runtime.loading) {\n setState(prev => ({ ...prev, loading: runtime.loading }))\n return\n }\n if (runtime.error && !runtime.data) {\n const snapshot = toRuntimeErrorSnapshot(runtime.error)\n setState({\n data: {\n appType: runtime.appType,\n canAccess: false,\n status: snapshot.status,\n code: snapshot.code,\n message: snapshot.message,\n errorType: snapshot.type,\n payload: snapshot.payload,\n },\n loading: false,\n error: runtime.error,\n })\n return\n }\n if (permissions?.hasFullAccess) {\n setState({\n data: { appType: runtime.appType, canAccess: true, permissions },\n loading: false,\n error: null,\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await runtime.fetchImpl(\n buildServiceUrl(\n runtime.servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n runtime.appType,\n )}/runtime/routes/check`,\n ),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(input),\n },\n )\n const payload = await readJsonPayload(response)\n const code = payload?.code ?? response.status\n const canAccess = Boolean(payload?.data?.canAccess)\n const errorType = canAccess\n ? undefined\n : classifyRuntimeError(response.status, code)\n const data: RouteAccessResult = {\n ...(payload?.data || {\n appType: runtime.appType,\n canAccess: false,\n }),\n appType: payload?.data?.appType || runtime.appType,\n canAccess,\n status: response.status,\n code,\n message: payload?.message,\n errorType,\n payload,\n }\n if (!disposed) {\n const shouldTreatAsError =\n !response.ok || (typeof code === \"number\" && code >= 500)\n setState({\n data,\n loading: false,\n error: shouldTreatAsError\n ? createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Route check failed: ${response.status}`,\n )\n : null,\n })\n }\n } catch (error) {\n if (!disposed) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }\n }\n void check()\n return () => {\n disposed = true\n }\n }, [\n input.menuCode,\n input.path,\n input.routeCode,\n runtime.appType,\n runtime.data?.permissions,\n runtime.fetchImpl,\n runtime.loading,\n runtime.servicePrefix,\n ])\n\n return {\n ...state,\n canAccess: Boolean(state.data?.canAccess),\n }\n}\n\nexport interface PermissionBoundaryProps extends UseCanAccessRouteInput {\n children: React.ReactNode\n fallback?: React.ReactNode | PermissionBoundaryFallback\n loadingFallback?: React.ReactNode | PermissionBoundaryFallback\n}\n\nexport interface PermissionBoundaryFallbackState {\n access: ReturnType<typeof useCanAccessRoute>\n runtime: ReturnType<typeof useOpenXiangda>\n error: RuntimeRequestError | null\n errorType: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n}\n\nexport type PermissionBoundaryFallback = (\n state: PermissionBoundaryFallbackState,\n) => React.ReactNode\n\nexport const PermissionBoundary: React.FC<PermissionBoundaryProps> = ({\n children,\n fallback = null,\n loadingFallback = null,\n routeCode,\n menuCode,\n path,\n}) => {\n const runtime = useOpenXiangda()\n const access = useCanAccessRoute({ routeCode, menuCode, path })\n const fallbackState = createPermissionFallbackState(access, runtime)\n if (access.loading) {\n return <>{renderBoundaryFallback(loadingFallback, fallbackState)}</>\n }\n if (!access.canAccess) {\n return <>{renderBoundaryFallback(fallback, fallbackState)}</>\n }\n return <>{children}</>\n}\n\nexport interface RuntimeResolveLoginOptions {\n redirectUri?: string\n loginUrl?: string\n domain?: string\n}\n\nexport interface RuntimeRedirectLoginOptions extends RuntimeResolveLoginOptions {\n replace?: boolean\n}\n\nexport interface RuntimeLogoutOptions extends RuntimeRedirectLoginOptions {\n continueOnError?: boolean\n}\n\nexport const useRuntimeAuth = () => {\n const runtime = useOpenXiangda()\n\n const resolveLoginUrl = useCallback(\n async (options: RuntimeResolveLoginOptions = {}) => {\n const redirectUri = options.redirectUri || getCurrentHref()\n const domain = options.domain || getCurrentHostname()\n const appTenantId = getRecordString(runtime.data?.app, \"tenantId\")\n\n try {\n const statusUrl = withQuery(\n buildServiceUrl(runtime.servicePrefix, \"/api/sso/status\"),\n { domain },\n )\n const statusResponse = await runtime.fetchImpl(statusUrl, {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n })\n const statusPayload = await readJsonPayload(statusResponse)\n const sso = statusPayload?.data || {}\n const enabled = Boolean(sso.enabled)\n const shouldUseSso = Boolean(\n enabled && (sso.forceLogin ?? sso.autoRedirect ?? true),\n )\n if (shouldUseSso) {\n const loginUrlResponse = await runtime.fetchImpl(\n withQuery(buildServiceUrl(runtime.servicePrefix, \"/api/sso/login-url\"), {\n domain,\n redirectUri,\n ...(sso.tenantId || appTenantId\n ? { tenantId: String(sso.tenantId || appTenantId) }\n : {}),\n ...(sso.protocol ? { protocol: String(sso.protocol) } : {}),\n }),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const loginUrlPayload = await readJsonPayload(loginUrlResponse)\n const loginUrl =\n loginUrlPayload?.data?.loginUrl ||\n loginUrlPayload?.data?.url ||\n loginUrlPayload?.loginUrl ||\n loginUrlPayload?.url\n if (loginUrl) return String(loginUrl)\n }\n } catch {\n // Login resolution must always have a local fallback so logged-out\n // users are not stranded behind a permission state.\n }\n\n const configuredLoginUrl =\n options.loginUrl ||\n getRuntimeEnv(\"OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_BATH_AUTH_URL\") ||\n getRuntimeEnv(\"BATH_AUTH_URL\")\n if (configuredLoginUrl) {\n return attachCallback(configuredLoginUrl, redirectUri)\n }\n return attachCallback(\"/platform/login\", redirectUri)\n },\n [runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix],\n )\n\n const redirectToLogin = useCallback(\n async (options: RuntimeRedirectLoginOptions = {}) => {\n const loginUrl = await resolveLoginUrl(options)\n if (typeof window !== \"undefined\") {\n if (options.replace === false) {\n window.location.assign(loginUrl)\n } else {\n window.location.replace(loginUrl)\n }\n }\n return loginUrl\n },\n [resolveLoginUrl],\n )\n\n const logout = useCallback(async () => {\n const response = await runtime.fetchImpl(\n buildServiceUrl(runtime.servicePrefix, \"/api/auth/logout\"),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Logout failed: ${response.status}`,\n )\n }\n return payload\n }, [runtime.fetchImpl, runtime.servicePrefix])\n\n const logoutAndRedirect = useCallback(\n async (options: RuntimeLogoutOptions = {}) => {\n try {\n await logout()\n } catch (error) {\n if (options.continueOnError === false) throw error\n }\n return redirectToLogin(options)\n },\n [logout, redirectToLogin],\n )\n\n return {\n logout,\n logoutAndRedirect,\n redirectToLogin,\n resolveLoginUrl,\n }\n}\n\nconst buildServiceUrl = (servicePrefix: string, path: string) => {\n const prefix = servicePrefix.endsWith(\"/\")\n ? servicePrefix.slice(0, -1)\n : servicePrefix\n const suffix = path.startsWith(\"/\") ? path : `/${path}`\n return `${prefix}${suffix}`\n}\n\nconst readJsonPayload = async (response: Response) => {\n try {\n return await response.json()\n } catch {\n return null\n }\n}\n\nconst createRuntimeHttpError = (\n response: Response,\n payload: unknown,\n fallbackMessage: string,\n): RuntimeRequestError =>\n createRuntimeError({\n type: classifyRuntimeError(\n response.status,\n getRecordValue(payload, \"code\") as number | string | undefined,\n ),\n status: response.status,\n code: getRecordValue(payload, \"code\") as number | string | undefined,\n message:\n (getRecordValue(payload, \"message\") as string | undefined) ||\n fallbackMessage,\n payload,\n })\n\nconst createRuntimeError = (\n snapshot: RuntimeErrorSnapshot,\n): RuntimeRequestError =>\n new RuntimeHttpError({\n ...snapshot,\n type: snapshot.type || \"unknown\",\n message: snapshot.message || \"Runtime request failed\",\n })\n\nconst normalizeRuntimeError = (error: unknown): RuntimeRequestError => {\n if (error instanceof RuntimeHttpError) return error\n if (error instanceof Error) {\n const runtimeError = error as RuntimeRequestError\n runtimeError.type = runtimeError.type || classifyRuntimeError(runtimeError.status, runtimeError.code)\n return runtimeError\n }\n return createRuntimeError({\n type: \"unknown\",\n message: String(error),\n })\n}\n\nconst toRuntimeErrorSnapshot = (\n error: RuntimeRequestError,\n): RuntimeErrorSnapshot => ({\n type: error.type || classifyRuntimeError(error.status, error.code),\n status: error.status,\n code: error.code,\n message: error.message || \"Runtime request failed\",\n payload: error.payload,\n})\n\nconst classifyRuntimeError = (\n status?: number,\n code?: number | string,\n): RuntimeErrorType => {\n const normalizedCode = typeof code === \"string\" ? Number(code) : code\n if (status === 401 || normalizedCode === 401) return \"unauthenticated\"\n if (status === 403 || normalizedCode === 403) return \"forbidden\"\n if (!status && !normalizedCode) return \"network\"\n return \"unknown\"\n}\n\nconst createPermissionFallbackState = (\n access: ReturnType<typeof useCanAccessRoute>,\n runtime: ReturnType<typeof useOpenXiangda>,\n): PermissionBoundaryFallbackState => {\n const error = access.error || runtime.error\n const accessData = access.data\n const errorType =\n accessData?.errorType ||\n error?.type ||\n (!access.canAccess ? \"forbidden\" : \"unknown\")\n return {\n access,\n runtime,\n error,\n errorType,\n status: accessData?.status || error?.status,\n code: accessData?.code || error?.code,\n message:\n accessData?.message ||\n error?.message ||\n (errorType === \"unauthenticated\"\n ? \"当前账号尚未登录\"\n : \"当前账号没有访问权限\"),\n }\n}\n\nconst renderBoundaryFallback = (\n fallback: React.ReactNode | PermissionBoundaryFallback,\n state: PermissionBoundaryFallbackState,\n) => (typeof fallback === \"function\" ? fallback(state) : fallback)\n\nconst withQuery = (\n url: string,\n params: Record<string, string | number | boolean | undefined>,\n) => {\n const query = new URLSearchParams()\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === \"\") return\n query.set(key, String(value))\n })\n const serialized = query.toString()\n if (!serialized) return url\n return `${url}${url.includes(\"?\") ? \"&\" : \"?\"}${serialized}`\n}\n\nconst attachCallback = (loginUrl: string, callback: string) => {\n if (!callback) return loginUrl\n try {\n const base =\n typeof window !== \"undefined\" ? window.location.origin : \"http://localhost\"\n const parsed = new URL(loginUrl, base)\n if (!parsed.searchParams.has(\"callback\") && !parsed.searchParams.has(\"redirectUri\")) {\n parsed.searchParams.set(\"callback\", callback)\n }\n if (loginUrl.startsWith(\"http://\") || loginUrl.startsWith(\"https://\")) {\n return parsed.toString()\n }\n return `${parsed.pathname}${parsed.search}${parsed.hash}`\n } catch {\n const separator = loginUrl.includes(\"?\") ? \"&\" : \"?\"\n return `${loginUrl}${separator}callback=${encodeURIComponent(callback)}`\n }\n}\n\nconst getCurrentHref = () =>\n typeof window === \"undefined\" ? \"\" : window.location.href\n\nconst getCurrentHostname = () =>\n typeof window === \"undefined\" ? \"\" : window.location.hostname\n\nconst getRuntimeEnv = (key: string) => {\n const env =\n typeof process !== \"undefined\"\n ? (process as unknown as { env?: Record<string, string | undefined> }).env\n : undefined\n return env?.[key]\n}\n\nconst getRecordValue = (value: unknown, key: string) => {\n if (!value || typeof value !== \"object\") return undefined\n return (value as Record<string, unknown>)[key]\n}\n\nconst getRecordString = (value: unknown, key: string) => {\n const result = getRecordValue(value, key)\n return typeof result === \"string\" ? result : undefined\n}\n\nconst resolveAppTypeFromLocation = () => {\n if (typeof window === \"undefined\") return \"\"\n const segments = window.location.pathname.split(\"/\").filter(Boolean)\n const viewIndex = segments[0] === \"view\" ? 1 : 0\n if (segments[viewIndex] === \"submit\") return segments[viewIndex + 1] || \"\"\n if (segments[viewIndex] === \"preview\") return segments[viewIndex + 1] || \"\"\n return segments[viewIndex] || \"\"\n}\n","export const createBoundFetch = (fetchImpl?: typeof fetch): typeof fetch => {\n const baseFetch = fetchImpl || globalThis.fetch;\n return ((input, init) => baseFetch.call(globalThis, input, init)) as typeof fetch;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAOO;;;ACPA,IAAM,mBAAmB,CAAC,cAA2C;AAC1E,QAAM,YAAY,aAAa,WAAW;AAC1C,UAAQ,CAAC,OAAO,SAAS,UAAU,KAAK,YAAY,OAAO,IAAI;AACjE;;;AD+MI;AAnLG,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAM1C,YAAY,UAAgC;AAC1C,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AACZ,SAAK,OAAO,SAAS;AACrB,SAAK,SAAS,SAAS;AACvB,SAAK,OAAO,SAAS;AACrB,SAAK,UAAU,SAAS;AAAA,EAC1B;AACF;AAiFA,IAAM,gCACJ,4BAA8C,IAAI;AAE7C,IAAM,sBAA0D,CAAC;AAAA,EACtE;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AACF,MAAM;AACJ,QAAM,oBAAgB,sBAAQ,MAAM,iBAAiB,SAAS,GAAG,CAAC,SAAS,CAAC;AAC5E,QAAM,sBAAkB;AAAA,IACtB,MAAM,WAAW,2BAA2B;AAAA,IAC5C,CAAC,OAAO;AAAA,EACV;AACA,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAgD;AAAA,IACxE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,EACT,CAAC;AAED,QAAM,aAAS,0BAAY,YAAY;AACrC,QAAI,CAAC,iBAAiB;AACpB,eAAS;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO,mBAAmB;AAAA,UACxB,SAAS;AAAA,UACT,MAAM;AAAA,QACR,CAAC;AAAA,MACH,CAAC;AACD;AAAA,IACF;AACA,aAAS,WAAS,EAAE,GAAG,MAAM,SAAS,MAAM,OAAO,KAAK,EAAE;AAC1D,QAAI;AACF,YAAM,WAAW,MAAM;AAAA,QACrB;AAAA,UACE;AAAA,UACA,4BAA4B;AAAA,YAC1B;AAAA,UACF,CAAC;AAAA,QACH;AAAA,QACA;AAAA,UACE,aAAa;AAAA,UACb,SAAS,EAAE,QAAQ,mBAAmB;AAAA,QACxC;AAAA,MACF;AACA,YAAM,UAAU,MAAM,gBAAgB,QAAQ;AAC9C,UAAI,CAAC,SAAS,MAAM,SAAS,QAAQ,KAAK;AACxC,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA,SAAS,WAAW,6BAA6B,SAAS,MAAM;AAAA,QAClE;AAAA,MACF;AACA,eAAS;AAAA,QACP,MAAM,SAAS,QAAQ;AAAA,QACvB,SAAS;AAAA,QACT,OAAO;AAAA,MACT,CAAC;AAAA,IACH,SAAS,OAAO;AACd,eAAS;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,QACT,OAAO,sBAAsB,KAAK;AAAA,MACpC,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,iBAAiB,eAAe,aAAa,CAAC;AAElD,8BAAU,MAAM;AACd,SAAK,OAAO;AAAA,EACd,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,YAAQ;AAAA,IACZ,OAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS;AAAA,MACT;AAAA,MACA,WAAW;AAAA,MACX;AAAA,IACF;AAAA,IACA,CAAC,QAAQ,iBAAiB,eAAe,eAAe,KAAK;AAAA,EAC/D;AAEA,SACE,4CAAC,0BAA0B,UAA1B,EAAmC,OACjC,UACH;AAEJ;AAEO,IAAM,iBAAiB,MAAM;AAClC,QAAM,cAAU,yBAAW,yBAAyB;AACpD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,wDAAwD;AAAA,EAC1E;AACA,SAAO;AACT;AAEO,IAAM,sBAAsB,MAAM,eAAe;AAEjD,IAAM,cAAc,MAAM;AAC/B,QAAM,UAAU,eAAe;AAC/B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,QAAQ,MAAM,SAAS,CAAC;AAAA,EAChC;AACF;AAEO,IAAM,gBAAgB,MAAM;AACjC,QAAM,UAAU,eAAe;AAC/B,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,QAAQ,MAAM,eAAe;AAAA,EACrC;AACF;AAQO,IAAM,oBAAoB,CAAC,UAAkC;AAClE,QAAM,UAAU,eAAe;AAC/B,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAiD;AAAA,IACzE,MAAM;AAAA,IACN,SAAS;AAAA,IACT,OAAO;AAAA,EACT,CAAC;AAED,8BAAU,MAAM;AACd,QAAI,WAAW;AACf,UAAM,QAAQ,YAAY;AACxB,YAAM,cAAc,QAAQ,MAAM;AAClC,UAAI,CAAC,QAAQ,WAAW,QAAQ,SAAS;AACvC,iBAAS,WAAS,EAAE,GAAG,MAAM,SAAS,QAAQ,QAAQ,EAAE;AACxD;AAAA,MACF;AACA,UAAI,QAAQ,SAAS,CAAC,QAAQ,MAAM;AAClC,cAAM,WAAW,uBAAuB,QAAQ,KAAK;AACrD,iBAAS;AAAA,UACP,MAAM;AAAA,YACJ,SAAS,QAAQ;AAAA,YACjB,WAAW;AAAA,YACX,QAAQ,SAAS;AAAA,YACjB,MAAM,SAAS;AAAA,YACf,SAAS,SAAS;AAAA,YAClB,WAAW,SAAS;AAAA,YACpB,SAAS,SAAS;AAAA,UACpB;AAAA,UACA,SAAS;AAAA,UACT,OAAO,QAAQ;AAAA,QACjB,CAAC;AACD;AAAA,MACF;AACA,UAAI,aAAa,eAAe;AAC9B,iBAAS;AAAA,UACP,MAAM,EAAE,SAAS,QAAQ,SAAS,WAAW,MAAM,YAAY;AAAA,UAC/D,SAAS;AAAA,UACT,OAAO;AAAA,QACT,CAAC;AACD;AAAA,MACF;AACA,eAAS,WAAS,EAAE,GAAG,MAAM,SAAS,MAAM,OAAO,KAAK,EAAE;AAC1D,UAAI;AACF,cAAM,WAAW,MAAM,QAAQ;AAAA,UAC7B;AAAA,YACE,QAAQ;AAAA,YACR,4BAA4B;AAAA,cAC1B,QAAQ;AAAA,YACV,CAAC;AAAA,UACH;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,aAAa;AAAA,YACb,SAAS;AAAA,cACP,QAAQ;AAAA,cACR,gBAAgB;AAAA,YAClB;AAAA,YACA,MAAM,KAAK,UAAU,KAAK;AAAA,UAC5B;AAAA,QACF;AACA,cAAM,UAAU,MAAM,gBAAgB,QAAQ;AAC9C,cAAM,OAAO,SAAS,QAAQ,SAAS;AACvC,cAAM,YAAY,QAAQ,SAAS,MAAM,SAAS;AAClD,cAAM,YAAY,YACd,SACA,qBAAqB,SAAS,QAAQ,IAAI;AAC9C,cAAM,OAA0B;AAAA,UAC9B,GAAI,SAAS,QAAQ;AAAA,YACnB,SAAS,QAAQ;AAAA,YACjB,WAAW;AAAA,UACb;AAAA,UACA,SAAS,SAAS,MAAM,WAAW,QAAQ;AAAA,UAC3C;AAAA,UACA,QAAQ,SAAS;AAAA,UACjB;AAAA,UACA,SAAS,SAAS;AAAA,UAClB;AAAA,UACA;AAAA,QACF;AACA,YAAI,CAAC,UAAU;AACb,gBAAM,qBACJ,CAAC,SAAS,MAAO,OAAO,SAAS,YAAY,QAAQ;AACvD,mBAAS;AAAA,YACP;AAAA,YACA,SAAS;AAAA,YACT,OAAO,qBACH;AAAA,cACE;AAAA,cACA;AAAA,cACA,SAAS,WAAW,uBAAuB,SAAS,MAAM;AAAA,YAC5D,IACA;AAAA,UACN,CAAC;AAAA,QACH;AAAA,MACF,SAAS,OAAO;AACd,YAAI,CAAC,UAAU;AACb,mBAAS;AAAA,YACP,MAAM;AAAA,YACN,SAAS;AAAA,YACT,OAAO,sBAAsB,KAAK;AAAA,UACpC,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AACA,SAAK,MAAM;AACX,WAAO,MAAM;AACX,iBAAW;AAAA,IACb;AAAA,EACF,GAAG;AAAA,IACD,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ,MAAM;AAAA,IACd,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAED,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW,QAAQ,MAAM,MAAM,SAAS;AAAA,EAC1C;AACF;AAsBO,IAAM,qBAAwD,CAAC;AAAA,EACpE;AAAA,EACA,WAAW;AAAA,EACX,kBAAkB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,UAAU,eAAe;AAC/B,QAAM,SAAS,kBAAkB,EAAE,WAAW,UAAU,KAAK,CAAC;AAC9D,QAAM,gBAAgB,8BAA8B,QAAQ,OAAO;AACnE,MAAI,OAAO,SAAS;AAClB,WAAO,2EAAG,iCAAuB,iBAAiB,aAAa,GAAE;AAAA,EACnE;AACA,MAAI,CAAC,OAAO,WAAW;AACrB,WAAO,2EAAG,iCAAuB,UAAU,aAAa,GAAE;AAAA,EAC5D;AACA,SAAO,2EAAG,UAAS;AACrB;AAgBO,IAAM,iBAAiB,MAAM;AAClC,QAAM,UAAU,eAAe;AAE/B,QAAM,sBAAkB;AAAA,IACtB,OAAO,UAAsC,CAAC,MAAM;AAClD,YAAM,cAAc,QAAQ,eAAe,eAAe;AAC1D,YAAM,SAAS,QAAQ,UAAU,mBAAmB;AACpD,YAAM,cAAc,gBAAgB,QAAQ,MAAM,KAAK,UAAU;AAEjE,UAAI;AACF,cAAM,YAAY;AAAA,UAChB,gBAAgB,QAAQ,eAAe,iBAAiB;AAAA,UACxD,EAAE,OAAO;AAAA,QACX;AACA,cAAM,iBAAiB,MAAM,QAAQ,UAAU,WAAW;AAAA,UACxD,aAAa;AAAA,UACb,SAAS,EAAE,QAAQ,mBAAmB;AAAA,QACxC,CAAC;AACD,cAAM,gBAAgB,MAAM,gBAAgB,cAAc;AAC1D,cAAM,MAAM,eAAe,QAAQ,CAAC;AACpC,cAAM,UAAU,QAAQ,IAAI,OAAO;AACnC,cAAM,eAAe;AAAA,UACnB,YAAY,IAAI,cAAc,IAAI,gBAAgB;AAAA,QACpD;AACA,YAAI,cAAc;AAChB,gBAAM,mBAAmB,MAAM,QAAQ;AAAA,YACrC,UAAU,gBAAgB,QAAQ,eAAe,oBAAoB,GAAG;AAAA,cACtE;AAAA,cACA;AAAA,cACA,GAAI,IAAI,YAAY,cAChB,EAAE,UAAU,OAAO,IAAI,YAAY,WAAW,EAAE,IAChD,CAAC;AAAA,cACL,GAAI,IAAI,WAAW,EAAE,UAAU,OAAO,IAAI,QAAQ,EAAE,IAAI,CAAC;AAAA,YAC3D,CAAC;AAAA,YACD;AAAA,cACE,aAAa;AAAA,cACb,SAAS,EAAE,QAAQ,mBAAmB;AAAA,YACxC;AAAA,UACF;AACA,gBAAM,kBAAkB,MAAM,gBAAgB,gBAAgB;AAC9D,gBAAM,WACJ,iBAAiB,MAAM,YACvB,iBAAiB,MAAM,OACvB,iBAAiB,YACjB,iBAAiB;AACnB,cAAI,SAAU,QAAO,OAAO,QAAQ;AAAA,QACtC;AAAA,MACF,QAAQ;AAAA,MAGR;AAEA,YAAM,qBACJ,QAAQ,YACR,cAAc,uBAAuB,KACrC,cAAc,4BAA4B,KAC1C,cAAc,eAAe,KAC7B,cAAc,oBAAoB,KAClC,cAAc,oBAAoB,KAClC,cAAc,eAAe;AAC/B,UAAI,oBAAoB;AACtB,eAAO,eAAe,oBAAoB,WAAW;AAAA,MACvD;AACA,aAAO,eAAe,mBAAmB,WAAW;AAAA,IACtD;AAAA,IACA,CAAC,QAAQ,MAAM,KAAK,QAAQ,WAAW,QAAQ,aAAa;AAAA,EAC9D;AAEA,QAAM,sBAAkB;AAAA,IACtB,OAAO,UAAuC,CAAC,MAAM;AACnD,YAAM,WAAW,MAAM,gBAAgB,OAAO;AAC9C,UAAI,OAAO,WAAW,aAAa;AACjC,YAAI,QAAQ,YAAY,OAAO;AAC7B,iBAAO,SAAS,OAAO,QAAQ;AAAA,QACjC,OAAO;AACL,iBAAO,SAAS,QAAQ,QAAQ;AAAA,QAClC;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAAC,eAAe;AAAA,EAClB;AAEA,QAAM,aAAS,0BAAY,YAAY;AACrC,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,gBAAgB,QAAQ,eAAe,kBAAkB;AAAA,MACzD;AAAA,QACE,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,SAAS,EAAE,QAAQ,mBAAmB;AAAA,MACxC;AAAA,IACF;AACA,UAAM,UAAU,MAAM,gBAAgB,QAAQ;AAC9C,QAAI,CAAC,SAAS,MAAM,SAAS,QAAQ,KAAK;AACxC,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA,SAAS,WAAW,kBAAkB,SAAS,MAAM;AAAA,MACvD;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,QAAQ,WAAW,QAAQ,aAAa,CAAC;AAE7C,QAAM,wBAAoB;AAAA,IACxB,OAAO,UAAgC,CAAC,MAAM;AAC5C,UAAI;AACF,cAAM,OAAO;AAAA,MACf,SAAS,OAAO;AACd,YAAI,QAAQ,oBAAoB,MAAO,OAAM;AAAA,MAC/C;AACA,aAAO,gBAAgB,OAAO;AAAA,IAChC;AAAA,IACA,CAAC,QAAQ,eAAe;AAAA,EAC1B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,kBAAkB,CAAC,eAAuB,SAAiB;AAC/D,QAAM,SAAS,cAAc,SAAS,GAAG,IACrC,cAAc,MAAM,GAAG,EAAE,IACzB;AACJ,QAAM,SAAS,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AACrD,SAAO,GAAG,MAAM,GAAG,MAAM;AAC3B;AAEA,IAAM,kBAAkB,OAAO,aAAuB;AACpD,MAAI;AACF,WAAO,MAAM,SAAS,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAM,yBAAyB,CAC7B,UACA,SACA,oBAEA,mBAAmB;AAAA,EACjB,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,eAAe,SAAS,MAAM;AAAA,EAChC;AAAA,EACA,QAAQ,SAAS;AAAA,EACjB,MAAM,eAAe,SAAS,MAAM;AAAA,EACpC,SACG,eAAe,SAAS,SAAS,KAClC;AAAA,EACF;AACF,CAAC;AAEH,IAAM,qBAAqB,CACzB,aAEA,IAAI,iBAAiB;AAAA,EACnB,GAAG;AAAA,EACH,MAAM,SAAS,QAAQ;AAAA,EACvB,SAAS,SAAS,WAAW;AAC/B,CAAC;AAEH,IAAM,wBAAwB,CAAC,UAAwC;AACrE,MAAI,iBAAiB,iBAAkB,QAAO;AAC9C,MAAI,iBAAiB,OAAO;AAC1B,UAAM,eAAe;AACrB,iBAAa,OAAO,aAAa,QAAQ,qBAAqB,aAAa,QAAQ,aAAa,IAAI;AACpG,WAAO;AAAA,EACT;AACA,SAAO,mBAAmB;AAAA,IACxB,MAAM;AAAA,IACN,SAAS,OAAO,KAAK;AAAA,EACvB,CAAC;AACH;AAEA,IAAM,yBAAyB,CAC7B,WAC0B;AAAA,EAC1B,MAAM,MAAM,QAAQ,qBAAqB,MAAM,QAAQ,MAAM,IAAI;AAAA,EACjE,QAAQ,MAAM;AAAA,EACd,MAAM,MAAM;AAAA,EACZ,SAAS,MAAM,WAAW;AAAA,EAC1B,SAAS,MAAM;AACjB;AAEA,IAAM,uBAAuB,CAC3B,QACA,SACqB;AACrB,QAAM,iBAAiB,OAAO,SAAS,WAAW,OAAO,IAAI,IAAI;AACjE,MAAI,WAAW,OAAO,mBAAmB,IAAK,QAAO;AACrD,MAAI,WAAW,OAAO,mBAAmB,IAAK,QAAO;AACrD,MAAI,CAAC,UAAU,CAAC,eAAgB,QAAO;AACvC,SAAO;AACT;AAEA,IAAM,gCAAgC,CACpC,QACA,YACoC;AACpC,QAAM,QAAQ,OAAO,SAAS,QAAQ;AACtC,QAAM,aAAa,OAAO;AAC1B,QAAM,YACJ,YAAY,aACZ,OAAO,SACN,CAAC,OAAO,YAAY,cAAc;AACrC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,YAAY,UAAU,OAAO;AAAA,IACrC,MAAM,YAAY,QAAQ,OAAO;AAAA,IACjC,SACE,YAAY,WACZ,OAAO,YACN,cAAc,oBACX,qDACA;AAAA,EACR;AACF;AAEA,IAAM,yBAAyB,CAC7B,UACA,UACI,OAAO,aAAa,aAAa,SAAS,KAAK,IAAI;AAEzD,IAAM,YAAY,CAChB,KACA,WACG;AACH,QAAM,QAAQ,IAAI,gBAAgB;AAClC,SAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC/C,QAAI,UAAU,UAAa,UAAU,GAAI;AACzC,UAAM,IAAI,KAAK,OAAO,KAAK,CAAC;AAAA,EAC9B,CAAC;AACD,QAAM,aAAa,MAAM,SAAS;AAClC,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,GAAG,UAAU;AAC5D;AAEA,IAAM,iBAAiB,CAAC,UAAkB,aAAqB;AAC7D,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI;AACF,UAAM,OACJ,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;AAC3D,UAAM,SAAS,IAAI,IAAI,UAAU,IAAI;AACrC,QAAI,CAAC,OAAO,aAAa,IAAI,UAAU,KAAK,CAAC,OAAO,aAAa,IAAI,aAAa,GAAG;AACnF,aAAO,aAAa,IAAI,YAAY,QAAQ;AAAA,IAC9C;AACA,QAAI,SAAS,WAAW,SAAS,KAAK,SAAS,WAAW,UAAU,GAAG;AACrE,aAAO,OAAO,SAAS;AAAA,IACzB;AACA,WAAO,GAAG,OAAO,QAAQ,GAAG,OAAO,MAAM,GAAG,OAAO,IAAI;AAAA,EACzD,QAAQ;AACN,UAAM,YAAY,SAAS,SAAS,GAAG,IAAI,MAAM;AACjD,WAAO,GAAG,QAAQ,GAAG,SAAS,YAAY,mBAAmB,QAAQ,CAAC;AAAA,EACxE;AACF;AAEA,IAAM,iBAAiB,MACrB,OAAO,WAAW,cAAc,KAAK,OAAO,SAAS;AAEvD,IAAM,qBAAqB,MACzB,OAAO,WAAW,cAAc,KAAK,OAAO,SAAS;AAEvD,IAAM,gBAAgB,CAAC,QAAgB;AACrC,QAAM,MACJ,OAAO,YAAY,cACd,QAAoE,MACrE;AACN,SAAO,MAAM,GAAG;AAClB;AAEA,IAAM,iBAAiB,CAAC,OAAgB,QAAgB;AACtD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,SAAQ,MAAkC,GAAG;AAC/C;AAEA,IAAM,kBAAkB,CAAC,OAAgB,QAAgB;AACvD,QAAM,SAAS,eAAe,OAAO,GAAG;AACxC,SAAO,OAAO,WAAW,WAAW,SAAS;AAC/C;AAEA,IAAM,6BAA6B,MAAM;AACvC,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,WAAW,OAAO,SAAS,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AACnE,QAAM,YAAY,SAAS,CAAC,MAAM,SAAS,IAAI;AAC/C,MAAI,SAAS,SAAS,MAAM,SAAU,QAAO,SAAS,YAAY,CAAC,KAAK;AACxE,MAAI,SAAS,SAAS,MAAM,UAAW,QAAO,SAAS,YAAY,CAAC,KAAK;AACzE,SAAO,SAAS,SAAS,KAAK;AAChC;","names":[]}
|
|
@@ -308,7 +308,7 @@ var useRuntimeAuth = () => {
|
|
|
308
308
|
if (configuredLoginUrl) {
|
|
309
309
|
return attachCallback(configuredLoginUrl, redirectUri);
|
|
310
310
|
}
|
|
311
|
-
return attachCallback("/login", redirectUri);
|
|
311
|
+
return attachCallback("/platform/login", redirectUri);
|
|
312
312
|
},
|
|
313
313
|
[runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix]
|
|
314
314
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/runtime/react/openxiangdaProvider.tsx","../../src/runtime/core/fetch.ts"],"sourcesContent":["import React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\"\nimport { createBoundFetch } from \"../core/fetch\"\n\nexport type RuntimeErrorType =\n | \"unauthenticated\"\n | \"forbidden\"\n | \"network\"\n | \"unknown\"\n\nexport type RuntimeRequestError = Error & {\n type?: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n}\n\nexport interface RuntimeErrorSnapshot {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n payload?: unknown\n}\n\nexport class RuntimeHttpError extends Error {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n\n constructor(snapshot: RuntimeErrorSnapshot) {\n super(snapshot.message)\n this.name = \"RuntimeHttpError\"\n this.type = snapshot.type\n this.status = snapshot.status\n this.code = snapshot.code\n this.payload = snapshot.payload\n }\n}\n\nexport interface RuntimeMenuItem {\n id: string\n name: string\n resourceCode?: string | null\n routeCode?: string | null\n path?: string | null\n type?: string\n formUuid?: string | null\n pageId?: string | null\n parentId?: string | null\n sortOrder?: number\n isHidden?: boolean\n icon?: string | null\n children?: RuntimeMenuItem[]\n [key: string]: unknown\n}\n\nexport interface RuntimePagePermissions {\n appType: string\n hasFullAccess: boolean\n roleCodes: string[]\n roleSource?: string\n menuFormUuids: string[]\n menuCodes: string[]\n routeCodes: string[]\n pathPatterns: string[]\n}\n\nexport interface RuntimeBootstrap {\n appType: string\n app?: Record<string, unknown> | null\n user?: Record<string, unknown> | null\n runtime?: {\n mode?: \"legacy\" | \"react-spa\" | string\n settings?: Record<string, unknown>\n activeReleaseId?: string | null\n activeBuildId?: string | null\n indexUrl?: string | null\n assetBaseUrl?: string | null\n }\n permissions?: RuntimePagePermissions\n menus?: RuntimeMenuItem[]\n servicePrefix?: string\n}\n\nexport interface RouteAccessResult {\n appType: string\n canAccess: boolean\n routeCode?: string\n menuCode?: string\n path?: string\n status?: number\n code?: number | string\n message?: string\n errorType?: RuntimeErrorType\n payload?: unknown\n permissions?: RuntimePagePermissions\n}\n\nexport interface RuntimeRequestState<T> {\n data: T | null\n loading: boolean\n error: RuntimeRequestError | null\n}\n\nexport interface OpenXiangdaProviderProps {\n appType?: string\n servicePrefix?: string\n fetchImpl?: typeof fetch\n children: React.ReactNode\n}\n\ninterface OpenXiangdaRuntimeStore extends RuntimeRequestState<RuntimeBootstrap> {\n appType: string\n servicePrefix: string\n fetchImpl: typeof fetch\n reload: () => Promise<void>\n}\n\nconst OpenXiangdaRuntimeContext =\n createContext<OpenXiangdaRuntimeStore | null>(null)\n\nexport const OpenXiangdaProvider: React.FC<OpenXiangdaProviderProps> = ({\n appType,\n servicePrefix = \"/service\",\n fetchImpl,\n children,\n}) => {\n const resolvedFetch = useMemo(() => createBoundFetch(fetchImpl), [fetchImpl])\n const resolvedAppType = useMemo(\n () => appType || resolveAppTypeFromLocation(),\n [appType],\n )\n const [state, setState] = useState<RuntimeRequestState<RuntimeBootstrap>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const reload = useCallback(async () => {\n if (!resolvedAppType) {\n setState({\n data: null,\n loading: false,\n error: createRuntimeError({\n message: \"appType 不能为空\",\n type: \"unknown\",\n }),\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await resolvedFetch(\n buildServiceUrl(\n servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n resolvedAppType,\n )}/runtime/bootstrap`,\n ),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Runtime bootstrap failed: ${response.status}`,\n )\n }\n setState({\n data: payload?.data || null,\n loading: false,\n error: null,\n })\n } catch (error) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }, [resolvedAppType, resolvedFetch, servicePrefix])\n\n useEffect(() => {\n void reload()\n }, [reload])\n\n const value = useMemo<OpenXiangdaRuntimeStore>(\n () => ({\n ...state,\n appType: resolvedAppType,\n servicePrefix,\n fetchImpl: resolvedFetch,\n reload,\n }),\n [reload, resolvedAppType, resolvedFetch, servicePrefix, state],\n )\n\n return (\n <OpenXiangdaRuntimeContext.Provider value={value}>\n {children}\n </OpenXiangdaRuntimeContext.Provider>\n )\n}\n\nexport const useOpenXiangda = () => {\n const context = useContext(OpenXiangdaRuntimeContext)\n if (!context) {\n throw new Error(\"useOpenXiangda must be used inside OpenXiangdaProvider\")\n }\n return context\n}\n\nexport const useRuntimeBootstrap = () => useOpenXiangda()\n\nexport const useAppMenus = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.menus || [],\n }\n}\n\nexport const usePermission = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.permissions || null,\n }\n}\n\nexport interface UseCanAccessRouteInput {\n routeCode?: string\n menuCode?: string\n path?: string\n}\n\nexport const useCanAccessRoute = (input: UseCanAccessRouteInput) => {\n const runtime = useOpenXiangda()\n const [state, setState] = useState<RuntimeRequestState<RouteAccessResult>>({\n data: null,\n loading: true,\n error: null,\n })\n\n useEffect(() => {\n let disposed = false\n const check = async () => {\n const permissions = runtime.data?.permissions\n if (!runtime.appType || runtime.loading) {\n setState(prev => ({ ...prev, loading: runtime.loading }))\n return\n }\n if (runtime.error && !runtime.data) {\n const snapshot = toRuntimeErrorSnapshot(runtime.error)\n setState({\n data: {\n appType: runtime.appType,\n canAccess: false,\n status: snapshot.status,\n code: snapshot.code,\n message: snapshot.message,\n errorType: snapshot.type,\n payload: snapshot.payload,\n },\n loading: false,\n error: runtime.error,\n })\n return\n }\n if (permissions?.hasFullAccess) {\n setState({\n data: { appType: runtime.appType, canAccess: true, permissions },\n loading: false,\n error: null,\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await runtime.fetchImpl(\n buildServiceUrl(\n runtime.servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n runtime.appType,\n )}/runtime/routes/check`,\n ),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(input),\n },\n )\n const payload = await readJsonPayload(response)\n const code = payload?.code ?? response.status\n const canAccess = Boolean(payload?.data?.canAccess)\n const errorType = canAccess\n ? undefined\n : classifyRuntimeError(response.status, code)\n const data: RouteAccessResult = {\n ...(payload?.data || {\n appType: runtime.appType,\n canAccess: false,\n }),\n appType: payload?.data?.appType || runtime.appType,\n canAccess,\n status: response.status,\n code,\n message: payload?.message,\n errorType,\n payload,\n }\n if (!disposed) {\n const shouldTreatAsError =\n !response.ok || (typeof code === \"number\" && code >= 500)\n setState({\n data,\n loading: false,\n error: shouldTreatAsError\n ? createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Route check failed: ${response.status}`,\n )\n : null,\n })\n }\n } catch (error) {\n if (!disposed) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }\n }\n void check()\n return () => {\n disposed = true\n }\n }, [\n input.menuCode,\n input.path,\n input.routeCode,\n runtime.appType,\n runtime.data?.permissions,\n runtime.fetchImpl,\n runtime.loading,\n runtime.servicePrefix,\n ])\n\n return {\n ...state,\n canAccess: Boolean(state.data?.canAccess),\n }\n}\n\nexport interface PermissionBoundaryProps extends UseCanAccessRouteInput {\n children: React.ReactNode\n fallback?: React.ReactNode | PermissionBoundaryFallback\n loadingFallback?: React.ReactNode | PermissionBoundaryFallback\n}\n\nexport interface PermissionBoundaryFallbackState {\n access: ReturnType<typeof useCanAccessRoute>\n runtime: ReturnType<typeof useOpenXiangda>\n error: RuntimeRequestError | null\n errorType: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n}\n\nexport type PermissionBoundaryFallback = (\n state: PermissionBoundaryFallbackState,\n) => React.ReactNode\n\nexport const PermissionBoundary: React.FC<PermissionBoundaryProps> = ({\n children,\n fallback = null,\n loadingFallback = null,\n routeCode,\n menuCode,\n path,\n}) => {\n const runtime = useOpenXiangda()\n const access = useCanAccessRoute({ routeCode, menuCode, path })\n const fallbackState = createPermissionFallbackState(access, runtime)\n if (access.loading) {\n return <>{renderBoundaryFallback(loadingFallback, fallbackState)}</>\n }\n if (!access.canAccess) {\n return <>{renderBoundaryFallback(fallback, fallbackState)}</>\n }\n return <>{children}</>\n}\n\nexport interface RuntimeResolveLoginOptions {\n redirectUri?: string\n loginUrl?: string\n domain?: string\n}\n\nexport interface RuntimeRedirectLoginOptions extends RuntimeResolveLoginOptions {\n replace?: boolean\n}\n\nexport interface RuntimeLogoutOptions extends RuntimeRedirectLoginOptions {\n continueOnError?: boolean\n}\n\nexport const useRuntimeAuth = () => {\n const runtime = useOpenXiangda()\n\n const resolveLoginUrl = useCallback(\n async (options: RuntimeResolveLoginOptions = {}) => {\n const redirectUri = options.redirectUri || getCurrentHref()\n const domain = options.domain || getCurrentHostname()\n const appTenantId = getRecordString(runtime.data?.app, \"tenantId\")\n\n try {\n const statusUrl = withQuery(\n buildServiceUrl(runtime.servicePrefix, \"/api/sso/status\"),\n { domain },\n )\n const statusResponse = await runtime.fetchImpl(statusUrl, {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n })\n const statusPayload = await readJsonPayload(statusResponse)\n const sso = statusPayload?.data || {}\n const enabled = Boolean(sso.enabled)\n const shouldUseSso = Boolean(\n enabled && (sso.forceLogin ?? sso.autoRedirect ?? true),\n )\n if (shouldUseSso) {\n const loginUrlResponse = await runtime.fetchImpl(\n withQuery(buildServiceUrl(runtime.servicePrefix, \"/api/sso/login-url\"), {\n domain,\n redirectUri,\n ...(sso.tenantId || appTenantId\n ? { tenantId: String(sso.tenantId || appTenantId) }\n : {}),\n ...(sso.protocol ? { protocol: String(sso.protocol) } : {}),\n }),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const loginUrlPayload = await readJsonPayload(loginUrlResponse)\n const loginUrl =\n loginUrlPayload?.data?.loginUrl ||\n loginUrlPayload?.data?.url ||\n loginUrlPayload?.loginUrl ||\n loginUrlPayload?.url\n if (loginUrl) return String(loginUrl)\n }\n } catch {\n // Login resolution must always have a local fallback so logged-out\n // users are not stranded behind a permission state.\n }\n\n const configuredLoginUrl =\n options.loginUrl ||\n getRuntimeEnv(\"OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_BATH_AUTH_URL\") ||\n getRuntimeEnv(\"BATH_AUTH_URL\")\n if (configuredLoginUrl) {\n return attachCallback(configuredLoginUrl, redirectUri)\n }\n return attachCallback(\"/login\", redirectUri)\n },\n [runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix],\n )\n\n const redirectToLogin = useCallback(\n async (options: RuntimeRedirectLoginOptions = {}) => {\n const loginUrl = await resolveLoginUrl(options)\n if (typeof window !== \"undefined\") {\n if (options.replace === false) {\n window.location.assign(loginUrl)\n } else {\n window.location.replace(loginUrl)\n }\n }\n return loginUrl\n },\n [resolveLoginUrl],\n )\n\n const logout = useCallback(async () => {\n const response = await runtime.fetchImpl(\n buildServiceUrl(runtime.servicePrefix, \"/api/auth/logout\"),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Logout failed: ${response.status}`,\n )\n }\n return payload\n }, [runtime.fetchImpl, runtime.servicePrefix])\n\n const logoutAndRedirect = useCallback(\n async (options: RuntimeLogoutOptions = {}) => {\n try {\n await logout()\n } catch (error) {\n if (options.continueOnError === false) throw error\n }\n return redirectToLogin(options)\n },\n [logout, redirectToLogin],\n )\n\n return {\n logout,\n logoutAndRedirect,\n redirectToLogin,\n resolveLoginUrl,\n }\n}\n\nconst buildServiceUrl = (servicePrefix: string, path: string) => {\n const prefix = servicePrefix.endsWith(\"/\")\n ? servicePrefix.slice(0, -1)\n : servicePrefix\n const suffix = path.startsWith(\"/\") ? path : `/${path}`\n return `${prefix}${suffix}`\n}\n\nconst readJsonPayload = async (response: Response) => {\n try {\n return await response.json()\n } catch {\n return null\n }\n}\n\nconst createRuntimeHttpError = (\n response: Response,\n payload: unknown,\n fallbackMessage: string,\n): RuntimeRequestError =>\n createRuntimeError({\n type: classifyRuntimeError(\n response.status,\n getRecordValue(payload, \"code\") as number | string | undefined,\n ),\n status: response.status,\n code: getRecordValue(payload, \"code\") as number | string | undefined,\n message:\n (getRecordValue(payload, \"message\") as string | undefined) ||\n fallbackMessage,\n payload,\n })\n\nconst createRuntimeError = (\n snapshot: RuntimeErrorSnapshot,\n): RuntimeRequestError =>\n new RuntimeHttpError({\n ...snapshot,\n type: snapshot.type || \"unknown\",\n message: snapshot.message || \"Runtime request failed\",\n })\n\nconst normalizeRuntimeError = (error: unknown): RuntimeRequestError => {\n if (error instanceof RuntimeHttpError) return error\n if (error instanceof Error) {\n const runtimeError = error as RuntimeRequestError\n runtimeError.type = runtimeError.type || classifyRuntimeError(runtimeError.status, runtimeError.code)\n return runtimeError\n }\n return createRuntimeError({\n type: \"unknown\",\n message: String(error),\n })\n}\n\nconst toRuntimeErrorSnapshot = (\n error: RuntimeRequestError,\n): RuntimeErrorSnapshot => ({\n type: error.type || classifyRuntimeError(error.status, error.code),\n status: error.status,\n code: error.code,\n message: error.message || \"Runtime request failed\",\n payload: error.payload,\n})\n\nconst classifyRuntimeError = (\n status?: number,\n code?: number | string,\n): RuntimeErrorType => {\n const normalizedCode = typeof code === \"string\" ? Number(code) : code\n if (status === 401 || normalizedCode === 401) return \"unauthenticated\"\n if (status === 403 || normalizedCode === 403) return \"forbidden\"\n if (!status && !normalizedCode) return \"network\"\n return \"unknown\"\n}\n\nconst createPermissionFallbackState = (\n access: ReturnType<typeof useCanAccessRoute>,\n runtime: ReturnType<typeof useOpenXiangda>,\n): PermissionBoundaryFallbackState => {\n const error = access.error || runtime.error\n const accessData = access.data\n const errorType =\n accessData?.errorType ||\n error?.type ||\n (!access.canAccess ? \"forbidden\" : \"unknown\")\n return {\n access,\n runtime,\n error,\n errorType,\n status: accessData?.status || error?.status,\n code: accessData?.code || error?.code,\n message:\n accessData?.message ||\n error?.message ||\n (errorType === \"unauthenticated\"\n ? \"当前账号尚未登录\"\n : \"当前账号没有访问权限\"),\n }\n}\n\nconst renderBoundaryFallback = (\n fallback: React.ReactNode | PermissionBoundaryFallback,\n state: PermissionBoundaryFallbackState,\n) => (typeof fallback === \"function\" ? fallback(state) : fallback)\n\nconst withQuery = (\n url: string,\n params: Record<string, string | number | boolean | undefined>,\n) => {\n const query = new URLSearchParams()\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === \"\") return\n query.set(key, String(value))\n })\n const serialized = query.toString()\n if (!serialized) return url\n return `${url}${url.includes(\"?\") ? \"&\" : \"?\"}${serialized}`\n}\n\nconst attachCallback = (loginUrl: string, callback: string) => {\n if (!callback) return loginUrl\n try {\n const base =\n typeof window !== \"undefined\" ? window.location.origin : \"http://localhost\"\n const parsed = new URL(loginUrl, base)\n if (!parsed.searchParams.has(\"callback\") && !parsed.searchParams.has(\"redirectUri\")) {\n parsed.searchParams.set(\"callback\", callback)\n }\n if (loginUrl.startsWith(\"http://\") || loginUrl.startsWith(\"https://\")) {\n return parsed.toString()\n }\n return `${parsed.pathname}${parsed.search}${parsed.hash}`\n } catch {\n const separator = loginUrl.includes(\"?\") ? \"&\" : \"?\"\n return `${loginUrl}${separator}callback=${encodeURIComponent(callback)}`\n }\n}\n\nconst getCurrentHref = () =>\n typeof window === \"undefined\" ? \"\" : window.location.href\n\nconst getCurrentHostname = () =>\n typeof window === \"undefined\" ? \"\" : window.location.hostname\n\nconst getRuntimeEnv = (key: string) => {\n const env =\n typeof process !== \"undefined\"\n ? (process as unknown as { env?: Record<string, string | undefined> }).env\n : undefined\n return env?.[key]\n}\n\nconst getRecordValue = (value: unknown, key: string) => {\n if (!value || typeof value !== \"object\") return undefined\n return (value as Record<string, unknown>)[key]\n}\n\nconst getRecordString = (value: unknown, key: string) => {\n const result = getRecordValue(value, key)\n return typeof result === \"string\" ? result : undefined\n}\n\nconst resolveAppTypeFromLocation = () => {\n if (typeof window === \"undefined\") return \"\"\n const segments = window.location.pathname.split(\"/\").filter(Boolean)\n const viewIndex = segments[0] === \"view\" ? 1 : 0\n if (segments[viewIndex] === \"submit\") return segments[viewIndex + 1] || \"\"\n if (segments[viewIndex] === \"preview\") return segments[viewIndex + 1] || \"\"\n return segments[viewIndex] || \"\"\n}\n","export const createBoundFetch = (fetchImpl?: typeof fetch): typeof fetch => {\n const baseFetch = fetchImpl || globalThis.fetch;\n return ((input, init) => baseFetch.call(globalThis, input, init)) as typeof fetch;\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/runtime/react/openxiangdaProvider.tsx","../../src/runtime/core/fetch.ts"],"sourcesContent":["import React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from \"react\"\nimport { createBoundFetch } from \"../core/fetch\"\n\nexport type RuntimeErrorType =\n | \"unauthenticated\"\n | \"forbidden\"\n | \"network\"\n | \"unknown\"\n\nexport type RuntimeRequestError = Error & {\n type?: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n}\n\nexport interface RuntimeErrorSnapshot {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n payload?: unknown\n}\n\nexport class RuntimeHttpError extends Error {\n type: RuntimeErrorType\n status?: number\n code?: number | string\n payload?: unknown\n\n constructor(snapshot: RuntimeErrorSnapshot) {\n super(snapshot.message)\n this.name = \"RuntimeHttpError\"\n this.type = snapshot.type\n this.status = snapshot.status\n this.code = snapshot.code\n this.payload = snapshot.payload\n }\n}\n\nexport interface RuntimeMenuItem {\n id: string\n name: string\n resourceCode?: string | null\n routeCode?: string | null\n path?: string | null\n type?: string\n formUuid?: string | null\n pageId?: string | null\n parentId?: string | null\n sortOrder?: number\n isHidden?: boolean\n icon?: string | null\n children?: RuntimeMenuItem[]\n [key: string]: unknown\n}\n\nexport interface RuntimePagePermissions {\n appType: string\n hasFullAccess: boolean\n roleCodes: string[]\n roleSource?: string\n menuFormUuids: string[]\n menuCodes: string[]\n routeCodes: string[]\n pathPatterns: string[]\n}\n\nexport interface RuntimeBootstrap {\n appType: string\n app?: Record<string, unknown> | null\n user?: Record<string, unknown> | null\n runtime?: {\n mode?: \"legacy\" | \"react-spa\" | string\n settings?: Record<string, unknown>\n activeReleaseId?: string | null\n activeBuildId?: string | null\n indexUrl?: string | null\n assetBaseUrl?: string | null\n }\n permissions?: RuntimePagePermissions\n menus?: RuntimeMenuItem[]\n servicePrefix?: string\n}\n\nexport interface RouteAccessResult {\n appType: string\n canAccess: boolean\n routeCode?: string\n menuCode?: string\n path?: string\n status?: number\n code?: number | string\n message?: string\n errorType?: RuntimeErrorType\n payload?: unknown\n permissions?: RuntimePagePermissions\n}\n\nexport interface RuntimeRequestState<T> {\n data: T | null\n loading: boolean\n error: RuntimeRequestError | null\n}\n\nexport interface OpenXiangdaProviderProps {\n appType?: string\n servicePrefix?: string\n fetchImpl?: typeof fetch\n children: React.ReactNode\n}\n\ninterface OpenXiangdaRuntimeStore extends RuntimeRequestState<RuntimeBootstrap> {\n appType: string\n servicePrefix: string\n fetchImpl: typeof fetch\n reload: () => Promise<void>\n}\n\nconst OpenXiangdaRuntimeContext =\n createContext<OpenXiangdaRuntimeStore | null>(null)\n\nexport const OpenXiangdaProvider: React.FC<OpenXiangdaProviderProps> = ({\n appType,\n servicePrefix = \"/service\",\n fetchImpl,\n children,\n}) => {\n const resolvedFetch = useMemo(() => createBoundFetch(fetchImpl), [fetchImpl])\n const resolvedAppType = useMemo(\n () => appType || resolveAppTypeFromLocation(),\n [appType],\n )\n const [state, setState] = useState<RuntimeRequestState<RuntimeBootstrap>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const reload = useCallback(async () => {\n if (!resolvedAppType) {\n setState({\n data: null,\n loading: false,\n error: createRuntimeError({\n message: \"appType 不能为空\",\n type: \"unknown\",\n }),\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await resolvedFetch(\n buildServiceUrl(\n servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n resolvedAppType,\n )}/runtime/bootstrap`,\n ),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Runtime bootstrap failed: ${response.status}`,\n )\n }\n setState({\n data: payload?.data || null,\n loading: false,\n error: null,\n })\n } catch (error) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }, [resolvedAppType, resolvedFetch, servicePrefix])\n\n useEffect(() => {\n void reload()\n }, [reload])\n\n const value = useMemo<OpenXiangdaRuntimeStore>(\n () => ({\n ...state,\n appType: resolvedAppType,\n servicePrefix,\n fetchImpl: resolvedFetch,\n reload,\n }),\n [reload, resolvedAppType, resolvedFetch, servicePrefix, state],\n )\n\n return (\n <OpenXiangdaRuntimeContext.Provider value={value}>\n {children}\n </OpenXiangdaRuntimeContext.Provider>\n )\n}\n\nexport const useOpenXiangda = () => {\n const context = useContext(OpenXiangdaRuntimeContext)\n if (!context) {\n throw new Error(\"useOpenXiangda must be used inside OpenXiangdaProvider\")\n }\n return context\n}\n\nexport const useRuntimeBootstrap = () => useOpenXiangda()\n\nexport const useAppMenus = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.menus || [],\n }\n}\n\nexport const usePermission = () => {\n const runtime = useOpenXiangda()\n return {\n ...runtime,\n data: runtime.data?.permissions || null,\n }\n}\n\nexport interface UseCanAccessRouteInput {\n routeCode?: string\n menuCode?: string\n path?: string\n}\n\nexport const useCanAccessRoute = (input: UseCanAccessRouteInput) => {\n const runtime = useOpenXiangda()\n const [state, setState] = useState<RuntimeRequestState<RouteAccessResult>>({\n data: null,\n loading: true,\n error: null,\n })\n\n useEffect(() => {\n let disposed = false\n const check = async () => {\n const permissions = runtime.data?.permissions\n if (!runtime.appType || runtime.loading) {\n setState(prev => ({ ...prev, loading: runtime.loading }))\n return\n }\n if (runtime.error && !runtime.data) {\n const snapshot = toRuntimeErrorSnapshot(runtime.error)\n setState({\n data: {\n appType: runtime.appType,\n canAccess: false,\n status: snapshot.status,\n code: snapshot.code,\n message: snapshot.message,\n errorType: snapshot.type,\n payload: snapshot.payload,\n },\n loading: false,\n error: runtime.error,\n })\n return\n }\n if (permissions?.hasFullAccess) {\n setState({\n data: { appType: runtime.appType, canAccess: true, permissions },\n loading: false,\n error: null,\n })\n return\n }\n setState(prev => ({ ...prev, loading: true, error: null }))\n try {\n const response = await runtime.fetchImpl(\n buildServiceUrl(\n runtime.servicePrefix,\n `/openxiangda-api/v1/apps/${encodeURIComponent(\n runtime.appType,\n )}/runtime/routes/check`,\n ),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: {\n accept: \"application/json\",\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(input),\n },\n )\n const payload = await readJsonPayload(response)\n const code = payload?.code ?? response.status\n const canAccess = Boolean(payload?.data?.canAccess)\n const errorType = canAccess\n ? undefined\n : classifyRuntimeError(response.status, code)\n const data: RouteAccessResult = {\n ...(payload?.data || {\n appType: runtime.appType,\n canAccess: false,\n }),\n appType: payload?.data?.appType || runtime.appType,\n canAccess,\n status: response.status,\n code,\n message: payload?.message,\n errorType,\n payload,\n }\n if (!disposed) {\n const shouldTreatAsError =\n !response.ok || (typeof code === \"number\" && code >= 500)\n setState({\n data,\n loading: false,\n error: shouldTreatAsError\n ? createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Route check failed: ${response.status}`,\n )\n : null,\n })\n }\n } catch (error) {\n if (!disposed) {\n setState({\n data: null,\n loading: false,\n error: normalizeRuntimeError(error),\n })\n }\n }\n }\n void check()\n return () => {\n disposed = true\n }\n }, [\n input.menuCode,\n input.path,\n input.routeCode,\n runtime.appType,\n runtime.data?.permissions,\n runtime.fetchImpl,\n runtime.loading,\n runtime.servicePrefix,\n ])\n\n return {\n ...state,\n canAccess: Boolean(state.data?.canAccess),\n }\n}\n\nexport interface PermissionBoundaryProps extends UseCanAccessRouteInput {\n children: React.ReactNode\n fallback?: React.ReactNode | PermissionBoundaryFallback\n loadingFallback?: React.ReactNode | PermissionBoundaryFallback\n}\n\nexport interface PermissionBoundaryFallbackState {\n access: ReturnType<typeof useCanAccessRoute>\n runtime: ReturnType<typeof useOpenXiangda>\n error: RuntimeRequestError | null\n errorType: RuntimeErrorType\n status?: number\n code?: number | string\n message: string\n}\n\nexport type PermissionBoundaryFallback = (\n state: PermissionBoundaryFallbackState,\n) => React.ReactNode\n\nexport const PermissionBoundary: React.FC<PermissionBoundaryProps> = ({\n children,\n fallback = null,\n loadingFallback = null,\n routeCode,\n menuCode,\n path,\n}) => {\n const runtime = useOpenXiangda()\n const access = useCanAccessRoute({ routeCode, menuCode, path })\n const fallbackState = createPermissionFallbackState(access, runtime)\n if (access.loading) {\n return <>{renderBoundaryFallback(loadingFallback, fallbackState)}</>\n }\n if (!access.canAccess) {\n return <>{renderBoundaryFallback(fallback, fallbackState)}</>\n }\n return <>{children}</>\n}\n\nexport interface RuntimeResolveLoginOptions {\n redirectUri?: string\n loginUrl?: string\n domain?: string\n}\n\nexport interface RuntimeRedirectLoginOptions extends RuntimeResolveLoginOptions {\n replace?: boolean\n}\n\nexport interface RuntimeLogoutOptions extends RuntimeRedirectLoginOptions {\n continueOnError?: boolean\n}\n\nexport const useRuntimeAuth = () => {\n const runtime = useOpenXiangda()\n\n const resolveLoginUrl = useCallback(\n async (options: RuntimeResolveLoginOptions = {}) => {\n const redirectUri = options.redirectUri || getCurrentHref()\n const domain = options.domain || getCurrentHostname()\n const appTenantId = getRecordString(runtime.data?.app, \"tenantId\")\n\n try {\n const statusUrl = withQuery(\n buildServiceUrl(runtime.servicePrefix, \"/api/sso/status\"),\n { domain },\n )\n const statusResponse = await runtime.fetchImpl(statusUrl, {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n })\n const statusPayload = await readJsonPayload(statusResponse)\n const sso = statusPayload?.data || {}\n const enabled = Boolean(sso.enabled)\n const shouldUseSso = Boolean(\n enabled && (sso.forceLogin ?? sso.autoRedirect ?? true),\n )\n if (shouldUseSso) {\n const loginUrlResponse = await runtime.fetchImpl(\n withQuery(buildServiceUrl(runtime.servicePrefix, \"/api/sso/login-url\"), {\n domain,\n redirectUri,\n ...(sso.tenantId || appTenantId\n ? { tenantId: String(sso.tenantId || appTenantId) }\n : {}),\n ...(sso.protocol ? { protocol: String(sso.protocol) } : {}),\n }),\n {\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const loginUrlPayload = await readJsonPayload(loginUrlResponse)\n const loginUrl =\n loginUrlPayload?.data?.loginUrl ||\n loginUrlPayload?.data?.url ||\n loginUrlPayload?.loginUrl ||\n loginUrlPayload?.url\n if (loginUrl) return String(loginUrl)\n }\n } catch {\n // Login resolution must always have a local fallback so logged-out\n // users are not stranded behind a permission state.\n }\n\n const configuredLoginUrl =\n options.loginUrl ||\n getRuntimeEnv(\"OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_OPENXIANGDA_LOGIN_URL\") ||\n getRuntimeEnv(\"APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_APP_LOGIN_URL\") ||\n getRuntimeEnv(\"VITE_BATH_AUTH_URL\") ||\n getRuntimeEnv(\"BATH_AUTH_URL\")\n if (configuredLoginUrl) {\n return attachCallback(configuredLoginUrl, redirectUri)\n }\n return attachCallback(\"/platform/login\", redirectUri)\n },\n [runtime.data?.app, runtime.fetchImpl, runtime.servicePrefix],\n )\n\n const redirectToLogin = useCallback(\n async (options: RuntimeRedirectLoginOptions = {}) => {\n const loginUrl = await resolveLoginUrl(options)\n if (typeof window !== \"undefined\") {\n if (options.replace === false) {\n window.location.assign(loginUrl)\n } else {\n window.location.replace(loginUrl)\n }\n }\n return loginUrl\n },\n [resolveLoginUrl],\n )\n\n const logout = useCallback(async () => {\n const response = await runtime.fetchImpl(\n buildServiceUrl(runtime.servicePrefix, \"/api/auth/logout\"),\n {\n method: \"POST\",\n credentials: \"include\",\n headers: { accept: \"application/json\" },\n },\n )\n const payload = await readJsonPayload(response)\n if (!response.ok || payload?.code >= 400) {\n throw createRuntimeHttpError(\n response,\n payload,\n payload?.message || `Logout failed: ${response.status}`,\n )\n }\n return payload\n }, [runtime.fetchImpl, runtime.servicePrefix])\n\n const logoutAndRedirect = useCallback(\n async (options: RuntimeLogoutOptions = {}) => {\n try {\n await logout()\n } catch (error) {\n if (options.continueOnError === false) throw error\n }\n return redirectToLogin(options)\n },\n [logout, redirectToLogin],\n )\n\n return {\n logout,\n logoutAndRedirect,\n redirectToLogin,\n resolveLoginUrl,\n }\n}\n\nconst buildServiceUrl = (servicePrefix: string, path: string) => {\n const prefix = servicePrefix.endsWith(\"/\")\n ? servicePrefix.slice(0, -1)\n : servicePrefix\n const suffix = path.startsWith(\"/\") ? path : `/${path}`\n return `${prefix}${suffix}`\n}\n\nconst readJsonPayload = async (response: Response) => {\n try {\n return await response.json()\n } catch {\n return null\n }\n}\n\nconst createRuntimeHttpError = (\n response: Response,\n payload: unknown,\n fallbackMessage: string,\n): RuntimeRequestError =>\n createRuntimeError({\n type: classifyRuntimeError(\n response.status,\n getRecordValue(payload, \"code\") as number | string | undefined,\n ),\n status: response.status,\n code: getRecordValue(payload, \"code\") as number | string | undefined,\n message:\n (getRecordValue(payload, \"message\") as string | undefined) ||\n fallbackMessage,\n payload,\n })\n\nconst createRuntimeError = (\n snapshot: RuntimeErrorSnapshot,\n): RuntimeRequestError =>\n new RuntimeHttpError({\n ...snapshot,\n type: snapshot.type || \"unknown\",\n message: snapshot.message || \"Runtime request failed\",\n })\n\nconst normalizeRuntimeError = (error: unknown): RuntimeRequestError => {\n if (error instanceof RuntimeHttpError) return error\n if (error instanceof Error) {\n const runtimeError = error as RuntimeRequestError\n runtimeError.type = runtimeError.type || classifyRuntimeError(runtimeError.status, runtimeError.code)\n return runtimeError\n }\n return createRuntimeError({\n type: \"unknown\",\n message: String(error),\n })\n}\n\nconst toRuntimeErrorSnapshot = (\n error: RuntimeRequestError,\n): RuntimeErrorSnapshot => ({\n type: error.type || classifyRuntimeError(error.status, error.code),\n status: error.status,\n code: error.code,\n message: error.message || \"Runtime request failed\",\n payload: error.payload,\n})\n\nconst classifyRuntimeError = (\n status?: number,\n code?: number | string,\n): RuntimeErrorType => {\n const normalizedCode = typeof code === \"string\" ? Number(code) : code\n if (status === 401 || normalizedCode === 401) return \"unauthenticated\"\n if (status === 403 || normalizedCode === 403) return \"forbidden\"\n if (!status && !normalizedCode) return \"network\"\n return \"unknown\"\n}\n\nconst createPermissionFallbackState = (\n access: ReturnType<typeof useCanAccessRoute>,\n runtime: ReturnType<typeof useOpenXiangda>,\n): PermissionBoundaryFallbackState => {\n const error = access.error || runtime.error\n const accessData = access.data\n const errorType =\n accessData?.errorType ||\n error?.type ||\n (!access.canAccess ? \"forbidden\" : \"unknown\")\n return {\n access,\n runtime,\n error,\n errorType,\n status: accessData?.status || error?.status,\n code: accessData?.code || error?.code,\n message:\n accessData?.message ||\n error?.message ||\n (errorType === \"unauthenticated\"\n ? \"当前账号尚未登录\"\n : \"当前账号没有访问权限\"),\n }\n}\n\nconst renderBoundaryFallback = (\n fallback: React.ReactNode | PermissionBoundaryFallback,\n state: PermissionBoundaryFallbackState,\n) => (typeof fallback === \"function\" ? fallback(state) : fallback)\n\nconst withQuery = (\n url: string,\n params: Record<string, string | number | boolean | undefined>,\n) => {\n const query = new URLSearchParams()\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === \"\") return\n query.set(key, String(value))\n })\n const serialized = query.toString()\n if (!serialized) return url\n return `${url}${url.includes(\"?\") ? \"&\" : \"?\"}${serialized}`\n}\n\nconst attachCallback = (loginUrl: string, callback: string) => {\n if (!callback) return loginUrl\n try {\n const base =\n typeof window !== \"undefined\" ? window.location.origin : \"http://localhost\"\n const parsed = new URL(loginUrl, base)\n if (!parsed.searchParams.has(\"callback\") && !parsed.searchParams.has(\"redirectUri\")) {\n parsed.searchParams.set(\"callback\", callback)\n }\n if (loginUrl.startsWith(\"http://\") || loginUrl.startsWith(\"https://\")) {\n return parsed.toString()\n }\n return `${parsed.pathname}${parsed.search}${parsed.hash}`\n } catch {\n const separator = loginUrl.includes(\"?\") ? \"&\" : \"?\"\n return `${loginUrl}${separator}callback=${encodeURIComponent(callback)}`\n }\n}\n\nconst getCurrentHref = () =>\n typeof window === \"undefined\" ? \"\" : window.location.href\n\nconst getCurrentHostname = () =>\n typeof window === \"undefined\" ? \"\" : window.location.hostname\n\nconst getRuntimeEnv = (key: string) => {\n const env =\n typeof process !== \"undefined\"\n ? (process as unknown as { env?: Record<string, string | undefined> }).env\n : undefined\n return env?.[key]\n}\n\nconst getRecordValue = (value: unknown, key: string) => {\n if (!value || typeof value !== \"object\") return undefined\n return (value as Record<string, unknown>)[key]\n}\n\nconst getRecordString = (value: unknown, key: string) => {\n const result = getRecordValue(value, key)\n return typeof result === \"string\" ? result : undefined\n}\n\nconst resolveAppTypeFromLocation = () => {\n if (typeof window === \"undefined\") return \"\"\n const segments = window.location.pathname.split(\"/\").filter(Boolean)\n const viewIndex = segments[0] === \"view\" ? 1 : 0\n if (segments[viewIndex] === \"submit\") return segments[viewIndex + 1] || \"\"\n if (segments[viewIndex] === \"preview\") return segments[viewIndex + 1] || \"\"\n return segments[viewIndex] || \"\"\n}\n","export const createBoundFetch = (fetchImpl?: typeof fetch): typeof fetch => {\n const baseFetch = fetchImpl || globalThis.fetch;\n return ((input, init) => baseFetch.call(globalThis, input, init)) as typeof fetch;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
useParams,
|
|
6
6
|
} from "react-router-dom";
|
|
7
7
|
import { lazy, Suspense, type ReactNode } from "react";
|
|
8
|
-
import { Sparkles } from "lucide-react";
|
|
8
|
+
import { Database, FileText, Rocket, Settings, Shield, Sparkles, Workflow } from "lucide-react";
|
|
9
9
|
import { OpenXiangdaProvider } from "openxiangda/runtime/react";
|
|
10
10
|
|
|
11
11
|
import { AdminShell } from "@/layouts/AdminShell";
|
|
@@ -78,6 +78,13 @@ export const router = createBrowserRouter([
|
|
|
78
78
|
element: <AdminShell />,
|
|
79
79
|
children: [
|
|
80
80
|
{ index: true, element: <RuntimeWorkspacePage /> },
|
|
81
|
+
{ path: "forms", element: <MissingResourcePage type="form" /> },
|
|
82
|
+
{ path: "process", element: <MissingResourcePage type="process" /> },
|
|
83
|
+
{ path: "data", element: <MissingResourcePage type="data" /> },
|
|
84
|
+
{ path: "verification", element: <AdminSectionPage type="verification" /> },
|
|
85
|
+
{ path: "permissions", element: <AdminSectionPage type="permissions" /> },
|
|
86
|
+
{ path: "releases", element: <AdminSectionPage type="releases" /> },
|
|
87
|
+
{ path: "settings", element: <AdminSectionPage type="settings" /> },
|
|
81
88
|
{ path: "data/:formUuid", element: routeElement(<DataRoutePage />) },
|
|
82
89
|
{ path: "forms/:formUuid/new", element: routeElement(<FormRoutePage mode="submit" />) },
|
|
83
90
|
{ path: "forms/:formUuid/:formInstId", element: routeElement(<FormRoutePage mode="detail" />) },
|
|
@@ -107,3 +114,70 @@ export const router = createBrowserRouter([
|
|
|
107
114
|
},
|
|
108
115
|
{ path: "*", element: <NotFoundPage /> },
|
|
109
116
|
]);
|
|
117
|
+
|
|
118
|
+
function MissingResourcePage({ type }: { type: "form" | "process" | "data" }) {
|
|
119
|
+
const config = {
|
|
120
|
+
form: {
|
|
121
|
+
description: "当前应用还没有可用于默认提交页的普通表单。发布表单资源后,菜单会自动进入对应默认页。",
|
|
122
|
+
icon: <FileText size={24} />,
|
|
123
|
+
title: "暂无表单资源",
|
|
124
|
+
},
|
|
125
|
+
process: {
|
|
126
|
+
description: "当前应用还没有可用于流程发起页的流程表单。发布流程资源后,菜单会自动进入对应默认页。",
|
|
127
|
+
icon: <Workflow size={24} />,
|
|
128
|
+
title: "暂无流程资源",
|
|
129
|
+
},
|
|
130
|
+
data: {
|
|
131
|
+
description: "当前应用还没有可用于数据管理列表的普通表单。发布表单资源后,菜单会自动进入对应数据列表。",
|
|
132
|
+
icon: <Database size={24} />,
|
|
133
|
+
title: "暂无数据资源",
|
|
134
|
+
},
|
|
135
|
+
}[type];
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<MacStatePage
|
|
139
|
+
description={config.description}
|
|
140
|
+
icon={config.icon}
|
|
141
|
+
status="RESOURCE"
|
|
142
|
+
title={config.title}
|
|
143
|
+
/>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function AdminSectionPage({
|
|
148
|
+
type,
|
|
149
|
+
}: {
|
|
150
|
+
type: "verification" | "permissions" | "releases" | "settings";
|
|
151
|
+
}) {
|
|
152
|
+
const config = {
|
|
153
|
+
verification: {
|
|
154
|
+
description: "这里预留 AI 验证、测试账号和一次性登录链接的工作台入口。后续可按项目需要替换为自定义实现。",
|
|
155
|
+
icon: <Sparkles size={24} />,
|
|
156
|
+
title: "AI 验证",
|
|
157
|
+
},
|
|
158
|
+
permissions: {
|
|
159
|
+
description: "这里预留页面 code、角色页面权限和菜单可见性配置说明。平台权限仍以后端接口为准。",
|
|
160
|
+
icon: <Shield size={24} />,
|
|
161
|
+
title: "角色权限",
|
|
162
|
+
},
|
|
163
|
+
releases: {
|
|
164
|
+
description: "这里预留运行时版本、构建记录和发布动作入口。当前模板默认通过 OpenXiangda CLI 发布。",
|
|
165
|
+
icon: <Rocket size={24} />,
|
|
166
|
+
title: "发布版本",
|
|
167
|
+
},
|
|
168
|
+
settings: {
|
|
169
|
+
description: "这里预留应用运行参数和本地开发代理配置入口。业务项目可以按需整页覆盖。",
|
|
170
|
+
icon: <Settings size={24} />,
|
|
171
|
+
title: "系统设置",
|
|
172
|
+
},
|
|
173
|
+
}[type];
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<MacStatePage
|
|
177
|
+
description={config.description}
|
|
178
|
+
icon={config.icon}
|
|
179
|
+
status="ADMIN"
|
|
180
|
+
title={config.title}
|
|
181
|
+
/>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
@@ -61,23 +61,29 @@ const systemNavigation: MenuGroup[] = [
|
|
|
61
61
|
{
|
|
62
62
|
title: "表单与流程",
|
|
63
63
|
items: [
|
|
64
|
-
{ hint: "默认提交页", icon: FileText, name: "表单模板", path: "admin
|
|
65
|
-
{ hint: "流程发起和详情", icon: Workflow, name: "流程模板", path: "admin
|
|
66
|
-
{ hint: "数据管理列表", icon: Database, name: "数据列表", path: "admin
|
|
67
|
-
{ hint: "平台文件 ticket", icon: Upload, name: "文件预览", path: "
|
|
64
|
+
{ hint: "默认提交页", icon: FileText, name: "表单模板", path: "admin/forms" },
|
|
65
|
+
{ hint: "流程发起和详情", icon: Workflow, name: "流程模板", path: "admin/process" },
|
|
66
|
+
{ hint: "数据管理列表", icon: Database, name: "数据列表", path: "admin/data" },
|
|
67
|
+
{ hint: "平台文件 ticket", icon: Upload, name: "文件预览", path: "file-preview" },
|
|
68
68
|
],
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
title: "权限与发布",
|
|
72
72
|
items: [
|
|
73
|
-
{ hint: "真实用户验证", icon: Sparkles, name: "AI 验证", path: "admin
|
|
74
|
-
{ hint: "页面 code 与角色", icon: Shield, name: "角色权限", path: "admin
|
|
75
|
-
{ hint: "版本与部署", icon: Rocket, name: "发布版本", path: "admin
|
|
76
|
-
{ hint: "运行参数", icon: Settings, name: "系统设置", path: "admin
|
|
73
|
+
{ hint: "真实用户验证", icon: Sparkles, name: "AI 验证", path: "admin/verification" },
|
|
74
|
+
{ hint: "页面 code 与角色", icon: Shield, name: "角色权限", path: "admin/permissions" },
|
|
75
|
+
{ hint: "版本与部署", icon: Rocket, name: "发布版本", path: "admin/releases" },
|
|
76
|
+
{ hint: "运行参数", icon: Settings, name: "系统设置", path: "admin/settings" },
|
|
77
77
|
],
|
|
78
78
|
},
|
|
79
79
|
];
|
|
80
80
|
|
|
81
|
+
type RuntimeMenuLike = {
|
|
82
|
+
formUuid?: string | null;
|
|
83
|
+
path?: string | null;
|
|
84
|
+
type?: string | null;
|
|
85
|
+
};
|
|
86
|
+
|
|
81
87
|
export function AdminShell() {
|
|
82
88
|
const { appType = "" } = useParams();
|
|
83
89
|
const location = useLocation();
|
|
@@ -97,6 +103,14 @@ export function AdminShell() {
|
|
|
97
103
|
bootstrap.data?.user?.id ||
|
|
98
104
|
"未登录",
|
|
99
105
|
);
|
|
106
|
+
const primaryReceiptFormUuid = useMemo(
|
|
107
|
+
() => findMenuFormUuid(menus.data, ["receipt", "form"]),
|
|
108
|
+
[menus.data],
|
|
109
|
+
);
|
|
110
|
+
const primaryProcessFormUuid = useMemo(
|
|
111
|
+
() => findMenuFormUuid(menus.data, ["process", "workflow"]),
|
|
112
|
+
[menus.data],
|
|
113
|
+
);
|
|
100
114
|
|
|
101
115
|
const groups = useMemo<MenuGroup[]>(() => {
|
|
102
116
|
const platformItems = menus.data.length
|
|
@@ -108,7 +122,7 @@ export function AdminShell() {
|
|
|
108
122
|
hint: child.routeCode || child.resourceCode || undefined,
|
|
109
123
|
icon: resolveMenuIcon(String(child.name || child.path || "")),
|
|
110
124
|
name: child.name,
|
|
111
|
-
path:
|
|
125
|
+
path: resolveRuntimeMenuPath(appType, child),
|
|
112
126
|
}));
|
|
113
127
|
})
|
|
114
128
|
: fallbackNavigation.map(item => ({
|
|
@@ -118,15 +132,17 @@ export function AdminShell() {
|
|
|
118
132
|
|
|
119
133
|
return [
|
|
120
134
|
{ title: "应用导航", items: platformItems },
|
|
121
|
-
...
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
135
|
+
...buildSystemNavigation(primaryReceiptFormUuid, primaryProcessFormUuid).map(
|
|
136
|
+
group => ({
|
|
137
|
+
...group,
|
|
138
|
+
items: group.items.map(item => ({
|
|
139
|
+
...item,
|
|
140
|
+
path: resolveMenuPath(appType, item.path),
|
|
141
|
+
})),
|
|
142
|
+
}),
|
|
143
|
+
),
|
|
128
144
|
];
|
|
129
|
-
}, [appType, menus.data]);
|
|
145
|
+
}, [appType, menus.data, primaryProcessFormUuid, primaryReceiptFormUuid]);
|
|
130
146
|
|
|
131
147
|
const handleLogout = async () => {
|
|
132
148
|
setLoggingOut(true);
|
|
@@ -418,6 +434,58 @@ function resolveMenuPath(appType: string, rawPath: string) {
|
|
|
418
434
|
return `/view/${appType}/${path}`.replace(/\/{2,}/g, "/");
|
|
419
435
|
}
|
|
420
436
|
|
|
437
|
+
function resolveRuntimeMenuPath(appType: string, menu: RuntimeMenuLike) {
|
|
438
|
+
if (menu.path) return resolveMenuPath(appType, menu.path);
|
|
439
|
+
const type = String(menu.type || "").toLowerCase();
|
|
440
|
+
const formUuid = menu.formUuid ? encodeURIComponent(menu.formUuid) : "";
|
|
441
|
+
if (formUuid && (type.includes("process") || type.includes("workflow"))) {
|
|
442
|
+
return resolveMenuPath(appType, `admin/forms/${formUuid}/new`);
|
|
443
|
+
}
|
|
444
|
+
if (formUuid && (type.includes("receipt") || type.includes("form"))) {
|
|
445
|
+
return resolveMenuPath(appType, `admin/forms/${formUuid}/new`);
|
|
446
|
+
}
|
|
447
|
+
return resolveMenuPath(appType, "admin");
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function buildSystemNavigation(receiptFormUuid?: string, processFormUuid?: string): MenuGroup[] {
|
|
451
|
+
const receiptPath = receiptFormUuid
|
|
452
|
+
? `admin/forms/${encodeURIComponent(receiptFormUuid)}/new`
|
|
453
|
+
: "admin/forms";
|
|
454
|
+
const processPath = processFormUuid
|
|
455
|
+
? `admin/forms/${encodeURIComponent(processFormUuid)}/new`
|
|
456
|
+
: "admin/process";
|
|
457
|
+
const dataPath = receiptFormUuid
|
|
458
|
+
? `admin/data/${encodeURIComponent(receiptFormUuid)}`
|
|
459
|
+
: "admin/data";
|
|
460
|
+
|
|
461
|
+
return systemNavigation.map(group => ({
|
|
462
|
+
...group,
|
|
463
|
+
items: group.items.map(item => {
|
|
464
|
+
if (item.name === "表单模板") return { ...item, path: receiptPath };
|
|
465
|
+
if (item.name === "流程模板") return { ...item, path: processPath };
|
|
466
|
+
if (item.name === "数据列表") return { ...item, path: dataPath };
|
|
467
|
+
if (item.name === "文件预览") return { ...item, path: "file-preview" };
|
|
468
|
+
return item;
|
|
469
|
+
}),
|
|
470
|
+
}));
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function findMenuFormUuid(
|
|
474
|
+
items: RuntimeMenuLike[],
|
|
475
|
+
types: string[],
|
|
476
|
+
): string | undefined {
|
|
477
|
+
for (const item of items) {
|
|
478
|
+
const type = String(item.type || "").toLowerCase();
|
|
479
|
+
if (item.formUuid && types.some(candidate => type.includes(candidate))) {
|
|
480
|
+
return item.formUuid;
|
|
481
|
+
}
|
|
482
|
+
const children = (item as { children?: RuntimeMenuLike[] }).children || [];
|
|
483
|
+
const nested: string | undefined = findMenuFormUuid(children, types);
|
|
484
|
+
if (nested) return nested;
|
|
485
|
+
}
|
|
486
|
+
return undefined;
|
|
487
|
+
}
|
|
488
|
+
|
|
421
489
|
function resolveMenuIcon(value: string): typeof LayoutDashboard {
|
|
422
490
|
const normalized = value.toLowerCase();
|
|
423
491
|
if (normalized.includes("用户") || normalized.includes("portal")) return Home;
|