16
16
class =" rounded text-center p-7 w-full"
17
17
>
18
18
<div >
19
- <icon-upload class =" text-5xl text-gray-400" />
19
+ <icon-upload class =" text-5xl text-gray-400" />
20
20
<div class =" text-red-600 font-bold" >
21
21
{{ config.title === 'buttonText' ? $t('upload.buttonText') : config.title }}
22
22
</div >
27
27
</template >
28
28
</a-upload >
29
29
30
- <!-- 单文件 -->
30
+ <!-- 单文件 -->
31
31
<div
32
32
class =" file-list mt-2"
33
33
v-if =" !config.multiple && config.showList && currentItem?.percent"
38
38
animation
39
39
type =" circle"
40
40
size =" mini"
41
+ show-text
41
42
class =" progress"
42
43
/>
44
+ <span v-if =" currentItem.percent < 100" >上传中...</span >
45
+
46
+ <a-tooltip content =" 点击文件名预览/下载" position =" tr" >
47
+ <a :href =" currentItem.url"
48
+ v-if =" currentItem?.url && currentItem.percent === 100 && currentItem?.status === 'complete'"
49
+ class =" file-name"
50
+ target =" _blank"
51
+ >{{ currentItem.name }}</a >
52
+ </a-tooltip >
53
+
43
54
<a-button
44
- class =" delete"
55
+ type =" text"
56
+ size =" small"
45
57
@click =" removeSignFile()"
46
58
v-if =" currentItem.percent === 100"
47
59
>
48
- <template #icon ><icon-delete /></template >
60
+ <template #icon >
61
+ <icon-delete />
62
+ </template >
49
63
</a-button >
50
- <div
51
- v-if =" currentItem?.url && currentItem.percent === 100 && currentItem?.status === 'complete'"
52
- class =" file-item"
53
- >
54
- {{ currentItem.url }}
55
- </div >
56
64
</div >
57
65
58
66
<!-- 多文件 -->
69
77
size =" mini"
70
78
class =" progress"
71
79
/>
80
+ <span v-if =" file.percent < 100" >上传中...</span >
81
+
82
+ <a-tooltip content =" 点击文件名预览/下载" position =" tr" >
83
+ <a :href =" file.url"
84
+ v-if =" file?.url && file.percent === 100 && file?.status === 'complete'"
85
+ class =" file-name"
86
+ target =" _blank"
87
+ >{{ file.name }}</a >
88
+ </a-tooltip >
89
+
72
90
<a-button
73
- class =" delete"
91
+ type =" text"
92
+ size =" small"
74
93
@click =" removeFile(idx)"
75
94
v-if =" file.percent === 100"
76
95
>
77
- <template #icon ><icon-delete /></template >
96
+ <template #icon >
97
+ <icon-delete />
98
+ </template >
78
99
</a-button >
79
- <div
80
- v-if =" file?.url && file.percent === 100 && file?.status === 'complete'"
81
- class =" file-item"
82
- >
83
- {{ file.url }}
84
- </div >
85
100
</div >
86
101
</template >
87
102
<script setup>
@@ -94,10 +109,14 @@ import { Message } from '@arco-design/web-vue'
94
109
import file2md5 from ' file2md5'
95
110
96
111
import { useI18n } from ' vue-i18n'
112
+
97
113
const { t } = useI18n ()
98
114
99
115
const props = defineProps ({
100
- modelValue: { type: [ String , Number , Array ], default : () => {} }
116
+ modelValue: {
117
+ type: [String , Number , Array ], default : () => {
118
+ }
119
+ }
101
120
})
102
121
const emit = defineEmits ([' update:modelValue' ])
103
122
const config = inject (' config' )
@@ -106,9 +125,9 @@ const showFileList = ref([])
106
125
const signFile = ref ()
107
126
const currentItem = ref ({})
108
127
109
- const chunkUpload = async (options ) => {
128
+ const chunkUpload = async (options) => {
110
129
let idx
111
- if (config .multiple ) {
130
+ if (config .multiple ) {
112
131
showFileList .value .push (options .fileItem )
113
132
idx = showFileList .value .length - 1
114
133
} else {
@@ -118,16 +137,16 @@ const chunkUpload = async (options) => {
118
137
try {
119
138
const file = options .fileItem .file
120
139
const hash = await file2md5 (file)
121
- if ( ! file .type ) {
140
+ if ( ! file .type ) {
122
141
Message .error (' 获取文件类型失败,无法上传' )
123
142
return
124
143
}
125
144
const chunks = Math .ceil (file .size / config .chunkSize )
126
- for (let currentChunk = 0 ; currentChunk < chunks; currentChunk++ ) {
145
+ for (let currentChunk = 0 ; currentChunk < chunks; currentChunk++ ) {
127
146
const start = currentChunk * config .chunkSize
128
147
const end = (start + config .chunkSize >= file .size )
129
- ? file .size
130
- : start + config .chunkSize
148
+ ? file .size
149
+ : start + config .chunkSize
131
150
const dataForm = new FormData ()
132
151
dataForm .append (' package' , file .slice (start, end))
133
152
dataForm .append (' hash' , hash)
@@ -137,14 +156,15 @@ const chunkUpload = async (options) => {
137
156
dataForm .append (' size' , file .size )
138
157
dataForm .append (' index' , currentChunk + 1 )
139
158
dataForm .append (' ext' , / [^ . ] + $ / g .exec (file .name )[0 ])
140
- for (let name in config .requestData ) {
159
+ for (let name in config .requestData ) {
141
160
dataForm .append (name, config .requestData [name])
142
161
}
143
162
const res = await commonApi .chunkUpload (dataForm)
144
163
145
- if (res .data && res .data .hash ) {
164
+ if (res .data && res .data .hash ) {
146
165
res .data .url = tool .attachUrl (res .data .url , storageMode[res .data .storage_mode ])
147
- if (config .multiple ) {
166
+ if (config .multiple ) {
167
+ showFileList .value [idx].name = res .data .origin_name
148
168
showFileList .value [idx].percent = 100
149
169
showFileList .value [idx].status = ' complete'
150
170
showFileList .value [idx].url = res .data .url
@@ -166,17 +186,19 @@ const chunkUpload = async (options) => {
166
186
}
167
187
return
168
188
}
169
- if (res .data && res .data .code && res .data .code === 201 ) {
170
- const percent = parseFloat ((1 / chunks).toFixed (4 ))
171
- if (config .multiple ) {
189
+ if (res .data && res .data .code && res .data .code === 201 ) {
190
+ const percent = Math .floor ((1 / chunks) * 10000 ) / 10000 ;
191
+ console .log (' showFileList.value[idx].percent' , showFileList .value [idx].percent )
192
+ console .log (' percent' , percent)
193
+ if (config .multiple ) {
172
194
showFileList .value [idx].percent += percent
173
195
} else {
174
196
currentItem .value .status = ' uploading'
175
197
currentItem .value .percent += percent
176
198
}
177
199
}
178
200
}
179
- } catch (e) {
201
+ } catch (e) {
180
202
console .error (e)
181
203
Message .error (t (' upload.fileHashFail' ))
182
204
}
@@ -197,34 +219,45 @@ const removeFile = (idx) => {
197
219
emit (' update:modelValue' , files)
198
220
}
199
221
200
- const init = async () => {
201
- if (config .multiple ) {
202
- if (isArray (props .modelValue ) && props .modelValue .length > 0 ) {
222
+ const init = async () => {
223
+ if (config .multiple ) {
224
+ if (isArray (props .modelValue ) && props .modelValue .length > 0 ) {
203
225
const result = await props .modelValue .map (async item => {
204
226
return await getFileUrl (config .returnType , item, storageMode)
205
227
})
206
228
const data = await Promise .all (result)
207
229
208
230
let fileItemObj = { percent: 100 , status: ' complete' };
209
- if (config .returnType === ' url' ) {
210
- showFileList .value = data .map (url => { return { url, ... fileItemObj } })
231
+ if (config .returnType === ' url' ) {
232
+ showFileList .value = data .map (url => {
233
+ return { url, name: url .substring (url .lastIndexOf (' /' ) + 1 ), ... fileItemObj }
234
+ })
211
235
} else {
212
- showFileList .value = data .map (item => { return { url: item .url , [config .returnType ]: item[config .returnType ], ... fileItemObj } })
236
+ showFileList .value = data .map (item => {
237
+ return {
238
+ name: item .origin_name ,
239
+ [config .returnType ]: item[config .returnType ],
240
+ url: item .url ,
241
+ ... fileItemObj
242
+ }
243
+ })
213
244
}
214
245
} else {
215
246
showFileList .value = []
216
247
}
217
- } else if (props .modelValue ) {
218
- if (config .returnType === ' url' ) {
248
+ } else if (props .modelValue ) {
249
+ if (config .returnType === ' url' ) {
219
250
signFile .value = props .modelValue
220
251
currentItem .value .url = props .modelValue
252
+ currentItem .value .name = (props .modelValue )? .substring ((props .modelValue ? .lastIndexOf (' /' ) || 0 ) + 1 )
221
253
} else {
222
254
const result = await getFileUrl (config .returnType , props .modelValue , storageMode)
223
255
signFile .value = result .url
224
256
currentItem .value .url = result .url
257
+ currentItem .value .name = result .origin_name
225
258
}
226
259
currentItem .value .percent = 100
227
- currentItem .value .status = ' complete'
260
+ currentItem .value .status = ' complete'
228
261
} else {
229
262
removeSignFile ()
230
263
}
@@ -238,20 +271,21 @@ watch(() => props.modelValue, (val) => {
238
271
< / script>
239
272
< style lang= " less" scoped>
240
273
.file - list {
241
- position : relative ;
242
274
background- color: var (-- color- primary- light- 1 );
243
275
border- radius: 4px ;
244
- height : 36px ; line-height : 36px ; padding : 0 10px ;
276
+ height: 36px ;
277
+ padding: 0 5px ;
245
278
width: 100 % ;
246
- .delete {
247
- position : absolute ; z-index : 99 ; right : 2px ; top : 2px ;
248
- }
279
+ display: flex;
280
+ flex- direction: row;
281
+ justify- content: space- between;
282
+ align- items: center;
249
283
250
- .progress {
251
- position : absolute ;
252
- left : 30 px ;
253
- top : 50 % ;
254
- transform : translateX ( -50 % ) translateY ( -50 % );
284
+ .file - name {
285
+ max - width : 90 % ;
286
+ margin : 0 5px ;
287
+ overflow : hidden ;
288
+ color : # 165DFF
255
289
}
256
290
}
257
291
< / style>
0 commit comments