@oj-module/runtime 0.2.2 → 0.2.5
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/dist/api/rbac/helpers.d.ts +18 -0
- package/dist/api/rbac/index.d.ts +5 -1
- package/dist/api/rbac/types.d.ts +21 -0
- package/dist/api/user/types.d.ts +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/router/routes/index.d.ts +2 -0
- package/dist/router/types.d.ts +6 -0
- package/dist/router/utils/ascending.d.ts +2 -0
- package/dist/router/utils/merge-solution-categories.d.ts +21 -0
- package/dist/runtime.js +143 -8
- package/dist/store/access.d.ts +5 -1
- package/dist/store/solution-routes.d.ts +21 -0
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { RbacSettingItem } from "./types";
|
|
1
2
|
/** 展示名:title 缺省回落机器名。 */
|
|
2
3
|
export declare function roleLabel(role: {
|
|
3
4
|
name: string;
|
|
@@ -26,3 +27,20 @@ export declare function groupByModule<T extends {
|
|
|
26
27
|
module: string;
|
|
27
28
|
items: T[];
|
|
28
29
|
}>;
|
|
30
|
+
/** 设置卡片(系统设置页三层嵌套渲染单元,R20):框架卡 module=null,方案卡带所属方案名。 */
|
|
31
|
+
export interface RbacSettingCard {
|
|
32
|
+
/** 方案模块名;框架卡为 null(标题走 system:setting.group.*,与 C4 现状一致) */
|
|
33
|
+
module: string | null;
|
|
34
|
+
/** settings 组 id(sys_setting.group 列) */
|
|
35
|
+
group: string;
|
|
36
|
+
/** 卡片标题 i18n key:方案卡 = `<module>:settings.group.<group>`(C2-22 组标题契约);框架卡 null */
|
|
37
|
+
label_key: string | null;
|
|
38
|
+
items: RbacSettingItem[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 设置行按模块三层嵌套分组(R20/R24,纯函数):框架卡在前(按 group 列聚合、保持服务端
|
|
42
|
+
* `order by group, key` 次序),方案卡在后(module 名升序、组内按 group 列聚合)。
|
|
43
|
+
* 不按 key 首段切组——框架 seed 存在无点号键(ldap_base_dn),首段不是其模块名;
|
|
44
|
+
* module 列是落库的所有权真源。空行降级返回空数组。
|
|
45
|
+
*/
|
|
46
|
+
export declare function groupSettingsByModule(rows: RbacSettingItem[]): RbacSettingCard[];
|
package/dist/api/rbac/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AuthSessionPayload, LoginMethods, RbacContact, RbacOplogPage, RbacPermission, RbacRole, RbacSettingGroup, RbacUser } from "./types";
|
|
1
|
+
import type { AuthSessionPayload, LoginMethods, RbacContact, RbacOplogPage, RbacOplogWrite, RbacPermission, RbacRole, RbacSettingGroup, RbacUser, SolutionRouteRow } from "./types";
|
|
2
2
|
export * from "./types";
|
|
3
3
|
export declare const fetchRbacRoleList: () => Promise<RbacRole[]>;
|
|
4
4
|
export declare const fetchRbacPermissionList: () => Promise<RbacPermission[]>;
|
|
@@ -25,8 +25,12 @@ export declare function fetchRbacOplog(query: {
|
|
|
25
25
|
module?: string;
|
|
26
26
|
limit?: number;
|
|
27
27
|
}): Promise<RbacOplogPage>;
|
|
28
|
+
export declare const fetchRbacOplogPost: (body: RbacOplogWrite) => Promise<{
|
|
29
|
+
ok: boolean;
|
|
30
|
+
}>;
|
|
28
31
|
export declare const fetchRbacSettings: () => Promise<RbacSettingGroup[]>;
|
|
29
32
|
export declare const fetchRbacUpdateSetting: (key: string, value: string) => Promise<unknown>;
|
|
33
|
+
export declare const fetchSolutionRoutes: () => Promise<SolutionRouteRow[]>;
|
|
30
34
|
export declare function fetchRbacContacts(keyword: string, limit?: number): Promise<RbacContact[]>;
|
|
31
35
|
export declare const fetchRbacContactDetail: (id: number) => Promise<RbacContact & {
|
|
32
36
|
email: string | null;
|
package/dist/api/rbac/types.d.ts
CHANGED
|
@@ -61,9 +61,30 @@ export interface RbacSettingGroup {
|
|
|
61
61
|
group: string;
|
|
62
62
|
items: RbacSettingItem[];
|
|
63
63
|
}
|
|
64
|
+
/** 方案路由行(GET /api/_platform/solutions/routes;P1-14/R21 前端归并数据源,登录即可只读端点) */
|
|
65
|
+
export interface SolutionRouteRow {
|
|
66
|
+
path: string;
|
|
67
|
+
module: string;
|
|
68
|
+
category: "main" | "admin" | "hidden";
|
|
69
|
+
order: number;
|
|
70
|
+
title_key: string | null;
|
|
71
|
+
/** 仅供深检对比,前端不做权限级菜单过滤(R22:后端 403 硬执行) */
|
|
72
|
+
required_permission: string | null;
|
|
73
|
+
/** false = 禁用:仅菜单层过滤(hideInMenu),路由可达性归装载层(D12) */
|
|
74
|
+
enabled: boolean;
|
|
75
|
+
}
|
|
64
76
|
export interface LoginMethods {
|
|
65
77
|
methods: Array<"local" | "ldap" | "sso">;
|
|
66
78
|
}
|
|
79
|
+
/** 操作日志写端入参(POST /api/system/oplog;module 为调用方自身模块名)。脱敏红线:detail 不得含口令/密钥/token。 */
|
|
80
|
+
export interface RbacOplogWrite {
|
|
81
|
+
action: string;
|
|
82
|
+
module: string;
|
|
83
|
+
version?: string;
|
|
84
|
+
target?: string;
|
|
85
|
+
detail?: unknown;
|
|
86
|
+
level?: number;
|
|
87
|
+
}
|
|
67
88
|
/** 登录响应(auth/login、auth/refresh、auth/password 同形) */
|
|
68
89
|
export interface AuthSessionPayload {
|
|
69
90
|
access_token: string;
|
package/dist/api/user/types.d.ts
CHANGED
|
@@ -6,6 +6,11 @@ export interface AuthType {
|
|
|
6
6
|
export interface LoginInfo {
|
|
7
7
|
username: string;
|
|
8
8
|
password: string;
|
|
9
|
+
/**
|
|
10
|
+
* 登录方式:local=本地口令(默认),ldap=目录登录;sso 走重定向不参与本载荷。
|
|
11
|
+
* 仅用于把 POST 路由到正确后端端点(auth/login vs auth/ldap-login),默认 local。
|
|
12
|
+
*/
|
|
13
|
+
method?: "local" | "ldap" | "sso";
|
|
9
14
|
}
|
|
10
15
|
export interface UserInfoType {
|
|
11
16
|
id: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -42,12 +42,14 @@ export type { NotificationsApiProvider, SystemApiProvider, UploadApiProvider, }
|
|
|
42
42
|
export { useAuthStore } from "./store/auth";
|
|
43
43
|
export type { AuthProvider } from "./store/auth-provider";
|
|
44
44
|
export type { HeaderProvider } from "./store/header-provider";
|
|
45
|
+
export { useSolutionRoutes } from "./store/solution-routes";
|
|
45
46
|
export { useTabsStore } from "./store/tabs";
|
|
46
47
|
export { useUserStore } from "./store/user";
|
|
47
48
|
export type { AppInfo } from "./types/app-info";
|
|
48
49
|
export { getAllExpandedKeys } from "./utils/get-all-expanded-keys";
|
|
49
50
|
export { getAppInfo } from "./utils/get-app-info";
|
|
50
51
|
export { getRedirectPath } from "./utils/get-redirect-path";
|
|
52
|
+
export { request } from "./utils/request";
|
|
51
53
|
export * from "./utils/tree";
|
|
52
54
|
export type { NoticeCategory, NoticeItem, PushBroadcastInput, PushInput, } from "@oj-module/runtime/notify";
|
|
53
55
|
export { ErrorBoundary } from "react-error-boundary";
|
|
@@ -23,6 +23,7 @@ declare const baseRoutes: ({
|
|
|
23
23
|
login?: boolean;
|
|
24
24
|
internal?: boolean;
|
|
25
25
|
hideInMenu?: boolean;
|
|
26
|
+
category?: "main" | "admin" | "hidden";
|
|
26
27
|
iframeLink?: string;
|
|
27
28
|
externalLink?: string;
|
|
28
29
|
ignoreAccess?: boolean;
|
|
@@ -71,6 +72,7 @@ declare const baseRoutes: ({
|
|
|
71
72
|
login?: boolean;
|
|
72
73
|
internal?: boolean;
|
|
73
74
|
hideInMenu?: boolean;
|
|
75
|
+
category?: "main" | "admin" | "hidden";
|
|
74
76
|
iframeLink?: string;
|
|
75
77
|
externalLink?: string;
|
|
76
78
|
ignoreAccess?: boolean;
|
package/dist/router/types.d.ts
CHANGED
|
@@ -61,6 +61,12 @@ export interface RouteMeta {
|
|
|
61
61
|
* 是否在菜单中隐藏,用于控制某些路由不在侧边栏菜单中显示
|
|
62
62
|
*/
|
|
63
63
|
hideInMenu?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 方案路由分类(P1-14/R21 三值归并,源自 sys_solution_route.category,经
|
|
66
|
+
* mergeSolutionCategories 注写):main=常规组、admin=管理组、hidden=不进菜单。
|
|
67
|
+
* 框架/后端路由未归并时缺省。
|
|
68
|
+
*/
|
|
69
|
+
category?: "main" | "admin" | "hidden";
|
|
64
70
|
/**
|
|
65
71
|
* iframe链接,如果路由需要在iframe中加载外部页面时使用
|
|
66
72
|
*/
|
|
@@ -12,6 +12,7 @@ export declare function ascending(arr: AppRouteRecordRaw[]): ({
|
|
|
12
12
|
login?: boolean;
|
|
13
13
|
internal?: boolean;
|
|
14
14
|
hideInMenu?: boolean;
|
|
15
|
+
category?: "main" | "admin" | "hidden";
|
|
15
16
|
iframeLink?: string;
|
|
16
17
|
externalLink?: string;
|
|
17
18
|
ignoreAccess?: boolean;
|
|
@@ -60,6 +61,7 @@ export declare function ascending(arr: AppRouteRecordRaw[]): ({
|
|
|
60
61
|
login?: boolean;
|
|
61
62
|
internal?: boolean;
|
|
62
63
|
hideInMenu?: boolean;
|
|
64
|
+
category?: "main" | "admin" | "hidden";
|
|
63
65
|
iframeLink?: string;
|
|
64
66
|
externalLink?: string;
|
|
65
67
|
ignoreAccess?: boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SolutionRouteRow } from "../../api/rbac/types";
|
|
2
|
+
import type { AppRouteRecordRaw } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* 归并产物:路由 + 方案分类注记(P1-14/R21 三值归并)。
|
|
5
|
+
* 形状与 AppRouteRecordRaw 相同,handle 上多出 category(及 hideInMenu/order 覆写)。
|
|
6
|
+
*/
|
|
7
|
+
export type AnnotatedRoute = AppRouteRecordRaw;
|
|
8
|
+
/**
|
|
9
|
+
* 方案路由归并(纯函数,R21):按 path 把 sys_solution_route 行注记到已注册路由上。
|
|
10
|
+
*
|
|
11
|
+
* - 三值 category 原样落 handle.category(main=常规组、admin=管理组、hidden=不进菜单);
|
|
12
|
+
* - hidden 与 enabled=0(禁用)复用既有 hideInMenu 通路——只过滤菜单层,路由仍可达
|
|
13
|
+
* (禁用的路由摘除归装载层三处同写,D12);
|
|
14
|
+
* - order 覆写为声明序:框架项保留 100 间隔带、方案项从 200 起编,共用一条序轴;
|
|
15
|
+
* - 未匹配路由(框架/后端)原样保留(同一对象引用),入参不突变;
|
|
16
|
+
* - solRoutes 为空(端点失败/未登录降级空表)时原样返回——降级不阻断,路由照常。
|
|
17
|
+
*
|
|
18
|
+
* title 不在此覆写:entry.ts 是模块元数据唯一来源(module-loader 既有惯例),
|
|
19
|
+
* title_key 随行下发仅供深检对比。
|
|
20
|
+
*/
|
|
21
|
+
export declare function mergeSolutionCategories(routes: AppRouteRecordRaw[], solRoutes: SolutionRouteRow[]): AnnotatedRoute[];
|
package/dist/runtime.js
CHANGED
|
@@ -201,7 +201,8 @@ function mapAuthPayload(data) {
|
|
|
201
201
|
};
|
|
202
202
|
}
|
|
203
203
|
function fetchLogin(data) {
|
|
204
|
-
|
|
204
|
+
const path = data.method === "ldap" ? "auth/ldap-login" : "auth/login";
|
|
205
|
+
return request.post(path, { json: data }).json().then((env) => mapAuthPayload(env.data));
|
|
205
206
|
}
|
|
206
207
|
function fetchLogout(data) {
|
|
207
208
|
return request.post("auth/logout", { json: { refresh_token: data?.refreshToken ?? "" } }).json().then(() => {});
|
|
@@ -255,10 +256,10 @@ function getAppInfo() {
|
|
|
255
256
|
return {
|
|
256
257
|
"pkg": {
|
|
257
258
|
"name": "@oj-module/runtime",
|
|
258
|
-
"version": "0.2.
|
|
259
|
+
"version": "0.2.5",
|
|
259
260
|
"license": "MIT"
|
|
260
261
|
},
|
|
261
|
-
"lastBuildTime": "2026-10-
|
|
262
|
+
"lastBuildTime": "2026-10-19 10:55:08"
|
|
262
263
|
};
|
|
263
264
|
}
|
|
264
265
|
var init_get_app_info = __esmMin((() => {}));
|
|
@@ -8321,6 +8322,39 @@ function generateMenuItemsFromRoutes(routeList, parentPath = "/") {
|
|
|
8321
8322
|
}
|
|
8322
8323
|
var init_generate_menu_items_from_routes = __esmMin((() => {}));
|
|
8323
8324
|
//#endregion
|
|
8325
|
+
//#region src/router/utils/merge-solution-categories.ts
|
|
8326
|
+
/**
|
|
8327
|
+
* 方案路由归并(纯函数,R21):按 path 把 sys_solution_route 行注记到已注册路由上。
|
|
8328
|
+
*
|
|
8329
|
+
* - 三值 category 原样落 handle.category(main=常规组、admin=管理组、hidden=不进菜单);
|
|
8330
|
+
* - hidden 与 enabled=0(禁用)复用既有 hideInMenu 通路——只过滤菜单层,路由仍可达
|
|
8331
|
+
* (禁用的路由摘除归装载层三处同写,D12);
|
|
8332
|
+
* - order 覆写为声明序:框架项保留 100 间隔带、方案项从 200 起编,共用一条序轴;
|
|
8333
|
+
* - 未匹配路由(框架/后端)原样保留(同一对象引用),入参不突变;
|
|
8334
|
+
* - solRoutes 为空(端点失败/未登录降级空表)时原样返回——降级不阻断,路由照常。
|
|
8335
|
+
*
|
|
8336
|
+
* title 不在此覆写:entry.ts 是模块元数据唯一来源(module-loader 既有惯例),
|
|
8337
|
+
* title_key 随行下发仅供深检对比。
|
|
8338
|
+
*/
|
|
8339
|
+
function mergeSolutionCategories(routes, solRoutes) {
|
|
8340
|
+
if (solRoutes.length === 0) return routes;
|
|
8341
|
+
const byPath = new Map(solRoutes.map((r) => [r.path, r]));
|
|
8342
|
+
return routes.map((route) => {
|
|
8343
|
+
const row = route.path ? byPath.get(route.path) : void 0;
|
|
8344
|
+
if (!row) return route;
|
|
8345
|
+
return {
|
|
8346
|
+
...route,
|
|
8347
|
+
handle: {
|
|
8348
|
+
...route.handle,
|
|
8349
|
+
category: row.category,
|
|
8350
|
+
order: row.order,
|
|
8351
|
+
hideInMenu: row.category === "hidden" || !row.enabled || (route.handle.hideInMenu ?? false)
|
|
8352
|
+
}
|
|
8353
|
+
};
|
|
8354
|
+
});
|
|
8355
|
+
}
|
|
8356
|
+
var init_merge_solution_categories = __esmMin((() => {}));
|
|
8357
|
+
//#endregion
|
|
8324
8358
|
//#region src/router/utils/resolve-login-route.ts
|
|
8325
8359
|
/**
|
|
8326
8360
|
* 内外 login 路由去重(P3,login 模块化):唯一合成入口(SRP/DRY),
|
|
@@ -8380,18 +8414,20 @@ var init_access = __esmMin((() => {
|
|
|
8380
8414
|
init_ascending();
|
|
8381
8415
|
init_flatten_routes();
|
|
8382
8416
|
init_generate_menu_items_from_routes();
|
|
8417
|
+
init_merge_solution_categories();
|
|
8383
8418
|
init_resolve_login_route();
|
|
8384
8419
|
initialState$1 = {
|
|
8385
8420
|
wholeMenus: generateMenuItemsFromRoutes(baseRoutes),
|
|
8386
8421
|
routeList: baseRoutes,
|
|
8387
8422
|
flatRouteList: flattenRoutes(baseRoutes),
|
|
8388
|
-
isAccessChecked: false
|
|
8423
|
+
isAccessChecked: false,
|
|
8424
|
+
solutionRoutes: []
|
|
8389
8425
|
};
|
|
8390
8426
|
lastRegisteredRoutes = [];
|
|
8391
|
-
useAccessStore = create((set) => ({
|
|
8427
|
+
useAccessStore = create((set, get) => ({
|
|
8392
8428
|
...initialState$1,
|
|
8393
8429
|
setAccessStore: (routes) => {
|
|
8394
|
-
const newRoutes = ascending([...resolveLoginRoute(baseRoutes, routes, router, rootRoute), ...routes]);
|
|
8430
|
+
const newRoutes = ascending([...resolveLoginRoute(baseRoutes, routes, router, rootRoute), ...mergeSolutionCategories(routes, get().solutionRoutes)]);
|
|
8395
8431
|
router.patchRoutes(ROOT_ROUTE_ID, routes);
|
|
8396
8432
|
const flatRouteList = flattenRoutes(newRoutes);
|
|
8397
8433
|
const newState = {
|
|
@@ -8404,6 +8440,10 @@ var init_access = __esmMin((() => {
|
|
|
8404
8440
|
set(() => newState);
|
|
8405
8441
|
return newState;
|
|
8406
8442
|
},
|
|
8443
|
+
setSolutionRoutes: (rows) => {
|
|
8444
|
+
set({ solutionRoutes: rows });
|
|
8445
|
+
if (lastRegisteredRoutes.length > 0) get().setAccessStore(lastRegisteredRoutes);
|
|
8446
|
+
},
|
|
8407
8447
|
reset: () => {
|
|
8408
8448
|
router._internalSetRoutes(rootRoute);
|
|
8409
8449
|
set(initialState$1);
|
|
@@ -8739,7 +8779,10 @@ var init_request = __esmMin((() => {
|
|
|
8739
8779
|
}
|
|
8740
8780
|
}
|
|
8741
8781
|
return refreshTokenAndRetry(request, options, refreshToken);
|
|
8742
|
-
} else
|
|
8782
|
+
} else {
|
|
8783
|
+
if (options.silentError) return response;
|
|
8784
|
+
return handleErrorResponse(response);
|
|
8785
|
+
}
|
|
8743
8786
|
}
|
|
8744
8787
|
return response;
|
|
8745
8788
|
}]
|
|
@@ -8777,11 +8820,13 @@ function fetchRbacOplog(query) {
|
|
|
8777
8820
|
for (const [k, v] of Object.entries(query)) if (v != null && v !== "") sp.set(k, String(v));
|
|
8778
8821
|
return get(`system/oplog?${sp.toString()}`);
|
|
8779
8822
|
}
|
|
8823
|
+
var fetchRbacOplogPost = (body) => post("system/oplog", body);
|
|
8780
8824
|
var fetchRbacSettings = () => get("system/settings");
|
|
8781
8825
|
var fetchRbacUpdateSetting = (key, value) => put("system/settings", {
|
|
8782
8826
|
key,
|
|
8783
8827
|
value
|
|
8784
8828
|
});
|
|
8829
|
+
var fetchSolutionRoutes = () => get("_platform/solutions/routes");
|
|
8785
8830
|
function fetchRbacContacts(keyword, limit) {
|
|
8786
8831
|
return get(`_platform/contacts?keyword=${encodeURIComponent(keyword)}${limit ? `&limit=${limit}` : ""}`);
|
|
8787
8832
|
}
|
|
@@ -8827,6 +8872,46 @@ function groupByModule(items) {
|
|
|
8827
8872
|
items
|
|
8828
8873
|
}));
|
|
8829
8874
|
}
|
|
8875
|
+
/**
|
|
8876
|
+
* 框架自有设置模块(seed.sql 现行集合;新增框架设置模块须同步)。
|
|
8877
|
+
* 方案设置经安装预检强制 `moduleOf(key)===name`(R24),落库 module 列即方案名——
|
|
8878
|
+
* 据此把 sys_setting 行二分为框架区(维持按 group 聚合的现状渲染)与方案区(按模块三层嵌套)。
|
|
8879
|
+
*/
|
|
8880
|
+
var FRAMEWORK_SETTING_MODULES = /* @__PURE__ */ new Set([
|
|
8881
|
+
"framework",
|
|
8882
|
+
"market",
|
|
8883
|
+
"ldap",
|
|
8884
|
+
"sso"
|
|
8885
|
+
]);
|
|
8886
|
+
/**
|
|
8887
|
+
* 设置行按模块三层嵌套分组(R20/R24,纯函数):框架卡在前(按 group 列聚合、保持服务端
|
|
8888
|
+
* `order by group, key` 次序),方案卡在后(module 名升序、组内按 group 列聚合)。
|
|
8889
|
+
* 不按 key 首段切组——框架 seed 存在无点号键(ldap_base_dn),首段不是其模块名;
|
|
8890
|
+
* module 列是落库的所有权真源。空行降级返回空数组。
|
|
8891
|
+
*/
|
|
8892
|
+
function groupSettingsByModule(rows) {
|
|
8893
|
+
const framework = /* @__PURE__ */ new Map();
|
|
8894
|
+
const solutions = /* @__PURE__ */ new Map();
|
|
8895
|
+
for (const item of rows) if (FRAMEWORK_SETTING_MODULES.has(item.module)) (framework.get(item.group) ?? framework.set(item.group, []).get(item.group)).push(item);
|
|
8896
|
+
else {
|
|
8897
|
+
const groups = solutions.get(item.module) ?? solutions.set(item.module, /* @__PURE__ */ new Map()).get(item.module);
|
|
8898
|
+
(groups.get(item.group) ?? groups.set(item.group, []).get(item.group)).push(item);
|
|
8899
|
+
}
|
|
8900
|
+
const cards = [];
|
|
8901
|
+
for (const [group, items] of framework) cards.push({
|
|
8902
|
+
module: null,
|
|
8903
|
+
group,
|
|
8904
|
+
label_key: null,
|
|
8905
|
+
items
|
|
8906
|
+
});
|
|
8907
|
+
for (const module of [...solutions.keys()].sort()) for (const [group, items] of solutions.get(module)) cards.push({
|
|
8908
|
+
module,
|
|
8909
|
+
group,
|
|
8910
|
+
label_key: `${module}:settings.group.${group}`,
|
|
8911
|
+
items
|
|
8912
|
+
});
|
|
8913
|
+
return cards;
|
|
8914
|
+
}
|
|
8830
8915
|
//#endregion
|
|
8831
8916
|
//#region src/api/system/menu/index.ts
|
|
8832
8917
|
init_api_provider();
|
|
@@ -9545,6 +9630,55 @@ function defineModule(definition) {
|
|
|
9545
9630
|
return definition;
|
|
9546
9631
|
}
|
|
9547
9632
|
//#endregion
|
|
9633
|
+
//#region src/store/solution-routes.ts
|
|
9634
|
+
init_access();
|
|
9635
|
+
init_auth();
|
|
9636
|
+
var useSolutionRoutes = create((set) => ({
|
|
9637
|
+
routes: [],
|
|
9638
|
+
loaded: false,
|
|
9639
|
+
refresh: async () => {
|
|
9640
|
+
try {
|
|
9641
|
+
const routes = await fetchSolutionRoutes();
|
|
9642
|
+
set({
|
|
9643
|
+
routes,
|
|
9644
|
+
loaded: true
|
|
9645
|
+
});
|
|
9646
|
+
useAccessStore.getState().setSolutionRoutes(routes);
|
|
9647
|
+
} catch {
|
|
9648
|
+
set({
|
|
9649
|
+
routes: [],
|
|
9650
|
+
loaded: true
|
|
9651
|
+
});
|
|
9652
|
+
useAccessStore.getState().setSolutionRoutes([]);
|
|
9653
|
+
}
|
|
9654
|
+
},
|
|
9655
|
+
reset: () => {
|
|
9656
|
+
set({
|
|
9657
|
+
routes: [],
|
|
9658
|
+
loaded: false
|
|
9659
|
+
});
|
|
9660
|
+
useAccessStore.getState().setSolutionRoutes([]);
|
|
9661
|
+
}
|
|
9662
|
+
}));
|
|
9663
|
+
/**
|
|
9664
|
+
* token 就绪监视(R21):登录成功(token 翻转)强制重拉一次;登出清空行并解除归并。
|
|
9665
|
+
* 幂等(armed 防重),模块导入即武装——宿主链(shell 无 AuthGuard)同样生效。
|
|
9666
|
+
*/
|
|
9667
|
+
var armed = false;
|
|
9668
|
+
function watchTokenReady() {
|
|
9669
|
+
if (armed) return;
|
|
9670
|
+
armed = true;
|
|
9671
|
+
let lastToken = useAuthStore.getState().token;
|
|
9672
|
+
if (lastToken) useSolutionRoutes.getState().refresh();
|
|
9673
|
+
useAuthStore.subscribe((state) => {
|
|
9674
|
+
if (state.token === lastToken) return;
|
|
9675
|
+
lastToken = state.token;
|
|
9676
|
+
if (state.token) useSolutionRoutes.getState().refresh();
|
|
9677
|
+
else useSolutionRoutes.getState().reset();
|
|
9678
|
+
});
|
|
9679
|
+
}
|
|
9680
|
+
watchTokenReady();
|
|
9681
|
+
//#endregion
|
|
9548
9682
|
//#region src/utils/get-all-expanded-keys/index.ts
|
|
9549
9683
|
function getAllExpandedKeys(data, fieldName = "key") {
|
|
9550
9684
|
return data.flatMap((item) => [item[fieldName], ...item.children?.length ? getAllExpandedKeys(item.children, fieldName) : []]);
|
|
@@ -27594,10 +27728,11 @@ init_tabs();
|
|
|
27594
27728
|
init_user();
|
|
27595
27729
|
init_get_app_info();
|
|
27596
27730
|
init_get_redirect_path();
|
|
27731
|
+
init_request();
|
|
27597
27732
|
init_user$1();
|
|
27598
27733
|
init_local_icons();
|
|
27599
27734
|
init_ri();
|
|
27600
27735
|
init_menu_icons();
|
|
27601
27736
|
init_tree();
|
|
27602
27737
|
//#endregion
|
|
27603
|
-
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, bindingDiff, canAssignRole, canDeleteRole, canEditRoleBindings, defineModule, fetchAddMenuItem, fetchAddRoleItem, fetchAsyncRoutes, fetchChangePassword, fetchDeleteMenuItem, fetchDeleteRoleItem, fetchLdapLogin, fetchLogin, fetchLoginMethods, fetchLogout, fetchMenuByRoleId, fetchMenuList, fetchRbacAdminResetPassword, fetchRbacContactDetail, fetchRbacContacts, fetchRbacCreateRole, fetchRbacCreateUser, fetchRbacDeleteRole, fetchRbacOplog, fetchRbacPermissionList, fetchRbacRoleList, fetchRbacSetForbidden, fetchRbacSettings, fetchRbacUpdateBindings, fetchRbacUpdateSetting, fetchRbacUpdateUserRoles, fetchRbacUserList, fetchRefreshToken, fetchRoleList, fetchRoleMenu, fetchUpdateMenuItem, fetchUpdateRoleItem, fetchUserInfo, filterTree, getAllExpandedKeys, getAppInfo, getBooleanOptions, getModule, getModules, getRedirectPath, getRegisteredApiPrefix, getRegisteredStore, getRoutes, getYesNoOptions, groupByModule, handleTree, loadAll, mapTree, menuIcons, notify, permissionPrefix, roleLabel, setupI18n, traverseTreeValues, unloadModule, useAccess, useAuthStore, usePreferences, useSlotNodes, useTabKey, useTabsStore, useUserStore, external_exports as z };
|
|
27738
|
+
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, bindingDiff, canAssignRole, canDeleteRole, canEditRoleBindings, defineModule, fetchAddMenuItem, fetchAddRoleItem, fetchAsyncRoutes, fetchChangePassword, fetchDeleteMenuItem, fetchDeleteRoleItem, fetchLdapLogin, fetchLogin, fetchLoginMethods, fetchLogout, fetchMenuByRoleId, fetchMenuList, fetchRbacAdminResetPassword, fetchRbacContactDetail, fetchRbacContacts, fetchRbacCreateRole, fetchRbacCreateUser, fetchRbacDeleteRole, fetchRbacOplog, fetchRbacOplogPost, fetchRbacPermissionList, fetchRbacRoleList, fetchRbacSetForbidden, fetchRbacSettings, fetchRbacUpdateBindings, fetchRbacUpdateSetting, fetchRbacUpdateUserRoles, fetchRbacUserList, fetchRefreshToken, fetchRoleList, fetchRoleMenu, fetchSolutionRoutes, fetchUpdateMenuItem, fetchUpdateRoleItem, fetchUserInfo, filterTree, getAllExpandedKeys, getAppInfo, getBooleanOptions, getModule, getModules, getRedirectPath, getRegisteredApiPrefix, getRegisteredStore, getRoutes, getYesNoOptions, groupByModule, groupSettingsByModule, handleTree, loadAll, mapTree, menuIcons, notify, permissionPrefix, request, roleLabel, setupI18n, traverseTreeValues, unloadModule, useAccess, useAuthStore, usePreferences, useSlotNodes, useSolutionRoutes, useTabKey, useTabsStore, useUserStore, external_exports as z };
|
package/dist/store/access.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SolutionRouteRow } from "../api/rbac/types";
|
|
1
2
|
import type { MenuItemType } from "../layout/layout-menu/types";
|
|
2
3
|
import type { AppRouteRecordRaw } from "../router/types";
|
|
3
4
|
interface AccessState {
|
|
@@ -5,9 +6,12 @@ interface AccessState {
|
|
|
5
6
|
routeList: AppRouteRecordRaw[];
|
|
6
7
|
flatRouteList: Record<string, AppRouteRecordRaw>;
|
|
7
8
|
isAccessChecked: boolean;
|
|
9
|
+
solutionRoutes: SolutionRouteRow[];
|
|
8
10
|
}
|
|
9
11
|
interface AccessAction {
|
|
10
|
-
setAccessStore: (routes: AppRouteRecordRaw[]) => AccessState
|
|
12
|
+
setAccessStore: (routes: AppRouteRecordRaw[]) => Omit<AccessState, "solutionRoutes">;
|
|
13
|
+
/** 方案路由行推送(useSolutionRoutes 就绪/清空时调用),推送后按快照重归并(R21) */
|
|
14
|
+
setSolutionRoutes: (rows: SolutionRouteRow[]) => void;
|
|
11
15
|
reset: () => void;
|
|
12
16
|
}
|
|
13
17
|
export declare const useAccessStore: import("zustand").UseBoundStore<import("zustand").StoreApi<AccessState & AccessAction>>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { SolutionRouteRow } from "../api/rbac/types";
|
|
2
|
+
/**
|
|
3
|
+
* 方案路由归并 store(P1-14,R21 独立缓存 store)。
|
|
4
|
+
*
|
|
5
|
+
* 职责:登录即可只读端点(GET /api/_platform/solutions/routes)的唯一前端消费口——
|
|
6
|
+
* - token 就绪强制重拉一次(首登会话归并补齐;现状菜单登记在登录前且 alreadyRegistered
|
|
7
|
+
* 跳过,无此补拉则首登永久降级为无分类,R21);
|
|
8
|
+
* - 端点失败/未登录降级空表不炸(按无分类渲染,路由照常,R21 降级不阻断);
|
|
9
|
+
* - 行就绪即推送 access store(setSolutionRoutes)触发按快照重归并。
|
|
10
|
+
*/
|
|
11
|
+
interface SolutionRoutesState {
|
|
12
|
+
/** 未 deprecated 方案路由行(降级时为空表) */
|
|
13
|
+
routes: SolutionRouteRow[];
|
|
14
|
+
/** 已完成过一次拉取(成功或失败) */
|
|
15
|
+
loaded: boolean;
|
|
16
|
+
refresh: () => Promise<void>;
|
|
17
|
+
reset: () => void;
|
|
18
|
+
}
|
|
19
|
+
export declare const useSolutionRoutes: import("zustand").UseBoundStore<import("zustand").StoreApi<SolutionRoutesState>>;
|
|
20
|
+
export declare function watchTokenReady(): void;
|
|
21
|
+
export {};
|