@oj-module/runtime 0.1.8 → 0.1.11

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.
@@ -7,9 +7,37 @@ import type { z } from "zod";
7
7
  * `{*path}` catch-all,参数段内不得混字面(`{id}.json` 非法)。
8
8
  */
9
9
  export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD" | "OPTIONS";
10
+ /**
11
+ * multipart/form-data 的文件部件:**只声明名字与形态**。
12
+ *
13
+ * 二进制刻意不进 zod(JSON Schema 无 binary 类型,且字节由运行时的 FormData
14
+ * 组装):oj 侧按 `http.files`(元数据 { field, filename, content_type, size })
15
+ * 与 `http.file(i)`(字节)读取。
16
+ */
17
+ export interface ApiFormFile {
18
+ /** 表单字段名(= FormData 的 append key = oj 侧 http.files[].field) */
19
+ name: string;
20
+ /** true = 必传;缺省可选(可选文件不 append 部件,oj 侧自然缺省) */
21
+ required?: boolean;
22
+ /** true = 同名多文件:生成 client 接受数组并逐个 append(oj 侧 http.files 多条) */
23
+ multiple?: boolean;
24
+ }
25
+ /** multipart/form-data 请求体:文本部件走 zod,文件部件只声明形态(与 body 互斥) */
26
+ export interface ApiFormInput {
27
+ /** 文本部件 schema(z.object——字段名即部件名;进 OpenAPI 的 multipart JSON schema) */
28
+ fields?: z.ZodType;
29
+ /** 文件部件(与 fields 至少声明其一) */
30
+ files?: ApiFormFile[];
31
+ }
10
32
  export interface ApiDefinitionInput {
11
33
  /** 模块 API 前缀("/" 开头);uni-dev 形态字面等于 oj 模块段名(AC-D9) */
12
34
  apiPrefix: string;
35
+ /**
36
+ * 线上 URL 前缀("/" 开头,D-M8):存量 oj 后端 URL 命名空间与目录名错位时
37
+ * 显式声明(如目录 workitems、URL /workspaces/{slug}/...)。缺省 = apiPrefix。
38
+ * 认领/护栏身份仍按 apiPrefix(目录名);线上前缀不一致的同模块端点混用报错。
39
+ */
40
+ urlPrefix?: string;
13
41
  /** 相对 apiPrefix 的路由("/" 开头),支持 `{id}` / `{*path}` 参数段 */
14
42
  route: string;
15
43
  /** HTTP 方法,缺省 "GET"(IR 层归一) */
@@ -18,8 +46,13 @@ export interface ApiDefinitionInput {
18
46
  query?: z.ZodType;
19
47
  /** 路径参数 schema(与 route 参数段一一对应) */
20
48
  params?: z.ZodType;
21
- /** 请求体 schema */
49
+ /** 请求体 schema(JSON;与 form 互斥) */
22
50
  body?: z.ZodType;
51
+ /**
52
+ * multipart/form-data 请求体(与 body 互斥):文本部件写进 form.fields(zod),
53
+ * 文件部件只声明名字——二进制无法保真进 JSON Schema,FormData 由生成 client 组装。
54
+ */
55
+ form?: ApiFormInput;
23
56
  /** 响应信封 data 部分的 schema;与 response:"raw" 互斥 */
24
57
  data?: z.ZodType;
25
58
  /** "raw" = 二进制/非信封逃生口:不解包、不校验、不进 mock 生成 */
@@ -8,6 +8,8 @@ function validateDefinition(def) {
8
8
  if (!apiPrefix?.startsWith("/")) {
9
9
  throw new Error(`[契约] apiPrefix 必须以 "/" 开头(收到: ${apiPrefix})——如 "/order";uni-dev 形态请与 oj 模块段名保持一致(AC-D9)。`);
10
10
  }
11
+ if (def.urlPrefix !== undefined && !def.urlPrefix.startsWith("/"))
12
+ fail(route, `urlPrefix 必须以 "/" 开头(收到: ${def.urlPrefix})。`);
11
13
  if (!route?.startsWith("/"))
12
14
  fail(route, `route 必须以 "/" 开头(收到: ${route}),且一律相对 apiPrefix——不支持 oj 的根绝对写法(模块手册 D11 前缀收敛)。`);
13
15
  if (route.split("/").some(seg => seg === ".." || seg === "." || seg === "\\"))
@@ -18,6 +20,21 @@ function validateDefinition(def) {
18
20
  }
19
21
  if (def.data && def.response === "raw")
20
22
  fail(route, "data schema 与 response:\"raw\" 互斥——raw 端点不解包信封,不需要 data schema。");
23
+ if (def.form && def.body)
24
+ fail(route, "form 与 body 互斥——一个端点只有一种请求体形态:multipart/form-data(form)与 JSON(body)声明其一,文本字段请写进 form.fields。");
25
+ if (def.form) {
26
+ const files = def.form.files ?? [];
27
+ if (!def.form.fields && files.length === 0)
28
+ fail(route, "form 至少需要 fields 或一项 files——空 multipart 请求体无意义;无请求体请删掉 form(改用 query/params)。");
29
+ const seen = new Set();
30
+ for (const file of files) {
31
+ if (!file?.name)
32
+ fail(route, "form.files 每项必须有 name——它既是 FormData 的 append key,也是 oj 侧 http.files[].field 的字段名。");
33
+ if (seen.has(file.name))
34
+ fail(route, `form.files 字段名 "${file.name}" 重复——同名多文件请用 multiple: true。`);
35
+ seen.add(file.name);
36
+ }
37
+ }
21
38
  if (def.response !== undefined && def.response !== "raw")
22
39
  fail(route, `response 仅支持 "raw"(收到: ${String(def.response)})。`);
23
40
  // 评审 F9:方法面在定义期封顶,而不是延迟到 codegen 才炸
@@ -9,7 +9,7 @@
9
9
  * - ScopedRequestLike:生成 client 的 request 最小结构类型
10
10
  */
11
11
  export { API_DEF, defineApi } from "./define-api.ts";
12
- export type { ApiDefinitionInput, HttpMethod } from "./define-api.ts";
12
+ export type { ApiDefinitionInput, ApiFormFile, ApiFormInput, HttpMethod } from "./define-api.ts";
13
13
  export { ContractApiError } from "./errors.ts";
14
14
  export type { ScopedRequestLike } from "./scoped-request-like.ts";
15
15
  export { z } from "zod";
@@ -12,6 +12,11 @@ export interface RequestCall {
12
12
  /** 与 ky SearchParamsOption 的 Record 形态对齐——宽于它则真 ky 实例无法赋给本接口 */
13
13
  searchParams?: Record<string, string | number | boolean>;
14
14
  json?: unknown;
15
+ /**
16
+ * multipart/form-data 请求体(form 端点):由生成 client 组装 FormData,
17
+ * content-type 交运行时(ky 按 boundary 自动补 multipart/form-data)。
18
+ */
19
+ body?: FormData;
15
20
  ignoreLoading?: boolean;
16
21
  }): ResponsePromiseLike;
17
22
  }
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ export * from "./components/basic-form";
21
21
  export { BasicTable } from "./components/basic-table";
22
22
  export type { BasicTableProps } from "./components/basic-table";
23
23
  export { Iframe } from "./components/iframe";
24
+ export { PageError } from "./components/page-error";
24
25
  export * from "./constants/options";
25
26
  export * from "./hooks/use-access";
26
27
  export { usePreferences } from "./hooks/use-preferences";
@@ -36,10 +37,12 @@ export type { AppRouteRecordRaw, RouteMeta } from "./router/types";
36
37
  export type { NotificationsApiProvider, SystemApiProvider, UploadApiProvider, } from "./store/api-provider";
37
38
  export { useAuthStore } from "./store/auth";
38
39
  export type { AuthProvider } from "./store/auth-provider";
40
+ export type { HeaderProvider } from "./store/header-provider";
39
41
  export { useUserStore } from "./store/user";
40
42
  export type { AppInfo } from "./types/app-info";
41
43
  export { getAllExpandedKeys } from "./utils/get-all-expanded-keys";
42
44
  export { getAppInfo } from "./utils/get-app-info";
43
45
  export { getRedirectPath } from "./utils/get-redirect-path";
44
46
  export * from "./utils/tree";
47
+ export { ErrorBoundary } from "react-error-boundary";
45
48
  export { z } from "zod";
@@ -0,0 +1,8 @@
1
+ import type { ComponentType } from "react";
2
+ export declare function registerLayout(moduleName: string, name: string, component: ComponentType): void;
3
+ export declare function getRegisteredLayout(name: string): ComponentType | undefined;
4
+ /**
5
+ * 卸载模块时清掉其登记的全部布局(以 moduleName 隔离,不影响其他模块)。
6
+ * 只影响「再解析」语义——已注入运行中 router 的路由不热回落(设计文档 N8)。
7
+ */
8
+ export declare function unregisterLayouts(moduleName: string): void;
@@ -1,9 +1,11 @@
1
1
  import type { ButtonProps } from "antd";
2
2
  import type { NotificationItem } from "./types";
3
- type NotificationEventType = "viewAll" | "makeAll" | "clear" | "read";
3
+ export type NotificationEventType = "viewAll" | "makeAll" | "clear" | "read";
4
4
  interface Props extends ButtonProps {
5
5
  /**
6
- * 显示圆点
6
+ * 互动事件回调。存在即可互动;缺省(未注册 provider / provider 缺写方法的
7
+ * 老 bundle 漂移)时整体只读——「全部已读」「清空」禁用、单条点击 no-op
8
+ * (评审 A3:不加 disabled/readOnly 新 prop,由回调存在性推导)。
7
9
  */
8
10
  onEventChange?: (event: NotificationEventType, item?: NotificationItem) => void;
9
11
  /**
@@ -1,2 +1,11 @@
1
1
  import type { ButtonProps } from "antd";
2
+ /**
3
+ * 通知容器(G4):拉取列表 + 接线互动事件。
4
+ *
5
+ * - 互动可用的前提:注册了 provider 且四方法齐全;否则降级只读
6
+ * (popup 按 onEventChange 是否存在推导,评审 A3——不加新 prop);
7
+ * - 写操作成功后重拉刷新;**重拉失败不清空现有列表**(评审 b4);
8
+ * - 20x 复制残留已删除(评审 b4,同一 id 复制 20 份会让 markRead 语义失真);
9
+ * - viewAll 不接线(N3,模板无通知中心页)。
10
+ */
2
11
  export declare function NotificationContainer({ ...restProps }: ButtonProps): import("#node_modules/@types/react").JSX.Element;
@@ -1,4 +1,6 @@
1
1
  export interface NotificationItem {
2
+ /** 必填——单条已读/清空等写操作的前提(G4,破坏性变更,发版说明标注) */
3
+ id: string | number;
2
4
  avatar: string;
3
5
  date: string;
4
6
  isRead?: boolean;
@@ -5,6 +5,7 @@ export declare function getModules(): ModuleInstance[];
5
5
  export declare function getModule(name: string): ModuleInstance | undefined;
6
6
  export declare function getRoutes(): AppRouteRecordRaw[];
7
7
  export declare function getRegisteredStore<T = unknown>(name: string): T | undefined;
8
+ /** 首个登记的前缀(一模块可登记多个);未登记返回 undefined */
8
9
  export declare function getRegisteredApiPrefix(moduleName: string): string | undefined;
9
10
  /**
10
11
  * 卸载模块:执行 onDestroy 生命周期 → 清理其布局插槽(US-8)→ 移除实例。
@@ -1,6 +1,7 @@
1
1
  import type { AppRouteRecordRaw } from "../router/types";
2
- import type { NotificationsApiProvider, SystemApiProvider, UploadApiProvider } from "../store/api-provider";
2
+ import type { NotificationsApiProvider, RoutesApiProvider, SystemApiProvider, UploadApiProvider } from "../store/api-provider";
3
3
  import type { AuthProvider } from "../store/auth-provider";
4
+ import type { HeaderProvider } from "../store/header-provider";
4
5
  /** 模块上下文 — 主框架向模块注入的能力 */
5
6
  export interface ModuleContext {
6
7
  /** 当前模块的元信息 */
@@ -16,16 +17,29 @@ export interface ModuleContext {
16
17
  register: {
17
18
  /** 注册额外的 Zustand store */
18
19
  store: (name: string, store: unknown) => void;
19
- /** 注册 API 路由前缀 */
20
+ /**
21
+ * 注册 API 路由前缀(追加语义:一模块可登记多个,重复登记同值无副作用)。
22
+ * `ctx.utils.request` 放行命中其中任一前缀的 URL
23
+ */
20
24
  apiPrefix: (prefix: string) => void;
21
25
  /** 接管登录/登出/用户信息(P5);先到先得,模块卸载时自动注销 */
22
26
  authProvider: (provider: AuthProvider) => void;
27
+ /** 注入惰性求值的自定义请求头(D-M9);先到先得,模块卸载时自动注销 */
28
+ headerProvider: (provider: HeaderProvider) => void;
23
29
  /** 接管系统角色/菜单类 API(D9);先到先得,模块卸载时自动注销 */
24
30
  systemApi: (provider: SystemApiProvider) => void;
25
31
  /** 接管通知拉取 API(D9);先到先得,模块卸载时自动注销 */
26
32
  notificationsApi: (provider: NotificationsApiProvider) => void;
27
33
  /** 接管头像/附件上传端点(D9);先到先得,模块卸载时自动注销 */
28
34
  uploadApi: (provider: UploadApiProvider) => void;
35
+ /**
36
+ * 注册布局名(G1):新名字供 handle.layout 引用,或覆盖内建名
37
+ * (container/parent/fullscreen,覆盖 = 自担 chrome 全部职责)。
38
+ * 先到先得,模块卸载时自动注销(再解析语义,不热回落见 N8)
39
+ */
40
+ layout: (name: string, component: React.ComponentType) => void;
41
+ /** 接管后端动态路由拉取(G2);先到先得,模块卸载时自动注销 */
42
+ routesApi: (provider: RoutesApiProvider) => void;
29
43
  };
30
44
  /** 注册布局插槽节点(US-8 L2),卸载模块时自动清理 */
31
45
  registerSlot: (slotName: string, node: React.ReactNode) => void;
@@ -19,7 +19,7 @@ declare const baseRoutes: ({
19
19
  roles?: string[];
20
20
  permissions?: string[];
21
21
  keepAlive?: boolean;
22
- layout?: "container" | "parent" | "fullscreen" | "none";
22
+ layout?: "container" | "parent" | "fullscreen" | "none" | (string & {});
23
23
  login?: boolean;
24
24
  internal?: boolean;
25
25
  hideInMenu?: boolean;
@@ -67,7 +67,7 @@ declare const baseRoutes: ({
67
67
  roles?: string[];
68
68
  permissions?: string[];
69
69
  keepAlive?: boolean;
70
- layout?: "container" | "parent" | "fullscreen" | "none";
70
+ layout?: "container" | "parent" | "fullscreen" | "none" | (string & {});
71
71
  login?: boolean;
72
72
  internal?: boolean;
73
73
  hideInMenu?: boolean;
@@ -42,9 +42,11 @@ export interface RouteMeta {
42
42
  * - `"parent"`:套父级布局(自身含 Outlet,用于嵌套菜单场景)
43
43
  * - `"fullscreen"`:套全屏外壳(视口 + 品牌区 + 角落工具 + 页脚,无 chrome),登录页用(P1)
44
44
  * - `"none"`:不套任何布局,页面/子路由直接渲染
45
+ * - 其他字符串:模块经 `ctx.register.layout` 登记的名字(含覆盖内建名)。
46
+ * 模板联合保留内建名补全,未知名运行时 warn-once 并回落 Outlet(G1,评审 P2-6)
45
47
  * @default "container"(迁移期向后兼容,目标在 P2.7 补全显式声明后改为 `"none"`)
46
48
  */
47
- layout?: "container" | "parent" | "fullscreen" | "none";
49
+ layout?: "container" | "parent" | "fullscreen" | "none" | (string & {});
48
50
  /**
49
51
  * 登录页标记(login 模块化,P1):声明在 `path: "/login"` 的模块路由上,
50
52
  * 供 resolveLoginRoute 识别并剔除内置兜底。仅模块路由受信,后端路由忽略。
@@ -8,7 +8,7 @@ export declare function ascending(arr: AppRouteRecordRaw[]): ({
8
8
  roles?: string[];
9
9
  permissions?: string[];
10
10
  keepAlive?: boolean;
11
- layout?: "container" | "parent" | "fullscreen" | "none";
11
+ layout?: "container" | "parent" | "fullscreen" | "none" | (string & {});
12
12
  login?: boolean;
13
13
  internal?: boolean;
14
14
  hideInMenu?: boolean;
@@ -56,7 +56,7 @@ export declare function ascending(arr: AppRouteRecordRaw[]): ({
56
56
  roles?: string[];
57
57
  permissions?: string[];
58
58
  keepAlive?: boolean;
59
- layout?: "container" | "parent" | "fullscreen" | "none";
59
+ layout?: "container" | "parent" | "fullscreen" | "none" | (string & {});
60
60
  login?: boolean;
61
61
  internal?: boolean;
62
62
  hideInMenu?: boolean;
@@ -1,10 +1,13 @@
1
1
  import type { ComponentType } from "react";
2
2
  import type { AppRouteRecordRaw, RouteMeta } from "../types";
3
3
  /**
4
- * 根据路由 `handle.layout` 解析所用布局组件(P2.2,设计文档 D9)。
4
+ * 根据路由 `handle.layout` 解析所用布局组件(P2.2,设计文档 D9;G1 模块登记优先)。
5
5
  *
6
6
  * 未声明即 `none` 是 D9 的目标态(P2.7 dogfooding 验证后自迁移期默认 `container` 翻转):
7
7
  * 布局必须显式声明,框架不做隐式推导;后端下发的父级路由需在 handle 中携带 layout。
8
+ *
9
+ * 非内建且模块注册表未命中的名字 warn-once 一次并回落 Outlet——
10
+ * 后端下发了模块布局名而提供方模块未加载时,这条 warn 是唯一线索(评审 A6)。
8
11
  */
9
12
  export declare function resolveLayoutComponent(handle?: Partial<RouteMeta>): ComponentType;
10
13
  /**
package/dist/runtime.js CHANGED
@@ -9,7 +9,7 @@ import ky from "ky";
9
9
  import { create } from "zustand";
10
10
  import { persist } from "zustand/middleware";
11
11
  import { Link, Navigate, Outlet, createBrowserRouter, matchRoutes, useLocation, useMatches, useNavigate, useOutlet, useSearchParams } from "react-router";
12
- import { ErrorBoundary } from "react-error-boundary";
12
+ import { ErrorBoundary, ErrorBoundary as ErrorBoundary$1 } from "react-error-boundary";
13
13
  import { AntDesignOutlined, ApartmentOutlined, AppstoreOutlined, ArrowDownOutlined, ArrowLeftOutlined, ArrowUpOutlined, BellOutlined, CloseOutlined, CloudOutlined, ContainerOutlined, CopyOutlined, CopyrightOutlined, DownOutlined, EnterOutlined, EyeOutlined, FileTextOutlined, FullscreenExitOutlined, FullscreenOutlined, HomeOutlined, LoadingOutlined, LockOutlined, LogoutOutlined, MenuFoldOutlined, MenuOutlined, MenuUnfoldOutlined, NodeExpandOutlined, QuestionCircleOutlined, RedoOutlined, ReloadOutlined, RocketOutlined, SafetyOutlined, SearchOutlined, SettingOutlined, SisternodeOutlined, SubnodeOutlined, SwapOutlined, TeamOutlined, TranslationOutlined, UploadOutlined, UserOutlined, VerticalAlignBottomOutlined, VerticalAlignMiddleOutlined, VerticalAlignTopOutlined } from "@ant-design/icons";
14
14
  import { App, Avatar, Badge, Breadcrumb, Button, Checkbox, Col, ColorPicker, ConfigProvider, Divider, Drawer, Dropdown, Empty, FloatButton, Form, Grid, Input, InputNumber, List, Menu, Modal, Popover, Result, Row, Select, Slider, Space, Spin, Switch, Tabs, Tooltip, Tree, Typography, Upload, Watermark, message, notification, theme } from "antd";
15
15
  import { Fragment, Suspense, cloneElement, createElement, forwardRef, isValidElement, lazy, use, useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -96,16 +96,30 @@ function registerUploadApiProvider(moduleName, provider) {
96
96
  function getUploadApiProvider() {
97
97
  return uploadCurrent?.provider;
98
98
  }
99
+ function registerRoutesApiProvider(moduleName, provider) {
100
+ if (routesCurrent) {
101
+ console.warn(`[api] 重复的动态路由 provider 忽略:已由模块 "${routesCurrent.moduleName}" 提供,忽略 "${moduleName}"(先到先得)。`);
102
+ return;
103
+ }
104
+ routesCurrent = {
105
+ moduleName,
106
+ provider
107
+ };
108
+ }
109
+ function getRoutesApiProvider() {
110
+ return routesCurrent?.provider;
111
+ }
99
112
  /**
100
- * 卸载模块时复位其登记的全部 API provider(系统/通知/上传)。以 moduleName
113
+ * 卸载模块时复位其登记的全部 API provider(系统/通知/上传/动态路由)。以 moduleName
101
114
  * 作命名隔离——不同模块各自登记互不干扰,卸载只清自己的。
102
115
  */
103
116
  function unregisterApiProviders(moduleName) {
104
117
  if (systemCurrent?.moduleName === moduleName) systemCurrent = void 0;
105
118
  if (notificationsCurrent?.moduleName === moduleName) notificationsCurrent = void 0;
106
119
  if (uploadCurrent?.moduleName === moduleName) uploadCurrent = void 0;
120
+ if (routesCurrent?.moduleName === moduleName) routesCurrent = void 0;
107
121
  }
108
- var systemCurrent, notificationsCurrent, uploadCurrent;
122
+ var systemCurrent, notificationsCurrent, uploadCurrent, routesCurrent;
109
123
  var init_api_provider = __esmMin((() => {}));
110
124
  //#endregion
111
125
  //#region src/router/extra-info/route-path.ts
@@ -163,6 +177,8 @@ function fetchLogout(data) {
163
177
  return request.post("auth/logout", { json: { refresh_token: data?.refreshToken ?? "" } }).json().then(() => {});
164
178
  }
165
179
  function fetchAsyncRoutes() {
180
+ const p = getRoutesApiProvider();
181
+ if (p) return p.fetchAsyncRoutes();
166
182
  return request.get("web/get-async-routes").json().then((env) => env.data ?? []);
167
183
  }
168
184
  function fetchUserInfo() {
@@ -172,12 +188,13 @@ function fetchRefreshToken(data) {
172
188
  return request.post(REFRESH_TOKEN_PATH, { json: { refresh_token: data.refreshToken } }).json().then((env) => mapAuthPayload(env.data));
173
189
  }
174
190
  var init_user$1 = __esmMin((() => {
191
+ init_api_provider();
175
192
  init_request();
176
193
  init_constants$3();
177
194
  init_types();
178
195
  }));
179
196
  //#endregion
180
- //#region src/assets/svg/undraw-bug-fixing.svg?react
197
+ //#region src/assets/svg/undraw-bug-fixing.svg?url
181
198
  var undraw_bug_fixing_default;
182
199
  var init_undraw_bug_fixing = __esmMin((() => {
183
200
  undraw_bug_fixing_default = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201022.7%20785.81'%3e%3cdefs%3e%3clinearGradient%20id='a'%20x1='678.2'%20x2='678.2'%20y1='821.79'%20y2='493.4'%20gradientTransform='rotate(-2.31%20725.2%20516.777)'%20gradientUnits='userSpaceOnUse'%3e%3cstop%20offset='0'%20stop-color='gray'%20stop-opacity='.25'/%3e%3cstop%20offset='.54'%20stop-color='gray'%20stop-opacity='.12'/%3e%3cstop%20offset='1'%20stop-color='gray'%20stop-opacity='.1'/%3e%3c/linearGradient%3e%3c/defs%3e%3cellipse%20cx='468.63'%20cy='660.88'%20fill='%236c63ff'%20opacity='.1'%20rx='425'%20ry='33'/%3e%3cg%20opacity='.1'%3e%3cpath%20fill='%233f3d56'%20d='M845.05%20472.84c-2.54-7.71-12.84-11.26-23-7.92a24.76%2024.76%200%200%200-4.23%201.83c-.65-.18-1.32-.34-2-.46a22.42%2022.42%200%200%200%20.63-6.79%2024.6%2024.6%200%200%200%2010.9-21.47%2024.63%2024.63%200%200%200%2010.86-21.47%2023.76%2023.76%200%200%200%208.23-9.32c4.9-9.7%202.87-20.6-4.54-24.35s-17.4%201.08-22.3%2010.78a23.69%2023.69%200%200%200-2.63%2012.15%2024.63%2024.63%200%200%200-10.86%2021.47%2024.63%2024.63%200%200%200-10.86%2021.47%2024.64%2024.64%200%200%200-10.9%2021.48%2023.76%2023.76%200%200%200-8.23%209.32%2025.46%2025.46%200%200%200-2.08%205.74%2021.18%2021.18%200%200%200-4.44-4.73%2025.38%2025.38%200%200%200-1-4.5c-3.34-10.17-12.3-16.37-20-13.83s-11.26%2012.83-7.92%2023a23.07%2023.07%200%200%200%207.56%2011.08%2025.38%2025.38%200%200%200%201%204.5c1.94%205.9%205.77%2010.46%2010.15%2012.75a23.23%2023.23%200%200%200-.83%203.9%2025.29%2025.29%200%200%200-7.54%2014.91%2025.27%2025.27%200%200%200-7.54%2014.92%2024.63%2024.63%200%200%200-5%206.81c-4.91%209.7-2.88%2020.61%204.53%2024.35s17.4-1.07%2022.31-10.78a24.62%2024.62%200%200%200%202.5-8.09%2025.29%2025.29%200%200%200%207.54-14.91%2025.27%2025.27%200%200%200%207.54-14.92%2025.21%2025.21%200%200%200%207.45-14.91%2025.21%2025.21%200%200%200%207.56-14.94%2024.11%2024.11%200%200%200%203.39-4%2023.46%2023.46%200%200%200%2012.27-.77%2024.76%2024.76%200%200%200%204.23-1.83%2023.2%2023.2%200%200%200%2013.42-.48c10.13-3.31%2016.36-12.27%2013.83-19.99Z'/%3e%3cg%20opacity='.1'%3e%3cpath%20d='M827.12%20442.44a21.5%2021.5%200%200%201-3.44%202.75%2023%2023%200%200%201-1.11%208.43%2026.18%2026.18%200%200%200%202.1-3.43%2024.64%2024.64%200%200%200%202.45-7.75ZM837.98%20420.97a21.5%2021.5%200%200%201-3.44%202.75%2023%2023%200%200%201-1.11%208.43%2025.65%2025.65%200%200%200%202.1-3.44%2024.85%2024.85%200%200%200%202.45-7.74ZM813.35%20412.98a21.91%2021.91%200%200%201%20.17-4.41%2024.93%2024.93%200%200%200-4.78%206.57%2025.63%2025.63%200%200%200-1.52%203.73%2022.75%2022.75%200%200%201%206.13-5.89ZM744.42%20542.91a23.59%2023.59%200%200%201%202.95-3.38%2022.92%2022.92%200%200%201%20.87-4%2025.09%2025.09%200%200%200-2.29%203.71%2025.59%2025.59%200%200%200-1.53%203.67ZM751.96%20528.01a23.59%2023.59%200%200%201%202.95-3.38%2023%2023%200%200%201%20.83-3.9%2025.68%2025.68%200%200%200-2.2%203.59%2026.76%2026.76%200%200%200-1.58%203.69ZM816.25%20463.91a20.82%2020.82%200%200%201-3.43%202.74%2022.45%2022.45%200%200%201-.63%206.79%2018.75%2018.75%200%200%201%202%20.46%2024.76%2024.76%200%200%201%204.23-1.83c10.18-3.34%2020.47.21%2023%207.92a11.68%2011.68%200%200%201%20.32%206c3.35-3.94%204.74-8.74%203.3-13.14-2.54-7.71-12.84-11.26-23-7.92a24.76%2024.76%200%200%200-4.23%201.83c-.65-.18-1.32-.34-2-.46.19-.8.33-1.59.44-2.39ZM740.7%20550.4a25.09%2025.09%200%200%200-2.29%203.71%2026.56%2026.56%200%200%200-1.54%203.74%2024.48%2024.48%200%200%201%203-3.4%2022.92%2022.92%200%200%201%20.83-4.05ZM802.44%20434.45a22%2022%200%200%201%20.17-4.41%2024.93%2024.93%200%200%200-4.78%206.57%2025.63%2025.63%200%200%200-1.52%203.73%2022.75%2022.75%200%200%201%206.13-5.89ZM786.75%20522.01a24.29%2024.29%200%200%201-1%204.38%2026.67%2026.67%200%200%200%202.09-3.44%2025.49%2025.49%200%200%200%201.63-4%2024.23%2024.23%200%200%201-2.72%203.06ZM771.67%20551.83a24.15%2024.15%200%200%201-1%204.38%2025.65%2025.65%200%200%200%202.1-3.44%2026.47%2026.47%200%200%200%201.63-4%2023.57%2023.57%200%200%201-2.73%203.06ZM779.21%20536.91a24.11%2024.11%200%200%201-1%204.38%2026.67%2026.67%200%200%200%202.14-3.38%2025.49%2025.49%200%200%200%201.63-4%2024.23%2024.23%200%200%201-2.77%203ZM794.29%20507.1a24%2024%200%200%201-1%204.37%2025.89%2025.89%200%200%200%202.09-3.43%2025.48%2025.48%200%200%200%201.64-4.07%2023.22%2023.22%200%200%201-2.73%203.13ZM744.92%20469.39c7.72-2.53%2016.68%203.66%2020%2013.83a25.68%2025.68%200%200%201%201%204.51%2021.18%2021.18%200%200%201%204.44%204.73%2025.53%2025.53%200%200%201%202.08-5.75c.35-.68.73-1.33%201.12-2a21.07%2021.07%200%200%200-4-4.18%2025.38%2025.38%200%200%200-1-4.5c-3.34-10.17-12.3-16.37-20-13.83-4.4%201.44-7.44%205.41-8.62%2010.43a11.69%2011.69%200%200%201%204.98-3.24ZM780.72%20477.39a21.85%2021.85%200%200%201%20.18-4.4%2024.73%2024.73%200%200%200-4.79%206.57%2025.07%2025.07%200%200%200-1.52%203.72%2023%2023%200%200%201%206.13-5.89ZM791.58%20455.91a21.85%2021.85%200%200%201%20.18-4.4%2024.52%2024.52%200%200%200-4.79%206.56%2025.63%2025.63%200%200%200-1.52%203.73%2022.75%2022.75%200%200%201%206.13-5.89ZM764.13%20566.74a24.25%2024.25%200%200%201-1%204.39%2025.73%2025.73%200%200%200%203.73-7.49%2023.57%2023.57%200%200%201-2.73%203.1Z'/%3e%3c/g%3e%3cpath%20fill='%233f3d56'%20d='M859.87%20373.62a23.68%2023.68%200%200%200%208.23-9.32c4.91-9.7%202.88-20.61-4.53-24.36s-17.4%201.08-22.31%2010.79a23.68%2023.68%200%200%200-2.62%2012.18%2024.63%2024.63%200%200%200-10.86%2021.47%2023.61%2023.61%200%200%200-8.23%209.32%2024.69%2024.69%200%200%200-1.51%203.69%2020.85%2020.85%200%200%201%2010.77-8%2012.24%2012.24%200%200%200%2015.54%207.84%2020.85%2020.85%200%200%201%200%2013.41%2025.48%2025.48%200%200%200%202.08-3.4%2023.68%2023.68%200%200%200%202.62-12.15%2024.57%2024.57%200%200%200%2010.86-21.47Z'/%3e%3cpath%20fill='%236c63ff'%20d='M979.23%20235.98a72%2072%200%200%200%208.72-4.83l-32.33-23.62%2038%2019.57a72.13%2072.13%200%200%200%2027-50.31l-64.58.66%2064.72-10.82a72%2072%200%201%200-142.58%2018.28%2072.09%2072.09%200%200%200-13.26%208l33.75%2046.93-40.52-41.08a72.08%2072.08%200%200%200-20.17%2065.61%2072%2072%200%201%200%20101.05%2051.1%2072%2072%200%200%200%2040.2-79.49Z'/%3e%3cpath%20d='M844.35%20217.66a71.77%2071.77%200%200%200-6.35%2046.71%2072%2072%200%201%200%20101.05%2051.1c14.13-6.56-91.08-105.02-94.7-97.81Z'%20opacity='.1'/%3e%3ccircle%20cx='925.49'%20cy='102.72'%20r='10.69'%20fill='%236c63ff'/%3e%3ccircle%20cx='987.93'%20cy='109.58'%20r='10.69'%20fill='%236c63ff'/%3e%3ccircle%20cx='1012.01'%20cy='205.64'%20r='10.69'%20fill='%236c63ff'/%3e%3ccircle%20cx='979.51'%20cy='253.61'%20r='10.69'%20fill='%236c63ff'/%3e%3ccircle%20cx='935.11'%20cy='353.24'%20r='10.69'%20fill='%236c63ff'/%3e%3ccircle%20cx='935.11'%20cy='353.24'%20r='10.69'%20opacity='.1'/%3e%3ccircle%20cx='836.39'%20cy='240.4'%20r='10.69'%20fill='%236c63ff'/%3e%3ccircle%20cx='836.39'%20cy='240.4'%20r='10.69'%20opacity='.1'/%3e%3cpath%20d='M824.99%20416.23c-7.11-3.59-9.26-13.76-5.11-23.14-.22.38-.43.77-.63%201.18-4.91%209.7-2.88%2020.6%204.53%2024.35s17.4-1.08%2022.3-10.78c.21-.4.39-.81.57-1.21-5.09%208.91-14.56%2013.2-21.66%209.6ZM814.43%20437.11c-7.1-3.59-9.26-13.76-5.1-23.15-.22.39-.44.78-.64%201.18-4.91%209.7-2.88%2020.61%204.53%2024.35s17.4-1.07%2022.31-10.78c.2-.4.39-.8.57-1.21-5.1%208.91-14.56%2013.2-21.67%209.61ZM803.87%20457.98c-7.1-3.59-9.26-13.76-5.1-23.14-.22.38-.44.77-.64%201.18-4.91%209.7-2.87%2020.6%204.54%2024.35s17.39-1.08%2022.3-10.78c.2-.4.39-.81.57-1.21-5.09%208.91-14.56%2013.2-21.67%209.6ZM793.35%20478.91c-7.11-3.59-9.26-13.76-5.11-23.14-.22.38-.43.77-.64%201.17-4.9%209.7-2.87%2020.61%204.54%2024.36s17.4-1.08%2022.3-10.79c.21-.4.39-.8.57-1.21-5.12%208.86-14.59%2013.15-21.66%209.61ZM782.76%20499.73c-7.11-3.59-9.26-13.76-5.11-23.14-.22.38-.43.77-.63%201.18-4.91%209.7-2.88%2020.6%204.53%2024.35s17.4-1.08%2022.31-10.78c.2-.4.39-.81.57-1.21-5.08%208.91-14.57%2013.2-21.67%209.6ZM772.2%20520.61c-7.1-3.59-9.26-13.76-5.1-23.14-.22.38-.44.77-.64%201.17-4.91%209.7-2.88%2020.61%204.54%2024.36s17.35-1.09%2022.35-10.79c.2-.4.39-.8.57-1.21-5.15%208.91-14.57%2013.2-21.72%209.61ZM761.64%20541.48c-7.1-3.59-9.26-13.76-5.1-23.14-.22.39-.43.77-.64%201.18-4.9%209.7-2.87%2020.6%204.54%2024.35s17.4-1.08%2022.3-10.78c.21-.4.39-.81.57-1.21-5.09%208.91-14.56%2013.2-21.67%209.6ZM751.09%20562.36c-7.11-3.59-9.26-13.76-5.11-23.14q-.33.57-.63%201.17c-4.91%209.7-2.88%2020.61%204.53%2024.36s17.4-1.08%2022.31-10.79c.2-.4.38-.8.56-1.21-5.09%208.91-14.56%2013.16-21.66%209.61Z'%20opacity='.1'/%3e%3cpath%20d='M744.15%20576.08c-7.1-3.6-9.26-13.76-5.1-23.15-.22.39-.44.78-.64%201.18-4.91%209.7-2.88%2020.61%204.53%2024.35s17.4-1.07%2022.31-10.78c.2-.4.39-.8.57-1.21-5.1%208.91-14.57%2013.2-21.67%209.61Z'%20opacity='.1'/%3e%3cpath%20fill='%236c63ff'%20d='M934.94%20483.17a37.4%2037.4%200%200%200%202-9.79%205.34%205.34%200%201%200-.81-10.62%2037.31%2037.31%200%200%200-19.64-25.31%205.344%205.344%200%201%200-9.54-4.82%205%205%200%200%200-.48%201.43%2037.49%2037.49%200%200%200-32.87%209.85%2037.64%2037.64%200%200%200-9.82-.29l-4.33%2019.71-.26-19a37.42%2037.42%200%201%200%2020%2072%205.28%205.28%200%200%200%202.25%202.16%205.34%205.34%200%200%200%207.32-6.88%2037.35%2037.35%200%200%200%204.8-3.92%2037.45%2037.45%200%200%200%2039.31-19.83l-20.15-3.39Z'/%3e%3cpath%20d='M903.81%20492.74c-7.44-9.82-12-21.45-17.25-32.61a136.38%20136.38%200%200%200-7.07-13.36l-3.94-4.59c-.66.56-1.32%201.14-2%201.75a37.64%2037.64%200%200%200-9.82-.29l-4.33%2019.71-.26-19a37.42%2037.42%200%201%200%2020%2072%205.28%205.28%200%200%200%202.25%202.16%205.34%205.34%200%200%200%207.32-6.88%2037.35%2037.35%200%200%200%204.8-3.92%2037.49%2037.49%200%200%200%2022.44-3.32%2052.71%2052.71%200%200%201-12.14-11.65Z'%20opacity='.1'/%3e%3cpath%20fill='%236c63ff'%20d='M772.06%20450.54a5.34%205.34%200%200%200-4.78-7.75%2037.37%2037.37%200%200%200-11.7-20.83%2037.52%2037.52%200%200%200%201.1-11.7l-19.65-3.35%2019.08-1.2a38%2038%200%200%200-1.41-5.28%205.46%205.46%200%200%200%201.76-2%205.35%205.35%200%200%200-6.59-7.44%2037.42%2037.42%200%200%200-66.79%2030.92%205.25%205.25%200%200%200-2.66%202.5%205.34%205.34%200%200%200%206.75%207.37%2037.53%2037.53%200%200%200%207.09%208.65%2037.4%2037.4%200%200%200%201.74%2023.76l26.35-6.84-23.5%2012.36a37.42%2037.42%200%200%200%2068.91-16.26%205.33%205.33%200%200%200%204.3-2.91Z'/%3e%3cpath%20d='M772.06%20450.54a5.34%205.34%200%200%200-4.78-7.75%2037.37%2037.37%200%200%200-11.7-20.83c.16-.63.3-1.25.42-1.88a13.18%2013.18%200%200%200-1.93%201.71c-3.55%203.89-5.37%209.12-8.88%2013.05-4.14%204.64-10.34%207.06-16.53%207.71s-12.42-.3-18.53-1.49c-5.06-1-10.19-2.16-15.32-1.67-.5%200-1%20.11-1.46.19.3.29.6.58.91.86A37.4%2037.4%200%200%200%20696%20464.2l26.35-6.85-23.5%2012.36a37.42%2037.42%200%200%200%2068.91-16.26%205.33%205.33%200%200%200%204.3-2.91Z'%20opacity='.1'/%3e%3c/g%3e%3cg%20opacity='.1'%3e%3cpath%20fill='%233f3d56'%20d='M89.49%20511.24c1.28-3.89%206.47-5.68%2011.59-4a12.78%2012.78%200%200%201%202.13.92c.33-.09.67-.17%201-.23a11.26%2011.26%200%200%201-.32-3.42%2012.46%2012.46%200%200%201-5.47-10.82%2011.92%2011.92%200%200%201-4.14-4.69%2012%2012%200%200%201-1.33-6.12%2012%2012%200%200%201-4.14-4.7c-2.46-4.88-1.46-10.37%202.29-12.27s8.77.55%2011.24%205.43a12%2012%200%200%201%201.32%206.13%2012.37%2012.37%200%200%201%205.47%2010.81%2012.4%2012.4%200%200%201%205.47%2010.82%2012.37%2012.37%200%200%201%205.47%2010.81%2012%2012%200%200%201%204.15%204.7%2012.66%2012.66%200%200%201%201%202.9%2010.66%2010.66%200%200%201%202.23-2.39%2012.58%2012.58%200%200%201%20.52-2.27c1.69-5.12%206.2-8.24%2010.09-7s5.67%206.47%204%2011.59a11.67%2011.67%200%200%201-3.81%205.59%2012.67%2012.67%200%200%201-.52%202.26%2011.1%2011.1%200%200%201-5.11%206.42%2012.84%2012.84%200%200%201%20.42%202%2012.57%2012.57%200%200%201%202.53%203.43%2012.32%2012.32%200%200%201%201.26%204.08%2012.55%2012.55%200%200%201%202.54%203.43%2012.39%2012.39%200%200%201%201.26%204.08%2012.45%2012.45%200%200%201%202.54%203.44c2.47%204.88%201.45%2010.38-2.28%2012.26s-8.77-.54-11.24-5.43a12.48%2012.48%200%200%201-1.26-4.08%2012.7%2012.7%200%200%201-3.8-7.51%2012.7%2012.7%200%200%201-3.8-7.51%2012.6%2012.6%200%200%201-2.54-3.43%2012.73%2012.73%200%200%201-1.26-4.08%2012.57%2012.57%200%200%201-2.53-3.43%2012.32%2012.32%200%200%201-1.26-4.08%2011.63%2011.63%200%200%201-1.71-2%2011.9%2011.9%200%200%201-6.18-.38%2013.29%2013.29%200%200%201-2.14-.93%2011.61%2011.61%200%200%201-6.75-.24c-5.07-1.69-8.2-6.2-6.93-10.09Z'/%3e%3cg%20opacity='.1'%3e%3cpath%20d='M98.52%20495.91a10.72%2010.72%200%200%200%201.74%201.39%2011.31%2011.31%200%200%200%20.56%204.24%2011.93%2011.93%200%200%201-1.06-1.73%2012.46%2012.46%200%200%201-1.24-3.9ZM93.05%20485.11a11.21%2011.21%200%200%200%201.74%201.38%2011.39%2011.39%200%200%200%20.56%204.25%2012.7%2012.7%200%200%201-2.3-5.63ZM105.48%20481.08a11.11%2011.11%200%200%200-.08-2.22%2012.66%2012.66%200%200%201%202.41%203.31%2013%2013%200%200%201%20.76%201.88%2011.42%2011.42%200%200%200-3.09-2.97ZM140.18%20546.54a11.65%2011.65%200%200%200-1.48-1.7%2012.4%2012.4%200%200%200-.44-2%2013.23%2013.23%200%200%201%201.15%201.86%2013%2013%200%200%201%20.77%201.84ZM136.35%20539.03a11.65%2011.65%200%200%200-1.48-1.7%2011.75%2011.75%200%200%200-.42-2%2012.67%2012.67%200%200%201%201.88%203.68ZM104%20506.75a10.11%2010.11%200%200%200%201.73%201.37%2010.9%2010.9%200%200%200%20.32%203.42%2010%2010%200%200%200-1%20.23%2013.26%2013.26%200%200%200-2.14-.92c-5.12-1.68-10.31.11-11.58%204a5.82%205.82%200%200%200-.17%203%206.93%206.93%200%200%201-1.66-6.61c1.28-3.89%206.47-5.68%2011.59-4a12.78%2012.78%200%200%201%202.13.92c.33-.09.67-.17%201-.23a10.32%2010.32%200%200%201-.22-1.18ZM142.06%20550.31a12.79%2012.79%200%200%201%201.15%201.87%2013%2013%200%200%201%20.77%201.88%2011.74%2011.74%200%200%200-1.48-1.71%2012.4%2012.4%200%200%200-.44-2.04ZM110.95%20491.91a11.08%2011.08%200%200%200-.08-2.22%2012.49%2012.49%200%200%201%202.41%203.31%2012.87%2012.87%200%200%201%20.76%201.87%2011.38%2011.38%200%200%200-3.09-2.96ZM118.86%20536.01a11.94%2011.94%200%200%200%20.49%202.2%2012.63%2012.63%200%200%201-1.88-3.77%2011.72%2011.72%200%200%200%201.39%201.57ZM126.45%20551.03a12.66%2012.66%200%200%200%20.5%202.2%2011.93%2011.93%200%200%201-1.06-1.73%2012.88%2012.88%200%200%201-.82-2%2013%2013%200%200%200%201.38%201.53ZM122.66%20543.52a11.94%2011.94%200%200%200%20.49%202.2%2012.88%2012.88%200%200%201-1.06-1.73%2012.6%2012.6%200%200%201-.82-2%2011.72%2011.72%200%200%200%201.39%201.53ZM115.06%20528.49a11.86%2011.86%200%200%200%20.49%202.21%2012.44%2012.44%200%200%201-1-1.73%2012.23%2012.23%200%200%201-.83-2%2011.13%2011.13%200%200%200%201.34%201.52ZM139.93%20509.5c-3.89-1.28-8.4%201.84-10.08%207a12.58%2012.58%200%200%200-.52%202.27%2010.63%2010.63%200%200%200-2.24%202.38%2012.83%2012.83%200%200%200-1.05-2.9c-.17-.34-.36-.67-.56-1a10.63%2010.63%200%200%201%202-2.1%2012.58%2012.58%200%200%201%20.52-2.27c1.69-5.12%206.2-8.24%2010.09-7a6.93%206.93%200%200%201%204.34%205.26%205.93%205.93%200%200%200-2.5-1.64ZM121.89%20513.53a11.11%2011.11%200%200%200-.08-2.22%2012.49%2012.49%200%200%201%202.41%203.31%2013%2013%200%200%201%20.76%201.88%2011.28%2011.28%200%200%200-3.09-2.97ZM116.42%20502.71a11.13%2011.13%200%200%200-.08-2.22%2012.83%2012.83%200%200%201%202.41%203.31%2013%2013%200%200%201%20.76%201.88%2011.42%2011.42%200%200%200-3.09-2.97ZM130.25%20558.54a11.9%2011.9%200%200%200%20.5%202.21%2012.61%2012.61%200%200%201-1.06-1.74%2012.88%2012.88%200%200%201-.82-2%2013%2013%200%200%200%201.38%201.53Z'/%3e%3c/g%3e%3cpath%20fill='%233f3d56'%20d='M82.02%20461.25a11.92%2011.92%200%200%201-4.14-4.69c-2.47-4.89-1.45-10.38%202.28-12.27s8.77.54%2011.24%205.43a11.93%2011.93%200%200%201%201.32%206.12%2012.4%2012.4%200%200%201%205.47%2010.82%2012%2012%200%200%201%204.15%204.69%2013.23%2013.23%200%200%201%20.76%201.86%2010.57%2010.57%200%200%200-5.43-4%206.16%206.16%200%200%201-7.83%204%2010.52%2010.52%200%200%200%200%206.75%2013.19%2013.19%200%200%201-1-1.71%2012%2012%200%200%201-1.33-6.12%2012.43%2012.43%200%200%201-5.47-10.82Z'/%3e%3cpath%20fill='%236c63ff'%20d='M21.9%20391.91a36.81%2036.81%200%200%201-4.39-2.43l16.28-11.9-19.14%209.85a36.34%2036.34%200%200%201-13.59-25.34l32.54.34-32.61-5.46a36.29%2036.29%200%201%201%2071.81%209.2%2036.73%2036.73%200%200%201%206.68%204l-17%2023.64%2020.41-20.68a36.32%2036.32%200%200%201%2010.16%2033.05%2036.29%2036.29%200%201%201-50.9%2025.74%2036.28%2036.28%200%200%201-20.25-40Z'/%3e%3cpath%20d='M89.85%20382.69a36.12%2036.12%200%200%201%203.2%2023.53%2036.29%2036.29%200%201%201-50.9%2025.74c-7.13-3.31%2045.87-52.9%2047.7-49.27Z'%20opacity='.1'/%3e%3ccircle%20cx='48.97'%20cy='324.78'%20r='5.39'%20fill='%236c63ff'/%3e%3ccircle%20cx='17.51'%20cy='328.24'%20r='5.39'%20fill='%236c63ff'/%3e%3ccircle%20cx='5.39'%20cy='376.63'%20r='5.39'%20fill='%236c63ff'/%3e%3ccircle%20cx='21.76'%20cy='400.8'%20r='5.39'%20fill='%236c63ff'/%3e%3ccircle%20cx='44.12'%20cy='450.99'%20r='5.39'%20fill='%236c63ff'/%3e%3ccircle%20cx='44.12'%20cy='450.99'%20r='5.39'%20opacity='.1'/%3e%3ccircle%20cx='93.85'%20cy='394.14'%20r='5.39'%20fill='%236c63ff'/%3e%3ccircle%20cx='93.85'%20cy='394.14'%20r='5.39'%20opacity='.1'/%3e%3cpath%20d='M99.6%20482.72c3.58-1.81%204.66-6.93%202.57-11.66.11.2.22.39.32.59%202.47%204.89%201.45%2010.38-2.29%2012.27s-8.76-.54-11.23-5.43c-.1-.2-.2-.4-.29-.61%202.57%204.49%207.34%206.65%2010.92%204.84ZM104.91%20493.24c3.58-1.81%204.67-6.94%202.58-11.66.11.19.22.39.32.59%202.47%204.89%201.45%2010.38-2.29%2012.27s-8.76-.54-11.23-5.43c-.11-.2-.2-.41-.29-.61%202.57%204.51%207.35%206.65%2010.91%204.84ZM110.23%20503.75c3.58-1.81%204.67-6.93%202.57-11.66.12.2.22.39.33.6%202.47%204.88%201.44%2010.38-2.29%2012.26s-8.76-.54-11.23-5.43c-.11-.2-.2-.4-.29-.61%202.56%204.49%207.33%206.65%2010.91%204.84ZM115.55%20514.27c3.58-1.81%204.67-6.93%202.57-11.66.11.19.22.39.32.59%202.48%204.89%201.45%2010.38-2.28%2012.27s-8.77-.54-11.24-5.43c-.1-.2-.19-.41-.28-.61%202.56%204.48%207.33%206.65%2010.91%204.84ZM120.87%20524.78c3.58-1.81%204.66-6.93%202.57-11.65.11.19.22.39.32.59%202.47%204.89%201.45%2010.38-2.28%2012.27s-8.77-.55-11.24-5.43c-.1-.21-.19-.41-.29-.61%202.57%204.48%207.34%206.64%2010.92%204.83ZM126.19%20535.3c3.58-1.81%204.66-6.93%202.57-11.66.11.2.22.39.32.59%202.47%204.89%201.45%2010.38-2.28%2012.27s-8.77-.54-11.24-5.43c-.1-.2-.2-.4-.29-.61%202.57%204.45%207.34%206.65%2010.92%204.84ZM131.51%20545.82c3.57-1.81%204.66-6.94%202.57-11.66.11.19.22.39.32.59%202.47%204.89%201.45%2010.38-2.29%2012.27s-8.76-.55-11.23-5.43c-.1-.21-.2-.41-.29-.61%202.57%204.48%207.34%206.65%2010.92%204.84ZM136.82%20556.33c3.58-1.81%204.67-6.93%202.57-11.66.12.2.22.39.33.6%202.47%204.88%201.44%2010.38-2.29%2012.26s-8.76-.54-11.23-5.43c-.11-.2-.2-.4-.29-.61%202.57%204.49%207.33%206.65%2010.91%204.84Z'%20opacity='.1'/%3e%3cpath%20d='M140.35%20563.24c3.58-1.81%204.66-6.93%202.57-11.66.11.2.22.39.32.6%202.47%204.88%201.45%2010.38-2.28%2012.26s-8.77-.54-11.24-5.43c-.1-.2-.2-.4-.29-.61%202.54%204.51%207.31%206.65%2010.92%204.84Z'%20opacity='.1'/%3e%3cpath%20fill='%236c63ff'%20d='M44.21%20516.44a18.57%2018.57%200%200%201-1-4.93%202.69%202.69%200%201%201%20.41-5.35%2018.82%2018.82%200%200%201%209.89-12.75%202.694%202.694%200%201%201%204.81-2.43%202.44%202.44%200%200%201%20.24.72%2018.92%2018.92%200%200%201%2016.56%205%2018.68%2018.68%200%200%201%205-.14l2.18%209.92.05-9.57a18.85%2018.85%200%201%201-10.08%2036.29%202.76%202.76%200%200%201-1.13%201.09%202.7%202.7%200%200%201-3.7-3.47%2018.84%2018.84%200%200%201-2.41-2%2018.87%2018.87%200%200%201-19.8-10l10.15-1.71Z'/%3e%3cpath%20d='M59.89%20521.26c3.75-5%206.05-10.8%208.69-16.42a66.7%2066.7%200%200%201%203.56-6.74l2-2.31c.34.29.67.58%201%20.88a18.68%2018.68%200%200%201%205-.14l2.18%209.92.03-9.54a18.85%2018.85%200%201%201-10.08%2036.29%202.76%202.76%200%200%201-1.13%201.09%202.7%202.7%200%200%201-3.7-3.47%2018.84%2018.84%200%200%201-2.41-2%2019%2019%200%200%201-11.31-1.67%2026.59%2026.59%200%200%200%206.17-5.89Z'%20opacity='.1'/%3e%3cpath%20fill='%236c63ff'%20d='M126.26%20500a2.68%202.68%200%200%201%201.19-3.61%202.64%202.64%200%200%201%201.22-.29%2018.85%2018.85%200%200%201%205.89-10.5%2018.71%2018.71%200%200%201-.55-5.89l9.89-1.66-9.61-.61a18.65%2018.65%200%200%201%20.72-2.66%202.64%202.64%200%200%201-.89-1%202.7%202.7%200%200%201%203.32-3.75%2018.63%2018.63%200%200%201%206.87-5.93%2018.84%2018.84%200%200%201%2026.77%2021.5%202.69%202.69%200%200%201%20.16%204.87%202.7%202.7%200%200%201-2.22.1%2018.74%2018.74%200%200%201-3.57%204.34%2018.9%2018.9%200%200%201-.87%2012l-13.23-3.48%2011.83%206.23a18.86%2018.86%200%200%201-32.83-1.54%2019.11%2019.11%200%200%201-1.94-6.65%202.67%202.67%200%200%201-2.15-1.47Z'/%3e%3cpath%20d='M126.26%20500a2.68%202.68%200%200%201%201.19-3.61%202.64%202.64%200%200%201%201.22-.29%2018.85%2018.85%200%200%201%205.89-10.5c-.08-.31-.15-.63-.21-.94a7.27%207.27%200%200%201%201%20.86c1.79%202%202.71%204.59%204.47%206.57a12.91%2012.91%200%200%200%208.33%203.89%2031.54%2031.54%200%200%200%209.33-.75%2027.35%2027.35%200%200%201%207.72-.85l.74.1-.46.43a18.9%2018.9%200%200%201-.87%2012l-13.26-3.48%2011.83%206.23a18.86%2018.86%200%200%201-32.83-1.54%2019.11%2019.11%200%200%201-1.94-6.65%202.67%202.67%200%200%201-2.15-1.47Z'%20opacity='.1'/%3e%3c/g%3e%3cpath%20fill='%236c63ff'%20d='M346.35%2051.91a20.23%2020.23%200%200%200-11.74%201.28%2017.32%2017.32%200%200%201-14.1%200%2019.76%2019.76%200%200%200-16.58.33%2010.28%2010.28%200%200%201-4.77%201.19c-6.72%200-12.31-6.77-13.47-15.7a13.07%2013.07%200%200%200%203.36-3.62c3.94-6.35%2010-10.43%2016.89-10.43s12.89%204%2016.83%2010.31a13%2013%200%200%200%2011.16%206.14h.18c5.3-.03%209.93%204.26%2012.24%2010.5Z'%20opacity='.1'/%3e%3cpath%20fill='%236c63ff'%20d='m366.77%2023.91-10.86%206.89%206.59-12a10.74%2010.74%200%200%200-6.57-2.34h-.17a12.89%2012.89%200%200%201-2.25-.17l-3.69%202.34%201.58-2.87a13.19%2013.19%200%200%201-6.44-4.85l-6.61%204.13%204.16-7.57C338.66%202.84%20333.46%200%20327.75%200c-6.85%200-13%204.08-16.9%2010.43a12.62%2012.62%200%200%201-11.17%206h-.33c-7.56%200-13.7%208.57-13.7%2019.16s6.14%2019.15%2013.7%2019.15a10.28%2010.28%200%200%200%204.77-1.19%2019.72%2019.72%200%200%201%2016.58-.32%2017.37%2017.37%200%200%200%2014.1%200%2019.75%2019.75%200%200%201%2016.43.32%2010.35%2010.35%200%200%200%204.72%201.16c7.57%200%2013.7-8.57%2013.7-19.15a24.36%2024.36%200%200%200-2.88-11.65ZM120.35%20190.45a29%2029%200%200%200-16.77%201.82%2024.71%2024.71%200%200%201-20.14-.05%2028.22%2028.22%200%200%200-23.68.47%2014.75%2014.75%200%200%201-6.82%201.7c-9.6%200-17.59-9.67-19.25-22.43a18.41%2018.41%200%200%200%204.8-5.17c5.63-9.07%2014.35-14.9%2024.14-14.9s18.4%205.76%2024%2014.73a18.52%2018.52%200%200%200%2016%208.77h.25c7.58-.01%2014.2%206.12%2017.47%2015.06Z'%20opacity='.1'/%3e%3cpath%20fill='%236c63ff'%20d='m149.55%20150.4-15.52%209.84%209.42-17.13a15.34%2015.34%200%200%200-9.39-3.35h-.25a18.16%2018.16%200%200%201-3.22-.24l-5.24%203.39%202.26-4.1a18.7%2018.7%200%200%201-9.2-7l-9.42%206%205.93-10.9c-5.51-6.61-12.93-10.66-21.09-10.66-9.79%200-18.51%205.82-24.14%2014.89a18.05%2018.05%200%200%201-16%208.61h-.53c-10.81%200-19.57%2012.25-19.57%2027.37s8.76%2027.37%2019.57%2027.37a14.61%2014.61%200%200%200%206.82-1.71%2028.22%2028.22%200%200%201%2023.68-.46%2024.71%2024.71%200%200%200%2020.14.05%2028.25%2028.25%200%200%201%2023.48.45%2014.65%2014.65%200%200%200%206.74%201.67c10.81%200%2019.57-12.26%2019.57-27.37a34.76%2034.76%200%200%200-4.04-16.72ZM747.97%2090.91a20.24%2020.24%200%200%201%2011.74%201.28%2017.29%2017.29%200%200%200%2014.09%200%2019.76%2019.76%200%200%201%2016.58.33%2010.31%2010.31%200%200%200%204.77%201.19c6.72%200%2012.32-6.77%2013.48-15.7a12.93%2012.93%200%200%201-3.36-3.62c-3.92-6.37-10.05-10.48-16.92-10.48s-12.88%204-16.82%2010.31a13%2013%200%200%201-11.18%206.17h-.17c-5.32-.01-9.96%204.28-12.21%2010.52Z'%20opacity='.1'/%3e%3cpath%20fill='%236c63ff'%20d='m727.49%2062.91%2010.86%206.87-6.6-12a10.76%2010.76%200%200%201%206.57-2.34h.18a13%2013%200%200%200%202.25-.17l3.68%202.34-1.58-2.87a13.21%2013.21%200%200%200%206.5-4.83l6.59%204.18-4.17-7.57c3.86-4.63%209-7.47%2014.77-7.47%206.85%200%2013%204.08%2016.9%2010.43a12.61%2012.61%200%200%200%2011.17%206h.36c7.57%200%2013.7%208.57%2013.7%2019.16s-6.13%2019.15-13.7%2019.15a10.34%2010.34%200%200%201-4.77-1.19%2019.72%2019.72%200%200%200-16.58-.32%2017.35%2017.35%200%200%201-14.09%200%2019.77%2019.77%200%200%200-16.44.32%2010.32%2010.32%200%200%201-4.72%201.16c-7.56%200-13.7-8.57-13.7-19.15a24.36%2024.36%200%200%201%202.82-11.7Z'%20opacity='.1'/%3e%3cellipse%20cx='615.63'%20cy='756.88'%20fill='%236c63ff'%20opacity='.1'%20rx='115'%20ry='20'/%3e%3cpath%20fill='%23d0d2d5'%20d='m555.44%20661.88-178.19-2.29.53-4.57%208.61-75.39h156.49l11.51%2075.39.88%205.72.17%201.14z'/%3e%3cpath%20d='M555.27%20660.74h-88.92l-89.1-1.15.53-4.57h176.61l.88%205.72z'%20opacity='.1'/%3e%3cpath%20fill='%23d0d2d5'%20d='M347.55%20656.17H584v5.71H347.55z'/%3e%3cpath%20fill='%233f3d56'%20d='M809.59%20126.83a14.87%2014.87%200%200%200-14.8-14.92H134.47a14.87%2014.87%200%200%200-14.8%2014.94V527.1h689.92Z'/%3e%3cpath%20fill='%23d0d2d5'%20d='M119.67%20523.1v46.88a14.8%2014.8%200%200%200%2014.8%2014.8h660.32a14.8%2014.8%200%200%200%2014.8-14.8V523.1Z'/%3e%3cpath%20fill='%23fff'%20d='M148.23%20137.01h636.23v359.81H148.23z'/%3e%3cpath%20fill='%236c63ff'%20d='M468.06%20566.99a15.4%2015.4%200%200%200%2012.13-5.89%2016.06%2016.06%200%200%200%201.2-1.76l-8.47-1.43%209.15.06a15.42%2015.42%200%200%200%20.29-12.21l-12.27%206.36%2011.32-8.32a15.42%2015.42%200%201%200-25.47%2017.26%2015.4%2015.4%200%200%200%2012.12%205.93Z'/%3e%3cpath%20d='m483.48%20584.77%2071.09%2071.4-10.91-71.4h-60.18z'%20opacity='.1'/%3e%3cpath%20fill='%23444053'%20d='M147.73%20137.05h636.92v21.02H147.73z'%20opacity='.1'/%3e%3crect%20width='191.9'%20height='12.79'%20x='368.87'%20y='140.71'%20fill='%236c63ff'%20opacity='.3'%20rx='.58'/%3e%3cpath%20fill='%233f3d56'%20d='M555.07%20148.43h-.47l-.17-.15a3.89%203.89%200%200%200%20.9-2.49%203.78%203.78%200%201%200-3.77%203.81%203.9%203.9%200%200%200%202.49-.91l.17.15v.47l2.93%202.93.87-.88Zm-3.51%200a2.64%202.64%200%201%201%202.63-2.64%202.62%202.62%200%200%201-2.63%202.64Z'/%3e%3ccircle%20cx='159.18'%20cy='147.56'%20r='3.85'%20fill='%23fa5959'%20opacity='.8'/%3e%3ccircle%20cx='169.77'%20cy='147.56'%20r='3.85'%20fill='%23fed253'%20opacity='.8'/%3e%3ccircle%20cx='180.37'%20cy='147.56'%20r='3.85'%20fill='%238ccf4d'%20opacity='.8'/%3e%3cpath%20fill='%236c63ff'%20d='M500.05%20291.4c-8.73-11.6-21.38-18.92-35.46-18.92s-26.73%207.32-35.46%2018.92a38.39%2038.39%200%200%200%208.4%2012.65%2038.28%2038.28%200%200%200%2062.52-12.65Z'/%3e%3cpath%20fill='%236c63ff'%20d='M424.52%20298.19a9.17%209.17%200%200%201-1.76-1%207.06%207.06%200%200%201-1.94-2.51%207.18%207.18%200%201%200-11.72%201.74%208%208%200%200%200%201.7%201.37%204.94%204.94%200%200%201%201.91%202%2014.44%2014.44%200%200%200%203.32%204.36%2029%2029%200%200%200%204.55%203.2%2066.31%2066.31%200%200%200-3.74%2019.56%2027.05%2027.05%200%200%200-7.62%201.23%2012.29%2012.29%200%200%200-3.53%201.76%208.48%208.48%200%200%200-.87-.06%207.19%207.19%200%201%200%206.73%209.72%204.59%204.59%200%200%201%203.71-3%2016.75%2016.75%200%200%201%201.85-.12%2064.4%2064.4%200%200%200%208.55%2026.67c-4.24%203.29-6.85%206.88-7.95%2010.86a3%203%200%200%200-.57.41%206.81%206.81%200%200%200-.84.78%207.18%207.18%200%201%200%2012.05%202.35%204.71%204.71%200%200%201%201.17-5.08c.48-.45%201-.93%201.7-1.46%208.11%209.47%2017.76%2015.54%2029.81%2016.26v-64.25c-15.93-.87-29.81-11.24-36.51-24.79Zm99.83%2031.72a7.93%207.93%200%200%200-.87.06%2013.56%2013.56%200%200%200-3.53-1.76%2026.86%2026.86%200%200%200-7.62-1.23%2067.76%2067.76%200%200%200-3.74-19.55%2029%2029%200%200%200%204.55-3.2%2015.58%2015.58%200%200%200%203.44-4.57%204.22%204.22%200%200%201%201.77-1.75%207.18%207.18%200%201%200-10-3.17%206.82%206.82%200%200%201-1.94%202.51%2018.85%2018.85%200%200%201-1.76%201.29c-6.7%2013.54-20.57%2023.62-36.48%2024.49v64.31c12-.72%2021.71-6.82%2029.81-16.26.63.5%201.16.95%201.61%201.37a4.86%204.86%200%200%201%201.26%205.23%207.18%207.18%200%201%200%2012.08-2.33%206.81%206.81%200%200%200-.84-.78c-.33-.26-.57-.41-.57-.41-1.1-4-3.7-7.57-8-10.86a64.4%2064.4%200%200%200%208.55-26.67%2015.9%2015.9%200%200%201%201.77.12%204.8%204.8%200%200%201%203.85%203%207.18%207.18%200%200%200%2013.85-2.18%207.29%207.29%200%200%200-7.19-7.66Z'/%3e%3cpath%20fill='url(%23a)'%20d='M769.65%20802.31a9.56%209.56%200%200%200-2.17-2.41c-4.37-4.13-6.4-10.19-7.48-16.13s-1.39-12-3.12-17.81a58.74%2058.74%200%200%200-3.52-8.67c-1-2.14-2.26-6.33-4.09-7.83a2.7%202.7%200%200%200-1.26-.61%2014.85%2014.85%200%200%200-3.62-4.82c-2.86-2.59-6.35-4.65-8.26-8a18%2018%200%200%200-1.93-3.29c-1.29-1.42-3.33-2-4.52-3.5-1.55-1.94-1.2-4.72-1-7.19s0-5.43-2.14-6.73c-1.28-.79-2.93-.71-4.26-1.41-2-1-2.79-3.52-2.75-5.77s.74-4.44.92-6.69c.56-7.16-4.16-14.28-2.34-21.22.69-2.63%202.27-4.91%203.44-7.36a15.37%2015.37%200%200%200%201-2.54%2035.73%2035.73%200%200%200%209.74%202.35c-5.51-12.36-4.11-26.72-6.68-40l.33-.45a20.84%2020.84%200%200%200%204.22-11.86c0-4.94-2.31-9.56-3.35-14.4-.89-4.11-.85-8.41-2-12.45a37.65%2037.65%200%200%200-3.16-7.22q-1.87-3.47-3.93-6.83-1.92-6.36-3.85-12.72c-1.8-5.95-3.65-12-7.15-17.14-1.28-1.88-1.67-5.7-3.64-6.84a8.81%208.81%200%200%200-5.2-.91c-2.78-1.56-5.22-3.81-5.57-6.89a6.68%206.68%200%200%201%20.2-2h.34c4.4-.4%206.63-4.28%208.92-7.68%203.7-5.5%202.29-12.94%200-19.2a13%2013%200%200%200-3-5.29c-3.21-3-8.29-2.34-12.43-3.79-1.39-.48-2.69-1.21-4.11-1.55-2.75-.64-5.63.26-8.15%201.53s-4.87%202.91-7.51%203.91-5.9%201.79-6.55%204.5a5%205%200%200%200%20.22%202.73%2010.18%2010.18%200%200%200%203.09%204.46%2017.81%2017.81%200%200%200%2010.87%2024.82%2051.01%2051.01%200%200%201%202.12%203.73c1.16%202.24%202.14%204.88%201.74%207.28a22.45%2022.45%200%200%200-2%202.45c-2.87%204-4.5%208.69-6%2013.37a141.65%20141.65%200%200%200-4.83%2018.27c-2.44%205.19-5.42%2010.15-7.19%2015.6a35.21%2035.21%200%200%201-9.38-1.26l-8.44-1.91c-2.94-.67-6-1.39-8.3-3.33-1.22-1-2.17-2.33-3.41-3.32s-3.73-2.15-5.09-1.33a4%204%200%200%200-.69.53c-1.24-2.51-2.42-5-3.86-7.43-2.07-3.4-5.15-6.51-9.05-7.16a9.21%209.21%200%200%200-6.79%201.58c-2.28%201.62-3.71%205-2%207.28a13.29%2013.29%200%200%200%201.39%201.42%2029.2%2029.2%200%200%201%203.09%204.29%2021.91%2021.91%200%200%200%2013.49%208.76l-.35%201c-.71%202.08-2.22%204.59-1.84%206.75l37.54%2012.85a23.13%2023.13%200%200%200%207.56%201.67%2012.21%2012.21%200%200%200%203-.4v2c.1%2013.19-2%2026.29-2.39%2039.47-.07%202.41%200%205%201.52%206.88%201.7%202.06%204.72%202.47%207.35%202q.95-.16%201.86-.42a69.33%2069.33%200%200%201%201.92%2010.11l2.48%2017.86a27.14%2027.14%200%200%201%20.39%205.54c-.29%204.19-2.5%207.94-4.1%2011.81s-2.55%208.5-.45%2012.12c.66%201.12%201.57%202.07%202.16%203.23a13.14%2013.14%200%200%201%201%205.68q.23%208.08.44%2016.18a1.83%201.83%200%200%200-1.26.25c-2.08%201.62-1.85%209.33-2%2011.72-.16%204%200%208.08-.22%2012.12a72.22%2072.22%200%200%201-2.61%2016.09%2010.29%2010.29%200%200%201-2.29%204.61%209.74%209.74%200%200%201-4.07%202.11%2046.49%2046.49%200%200%201-15.41%202.1c-2.11-.07-4.31-.27-6.27.53s-3.54%203-2.83%205c.61%201.68%202.46%202.48%204.13%203.11a65.53%2065.53%200%200%201%2011%205.06%2029.74%2029.74%200%200%200%204.25%202.41%2021.91%2021.91%200%200%200%204.38%201.08l17.73%203.06c3.63.62%208%201%2010.31-2%201.25-1.62%201.43-3.82%201.37-5.88-.1-4-.9-8.07-.38-12.07a37.14%2037.14%200%200%201%201.86-6.93q2.65-7.87%205.32-15.73c1.78-5.26%203.58-10.57%204.27-16.09.25-2%20.23-4.28-1.3-5.53a3.54%203.54%200%200%200-1.32-.68c-.06-4.82-.69-9.65-.42-14.47.07-1.2.19-2.4.29-3.61a17.61%2017.61%200%200%201%202.47%202.92c1.71%202.68%202.34%206.22%204.95%208%202.22%201.52%205.51%201.44%207.07%203.64a10.26%2010.26%200%200%201%201.12%202.71%2019.32%2019.32%200%200%200%204%206.35%2032%2032%200%200%200%202.47%206.34q2.21%204.67%204.4%209.31a108.59%20108.59%200%200%200%205%209.77%2027.55%2027.55%200%200%201%203.35%206.46c1.41%204.94-.89%2010.36-4.53%2014s-8.44%205.73-13.17%207.68a3.71%203.71%200%200%200-1.34.8%202.59%202.59%200%200%200-.61%201.74c0%202.31%201.9%204.29%204.08%205a15.26%2015.26%200%200%200%206.83.25c12.78-1.55%2025.52-4.67%2036.82-10.88a13%2013%200%200%200%204.39-3.39%205.13%205.13%200%200%200%20.73-5.21Z'%20transform='translate(-88.65%20-57.09)'/%3e%3cpath%20fill='%232f2e41'%20d='M626.99%20520.97q3.2%204.91%206%2010.06a37%2037%200%200%201%203.17%207.17c1.16%204%201.13%208.27%202%2012.35%201%204.8%203.34%209.38%203.34%2014.3a20.56%2020.56%200%200%201-4.22%2011.76%2055.82%2055.82%200%200%201-8.82%209.1%20187.62%20187.62%200%200%201-12.48-61.21c-.1-2.9-.12-5.89.94-8.6.65-1.7%203.77-6.36%205.78-4.53.73.67.92%203.69%201.37%204.7a36.13%2036.13%200%200%200%202.92%204.9Z'/%3e%3cpath%20d='M626.99%20520.97q3.2%204.91%206%2010.06a37%2037%200%200%201%203.17%207.17c1.16%204%201.13%208.27%202%2012.35%201%204.8%203.34%209.38%203.34%2014.3a20.56%2020.56%200%200%201-4.22%2011.76%2055.82%2055.82%200%200%201-8.82%209.1%20187.62%20187.62%200%200%201-12.48-61.21c-.1-2.9-.12-5.89.94-8.6.65-1.7%203.77-6.36%205.78-4.53.73.67.92%203.69%201.37%204.7a36.13%2036.13%200%200%200%202.92%204.9Z'%20opacity='.1'/%3e%3cpath%20fill='%23d0d2d5'%20d='M363.35%20384.54c-7.91%207.9-8.86%2011.38-13.61%2012.95s-21.84%2010.42-16.47%2020.23l14.44%209.54.42.28%202.21%206.64-21.84%2038.88s-36-16.46-39.53%207.89-1.29%2031-2.24%2044%20.31%2016.76-2.86%2016.76-4.42-8.54-4.42-8.54-.2-.39-.55-1.12c-4.71-9.79-36.68-81.66%2014.53-131.06%200%200%2023.72-1.56%2029.43-28.76%203.94-18.8%2017.72-17.18%2026.88-13.35a30.38%2030.38%200%200%201%208.22%204.83%2040.48%2040.48%200%200%201%205.89%207c2.61%204.12%204.03%209.29-.5%2013.83Z'/%3e%3cpath%20d='m348.13%20427.54%202.21%206.64-21.84%2038.88s-36-16.46-39.53%207.89-1.29%2031-2.24%2044%20.31%2016.76-2.86%2016.76-4.42-8.54-4.42-8.54-.2-.39-.55-1.12c-1.59-12.16-9.65-83.29%2019.57-79.51%200%200%2023.71%2011.08%2027.5%206.66%203-3.5%2016.32-23.63%2021.74-31.89ZM363.85%20370.65l-14.44%2016.41s-16.77%2022.44-20.25%2021.49a16.23%2016.23%200%200%200-3.17-.37%206.16%206.16%200%200%201-4-10.38c5.72-6%2016.26-17.39%2016.95-19.92s7.4-13.62%2010.76-19.05a30.38%2030.38%200%200%201%208.22%204.83%2040.48%2040.48%200%200%201%205.93%206.99Z'%20opacity='.1'/%3e%3cpath%20fill='%23454b69'%20d='M772.41%20606.74c-2.45%204.9-15%2023.28-20.49%2031.31l-2.57%203.78s-1%206.64-17.39-1.59-401.48-170.72-401.48-170.72l-2.61-7.84%2019-28.45L768.94%20596.3s6.64%204.11%203.47%2010.44Z'/%3e%3cpath%20d='m751.92%20638.05-2.57%203.78s-1%206.64-17.39-1.59-401.48-170.72-401.48-170.72l-2.61-7.84Z'%20opacity='.1'/%3e%3cpath%20fill='%23fbbebe'%20d='M519.64%20531.91c-3.91-.64-8.25-.33-11.29%202.21a9.29%209.29%200%200%200-3.24%206.16c-.26%202.77%201.35%206.06%204.13%206.27a13.17%2013.17%200%200%200%202-.13%2029.89%2029.89%200%200%201%205.24.44%2021.39%2021.39%200%200%200%2018.23-7.36c2.39-3-.76-4.3-3.58-4.9-3.86-.82-7.63-2.07-11.49-2.69Z'/%3e%3cpath%20fill='%233f3d56'%20d='m586.52%20622.22%202.48%2017.62a26.84%2026.84%200%200%201%20.38%205.51c-.29%204.15-2.5%207.87-4.09%2011.71s-2.56%208.44-.45%2012c.65%201.11%201.56%202.06%202.15%203.21a12.92%2012.92%200%200%201%201%205.63l.68%2025a157.33%20157.33%200%200%200%2023.18-.13%201.29%201.29%200%200%200%20.84-.26%201.36%201.36%200%200%200%20.29-.91c.34-5.85-.68-11.71-.35-17.56.12-2.14.42-4.27.46-6.42.12-8.71-4.18-17.24-2.88-25.85a57%2057%200%200%201%201.6-6.43c4.11-15%203.24-30.76%202.33-46.25a1.09%201.09%200%200%200-.2-.7%201.06%201.06%200%200%200-.54-.29%2028.45%2028.45%200%200%200-25.78%204.9c-1.09.88-3.84%201.73-4.56%202.78-1%201.46.31%202.92.89%204.47a56.89%2056.89%200%200%201%202.57%2011.97Z'/%3e%3cpath%20d='m586.52%20622.22%202.48%2017.62a26.84%2026.84%200%200%201%20.38%205.51c-.29%204.15-2.5%207.87-4.09%2011.71s-2.56%208.44-.45%2012c.65%201.11%201.56%202.06%202.15%203.21a12.92%2012.92%200%200%201%201%205.63l.68%2025a157.33%20157.33%200%200%200%2023.18-.13%201.29%201.29%200%200%200%20.84-.26%201.36%201.36%200%200%200%20.29-.91c.34-5.85-.68-11.71-.35-17.56.12-2.14.42-4.27.46-6.42.12-8.71-4.18-17.24-2.88-25.85a57%2057%200%200%201%201.6-6.43c4.11-15%203.24-30.76%202.33-46.25a1.09%201.09%200%200%200-.2-.7%201.06%201.06%200%200%200-.54-.29%2028.45%2028.45%200%200%200-25.78%204.9c-1.09.88-3.84%201.73-4.56%202.78-1%201.46.31%202.92.89%204.47a56.89%2056.89%200%200%201%202.57%2011.97Z'%20opacity='.1'/%3e%3cpath%20fill='%233f3d56'%20d='M632.89%20616.91c-1.17%202.43-2.74%204.69-3.44%207.3-1.82%206.89%202.89%2014%202.33%2021.06-.18%202.23-.87%204.4-.92%206.63s.77%204.71%202.75%205.74c1.33.68%203%20.61%204.25%201.39%202.11%201.29%202.35%204.22%202.14%206.68s-.56%205.21%201%207.13c1.19%201.49%203.23%202.07%204.51%203.48a17.17%2017.17%200%200%201%201.93%203.26c1.91%203.34%205.4%205.38%208.26%208s5.28%206.46%204%2010.09c-.94%202.66-3.58%204.3-6.12%205.55a64.93%2064.93%200%200%201-14.57%205.15%203.52%203.52%200%200%201-1.67.09%203.57%203.57%200%200%201-1.46-1c-2.95-2.89-6-5.92-7.36-9.81a10.07%2010.07%200%200%200-1.12-2.68c-1.56-2.19-4.85-2.11-7.07-3.62-2.6-1.77-3.23-5.28-4.93-7.93s-4.19-4.23-6-6.56c-3.06-3.88-3.81-9.06-6-13.49-.93-1.88-2.12-3.64-2.86-5.6a30.58%2030.58%200%200%201-1.37-7.24c-1.41-11.68-5-23.44-2.74-35%20.5-2.54%201.27-5%201.59-7.62.55-4.53-.32-9.17.35-13.69a3.77%203.77%200%200%201%201.51-2.91%204%204%200%200%201%201.72-.35%20117.28%20117.28%200%200%201%2017.78.4c3%20.29%206.36.9%208.16%203.35%201.53%202.1%201.45%204.91%201.94%207.46.61%203.14%202.2%204.85%203.87%207.31s.77%204.89-.46%207.43Z'/%3e%3cpath%20fill='%232f2e41'%20d='M609.82%20698.17c1.58%200%203.33-.1%204.55.9%201.52%201.25%201.54%203.54%201.3%205.49-.7%205.48-2.49%2010.75-4.28%2016l-5.32%2015.61a36.65%2036.65%200%200%200-1.86%206.88c-.52%204%20.28%208%20.38%2012%200%202-.13%204.22-1.38%205.83-2.26%202.91-6.67%202.57-10.3%202l-17.71-3a21.07%2021.07%200%200%201-4.38-1.07%2030.61%2030.61%200%200%201-4.25-2.39%2065.42%2065.42%200%200%200-11-5c-1.66-.62-3.52-1.41-4.12-3.08-.71-2%20.87-4.2%202.83-5s4.15-.6%206.27-.54a47%2047%200%200%200%2015.4-2.08%209.74%209.74%200%200%200%204.06-2.1%2010%2010%200%200%200%202.34-4.71%2070.17%2070.17%200%200%200%202.68-16c.21-4%20.07-8%20.23-12%20.1-2.37-.13-10%201.95-11.63%201.59-1.22%208.13%202.15%2010.28%202.64a50%2050%200%200%200%2012.33%201.25ZM668.16%20709.29c1.73%205.73%202%2011.79%203.12%2017.68s3.1%2011.9%207.47%2016a9.87%209.87%200%200%201%202.17%202.4%205.06%205.06%200%200%201-.75%205.23%2013.13%2013.13%200%200%201-4.39%203.37c-11.29%206.16-24%209.27-36.81%2010.81a15.51%2015.51%200%200%201-6.82-.25c-2.18-.74-4.11-2.7-4.07-5a2.55%202.55%200%200%201%20.6-1.73%203.73%203.73%200%200%201%201.35-.79c4.72-1.94%209.51-4.05%2013.16-7.63s5.94-9%204.53-13.86a27.42%2027.42%200%200%200-3.37-6.41%20108.35%20108.35%200%200%201-5-9.69l-4.4-9.23c-1.29-2.7-2.59-5.48-2.81-8.46a40.6%2040.6%200%200%200%2016.22-2.6%2025.51%2025.51%200%200%200%206.67-4c1.7-1.42%203.25-4.07%205.54-2.22%201.84%201.48%203%205.65%204.08%207.76a57%2057%200%200%201%203.51%208.62Z'/%3e%3cpath%20fill='%23fbbebe'%20d='M603.68%20480.1c.44%203.84%204.16%206.37%207.71%207.89l-22.47%207.17c1.45-2.78.28-6.18-1.16-9a50.93%2050.93%200%200%200-4-6.41c-.22-.31-.47-.7-.31-1.06a1.12%201.12%200%200%201%20.63-.49c4.62-2.06%209.38-4.19%2014.43-4.94%201.46-.21%204.22-.79%205.31.69s-.35%204.38-.14%206.15Z'/%3e%3cpath%20d='M603.68%20480.1c.44%203.84%204.16%206.37%207.71%207.89l-22.47%207.17c1.45-2.78.28-6.18-1.16-9a50.93%2050.93%200%200%200-4-6.41c-.22-.31-.47-.7-.31-1.06a1.12%201.12%200%200%201%20.63-.49c4.62-2.06%209.38-4.19%2014.43-4.94%201.46-.21%204.22-.79%205.31.69s-.35%204.38-.14%206.15Z'%20opacity='.1'/%3e%3ccircle%20cx='590.62'%20cy='465.59'%20r='17.62'%20fill='%23fbbebe'/%3e%3cpath%20fill='%232f2e41'%20d='M575.35%20610.59c1.71%202.05%204.72%202.45%207.35%202%206.15-1%2011.18-5.53%2017.2-7.16%207.38-2%2015.19.57%2022.16%203.72s13.9%207%2021.52%207.54c-6.89-15.36-2.95-33.84-9.54-49.33-1.61-3.79-3.86-7.44-4.22-11.54-.45-5.09%202.09-10%202.48-15.06.36-4.51-1-9-2.3-13.3l-4.82-15.84c-1.8-5.91-3.65-11.92-7.14-17-1.29-1.87-1.68-5.66-3.64-6.79-4.28-2.47-10.77.64-15.41.81s-8.87%203.47-11.58%207.2c-2.87%203.94-4.5%208.63-6%2013.27a126.15%20126.15%200%200%200-5.33%2021.23c-.15%201.08-.28%202.16-.38%203.25-1%2010.27.46%2020.6.54%2030.92v.07c.1%2013.09-2%2026.1-2.39%2039.18-.04%202.39.02%205%201.5%206.83Z'/%3e%3cpath%20d='M576.27%20564.52c3.45-.87%206.57-3.1%209.25-5.54a38.67%2038.67%200%200%200%206.14-7%2049.86%2049.86%200%200%200%205.29-11.07%20129.36%20129.36%200%200%200%207-32.27c.26-3%20.34-6.22-1.45-8.6a7.24%207.24%200%200%200-8.75-2.12c-2.36%201.15-3.89%203.48-5.31%205.71-2.81%204.42-5.64%208.9-7.45%2013.82-.8%202.18-1.39%204.42-2.17%206.61a61%2061%200%200%201-2.74%206.33c-.15%201.08-.28%202.16-.38%203.25-.93%2010.27.49%2020.56.57%2030.88Z'%20opacity='.1'/%3e%3cpath%20fill='%232f2e41'%20d='M602.45%20498.11c1.79%202.38%201.71%205.63%201.46%208.59a129.18%20129.18%200%200%201-7%2032.27%2049.43%2049.43%200%200%201-5.29%2011.16%2039.07%2039.07%200%200%201-6.14%207c-3.4%203.1-7.54%205.87-12.15%205.91a23.16%2023.16%200%200%201-7.56-1.65l-37.55-12.78c-.38-2.14%201.13-4.64%201.84-6.7l2-5.93c.57-1.64%201.23-3.41%202.72-4.3s3.85.33%205.09%201.32%202.18%202.29%203.4%203.3c2.31%201.92%205.36%202.64%208.3%203.3l8.43%201.89a35.2%2035.2%200%200%200%209.38%201.25c2.35-7.18%206.82-13.5%209.35-20.62.78-2.18%201.37-4.43%202.18-6.61%201.8-4.92%204.64-9.39%207.45-13.82%201.41-2.22%202.94-4.55%205.31-5.71a7.23%207.23%200%200%201%208.78%202.13ZM596.24%20469.57a8.89%208.89%200%200%200-1.06-3.3%202.77%202.77%200%200%200-3-1.32c-1.76.55-2.35%203.27-4.19%203.36-1.24.06-2.13-1.2-2.52-2.38s-.6-2.53-1.53-3.36a5.7%205.7%200%200%200-2.18-1c-4.27-1.35-8.68-3.84-10.1-8.09a4.84%204.84%200%200%201-.23-2.71c.65-2.69%204-3.5%206.55-4.47s5-2.63%207.5-3.89%205.4-2.15%208.15-1.51a42.47%2042.47%200%200%201%204.11%201.53c4.14%201.44%209.21.77%2012.42%203.76a12.83%2012.83%200%200%201%203%205.24c2.24%206.22%203.66%2013.6-.05%2019.06-2.29%203.37-4.51%207.22-8.91%207.63-5.12.43-7.15-4.21-7.96-8.55Z'/%3e%3cg%20opacity='.1'%3e%3cpath%20d='M588.42%20463.81c-.39-1.18-.6-2.53-1.52-3.36a5.7%205.7%200%200%200-2.18-1c-4.28-1.35-8.68-3.84-10.11-8.09a4.93%204.93%200%200%201-.22-2.71%203.39%203.39%200%200%201%20.53-1.19c-1.63.71-3.05%201.65-3.45%203.31a4.84%204.84%200%200%200%20.23%202.71c1.42%204.25%205.83%206.74%2010.1%208.09a5.7%205.7%200%200%201%202.18%201c.93.83%201.13%202.17%201.53%203.36s1.28%202.44%202.52%202.38%201.84-1.19%202.63-2.14c-1.09-.14-1.88-1.26-2.24-2.36ZM607.14%20475.97c-5.14.47-7.17-4.21-8-8.52a8.7%208.7%200%200%200-1-3.3%202.78%202.78%200%200%200-3-1.32%205.32%205.32%200%200%200-2.21%202%203%203%200%200%201%202.26%201.4%208.89%208.89%200%200%201%201.06%203.3c.81%204.31%202.84%209%208%208.52a8.25%208.25%200%200%200%205.28-2.74%207.46%207.46%200%200%201-2.39.66Z'/%3e%3c/g%3e%3cellipse%20cx='813.11'%20cy='655.78'%20fill='%236c63ff'%20rx='32.29'%20ry='6.21'/%3e%3cellipse%20cx='812.57'%20cy='653.14'%20fill='%233f3d56'%20rx='3.76'%20ry='4.92'/%3e%3cellipse%20cx='812.57'%20cy='647.12'%20fill='%233f3d56'%20rx='3.76'%20ry='4.92'/%3e%3cellipse%20cx='812.57'%20cy='641.11'%20fill='%233f3d56'%20rx='3.76'%20ry='4.92'/%3e%3cellipse%20cx='812.57'%20cy='635.09'%20fill='%233f3d56'%20rx='3.76'%20ry='4.92'/%3e%3cellipse%20cx='812.57'%20cy='629.07'%20fill='%233f3d56'%20rx='3.76'%20ry='4.92'/%3e%3cellipse%20cx='812.57'%20cy='623.06'%20fill='%233f3d56'%20rx='3.76'%20ry='4.92'/%3e%3cellipse%20cx='812.57'%20cy='617.04'%20fill='%233f3d56'%20rx='3.76'%20ry='4.92'/%3e%3cpath%20fill='%236c63ff'%20d='M826.64%20575.91a18.19%2018.19%200%200%200%201.4-2.06l-9.88-1.62%2010.69.07a18.11%2018.11%200%200%200%20.34-14.27l-14.34%207.44%2013.22-9.72a18%2018%200%201%200-29.72%2020.16%2017.92%2017.92%200%200%200-2.06%203.28l12.83%206.67-13.68-4.59a18%2018%200%200%200%202.91%2016.88%2018%2018%200%201%200%2028.31%200%2018%2018%200%200%200%200-22.27Z'/%3e%3cpath%20d='M794.47%20587.01a17.91%2017.91%200%200%200%203.88%2011.14%2018%2018%200%201%200%2028.31%200c2.39-3.07-32.19-13.16-32.19-11.14Z'%20opacity='.1'/%3e%3cellipse%20cx='148.42'%20cy='776.87'%20fill='%236c63ff'%20rx='46.49'%20ry='8.94'/%3e%3cellipse%20cx='147.64'%20cy='773.07'%20fill='%233f3d56'%20rx='5.41'%20ry='7.09'/%3e%3cellipse%20cx='147.64'%20cy='764.41'%20fill='%233f3d56'%20rx='5.41'%20ry='7.09'/%3e%3cellipse%20cx='147.64'%20cy='755.75'%20fill='%233f3d56'%20rx='5.41'%20ry='7.09'/%3e%3cellipse%20cx='147.64'%20cy='747.09'%20fill='%233f3d56'%20rx='5.41'%20ry='7.09'/%3e%3cellipse%20cx='147.64'%20cy='738.43'%20fill='%233f3d56'%20rx='5.41'%20ry='7.09'/%3e%3cellipse%20cx='147.64'%20cy='729.76'%20fill='%233f3d56'%20rx='5.41'%20ry='7.09'/%3e%3cellipse%20cx='147.64'%20cy='721.1'%20fill='%233f3d56'%20rx='5.41'%20ry='7.09'/%3e%3cpath%20fill='%236c63ff'%20d='M167.9%20661.84a27.23%2027.23%200%200%200%202-3l-14.22-2.34%2015.38.12a26%2026%200%200%200%20.49-20.55l-20.62%2010.74%2019-14a25.93%2025.93%200%201%200-42.83%2029%2025.83%2025.83%200%200%200-3%204.72l18.47%209.6-19.69-6.61a25.93%2025.93%200%200%200%204.26%2024.39%2025.93%2025.93%200%201%200%2040.76%200%2025.92%2025.92%200%200%200%200-32.06Z'/%3e%3cpath%20d='M121.59%20677.91a25.85%2025.85%200%200%200%205.55%2016%2025.93%2025.93%200%201%200%2040.76%200c3.45-4.42-46.31-18.95-46.31-16Z'%20opacity='.1'/%3e%3c/svg%3e";
@@ -208,10 +225,10 @@ function getAppInfo() {
208
225
  return {
209
226
  "pkg": {
210
227
  "name": "@oj-module/runtime",
211
- "version": "0.1.8",
228
+ "version": "0.1.11",
212
229
  "license": "MIT"
213
230
  },
214
- "lastBuildTime": "2026-09-12 00:19:59"
231
+ "lastBuildTime": "2026-10-07 12:56:35"
215
232
  };
216
233
  }
217
234
  var init_get_app_info = __esmMin((() => {}));
@@ -339,7 +356,11 @@ function PageError({ error, resetErrorBoundary }) {
339
356
  status: "error",
340
357
  icon: /* @__PURE__ */ jsx("div", {
341
358
  className: "w-7/12 md:w-3/12 xl:w-2/12 inline-block",
342
- children: /* @__PURE__ */ jsx(undraw_bug_fixing_default, {})
359
+ children: /* @__PURE__ */ jsx("img", {
360
+ src: undraw_bug_fixing_default,
361
+ alt: "",
362
+ className: "w-full"
363
+ })
343
364
  }),
344
365
  title: error?.message ?? t("exception.pageErrorTitle"),
345
366
  extra: /* @__PURE__ */ jsxs(Space, {
@@ -3106,22 +3127,22 @@ var init_routes = __esmMin((() => {
3106
3127
  //#endregion
3107
3128
  //#region src/store/auth-provider.ts
3108
3129
  function registerAuthProvider(moduleName, provider) {
3109
- if (current) {
3110
- console.warn(`[auth] 重复的认证 provider 忽略:已由模块 "${current.moduleName}" 提供,忽略 "${moduleName}"(先到先得,与 login 路由去重同一规则)。`);
3130
+ if (current$1) {
3131
+ console.warn(`[auth] 重复的认证 provider 忽略:已由模块 "${current$1.moduleName}" 提供,忽略 "${moduleName}"(先到先得,与 login 路由去重同一规则)。`);
3111
3132
  return;
3112
3133
  }
3113
- current = {
3134
+ current$1 = {
3114
3135
  moduleName,
3115
3136
  provider
3116
3137
  };
3117
3138
  }
3118
3139
  function getAuthProvider() {
3119
- return current?.provider;
3140
+ return current$1?.provider;
3120
3141
  }
3121
3142
  function unregisterAuthProvider(moduleName) {
3122
- if (current?.moduleName === moduleName) current = void 0;
3143
+ if (current$1?.moduleName === moduleName) current$1 = void 0;
3123
3144
  }
3124
- var current;
3145
+ var current$1;
3125
3146
  var init_auth_provider = __esmMin((() => {}));
3126
3147
  //#endregion
3127
3148
  //#region src/store/user.ts
@@ -3302,6 +3323,33 @@ function useCurrentRoute() {
3302
3323
  }
3303
3324
  var init_use_current_route = __esmMin((() => {}));
3304
3325
  //#endregion
3326
+ //#region src/layout/layout-registry.ts
3327
+ function registerLayout(moduleName, name, component) {
3328
+ const current = registrations.get(name);
3329
+ if (current) {
3330
+ console.warn(`[layout] 重复的布局名 "${name}" 忽略:已由模块 "${current.moduleName}" 提供,忽略 "${moduleName}"(先到先得)。`);
3331
+ return;
3332
+ }
3333
+ registrations.set(name, {
3334
+ moduleName,
3335
+ component
3336
+ });
3337
+ }
3338
+ function getRegisteredLayout(name) {
3339
+ return registrations.get(name)?.component;
3340
+ }
3341
+ /**
3342
+ * 卸载模块时清掉其登记的全部布局(以 moduleName 隔离,不影响其他模块)。
3343
+ * 只影响「再解析」语义——已注入运行中 router 的路由不热回落(设计文档 N8)。
3344
+ */
3345
+ function unregisterLayouts(moduleName) {
3346
+ for (const [name, registration] of registrations) if (registration.moduleName === moduleName) registrations.delete(name);
3347
+ }
3348
+ var registrations;
3349
+ var init_layout_registry = __esmMin((() => {
3350
+ registrations = /* @__PURE__ */ new Map();
3351
+ }));
3352
+ //#endregion
3305
3353
  //#region src/components/jss-theme-provider/index.tsx
3306
3354
  /**
3307
3355
  * JSSThemeProvider 组件
@@ -4362,6 +4410,7 @@ var init_notification = __esmMin((() => {
4362
4410
  const [open, action] = useToggle();
4363
4411
  const classes = useStyles$5();
4364
4412
  const { t } = useTranslation();
4413
+ const readOnly = !onEventChange;
4365
4414
  const close = () => {
4366
4415
  action.set(false);
4367
4416
  };
@@ -4370,12 +4419,15 @@ var init_notification = __esmMin((() => {
4370
4419
  close();
4371
4420
  };
4372
4421
  const handleMakeAll = () => {
4422
+ if (readOnly) return;
4373
4423
  onEventChange && onEventChange("makeAll");
4374
4424
  };
4375
4425
  const handleClear = () => {
4426
+ if (readOnly) return;
4376
4427
  onEventChange && onEventChange("clear");
4377
4428
  };
4378
4429
  const handleClick = (item) => {
4430
+ if (readOnly) return;
4379
4431
  onEventChange && onEventChange("read", item);
4380
4432
  };
4381
4433
  dot = useMemo(() => {
@@ -4396,7 +4448,7 @@ var init_notification = __esmMin((() => {
4396
4448
  children: [/* @__PURE__ */ jsx("div", { children: t("widgets.notifications") }), /* @__PURE__ */ jsx(Tooltip, {
4397
4449
  title: notifications?.length ? t("widgets.markAllAsRead") : null,
4398
4450
  children: /* @__PURE__ */ jsx(BasicButton, {
4399
- disabled: !notifications?.length,
4451
+ disabled: readOnly || !notifications?.length,
4400
4452
  onClick: handleMakeAll,
4401
4453
  type: "text",
4402
4454
  icon: /* @__PURE__ */ jsx(RiMailCheckLine, {})
@@ -4406,7 +4458,7 @@ var init_notification = __esmMin((() => {
4406
4458
  footer: /* @__PURE__ */ jsxs("div", {
4407
4459
  className: "flex items-center justify-between",
4408
4460
  children: [/* @__PURE__ */ jsx(BasicButton, {
4409
- disabled: !notifications?.length,
4461
+ disabled: readOnly || !notifications?.length,
4410
4462
  type: "text",
4411
4463
  onClick: handleClear,
4412
4464
  children: t("widgets.clearNotifications")
@@ -4462,24 +4514,48 @@ var init_notification = __esmMin((() => {
4462
4514
  }));
4463
4515
  //#endregion
4464
4516
  //#region src/layout/widgets/notification/notification-container.tsx
4517
+ /**
4518
+ * 通知容器(G4):拉取列表 + 接线互动事件。
4519
+ *
4520
+ * - 互动可用的前提:注册了 provider 且四方法齐全;否则降级只读
4521
+ * (popup 按 onEventChange 是否存在推导,评审 A3——不加新 prop);
4522
+ * - 写操作成功后重拉刷新;**重拉失败不清空现有列表**(评审 b4);
4523
+ * - 20x 复制残留已删除(评审 b4,同一 id 复制 20 份会让 markRead 语义失真);
4524
+ * - viewAll 不接线(N3,模板无通知中心页)。
4525
+ */
4465
4526
  function NotificationContainer({ ...restProps }) {
4466
4527
  const [notifications, setNotifications] = useState([]);
4467
- useEffect(() => {
4528
+ const provider = getNotificationsApiProvider();
4529
+ const staleSafe = provider;
4530
+ const interactive = Boolean(staleSafe?.fetchNotifications && staleSafe.markRead && staleSafe.markAllRead && staleSafe.clearAll);
4531
+ if (provider && !interactive && !warnedStaleProviders.has("notifications")) {
4532
+ warnedStaleProviders.add("notifications");
4533
+ console.warn("[notification] 已注册的通知 provider 缺少写方法(markRead/markAllRead/clearAll),疑似老版本模块 bundle;通知降级为只读展示。");
4534
+ }
4535
+ const reload = useCallback(() => {
4468
4536
  fetchNotifications().then((res) => {
4469
- const list = Array.isArray(res) ? res : [];
4470
- setNotifications(Array.from({ length: 20 }).flatMap(() => list));
4471
- }).catch(() => {
4472
- setNotifications([]);
4473
- });
4537
+ setNotifications(Array.isArray(res) ? res : []);
4538
+ }).catch(() => {});
4474
4539
  }, []);
4540
+ useEffect(() => {
4541
+ reload();
4542
+ }, [reload]);
4475
4543
  return /* @__PURE__ */ jsx(NotificationPopup, {
4476
4544
  notifications,
4545
+ onEventChange: interactive ? (event, item) => {
4546
+ const p = provider;
4547
+ if (!p) return;
4548
+ (event === "read" ? () => p.markRead(item.id) : event === "makeAll" ? () => p.markAllRead() : event === "clear" ? () => p.clearAll() : void 0)?.().then(reload).catch(() => {});
4549
+ } : void 0,
4477
4550
  ...restProps
4478
4551
  });
4479
4552
  }
4553
+ var warnedStaleProviders;
4480
4554
  var init_notification_container = __esmMin((() => {
4481
4555
  init_notifications();
4556
+ init_api_provider();
4482
4557
  init_notification();
4558
+ warnedStaleProviders = /* @__PURE__ */ new Set();
4483
4559
  }));
4484
4560
  //#endregion
4485
4561
  //#region src/layout/widgets/preferences/switch-item.tsx
@@ -6840,13 +6916,25 @@ var init_parent_layout = __esmMin((() => {}));
6840
6916
  //#endregion
6841
6917
  //#region src/router/utils/resolve-layout.ts
6842
6918
  /**
6843
- * 根据路由 `handle.layout` 解析所用布局组件(P2.2,设计文档 D9)。
6919
+ * 根据路由 `handle.layout` 解析所用布局组件(P2.2,设计文档 D9;G1 模块登记优先)。
6844
6920
  *
6845
6921
  * 未声明即 `none` 是 D9 的目标态(P2.7 dogfooding 验证后自迁移期默认 `container` 翻转):
6846
6922
  * 布局必须显式声明,框架不做隐式推导;后端下发的父级路由需在 handle 中携带 layout。
6923
+ *
6924
+ * 非内建且模块注册表未命中的名字 warn-once 一次并回落 Outlet——
6925
+ * 后端下发了模块布局名而提供方模块未加载时,这条 warn 是唯一线索(评审 A6)。
6847
6926
  */
6848
6927
  function resolveLayoutComponent(handle) {
6849
- return handle?.layout && layoutRegistry[handle.layout] || Outlet;
6928
+ const name = handle?.layout;
6929
+ if (!name) return Outlet;
6930
+ const registered = getRegisteredLayout(name);
6931
+ if (registered) return registered;
6932
+ if (layoutRegistry[name]) return layoutRegistry[name];
6933
+ if (!warnedUnknownLayouts.has(name)) {
6934
+ warnedUnknownLayouts.add(name);
6935
+ console.warn(`[layout] 未知名布局 "${name}":既非内建(container/parent/fullscreen),也无模块登记,回落 Outlet。`);
6936
+ }
6937
+ return Outlet;
6850
6938
  }
6851
6939
  /**
6852
6940
  * 递归为缺少 Component 的父级路由按 `handle.layout` 注入布局组件(P2.7,US-8)。
@@ -6867,32 +6955,57 @@ function resolveRouteLayouts(routes) {
6867
6955
  } : resolved;
6868
6956
  });
6869
6957
  }
6870
- var layoutRegistry;
6958
+ var layoutRegistry, warnedUnknownLayouts;
6871
6959
  var init_resolve_layout = __esmMin((() => {
6872
6960
  init_container_layout();
6873
6961
  init_fullscreen_layout();
6962
+ init_layout_registry();
6874
6963
  init_parent_layout();
6875
6964
  layoutRegistry = {
6876
6965
  parent: ParentLayout,
6877
6966
  container: ContainerLayout,
6878
6967
  fullscreen: FullscreenLayout
6879
6968
  };
6969
+ warnedUnknownLayouts = /* @__PURE__ */ new Set();
6880
6970
  }));
6881
6971
  //#endregion
6972
+ //#region src/store/header-provider.ts
6973
+ function registerHeaderProvider(moduleName, provider) {
6974
+ if (current) {
6975
+ console.warn(`[header] 重复的请求头 provider 忽略:已由模块 "${current.moduleName}" 提供,忽略 "${moduleName}"(先到先得,与 authProvider 同一规则)。`);
6976
+ return;
6977
+ }
6978
+ current = {
6979
+ moduleName,
6980
+ provider
6981
+ };
6982
+ }
6983
+ function currentHeaderProvider() {
6984
+ return current?.provider;
6985
+ }
6986
+ function unregisterHeaderProvider(moduleName) {
6987
+ if (current?.moduleName === moduleName) current = void 0;
6988
+ }
6989
+ var current;
6990
+ var init_header_provider = __esmMin((() => {}));
6991
+ //#endregion
6882
6992
  //#region src/utils/request/scoped.ts
6883
6993
  /** 仅暴露安全子集:callable + HTTP verb 工厂;不给 create/extend(可绕过 hooks) */
6884
6994
  function createScopedRequest(moduleName, getPrefix, underlying = request) {
6885
6995
  function guard(rawUrl) {
6886
- const prefix = getPrefix();
6887
- if (!prefix) throw new Error(`[module] 模块 "${moduleName}" 尚未登记 API 前缀:请先在生命周期中调用 ctx.register.apiPrefix("/your-prefix") 再发起请求。`);
6996
+ const registered = getPrefix();
6997
+ const prefixes = (Array.isArray(registered) ? registered : [registered]).filter((prefix) => typeof prefix === "string" && prefix.length > 0);
6998
+ if (prefixes.length === 0) throw new Error(`[module] 模块 "${moduleName}" 尚未登记 API 前缀:请先在生命周期中调用 ctx.register.apiPrefix("/your-prefix") 再发起请求。`);
6888
6999
  let pathname;
6889
7000
  try {
6890
7001
  pathname = new URL(rawUrl, "http://scoped.local").pathname;
6891
7002
  } catch {
6892
7003
  pathname = rawUrl;
6893
7004
  }
6894
- const boundary = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
6895
- if (pathname !== boundary && !pathname.startsWith(`${boundary}/`)) throw new Error(`[module] 模块 "${moduleName}" 请求越界:${rawUrl} 不在其登记前缀 ${prefix} 内。请调整接口路径,或登记正确前缀(D11 安全收敛)。`);
7005
+ if (!prefixes.some((prefix) => {
7006
+ const boundary = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
7007
+ return pathname === boundary || pathname.startsWith(`${boundary}/`);
7008
+ })) throw new Error(`[module] 模块 "${moduleName}" 请求越界:${rawUrl} 不在其登记前缀 ${prefixes.join("、")} 内。请调整接口路径,或登记正确前缀(D11 安全收敛)。`);
6896
7009
  }
6897
7010
  /**
6898
7011
  * P7.2:剥离逐请求 prefix/prefixUrl——ky 2.x 允许逐请求覆盖默认 prefix,
@@ -7034,11 +7147,16 @@ function createModuleContext(definition) {
7034
7147
  registeredStores.set(name, store);
7035
7148
  },
7036
7149
  apiPrefix: (prefix) => {
7037
- registeredApiPrefixes.set(definition.name, prefix);
7150
+ const prefixes = registeredApiPrefixes.get(definition.name) ?? [];
7151
+ if (!prefixes.includes(prefix)) prefixes.push(prefix);
7152
+ registeredApiPrefixes.set(definition.name, prefixes);
7038
7153
  },
7039
7154
  authProvider: (provider) => {
7040
7155
  registerAuthProvider(definition.name, provider);
7041
7156
  },
7157
+ headerProvider: (provider) => {
7158
+ registerHeaderProvider(definition.name, provider);
7159
+ },
7042
7160
  systemApi: (provider) => {
7043
7161
  registerSystemApiProvider(definition.name, provider);
7044
7162
  },
@@ -7047,6 +7165,12 @@ function createModuleContext(definition) {
7047
7165
  },
7048
7166
  uploadApi: (provider) => {
7049
7167
  registerUploadApiProvider(definition.name, provider);
7168
+ },
7169
+ routesApi: (provider) => {
7170
+ registerRoutesApiProvider(definition.name, provider);
7171
+ },
7172
+ layout: (name, component) => {
7173
+ registerLayout(definition.name, name, component);
7050
7174
  }
7051
7175
  },
7052
7176
  registerSlot: (slotName, node) => {
@@ -7204,8 +7328,9 @@ function getRoutes() {
7204
7328
  function getRegisteredStore(name) {
7205
7329
  return registeredStores.get(name);
7206
7330
  }
7331
+ /** 首个登记的前缀(一模块可登记多个);未登记返回 undefined */
7207
7332
  function getRegisteredApiPrefix(moduleName) {
7208
- return registeredApiPrefixes.get(moduleName);
7333
+ return registeredApiPrefixes.get(moduleName)?.[0];
7209
7334
  }
7210
7335
  /**
7211
7336
  * 卸载模块:执行 onDestroy 生命周期 → 清理其布局插槽(US-8)→ 移除实例。
@@ -7219,7 +7344,9 @@ async function unloadModule(name) {
7219
7344
  }
7220
7345
  removeModuleSlots(name);
7221
7346
  unregisterAuthProvider(name);
7347
+ unregisterHeaderProvider(name);
7222
7348
  unregisterApiProviders(name);
7349
+ unregisterLayouts(name);
7223
7350
  modules.delete(name);
7224
7351
  }
7225
7352
  /**
@@ -7241,11 +7368,13 @@ function getAllRoutePathKeys() {
7241
7368
  }
7242
7369
  var modules, registeredStores, registeredApiPrefixes;
7243
7370
  var init_module_loader = __esmMin((() => {
7371
+ init_layout_registry();
7244
7372
  init_add_route_id_by_path();
7245
7373
  init_resolve_layout();
7246
7374
  init_access();
7247
7375
  init_api_provider();
7248
7376
  init_auth_provider();
7377
+ init_header_provider();
7249
7378
  init_user();
7250
7379
  init_scoped();
7251
7380
  init_keep_alive();
@@ -7980,7 +8109,7 @@ var init_guard = __esmMin((() => {
7980
8109
  * @en Root layout component
7981
8110
  */
7982
8111
  function LayoutRoot() {
7983
- return /* @__PURE__ */ jsxs(ErrorBoundary, {
8112
+ return /* @__PURE__ */ jsxs(ErrorBoundary$1, {
7984
8113
  FallbackComponent: PageError,
7985
8114
  children: [/* @__PURE__ */ jsx(LayoutEffects, {}), /* @__PURE__ */ jsx(AuthGuard, { children: /* @__PURE__ */ jsx(Outlet, {}) })]
7986
8115
  });
@@ -8487,6 +8616,7 @@ var defaultConfig, request;
8487
8616
  var init_request = __esmMin((() => {
8488
8617
  init_extra_info();
8489
8618
  init_auth();
8619
+ init_header_provider();
8490
8620
  init_preferences$3();
8491
8621
  init_constants$3();
8492
8622
  init_error_response();
@@ -8507,6 +8637,8 @@ var init_request = __esmMin((() => {
8507
8637
  setHeaderSafe(request.headers, AUTH_HEADER, `Bearer ${token}`);
8508
8638
  }
8509
8639
  setHeaderSafe(request.headers, LANG_HEADER, usePreferencesStore.getState().language);
8640
+ const headerProvider = currentHeaderProvider();
8641
+ if (headerProvider) for (const [name, value] of Object.entries(headerProvider())) setHeaderSafe(request.headers, name, value);
8510
8642
  }],
8511
8643
  afterResponse: [async ({ request, options, response }) => {
8512
8644
  if (!options.ignoreLoading) globalProgress.done();
@@ -27267,6 +27399,7 @@ var external_exports = /* @__PURE__ */ __exportAll({
27267
27399
  init_user$1();
27268
27400
  init_basic_button();
27269
27401
  init_iframe();
27402
+ init_page_error();
27270
27403
  init_use_preferences();
27271
27404
  init_icons();
27272
27405
  init_layout_effects();
@@ -27283,4 +27416,4 @@ init_ri();
27283
27416
  init_menu_icons();
27284
27417
  init_tree();
27285
27418
  //#endregion
27286
- export { AccessControl, AccessControlRoles, AntdApp, BasicButton, BasicContent, BasicTable, EmbeddedIcon, ExternalIcon, FormAvatarItem, FormTreeItem, Iframe, LayoutCenterIcon, LayoutEffects, LayoutLeftIcon, LayoutRightIcon, MixedNavigationIcon, OutsidePageIcon, ProfileCardIcon, RiAccountCircleLine, RiContrastFill, RiFullscreenExitLine, RiFullscreenLine, RiMailCheckLine, RiMoonIcon, RiReactjsLine, RiSunIcon, RiUserSettingsLine, ServerErrorIcon, SideNavigationIcon, TopNavigationIcon, TwoColumnNavigationIcon, accessControlCodes, defineModule, fetchAddMenuItem, fetchAddRoleItem, fetchAsyncRoutes, fetchDeleteMenuItem, fetchDeleteRoleItem, fetchLogin, fetchLogout, fetchMenuByRoleId, fetchMenuList, fetchRefreshToken, fetchRoleList, fetchRoleMenu, fetchUpdateMenuItem, fetchUpdateRoleItem, fetchUserInfo, filterTree, getAllExpandedKeys, getAppInfo, getBooleanOptions, getModule, getModules, getRedirectPath, getRegisteredApiPrefix, getRegisteredStore, getRoutes, getYesNoOptions, handleTree, loadAll, mapTree, menuIcons, permissionPrefix, setupI18n, traverseTreeValues, unloadModule, useAccess, useAuthStore, usePreferences, useSlotNodes, useUserStore, external_exports as z };
27419
+ export { AccessControl, AccessControlRoles, AntdApp, BasicButton, BasicContent, BasicTable, EmbeddedIcon, ErrorBoundary, ExternalIcon, FormAvatarItem, FormTreeItem, Iframe, LayoutCenterIcon, LayoutEffects, LayoutLeftIcon, LayoutRightIcon, MixedNavigationIcon, OutsidePageIcon, PageError, ProfileCardIcon, RiAccountCircleLine, RiContrastFill, RiFullscreenExitLine, RiFullscreenLine, RiMailCheckLine, RiMoonIcon, RiReactjsLine, RiSunIcon, RiUserSettingsLine, ServerErrorIcon, SideNavigationIcon, TopNavigationIcon, TwoColumnNavigationIcon, accessControlCodes, defineModule, fetchAddMenuItem, fetchAddRoleItem, fetchAsyncRoutes, fetchDeleteMenuItem, fetchDeleteRoleItem, fetchLogin, fetchLogout, fetchMenuByRoleId, fetchMenuList, fetchRefreshToken, fetchRoleList, fetchRoleMenu, fetchUpdateMenuItem, fetchUpdateRoleItem, fetchUserInfo, filterTree, getAllExpandedKeys, getAppInfo, getBooleanOptions, getModule, getModules, getRedirectPath, getRegisteredApiPrefix, getRegisteredStore, getRoutes, getYesNoOptions, handleTree, loadAll, mapTree, menuIcons, permissionPrefix, setupI18n, traverseTreeValues, unloadModule, useAccess, useAuthStore, usePreferences, useSlotNodes, useUserStore, external_exports as z };
@@ -1,6 +1,7 @@
1
1
  import type { MenuItemType } from "../api/system/menu/types";
2
2
  import type { FetchAddRoleItemBody, FetchAddRoleItemData, FetchDeleteRoleItemBody, FetchDeleteRoleItemData, FetchMenuByRoleIdData, FetchMenuByRoleIdQuery, FetchRoleListData, FetchRoleListQuery, FetchRoleMenuData, FetchUpdateRoleItemBody, FetchUpdateRoleItemData } from "../api/system/role/client/api";
3
3
  import type { NotificationItem } from "../layout/widgets/notification/types";
4
+ import type { AppRouteRecordRaw } from "../router/types";
4
5
  /**
5
6
  * 系统 API provider(D9):模块经 ctx.register.systemApi 接管角色/菜单类
6
7
  * 内置 API。系统角色/菜单/通知/上传这些原本硬编码在 runtime 根级路径的
@@ -23,9 +24,16 @@ export interface SystemApiProvider {
23
24
  fetchUpdateMenuItem: (data: MenuItemType) => Promise<string>;
24
25
  fetchDeleteMenuItem: (id: number) => Promise<string>;
25
26
  }
26
- /** 通知 provider(D9):模块经 ctx.register.notificationsApi 接管通知拉取 */
27
+ /**
28
+ * 通知 provider(D9 + G4):模块经 ctx.register.notificationsApi 接管通知。
29
+ * 四方法全必填——「接管通知 API」是全量接管(读 + 三个写),不做部分托管;
30
+ * 老 bundle 只有 fetchNotifications 的版本漂移由消费点运行时防御(评审 P2-7)。
31
+ */
27
32
  export interface NotificationsApiProvider {
28
33
  fetchNotifications: () => Promise<NotificationItem[]>;
34
+ markRead: (id: string | number) => Promise<void>;
35
+ markAllRead: () => Promise<void>;
36
+ clearAll: () => Promise<void>;
29
37
  }
30
38
  /** 上传 provider(D9):模块经 ctx.register.uploadApi 接管头像/附件上传端点 */
31
39
  export interface UploadApiProvider {
@@ -34,14 +42,25 @@ export interface UploadApiProvider {
34
42
  /** 每次上传动态取请求头(如注入 Bearer);返回普通对象 */
35
43
  headers: () => Record<string, string>;
36
44
  }
45
+ /** 动态路由 provider(G2):模块经 ctx.register.routesApi 接管后端动态路由拉取 */
46
+ export interface RoutesApiProvider {
47
+ /**
48
+ * 返回后端动态路由。component 解析边界(评审 P0-2):返回的路由按框架
49
+ * pages glob 解析 component(generate-routes-from-backend.ts),模块自有
50
+ * 组件的后端路由不在本契约内——请走模块路由(N7)。
51
+ */
52
+ fetchAsyncRoutes: () => Promise<AppRouteRecordRaw[]>;
53
+ }
37
54
  export declare function registerSystemApiProvider(moduleName: string, provider: SystemApiProvider): void;
38
55
  export declare function getSystemApiProvider(): SystemApiProvider | undefined;
39
56
  export declare function registerNotificationsApiProvider(moduleName: string, provider: NotificationsApiProvider): void;
40
57
  export declare function getNotificationsApiProvider(): NotificationsApiProvider | undefined;
41
58
  export declare function registerUploadApiProvider(moduleName: string, provider: UploadApiProvider): void;
42
59
  export declare function getUploadApiProvider(): UploadApiProvider | undefined;
60
+ export declare function registerRoutesApiProvider(moduleName: string, provider: RoutesApiProvider): void;
61
+ export declare function getRoutesApiProvider(): RoutesApiProvider | undefined;
43
62
  /**
44
- * 卸载模块时复位其登记的全部 API provider(系统/通知/上传)。以 moduleName
63
+ * 卸载模块时复位其登记的全部 API provider(系统/通知/上传/动态路由)。以 moduleName
45
64
  * 作命名隔离——不同模块各自登记互不干扰,卸载只清自己的。
46
65
  */
47
66
  export declare function unregisterApiProviders(moduleName: string): void;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 请求头 provider(D-M9):模块经 ctx.register.headerProvider 注入惰性求值的
3
+ * 自定义请求头(租户等),beforeRequest 在 token / X-Lang 注入之后逐请求合并。
4
+ *
5
+ * 合并语义 = 追加非替换:provider 未提及的头不受影响;同名头以后写(provider)
6
+ * 为准(ky Headers.set 语义)。provider 未注册时请求照发(时序容忍:
7
+ * 登录前 guard 请求无租户头)。
8
+ */
9
+ export type HeaderProvider = () => Record<string, string>;
10
+ export declare function registerHeaderProvider(moduleName: string, provider: HeaderProvider): void;
11
+ export declare function currentHeaderProvider(): HeaderProvider | undefined;
12
+ export declare function unregisterHeaderProvider(moduleName: string): void;
@@ -3,15 +3,20 @@ import { request } from "./index";
3
3
  * P6.3 / D11:模块专用 scoped request client。
4
4
  *
5
5
  * 模块不再拿到全局 request——它以模块登记的 apiPrefix 为边界收敛:
6
- * 请求 URL 必须以 `ctx.register.apiPrefix()` 声明的前缀开头,越界直接
6
+ * 请求 URL 必须以 `ctx.register.apiPrefix()` 声明的**任一**前缀开头,越界直接
7
7
  * 拒绝(人话报错)。前缀读取是惰性的(每次请求时求值),因此允许模块
8
- * 在生命周期中先发请求前登记、甚至重新登记。
8
+ * 在生命周期中先发请求前登记、甚至追加登记。
9
9
  *
10
10
  * 这是纵深防御的前端一半;后端逐接口鉴权仍是安全兜底(§4.8 授权行)。
11
11
  */
12
12
  type GlobalRequest = typeof request;
13
13
  /** 仅暴露安全子集:callable + HTTP verb 工厂;不给 create/extend(可绕过 hooks) */
14
- export declare function createScopedRequest(moduleName: string, getPrefix: () => string | undefined,
14
+ export declare function createScopedRequest(moduleName: string,
15
+ /**
16
+ * 惰性取已登记前缀。一模块可登记多个(多个生成 client 各自登记),
17
+ * 传数组即「命中任一放行」;兼容单值写法。
18
+ */
19
+ getPrefix: () => string | readonly string[] | undefined,
15
20
  /** 注入底层实例,测试用 */
16
21
  underlying?: GlobalRequest): GlobalRequest;
17
22
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oj-module/runtime",
3
3
  "type": "module",
4
- "version": "0.1.8",
4
+ "version": "0.1.11",
5
5
  "description": "React Antd Admin 框架运行时,供模块工程消费",
6
6
  "license": "MIT",
7
7
  "imports": {