@litianxiang/portal-core 0.1.21 → 0.1.23
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 +312 -269
- package/dist/index.d.ts +191 -8
- package/dist/index.js +518 -198
- package/package.json +17 -3
- package/dist/index.cjs +0 -183
package/dist/index.js
CHANGED
|
@@ -1,7 +1,207 @@
|
|
|
1
1
|
// src/router/router.ts
|
|
2
2
|
import { createRouter, createWebHashHistory } from "vue-router";
|
|
3
|
+
|
|
4
|
+
// src/menu/menu.ts
|
|
5
|
+
function normalizePath(raw) {
|
|
6
|
+
if (!raw) return "";
|
|
7
|
+
const [base] = raw.split("?");
|
|
8
|
+
if (!base) return "";
|
|
9
|
+
return base.startsWith("/") ? base : `/${base}`;
|
|
10
|
+
}
|
|
11
|
+
function _findMenuByPath(menuList, targetPath) {
|
|
12
|
+
const target = normalizePath(targetPath);
|
|
13
|
+
if (!target || !Array.isArray(menuList)) return null;
|
|
14
|
+
for (const item of menuList) {
|
|
15
|
+
const current = normalizePath(item?.path);
|
|
16
|
+
if (current === target) {
|
|
17
|
+
return item;
|
|
18
|
+
}
|
|
19
|
+
if (item?.children && item.children.length > 0) {
|
|
20
|
+
const found = _findMenuByPath(item.children, targetPath);
|
|
21
|
+
if (found) return found;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
function _findMenuChain(menuList, targetPath, parentChain = []) {
|
|
27
|
+
const target = normalizePath(targetPath);
|
|
28
|
+
if (!target || !Array.isArray(menuList)) return [];
|
|
29
|
+
for (const menu of menuList) {
|
|
30
|
+
const current = normalizePath(menu?.path);
|
|
31
|
+
const chain = [...parentChain, menu];
|
|
32
|
+
if (current === target) {
|
|
33
|
+
return chain;
|
|
34
|
+
}
|
|
35
|
+
if (menu?.children && menu.children.length > 0) {
|
|
36
|
+
const result = _findMenuChain(menu.children, targetPath, chain);
|
|
37
|
+
if (result.length > 0) return result;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
function _findParentMenuIds(menuList, targetPath, parentIds = []) {
|
|
43
|
+
const target = normalizePath(targetPath);
|
|
44
|
+
if (!target || !Array.isArray(menuList)) return [];
|
|
45
|
+
for (const menu of menuList) {
|
|
46
|
+
const current = normalizePath(menu?.path);
|
|
47
|
+
if (menu?.children && menu.children.length > 0) {
|
|
48
|
+
const currentIds = [...parentIds, menu.id];
|
|
49
|
+
const result = _findParentMenuIds(menu.children, targetPath, currentIds);
|
|
50
|
+
if (result.length > 0) return result;
|
|
51
|
+
} else if (current === target) {
|
|
52
|
+
return parentIds;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
function createMenuHelper(options) {
|
|
58
|
+
const { getMenuTree } = options;
|
|
59
|
+
const findMenuByPath2 = (path) => {
|
|
60
|
+
const tree = getMenuTree() || [];
|
|
61
|
+
return _findMenuByPath(tree, path);
|
|
62
|
+
};
|
|
63
|
+
const getMenuTitle = (path) => {
|
|
64
|
+
const item = findMenuByPath2(path);
|
|
65
|
+
return item?.name || null;
|
|
66
|
+
};
|
|
67
|
+
const getMenuChain = (path) => {
|
|
68
|
+
const tree = getMenuTree() || [];
|
|
69
|
+
return _findMenuChain(tree, path);
|
|
70
|
+
};
|
|
71
|
+
const getParentMenuIds = (path) => {
|
|
72
|
+
const tree = getMenuTree() || [];
|
|
73
|
+
return _findParentMenuIds(tree, path);
|
|
74
|
+
};
|
|
75
|
+
const getBreadcrumb = (path) => {
|
|
76
|
+
const chain = getMenuChain(path);
|
|
77
|
+
return chain.map((item) => ({
|
|
78
|
+
title: item?.name ?? "",
|
|
79
|
+
path: item?.path ?? ""
|
|
80
|
+
}));
|
|
81
|
+
};
|
|
82
|
+
return {
|
|
83
|
+
findMenuByPath: findMenuByPath2,
|
|
84
|
+
getMenuTitle,
|
|
85
|
+
getMenuChain,
|
|
86
|
+
getParentMenuIds,
|
|
87
|
+
getBreadcrumb
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function transformMenuTree(menuList, options) {
|
|
91
|
+
const defaultSite = options?.defaultSite;
|
|
92
|
+
return (menuList || []).map((item) => {
|
|
93
|
+
const children = Array.isArray(item?.children) ? transformMenuTree(item.children, options) : void 0;
|
|
94
|
+
return {
|
|
95
|
+
id: item?.id,
|
|
96
|
+
parent_id: item?.parent_id ?? null,
|
|
97
|
+
category: item?.category,
|
|
98
|
+
name: item?.name,
|
|
99
|
+
path: item?.path,
|
|
100
|
+
icon: item?.icon,
|
|
101
|
+
order_num: item?.order_num,
|
|
102
|
+
site: item?.site ?? defaultSite,
|
|
103
|
+
children
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function buildAllMenuTree(menuList) {
|
|
108
|
+
const result = [];
|
|
109
|
+
for (const item of menuList || []) {
|
|
110
|
+
result.push({
|
|
111
|
+
id: item.id,
|
|
112
|
+
parent_id: item.parent_id ?? null,
|
|
113
|
+
category: item.category,
|
|
114
|
+
name: item.name,
|
|
115
|
+
path: item.path,
|
|
116
|
+
icon: item.icon,
|
|
117
|
+
order_num: item.order_num,
|
|
118
|
+
site: item.site,
|
|
119
|
+
children: item.children && item.children.length > 0 ? buildAllMenuTree(item.children) : []
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
function buildPageMenuList(menuList) {
|
|
125
|
+
const pages = [];
|
|
126
|
+
for (const item of menuList || []) {
|
|
127
|
+
if (item.category !== "module") {
|
|
128
|
+
pages.push({
|
|
129
|
+
id: item.id,
|
|
130
|
+
parent_id: item.parent_id ?? null,
|
|
131
|
+
category: item.category,
|
|
132
|
+
name: item.name,
|
|
133
|
+
path: item.path,
|
|
134
|
+
icon: item.icon,
|
|
135
|
+
order_num: item.order_num,
|
|
136
|
+
site: item.site,
|
|
137
|
+
children: item.children ? buildPageMenuList(item.children) : []
|
|
138
|
+
});
|
|
139
|
+
} else if (item.children && item.children.length > 0) {
|
|
140
|
+
const childMenus = buildPageMenuList(item.children);
|
|
141
|
+
if (childMenus.length > 0) {
|
|
142
|
+
for (const child of childMenus) {
|
|
143
|
+
pages.push({
|
|
144
|
+
id: child.id,
|
|
145
|
+
parent_id: child.parent_id ?? null,
|
|
146
|
+
category: child.category,
|
|
147
|
+
name: child.name,
|
|
148
|
+
path: child.path,
|
|
149
|
+
icon: child.icon,
|
|
150
|
+
order_num: child.order_num,
|
|
151
|
+
site: child.site,
|
|
152
|
+
children: child.children
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return pages;
|
|
159
|
+
}
|
|
160
|
+
function findFirstPagePath(menuList) {
|
|
161
|
+
for (const item of menuList || []) {
|
|
162
|
+
if (item.category === "page" && item.path) {
|
|
163
|
+
return item.path;
|
|
164
|
+
}
|
|
165
|
+
if (item.children && item.children.length > 0) {
|
|
166
|
+
const childFirst = findFirstPagePath(item.children);
|
|
167
|
+
if (childFirst) return childFirst;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/router/router.ts
|
|
3
174
|
function createAppRouter(options) {
|
|
4
|
-
const {
|
|
175
|
+
const {
|
|
176
|
+
staticRoutes,
|
|
177
|
+
getUserStore,
|
|
178
|
+
getFirstPage,
|
|
179
|
+
authLoginUrl,
|
|
180
|
+
enableUrlTokenRecovery = false
|
|
181
|
+
} = options;
|
|
182
|
+
const trySyncTokenFromUrl = (userStore) => {
|
|
183
|
+
if (typeof window === "undefined") return false;
|
|
184
|
+
const url = new URL(window.location.href);
|
|
185
|
+
const accessToken = url.searchParams.get("access_token");
|
|
186
|
+
const refreshToken = url.searchParams.get("refresh_token");
|
|
187
|
+
const lastActiveTime = Number(url.searchParams.get("last_active_time") || Date.now());
|
|
188
|
+
if (!accessToken) return false;
|
|
189
|
+
userStore.setUserAccessToken?.(accessToken);
|
|
190
|
+
if (refreshToken) {
|
|
191
|
+
userStore.setUserRefreshToken?.(refreshToken);
|
|
192
|
+
}
|
|
193
|
+
userStore.setUserLastActiveTime?.(Number.isFinite(lastActiveTime) ? lastActiveTime : Date.now());
|
|
194
|
+
url.searchParams.delete("access_token");
|
|
195
|
+
url.searchParams.delete("refresh_token");
|
|
196
|
+
url.searchParams.delete("last_active_time");
|
|
197
|
+
window.history.replaceState({}, "", url.toString());
|
|
198
|
+
return true;
|
|
199
|
+
};
|
|
200
|
+
const resolveFirstPage = (allMenu) => {
|
|
201
|
+
const firstPageByCustom = getFirstPage?.(allMenu);
|
|
202
|
+
if (firstPageByCustom) return firstPageByCustom;
|
|
203
|
+
return findFirstPagePath(allMenu);
|
|
204
|
+
};
|
|
5
205
|
const router = createRouter({
|
|
6
206
|
history: createWebHashHistory(),
|
|
7
207
|
routes: staticRoutes
|
|
@@ -81,6 +281,16 @@ function createAppRouter(options) {
|
|
|
81
281
|
router.beforeEach(async (to, _from, next) => {
|
|
82
282
|
const userStore = getUserStore();
|
|
83
283
|
let access_token = userStore.getUserAccessToken;
|
|
284
|
+
if (access_token && !userStore.getUserName && typeof window !== "undefined") {
|
|
285
|
+
userStore.syncFromAuthStore?.();
|
|
286
|
+
access_token = userStore.getUserAccessToken;
|
|
287
|
+
}
|
|
288
|
+
if (!access_token && enableUrlTokenRecovery) {
|
|
289
|
+
const restoredFromUrl = trySyncTokenFromUrl(userStore);
|
|
290
|
+
if (restoredFromUrl) {
|
|
291
|
+
access_token = userStore.getUserAccessToken;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
84
294
|
if (!access_token && typeof window !== "undefined") {
|
|
85
295
|
const restored = userStore.syncFromAuthStore();
|
|
86
296
|
if (restored) {
|
|
@@ -100,7 +310,7 @@ function createAppRouter(options) {
|
|
|
100
310
|
if (userStore.isMenuLoaded && (to.path === "/" || to.path === "")) {
|
|
101
311
|
const allMenu = userStore.getUserALLMenu;
|
|
102
312
|
if (allMenu && allMenu.length > 0) {
|
|
103
|
-
const firstPage =
|
|
313
|
+
const firstPage = resolveFirstPage(allMenu);
|
|
104
314
|
if (firstPage) {
|
|
105
315
|
const [basePath, queryString] = firstPage.split("?");
|
|
106
316
|
const query = {};
|
|
@@ -127,7 +337,7 @@ function createAppRouter(options) {
|
|
|
127
337
|
if (allMenu && allMenu.length > 0) {
|
|
128
338
|
addDynamicRoutes(allMenu);
|
|
129
339
|
if (to.path === "/" || to.path === "") {
|
|
130
|
-
const firstPage =
|
|
340
|
+
const firstPage = resolveFirstPage(allMenu);
|
|
131
341
|
if (firstPage) {
|
|
132
342
|
const [basePath, queryString] = firstPage.split("?");
|
|
133
343
|
const query = {};
|
|
@@ -154,13 +364,30 @@ function createAppRouter(options) {
|
|
|
154
364
|
return router;
|
|
155
365
|
}
|
|
156
366
|
|
|
367
|
+
// src/config/auth-config.ts
|
|
368
|
+
var DEFAULT_SSO_STORAGE_KEY = "auth-user-store";
|
|
369
|
+
var DEFAULT_AUTH_LOGIN_ENV_KEY = "VITE_AUTH_LOGIN_URL";
|
|
370
|
+
var DEFAULT_AUTH_LOGIN_PATH = "/auth/#/login";
|
|
371
|
+
function getDefaultAuthLoginUrl() {
|
|
372
|
+
if (typeof window === "undefined") return "";
|
|
373
|
+
const origin = window.location.origin || "";
|
|
374
|
+
return `${origin}${DEFAULT_AUTH_LOGIN_PATH}`;
|
|
375
|
+
}
|
|
376
|
+
var AUTH_CONFIG = {
|
|
377
|
+
ssoStorageKey: DEFAULT_SSO_STORAGE_KEY,
|
|
378
|
+
authLoginEnvKey: DEFAULT_AUTH_LOGIN_ENV_KEY,
|
|
379
|
+
authLoginPath: DEFAULT_AUTH_LOGIN_PATH
|
|
380
|
+
};
|
|
381
|
+
|
|
157
382
|
// src/auth/auth.ts
|
|
158
383
|
function createLogoutToAuth(options) {
|
|
159
384
|
const {
|
|
160
385
|
getUserStore,
|
|
161
386
|
getLoadingStore,
|
|
162
387
|
authLoginUrl,
|
|
163
|
-
ssoStorageKey =
|
|
388
|
+
ssoStorageKey = AUTH_CONFIG.ssoStorageKey,
|
|
389
|
+
legacySsoStorageKey = "user-store",
|
|
390
|
+
fallbackAccessTokenKey = "portal_access_token"
|
|
164
391
|
} = options;
|
|
165
392
|
const AUTH_LOGIN_URL = authLoginUrl || `${window.location.origin}/auth/#/login`;
|
|
166
393
|
return function logoutToAuth() {
|
|
@@ -184,6 +411,12 @@ function createLogoutToAuth(options) {
|
|
|
184
411
|
}
|
|
185
412
|
try {
|
|
186
413
|
localStorage.removeItem(ssoStorageKey);
|
|
414
|
+
if (legacySsoStorageKey && legacySsoStorageKey !== ssoStorageKey) {
|
|
415
|
+
localStorage.removeItem(legacySsoStorageKey);
|
|
416
|
+
}
|
|
417
|
+
if (fallbackAccessTokenKey) {
|
|
418
|
+
localStorage.removeItem(fallbackAccessTokenKey);
|
|
419
|
+
}
|
|
187
420
|
} catch (e) {
|
|
188
421
|
console.error("\u6E05\u7406\u7EDF\u4E00\u767B\u5F55\u7F13\u5B58\u5931\u8D25:", e);
|
|
189
422
|
}
|
|
@@ -225,23 +458,6 @@ function calcInactivityAction(lastActiveTime, now, config = {}) {
|
|
|
225
458
|
|
|
226
459
|
// src/http/http.ts
|
|
227
460
|
import axiosLib from "axios";
|
|
228
|
-
|
|
229
|
-
// src/config/auth-config.ts
|
|
230
|
-
var DEFAULT_SSO_STORAGE_KEY = "user-store";
|
|
231
|
-
var DEFAULT_AUTH_LOGIN_ENV_KEY = "VITE_AUTH_LOGIN_URL";
|
|
232
|
-
var DEFAULT_AUTH_LOGIN_PATH = "/auth/#/login";
|
|
233
|
-
function getDefaultAuthLoginUrl() {
|
|
234
|
-
if (typeof window === "undefined") return "";
|
|
235
|
-
const origin = window.location.origin || "";
|
|
236
|
-
return `${origin}${DEFAULT_AUTH_LOGIN_PATH}`;
|
|
237
|
-
}
|
|
238
|
-
var AUTH_CONFIG = {
|
|
239
|
-
ssoStorageKey: DEFAULT_SSO_STORAGE_KEY,
|
|
240
|
-
authLoginEnvKey: DEFAULT_AUTH_LOGIN_ENV_KEY,
|
|
241
|
-
authLoginPath: DEFAULT_AUTH_LOGIN_PATH
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
// src/http/http.ts
|
|
245
461
|
function createAuthHttpClient(options) {
|
|
246
462
|
const {
|
|
247
463
|
axios,
|
|
@@ -276,7 +492,7 @@ function createAuthHttpClient(options) {
|
|
|
276
492
|
const userStore = getUserStore();
|
|
277
493
|
const accessToken = userStore.getUserAccessToken;
|
|
278
494
|
const refreshToken = userStore.getUserRefreshToken;
|
|
279
|
-
if (!accessToken
|
|
495
|
+
if (!accessToken) {
|
|
280
496
|
return config;
|
|
281
497
|
}
|
|
282
498
|
const lastActiveTime = userStore.getUserLastActiveTime ?? 0;
|
|
@@ -292,7 +508,7 @@ function createAuthHttpClient(options) {
|
|
|
292
508
|
if (!lastActiveTime) {
|
|
293
509
|
userStore.setUserLastActiveTime?.(currentTime);
|
|
294
510
|
} else {
|
|
295
|
-
if (shouldRefresh && !isRefreshing) {
|
|
511
|
+
if (shouldRefresh && refreshToken && !isRefreshing) {
|
|
296
512
|
isRefreshing = true;
|
|
297
513
|
try {
|
|
298
514
|
const response = await axiosInstance.post(refreshUrl, {}, {
|
|
@@ -392,17 +608,17 @@ function createAuthHttpClient(options) {
|
|
|
392
608
|
}
|
|
393
609
|
|
|
394
610
|
// src/permission/permission.ts
|
|
395
|
-
function
|
|
611
|
+
function normalizePath2(raw) {
|
|
396
612
|
if (!raw) return "";
|
|
397
613
|
const [base] = raw.split("?");
|
|
398
614
|
if (!base) return "";
|
|
399
615
|
return base.startsWith("/") ? base : `/${base}`;
|
|
400
616
|
}
|
|
401
617
|
function findMenuByPath(menuList, targetPath, category) {
|
|
402
|
-
const target =
|
|
618
|
+
const target = normalizePath2(targetPath);
|
|
403
619
|
if (!target || !Array.isArray(menuList)) return null;
|
|
404
620
|
for (const item of menuList) {
|
|
405
|
-
const current =
|
|
621
|
+
const current = normalizePath2(item?.path);
|
|
406
622
|
if (current === target) {
|
|
407
623
|
if (!category || item?.category === category) {
|
|
408
624
|
return item;
|
|
@@ -447,175 +663,6 @@ function createPermissionHelper(options) {
|
|
|
447
663
|
};
|
|
448
664
|
}
|
|
449
665
|
|
|
450
|
-
// src/menu/menu.ts
|
|
451
|
-
function normalizePath2(raw) {
|
|
452
|
-
if (!raw) return "";
|
|
453
|
-
const [base] = raw.split("?");
|
|
454
|
-
if (!base) return "";
|
|
455
|
-
return base.startsWith("/") ? base : `/${base}`;
|
|
456
|
-
}
|
|
457
|
-
function _findMenuByPath(menuList, targetPath) {
|
|
458
|
-
const target = normalizePath2(targetPath);
|
|
459
|
-
if (!target || !Array.isArray(menuList)) return null;
|
|
460
|
-
for (const item of menuList) {
|
|
461
|
-
const current = normalizePath2(item?.path);
|
|
462
|
-
if (current === target) {
|
|
463
|
-
return item;
|
|
464
|
-
}
|
|
465
|
-
if (item?.children && item.children.length > 0) {
|
|
466
|
-
const found = _findMenuByPath(item.children, targetPath);
|
|
467
|
-
if (found) return found;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
return null;
|
|
471
|
-
}
|
|
472
|
-
function _findMenuChain(menuList, targetPath, parentChain = []) {
|
|
473
|
-
const target = normalizePath2(targetPath);
|
|
474
|
-
if (!target || !Array.isArray(menuList)) return [];
|
|
475
|
-
for (const menu of menuList) {
|
|
476
|
-
const current = normalizePath2(menu?.path);
|
|
477
|
-
const chain = [...parentChain, menu];
|
|
478
|
-
if (current === target) {
|
|
479
|
-
return chain;
|
|
480
|
-
}
|
|
481
|
-
if (menu?.children && menu.children.length > 0) {
|
|
482
|
-
const result = _findMenuChain(menu.children, targetPath, chain);
|
|
483
|
-
if (result.length > 0) return result;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
return [];
|
|
487
|
-
}
|
|
488
|
-
function _findParentMenuIds(menuList, targetPath, parentIds = []) {
|
|
489
|
-
const target = normalizePath2(targetPath);
|
|
490
|
-
if (!target || !Array.isArray(menuList)) return [];
|
|
491
|
-
for (const menu of menuList) {
|
|
492
|
-
const current = normalizePath2(menu?.path);
|
|
493
|
-
if (menu?.children && menu.children.length > 0) {
|
|
494
|
-
const currentIds = [...parentIds, menu.id];
|
|
495
|
-
const result = _findParentMenuIds(menu.children, targetPath, currentIds);
|
|
496
|
-
if (result.length > 0) return result;
|
|
497
|
-
} else if (current === target) {
|
|
498
|
-
return parentIds;
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
return [];
|
|
502
|
-
}
|
|
503
|
-
function createMenuHelper(options) {
|
|
504
|
-
const { getMenuTree } = options;
|
|
505
|
-
const findMenuByPath2 = (path) => {
|
|
506
|
-
const tree = getMenuTree() || [];
|
|
507
|
-
return _findMenuByPath(tree, path);
|
|
508
|
-
};
|
|
509
|
-
const getMenuTitle = (path) => {
|
|
510
|
-
const item = findMenuByPath2(path);
|
|
511
|
-
return item?.name || null;
|
|
512
|
-
};
|
|
513
|
-
const getMenuChain = (path) => {
|
|
514
|
-
const tree = getMenuTree() || [];
|
|
515
|
-
return _findMenuChain(tree, path);
|
|
516
|
-
};
|
|
517
|
-
const getParentMenuIds = (path) => {
|
|
518
|
-
const tree = getMenuTree() || [];
|
|
519
|
-
return _findParentMenuIds(tree, path);
|
|
520
|
-
};
|
|
521
|
-
const getBreadcrumb = (path) => {
|
|
522
|
-
const chain = getMenuChain(path);
|
|
523
|
-
return chain.map((item) => ({
|
|
524
|
-
title: item?.name ?? "",
|
|
525
|
-
path: item?.path ?? ""
|
|
526
|
-
}));
|
|
527
|
-
};
|
|
528
|
-
return {
|
|
529
|
-
findMenuByPath: findMenuByPath2,
|
|
530
|
-
getMenuTitle,
|
|
531
|
-
getMenuChain,
|
|
532
|
-
getParentMenuIds,
|
|
533
|
-
getBreadcrumb
|
|
534
|
-
};
|
|
535
|
-
}
|
|
536
|
-
function transformMenuTree(menuList, options) {
|
|
537
|
-
const defaultSite = options?.defaultSite;
|
|
538
|
-
return (menuList || []).map((item) => {
|
|
539
|
-
const children = Array.isArray(item?.children) ? transformMenuTree(item.children, options) : void 0;
|
|
540
|
-
return {
|
|
541
|
-
id: item?.id,
|
|
542
|
-
parent_id: item?.parent_id ?? null,
|
|
543
|
-
category: item?.category,
|
|
544
|
-
name: item?.name,
|
|
545
|
-
path: item?.path,
|
|
546
|
-
icon: item?.icon,
|
|
547
|
-
order_num: item?.order_num,
|
|
548
|
-
site: item?.site ?? defaultSite,
|
|
549
|
-
children
|
|
550
|
-
};
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
function buildAllMenuTree(menuList) {
|
|
554
|
-
const result = [];
|
|
555
|
-
for (const item of menuList || []) {
|
|
556
|
-
result.push({
|
|
557
|
-
id: item.id,
|
|
558
|
-
parent_id: item.parent_id ?? null,
|
|
559
|
-
category: item.category,
|
|
560
|
-
name: item.name,
|
|
561
|
-
path: item.path,
|
|
562
|
-
icon: item.icon,
|
|
563
|
-
order_num: item.order_num,
|
|
564
|
-
site: item.site,
|
|
565
|
-
children: item.children && item.children.length > 0 ? buildAllMenuTree(item.children) : []
|
|
566
|
-
});
|
|
567
|
-
}
|
|
568
|
-
return result;
|
|
569
|
-
}
|
|
570
|
-
function buildPageMenuList(menuList) {
|
|
571
|
-
const pages = [];
|
|
572
|
-
for (const item of menuList || []) {
|
|
573
|
-
if (item.category !== "module") {
|
|
574
|
-
pages.push({
|
|
575
|
-
id: item.id,
|
|
576
|
-
parent_id: item.parent_id ?? null,
|
|
577
|
-
category: item.category,
|
|
578
|
-
name: item.name,
|
|
579
|
-
path: item.path,
|
|
580
|
-
icon: item.icon,
|
|
581
|
-
order_num: item.order_num,
|
|
582
|
-
site: item.site,
|
|
583
|
-
children: item.children ? buildPageMenuList(item.children) : []
|
|
584
|
-
});
|
|
585
|
-
} else if (item.children && item.children.length > 0) {
|
|
586
|
-
const childMenus = buildPageMenuList(item.children);
|
|
587
|
-
if (childMenus.length > 0) {
|
|
588
|
-
for (const child of childMenus) {
|
|
589
|
-
pages.push({
|
|
590
|
-
id: child.id,
|
|
591
|
-
parent_id: child.parent_id ?? null,
|
|
592
|
-
category: child.category,
|
|
593
|
-
name: child.name,
|
|
594
|
-
path: child.path,
|
|
595
|
-
icon: child.icon,
|
|
596
|
-
order_num: child.order_num,
|
|
597
|
-
site: child.site,
|
|
598
|
-
children: child.children
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
return pages;
|
|
605
|
-
}
|
|
606
|
-
function findFirstPagePath(menuList) {
|
|
607
|
-
for (const item of menuList || []) {
|
|
608
|
-
if (item.category === "page" && item.path) {
|
|
609
|
-
return item.path;
|
|
610
|
-
}
|
|
611
|
-
if (item.children && item.children.length > 0) {
|
|
612
|
-
const childFirst = findFirstPagePath(item.children);
|
|
613
|
-
if (childFirst) return childFirst;
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
return null;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
666
|
// src/time/time.ts
|
|
620
667
|
import dayjs from "dayjs";
|
|
621
668
|
import relativeTime from "dayjs/plugin/relativeTime";
|
|
@@ -791,8 +838,144 @@ function closeRight(tabs, path, homePath = DEFAULT_HOME_PATH) {
|
|
|
791
838
|
function closeAll(tabs) {
|
|
792
839
|
return tabs.filter((tab) => tab.closable === false);
|
|
793
840
|
}
|
|
841
|
+
function createTabStoreOptions(homePath = DEFAULT_HOME_PATH) {
|
|
842
|
+
return {
|
|
843
|
+
state: () => ({
|
|
844
|
+
tabs: []
|
|
845
|
+
}),
|
|
846
|
+
actions: {
|
|
847
|
+
addTab(tab) {
|
|
848
|
+
this.tabs = addTab(this.tabs, tab);
|
|
849
|
+
},
|
|
850
|
+
removeTab(path) {
|
|
851
|
+
this.tabs = removeTab(this.tabs, path);
|
|
852
|
+
},
|
|
853
|
+
closeOthers(path) {
|
|
854
|
+
this.tabs = closeOthers(this.tabs, path, homePath);
|
|
855
|
+
},
|
|
856
|
+
closeLeft(path) {
|
|
857
|
+
this.tabs = closeLeft(this.tabs, path, homePath);
|
|
858
|
+
},
|
|
859
|
+
closeRight(path) {
|
|
860
|
+
this.tabs = closeRight(this.tabs, path, homePath);
|
|
861
|
+
},
|
|
862
|
+
closeAll() {
|
|
863
|
+
this.tabs = closeAll(this.tabs);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
};
|
|
867
|
+
}
|
|
794
868
|
|
|
795
869
|
// src/user/user.ts
|
|
870
|
+
function createBaseUserState() {
|
|
871
|
+
return {
|
|
872
|
+
userno: "",
|
|
873
|
+
username: "",
|
|
874
|
+
access_token: "",
|
|
875
|
+
refresh_token: "",
|
|
876
|
+
lastActiveTime: null
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
function createBaseUserGetters() {
|
|
880
|
+
return {
|
|
881
|
+
// 获取完整用户信息
|
|
882
|
+
getUserInfo: (state) => ({
|
|
883
|
+
userno: state.userno,
|
|
884
|
+
username: state.username,
|
|
885
|
+
access_token: state.access_token,
|
|
886
|
+
refresh_token: state.refresh_token,
|
|
887
|
+
lastActiveTime: state.lastActiveTime
|
|
888
|
+
}),
|
|
889
|
+
// 获取用户工号
|
|
890
|
+
getUserNo: (state) => state.userno,
|
|
891
|
+
// 获取用户姓名
|
|
892
|
+
getUserName: (state) => state.username,
|
|
893
|
+
// 获取用户access_token
|
|
894
|
+
getUserAccessToken: (state) => state.access_token,
|
|
895
|
+
// 获取用户refresh_token
|
|
896
|
+
getUserRefreshToken: (state) => state.refresh_token,
|
|
897
|
+
// 获取用户最后操作时间
|
|
898
|
+
getUserLastActiveTime: (state) => state.lastActiveTime
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
function createBaseUserActions(options) {
|
|
902
|
+
const ssoStorageKey = options?.ssoStorageKey ?? AUTH_CONFIG.ssoStorageKey;
|
|
903
|
+
return {
|
|
904
|
+
// 设置用户信息
|
|
905
|
+
setUserInfo(userInfo) {
|
|
906
|
+
this.userno = userInfo.userno;
|
|
907
|
+
this.username = userInfo.username;
|
|
908
|
+
this.access_token = userInfo.access_token;
|
|
909
|
+
this.refresh_token = userInfo.refresh_token;
|
|
910
|
+
this.lastActiveTime = userInfo.lastActiveTime;
|
|
911
|
+
},
|
|
912
|
+
// 单独设置用户 token
|
|
913
|
+
setUserAccessToken(access_token) {
|
|
914
|
+
this.access_token = access_token;
|
|
915
|
+
},
|
|
916
|
+
// 单独设置用户刷新 token
|
|
917
|
+
setUserRefreshToken(refresh_token) {
|
|
918
|
+
this.refresh_token = refresh_token;
|
|
919
|
+
},
|
|
920
|
+
// 单独设置用户最后操作时间
|
|
921
|
+
setUserLastActiveTime(lastActiveTime) {
|
|
922
|
+
this.lastActiveTime = lastActiveTime;
|
|
923
|
+
},
|
|
924
|
+
// 尝试从统一登录站点的本地缓存中恢复 token(SSO)
|
|
925
|
+
syncFromAuthStore() {
|
|
926
|
+
return syncFromAuthStoreToStore(this, { storageKey: ssoStorageKey });
|
|
927
|
+
},
|
|
928
|
+
// 清除用户信息
|
|
929
|
+
clearUserInfo() {
|
|
930
|
+
this.userno = "";
|
|
931
|
+
this.username = "";
|
|
932
|
+
this.access_token = "";
|
|
933
|
+
this.refresh_token = "";
|
|
934
|
+
this.lastActiveTime = null;
|
|
935
|
+
}
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
function createMenuUserState() {
|
|
939
|
+
return {
|
|
940
|
+
userno: "",
|
|
941
|
+
username: "",
|
|
942
|
+
access_token: "",
|
|
943
|
+
refresh_token: "",
|
|
944
|
+
lastActiveTime: null,
|
|
945
|
+
all_menu: [],
|
|
946
|
+
sidebar_menu: [],
|
|
947
|
+
menuLoaded: false
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
function createMenuUserGetters() {
|
|
951
|
+
return {
|
|
952
|
+
// 获取完整用户信息
|
|
953
|
+
getUserInfo: (state) => ({
|
|
954
|
+
userno: state.userno,
|
|
955
|
+
username: state.username,
|
|
956
|
+
access_token: state.access_token,
|
|
957
|
+
refresh_token: state.refresh_token,
|
|
958
|
+
lastActiveTime: state.lastActiveTime,
|
|
959
|
+
all_menu: state.all_menu
|
|
960
|
+
}),
|
|
961
|
+
// 获取用户工号
|
|
962
|
+
getUserNo: (state) => state.userno,
|
|
963
|
+
// 获取用户姓名
|
|
964
|
+
getUserName: (state) => state.username,
|
|
965
|
+
// 获取用户access_token
|
|
966
|
+
getUserAccessToken: (state) => state.access_token,
|
|
967
|
+
// 获取用户refresh_token
|
|
968
|
+
getUserRefreshToken: (state) => state.refresh_token,
|
|
969
|
+
// 获取用户最后操作时间
|
|
970
|
+
getUserLastActiveTime: (state) => state.lastActiveTime,
|
|
971
|
+
// 获取用户所有菜单(完整菜单树,包含按钮等)
|
|
972
|
+
getUserALLMenu: (state) => state.all_menu,
|
|
973
|
+
// 获取用于侧边栏展示的菜单(已过滤按钮 / 流程类)
|
|
974
|
+
getUserSidebarMenu: (state) => state.sidebar_menu,
|
|
975
|
+
// 菜单是否已加载
|
|
976
|
+
isMenuLoaded: (state) => state.menuLoaded
|
|
977
|
+
};
|
|
978
|
+
}
|
|
796
979
|
function filterSidebarMenu(menus, options) {
|
|
797
980
|
const exclude = options?.excludeCategories ?? ["button", "flow-module", "flow-page"];
|
|
798
981
|
return (menus || []).filter((item) => !exclude.includes(item?.category)).map((item) => ({
|
|
@@ -801,11 +984,22 @@ function filterSidebarMenu(menus, options) {
|
|
|
801
984
|
}));
|
|
802
985
|
}
|
|
803
986
|
function syncFromAuthStoreToStore(store, options) {
|
|
804
|
-
const storageKey = options?.storageKey ??
|
|
987
|
+
const storageKey = options?.storageKey ?? AUTH_CONFIG.ssoStorageKey;
|
|
988
|
+
const legacyStorageKey = options?.legacyStorageKey ?? "user-store";
|
|
989
|
+
const fallbackAccessTokenKey = options?.fallbackAccessTokenKey ?? "portal_access_token";
|
|
805
990
|
if (typeof window === "undefined") return false;
|
|
806
991
|
try {
|
|
807
|
-
|
|
808
|
-
if (!raw)
|
|
992
|
+
let raw = window.localStorage.getItem(storageKey);
|
|
993
|
+
if (!raw && legacyStorageKey && legacyStorageKey !== storageKey) {
|
|
994
|
+
raw = window.localStorage.getItem(legacyStorageKey);
|
|
995
|
+
}
|
|
996
|
+
if (!raw) {
|
|
997
|
+
const accessToken = window.localStorage.getItem(fallbackAccessTokenKey);
|
|
998
|
+
if (!accessToken) return false;
|
|
999
|
+
store.access_token = accessToken;
|
|
1000
|
+
store.lastActiveTime = Date.now();
|
|
1001
|
+
return true;
|
|
1002
|
+
}
|
|
809
1003
|
const data = JSON.parse(raw);
|
|
810
1004
|
if (!data || !data.access_token) return false;
|
|
811
1005
|
store.userno = data.userno || "";
|
|
@@ -819,6 +1013,73 @@ function syncFromAuthStoreToStore(store, options) {
|
|
|
819
1013
|
return false;
|
|
820
1014
|
}
|
|
821
1015
|
}
|
|
1016
|
+
function createMenuUserActions(options) {
|
|
1017
|
+
const {
|
|
1018
|
+
http,
|
|
1019
|
+
site,
|
|
1020
|
+
transformMenuData,
|
|
1021
|
+
getALLMenu,
|
|
1022
|
+
filterOptions,
|
|
1023
|
+
ssoStorageKey = AUTH_CONFIG.ssoStorageKey
|
|
1024
|
+
} = options;
|
|
1025
|
+
return {
|
|
1026
|
+
// 设置用户信息
|
|
1027
|
+
setUserInfo(userInfo) {
|
|
1028
|
+
this.userno = userInfo.userno;
|
|
1029
|
+
this.username = userInfo.username;
|
|
1030
|
+
this.access_token = userInfo.access_token;
|
|
1031
|
+
this.refresh_token = userInfo.refresh_token;
|
|
1032
|
+
this.lastActiveTime = userInfo.lastActiveTime;
|
|
1033
|
+
this.all_menu = userInfo.all_menu || [];
|
|
1034
|
+
this.sidebar_menu = filterSidebarMenu(userInfo.all_menu || [], filterOptions);
|
|
1035
|
+
},
|
|
1036
|
+
// 单独设置用户 token
|
|
1037
|
+
setUserAccessToken(access_token) {
|
|
1038
|
+
this.access_token = access_token;
|
|
1039
|
+
},
|
|
1040
|
+
// 单独设置用户刷新 token
|
|
1041
|
+
setUserRefreshToken(refresh_token) {
|
|
1042
|
+
this.refresh_token = refresh_token;
|
|
1043
|
+
},
|
|
1044
|
+
// 单独设置用户最后操作时间
|
|
1045
|
+
setUserLastActiveTime(lastActiveTime) {
|
|
1046
|
+
this.lastActiveTime = lastActiveTime;
|
|
1047
|
+
},
|
|
1048
|
+
// 尝试从统一登录站点的本地缓存中恢复 token(SSO)
|
|
1049
|
+
syncFromAuthStore() {
|
|
1050
|
+
return syncFromAuthStoreToStore(this, { storageKey: ssoStorageKey });
|
|
1051
|
+
},
|
|
1052
|
+
// 页面刷新时加载菜单(使用本地缓存)
|
|
1053
|
+
setLoadUserMenulist() {
|
|
1054
|
+
this.menuLoaded = false;
|
|
1055
|
+
},
|
|
1056
|
+
// 从服务器获取用户完整菜单(后台管理使用)
|
|
1057
|
+
async fetchUserMenu() {
|
|
1058
|
+
return fetchUserMenuForStore(this, {
|
|
1059
|
+
http,
|
|
1060
|
+
site,
|
|
1061
|
+
transformMenuData,
|
|
1062
|
+
getALLMenu,
|
|
1063
|
+
filterOptions
|
|
1064
|
+
});
|
|
1065
|
+
},
|
|
1066
|
+
// 重置菜单加载状态
|
|
1067
|
+
resetMenuLoaded() {
|
|
1068
|
+
this.menuLoaded = false;
|
|
1069
|
+
},
|
|
1070
|
+
// 清除用户信息
|
|
1071
|
+
clearUserInfo() {
|
|
1072
|
+
this.userno = "";
|
|
1073
|
+
this.username = "";
|
|
1074
|
+
this.access_token = "";
|
|
1075
|
+
this.refresh_token = "";
|
|
1076
|
+
this.lastActiveTime = null;
|
|
1077
|
+
this.all_menu = [];
|
|
1078
|
+
this.sidebar_menu = [];
|
|
1079
|
+
this.menuLoaded = false;
|
|
1080
|
+
}
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
822
1083
|
async function fetchUserMenuForStore(store, options) {
|
|
823
1084
|
const { http, site, transformMenuData, getALLMenu, filterOptions } = options;
|
|
824
1085
|
if (!store.access_token) return false;
|
|
@@ -862,6 +1123,56 @@ function createLoadingStoreOptions() {
|
|
|
862
1123
|
}
|
|
863
1124
|
};
|
|
864
1125
|
}
|
|
1126
|
+
|
|
1127
|
+
// src/app/setup.ts
|
|
1128
|
+
function usePlugin(app, plugin) {
|
|
1129
|
+
if (Array.isArray(plugin)) {
|
|
1130
|
+
const [pluginInstance, ...args] = plugin;
|
|
1131
|
+
app.use(pluginInstance, ...args);
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
app.use(plugin);
|
|
1135
|
+
}
|
|
1136
|
+
function setupPortalApp(options) {
|
|
1137
|
+
const {
|
|
1138
|
+
app,
|
|
1139
|
+
plugins = [],
|
|
1140
|
+
elementIcons,
|
|
1141
|
+
beforeMount,
|
|
1142
|
+
mountSelector = "#app"
|
|
1143
|
+
} = options;
|
|
1144
|
+
plugins.forEach((plugin) => usePlugin(app, plugin));
|
|
1145
|
+
if (elementIcons) {
|
|
1146
|
+
Object.entries(elementIcons).forEach(([name, component]) => {
|
|
1147
|
+
app.component(name, component);
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1150
|
+
beforeMount?.();
|
|
1151
|
+
app.mount(mountSelector);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
// src/i18n/i18n.ts
|
|
1155
|
+
import { createI18n } from "vue-i18n";
|
|
1156
|
+
function createPortalI18n(options) {
|
|
1157
|
+
const {
|
|
1158
|
+
messages,
|
|
1159
|
+
storageKey = "locale",
|
|
1160
|
+
defaultLocale = "zh-CN",
|
|
1161
|
+
fallbackLocale = "zh-CN"
|
|
1162
|
+
} = options;
|
|
1163
|
+
const getLocale = () => {
|
|
1164
|
+
if (typeof window === "undefined") return defaultLocale;
|
|
1165
|
+
const saved = localStorage.getItem(storageKey);
|
|
1166
|
+
return saved || defaultLocale;
|
|
1167
|
+
};
|
|
1168
|
+
return createI18n({
|
|
1169
|
+
locale: getLocale(),
|
|
1170
|
+
fallbackLocale,
|
|
1171
|
+
messages,
|
|
1172
|
+
legacy: false,
|
|
1173
|
+
globalInjection: true
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
865
1176
|
export {
|
|
866
1177
|
AUTH_CONFIG,
|
|
867
1178
|
DEFAULT_AUTH_LOGIN_ENV_KEY,
|
|
@@ -879,11 +1190,19 @@ export {
|
|
|
879
1190
|
closeRight,
|
|
880
1191
|
createAppRouter,
|
|
881
1192
|
createAuthHttpClient,
|
|
1193
|
+
createBaseUserActions,
|
|
1194
|
+
createBaseUserGetters,
|
|
1195
|
+
createBaseUserState,
|
|
882
1196
|
createLoadingStoreOptions,
|
|
883
1197
|
createLogoutToAuth,
|
|
884
1198
|
createMenuHelper,
|
|
1199
|
+
createMenuUserActions,
|
|
1200
|
+
createMenuUserGetters,
|
|
1201
|
+
createMenuUserState,
|
|
885
1202
|
createPermissionHelper,
|
|
1203
|
+
createPortalI18n,
|
|
886
1204
|
createRange,
|
|
1205
|
+
createTabStoreOptions,
|
|
887
1206
|
fetchUserMenuForStore,
|
|
888
1207
|
filterSidebarMenu,
|
|
889
1208
|
findFirstPagePath,
|
|
@@ -899,6 +1218,7 @@ export {
|
|
|
899
1218
|
initTheme,
|
|
900
1219
|
isInRange,
|
|
901
1220
|
removeTab,
|
|
1221
|
+
setupPortalApp,
|
|
902
1222
|
syncFromAuthStoreToStore,
|
|
903
1223
|
timeDiff,
|
|
904
1224
|
transformMenuTree,
|