@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,304 @@
1
+ import { hostUrl, IUrlInfo } from '@skyfox2000/fapi';
2
+
3
+ import { getToken } from '@/utils/main-openapis';
4
+ import { UploadFile, UploadStatus } from '@/typings/upload.d';
5
+ import dayjs from 'dayjs';
6
+
7
+ export class path {
8
+ /**
9
+ * 连接路径参数,已判断 undefined 或 null 值
10
+ * @param args 路径参数数组
11
+ * @returns 连接后的路径字符串
12
+ */
13
+ public static join(...args: (string | undefined | null)[]): string {
14
+ // 忽略 undefined 或 null
15
+ const validArgs = args.filter((arg) => arg !== undefined && arg !== null);
16
+ // 连接路径
17
+ const result = validArgs.join('/');
18
+ // 确保不会重复斜杠
19
+ return result.replace(/[\/]+/, '/');
20
+ }
21
+ }
22
+
23
+ /**
24
+ * 异步文件上传类
25
+ */
26
+ export class AsyncUploader {
27
+ /**
28
+ * 设置 API 端点和最大并发数,所有上传文件通过该类控制
29
+ */
30
+ private urlInfo: IUrlInfo;
31
+
32
+ /**
33
+ * 最大并发上传数
34
+ */
35
+ private maxConcurrent: number;
36
+
37
+ /**
38
+ * 控制上传任务的中断信号
39
+ */
40
+ private abortController?: AbortController;
41
+
42
+ /**
43
+ * AsyncUploader 构造函数
44
+ * @param urlInfo 文件上传的 API 配置(IUrlInfo 对象)
45
+ * @param maxConcurrent 最大允许并发上传的文件数量
46
+ */
47
+ constructor(urlInfo: IUrlInfo, maxConcurrent: number) {
48
+ this.urlInfo = urlInfo;
49
+ this.maxConcurrent = maxConcurrent;
50
+ }
51
+
52
+ /**
53
+ * 上传多个文件,控制并发数量
54
+ * @param files 文件列表(File[] 或 FileList)
55
+ * @param onProgress 上传进度回调
56
+ * @param onComplete 上传完成回调
57
+ */
58
+ public async uploadFiles(
59
+ fileList: UploadFile[],
60
+ onProgress?: (file: UploadFile) => void,
61
+ onComplete?: (files: UploadFile[]) => void,
62
+ ): Promise<void> {
63
+ if (!fileList.length) return;
64
+
65
+ const maxConcurrent = Math.min(this.maxConcurrent, fileList.length);
66
+ const pendingFiles: UploadFile[] = [];
67
+ for (const file of fileList) {
68
+ switch (file.status) {
69
+ case UploadStatus.Success:
70
+ case UploadStatus.Online:
71
+ case UploadStatus.Offline:
72
+ // 已在服务器上,不处理
73
+ break;
74
+ default:
75
+ file.status = UploadStatus.Pending;
76
+ pendingFiles.push(file);
77
+ break;
78
+ }
79
+ }
80
+ const activeUploads: Promise<void>[] = [];
81
+
82
+ // 创建新的中止控制器
83
+ this.abortController = new AbortController();
84
+
85
+ try {
86
+ // 启动并发上传任务
87
+ while (activeUploads.length < maxConcurrent && pendingFiles.length > 0) {
88
+ const file = pendingFiles.shift();
89
+ if (!file) break;
90
+
91
+ activeUploads.push(this.handleFileStatus(file, activeUploads, pendingFiles, onProgress));
92
+ }
93
+
94
+ // 等待所有上传任务完成
95
+ await Promise.all(activeUploads);
96
+ onComplete?.(fileList);
97
+ } catch (error) {
98
+ console.error('上传失败:', error);
99
+ fileList.forEach((file) => {
100
+ file.status = UploadStatus.Error;
101
+ file.error = error instanceof Error ? error : new Error('上传失败');
102
+ onProgress?.(file);
103
+ });
104
+ onComplete?.(fileList);
105
+ }
106
+ }
107
+
108
+ /**
109
+ * 处理单个文件的上传逻辑
110
+ * @param file 当前上传的文件
111
+ * @param activeUploads 当前正在上传的文件列表
112
+ * @param pendingFiles 等待上传的文件列表
113
+ * @param onProgress 上传进度回调
114
+ */
115
+ private async handleFileStatus(
116
+ file: UploadFile,
117
+ activeUploads: Promise<void>[],
118
+ pendingFiles: UploadFile[],
119
+ onProgress?: (file: UploadFile) => void,
120
+ ): Promise<void> {
121
+ try {
122
+ // 更新文件状态为"正在上传"
123
+ file.status = UploadStatus.Uploading;
124
+
125
+ await this.uploadFile(file, this.abortController!.signal, (percent) => {
126
+ file.percent = percent;
127
+ onProgress?.(file);
128
+ });
129
+
130
+ // 更新文件状态为"上传成功"
131
+ file.status = UploadStatus.Success;
132
+ } catch (error) {
133
+ // 更新文件状态为"上传失败"
134
+ file.status = UploadStatus.Error;
135
+ file.error = error instanceof Error ? error : new Error('上传失败');
136
+ console.error(file.error);
137
+ } finally {
138
+ // 启动下一个上传任务
139
+ if (pendingFiles.length > 0) {
140
+ const nextFile = pendingFiles.shift();
141
+ if (nextFile) {
142
+ activeUploads.push(this.handleFileStatus(nextFile, activeUploads, pendingFiles, onProgress));
143
+ }
144
+ }
145
+ }
146
+ }
147
+
148
+ /**
149
+ * 使用 XMLHttpRequest 上传文件
150
+ * @param file 文件对象
151
+ * @param signal 中断信号
152
+ * @param onProgress 上传进度回调
153
+ */
154
+ public async uploadFile(
155
+ file: UploadFile,
156
+ signal: AbortSignal,
157
+ onProgress: (percent: number) => void,
158
+ ): Promise<UploadFile> {
159
+ // 以 Promise 化的方式处理上传请求
160
+ return new Promise((resolve, reject) => {
161
+ // 创建表单数据
162
+ const formData = new FormData();
163
+ formData.append('file', file.originFileObj as File);
164
+
165
+ // 添加 params 参数
166
+ if (file.params) {
167
+ for (const key in file.params) {
168
+ formData.append(key, file.params[key]);
169
+ }
170
+ }
171
+
172
+ // 创建 XMLHttpRequest 对象
173
+ const xhr = new XMLHttpRequest();
174
+ const url = hostUrl(this.urlInfo);
175
+ if (url === false) return Promise.resolve(null);
176
+ xhr.open('POST', url, true);
177
+
178
+ // 设置请求头
179
+ if (this.urlInfo.header) {
180
+ if (typeof this.urlInfo.header === 'object') {
181
+ Object.entries(this.urlInfo.header).forEach(([key, value]) => {
182
+ xhr.setRequestHeader(key, value);
183
+ });
184
+ }
185
+ }
186
+
187
+ // 添加授权 Token(如果需要)
188
+ if (this.urlInfo.authorize) {
189
+ const token = getToken(); // 假设 getToken 是获取 Token 的方法
190
+ if (!token) {
191
+ reject(new Error('未授权或授权过期'));
192
+ return;
193
+ }
194
+ xhr.setRequestHeader('Authorization', 'Bearer ' + token);
195
+ }
196
+
197
+ // 监听上传进度事件
198
+ xhr.upload.addEventListener('progress', (event) => {
199
+ if (event.lengthComputable && event.total > 0) {
200
+ const percent = Math.round((event.loaded / event.total) * 100); // 计算进度百分比
201
+ onProgress(percent);
202
+ }
203
+ });
204
+
205
+ // 监听加载完成事件
206
+ xhr.addEventListener('load', () => {
207
+ if (xhr.status >= 200 && xhr.status < 300) {
208
+ // 检查返回的内容类型是否是 JSON
209
+ const contentType = xhr.getResponseHeader('Content-Type');
210
+ if (!contentType || !contentType.includes('application/json')) {
211
+ reject(new Error('返回的结果不是 JSON 格式'));
212
+ return;
213
+ }
214
+
215
+ try {
216
+ // 解析 JSON 数据
217
+ const res = JSON.parse(xhr.response);
218
+ // 判断上传是否成功
219
+ if (res.status === 'success') {
220
+ // 上传成功
221
+ if (res.data)
222
+ file.minioFile = {
223
+ ETag: res.data.ETag,
224
+ Bucket: res.data.Bucket,
225
+ Key: res.data.Key,
226
+ Size: res.data.Size,
227
+ UpdateTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
228
+ Status: UploadStatus.Online,
229
+ };
230
+ resolve(file); // 上传成功,返回解析后的 JSON 数据
231
+ } else {
232
+ // 如果 status 不是 success,则视为失败,提取 msg 作为错误信息
233
+ const error = res.msg;
234
+ reject(new Error(error));
235
+ }
236
+ } catch (error) {
237
+ // 如果 JSON 格式无效,抛出错误
238
+ reject(new Error('无法解析返回的 JSON 数据: ' + error));
239
+ }
240
+ } else {
241
+ // 根据 HTTP 状态码判断上传失败的原因
242
+ reject(new Error(`上传失败,状态码:${xhr.status}`));
243
+ }
244
+ });
245
+
246
+ // 监听网络错误事件
247
+ xhr.addEventListener('error', () => {
248
+ reject(new Error('上传失败,网络异常'));
249
+ });
250
+
251
+ // 发送请求
252
+ xhr.send(formData);
253
+
254
+ // 绑定中断信号
255
+ signal.addEventListener('abort', () => {
256
+ xhr.abort(); // 中断上传
257
+ reject(new Error('上传已取消'));
258
+ });
259
+ });
260
+ }
261
+
262
+ /**
263
+ * 取消当前所有的上传任务
264
+ */
265
+ public cancelUpload(): void {
266
+ if (this.abortController) {
267
+ this.abortController.abort(); // 触发中断信号
268
+ }
269
+ }
270
+ }
271
+
272
+ // // 使用示例
273
+ // (async () => {
274
+ // // 创建上传器实例,指定 API 配置和最大并发数
275
+ // const urlInfo: IUrlInfo = {
276
+ // url: 'https://your-api-endpoint.com/upload',
277
+ // header: {
278
+ // 'Content-Type': 'multipart/form-data',
279
+ // },
280
+ // authorize: true, // 需要授权
281
+ // };
282
+
283
+ // const uploader = new AsyncUploader(urlInfo, 3);
284
+
285
+ // // 模拟文件列表
286
+ // const fileList: File[] = [
287
+ // /* 添加你的文件 */
288
+ // ];
289
+
290
+ // try {
291
+ // // 开始上传文件
292
+ // await uploader.upload(
293
+ // fileList,
294
+ // (file) => {
295
+ // console.log(`${file.name} 上传进度:${file.percent}% (${file.status})`);
296
+ // },
297
+ // (files) => {
298
+ // console.log('所有文件上传完成:', files);
299
+ // },
300
+ // );
301
+ // } catch (error) {
302
+ // console.error('上传错误:', error);
303
+ // }
304
+ // })();