@litianxiang/portal-core 0.1.9 → 0.1.10
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/README.md +53 -2
- package/dist/index.d.ts +23 -1
- package/dist/index.js +58 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,7 +34,8 @@ import {
|
|
|
34
34
|
createAppRouter,
|
|
35
35
|
createLogoutToAuth,
|
|
36
36
|
calcInactivityAction,
|
|
37
|
-
createAuthHttpClient
|
|
37
|
+
createAuthHttpClient,
|
|
38
|
+
createPermissionHelper
|
|
38
39
|
} from '@litianxiang/portal-core'
|
|
39
40
|
```
|
|
40
41
|
|
|
@@ -105,6 +106,26 @@ function createAuthHttpClient(options: CreateAuthHttpClientOptions): {
|
|
|
105
106
|
logoutToAuth: () => void // 同 createLogoutToAuth,便于复用
|
|
106
107
|
}
|
|
107
108
|
```
|
|
109
|
+
|
|
110
|
+
`permission` 相关工具简化说明:
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
interface PermissionHelperOptions {
|
|
114
|
+
// 返回用户 Store 实例,需至少提供 getUserALLMenu 或 getUserPageMenu
|
|
115
|
+
getUserStore: () => any
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
interface PermissionHelper {
|
|
119
|
+
// 判断是否拥有某个页面(路由)权限
|
|
120
|
+
hasPagePermission: (path: string) => boolean
|
|
121
|
+
// 判断是否拥有某个按钮权限(约定使用菜单 path 作为唯一标识)
|
|
122
|
+
hasButtonPermission: (codeOrPath: string) => boolean
|
|
123
|
+
// 判断是否拥有给定列表中的任意一个权限
|
|
124
|
+
hasAnyPermission: (codesOrPaths: string[]) => boolean
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function createPermissionHelper(options: PermissionHelperOptions): PermissionHelper
|
|
128
|
+
```
|
|
108
129
|
```
|
|
109
130
|
|
|
110
131
|
## 子系统接入步骤
|
|
@@ -283,7 +304,37 @@ export { logoutToAuth }
|
|
|
283
304
|
|
|
284
305
|
如需完全自定义 http 行为,也可以直接基于前面的 `auth` 工具自行编写拦截器。
|
|
285
306
|
|
|
286
|
-
### 7
|
|
307
|
+
### 7.(可选)接入菜单 / 按钮权限判断
|
|
308
|
+
|
|
309
|
+
在需要做“是否显示某个按钮”或“是否放行某个页面”时,可以使用 `createPermissionHelper` 来基于菜单数据做权限判断:
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
// 例如在某个业务系统的全局 helper 中:
|
|
313
|
+
import { createPermissionHelper } from '@litianxiang/portal-core'
|
|
314
|
+
import { useUserStore } from '@/stores/user'
|
|
315
|
+
|
|
316
|
+
const permission = createPermissionHelper({
|
|
317
|
+
getUserStore: () => useUserStore()
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
// 页面/路由级权限判断(基于菜单的 path,忽略 query 部分)
|
|
321
|
+
permission.hasPagePermission('/system/menu')
|
|
322
|
+
|
|
323
|
+
// 按钮权限判断(约定后台为按钮类型菜单配置唯一的 path 作为权限码)
|
|
324
|
+
permission.hasButtonPermission('/system/menu:add')
|
|
325
|
+
|
|
326
|
+
// 任一权限命中即通过(可用于复杂场景)
|
|
327
|
+
permission.hasAnyPermission([
|
|
328
|
+
'/system/menu:add',
|
|
329
|
+
'/system/menu:edit'
|
|
330
|
+
])
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
> 说明:
|
|
334
|
+
> - `createPermissionHelper` 内部会优先使用 `userStore.getUserPageMenu`(包含 page + button),若不存在则退回 `userStore.getUserALLMenu`;
|
|
335
|
+
> - 匹配时仅按基础路径(去掉 `?query`)比较,避免 query 影响权限判断。
|
|
336
|
+
|
|
337
|
+
### 8. 项目视图目录约定
|
|
287
338
|
|
|
288
339
|
`portal-core` 会根据后端菜单返回的 `path` 去匹配前端视图,规则如下:
|
|
289
340
|
|
package/dist/index.d.ts
CHANGED
|
@@ -68,4 +68,26 @@ declare function createAuthHttpClient(options: CreateAuthHttpClientOptions): {
|
|
|
68
68
|
logoutToAuth: () => void;
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
interface PermissionHelperOptions {
|
|
72
|
+
/** 返回用户 Store 实例,需至少提供 getUserALLMenu 或 getUserPageMenu */
|
|
73
|
+
getUserStore: () => any;
|
|
74
|
+
}
|
|
75
|
+
interface PermissionHelper {
|
|
76
|
+
/**
|
|
77
|
+
* 判断当前用户是否拥有某个页面(路由)权限
|
|
78
|
+
* @param path 完整路径,支持携带 query(内部只按基础路径匹配)
|
|
79
|
+
*/
|
|
80
|
+
hasPagePermission: (path: string) => boolean;
|
|
81
|
+
/**
|
|
82
|
+
* 判断当前用户是否拥有某个按钮权限
|
|
83
|
+
* 约定:按钮权限同样使用菜单的 path 字段作为唯一标识
|
|
84
|
+
*/
|
|
85
|
+
hasButtonPermission: (codeOrPath: string) => boolean;
|
|
86
|
+
/**
|
|
87
|
+
* 判断当前用户是否拥有给定列表中的任意一个权限(页面或按钮)
|
|
88
|
+
*/
|
|
89
|
+
hasAnyPermission: (codesOrPaths: string[]) => boolean;
|
|
90
|
+
}
|
|
91
|
+
declare function createPermissionHelper(options: PermissionHelperOptions): PermissionHelper;
|
|
92
|
+
|
|
93
|
+
export { type AppRouterOptions, type CreateAuthHttpClientOptions, type InactivityConfig, type InactivityResult, type LogoutToAuthOptions, type PermissionHelper, type PermissionHelperOptions, calcInactivityAction, createAppRouter, createAuthHttpClient, createLogoutToAuth, createPermissionHelper };
|
package/dist/index.js
CHANGED
|
@@ -370,9 +370,66 @@ function createAuthHttpClient(options) {
|
|
|
370
370
|
);
|
|
371
371
|
return { http, logoutToAuth };
|
|
372
372
|
}
|
|
373
|
+
|
|
374
|
+
// src/permission.ts
|
|
375
|
+
function normalizePath(raw) {
|
|
376
|
+
if (!raw) return "";
|
|
377
|
+
const [base] = raw.split("?");
|
|
378
|
+
if (!base) return "";
|
|
379
|
+
return base.startsWith("/") ? base : `/${base}`;
|
|
380
|
+
}
|
|
381
|
+
function findMenuByPath(menuList, targetPath, category) {
|
|
382
|
+
const target = normalizePath(targetPath);
|
|
383
|
+
if (!target || !Array.isArray(menuList)) return null;
|
|
384
|
+
for (const item of menuList) {
|
|
385
|
+
const current = normalizePath(item?.path);
|
|
386
|
+
if (current === target) {
|
|
387
|
+
if (!category || item?.category === category) {
|
|
388
|
+
return item;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
if (item?.children && item.children.length > 0) {
|
|
392
|
+
const found = findMenuByPath(item.children, targetPath, category);
|
|
393
|
+
if (found) return found;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
function createPermissionHelper(options) {
|
|
399
|
+
const { getUserStore } = options;
|
|
400
|
+
const getMenuTree = () => {
|
|
401
|
+
const userStore = getUserStore();
|
|
402
|
+
const pageMenu = userStore?.getUserPageMenu;
|
|
403
|
+
const allMenu = userStore?.getUserALLMenu;
|
|
404
|
+
if (Array.isArray(pageMenu)) return pageMenu;
|
|
405
|
+
if (Array.isArray(allMenu)) return allMenu;
|
|
406
|
+
return [];
|
|
407
|
+
};
|
|
408
|
+
const hasPagePermission = (path) => {
|
|
409
|
+
const menuTree = getMenuTree();
|
|
410
|
+
const item = findMenuByPath(menuTree, path);
|
|
411
|
+
if (!item) return false;
|
|
412
|
+
return item.category === "page" || item.category === "flow-page";
|
|
413
|
+
};
|
|
414
|
+
const hasButtonPermission = (codeOrPath) => {
|
|
415
|
+
const menuTree = getMenuTree();
|
|
416
|
+
const item = findMenuByPath(menuTree, codeOrPath, "button");
|
|
417
|
+
return !!item;
|
|
418
|
+
};
|
|
419
|
+
const hasAnyPermission = (codesOrPaths) => {
|
|
420
|
+
if (!Array.isArray(codesOrPaths) || codesOrPaths.length === 0) return false;
|
|
421
|
+
return codesOrPaths.some((code) => hasPagePermission(code) || hasButtonPermission(code));
|
|
422
|
+
};
|
|
423
|
+
return {
|
|
424
|
+
hasPagePermission,
|
|
425
|
+
hasButtonPermission,
|
|
426
|
+
hasAnyPermission
|
|
427
|
+
};
|
|
428
|
+
}
|
|
373
429
|
export {
|
|
374
430
|
calcInactivityAction,
|
|
375
431
|
createAppRouter,
|
|
376
432
|
createAuthHttpClient,
|
|
377
|
-
createLogoutToAuth
|
|
433
|
+
createLogoutToAuth,
|
|
434
|
+
createPermissionHelper
|
|
378
435
|
};
|