@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,131 @@
1
+ export type ButtonType = 'link' | 'default' | 'primary' | 'ghost' | 'dashed' | 'text';
2
+
3
+ import { GridControl } from '@/typings/table.d';
4
+ import { EditorControl } from '@/typings/form.d';
5
+ import { PageControl } from '@/typings/page.d';
6
+ import { AnyData } from '@skyfox2000/fapi';
7
+ import { VNode, Ref, ShallowRef } from 'vue';
8
+ export type RowRecord = Record<string, any> | RowRecord[];
9
+ /**
10
+ * 工具/操作按钮定义
11
+ */
12
+ export interface ButtonTool {
13
+ /**
14
+ * 按钮关键字,与权限控制相关
15
+ * 功能码,必须唯一
16
+ * 字符串配置时,使用默认设置
17
+ */
18
+ key: string;
19
+ /**
20
+ * 文字
21
+ */
22
+ label?: string;
23
+ /**
24
+ * 状态文字,与状态图标对应
25
+ * 可切换
26
+ */
27
+ labels?: string[];
28
+ /**
29
+ * 图标
30
+ */
31
+ icon?: string;
32
+ /**
33
+ * 状态图标
34
+ */
35
+ icons?: string[];
36
+ /**
37
+ * 图标状态位
38
+ * - 当前文字
39
+ * - 当前图标
40
+ */
41
+ iconStatus?: number;
42
+ /**
43
+ * 下拉操作
44
+ */
45
+ children?: (IconTool | ButtonTool)[];
46
+ /**
47
+ * 控制表单控制自动弹窗
48
+ * - 配置表单控制器visible
49
+ * - 配置后,可不配置click事件(click自动执行)
50
+ */
51
+ formVisible?: Ref;
52
+ /**
53
+ * /// 主工具栏批量操作
54
+ * @param pageCtrl 页面控制对象
55
+ * @param gridCtrl 表格控制对象
56
+ * @param record 数据表行记录
57
+ * - 配置formVibible后,可自动执行click事件
58
+ * - 实现 grid.rowData.value = record
59
+ * - 实现 formVisible.value = true
60
+ * - 未配置formVisible时,会提示未配置点击处理事件
61
+ * 操作
62
+ * @example
63
+ click: <T>(_: PageControl<T>, _: GridControl<T>, row: T) => {
64
+ const rowData = row as OrderEntity;
65
+ },
66
+ * @returns
67
+ */
68
+ click?: <T>(pageCtrl: PageControl<T>, gridCtrl?: GridControl<T>, record?: T | RowRecord | string[]) => void;
69
+ /**
70
+ * 按钮主样式
71
+ */
72
+ type?: ButtonType;
73
+ /**
74
+ * 是否禁用
75
+ * @example
76
+ visible: (row: OrderEntity) => { }
77
+ */
78
+ disabled?: boolean | ((record) => boolean); /// 表格操作
79
+ /**
80
+ * 是否可见
81
+ * @example
82
+ visible: (row: OrderEntity) => { }
83
+ */
84
+ visible?: boolean | ((record) => boolean); /// 表格操作
85
+ /**
86
+ * 是否弹出确认框,确认操作由确认方法执行
87
+ */
88
+ confirm?: boolean;
89
+ /**
90
+ * 确认框提示文字
91
+ */
92
+ confirmText?: string;
93
+ /**
94
+ * 警告色
95
+ */
96
+ danger?: boolean;
97
+ /**
98
+ * 自定义样式
99
+ */
100
+ class?: string;
101
+ /**
102
+ * 图标属性
103
+ */
104
+ iconProps?: Record<string, any>;
105
+ /**
106
+ * 下拉组件
107
+ */
108
+ dropdown?: string;
109
+ /**
110
+ * 下拉容器样式
111
+ */
112
+ dropdownClass?: string;
113
+ /**
114
+ * 角色权限控制
115
+ */
116
+ role?: string | string[];
117
+ /**
118
+ * 权限控制
119
+ */
120
+ permit?: string;
121
+ }
122
+
123
+ export type IconTool = Omit<ButtonTool, 'disabled' | 'children'> & {
124
+ disabled?: boolean;
125
+ children?: (IconTool | ButtonTool)[];
126
+ };
127
+
128
+ /**
129
+ * 工具/操作按钮定义组
130
+ */
131
+ export type ButtonTools = (IconTool | ButtonTool | string)[];
@@ -0,0 +1,73 @@
1
+ import { Ref, ShallowRef } from 'vue';
2
+ import { AnyData, IUrlInfo, ReqParams } from '@skyfox2000/fapi';
3
+ import { PageControl } from './page';
4
+
5
+ export interface TreeNode {
6
+ /**
7
+ * 节点名称
8
+ */
9
+ title: string;
10
+ /**
11
+ * 节点ID
12
+ */
13
+ key: string;
14
+ /**
15
+ * 节点子节点
16
+ */
17
+ children?: TreeNode[];
18
+ /**
19
+ * 节点数据
20
+ */
21
+ [key: string]: AnyData;
22
+ }
23
+ /**
24
+ * 树控制默认设置
25
+ */
26
+ export interface TreeControlOption {
27
+ /**
28
+ * 自动加载树,默认true
29
+ */
30
+ autoload: boolean;
31
+ }
32
+
33
+ /**
34
+ * 页面左侧树数据交互标准定义
35
+ */
36
+ export type TreeControl = TreeControlOption & {
37
+ /**
38
+ * 重新加载树数据
39
+ */
40
+ reload: Ref<boolean>;
41
+ /**
42
+ * 所属页面控制器
43
+ */
44
+ page: PageControl<AnyData>;
45
+ /**
46
+ * 当前选择节点
47
+ */
48
+ node: Ref<TreeNode | undefined>;
49
+ /**
50
+ * 当前表格查询条件
51
+ */
52
+ treeQuery?: ReqParams;
53
+ /**
54
+ * 当前树数据
55
+ */
56
+ data: ShallowRef<TreeNode[] | undefined>;
57
+ /**
58
+ * 字段转换控制
59
+ * - Key:目的字段
60
+ * - Value:源字段,支持模板 ${}
61
+ */
62
+ fieldMap?: Record<string, string>;
63
+ /**
64
+ * 树查询接口
65
+ * - 优先使用
66
+ * - 或使用PageData.urls.tree
67
+ */
68
+ url?: IUrlInfo;
69
+ /**
70
+ * 是否正在加载中
71
+ */
72
+ isTreeLoading: Ref<boolean>;
73
+ };
@@ -0,0 +1,162 @@
1
+ import { ImgHTMLAttributes } from 'vue';
2
+ import { AjaxResponse, IUrlInfo } from '@skyfox2000/fapi';
3
+
4
+ /**
5
+ * 上传文件的状态枚举
6
+ */
7
+ export enum UploadStatus {
8
+ /** 正在等待上传 */
9
+ Pending = 'pending',
10
+
11
+ /** 正在上传中 */
12
+ Uploading = 'uploading',
13
+
14
+ /** 上传成功 */
15
+ Success = 'success',
16
+
17
+ /** 上传失败 */
18
+ Error = 'error',
19
+
20
+ /** 在线 */
21
+ Online = 'online',
22
+ /** 下线 */
23
+ Offline = 'offline',
24
+ }
25
+
26
+ /**
27
+ * Minio文件格式定义
28
+ */
29
+ export interface MinioFile {
30
+ /**
31
+ * 唯一键,Etag
32
+ */
33
+ ETag: string;
34
+ /**
35
+ * 主键文件名
36
+ */
37
+ Key: string;
38
+ /**
39
+ * - 实际文件名
40
+ */
41
+ FileName?: string;
42
+ /**
43
+ * 文件大小
44
+ */
45
+ Size: number;
46
+ /**
47
+ * 在线状态
48
+ * - Online
49
+ * - Offline
50
+ */
51
+ Status: UploadStatus;
52
+ /**
53
+ * 所属桶
54
+ */
55
+ Bucket?: string;
56
+ /**
57
+ * 文件类型
58
+ */
59
+ Type?: string;
60
+ /**
61
+ * 上传时间
62
+ */
63
+ UpdateTime?: string;
64
+ /**
65
+ * 文件内容
66
+ * - base64
67
+ * - 二进制
68
+ */
69
+ Content?: string | Array;
70
+ }
71
+
72
+ /**
73
+ * 上传文件接口定义
74
+ */
75
+ export interface UploadFile<T = AjaxResponse> {
76
+ /** 文件的唯一标识符 */
77
+ uid: string;
78
+
79
+ /** 文件大小(可选) */
80
+ size?: number;
81
+
82
+ /** 文件名称 */
83
+ name: string;
84
+
85
+ /** 文件名(可选,用于特殊需求) */
86
+ fileName?: string;
87
+
88
+ /** 最后修改时间戳(可选) */
89
+ lastModified?: number;
90
+
91
+ /** 最后修改日期(可选) */
92
+ lastModifiedDate?: Date;
93
+
94
+ /** 文件的网络地址(可选) */
95
+ url?: string;
96
+
97
+ /** 文件上传状态 */
98
+ status?: UploadStatus;
99
+
100
+ /** 文件上传的百分比进度(0 到 100,单位:%) */
101
+ percent?: number;
102
+
103
+ /** 文件的缩略图 URL(可选) */
104
+ thumbUrl?: string;
105
+
106
+ /** 图片的跨域属性(对应 `<img>` 标签的 `crossorigin`) */
107
+ crossOrigin?: ImgHTMLAttributes['crossorigin'];
108
+
109
+ /** 原始文件对象(可选) */
110
+ originFileObj?: any;
111
+
112
+ /** 服务器返回的响应数据(根据 `T` 泛型定义) */
113
+ response?: T;
114
+
115
+ /** 上传错误信息(可选) */
116
+ error?: any;
117
+
118
+ /** 文件链接的附加属性(可用于自定义跳转逻辑等) */
119
+ linkProps?: any;
120
+
121
+ /** 文件类型(MIME 类型) */
122
+ type?: string;
123
+
124
+ /** XMLHttpRequest 对象(可选,底层上传使用的请求对象) */
125
+ xhr?: T;
126
+
127
+ /** 文件预览 URL(可选,用于生成临时预览图片等) */
128
+ preview?: string;
129
+
130
+ /**
131
+ * 自定义上传参数
132
+ * 仅支持字符串或二进制
133
+ */
134
+ params: Record<string, string | Blob>;
135
+
136
+ /**
137
+ * minio文件信息
138
+ */
139
+ minioFile?: MinioFile;
140
+ }
141
+
142
+ /**
143
+ * Excel文件上传参数
144
+ */
145
+ export interface ExcelFileParams {
146
+ /**
147
+ * 基础路径
148
+ */
149
+ basePath?: string;
150
+ /**
151
+ * 上传地址和参数
152
+ */
153
+ uploadUrl: IUrlInfo;
154
+ /**
155
+ * 重复数据检测,限制重复的字段
156
+ */
157
+ duplicateRules?: Array<string>;
158
+ /**
159
+ * 重复数据服务端检测
160
+ */
161
+ duplicateUrl?: IUrlInfo;
162
+ }
@@ -0,0 +1,70 @@
1
+ import { IUrlInfo, RequestOptions } from '@skyfox2000/fapi';
2
+
3
+ /**
4
+ * 请求相关常用地址接口定义
5
+ */
6
+ export interface ReqUrls {
7
+ /**
8
+ * 获取分页数据列表
9
+ */
10
+ find?: IUrlInfo;
11
+ /**
12
+ * 获取数据列表
13
+ */
14
+ list?: IUrlInfo;
15
+ /**
16
+ * 获取树列表
17
+ */
18
+ tree?: IUrlInfo;
19
+ /**
20
+ * 获取数据详情
21
+ */
22
+ detail?: IUrlInfo;
23
+ /**
24
+ * 默认保存数据地址
25
+ */
26
+ save?: IUrlInfo;
27
+ /**
28
+ * 默认新增数据地址
29
+ */
30
+ insert?: IUrlInfo;
31
+ /**
32
+ * 默认更新数据地址
33
+ */
34
+ update?: IUrlInfo;
35
+ /**
36
+ * 默认删除数据地址
37
+ */
38
+ delete?: IUrlInfo;
39
+ /**
40
+ * 默认上传地址
41
+ */
42
+ upload?: IUrlInfo;
43
+ /**
44
+ * 默认下载地址
45
+ */
46
+ download?: IUrlInfo;
47
+
48
+ [key: string]: IUrlInfo | undefined;
49
+ }
50
+
51
+ export interface ApiUrls {
52
+ /**
53
+ * 所使用的API地址
54
+ * - API_HOST字段名
55
+ */
56
+ api: string;
57
+ /**
58
+ * 是否需要授权Token
59
+ * 方法内配置授权,返回是否允许继续调用
60
+ * @param options 请求实际参数配置
61
+ * @param urlInfo 前端请求配置
62
+ * @param token 当前token
63
+ * @returns 是否允许调用接口
64
+ */
65
+ authorize?: boolean | ((options: RequestOptions, urlInfo: IUrlInfo, token: string) => boolean);
66
+ /**
67
+ * 常用接口定义
68
+ */
69
+ urls: ReqUrls;
70
+ }
@@ -0,0 +1,175 @@
1
+ import { FrontCache, httpPost, ResStatus } from '@skyfox2000/fapi';
2
+
3
+ /** 缓存Key枚举 */
4
+ export enum CacheKeys {
5
+ // 系统级配置(不常变化)
6
+ SYS_CONFIG = 'SYS_CONFIG_', // 系统配置
7
+ APP_MENU = 'APP_MENU_', // 应用菜单
8
+ DICT_TYPE = 'DICT_TYPE_', // 字典类型
9
+ HOST_INFO = 'HOST_INFO_', // 站点信息
10
+
11
+ // 用户级配置(登录后加载)
12
+ APP_PERMITS = 'APP_PERMITS_', // 应用权限
13
+ USER_SETTINGS = 'USER_SETTINGS_', // 用户设置
14
+
15
+ // 业务数据(按需缓存)
16
+ DICT_DATA = 'DICT_DATA_', // 字典数据
17
+ COMMON_OPTIONS = 'COMMON_OPTIONS_', // 通用选项数据
18
+ }
19
+
20
+ /** 带时间戳的缓存数据结构 */
21
+ interface TimedCacheData<T> {
22
+ data: T;
23
+ lastTime: number;
24
+ }
25
+
26
+ /**
27
+ * 缓存操作类
28
+ */
29
+ export class Cache {
30
+ /**
31
+ * 设置缓存数据(带服务器时间)
32
+ */
33
+ public static setWithServerTime<T>(key: string, data: T, lastTime: number): void {
34
+ const timedData: TimedCacheData<T> = {
35
+ data,
36
+ lastTime,
37
+ };
38
+ FrontCache.set({ key, storage: 'local' }, timedData);
39
+ }
40
+
41
+ /**
42
+ * 设置缓存数据
43
+ */
44
+ public static setData<T>(key: string, data: T): void {
45
+ FrontCache.set({ key, storage: 'local' }, data);
46
+ }
47
+
48
+ /**
49
+ * 获取缓存数据
50
+ */
51
+ public static getData<T>(key: string): T | null {
52
+ const data = FrontCache.get({ key, storage: 'local' });
53
+ if (data && Cache.isTimedData(data)) {
54
+ return data.data;
55
+ }
56
+ return data ?? null;
57
+ }
58
+
59
+ /**
60
+ * 清除缓存
61
+ */
62
+ public static remove(key: string): void {
63
+ FrontCache.remove({ key, storage: 'local' });
64
+ }
65
+
66
+ /**
67
+ * 清理指定前缀的缓存 (基于 localStorage 实现,因为 FrontCache 未提供此方法)
68
+ */
69
+ public static clearByPrefix(prefix: string): void {
70
+ // 遍历 localStorage 查找匹配前缀的键
71
+ for (let i = 0; i < localStorage.length; i++) {
72
+ const key = localStorage.key(i);
73
+ if (key && key.startsWith('frontCache::' + prefix)) {
74
+ localStorage.removeItem(key);
75
+ }
76
+ }
77
+
78
+ // 如果此版本的 FrontCache 使用了内存缓存,我们也需要清理它
79
+ // 这里我们无法直接访问 FrontCache 的内存缓存,但我们可以利用 get/remove 方法来处理
80
+ // 这是一个不完美的解决方案,但在当前约束下的最佳选择
81
+ }
82
+
83
+ /**
84
+ * 清理所有缓存
85
+ */
86
+ public static clearAll(): void {
87
+ // 清理所有 localStorage 中的 frontCache 项
88
+ for (let i = localStorage.length - 1; i >= 0; i--) {
89
+ const key = localStorage.key(i);
90
+ if (key && key.startsWith('frontCache::')) {
91
+ localStorage.removeItem(key);
92
+ }
93
+ }
94
+
95
+ // 清理其他存储位置的缓存需要针对特定的 key 调用 remove
96
+ // 由于我们无法枚举 FrontCache 内存中的所有键,这也是不完美的解决方案
97
+ }
98
+
99
+ /**
100
+ * 判断是否是带时间戳的数据
101
+ */
102
+ private static isTimedData(data: any): data is TimedCacheData<any> {
103
+ return (
104
+ data && typeof data === 'object' && 'data' in data && 'lastTime' in data && typeof data.lastTime === 'number'
105
+ );
106
+ }
107
+ }
108
+
109
+ /** 最后更新时间信息接口 */
110
+ export interface LastTimeMap {
111
+ [key: string]: number;
112
+ }
113
+
114
+ /**
115
+ * 初始化缓存检查
116
+ */
117
+ export async function initCacheCheck(): Promise<void> {
118
+ try {
119
+ // 获取服务器最新时间信息
120
+ const result = await httpPost<LastTimeMap>(
121
+ {
122
+ api: 'PLATFORM_API',
123
+ url: '/api/SysCacheSvr/getLastTime',
124
+ loadingText: false,
125
+ },
126
+ {},
127
+ );
128
+
129
+ if (result?.status === ResStatus.SUCCESS) {
130
+ const lastTimeMap = result.data as LastTimeMap;
131
+
132
+ // 遍历所有缓存Key
133
+ Object.keys(lastTimeMap).forEach((key) => {
134
+ const newLastTime = lastTimeMap[key];
135
+
136
+ // 检查所有支持的存储类型
137
+ const storages = ['local', 'session'] as const;
138
+ storages.forEach((type) => {
139
+ const storage = type === 'local' ? localStorage : sessionStorage;
140
+
141
+ // 遍历存储中的所有key
142
+ for (let i = 0; i < storage.length; i++) {
143
+ const storageKey = storage.key(i);
144
+ if (!storageKey) continue;
145
+
146
+ // 检查key是否匹配
147
+ if (storageKey.endsWith(key)) {
148
+ try {
149
+ const value = JSON.parse(storage.getItem(storageKey)!);
150
+ // 检查是否是带时间戳的数据结构
151
+ if (
152
+ value &&
153
+ typeof value === 'object' &&
154
+ 'lastTime' in value &&
155
+ typeof value.lastTime === 'number'
156
+ ) {
157
+ // 比较时间戳
158
+ if (value.lastTime !== newLastTime) {
159
+ // 时间不一致,删除缓存
160
+ storage.removeItem(storageKey);
161
+ }
162
+ }
163
+ } catch (e) {
164
+ // 解析失败,跳过
165
+ continue;
166
+ }
167
+ }
168
+ }
169
+ });
170
+ });
171
+ }
172
+ } catch (error) {
173
+ console.error('检查缓存更新失败', error);
174
+ }
175
+ }