@skyfox2000/webui 1.5.10 → 1.5.11
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/lib/assets/modules/{baseLayout-BuQjrozB.js → baseLayout-CRSIlLKU.js} +3 -3
- package/lib/assets/modules/file-upload-CrA5-gqr.js +211 -0
- package/lib/assets/modules/{index-CW_ZCHWs.js → index-CA_H2eOk.js} +1 -1
- package/lib/assets/modules/index-CW7dVG4Z.js +372 -0
- package/lib/assets/modules/index-Doi0zREW.js +114 -0
- package/lib/assets/modules/{menuTabs-BYSjomB7.js → menuTabs-DRoP9rnS.js} +27 -28
- package/lib/assets/modules/{toolIcon-D4vAp0qA.js → toolIcon-CghIoh0a.js} +1 -1
- package/lib/assets/modules/{upload-template-NU0Bpg4N.js → upload-template-D6r6X3vP.js} +101 -85
- package/lib/assets/modules/uploadList-CIGuBEpz.js +468 -0
- package/lib/es/AceEditor/index.js +3 -3
- package/lib/es/BasicLayout/index.js +2 -2
- package/lib/es/Error403/index.js +1 -1
- package/lib/es/Error404/index.js +1 -1
- package/lib/es/ExcelForm/index.js +196 -196
- package/lib/es/MenuLayout/index.js +2 -2
- package/lib/es/TemplateFile/index.js +4 -4
- package/lib/es/UploadForm/index.js +4 -4
- package/lib/locales/default.d.ts +15 -0
- package/lib/webui.css +1 -1
- package/lib/webui.es.js +1191 -1194
- package/package.json +3 -3
- package/src/components/content/dialog/excelForm.vue +2 -2
- package/src/components/form/upload/imageList.vue +0 -2
- package/src/components/form/upload/uploadList.vue +0 -3
- package/src/locales/default.ts +18 -3
- package/src/utils/data.ts +1 -1
- package/src/utils/excel-preview.ts +10 -10
- package/src/utils/excel-view.ts +6 -4
- package/src/utils/file-upload.ts +2 -2
- package/src/utils/micro-openapis.ts +4 -3
- package/src/utils/tools.ts +1 -1
- package/src/utils/upload-template.ts +2 -1
- package/lib/assets/modules/file-upload-DcusqXDb.js +0 -211
- package/lib/assets/modules/index-BlQB5KSU.js +0 -381
- package/lib/assets/modules/index-CekzHbWp.js +0 -114
- package/lib/assets/modules/uploadList-ENSsTfpD.js +0 -472
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyfox2000/webui",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.11",
|
|
4
4
|
"description": "后台前端通用组件定义, 支持国际化",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [],
|
|
@@ -67,9 +67,9 @@
|
|
|
67
67
|
"rollup": "^4.29.1",
|
|
68
68
|
"tailwindcss": "^3.4.17",
|
|
69
69
|
"typescript": "^5.7.2",
|
|
70
|
-
"vite": "^6.2.
|
|
70
|
+
"vite": "^6.2.7",
|
|
71
71
|
"vite-plugin-dts": "^4.5.4",
|
|
72
|
-
"vue-tsc": "^
|
|
72
|
+
"vue-tsc": "^3.2.1"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
75
|
"vue-i18n": "^11.2.2"
|
|
@@ -115,6 +115,7 @@ import {
|
|
|
115
115
|
processExcelFile,
|
|
116
116
|
path,
|
|
117
117
|
UploadFile,
|
|
118
|
+
csvToExcelView,
|
|
118
119
|
} from '@/index';
|
|
119
120
|
import { validateExcelUnified } from '@/utils/form-excel';
|
|
120
121
|
import { $t } from '@/locales/index';
|
|
@@ -496,7 +497,7 @@ const performDataValidation = async (buffer: ArrayBuffer): Promise<void> => {
|
|
|
496
497
|
const beforeUpload: UploadProps['beforeUpload'] = async (file) => {
|
|
497
498
|
const gridCtrl = props.gridCtrl;
|
|
498
499
|
if (!gridCtrl) {
|
|
499
|
-
message.error('
|
|
500
|
+
message.error($t('webui.components.content.excelForm.gridCtrlNotConfigured'));
|
|
500
501
|
return;
|
|
501
502
|
}
|
|
502
503
|
|
|
@@ -551,7 +552,6 @@ const beforeUpload: UploadProps['beforeUpload'] = async (file) => {
|
|
|
551
552
|
const csvText = decoder.decode(csvBuffer);
|
|
552
553
|
|
|
553
554
|
// 转换CSV为Excel格式用于验证
|
|
554
|
-
const { csvToExcelView } = await import('@/utils/excel-view');
|
|
555
555
|
const excelResult = await csvToExcelView(csvText, file.name);
|
|
556
556
|
if (!excelResult.success) {
|
|
557
557
|
throw new Error(excelResult.error || $t('webui.components.content.excelForm.csvProcessingFailed'));
|
|
@@ -92,8 +92,6 @@ const { t } = useI18n();
|
|
|
92
92
|
const displayList = ref<UploadFile[]>(props.fileList);
|
|
93
93
|
// Upload 组件的内部文件列表
|
|
94
94
|
const uploadList = ref<UploadFile[]>([]);
|
|
95
|
-
|
|
96
|
-
const fileUploader = ref();
|
|
97
95
|
const emit = defineEmits(['update:file-list']);
|
|
98
96
|
const acceptString = computed(() => (props.fileExt?.length ? props.fileExt.map((ext) => `.${ext}`).join(',') : ''));
|
|
99
97
|
|
|
@@ -109,9 +109,6 @@ const { errInfo } = inputFactory;
|
|
|
109
109
|
const displayList = ref<UploadFile[]>(props.fileList);
|
|
110
110
|
// Upload 组件的内部文件列表
|
|
111
111
|
const uploadList = ref<UploadFile[]>([]);
|
|
112
|
-
|
|
113
|
-
const fileUploader = ref();
|
|
114
|
-
const fileFolderUploader = ref();
|
|
115
112
|
const emit = defineEmits(['update:file-list']);
|
|
116
113
|
const acceptString = computed(() => (props.fileExt?.length ? props.fileExt.map((ext) => `.${ext}`).join(',') : ''));
|
|
117
114
|
|
package/src/locales/default.ts
CHANGED
|
@@ -286,7 +286,8 @@ export const defaultLocale = {
|
|
|
286
286
|
"noDataToSave": "错误!无保存数据!",
|
|
287
287
|
"saveSuccess": "保存成功!",
|
|
288
288
|
"conditionalDeleteForbidden": "错误!禁止无条件删除数据!",
|
|
289
|
-
"deleteSuccess": "删除成功!"
|
|
289
|
+
"deleteSuccess": "删除成功!",
|
|
290
|
+
"urlNotSet": "URL未设置: {urlKey}"
|
|
290
291
|
},
|
|
291
292
|
"download": {
|
|
292
293
|
"downloadFailed": "下载文件失败!",
|
|
@@ -309,11 +310,20 @@ export const defaultLocale = {
|
|
|
309
310
|
"duplicateCheckPassed": "重复性检验通过"
|
|
310
311
|
},
|
|
311
312
|
"options": {
|
|
312
|
-
"notConfigured": "未配置选项数据!"
|
|
313
|
+
"notConfigured": "未配置选项数据!",
|
|
314
|
+
"outFieldsFormatError": "outFields 格式错误:{sourceKey},必须是 ${index} 或者 ${index}.${key}"
|
|
313
315
|
},
|
|
314
316
|
"excelPreview": {
|
|
315
317
|
"previewUrlNotConfigured": "预览URL或Excel控制器未配置",
|
|
316
|
-
"fileLoadFailed": "文件加载失败"
|
|
318
|
+
"fileLoadFailed": "文件加载失败",
|
|
319
|
+
"csvProcessingFailed": "CSV格式处理失败",
|
|
320
|
+
"previewFile": "预览文件",
|
|
321
|
+
"previewFileXlsx": "预览文件.xlsx",
|
|
322
|
+
"previewFileCsv": "preview.csv",
|
|
323
|
+
"unsupportedRawFormat": "不支持的原始文件格式",
|
|
324
|
+
"unsupportedFileFormat": "不支持的文件格式",
|
|
325
|
+
"dataEmpty": "数据为空",
|
|
326
|
+
"excelProcessingFailed": "Excel处理失败"
|
|
317
327
|
},
|
|
318
328
|
"tools": {
|
|
319
329
|
"noClickHandler": "未配置点击处理事件!",
|
|
@@ -321,6 +331,7 @@ export const defaultLocale = {
|
|
|
321
331
|
"expandSearch": "展开搜索栏",
|
|
322
332
|
"collapseSearch": "折叠搜索栏",
|
|
323
333
|
"rowHeight": "行高调整",
|
|
334
|
+
"templateManagement": "模板管理",
|
|
324
335
|
"showCheckbox": "显示多选框",
|
|
325
336
|
"hideCheckbox": "隐藏多选框",
|
|
326
337
|
"expandRows": "展开记录行",
|
|
@@ -340,6 +351,10 @@ export const defaultLocale = {
|
|
|
340
351
|
"csvToExcelFailed": "CSV转Excel失败",
|
|
341
352
|
"csvProcessFailed": "CSV文件处理失败",
|
|
342
353
|
"unknownError": "未知错误"
|
|
354
|
+
},
|
|
355
|
+
"microOpenapis": {
|
|
356
|
+
"interfaceNotConfigured": "未配置{method}接口!",
|
|
357
|
+
"apiCallTimeout": "API调用超时: {method}"
|
|
343
358
|
}
|
|
344
359
|
}
|
|
345
360
|
}
|
package/src/utils/data.ts
CHANGED
|
@@ -36,7 +36,7 @@ const doPost = <T>(control: AnyControl, options: PostOptions<T>): Promise<ApiRes
|
|
|
36
36
|
const url = options.url;
|
|
37
37
|
// 验证URL
|
|
38
38
|
if (!url || !url.url) {
|
|
39
|
-
const errorMsg =
|
|
39
|
+
const errorMsg = $t('webui.utils.data.urlNotSet', { urlKey: options.urlKey });
|
|
40
40
|
console.warn(errorMsg);
|
|
41
41
|
return Promise.reject(new Error(errorMsg));
|
|
42
42
|
}
|
|
@@ -57,7 +57,7 @@ export const processCsvContent = async (content: string, filename: string = 'pre
|
|
|
57
57
|
fileName: csvResult.fileName!,
|
|
58
58
|
};
|
|
59
59
|
} else {
|
|
60
|
-
throw new Error(csvResult.error || '
|
|
60
|
+
throw new Error(csvResult.error || $t('webui.utils.excelPreview.csvProcessingFailed'));
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
63
|
|
|
@@ -68,7 +68,7 @@ export const processCsvContent = async (content: string, filename: string = 'pre
|
|
|
68
68
|
* @param filename 文件名
|
|
69
69
|
* @returns 处理结果
|
|
70
70
|
*/
|
|
71
|
-
export const processExcelContent = (content: string, mimeType?: string, filename: string = '
|
|
71
|
+
export const processExcelContent = (content: string, mimeType?: string, filename: string = $t('webui.utils.excelPreview.previewFileXlsx')) => {
|
|
72
72
|
const type = mimeType || 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
|
|
73
73
|
return {
|
|
74
74
|
success: true,
|
|
@@ -93,16 +93,16 @@ export const handleFileData = async (data: any, isRawMode: boolean = false) => {
|
|
|
93
93
|
return processExcelContent(data);
|
|
94
94
|
}
|
|
95
95
|
} else if (data instanceof ArrayBuffer || data instanceof Uint8Array) {
|
|
96
|
-
const blob = new Blob([data], {
|
|
96
|
+
const blob = new Blob([data as ArrayBuffer], {
|
|
97
97
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
98
98
|
});
|
|
99
99
|
return {
|
|
100
100
|
success: true,
|
|
101
101
|
blobUrl: URL.createObjectURL(blob),
|
|
102
|
-
fileName: '
|
|
102
|
+
fileName: $t('webui.utils.excelPreview.previewFileXlsx'),
|
|
103
103
|
};
|
|
104
104
|
} else {
|
|
105
|
-
throw new Error('
|
|
105
|
+
throw new Error($t('webui.utils.excelPreview.unsupportedRawFormat'));
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -111,7 +111,7 @@ export const handleFileData = async (data: any, isRawMode: boolean = false) => {
|
|
|
111
111
|
if (isCsvType(data.Type, data.FileName)) {
|
|
112
112
|
return await processCsvContent(data.Content, data.FileName || 'preview.csv');
|
|
113
113
|
} else if (isExcelType(data.Type, data.FileName)) {
|
|
114
|
-
return processExcelContent(data.Content, data.Type, data.FileName || '
|
|
114
|
+
return processExcelContent(data.Content, data.Type, data.FileName || $t('webui.utils.excelPreview.previewFileXlsx'));
|
|
115
115
|
} else {
|
|
116
116
|
return processExcelContent(data.Content);
|
|
117
117
|
}
|
|
@@ -119,12 +119,12 @@ export const handleFileData = async (data: any, isRawMode: boolean = false) => {
|
|
|
119
119
|
return {
|
|
120
120
|
success: true,
|
|
121
121
|
blobUrl: data.url,
|
|
122
|
-
fileName: data.fileName || '
|
|
122
|
+
fileName: data.fileName || $t('webui.utils.excelPreview.previewFileXlsx'),
|
|
123
123
|
};
|
|
124
124
|
} else if (typeof data === 'string') {
|
|
125
125
|
return await processCsvContent(data);
|
|
126
126
|
} else {
|
|
127
|
-
throw new Error('
|
|
127
|
+
throw new Error($t('webui.utils.excelPreview.unsupportedFileFormat'));
|
|
128
128
|
}
|
|
129
129
|
};
|
|
130
130
|
|
|
@@ -183,8 +183,8 @@ export const loadPreviewFile = async (
|
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
} catch (error: any) {
|
|
186
|
-
console.error('
|
|
187
|
-
message.error($t('webui.utils.excelPreview.fileLoadFailed') + '
|
|
186
|
+
console.error('预览文件加载错误', error);
|
|
187
|
+
message.error($t('webui.utils.excelPreview.fileLoadFailed') + ': ' + (error?.message || $t('webui.utils.formCsv.unknownError')));
|
|
188
188
|
throw error;
|
|
189
189
|
}
|
|
190
190
|
};
|
package/src/utils/excel-view.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* 统一处理Excel和CSV数据的显示预处理,支持错误标记
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { $t } from '@/locales/index';
|
|
7
|
+
|
|
6
8
|
/**
|
|
7
9
|
* Excel错误标记单元格
|
|
8
10
|
*/
|
|
@@ -193,7 +195,7 @@ export const toExcel = async (
|
|
|
193
195
|
const { headers, rows } = data;
|
|
194
196
|
|
|
195
197
|
if (headers.length === 0) {
|
|
196
|
-
throw new Error('
|
|
198
|
+
throw new Error($t('webui.utils.excelPreview.dataEmpty'));
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
// 创建错误单元格映射
|
|
@@ -279,7 +281,7 @@ export const toExcel = async (
|
|
|
279
281
|
console.error('转换Excel失败:', error);
|
|
280
282
|
return {
|
|
281
283
|
success: false,
|
|
282
|
-
error: error instanceof Error ? error.message : '
|
|
284
|
+
error: error instanceof Error ? error.message : $t('webui.utils.formCsv.unknownError'),
|
|
283
285
|
};
|
|
284
286
|
}
|
|
285
287
|
};
|
|
@@ -297,7 +299,7 @@ export const csvToExcelView = async (csvContent: string, fileName: string): Prom
|
|
|
297
299
|
} catch (error) {
|
|
298
300
|
return {
|
|
299
301
|
success: false,
|
|
300
|
-
error: error instanceof Error ? error.message : '
|
|
302
|
+
error: error instanceof Error ? error.message : $t('webui.utils.excelPreview.csvProcessingFailed'),
|
|
301
303
|
};
|
|
302
304
|
}
|
|
303
305
|
};
|
|
@@ -324,7 +326,7 @@ export const excelToExcelView = async (excelBuffer: ArrayBuffer, fileName: strin
|
|
|
324
326
|
} catch (error) {
|
|
325
327
|
return {
|
|
326
328
|
success: false,
|
|
327
|
-
error: error instanceof Error ? error.message : '
|
|
329
|
+
error: error instanceof Error ? error.message : $t('webui.utils.excelPreview.excelProcessingFailed'),
|
|
328
330
|
};
|
|
329
331
|
}
|
|
330
332
|
};
|
package/src/utils/file-upload.ts
CHANGED
|
@@ -153,7 +153,7 @@ export class AsyncUploader {
|
|
|
153
153
|
} catch (error) {
|
|
154
154
|
fileList.forEach((file) => {
|
|
155
155
|
file.status = UploadStatus.Error;
|
|
156
|
-
file.error = error instanceof Error ? error : new Error('
|
|
156
|
+
file.error = error instanceof Error ? error : new Error($t('webui.utils.fileUpload.fileUploadFailed'));
|
|
157
157
|
onProgress?.(file);
|
|
158
158
|
});
|
|
159
159
|
} finally {
|
|
@@ -180,7 +180,7 @@ export class AsyncUploader {
|
|
|
180
180
|
onProgress?.(file);
|
|
181
181
|
});
|
|
182
182
|
} catch (error) {
|
|
183
|
-
file.error = error instanceof Error ? error : new Error('
|
|
183
|
+
file.error = error instanceof Error ? error : new Error($t('webui.utils.fileUpload.fileUploadFailed'));
|
|
184
184
|
} finally {
|
|
185
185
|
// 启动下一个上传任务
|
|
186
186
|
if (pendingFiles.length > 0) {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { AppInfo, HostInfo, UserInfo } from '@skyfox2000/microbase';
|
|
7
|
+
import { $t } from '@/locales/index';
|
|
7
8
|
|
|
8
9
|
// 定义请求数据格式
|
|
9
10
|
interface ApiRequestData {
|
|
@@ -44,7 +45,7 @@ class MicroAppSDK {
|
|
|
44
45
|
private static async callMainAppMethod(method: string, params?: any): Promise<any> {
|
|
45
46
|
// 检查是否在微前端环境中
|
|
46
47
|
if (!this.isInMicroApp()) {
|
|
47
|
-
throw new Error(
|
|
48
|
+
throw new Error($t('webui.utils.microOpenapis.interfaceNotConfigured', { method }));
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
// 生成请求标识符(方法名+参数JSON字符串)
|
|
@@ -68,7 +69,7 @@ class MicroAppSDK {
|
|
|
68
69
|
if (this.callbacks.has(id)) {
|
|
69
70
|
this.callbacks.delete(id);
|
|
70
71
|
this.pendingRequests.delete(requestKey);
|
|
71
|
-
reject(new Error(
|
|
72
|
+
reject(new Error($t('webui.utils.microOpenapis.apiCallTimeout', { method })));
|
|
72
73
|
}
|
|
73
74
|
}, 10000); // 10秒超时
|
|
74
75
|
});
|
|
@@ -113,7 +114,7 @@ class MicroAppSDK {
|
|
|
113
114
|
if (success) {
|
|
114
115
|
callback.resolve(result);
|
|
115
116
|
} else {
|
|
116
|
-
callback.reject(new Error(error || '
|
|
117
|
+
callback.reject(new Error(error || $t('webui.utils.formCsv.unknownError')));
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
}
|
package/src/utils/tools.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { ButtonTool } from '@/typings/tools';
|
|
2
2
|
import { ref } from 'vue';
|
|
3
|
+
import { $t } from '@/locales';
|
|
3
4
|
|
|
4
5
|
export const uploadTempOpener = ref<boolean>(false);
|
|
5
6
|
|
|
6
7
|
// 添加上传模板按钮
|
|
7
8
|
export const uploadTempBtn: ButtonTool = {
|
|
8
|
-
label: '
|
|
9
|
+
label: $t('webui.utils.tools.templateManagement'),
|
|
9
10
|
key: 'uploadTemp',
|
|
10
11
|
type: 'primary',
|
|
11
12
|
icon: 'icon-download',
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
var b = Object.defineProperty;
|
|
2
|
-
var E = (o, r, a) => r in o ? b(o, r, { enumerable: !0, configurable: !0, writable: !0, value: a }) : o[r] = a;
|
|
3
|
-
var h = (o, r, a) => E(o, typeof r != "symbol" ? r + "" : r, a);
|
|
4
|
-
import { hostUrl as m } from "@skyfox2000/fapi";
|
|
5
|
-
import U from "dayjs";
|
|
6
|
-
import f from "vue-m-message";
|
|
7
|
-
import { $ as u, M as y, u as g } from "./upload-template-NU0Bpg4N.js";
|
|
8
|
-
import { isMicroApp as F } from "@skyfox2000/microbase";
|
|
9
|
-
var i = /* @__PURE__ */ ((o) => (o.Pending = "pending", o.Uploading = "uploading", o.Success = "success", o.Error = "error", o.Online = "online", o.Offline = "offline", o))(i || {});
|
|
10
|
-
class M {
|
|
11
|
-
/**
|
|
12
|
-
* 连接路径参数,已判断 undefined 或 null 值
|
|
13
|
-
* @param args 路径参数数组
|
|
14
|
-
* @returns 连接后的路径字符串
|
|
15
|
-
*/
|
|
16
|
-
static join(...r) {
|
|
17
|
-
return r.filter((s) => s != null).join("/").replace(/[\/]+/, "/");
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
class S {
|
|
21
|
-
/**
|
|
22
|
-
* AsyncUploader 构造函数
|
|
23
|
-
* @param urlInfo 文件上传的 API 配置(IUrlInfo 对象)
|
|
24
|
-
* @param maxConcurrent 最大允许并发上传的文件数量
|
|
25
|
-
*/
|
|
26
|
-
constructor(r, a = 3) {
|
|
27
|
-
/**
|
|
28
|
-
* 设置 API 端点和最大并发数,所有上传文件通过该类控制
|
|
29
|
-
*/
|
|
30
|
-
h(this, "urlInfo");
|
|
31
|
-
/**
|
|
32
|
-
* 最大并发上传数
|
|
33
|
-
*/
|
|
34
|
-
h(this, "maxConcurrent");
|
|
35
|
-
/**
|
|
36
|
-
* 控制上传任务的中断信号
|
|
37
|
-
*/
|
|
38
|
-
h(this, "abortController");
|
|
39
|
-
this.urlInfo = r, this.maxConcurrent = a;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* 执行上传
|
|
43
|
-
* @param fileList 文件列表
|
|
44
|
-
* @param loading 加载状态
|
|
45
|
-
* @param continueOnError 错误时是否继续上传
|
|
46
|
-
* @param onComplete 上传完成回调
|
|
47
|
-
* @param onProgress 上传进度回调
|
|
48
|
-
* @returns 上传结果
|
|
49
|
-
*/
|
|
50
|
-
async doUpload(r, a, l, s, t) {
|
|
51
|
-
if (r.length) {
|
|
52
|
-
if (r.length === 0) {
|
|
53
|
-
f.warning(u("webui.utils.fileUpload.pleaseSelectFile"));
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
a.value = !0, await this.uploadFiles(r, t, (d) => {
|
|
57
|
-
let e = !1, p = 0;
|
|
58
|
-
for (const n of d)
|
|
59
|
-
n.status === i.Error && p++;
|
|
60
|
-
p ? p < d.length ? l ? (f.error(u("webui.utils.fileUpload.partialUploadFailed")), f.warning(u("webui.utils.fileUpload.saveUploadSuccess")), e = !0) : f.error(u("webui.utils.fileUpload.partialUploadFailedCancel")) : f.error(u("webui.utils.fileUpload.allUploadFailed")) : (f.success(u("webui.utils.fileUpload.allUploadSuccess")), e = !0), a.value = !1, s == null || s(e, d);
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* 上传多个文件,控制并发数量
|
|
66
|
-
* @param files 文件列表(File[] 或 FileList)
|
|
67
|
-
* @param onProgress 上传进度回调
|
|
68
|
-
* @param onComplete 上传完成回调
|
|
69
|
-
*/
|
|
70
|
-
async uploadFiles(r, a, l) {
|
|
71
|
-
if (!r.length) return;
|
|
72
|
-
const s = Math.min(this.maxConcurrent, r.length), t = [];
|
|
73
|
-
for (const e of r)
|
|
74
|
-
switch (e.status) {
|
|
75
|
-
case i.Success:
|
|
76
|
-
case i.Online:
|
|
77
|
-
case i.Offline:
|
|
78
|
-
break;
|
|
79
|
-
default:
|
|
80
|
-
e.status = i.Pending, t.push(e);
|
|
81
|
-
break;
|
|
82
|
-
}
|
|
83
|
-
const d = [];
|
|
84
|
-
this.abortController = new AbortController();
|
|
85
|
-
try {
|
|
86
|
-
for (; d.length < s && t.length > 0; ) {
|
|
87
|
-
const e = t.shift();
|
|
88
|
-
if (!e) break;
|
|
89
|
-
d.push(this.handleFileStatus(e, d, t, a));
|
|
90
|
-
}
|
|
91
|
-
await Promise.all(d);
|
|
92
|
-
} catch (e) {
|
|
93
|
-
r.forEach((p) => {
|
|
94
|
-
p.status = i.Error, p.error = e instanceof Error ? e : new Error("上传失败"), a == null || a(p);
|
|
95
|
-
});
|
|
96
|
-
} finally {
|
|
97
|
-
l == null || l(r);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* 处理单个文件的上传逻辑
|
|
102
|
-
* @param file 当前上传的文件
|
|
103
|
-
* @param activeUploads 当前正在上传的文件列表
|
|
104
|
-
* @param pendingFiles 等待上传的文件列表
|
|
105
|
-
* @param onProgress 上传进度回调
|
|
106
|
-
*/
|
|
107
|
-
async handleFileStatus(r, a, l, s) {
|
|
108
|
-
try {
|
|
109
|
-
await this.uploadFile(r, this.abortController.signal, (t) => {
|
|
110
|
-
r.percent = t, s == null || s(r);
|
|
111
|
-
});
|
|
112
|
-
} catch (t) {
|
|
113
|
-
r.error = t instanceof Error ? t : new Error("上传失败");
|
|
114
|
-
} finally {
|
|
115
|
-
if (l.length > 0) {
|
|
116
|
-
const t = l.shift();
|
|
117
|
-
t && a.push(this.handleFileStatus(t, a, l, s));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* 使用 XMLHttpRequest 上传文件
|
|
123
|
-
* @param file 文件对象
|
|
124
|
-
* @param signal 中断信号
|
|
125
|
-
* @param onProgress 上传进度回调
|
|
126
|
-
*/
|
|
127
|
-
async uploadFile(r, a, l) {
|
|
128
|
-
return r.status = i.Uploading, new Promise(async (s, t) => {
|
|
129
|
-
const d = new FormData();
|
|
130
|
-
if (d.append("file", r.originFileObj), r.params)
|
|
131
|
-
for (const n in r.params)
|
|
132
|
-
d.append(n, r.params[n]);
|
|
133
|
-
const e = new XMLHttpRequest(), p = m(this.urlInfo);
|
|
134
|
-
if (p === !1) return Promise.resolve(r);
|
|
135
|
-
if (e.open("POST", p, !0), this.urlInfo.header && typeof this.urlInfo.header == "object" && Object.entries(this.urlInfo.header).forEach(([n, c]) => {
|
|
136
|
-
e.setRequestHeader(n, c);
|
|
137
|
-
}), this.urlInfo.authorize) {
|
|
138
|
-
const n = F() ? await y.getToken() : g().getToken();
|
|
139
|
-
if (!n) {
|
|
140
|
-
t(new Error(u("webui.utils.fileUpload.unauthorized")));
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
e.setRequestHeader("Authorization", "Bearer " + n);
|
|
144
|
-
}
|
|
145
|
-
e.upload.addEventListener("progress", (n) => {
|
|
146
|
-
if (n.lengthComputable && n.total > 0) {
|
|
147
|
-
const c = Math.round(n.loaded / n.total * 100);
|
|
148
|
-
l(c);
|
|
149
|
-
}
|
|
150
|
-
}), e.addEventListener("load", () => {
|
|
151
|
-
if (e.status >= 200 && e.status < 300) {
|
|
152
|
-
const n = e.getResponseHeader("Content-Type");
|
|
153
|
-
if (!n || !n.includes("application/json")) {
|
|
154
|
-
t(new Error(u("webui.utils.fileUpload.invalidJsonFormat")));
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
try {
|
|
158
|
-
const c = JSON.parse(e.response);
|
|
159
|
-
if (c.status === "success")
|
|
160
|
-
c.data && (r.minioFile = {
|
|
161
|
-
ETag: c.data.ETag,
|
|
162
|
-
Bucket: c.data.Bucket,
|
|
163
|
-
FileName: r.fileName,
|
|
164
|
-
Key: c.data.Key,
|
|
165
|
-
Size: c.data.Size,
|
|
166
|
-
Type: r.type,
|
|
167
|
-
UpdateTime: U().format("YYYY-MM-DD HH:mm:ss"),
|
|
168
|
-
Status: i.Success
|
|
169
|
-
}), r.status = i.Success, s(r);
|
|
170
|
-
else {
|
|
171
|
-
const w = c.msg;
|
|
172
|
-
r.status = i.Error, t(new Error(w));
|
|
173
|
-
}
|
|
174
|
-
} catch (c) {
|
|
175
|
-
r.status = i.Error, t(new Error(u("webui.utils.fileUpload.jsonParseError") + ": " + c));
|
|
176
|
-
}
|
|
177
|
-
} else
|
|
178
|
-
r.status = i.Error, t(new Error(u("webui.utils.fileUpload.uploadFailed") + `:${e.status}`));
|
|
179
|
-
}), e.addEventListener("error", () => {
|
|
180
|
-
r.status = i.Error, t(new Error(u("webui.utils.fileUpload.networkError")));
|
|
181
|
-
}), e.send(d), a.addEventListener("abort", () => {
|
|
182
|
-
e.abort(), t(new Error(u("webui.utils.fileUpload.uploadCancelled")));
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* 取消当前所有的上传任务
|
|
188
|
-
*/
|
|
189
|
-
cancelUpload() {
|
|
190
|
-
this.abortController && this.abortController.abort();
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
const x = async (o, r) => {
|
|
194
|
-
const a = new S(o, 1), l = [r];
|
|
195
|
-
await a.uploadFiles(
|
|
196
|
-
l,
|
|
197
|
-
(s) => {
|
|
198
|
-
r.percent = s.percent;
|
|
199
|
-
},
|
|
200
|
-
(s) => {
|
|
201
|
-
const t = s[0];
|
|
202
|
-
r.percent = t.percent, t.status === i.Success ? (r.status = i.Online, f.success(u("webui.utils.fileUpload.fileUploadSuccess"))) : (r.status = i.Error, f.error(u("webui.utils.fileUpload.fileUploadFailed")));
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
-
};
|
|
206
|
-
export {
|
|
207
|
-
S as A,
|
|
208
|
-
i as U,
|
|
209
|
-
x as f,
|
|
210
|
-
M as p
|
|
211
|
-
};
|