xianniu-ui 0.9.13 → 2.0.1
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/style/basic.css +1 -1
- package/lib/style/ellipsis.css +1 -1
- package/lib/style/fonts/element-icons.ttf +0 -0
- package/lib/style/fonts/element-icons.woff +0 -0
- package/lib/style/index.css +1 -0
- package/lib/style/index.js +1 -0
- package/lib/style/page.css +1 -0
- package/lib/style/search.css +1 -0
- package/lib/style/table.css +1 -0
- package/lib/style/tag.css +1 -0
- package/lib/style/theme/element-variables.scss +13 -11
- package/lib/style/theme/theme.scss +5 -4
- package/lib/style/tip.css +1 -0
- package/lib/style/tree.css +1 -0
- package/lib/style/upload.css +1 -0
- package/lib/xianniu-ui.common.js +19609 -69544
- package/lib/xianniu-ui.css +1 -1
- package/lib/xianniu-ui.umd.js +19614 -69549
- package/lib/xianniu-ui.umd.min.js +2 -72
- package/package.json +20 -12
- package/packages/card/main.vue +1 -1
- package/packages/page/main.vue +2 -2
- package/packages/search/main.vue +391 -293
- package/packages/style/gulpfile.js +6 -6
- package/packages/style/src/index.scss +3 -5
- package/packages/style/src/search.scss +127 -15
- package/packages/style/src/theme/element-variables.scss +13 -11
- package/packages/style/src/theme/theme.scss +5 -4
- package/packages/style/src/upload.scss +47 -8
- package/packages/table/main.vue +84 -34
- package/packages/tag/main.vue +1 -1
- package/packages/upload/main.vue +165 -35
- package/src/area/data.js +3890 -0
- package/src/area/index.js +71 -1
- package/src/oss/index.js +93 -60
- package/src/plugins/index.js +5 -2
package/packages/upload/main.vue
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
<template v-else-if="listType === 'picture-card'">
|
|
30
30
|
<div slot="trigger" class="upload-limit">
|
|
31
31
|
<i class="el-icon el-icon-plus" />
|
|
32
|
+
<span class="text">{{ uploadText }}</span>
|
|
32
33
|
</div>
|
|
33
34
|
</template>
|
|
34
35
|
<template v-else>
|
|
@@ -49,25 +50,36 @@
|
|
|
49
50
|
<template v-if="['list'].includes(listType)">
|
|
50
51
|
<a
|
|
51
52
|
class="el-upload-list__item-name"
|
|
53
|
+
:class="{ 'is-error': file.status === 'fail' }"
|
|
52
54
|
@click="handlePictureCardPreview(file)"
|
|
53
|
-
v-if="$utils.isImg(file)"
|
|
55
|
+
v-if="$utils.isImg(file) && file.status !== 'fail'"
|
|
54
56
|
><i class="el-icon-document"></i>{{ file.name }}
|
|
55
57
|
</a>
|
|
56
58
|
<a
|
|
57
59
|
class="el-upload-list__item-name"
|
|
60
|
+
:class="{ 'is-error': file.status === 'fail' }"
|
|
58
61
|
@click="handleAVPreview(file)"
|
|
59
|
-
v-else-if="$utils.isAV(file)"
|
|
62
|
+
v-else-if="$utils.isAV(file) && file.status !== 'fail'"
|
|
60
63
|
><i class="el-icon-document"></i>{{ file.name }}
|
|
61
64
|
</a>
|
|
62
65
|
<a
|
|
63
66
|
class="el-upload-list__item-name"
|
|
67
|
+
:class="{ 'is-error': file.status === 'fail' }"
|
|
64
68
|
@click="handleDownload(file)"
|
|
65
|
-
v-else
|
|
69
|
+
v-else-if="file.status !== 'uploading' && file.status !== 'fail'"
|
|
66
70
|
><i class="el-icon-document"></i>{{ file.name }}
|
|
67
71
|
</a>
|
|
68
72
|
<a class="el-upload-list__item-name" v-if="file.status === 'uploading'"
|
|
69
73
|
><i class="el-icon-document"></i>{{ file.name }}
|
|
70
74
|
</a>
|
|
75
|
+
<a
|
|
76
|
+
class="el-upload-list__item-name is-error"
|
|
77
|
+
v-if="file.status === 'fail'"
|
|
78
|
+
@click="retryUpload(file)"
|
|
79
|
+
>
|
|
80
|
+
<i class="el-icon-document"></i>{{ file.name }}
|
|
81
|
+
<span class="error-tip">({{ file.errorMessage }})</span>
|
|
82
|
+
</a>
|
|
71
83
|
<el-progress
|
|
72
84
|
v-if="file.status === 'uploading'"
|
|
73
85
|
type="line"
|
|
@@ -86,6 +98,13 @@
|
|
|
86
98
|
}"
|
|
87
99
|
></i>
|
|
88
100
|
</label>
|
|
101
|
+
<i
|
|
102
|
+
v-if="file.status === 'fail'"
|
|
103
|
+
class="el-icon-refresh-right"
|
|
104
|
+
title="重新上传"
|
|
105
|
+
@click="retryUpload(file)"
|
|
106
|
+
style="cursor: pointer; color: #f56c6c; margin-right: 5px;"
|
|
107
|
+
></i>
|
|
89
108
|
<i
|
|
90
109
|
class="el-icon-close"
|
|
91
110
|
@click="handleRemove(file, fileList)"
|
|
@@ -130,7 +149,23 @@
|
|
|
130
149
|
:stroke-width="6"
|
|
131
150
|
/>
|
|
132
151
|
</div>
|
|
133
|
-
<
|
|
152
|
+
<div v-if="file.status === 'fail'" class="upload-error">
|
|
153
|
+
<div class="error-mask">
|
|
154
|
+
<p class="error-text">上传失败</p>
|
|
155
|
+
<div class="error-actions">
|
|
156
|
+
<el-link type="danger" :underline="false" icon="el-icon-refresh" @click.stop="retryUpload(file)"></el-link>
|
|
157
|
+
<el-link
|
|
158
|
+
v-if="!$attrs.disabled && !preview"
|
|
159
|
+
type="info"
|
|
160
|
+
:underline="false"
|
|
161
|
+
icon="el-icon-delete"
|
|
162
|
+
@click.stop="handleRemove(file, fileList)"
|
|
163
|
+
style="margin-left: 10px;"
|
|
164
|
+
></el-link>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
<span class="el-upload-list__item-actions" v-if="file.status !== 'fail'">
|
|
134
169
|
<span
|
|
135
170
|
v-if="$utils.isImg(file)"
|
|
136
171
|
class="el-upload-list__item-preview"
|
|
@@ -173,7 +208,7 @@
|
|
|
173
208
|
</template>
|
|
174
209
|
|
|
175
210
|
<script>
|
|
176
|
-
import ElImageViewer from "element-ui/packages/image/src/image-viewer";
|
|
211
|
+
import ElImageViewer from "@liuzengwei/element-ui/packages/image/src/image-viewer";
|
|
177
212
|
import Client from "@/oss";
|
|
178
213
|
import uploadPop from "./upload-pop.vue";
|
|
179
214
|
import idCard from "./idCard.vue";
|
|
@@ -227,7 +262,7 @@ export default {
|
|
|
227
262
|
default: () => {},
|
|
228
263
|
},
|
|
229
264
|
hideUpload: {
|
|
230
|
-
|
|
265
|
+
type: Boolean,
|
|
231
266
|
default: false,
|
|
232
267
|
},
|
|
233
268
|
type: {
|
|
@@ -253,7 +288,7 @@ export default {
|
|
|
253
288
|
isShowAV: false,
|
|
254
289
|
avUrl: "",
|
|
255
290
|
realFileList: [],
|
|
256
|
-
|
|
291
|
+
failedFiles: {}, // 记录失败的文件 { uid: { file, error } }
|
|
257
292
|
};
|
|
258
293
|
},
|
|
259
294
|
computed: {
|
|
@@ -265,9 +300,14 @@ export default {
|
|
|
265
300
|
fileSize() {
|
|
266
301
|
return this.$format.bytesToSize(this.file.size);
|
|
267
302
|
},
|
|
268
|
-
|
|
269
|
-
|
|
303
|
+
// 获取成功上传的文件列表(过滤掉失败的文件)
|
|
304
|
+
successFileList() {
|
|
305
|
+
return this.fileList.filter(file => file.status !== 'fail');
|
|
270
306
|
},
|
|
307
|
+
// 上传按钮文字
|
|
308
|
+
uploadText(){
|
|
309
|
+
return this.$attrs.drag != undefined || this.drag === true ? '点击或拖拽上传' : '上传文件';
|
|
310
|
+
}
|
|
271
311
|
},
|
|
272
312
|
watch: {
|
|
273
313
|
fileList: {
|
|
@@ -279,8 +319,6 @@ export default {
|
|
|
279
319
|
},
|
|
280
320
|
},
|
|
281
321
|
created() {
|
|
282
|
-
console.log(this.$attrs);
|
|
283
|
-
|
|
284
322
|
this.client = new Client({
|
|
285
323
|
stsUrl: this.$XN.stsUrl || "",
|
|
286
324
|
setFileIdUrl: this.$XN.setFileIdUrl || "",
|
|
@@ -303,7 +341,6 @@ export default {
|
|
|
303
341
|
return Promise.all([
|
|
304
342
|
this.checkFileExt(file),
|
|
305
343
|
this.onExceedSize(file.size),
|
|
306
|
-
this.getStsToken(file),
|
|
307
344
|
])
|
|
308
345
|
.then(() => {
|
|
309
346
|
return Promise.resolve();
|
|
@@ -349,43 +386,115 @@ export default {
|
|
|
349
386
|
});
|
|
350
387
|
},
|
|
351
388
|
onChange(file, fileList) {
|
|
352
|
-
|
|
389
|
+
// 保持realFileList的引用稳定性
|
|
390
|
+
this.realFileList = [...fileList];
|
|
353
391
|
},
|
|
354
392
|
async onHttpUpload(file) {
|
|
355
393
|
this.handleUpload(file);
|
|
356
394
|
},
|
|
357
|
-
handleUpload(file) {
|
|
395
|
+
async handleUpload(file, isRetry = false) {
|
|
358
396
|
this.isUploading = true;
|
|
359
397
|
this.$emit("on-uploaded", false);
|
|
398
|
+
|
|
399
|
+
// file 可能是 Element UI 的包装对象或原始文件对象
|
|
400
|
+
const fileUid = file.uid || file.file?.uid;
|
|
401
|
+
|
|
402
|
+
// 如果是重试,从失败列表中移除并重置状态
|
|
403
|
+
if (isRetry) {
|
|
404
|
+
if (this.failedFiles[fileUid]) {
|
|
405
|
+
delete this.failedFiles[fileUid];
|
|
406
|
+
}
|
|
407
|
+
const index = this.realFileList.findIndex(item => item.uid === fileUid);
|
|
408
|
+
if (index !== -1) {
|
|
409
|
+
this.$set(this.realFileList[index], 'status', 'uploading');
|
|
410
|
+
this.$set(this.realFileList[index], 'percentage', 0);
|
|
411
|
+
delete this.realFileList[index].errorMessage;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// 确保已获取 STS Token
|
|
416
|
+
if (!this.oss) {
|
|
417
|
+
try {
|
|
418
|
+
await this.getStsToken();
|
|
419
|
+
} catch (err) {
|
|
420
|
+
this.$notify.error({
|
|
421
|
+
title: '获取上传凭证失败',
|
|
422
|
+
message: err.message || '请稍后重试'
|
|
423
|
+
});
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
360
428
|
this.oss
|
|
361
429
|
.upload(file)
|
|
362
430
|
.then((res) => {
|
|
363
431
|
this.successFiles.push(res);
|
|
364
432
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
}
|
|
433
|
+
// 更新文件列表,用上传成功的信息替换原文件
|
|
434
|
+
const index = this.realFileList.findIndex(item => item.uid === res.file.uid);
|
|
435
|
+
if (index !== -1) {
|
|
436
|
+
const obj = { ...res };
|
|
437
|
+
delete obj.file;
|
|
438
|
+
this.$set(this.realFileList, index, obj);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// 从失败列表中移除(如果存在)
|
|
442
|
+
if (this.failedFiles[fileUid]) {
|
|
443
|
+
delete this.failedFiles[fileUid];
|
|
444
|
+
}
|
|
445
|
+
|
|
372
446
|
this.$emit("update:fileList", this.realFileList);
|
|
373
|
-
this.$emit("on-file",
|
|
447
|
+
this.$emit("on-file", res);
|
|
374
448
|
this.$emit("on-success", this.successFiles);
|
|
375
449
|
this.$emit("on-uploaded", true);
|
|
376
450
|
this.isUploading = false;
|
|
377
451
|
})
|
|
378
|
-
.catch((
|
|
452
|
+
.catch((error) => {
|
|
453
|
+
// 上传失败,标记文件状态但保留在列表中
|
|
454
|
+
// 处理不同的错误格式
|
|
455
|
+
const fileName = error?.fileName || file.file?.name || file.name || '未知文件';
|
|
456
|
+
const message = error?.message || error?.err?.message || '网络错误,请检查网络连接后重试';
|
|
457
|
+
// const failedFile = error?.file || file;
|
|
458
|
+
|
|
459
|
+
const index = this.realFileList.findIndex(item => item.uid === fileUid);
|
|
460
|
+
if (index !== -1) {
|
|
461
|
+
// 标记为失败状态
|
|
462
|
+
this.$set(this.realFileList[index], 'status', 'fail');
|
|
463
|
+
this.$set(this.realFileList[index], 'errorMessage', message);
|
|
464
|
+
|
|
465
|
+
// 记录失败文件信息(包含原始file对象),用于重试
|
|
466
|
+
this.$set(this.failedFiles, fileUid, {
|
|
467
|
+
file: this.realFileList[index],
|
|
468
|
+
rawFile: file, // 保存原始file对象用于重试
|
|
469
|
+
error: message
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
// 触发更新事件
|
|
473
|
+
this.$emit("update:fileList", [...this.realFileList]);
|
|
474
|
+
}
|
|
475
|
+
|
|
379
476
|
this.$notify.error({
|
|
380
477
|
title: "上传失败",
|
|
381
478
|
dangerouslyUseHTMLString: true,
|
|
382
|
-
message: `<div><p
|
|
479
|
+
message: `<div><p>文件名:${fileName}</p><p>错误:${message}</p><p>点击重试按钮可重新上传</p></div>`,
|
|
480
|
+
duration: 5000
|
|
383
481
|
});
|
|
482
|
+
this.$emit("on-uploaded", true);
|
|
483
|
+
this.isUploading = false;
|
|
384
484
|
});
|
|
385
485
|
},
|
|
386
486
|
// onError() {
|
|
387
487
|
// this.$message.error("上传失败,请重试");
|
|
388
488
|
// },
|
|
489
|
+
retryUpload(file) {
|
|
490
|
+
// 重新上传失败的文件
|
|
491
|
+
if (this.failedFiles[file.uid]) {
|
|
492
|
+
const failedFileInfo = this.failedFiles[file.uid];
|
|
493
|
+
// 使用保存的原始 file 对象进行重试
|
|
494
|
+
const uploadFile = failedFileInfo.rawFile || failedFileInfo.file;
|
|
495
|
+
this.handleUpload(uploadFile, true);
|
|
496
|
+
}
|
|
497
|
+
},
|
|
389
498
|
onSubmitUpload() {
|
|
390
499
|
this.$refs.upload.submit();
|
|
391
500
|
},
|
|
@@ -412,19 +521,16 @@ export default {
|
|
|
412
521
|
return this.$utils.download({ url, name });
|
|
413
522
|
},
|
|
414
523
|
handleRemove(file, fileList) {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
});
|
|
524
|
+
// 使用filter避免遍历中删除的索引问题
|
|
525
|
+
const newFileList = fileList.filter(item => item.uid !== file.uid);
|
|
526
|
+
|
|
420
527
|
if (this.viewList.length) {
|
|
421
|
-
this.viewList.
|
|
422
|
-
if (item.url === file.url) {
|
|
423
|
-
this.viewList.splice(idx, 1);
|
|
424
|
-
}
|
|
425
|
-
});
|
|
528
|
+
this.viewList = this.viewList.filter(item => item.url !== file.url);
|
|
426
529
|
}
|
|
427
|
-
|
|
530
|
+
|
|
531
|
+
// 更新realFileList
|
|
532
|
+
this.realFileList = newFileList;
|
|
533
|
+
this.$emit("update:fileList", newFileList);
|
|
428
534
|
},
|
|
429
535
|
closeViewer() {
|
|
430
536
|
this.isShowImageView = false;
|
|
@@ -432,7 +538,31 @@ export default {
|
|
|
432
538
|
abortUpload() {
|
|
433
539
|
return this.oss.oss.cancel();
|
|
434
540
|
},
|
|
541
|
+
// 获取成功上传的文件列表(不包含失败的文件)
|
|
542
|
+
getSuccessFiles() {
|
|
543
|
+
return this.fileList.filter(file => file.status !== 'fail');
|
|
544
|
+
},
|
|
545
|
+
// 获取失败的文件列表
|
|
546
|
+
getFailedFiles() {
|
|
547
|
+
return this.fileList.filter(file => file.status === 'fail');
|
|
548
|
+
},
|
|
549
|
+
// 检查是否有失败的文件
|
|
550
|
+
hasFailedFiles() {
|
|
551
|
+
return this.fileList.some(file => file.status === 'fail');
|
|
552
|
+
},
|
|
435
553
|
onPreviewFile(file) {
|
|
554
|
+
// 如果是失败的文件,点击重试
|
|
555
|
+
if (file.status === 'fail' && this.failedFiles[file.uid]) {
|
|
556
|
+
this.$confirm('上传失败,是否重新上传?', '提示', {
|
|
557
|
+
confirmButtonText: '重新上传',
|
|
558
|
+
cancelButtonText: '取消',
|
|
559
|
+
type: 'warning'
|
|
560
|
+
}).then(() => {
|
|
561
|
+
this.retryUpload(file);
|
|
562
|
+
}).catch(() => {});
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
|
|
436
566
|
if (file.isAV === 1) {
|
|
437
567
|
this.handleAVPreview(file);
|
|
438
568
|
} else if (file.imgFlag === 1) {
|