@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/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 { staticRoutes, getUserStore, getTabStore, getFirstPage, authLoginUrl } = options;
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 = getFirstPage(allMenu);
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 = getFirstPage(allMenu);
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 = "user-store"
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 || !refreshToken) {
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 normalizePath(raw) {
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 = normalizePath(targetPath);
618
+ const target = normalizePath2(targetPath);
403
619
  if (!target || !Array.isArray(menuList)) return null;
404
620
  for (const item of menuList) {
405
- const current = normalizePath(item?.path);
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 ?? "user-store";
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
- const raw = window.localStorage.getItem(storageKey);
808
- if (!raw) return false;
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,