@skyfox2000/webui 1.2.5 → 1.2.7

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.
Files changed (31) hide show
  1. package/README.md +441 -91
  2. package/lib/assets/modules/{file-upload-CoDWKNFQ.js → file-upload-D4bA7go8.js} +1 -1
  3. package/lib/assets/modules/{form-excel-DitXm4uj.js → form-excel-DL2_SNiS.js} +1 -1
  4. package/lib/assets/modules/{index-DG2jNBuv.js → index-BZvwPKou.js} +1 -1
  5. package/lib/assets/modules/{index-C4515EtU.js → index-CKMDsqve.js} +749 -735
  6. package/lib/assets/modules/{index-B5NckHoK.js → index-D16E7UbH.js} +2 -2
  7. package/lib/assets/modules/{menuTabs-BwX6S1WN.js → menuTabs-izaFx0kk.js} +196 -175
  8. package/lib/assets/modules/{toolIcon-B5Qojob9.js → toolIcon-66dclHit.js} +1 -1
  9. package/lib/assets/modules/{uploadList-BdeV2JlK.js → uploadList-Dw6eRrJT.js} +3 -3
  10. package/lib/components/common/icon/index.vue.d.ts +1 -1
  11. package/lib/es/AceEditor/index.js +3 -3
  12. package/lib/es/BasicLayout/index.js +3 -3
  13. package/lib/es/Error403/index.js +1 -1
  14. package/lib/es/Error404/index.js +1 -1
  15. package/lib/es/ExcelForm/index.js +4 -4
  16. package/lib/es/UploadForm/index.js +4 -4
  17. package/lib/stores/appInfo.d.ts +2 -5
  18. package/lib/stores/userInfo.d.ts +3 -1
  19. package/lib/webui.css +1 -1
  20. package/lib/webui.es.js +279 -290
  21. package/package.json +2 -2
  22. package/src/components/layout/header/headerExits.vue +5 -4
  23. package/src/components/layout/header/index.vue +4 -2
  24. package/src/components/layout/header/user.vue +4 -1
  25. package/src/directives/permission.ts +6 -2
  26. package/src/router/index.ts +1 -11
  27. package/src/stores/appInfo.ts +87 -58
  28. package/src/stores/pageInfo.ts +1 -0
  29. package/src/stores/settingInfo.ts +1 -7
  30. package/src/stores/userInfo.ts +78 -53
  31. package/src/utils/main-openapis.ts +1 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyfox2000/webui",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
4
  "description": "后台前端通用组件定义",
5
5
  "type": "module",
6
6
  "keywords": [],
@@ -66,4 +66,4 @@
66
66
  "vite-plugin-dts": "^4.5.4",
67
67
  "vue-tsc": "^2.2.10"
68
68
  }
69
- }
69
+ }
@@ -2,11 +2,10 @@
2
2
  import { ref } from 'vue';
3
3
  import { Modal, Flex } from 'ant-design-vue';
4
4
  import { mainAppApis } from '@skyfox2000/microbase';
5
- import { ToolIcon } from '../../common';
5
+ import { ToolIcon, Tooltip } from '../../common';
6
6
  import { useUserInfo } from '@/index';
7
7
 
8
8
  const userInfoStore = useUserInfo();
9
-
10
9
  const open = ref(false);
11
10
  const confirmExit = () => {
12
11
  open.value = false;
@@ -18,11 +17,13 @@ const confirmExit = () => {
18
17
  };
19
18
  </script>
20
19
  <template>
21
- <ToolIcon icon="icon-logout" @click="open = true" clickable class="w-5 h-5" title="退出系统" />
20
+ <Tooltip title="退出平台">
21
+ <ToolIcon icon="icon-logout" @click="open = true" clickable class="w-5 h-5" title="退出系统" />
22
+ </Tooltip>
22
23
  <Modal v-model:open="open" title="确定退出?" ok-text="确定" cancel-text="取消" :width="380" @ok="confirmExit">
23
24
  <Flex align="center" justify="flex-start" :style="{ padding: '0 32px', margin: '20px 0' }">
24
25
  <ToolIcon icon="icon-question-circle" color="orange" class="w-[60px] h-[60px]" />
25
- <div style="margin: 0 0 0 20px; font-weight: 400; font-size: 16px">是否退出系统,<br />清除用户缓存信息?</div>
26
+ <div style="margin: 0 0 0 20px; font-weight: 400; font-size: 16px">是否退出平台,<br />清除用户缓存信息?</div>
26
27
  </Flex>
27
28
  </Modal>
28
29
  </template>
@@ -5,6 +5,7 @@ import { ToolIcon } from '../../common';
5
5
  import Breadcrumb from '../breadcrumb/index.vue';
6
6
  import HeaderExits from './headerExits.vue';
7
7
  import User from './user.vue';
8
+ import DateTime from '../datetime/index.vue';
8
9
 
9
10
  const { useToken } = theme;
10
11
  const { token } = useToken();
@@ -21,7 +22,7 @@ const onCollapseClick = () => {
21
22
  height: '40px',
22
23
  lineHeight: '1',
23
24
  paddingLeft: '10px',
24
- paddingRight: '10px',
25
+ paddingRight: '20px',
25
26
  backgroundColor: token.colorBgContainer,
26
27
  }"
27
28
  >
@@ -37,7 +38,8 @@ const onCollapseClick = () => {
37
38
  </div>
38
39
  <div>
39
40
  <Space size="middle" class="flex items-center">
40
- <User class="w-7 h-7" />
41
+ <DateTime />
42
+ <User />
41
43
  <HeaderExits />
42
44
  </Space>
43
45
  </div>
@@ -6,6 +6,9 @@ const userInfo = useUserInfo().userInfo;
6
6
  </script>
7
7
  <template>
8
8
  <Tooltip :title="userInfo.Name">
9
- <AppIcon icon="icon-account" />
9
+ <div class="flex items-center flex-nowrap">
10
+ <span class="mr-2 text-sm whitespace-nowrap">{{ userInfo.Name }}</span>
11
+ <AppIcon icon="icon-account" />
12
+ </div>
10
13
  </Tooltip>
11
14
  </template>
@@ -93,8 +93,12 @@ const checkPermission = (params: PermissionParams): boolean => {
93
93
  let hasPermitPermission = false;
94
94
 
95
95
  // 检查角色权限
96
- if (!isEmpty(role) && role !== undefined) {
97
- hasRolePermission = userInfoStore.hasRole(role);
96
+ if (!isEmpty(role)) {
97
+ hasRolePermission = userInfoStore.hasRole(role!);
98
+ }
99
+
100
+ if (userInfoStore.isAdmin()) {
101
+ return hasRolePermission;
98
102
  }
99
103
 
100
104
  // 检查功能权限
@@ -1,5 +1,5 @@
1
1
  import { useUserInfo } from '@/stores/userInfo';
2
- import { isMicroApp, mainAppApis, RouteRecord, EnvConfig } from '@skyfox2000/microbase';
2
+ import { RouteRecord, EnvConfig } from '@skyfox2000/microbase';
3
3
  import { RouteLocationNormalizedGeneric, RouteRecordRaw, Router, createRouter, createWebHashHistory } from 'vue-router';
4
4
  import { useAppInfo } from '@/stores/appInfo';
5
5
  import { Ref, ref } from 'vue';
@@ -166,16 +166,6 @@ router.beforeEach((to, _from, next) => {
166
166
  }
167
167
  });
168
168
 
169
- /**
170
- * 子应用更新主应用路由
171
- */
172
- router.afterEach((to: RouteLocationNormalizedGeneric) => {
173
- if (isMicroApp() && mainAppApis.value) {
174
- const { mainAppPush } = mainAppApis.value;
175
- if (mainAppPush) mainAppPush(to.hash);
176
- }
177
- });
178
-
179
169
  /**
180
170
  * 继续执行之前挂起的导航
181
171
  * @param path 默认路径
@@ -1,15 +1,25 @@
1
1
  import { defineStore } from 'pinia';
2
- import { Router, RouteRecordRaw } from 'vue-router';
3
- import { AppAction, AppInfo, AppSource, isBaseMicroApp, isMicroApp, RouteRecord } from '@skyfox2000/microbase';
2
+ import { RouteRecordRaw } from 'vue-router';
3
+ import {
4
+ AppAction,
5
+ AppInfo,
6
+ AppSource,
7
+ isBaseMicroApp,
8
+ isMicroApp,
9
+ mainAppApis,
10
+ RouteRecord,
11
+ EnvConfig,
12
+ } from '@skyfox2000/microbase';
4
13
  import AppRouter, { addAppRoutes, continueNavigation, flattenRoute, LOGIN_PATH } from '@/router';
5
14
  import { usePageInfo } from './pageInfo';
15
+ import { isEmpty } from '@/utils/isEmpty';
6
16
 
7
17
  import { Component, h, nextTick } from 'vue';
8
18
  import { useUserInfo } from './userInfo';
9
19
  import { ApiResponse, httpPost, IUrlInfo, ResStatus } from '@skyfox2000/fapi';
10
20
  import message from 'vue-m-message';
11
21
 
12
- const APPINFO_STORE_KEY = 'appInfoStore';
22
+ // const APPINFO_STORE_KEY = 'appInfoStore';
13
23
 
14
24
  /** 授权应用相关接口 */
15
25
  const AppUrlList: {
@@ -27,31 +37,68 @@ const AppUrlList: {
27
37
  // 定义一个映射,用于存储不同路由路径对应的组件包装器
28
38
  const wrapperMap = new Map<string, Component>();
29
39
 
40
+ /**
41
+ * 检查路由权限
42
+ * @param route 路由信息
43
+ * @returns 是否有权限访问
44
+ */
45
+ const checkRoutePermission = (route: RouteRecord): boolean => {
46
+ const userInfoStore = useUserInfo();
47
+ const { roles, permission }: { roles?: string | string[]; permission?: string } = route.meta || {};
48
+ // 如果都没有配置,默认允许访问
49
+ if (isEmpty(roles) && isEmpty(permission)) {
50
+ return true;
51
+ }
52
+
53
+ if (EnvConfig.VITE_PERMISSION_MODE === 'role') {
54
+ // 仅判断角色权限
55
+ if (!isEmpty(roles) && roles) {
56
+ return userInfoStore.hasRole(roles);
57
+ }
58
+ // 如果没有配置角色,默认允许访问
59
+ return true;
60
+ } else if (EnvConfig.VITE_PERMISSION_MODE === 'permit') {
61
+ // 角色和权限任意一个有效即可
62
+ let hasRolePermission = false;
63
+ let hasPermitPermission = false;
64
+
65
+ // 检查角色权限
66
+ if (!isEmpty(roles) && roles) {
67
+ hasRolePermission = userInfoStore.hasRole(roles);
68
+ }
69
+
70
+ // 如果是管理员,只需要检查角色权限
71
+ if (userInfoStore.isAdmin()) {
72
+ return hasRolePermission;
73
+ }
74
+
75
+ // 检查功能权限
76
+ if (!isEmpty(permission) && permission) {
77
+ hasPermitPermission = userInfoStore.hasPermit(route.path, permission);
78
+ }
79
+
80
+ // 任意一个有权限即可
81
+ return hasRolePermission || hasPermitPermission;
82
+ }
83
+
84
+ // 默认不允许访问
85
+ return false;
86
+ };
87
+
30
88
  // 根据用户权限过滤路由
31
- const filterRoutes = (routes: RouteRecord[], userInfoStore: any) => {
89
+ const filterRoutes = (routes: RouteRecord[]) => {
32
90
  return routes
33
91
  .map((route) => {
34
92
  // 创建路由对象的副本
35
93
  const routeCopy = { ...route };
36
94
 
37
- // 如果没有配置角色和权限,默认允许访问
38
- if (!routeCopy.meta?.roles?.length && !routeCopy.meta?.permission?.length) {
39
- if (routeCopy.children) {
40
- routeCopy.children = filterRoutes(routeCopy.children, userInfoStore);
41
- }
42
- return routeCopy;
43
- }
44
-
45
- // 如果配置了角色或权限,满足任意一个条件即可
46
- const hasRole = routeCopy.meta?.roles?.length ? userInfoStore.hasRole(routeCopy.meta.roles) : false;
47
- const hasPermission = routeCopy.meta?.permission?.length
48
- ? userInfoStore.hasPermit(routeCopy.meta.permission, ':page')
49
- : false;
95
+ // 检查路由权限
96
+ const hasPermission = checkRoutePermission(routeCopy);
50
97
 
51
98
  // 如果当前路由有权限访问
52
- if (hasRole || hasPermission) {
99
+ if (hasPermission) {
53
100
  if (routeCopy.children) {
54
- routeCopy.children = filterRoutes(routeCopy.children, userInfoStore);
101
+ routeCopy.children = filterRoutes(routeCopy.children);
55
102
  }
56
103
  return routeCopy;
57
104
  }
@@ -102,10 +149,6 @@ const findFirstPage = (routes: RouteRecord[], path = ''): string | undefined =>
102
149
 
103
150
  export const useAppInfo = defineStore('appInfo', {
104
151
  state: (): {
105
- /// 微前端基座路由
106
- microRouter: any;
107
- /// 微前端基座方法
108
- microActions: Record<string, () => void>;
109
152
  /// 当前选中的
110
153
  appInfo: AppInfo & {
111
154
  /**
@@ -136,8 +179,6 @@ export const useAppInfo = defineStore('appInfo', {
136
179
  */
137
180
  menuLoaded: boolean;
138
181
  } => ({
139
- microRouter: null,
140
- microActions: {},
141
182
  appInfo: {
142
183
  Id: '',
143
184
  Name: '',
@@ -159,10 +200,6 @@ export const useAppInfo = defineStore('appInfo', {
159
200
  menuLoaded: false,
160
201
  }),
161
202
  actions: {
162
- init(router: Router, microActions: Record<string, () => void>) {
163
- this.microRouter = router;
164
- this.microActions = microActions;
165
- },
166
203
  /**
167
204
  * 加载授权应用列表
168
205
  */
@@ -264,8 +301,8 @@ export const useAppInfo = defineStore('appInfo', {
264
301
 
265
302
  if (!isMicroApp() || !isBaseMicroApp()) {
266
303
  /// 非基座应用,获取用户应用权限
304
+ const userInfoStore = useUserInfo();
267
305
  /// 获取用户应用权限
268
- const userInfoStore = await useUserInfo();
269
306
  await userInfoStore.getRolePermits(appInfo.Id);
270
307
 
271
308
  if (this.appInfo.Routes.length) this.setAppRoutes(this.appInfo.Routes);
@@ -306,13 +343,16 @@ export const useAppInfo = defineStore('appInfo', {
306
343
  });
307
344
 
308
345
  /// 根据用户权限过滤菜单
309
- const userInfoStore = useUserInfo();
310
- if (userInfoStore.isLogin) {
311
- const filteredRoutes = filterRoutes(this.appInfo.Routes, userInfoStore as any);
346
+ if (useUserInfo().isLogin) {
347
+ const filteredRoutes = filterRoutes(this.appInfo.Routes);
312
348
  addAppRoutes(filteredRoutes);
313
349
  this.appInfo.defaultPage = findFirstPage(filteredRoutes) || '';
314
350
  if (this.appInfo.defaultPage) {
315
351
  this.menuLoaded = true;
352
+ if (mainAppApis.value && mainAppApis.value.mainAppPush) {
353
+ const fullPath = this.formatRoute(this.appInfo.defaultPage);
354
+ mainAppApis.value.mainAppPush(fullPath);
355
+ }
316
356
  continueNavigation(this.appInfo.defaultPage);
317
357
  }
318
358
  }
@@ -347,19 +387,11 @@ export const useAppInfo = defineStore('appInfo', {
347
387
  usePageInfo().setTabActive(path);
348
388
  }
349
389
  nextTick(() => {
350
- if (isBaseMicroApp()) {
351
- // 跨应用路由
352
- path = this.formatRoute(path);
353
- if (this.microRouter) {
354
- /// 基座路由
355
- let microRouter = this.microRouter as Router;
356
- microRouter.push({ path });
357
- } else {
358
- AppRouter.push({ path });
359
- }
360
- } else {
361
- // 非微应用,直接使用当前应用路由AppRouter
362
- AppRouter.push({ path });
390
+ // 直接使用当前应用路由AppRouter
391
+ AppRouter.push({ path });
392
+ if (mainAppApis.value && mainAppApis.value.mainAppPush) {
393
+ const fullPath = this.formatRoute(path);
394
+ mainAppApis.value.mainAppPush(fullPath);
363
395
  }
364
396
  });
365
397
  },
@@ -433,7 +465,7 @@ export const useAppInfo = defineStore('appInfo', {
433
465
  return matched.reverse();
434
466
  },
435
467
 
436
- clear() {
468
+ clean() {
437
469
  /// 清空信息
438
470
  this.appInfo = {
439
471
  Id: '',
@@ -457,18 +489,15 @@ export const useAppInfo = defineStore('appInfo', {
457
489
  },
458
490
 
459
491
  logout() {
460
- if (this.microRouter) {
461
- // 避免界面跳动
462
- // this.microRouter.push({ path: LOGIN_PATH + '#/' });
463
- if (this.microActions && typeof this.microActions['login'] === 'function') {
464
- this.microActions['login']();
492
+ // 清理应用信息
493
+ this.clean();
494
+ AppRouter.push({ path: LOGIN_PATH + '#/' });
495
+ if (isMicroApp()) {
496
+ if (mainAppApis.value && mainAppApis.value.mainAppPush) {
497
+ mainAppApis.value.mainAppPush(LOGIN_PATH + '#/');
465
498
  }
466
- } else AppRouter.push({ path: LOGIN_PATH + '#/' });
499
+ }
467
500
  },
468
501
  },
469
- persist: {
470
- key: APPINFO_STORE_KEY,
471
- storage: localStorage,
472
- pick: ['appList'],
473
- },
502
+ persist: false,
474
503
  });
@@ -128,4 +128,5 @@ export const usePageInfo = defineStore('pageInfo', {
128
128
  this.TabActive = path;
129
129
  },
130
130
  },
131
+ persist: false,
131
132
  });
@@ -2,8 +2,6 @@ import { SettingInfo } from '@skyfox2000/microbase';
2
2
 
3
3
  import { defineStore } from 'pinia';
4
4
 
5
- const SETTINGINFO_STORE_KEY = 'settingInfoStore';
6
-
7
5
  export const useSettingInfo = defineStore('settingInfo', {
8
6
  state: (): SettingInfo => ({
9
7
  fullscreen: false,
@@ -45,9 +43,5 @@ export const useSettingInfo = defineStore('settingInfo', {
45
43
  });
46
44
  },
47
45
  },
48
- persist: {
49
- key: SETTINGINFO_STORE_KEY,
50
- storage: localStorage,
51
- pick: ['fullscreen', 'menuCollapse', 'tableColumns'],
52
- },
46
+ persist: false,
53
47
  });
@@ -5,8 +5,6 @@ import { LoginInfo, UserInfo } from '@skyfox2000/microbase';
5
5
  import { ref } from 'vue';
6
6
  import { useAppInfo } from './appInfo';
7
7
 
8
- const USERINFO_STORE_KEY = 'userInfoStore';
9
-
10
8
  const TokenError = 'Token解析失败';
11
9
  const LoginExpired = '登录过期,请重新登录';
12
10
 
@@ -45,7 +43,9 @@ const LoginUrlList: {
45
43
  */
46
44
  const loginApi = <T>(loginInfo: LoginInfo): Promise<ApiResponse<T> | null | undefined> => {
47
45
  let loginParams: ReqParams = {
48
- Option: {},
46
+ Option: {
47
+ Mode: 'MicroApp',
48
+ },
49
49
  Query: loginInfo,
50
50
  };
51
51
 
@@ -57,20 +57,6 @@ const loginApi = <T>(loginInfo: LoginInfo): Promise<ApiResponse<T> | null | unde
57
57
  });
58
58
  };
59
59
 
60
- /**
61
- * 界面授权信息接口
62
- */
63
- interface AuthInfo {
64
- /** 应用ID */
65
- appId: string;
66
- /** 用户角色级别 */
67
- level: string;
68
- /** 权限信息 */
69
- permits: Record<string, string[]>;
70
- /** 最后更新时间 */
71
- lastTime: number;
72
- }
73
-
74
60
  /**
75
61
  * 获取用户界面授权
76
62
  * @param appId 应用ID
@@ -180,8 +166,26 @@ interface UserState {
180
166
  refreshToken?: string;
181
167
  }
182
168
 
169
+ /**
170
+ * 界面授权信息接口
171
+ */
172
+ interface AuthInfo {
173
+ /** 应用ID */
174
+ appId: string;
175
+ /** 权限信息 */
176
+ permits: Record<string, string[]>;
177
+ /** 最后更新时间 */
178
+ lastTime: number;
179
+ }
180
+
181
+ /** 用户角色级别 */
182
+ const userLevel = ref<string>('');
183
183
  /** 授权信息(私有) */
184
+ /** 应用ID
185
+ * 这是子应用,不可能有多个应用
186
+ */
184
187
  const auth = ref<AuthInfo | null>(null);
188
+
185
189
  /**
186
190
  * 当前登录用户信息
187
191
  */
@@ -193,23 +197,12 @@ export const useUserInfo = defineStore('userInfo', {
193
197
  Name: '',
194
198
  Code: '',
195
199
  TenantId: null,
196
- UserLevel: 'Guest',
200
+ UserLevel: '',
197
201
  },
198
202
  token: '',
199
203
  refreshToken: '',
200
204
  }),
201
205
  actions: {
202
- /**
203
- * 启动时初始化用户信息
204
- */
205
- init() {
206
- if (this.token && this.isLogin) {
207
- checkToken(this.token, () => this.clean());
208
- setToken(this.token);
209
- } else {
210
- this.clean();
211
- }
212
- },
213
206
  /**
214
207
  * 登录操作
215
208
  * @param loginInfo 登录信息
@@ -228,10 +221,12 @@ export const useUserInfo = defineStore('userInfo', {
228
221
  this.isLogin = true;
229
222
 
230
223
  if (expandUser(loginInfo)) {
224
+ // 用户信息不显示用户级别,必须通过接口获取
231
225
  this.userInfo = {
232
226
  ...this.userInfo,
233
227
  ...loginInfo.UserInfo!,
234
228
  };
229
+ userLevel.value = loginInfo.UserInfo!.UserLevel;
235
230
  } else {
236
231
  message.error('用户信息解析失败');
237
232
  return;
@@ -239,7 +234,7 @@ export const useUserInfo = defineStore('userInfo', {
239
234
 
240
235
  // 加载子应用
241
236
  if (redirect) {
242
- const appInfoStore = await useAppInfo();
237
+ const appInfoStore = useAppInfo();
243
238
  appInfoStore.toDefaultApp();
244
239
  }
245
240
  }
@@ -262,14 +257,13 @@ export const useUserInfo = defineStore('userInfo', {
262
257
  }
263
258
 
264
259
  try {
265
- const result = await getRolePermitsApi<AuthInfo>(appId);
260
+ const result: AuthInfo | null | undefined = await getRolePermitsApi<AuthInfo>(appId);
266
261
  if (result) {
267
262
  // 保存授权信息到内存中
268
263
  auth.value = {
269
264
  appId: appId,
270
- level: this.userInfo.UserLevel,
271
265
  permits: (result as AuthInfo).permits || [],
272
- lastTime: (result as AuthInfo).lastTime,
266
+ lastTime: result.lastTime,
273
267
  };
274
268
 
275
269
  return true;
@@ -288,25 +282,27 @@ export const useUserInfo = defineStore('userInfo', {
288
282
  * @returns 是否有角色权限
289
283
  */
290
284
  hasRole(role: string | string[]): boolean {
291
- if (!auth.value || !auth.value.level) {
285
+ if (!userLevel.value) {
292
286
  return false;
293
287
  }
294
288
  if (Array.isArray(role)) {
295
- return role.includes(auth.value.level);
289
+ return role.includes(userLevel.value);
296
290
  }
297
- return auth.value.level === role;
291
+ return userLevel.value === role;
298
292
  },
299
293
 
300
294
  /**
301
295
  * 检查功能权限
296
+ * @param url 所在页面
302
297
  * @param permitCode 资源权限编码
303
298
  * @returns 是否有功能权限
304
299
  */
305
300
  hasPermit(url: string, permitCode: string): boolean {
306
- if (!auth.value || !auth.value.permits) {
301
+ const authInfo = auth.value;
302
+ if (!authInfo || !authInfo.permits) {
307
303
  return false;
308
304
  }
309
- return auth.value.permits[url]?.includes(permitCode) ?? false;
305
+ return authInfo.permits[url]?.includes(permitCode) ?? false;
310
306
  },
311
307
 
312
308
  /**
@@ -317,19 +313,29 @@ export const useUserInfo = defineStore('userInfo', {
317
313
  return this.userInfo;
318
314
  },
319
315
 
316
+ /**
317
+ * 设置用户信息
318
+ * 仅允许设置一次,启动时设置,避免通过其它方式设置
319
+ * @param userInfo 用户信息
320
+ * @param token 用户Token
321
+ */
320
322
  setUserInfo(userInfo: UserInfo, token: string) {
321
323
  if (!checkToken(token)) {
322
324
  this.clean();
323
325
  return;
324
326
  }
325
327
 
326
- this.userInfo = {
327
- ...this.userInfo,
328
- ...userInfo,
329
- };
330
- this.token = token;
331
- setToken(this.token);
332
- this.isLogin = true;
328
+ if (!userLevel.value) {
329
+ // 仅允许设置一次,启动时设置,避免通过其它方式设置
330
+ userLevel.value = userInfo.UserLevel;
331
+ this.userInfo = {
332
+ ...this.userInfo,
333
+ ...userInfo,
334
+ };
335
+ this.token = token;
336
+ setToken(this.token);
337
+ this.isLogin = true;
338
+ }
333
339
  },
334
340
 
335
341
  /**
@@ -348,6 +354,28 @@ export const useUserInfo = defineStore('userInfo', {
348
354
  return '';
349
355
  },
350
356
 
357
+ /**
358
+ * 是否超级管理员
359
+ */
360
+ isSuperAdmin(): boolean {
361
+ return userLevel.value === 'Super';
362
+ },
363
+
364
+ /**
365
+ * 是否管理员
366
+ */
367
+ isAdmin(): boolean {
368
+ return userLevel.value === 'Super' || userLevel.value === 'Admin';
369
+ },
370
+
371
+ /**
372
+ * 获取用户级别
373
+ * @returns 用户级别
374
+ */
375
+ getUserLevel(): string {
376
+ return userLevel.value;
377
+ },
378
+
351
379
  /*
352
380
  * 清理登录信息
353
381
  */
@@ -365,10 +393,11 @@ export const useUserInfo = defineStore('userInfo', {
365
393
  this.isLogin = false;
366
394
  // 清理授权信息
367
395
  auth.value = null;
396
+ userLevel.value = '';
368
397
 
369
398
  // 动态导入并使用appInfo
370
- const appInfoStore = await useAppInfo();
371
- appInfoStore.clear();
399
+ const appInfoStore = useAppInfo();
400
+ appInfoStore.clean();
372
401
  return Promise.resolve();
373
402
  },
374
403
 
@@ -391,7 +420,7 @@ export const useUserInfo = defineStore('userInfo', {
391
420
  message.success('已退出登录');
392
421
  }, 1000);
393
422
  setTimeout(async () => {
394
- const appInfoStore = await useAppInfo();
423
+ const appInfoStore = useAppInfo();
395
424
  appInfoStore.logout();
396
425
  }, 2000);
397
426
  }
@@ -399,9 +428,5 @@ export const useUserInfo = defineStore('userInfo', {
399
428
  return Promise.resolve();
400
429
  },
401
430
  },
402
- persist: {
403
- key: USERINFO_STORE_KEY,
404
- storage: localStorage,
405
- pick: ['isLogin', 'userInfo', 'token', 'refreshToken'],
406
- },
431
+ persist: false,
407
432
  });
@@ -61,12 +61,4 @@ export const getUserInfo = (): UserInfo => {
61
61
  if (mainAppApis.value && mainAppApis.value.getUserInfo) return mainAppApis.value.getUserInfo();
62
62
  const userInfoStore = useUserInfo();
63
63
  return userInfoStore.getUserInfo();
64
- };
65
-
66
- /**
67
- * 子应用推送路由变更
68
- */
69
- export const mainAppPush = (subPath: string) => {
70
- const appInfoStore = useAppInfo();
71
- appInfoStore.push(subPath);
72
- };
64
+ };