@skyfox2000/webui 1.0.13 → 1.2.0

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 (162) hide show
  1. package/lib/assets/modules/file-upload-CBUcsUnR.js +170 -0
  2. package/lib/assets/modules/form-validate-CgX7aR7T.js +297 -0
  3. package/lib/assets/modules/index-Civhd8xG.js +112 -0
  4. package/lib/assets/modules/index-DQMdt51R.js +726 -0
  5. package/lib/assets/modules/{index-BEWJ_qAH.js → index-DmWrkTXX.js} +1 -1
  6. package/lib/assets/modules/{menuTabs-BXdbFZor.js → menuTabs-BRYvFWA-.js} +131 -121
  7. package/lib/assets/modules/settingInfo-BZakNKIN.js +999 -0
  8. package/lib/assets/modules/uploadList-B7XoxGOh.js +278 -0
  9. package/lib/components/common/icon/index.vue.d.ts +1 -1
  10. package/lib/components/content/dialog/index.vue.d.ts +1 -1
  11. package/lib/components/content/drawer/index.vue.d.ts +1 -1
  12. package/lib/components/content/form/index.vue.d.ts +1 -1
  13. package/lib/components/content/search/index.vue.d.ts +1 -1
  14. package/lib/components/content/table/index.vue.d.ts +1 -1
  15. package/lib/components/content/table/tableOperate.vue.d.ts +1 -1
  16. package/lib/components/content/toolbar/icontool.vue.d.ts +1 -1
  17. package/lib/components/content/toolbar/index.vue.d.ts +1 -1
  18. package/lib/components/content/tree/index.vue.d.ts +1 -1
  19. package/lib/components/form/transfer/transferTable.vue.d.ts +1 -1
  20. package/lib/components/form/treeSelect/index.vue.d.ts +1 -1
  21. package/lib/components/form/upload/uploadList.vue.d.ts +1 -1
  22. package/lib/const/options.d.ts +32 -0
  23. package/lib/directives/enter-submit.d.ts +4 -0
  24. package/lib/directives/index.d.ts +2 -0
  25. package/lib/directives/permission.d.ts +5 -0
  26. package/lib/es/AceEditor/index.js +9 -8
  27. package/lib/es/BasicLayout/index.js +28 -24
  28. package/lib/es/Error403/index.js +15 -10
  29. package/lib/es/Error404/index.js +15 -10
  30. package/lib/es/ExcelForm/index.js +380 -175
  31. package/lib/es/UploadForm/index.js +23 -20
  32. package/lib/index.d.ts +42 -2
  33. package/lib/router/index.d.ts +16 -0
  34. package/lib/stores/appInfo.d.ts +34 -0
  35. package/lib/stores/hostInfo.d.ts +9 -0
  36. package/lib/stores/pageInfo.d.ts +18 -0
  37. package/lib/stores/pinia.d.ts +3 -0
  38. package/lib/stores/settingInfo.d.ts +8 -0
  39. package/lib/stores/userInfo.d.ts +21 -0
  40. package/lib/typings/data.d.ts +80 -0
  41. package/lib/typings/form.d.ts +171 -0
  42. package/lib/typings/menu.d.ts +7 -0
  43. package/lib/typings/option.d.ts +175 -0
  44. package/lib/typings/page.d.ts +69 -0
  45. package/lib/typings/table.d.ts +181 -0
  46. package/lib/typings/tools.d.ts +130 -0
  47. package/lib/typings/tree.d.ts +72 -0
  48. package/lib/typings/upload.d.ts +161 -0
  49. package/lib/typings/urls.d.ts +69 -0
  50. package/lib/utils/cache.d.ts +23 -0
  51. package/lib/utils/data.d.ts +6 -0
  52. package/lib/utils/download.d.ts +4 -0
  53. package/lib/utils/eventbus.d.ts +16 -0
  54. package/lib/utils/export-table.d.ts +12 -0
  55. package/lib/utils/file-upload.d.ts +15 -0
  56. package/lib/utils/form-excel.d.ts +30 -0
  57. package/lib/utils/form-validate.d.ts +29 -0
  58. package/lib/utils/form.d.ts +9 -0
  59. package/lib/utils/icon-loader.d.ts +125 -0
  60. package/lib/utils/isEmpty.d.ts +1 -0
  61. package/lib/utils/main-openapis.d.ts +9 -0
  62. package/lib/utils/menu.d.ts +6 -0
  63. package/lib/utils/options.d.ts +10 -0
  64. package/lib/utils/page.d.ts +25 -0
  65. package/lib/utils/table.d.ts +21 -0
  66. package/lib/utils/tools.d.ts +18 -0
  67. package/lib/utils/tree.d.ts +3 -0
  68. package/lib/vite-env.d.ts +8 -0
  69. package/lib/webui.css +1 -1
  70. package/lib/webui.es.js +1020 -854
  71. package/package.json +7 -6
  72. package/src/components/common/icon/appicon.vue +1 -1
  73. package/src/components/common/icon/fullscreen.vue +2 -1
  74. package/src/components/common/icon/index.vue +1 -1
  75. package/src/components/common/icon/layoutIcon.vue +1 -1
  76. package/src/components/common/icon/projectIcon.vue +1 -1
  77. package/src/components/common/icon/toolIcon.vue +1 -1
  78. package/src/components/content/dialog/excelForm.vue +2 -2
  79. package/src/components/content/dialog/index.vue +1 -1
  80. package/src/components/content/dialog/uploadForm.vue +7 -6
  81. package/src/components/content/drawer/index.vue +43 -18
  82. package/src/components/content/form/formItem.vue +1 -1
  83. package/src/components/content/form/index.vue +1 -1
  84. package/src/components/content/search/index.vue +1 -1
  85. package/src/components/content/search/searchItem.vue +1 -1
  86. package/src/components/content/table/index.vue +8 -5
  87. package/src/components/content/table/tableOperate.vue +8 -4
  88. package/src/components/content/toolbar/icontool.vue +2 -2
  89. package/src/components/content/toolbar/index.vue +9 -5
  90. package/src/components/content/tree/index.vue +1 -1
  91. package/src/components/error/error403.vue +2 -2
  92. package/src/components/error/error404.vue +2 -2
  93. package/src/components/form/autoComplete/index.vue +1 -1
  94. package/src/components/form/cascader/index.vue +1 -2
  95. package/src/components/form/checkbox/index.vue +11 -5
  96. package/src/components/form/datePicker/index.vue +1 -1
  97. package/src/components/form/input/index.vue +1 -1
  98. package/src/components/form/input/inputNumber.vue +1 -1
  99. package/src/components/form/input/inputPassword.vue +1 -1
  100. package/src/components/form/radio/index.vue +1 -1
  101. package/src/components/form/radio/radioStatus.vue +1 -1
  102. package/src/components/form/rangePicker/index.vue +1 -1
  103. package/src/components/form/select/index.vue +1 -1
  104. package/src/components/form/switch/index.vue +7 -3
  105. package/src/components/form/textarea/index.vue +1 -1
  106. package/src/components/form/transfer/index.vue +1 -1
  107. package/src/components/form/transfer/transferTable.vue +42 -22
  108. package/src/components/form/treeSelect/index.vue +2 -3
  109. package/src/components/form/upload/uploadList.vue +1 -1
  110. package/src/components/layout/breadcrumb/index.vue +1 -1
  111. package/src/components/layout/header/headerExits.vue +1 -1
  112. package/src/components/layout/header/index.vue +1 -1
  113. package/src/components/layout/header/user.vue +2 -1
  114. package/src/components/layout/menu/index.vue +9 -3
  115. package/src/components/layout/menu/menuTabs.vue +10 -12
  116. package/src/components/layout/page/basicLayout.vue +1 -1
  117. package/src/const/options.ts +114 -0
  118. package/src/directives/enter-submit.ts +13 -0
  119. package/src/directives/index.ts +26 -0
  120. package/src/directives/permission.ts +144 -0
  121. package/src/index.ts +201 -0
  122. package/src/router/index.ts +196 -0
  123. package/src/stores/appInfo.ts +471 -0
  124. package/src/stores/hostInfo.ts +117 -0
  125. package/src/stores/pageInfo.ts +131 -0
  126. package/src/stores/pinia.ts +10 -0
  127. package/src/stores/settingInfo.ts +53 -0
  128. package/src/stores/userInfo.ts +392 -0
  129. package/src/typings/data.d.ts +81 -0
  130. package/src/typings/form.d.ts +172 -0
  131. package/src/typings/menu.d.ts +7 -0
  132. package/src/typings/option.d.ts +177 -0
  133. package/src/typings/page.d.ts +70 -0
  134. package/src/typings/table.d.ts +182 -0
  135. package/src/typings/tools.d.ts +131 -0
  136. package/src/typings/tree.d.ts +73 -0
  137. package/src/typings/upload.d.ts +162 -0
  138. package/src/typings/urls.d.ts +70 -0
  139. package/src/utils/cache.ts +175 -0
  140. package/src/utils/data.ts +189 -0
  141. package/src/utils/download.ts +80 -0
  142. package/src/utils/eventbus.ts +78 -0
  143. package/src/utils/export-table.ts +155 -0
  144. package/src/utils/file-upload.ts +304 -0
  145. package/src/utils/form-excel.ts +523 -0
  146. package/src/utils/form-validate.ts +368 -0
  147. package/src/utils/form.ts +188 -0
  148. package/src/utils/icon-loader.ts +412 -0
  149. package/src/utils/isEmpty.ts +18 -0
  150. package/src/utils/main-openapis.ts +72 -0
  151. package/src/utils/menu.ts +89 -0
  152. package/src/utils/options.ts +324 -0
  153. package/src/utils/page.ts +262 -0
  154. package/src/utils/table.ts +274 -0
  155. package/src/utils/tools.ts +362 -0
  156. package/src/utils/tree.ts +28 -0
  157. package/tsconfig.json +1 -8
  158. package/vite.config.ts +7 -4
  159. package/lib/assets/modules/index-BahGnrAq.js +0 -415
  160. package/lib/assets/modules/index-BoKIa2sr.js +0 -109
  161. package/lib/assets/modules/index-D47Ci-T3.js +0 -107
  162. package/lib/assets/modules/uploadList-Dzlg47V0.js +0 -182
@@ -0,0 +1,471 @@
1
+ import { defineStore } from 'pinia';
2
+ import { Router, RouteRecordRaw } from 'vue-router';
3
+ import { AppAction, AppInfo, AppSource, isBaseMicroApp, isMicroApp, RouteRecord } from '@skyfox2000/microbase';
4
+ import AppRouter, { addAppRoutes, continueNavigation, flattenRoute, LOGIN_PATH } from '@/router';
5
+ import { usePageInfo } from './pageInfo';
6
+
7
+ import { Component, h, nextTick } from 'vue';
8
+ import { useUserInfo } from './userInfo';
9
+ import { ApiResponse, httpPost, IUrlInfo, ResStatus } from '@skyfox2000/fapi';
10
+ import message from 'vue-m-message';
11
+
12
+ const APPINFO_STORE_KEY = 'appInfoStore';
13
+
14
+ /** 授权应用相关接口 */
15
+ const AppUrlList: {
16
+ /** 授权应用列表 */
17
+ appList: IUrlInfo;
18
+ } = {
19
+ appList: {
20
+ api: 'PLATFORM_API',
21
+ authorize: true,
22
+ url: '/api/RCTenanetOpSrv/getApps',
23
+ loadingText: false,
24
+ },
25
+ };
26
+
27
+ // 定义一个映射,用于存储不同路由路径对应的组件包装器
28
+ const wrapperMap = new Map<string, Component>();
29
+
30
+ // 根据用户权限过滤路由
31
+ const filterRoutes = (routes: RouteRecord[], userInfoStore: any) => {
32
+ return routes
33
+ .map((route) => {
34
+ // 创建路由对象的副本
35
+ const routeCopy = { ...route };
36
+
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;
50
+
51
+ // 如果当前路由有权限访问
52
+ if (hasRole || hasPermission) {
53
+ if (routeCopy.children) {
54
+ routeCopy.children = filterRoutes(routeCopy.children, userInfoStore);
55
+ }
56
+ return routeCopy;
57
+ }
58
+
59
+ return null;
60
+ })
61
+ .filter(Boolean) as RouteRecord[];
62
+ };
63
+
64
+ /**
65
+ * 查找第一个可用页面路由
66
+ * @param routes 路由列表
67
+ * @param path 当前路径前缀
68
+ * @returns 第一个可用页面的完整路径
69
+ */
70
+ const findFirstPage = (routes: RouteRecord[], path = ''): string | undefined => {
71
+ for (const route of routes) {
72
+ // 如果没有子路由且没有重定向,说明是一个页面路由
73
+ if (!route.children && !route.redirect) {
74
+ // 正确拼接路径,确保以 / 开头
75
+ let fullPath = path + route.path;
76
+ // 确保路径以 / 开头
77
+ if (!fullPath.startsWith('/')) {
78
+ fullPath = '/' + fullPath;
79
+ }
80
+ return fullPath;
81
+ }
82
+
83
+ // 如果有子路由且不是特殊路由,递归查找
84
+ if (
85
+ route.children &&
86
+ route.children.length > 0 &&
87
+ route.path !== '/error' &&
88
+ route.path !== '/login' &&
89
+ route.path !== '/:page(.*)'
90
+ ) {
91
+ // 递归调用并获取结果
92
+ const result = findFirstPage(route.children, path + route.path + '/');
93
+ // 如果找到结果,立即返回
94
+ if (result) {
95
+ return result;
96
+ }
97
+ }
98
+ }
99
+ // 如果没有找到任何页面路由,返回 undefined
100
+ return undefined;
101
+ };
102
+
103
+ export const useAppInfo = defineStore('appInfo', {
104
+ state: (): {
105
+ /// 微前端基座路由
106
+ microRouter: any;
107
+ /// 微前端基座方法
108
+ microActions: Record<string, () => void>;
109
+ /// 当前选中的
110
+ appInfo: AppInfo & {
111
+ /**
112
+ * 应用路由
113
+ */
114
+ Routes: RouteRecordRaw[];
115
+ /**
116
+ * 平铺路由地址,方便快速查找
117
+ */
118
+ flattenRoutes: Record<string, RouteRecord>;
119
+ /**
120
+ * 默认页面
121
+ */
122
+ defaultPage: string;
123
+ };
124
+ /// 当前应用列表
125
+ appList: AppInfo[];
126
+ /**
127
+ * 缓存的组件
128
+ */
129
+ CachedComponents: string[];
130
+ /**
131
+ * 不缓存的组件
132
+ */
133
+ ExcludeComponents: string[];
134
+ /**
135
+ * 菜单是否已加载完成
136
+ */
137
+ menuLoaded: boolean;
138
+ } => ({
139
+ microRouter: null,
140
+ microActions: {},
141
+ appInfo: {
142
+ Id: '',
143
+ Name: '',
144
+ AppCode: '',
145
+ Version: '',
146
+ Host: '',
147
+ Source: AppSource.Manual,
148
+ Action: AppAction.App,
149
+ Path: '',
150
+ Icon: '',
151
+ Routes: [],
152
+ flattenRoutes: {},
153
+ defaultPage: '',
154
+ Enabled: 1,
155
+ },
156
+ appList: [],
157
+ CachedComponents: [],
158
+ ExcludeComponents: [],
159
+ menuLoaded: false,
160
+ }),
161
+ actions: {
162
+ init(router: Router, microActions: Record<string, () => void>) {
163
+ this.microRouter = router;
164
+ this.microActions = microActions;
165
+ },
166
+ /**
167
+ * 加载授权应用列表
168
+ */
169
+ async loadAppList(appList?: AppInfo[]): Promise<void> {
170
+ return new Promise(async (resolve) => {
171
+ if (appList && appList.length > 0) {
172
+ this.appList.length = 0;
173
+ /// 本地加载
174
+ setTimeout(async () => {
175
+ this.appList.push(...appList);
176
+ // 添加应用路由
177
+ // addRootRoutes(this.appList);
178
+ // if (this.appList.length > 0) {
179
+ // const defaultApp = this.appList.find((item) => item.Default);
180
+ // if (defaultApp) this.setActiveApp(defaultApp.AppCode);
181
+ // else this.setActiveApp(this.appList[0].AppCode);
182
+ // }
183
+ resolve();
184
+ }, 1000);
185
+ } else if (this.appList.length === 0) {
186
+ /// 远程加载
187
+ await this.getRemoteAppList();
188
+ resolve();
189
+ } else {
190
+ resolve();
191
+ }
192
+ });
193
+ },
194
+
195
+ async getRemoteAppList(): Promise<void> {
196
+ // 从服务器获取
197
+ return httpPost<AppInfo[]>(AppUrlList.appList, {
198
+ Query: {},
199
+ }).then((result: ApiResponse<AppInfo[]> | null) => {
200
+ if (result?.status === ResStatus.SUCCESS && result.data) {
201
+ this.appList.length = 0;
202
+ this.appList.push(...(result.data as AppInfo[]));
203
+ }
204
+ });
205
+ },
206
+
207
+ async toDefaultApp(url?: string) {
208
+ if (this.appList.length === 0) await this.loadAppList();
209
+ if (this.appList.length === 0) {
210
+ message.error('加载应用列表失败');
211
+ return;
212
+ }
213
+ // 默认地址的应用
214
+ let appCode = '';
215
+ const codes = window.location.pathname.split('/');
216
+ if (codes.length > 1) {
217
+ for (let i = codes.length - 1; i >= 0; i--) {
218
+ if (codes[i] !== '') {
219
+ appCode = codes[i];
220
+ break;
221
+ }
222
+ }
223
+ }
224
+
225
+ let defaultApp = null;
226
+ if (appCode && appCode != 'login') {
227
+ defaultApp = this.appList.find((item) => item.AppCode === appCode);
228
+ } else {
229
+ defaultApp = this.appList.find((item) => item.Default);
230
+ }
231
+ // 设置默认应用
232
+ appCode = defaultApp ? defaultApp.AppCode : this.appList[0].AppCode;
233
+
234
+ // 设置当前激活应用
235
+ await this.setActiveApp(appCode); // 替换当前路由并清空历史记录
236
+
237
+ // 如果未配置默认应用,则跳转到第一个应用
238
+ if (!url || url.startsWith('/#/') || url.includes('/error/') || window.location.hash.includes('/error/'))
239
+ this.push(this.appInfo.defaultPage);
240
+ },
241
+
242
+ /**
243
+ * 设置当前应用
244
+ * @param key 应用码
245
+ * @returns
246
+ */
247
+ async setActiveApp(key: string, appRoutes?: RouteRecord[]): Promise<void> {
248
+ this.menuLoaded = false;
249
+ const appInfo = this.appList.find((item) => item.AppCode === key);
250
+ if (!appInfo) {
251
+ return;
252
+ }
253
+ if (appInfo.AppCode !== this.appInfo.AppCode) {
254
+ this.appInfo = {
255
+ ...appInfo,
256
+ flattenRoutes: {},
257
+ Routes: appRoutes ?? [],
258
+ defaultPage: '',
259
+ };
260
+ }
261
+
262
+ if (!isMicroApp() || !isBaseMicroApp()) {
263
+ /// 非基座应用,获取用户应用权限
264
+ /// 获取用户应用权限
265
+ const userInfoStore = await useUserInfo();
266
+ await userInfoStore.getRolePermits(appInfo.Id);
267
+
268
+ if (this.appInfo.Routes.length) this.setAppRoutes(this.appInfo.Routes);
269
+ }
270
+ },
271
+
272
+ /**
273
+ * 设置当前应用路由信息
274
+ * @param routes 路由信息
275
+ */
276
+ setAppRoutes(appRoutes: RouteRecord[]): void {
277
+ this.appInfo = {
278
+ ...this.appInfo,
279
+ flattenRoutes: {},
280
+ Routes: appRoutes,
281
+ defaultPage: '',
282
+ };
283
+
284
+ const flattenRoutes = this.appInfo.flattenRoutes;
285
+ for (const route of appRoutes) {
286
+ flattenRoute(route, flattenRoutes, undefined);
287
+ }
288
+
289
+ /**
290
+ * 设置路由组件缓存信息
291
+ */
292
+ Object.keys(flattenRoutes).forEach((key) => {
293
+ const route = flattenRoutes[key];
294
+ // 如果路由有 children 或者没有 component 参数,则忽略该条
295
+ if (route.children || !route.component) return;
296
+
297
+ // 根据路由的 meta.keepAlive 属性决定添加到哪个数组
298
+ if (route.meta && route.meta.keepAlive === false) {
299
+ this.ExcludeComponents.push(key);
300
+ } else {
301
+ this.CachedComponents.push(key);
302
+ }
303
+ });
304
+
305
+ /// 根据用户权限过滤菜单
306
+ const userInfoStore = useUserInfo();
307
+ if (userInfoStore.isLogin) {
308
+ const filteredRoutes = filterRoutes(this.appInfo.Routes, userInfoStore as any);
309
+ addAppRoutes(filteredRoutes);
310
+ this.appInfo.defaultPage = findFirstPage(filteredRoutes) || '';
311
+ if (this.appInfo.defaultPage) {
312
+ this.menuLoaded = true;
313
+ continueNavigation(this.appInfo.defaultPage);
314
+ }
315
+ }
316
+ },
317
+
318
+ /**
319
+ * 根据地址,返回组合地址结构,/类型/子应用名/#/路由地址
320
+ * @param path 路由地址
321
+ * @returns
322
+ */
323
+ formatRoute(path: string): string {
324
+ let fullPath = path;
325
+
326
+ if (!path.includes('#')) {
327
+ if (this.appInfo.AppCode)
328
+ fullPath = '/' + this.appInfo.Action.toLowerCase() + '/' + this.appInfo.AppCode + '/#' + path;
329
+ else fullPath = '/#' + path;
330
+ } else if (path.startsWith('#')) {
331
+ fullPath = '/' + this.appInfo.Action.toLowerCase() + '/' + this.appInfo.AppCode + '/' + path;
332
+ }
333
+ return fullPath;
334
+ },
335
+
336
+ /**
337
+ * 应用导航,菜单路由,都使用此处导航
338
+ * @param path 路由地址
339
+ */
340
+ push(path: string): void {
341
+ let menuItem = this.findRoute(path);
342
+ if (menuItem) {
343
+ // 菜单路由,显示在Tab内
344
+ usePageInfo().setTabActive(path);
345
+ }
346
+ nextTick(() => {
347
+ if (isBaseMicroApp()) {
348
+ // 跨应用路由
349
+ path = this.formatRoute(path);
350
+ if (this.microRouter) {
351
+ /// 基座路由
352
+ let microRouter = this.microRouter as Router;
353
+ microRouter.push({ path });
354
+ } else {
355
+ AppRouter.push({ path });
356
+ }
357
+ } else {
358
+ // 非微应用,直接使用当前应用路由AppRouter
359
+ AppRouter.push({ path });
360
+ }
361
+ });
362
+ },
363
+
364
+ /**
365
+ * 快速查找路由信息
366
+ * @param key 路由地址
367
+ * @returns
368
+ */
369
+ findRoute(key: string): RouteRecord | undefined {
370
+ return this.appInfo.flattenRoutes[key];
371
+ },
372
+
373
+ /**
374
+ * 根据路由信息返回组件实例
375
+ * @param component 组件
376
+ * @param route 路由
377
+ * @returns 组件实例
378
+ */
379
+ cacheComponent(component: Component, route: { path: string }) {
380
+ // 从映射中获取当前路由路径对应的组件包装器
381
+ let wrapper = wrapperMap.get(route.path);
382
+ if (!wrapper) {
383
+ // 是否设置了缓存组件
384
+ if (this.CachedComponents.includes(route.path)) {
385
+ wrapper = {
386
+ // 设置组件包装器的名称为路由路径
387
+ name: route.path,
388
+ render() {
389
+ // 使用h函数创建一个组件实例
390
+ return h(component);
391
+ },
392
+ };
393
+ wrapperMap.set(route.path, wrapper);
394
+ } else return component;
395
+ }
396
+
397
+ // 返回当前路由路径对应的组件包装器
398
+ return wrapper;
399
+ },
400
+
401
+ /**
402
+ * 删除缓存组件
403
+ * @param path 路由地址
404
+ */
405
+ excludeComponent(path: string): void {
406
+ // 检查是否存在
407
+ if (!this.ExcludeComponents.includes(path)) {
408
+ this.ExcludeComponents.push(path);
409
+ }
410
+ // 删除缓存
411
+ this.CachedComponents.splice(this.CachedComponents.indexOf(path), 1);
412
+ // 删除包装器
413
+ wrapperMap.delete(path);
414
+ },
415
+
416
+ /**
417
+ * 路由路径层级查询,返回面包屑
418
+ */
419
+ matchedRoutes(key: string): RouteRecord[] {
420
+ const matched: RouteRecord[] = [];
421
+ const matchedRoute = this.findRoute(key);
422
+
423
+ if (matchedRoute) {
424
+ matched.push(matchedRoute);
425
+ if (matchedRoute.parent) {
426
+ const subMatched = this.matchedRoutes(matchedRoute.parent.path);
427
+ matched.push(...subMatched);
428
+ }
429
+ }
430
+ return matched.reverse();
431
+ },
432
+
433
+ clear() {
434
+ /// 清空信息
435
+ this.appInfo = {
436
+ Id: '',
437
+ Name: '',
438
+ AppCode: '',
439
+ Version: '',
440
+ Host: '',
441
+ Source: AppSource.Manual,
442
+ Action: AppAction.App,
443
+ Path: '',
444
+ Icon: '',
445
+ Routes: [],
446
+ flattenRoutes: {},
447
+ defaultPage: '',
448
+ Enabled: 1,
449
+ };
450
+ this.CachedComponents.splice(0, this.CachedComponents.length);
451
+ this.ExcludeComponents.splice(0, this.ExcludeComponents.length);
452
+ this.appList.splice(0, this.appList.length);
453
+ this.menuLoaded = false;
454
+ },
455
+
456
+ logout() {
457
+ if (this.microRouter) {
458
+ // 避免界面跳动
459
+ // this.microRouter.push({ path: LOGIN_PATH + '#/' });
460
+ if (this.microActions && typeof this.microActions['login'] === 'function') {
461
+ this.microActions['login']();
462
+ }
463
+ } else AppRouter.push({ path: LOGIN_PATH + '#/' });
464
+ },
465
+ },
466
+ persist: {
467
+ key: APPINFO_STORE_KEY,
468
+ storage: localStorage,
469
+ pick: ['appList'],
470
+ },
471
+ });
@@ -0,0 +1,117 @@
1
+ import { API_HOST, ApiResponse, httpPost, IUrlInfo, ResStatus, SERVER_HOST } from '@skyfox2000/fapi';
2
+
3
+ import { HostInfo, MainOpenApis } from '@skyfox2000/microbase';
4
+
5
+ import { defineStore } from 'pinia';
6
+
7
+ // import { Cache, CacheKeys } from '@/utils/cache';
8
+
9
+ // const HOSTINFO_STORE_KEY = 'hostInfoStore';
10
+
11
+ /** 站点相关接口 */
12
+ const HostUrlList: {
13
+ /** 站点信息 */
14
+ host: IUrlInfo;
15
+ } = {
16
+ host: {
17
+ api: 'SITEHOST_API',
18
+ url: '/openapi/RCSiteHostSrv/get',
19
+ fieldMap: {
20
+ hostId: 'Id',
21
+ hostName: 'Title',
22
+ },
23
+ loadingText: '站点配置加载中……',
24
+ // 不显示错误
25
+ hideErrorToast: true,
26
+ },
27
+ };
28
+
29
+ export const useHostInfo = defineStore('hostInfo', {
30
+ state: (): {
31
+ hostInfo: HostInfo;
32
+ } => ({
33
+ hostInfo: {
34
+ Host: '',
35
+ Title: '',
36
+ API_HOST: {},
37
+ SERVER_HOST: {},
38
+ ExtraProps: {},
39
+ ExtraPropLines: [],
40
+ },
41
+ }),
42
+ actions: {
43
+ /**
44
+ * 加载站点信息,如加载失败,则使用本地缓存或默认参数
45
+ * @param hostApi 启动配置主机地址
46
+ * @param hostKey 站点信息,默认为当前主域名
47
+ * @param mainOpenApis 宿主机开放接口
48
+ */
49
+ async loadHostInfo(hostApi: string, hostKey?: string, mainOpenApis?: MainOpenApis): Promise<void> {
50
+ if (mainOpenApis) {
51
+ this._setHostInfo(mainOpenApis.getHostInfo());
52
+ return;
53
+ }
54
+ return new Promise((resolve) => {
55
+ if (!API_HOST['SITEHOST_API']) API_HOST['SITEHOST_API'] = hostApi;
56
+
57
+ const host = hostKey || window.location.origin;
58
+ // const cacheKey = `${CacheKeys.HOST_INFO}${host}`;
59
+
60
+ // 尝试从缓存获取
61
+ // const cachedHostInfo = Cache.getData<HostInfo>(cacheKey);
62
+ // if (cachedHostInfo) {
63
+ // this._setHostInfo(cachedHostInfo);
64
+ // resolve();
65
+ // return;
66
+ // }
67
+
68
+ // 从服务器获取
69
+ httpPost<HostInfo>(HostUrlList.host, {
70
+ Query: {
71
+ Host: host,
72
+ },
73
+ }).then((result: ApiResponse<HostInfo> | null) => {
74
+ if (result?.status === ResStatus.SUCCESS && result.data) {
75
+ const hostInfo = result.data as HostInfo;
76
+ this._setHostInfo(hostInfo);
77
+
78
+ // 使用缓存代替持久化存储
79
+ // 检查是否有 lastTime 字段
80
+ // if (hostInfo.lastTime) {
81
+ // Cache.setWithServerTime(cacheKey, hostInfo, hostInfo.lastTime);
82
+ // }
83
+ // 不存储,避免数据无法更新
84
+ }
85
+ resolve();
86
+ });
87
+ });
88
+ },
89
+
90
+ /**
91
+ * 设置主机信息(私有方法)
92
+ */
93
+ _setHostInfo(hostInfo: HostInfo): void {
94
+ this.hostInfo = {
95
+ ...this.hostInfo,
96
+ ...hostInfo,
97
+ };
98
+ if (this.hostInfo.API_HOST) {
99
+ for (const key in this.hostInfo.API_HOST) API_HOST[key] = this.hostInfo.API_HOST[key];
100
+ }
101
+ if (this.hostInfo.SERVER_HOST) {
102
+ for (const key in this.hostInfo.SERVER_HOST) SERVER_HOST[key] = this.hostInfo.SERVER_HOST[key];
103
+ }
104
+ },
105
+
106
+ getHostInfo(): HostInfo {
107
+ return this.hostInfo;
108
+ },
109
+ },
110
+ // 使用自定义数据缓存
111
+ persist: false,
112
+ // persist: {
113
+ // key: HOSTINFO_STORE_KEY,
114
+ // storage: localStorage,
115
+ // pick: ['hostInfo'],
116
+ // },
117
+ });