@litianxiang/portal-core 0.1.20 → 0.1.22

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.d.ts CHANGED
@@ -1,13 +1,16 @@
1
1
  import * as vue_router from 'vue-router';
2
2
  import { RouteRecordRaw } from 'vue-router';
3
3
  import { Dayjs } from 'dayjs';
4
+ import { App, Plugin } from 'vue';
5
+ import * as vue_i18n from 'vue-i18n';
4
6
 
5
7
  interface AppRouterOptions {
6
8
  staticRoutes: RouteRecordRaw[];
7
9
  getUserStore: () => any;
8
- getTabStore: () => any;
9
- getFirstPage: (allMenu: any[]) => string | null | undefined;
10
+ getFirstPage?: (allMenu: any[]) => string | null | undefined;
10
11
  authLoginUrl?: string;
12
+ /** 是否开启从 URL 参数恢复 token,默认关闭 */
13
+ enableUrlTokenRecovery?: boolean;
11
14
  }
12
15
  /**
13
16
  * 创建带统一登录、动态菜单和 Tab 管理的 Router
@@ -24,11 +27,13 @@ interface LogoutToAuthOptions {
24
27
  };
25
28
  authLoginUrl?: string;
26
29
  ssoStorageKey?: string;
30
+ legacySsoStorageKey?: string;
31
+ fallbackAccessTokenKey?: string;
27
32
  }
28
33
  /**
29
34
  * 创建统一退出方法:
30
35
  * - 清除当前子系统的用户信息
31
- * - 清除统一登录站点的本地缓存(默认 key: user-store)
36
+ * - 清除统一登录站点的本地缓存(默认 key: auth-user-store)
32
37
  * - 跳转到统一登录地址,携带 redirect
33
38
  */
34
39
  declare function createLogoutToAuth(options: LogoutToAuthOptions): () => void;
@@ -263,17 +268,91 @@ declare function closeOthers(tabs: TabItem[], path: string, homePath?: string):
263
268
  declare function closeLeft(tabs: TabItem[], path: string, homePath?: string): TabItem[];
264
269
  declare function closeRight(tabs: TabItem[], path: string, homePath?: string): TabItem[];
265
270
  declare function closeAll(tabs: TabItem[]): TabItem[];
271
+ /**
272
+ * 为 Pinia 创建通用的 Tab Store 配置
273
+ * @param homePath 首页路径,默认 /main/home
274
+ */
275
+ declare function createTabStoreOptions(homePath?: string): {
276
+ state: () => {
277
+ tabs: TabItem[];
278
+ };
279
+ actions: {
280
+ addTab(this: {
281
+ tabs: TabItem[];
282
+ }, tab: TabItem): void;
283
+ removeTab(this: {
284
+ tabs: TabItem[];
285
+ }, path: string): void;
286
+ closeOthers(this: {
287
+ tabs: TabItem[];
288
+ }, path: string): void;
289
+ closeLeft(this: {
290
+ tabs: TabItem[];
291
+ }, path: string): void;
292
+ closeRight(this: {
293
+ tabs: TabItem[];
294
+ }, path: string): void;
295
+ closeAll(this: {
296
+ tabs: TabItem[];
297
+ }): void;
298
+ };
299
+ };
266
300
 
267
- interface CoreUserStoreLike {
301
+ interface BaseUserStoreLike {
268
302
  userno: string;
269
303
  username: string;
270
304
  access_token: string;
271
305
  refresh_token: string;
272
306
  lastActiveTime: number | null;
307
+ }
308
+ declare function createBaseUserState(): BaseUserStoreLike;
309
+ declare function createBaseUserGetters(): {
310
+ getUserInfo: (state: any) => {
311
+ userno: any;
312
+ username: any;
313
+ access_token: any;
314
+ refresh_token: any;
315
+ lastActiveTime: any;
316
+ };
317
+ getUserNo: (state: any) => any;
318
+ getUserName: (state: any) => any;
319
+ getUserAccessToken: (state: any) => any;
320
+ getUserRefreshToken: (state: any) => any;
321
+ getUserLastActiveTime: (state: any) => any;
322
+ };
323
+ interface CreateBaseUserActionsOptions {
324
+ /** SSO 缓存 key,默认读取 AUTH_CONFIG.ssoStorageKey */
325
+ ssoStorageKey?: string;
326
+ }
327
+ declare function createBaseUserActions(options?: CreateBaseUserActionsOptions): {
328
+ setUserInfo(this: BaseUserStoreLike, userInfo: any): void;
329
+ setUserAccessToken(this: BaseUserStoreLike, access_token: string): void;
330
+ setUserRefreshToken(this: BaseUserStoreLike, refresh_token: string): void;
331
+ setUserLastActiveTime(this: BaseUserStoreLike, lastActiveTime: number): void;
332
+ syncFromAuthStore(this: BaseUserStoreLike): boolean;
333
+ clearUserInfo(this: BaseUserStoreLike): void;
334
+ };
335
+ interface CoreUserStoreLike extends BaseUserStoreLike {
273
336
  all_menu: any[];
274
337
  sidebar_menu: any[];
275
338
  menuLoaded: boolean;
276
339
  }
340
+ interface CoreMenuUserState<TMenu = any> extends CoreUserStoreLike {
341
+ all_menu: TMenu[];
342
+ sidebar_menu: TMenu[];
343
+ }
344
+ declare function createMenuUserState<TMenu = any>(): CoreMenuUserState<TMenu>;
345
+ declare function createMenuUserGetters<TUserInfo = any>(): {
346
+ getUserInfo: (state: any) => TUserInfo;
347
+ getUserNo: (state: any) => any;
348
+ getUserName: (state: any) => any;
349
+ getUserAccessToken: (state: any) => any;
350
+ getUserRefreshToken: (state: any) => any;
351
+ getUserLastActiveTime: (state: any) => any;
352
+ getUserALLMenu: (state: any) => any;
353
+ getUserSidebarMenu: (state: any) => any;
354
+ isMenuLoaded: (state: any) => any;
355
+ };
277
356
  interface SidebarMenuFilterOptions {
278
357
  /** 需要排除的菜单类别 */
279
358
  excludeCategories?: string[];
@@ -283,8 +362,12 @@ interface SidebarMenuFilterOptions {
283
362
  */
284
363
  declare function filterSidebarMenu(menus: any[], options?: SidebarMenuFilterOptions): any[];
285
364
  interface SyncFromAuthStoreOptions {
286
- /** 统一登录站点在 localStorage 中使用的 key,默认 user-store */
365
+ /** 统一登录站点在 localStorage 中使用的 key,默认 auth-user-store */
287
366
  storageKey?: string;
367
+ /** 历史兼容 key,默认 user-store */
368
+ legacyStorageKey?: string;
369
+ /** 仅 access_token 的兜底 key,默认 portal_access_token */
370
+ fallbackAccessTokenKey?: string;
288
371
  }
289
372
  /**
290
373
  * 从统一登录站点的本地缓存中恢复用户基础信息
@@ -297,6 +380,25 @@ interface FetchUserMenuForStoreOptions {
297
380
  getALLMenu: (menuTree: any[]) => any[];
298
381
  filterOptions?: SidebarMenuFilterOptions;
299
382
  }
383
+ interface CreateMenuUserActionsOptions {
384
+ http: any;
385
+ site: string;
386
+ transformMenuData: (data: any[]) => any[];
387
+ getALLMenu: (menuTree: any[]) => any[];
388
+ filterOptions?: SidebarMenuFilterOptions;
389
+ ssoStorageKey?: string;
390
+ }
391
+ declare function createMenuUserActions(options: CreateMenuUserActionsOptions): {
392
+ setUserInfo(this: CoreUserStoreLike, userInfo: any): void;
393
+ setUserAccessToken(this: CoreUserStoreLike, access_token: string): void;
394
+ setUserRefreshToken(this: CoreUserStoreLike, refresh_token: string): void;
395
+ setUserLastActiveTime(this: CoreUserStoreLike, lastActiveTime: number): void;
396
+ syncFromAuthStore(this: CoreUserStoreLike): boolean;
397
+ setLoadUserMenulist(this: CoreUserStoreLike): void;
398
+ fetchUserMenu(this: CoreUserStoreLike): Promise<boolean>;
399
+ resetMenuLoaded(this: CoreUserStoreLike): void;
400
+ clearUserInfo(this: CoreUserStoreLike): void;
401
+ };
300
402
  /**
301
403
  * 为指定站点拉取并设置用户菜单(包含完整菜单树和侧边栏菜单)
302
404
  */
@@ -325,7 +427,7 @@ declare function createLoadingStoreOptions(): {
325
427
  * - DEFAULT_AUTH_LOGIN_ENV_KEY: 前端项目中约定的统一登录地址环境变量名
326
428
  * - DEFAULT_AUTH_LOGIN_PATH: 统一登录站点在当前域下的默认路径
327
429
  */
328
- declare const DEFAULT_SSO_STORAGE_KEY = "user-store";
430
+ declare const DEFAULT_SSO_STORAGE_KEY = "auth-user-store";
329
431
  declare const DEFAULT_AUTH_LOGIN_ENV_KEY = "VITE_AUTH_LOGIN_URL";
330
432
  declare const DEFAULT_AUTH_LOGIN_PATH = "/auth/#/login";
331
433
  /**
@@ -335,7 +437,7 @@ declare const DEFAULT_AUTH_LOGIN_PATH = "/auth/#/login";
335
437
  */
336
438
  declare function getDefaultAuthLoginUrl(): string;
337
439
  interface AuthConfig {
338
- /** 统一登录站点在 localStorage 中使用的 key,默认 user-store */
440
+ /** 统一登录站点在 localStorage 中使用的 key,默认 auth-user-store */
339
441
  ssoStorageKey: string;
340
442
  /** 前端项目中约定的统一登录地址环境变量名,默认 VITE_AUTH_LOGIN_URL */
341
443
  authLoginEnvKey: string;
@@ -344,4 +446,31 @@ interface AuthConfig {
344
446
  }
345
447
  declare const AUTH_CONFIG: AuthConfig;
346
448
 
347
- export { AUTH_CONFIG, type AppRouterOptions, type AuthConfig, type BreadcrumbItem, type CoreMenuItem, type CoreUserStoreLike, type CreateAuthHttpClientOptions, DEFAULT_AUTH_LOGIN_ENV_KEY, DEFAULT_AUTH_LOGIN_PATH, DEFAULT_HOME_PATH, DEFAULT_SSO_STORAGE_KEY, type FetchUserMenuForStoreOptions, type FontSize, type InactivityConfig, type InactivityResult, type LoadingState, type LogoutToAuthOptions, type MenuHelper, type MenuHelperOptions, type PermissionHelper, type PermissionHelperOptions, type PresetRangeKey, type SidebarMenuFilterOptions, type SyncFromAuthStoreOptions, type TabItem, type ThemeConfig, type ThemeMode, type TimeInput, type TimeRange, type TransformMenuOptions, addTab, applyTheme, buildAllMenuTree, buildPageMenuList, calcInactivityAction, closeAll, closeLeft, closeOthers, closeRight, createAppRouter, createAuthHttpClient, createLoadingStoreOptions, createLogoutToAuth, createMenuHelper, createPermissionHelper, createRange, fetchUserMenuForStore, filterSidebarMenu, findFirstPagePath, formatRange, formatTime, formatToMonthDay, formatToWanShou, formatToYi, formatWanYuanToYi, getDefaultAuthLoginUrl, getPresetRange, humanizeTime, initTheme, isInRange, removeTab, syncFromAuthStoreToStore, timeDiff, transformMenuTree, useThemeWatcher, useTime };
449
+ type PluginTuple = [Plugin, ...unknown[]];
450
+ type UsePluginItem = Plugin | PluginTuple;
451
+ interface SetupPortalAppOptions {
452
+ app: App;
453
+ plugins?: UsePluginItem[];
454
+ elementIcons?: Record<string, unknown>;
455
+ beforeMount?: () => void;
456
+ mountSelector?: string;
457
+ }
458
+ declare function setupPortalApp(options: SetupPortalAppOptions): void;
459
+
460
+ interface CreateI18nOptions {
461
+ /** 翻译消息,key 为 locale(如 'zh-CN'),value 为翻译对象 */
462
+ messages: Record<string, any>;
463
+ /** localStorage 中存储语言偏好的 key,默认 'locale' */
464
+ storageKey?: string;
465
+ /** 默认语言,默认 'zh-CN' */
466
+ defaultLocale?: string;
467
+ /** 回退语言,默认 'zh-CN' */
468
+ fallbackLocale?: string;
469
+ }
470
+ /**
471
+ * 创建统一配置的 vue-i18n 实例
472
+ * 四个站点的初始化逻辑完全相同,只有翻译内容不同
473
+ */
474
+ declare function createPortalI18n(options: CreateI18nOptions): vue_i18n.I18n<Record<string, any>, {}, {}, string, false>;
475
+
476
+ export { AUTH_CONFIG, type AppRouterOptions, type AuthConfig, type BaseUserStoreLike, type BreadcrumbItem, type CoreMenuItem, type CoreMenuUserState, type CoreUserStoreLike, type CreateAuthHttpClientOptions, type CreateBaseUserActionsOptions, type CreateI18nOptions, type CreateMenuUserActionsOptions, DEFAULT_AUTH_LOGIN_ENV_KEY, DEFAULT_AUTH_LOGIN_PATH, DEFAULT_HOME_PATH, DEFAULT_SSO_STORAGE_KEY, type FetchUserMenuForStoreOptions, type FontSize, type InactivityConfig, type InactivityResult, type LoadingState, type LogoutToAuthOptions, type MenuHelper, type MenuHelperOptions, type PermissionHelper, type PermissionHelperOptions, type PresetRangeKey, type SetupPortalAppOptions, type SidebarMenuFilterOptions, type SyncFromAuthStoreOptions, type TabItem, type ThemeConfig, type ThemeMode, type TimeInput, type TimeRange, type TransformMenuOptions, addTab, applyTheme, buildAllMenuTree, buildPageMenuList, calcInactivityAction, closeAll, closeLeft, closeOthers, closeRight, createAppRouter, createAuthHttpClient, createBaseUserActions, createBaseUserGetters, createBaseUserState, createLoadingStoreOptions, createLogoutToAuth, createMenuHelper, createMenuUserActions, createMenuUserGetters, createMenuUserState, createPermissionHelper, createPortalI18n, createRange, createTabStoreOptions, fetchUserMenuForStore, filterSidebarMenu, findFirstPagePath, formatRange, formatTime, formatToMonthDay, formatToWanShou, formatToYi, formatWanYuanToYi, getDefaultAuthLoginUrl, getPresetRange, humanizeTime, initTheme, isInRange, removeTab, setupPortalApp, syncFromAuthStoreToStore, timeDiff, transformMenuTree, useThemeWatcher, useTime };
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,
package/package.json CHANGED
@@ -1,29 +1,42 @@
1
1
  {
2
2
  "name": "@litianxiang/portal-core",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "default": "./dist/index.js"
14
+ }
15
+ },
9
16
  "files": [
10
17
  "dist"
11
18
  ],
12
19
  "scripts": {
13
- "build": "tsup src/index.ts --format esm --dts"
20
+ "clean": "rm -rf dist",
21
+ "build": "pnpm run clean && tsup src/index.ts --format esm --dts",
22
+ "pack:check": "pnpm run build && pnpm pack --pack-destination /tmp"
23
+ },
24
+ "publishConfig": {
25
+ "access": "public"
14
26
  },
15
27
  "peerDependencies": {
16
28
  "vue": "^3.5.0",
17
- "vue-router": "^4.5.0",
18
- "dayjs": "^1.11.0"
29
+ "vue-i18n": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0-0",
30
+ "vue-router": "^4.5.0"
19
31
  },
20
32
  "dependencies": {
21
- "axios": "^1.8.4"
33
+ "axios": "^1.8.4",
34
+ "dayjs": "^1.11.13"
22
35
  },
23
36
  "devDependencies": {
24
37
  "tsup": "^8.3.0",
25
38
  "typescript": "^5.6.3",
26
- "dayjs": "^1.11.13"
39
+ "vue-i18n": "^11.2.8"
27
40
  },
28
41
  "license": "UNLICENSED"
29
42
  }
package/dist/index.cjs DELETED
@@ -1,183 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- createAppRouter: () => createAppRouter
24
- });
25
- module.exports = __toCommonJS(index_exports);
26
-
27
- // src/router.ts
28
- var import_vue_router = require("vue-router");
29
- var import_meta = {};
30
- function createAppRouter(options) {
31
- const { staticRoutes, getUserStore, getTabStore, getFirstPage, authLoginUrl } = options;
32
- const router = (0, import_vue_router.createRouter)({
33
- history: (0, import_vue_router.createWebHashHistory)(),
34
- routes: staticRoutes
35
- });
36
- const AUTH_LOGIN_URL = authLoginUrl || `${window.location.origin}/auth/#/login`;
37
- const modules = import_meta.glob("@/views/**/*.vue");
38
- const registeredPaths = /* @__PURE__ */ new Set();
39
- const resolveRouteAndView = (item) => {
40
- const [rawPath] = (item.path || "").split("?");
41
- const normalizedPath = rawPath.startsWith("/") ? rawPath : `/${rawPath}`;
42
- const routePath = normalizedPath.slice(1);
43
- const candidates = [
44
- `/main${normalizedPath}`,
45
- // /views/main/system/user.vue
46
- `${normalizedPath}`
47
- // /views/system/user.vue 或 /views/kq/leave.vue
48
- ];
49
- let viewKey = "";
50
- for (const viewPath of candidates) {
51
- const key = `/src/views${viewPath}.vue`;
52
- if (key in modules) {
53
- viewKey = key;
54
- break;
55
- }
56
- }
57
- if (!viewKey) {
58
- const fallbackPath = `/main${normalizedPath}`;
59
- viewKey = `/src/views${fallbackPath}.vue`;
60
- }
61
- return { routePath, viewKey };
62
- };
63
- const transformRoutes = (menuItems) => {
64
- const routes = [];
65
- for (const item of menuItems) {
66
- if (item.category === "button") continue;
67
- const { routePath, viewKey } = resolveRouteAndView(item);
68
- const isPage = item.category === "page" || item.category === "flow-page";
69
- if (!registeredPaths.has(routePath)) {
70
- registeredPaths.add(routePath);
71
- routes.push({
72
- path: routePath,
73
- name: `menu_${item.id}`,
74
- component: isPage ? modules[viewKey] : void 0,
75
- meta: {
76
- id: item.id,
77
- parent_id: item.parent_id,
78
- icon: item.icon,
79
- category: item.category,
80
- keepAlive: true,
81
- title: item.name,
82
- fullPath: item.path
83
- },
84
- children: item.children ? transformRoutes(item.children) : []
85
- });
86
- } else if (item.children?.length) {
87
- routes.push(...transformRoutes(item.children));
88
- }
89
- }
90
- return routes;
91
- };
92
- const addDynamicRoutes = (menuData) => {
93
- const dynamicRoutes = transformRoutes(menuData);
94
- dynamicRoutes.forEach((route) => {
95
- router.addRoute("main", route);
96
- });
97
- };
98
- const clearDynamicRoutes = () => {
99
- const routes = router.getRoutes();
100
- routes.forEach((route) => {
101
- if (route.name?.toString().startsWith("menu_") && router.hasRoute(route.name)) {
102
- router.removeRoute(route.name);
103
- }
104
- });
105
- registeredPaths.clear();
106
- };
107
- let justLoadedMenu = false;
108
- router.beforeEach(async (to, _from, next) => {
109
- const userStore = getUserStore();
110
- let access_token = userStore.getUserAccessToken;
111
- if (!access_token && typeof window !== "undefined") {
112
- const restored = userStore.syncFromAuthStore();
113
- if (restored) {
114
- access_token = userStore.getUserAccessToken;
115
- }
116
- }
117
- if (!access_token) {
118
- const currentUrl = encodeURIComponent(window.location.href);
119
- window.location.href = `${AUTH_LOGIN_URL}?redirect=${currentUrl}`;
120
- return;
121
- }
122
- if (justLoadedMenu) {
123
- justLoadedMenu = false;
124
- next();
125
- return;
126
- }
127
- if (userStore.isMenuLoaded && (to.path === "/" || to.path === "")) {
128
- const tabStore = getTabStore();
129
- tabStore.clearAll();
130
- const allMenu = userStore.getUserALLMenu;
131
- if (allMenu && allMenu.length > 0) {
132
- const firstPage = getFirstPage(allMenu);
133
- if (firstPage) {
134
- const [basePath, queryString] = firstPage.split("?");
135
- const query = {};
136
- if (queryString) {
137
- queryString.split("&").forEach((param) => {
138
- const [key, value] = param.split("=");
139
- if (key) query[key] = value || "";
140
- });
141
- }
142
- next({ path: basePath, query, replace: true });
143
- return;
144
- }
145
- }
146
- }
147
- if (!userStore.isMenuLoaded) {
148
- clearDynamicRoutes();
149
- const tabStore = getTabStore();
150
- tabStore.clearAll();
151
- userStore.resetMenuLoaded();
152
- const success = await userStore.fetchUserMenu();
153
- if (!success) {
154
- window.location.href = AUTH_LOGIN_URL;
155
- return;
156
- }
157
- const allMenu = userStore.getUserALLMenu;
158
- if (allMenu && allMenu.length > 0) {
159
- addDynamicRoutes(allMenu);
160
- const firstPage = getFirstPage(allMenu);
161
- if (firstPage) {
162
- const [basePath, queryString] = firstPage.split("?");
163
- const query = {};
164
- if (queryString) {
165
- queryString.split("&").forEach((param) => {
166
- const [key, value] = param.split("=");
167
- if (key) query[key] = value || "";
168
- });
169
- }
170
- justLoadedMenu = true;
171
- next({ path: basePath, query, replace: true });
172
- return;
173
- }
174
- }
175
- }
176
- next();
177
- });
178
- return router;
179
- }
180
- // Annotate the CommonJS export names for ESM import in node:
181
- 0 && (module.exports = {
182
- createAppRouter
183
- });