Skip to content

Commit be8e250

Browse files
authored
优化文件上传结果展示
1 parent ff3473c commit be8e250

File tree

2 files changed

+153
-93
lines changed

2 files changed

+153
-93
lines changed

src/components/ma-upload/components/chunk-upload.vue

+85-51
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
class="rounded text-center p-7 w-full"
1717
>
1818
<div>
19-
<icon-upload class="text-5xl text-gray-400" />
19+
<icon-upload class="text-5xl text-gray-400"/>
2020
<div class="text-red-600 font-bold">
2121
{{ config.title === 'buttonText' ? $t('upload.buttonText') : config.title }}
2222
</div>
@@ -27,7 +27,7 @@
2727
</template>
2828
</a-upload>
2929

30-
<!-- 单文件 -->
30+
<!-- 单文件 -->
3131
<div
3232
class="file-list mt-2"
3333
v-if="!config.multiple && config.showList && currentItem?.percent"
@@ -38,21 +38,29 @@
3838
animation
3939
type="circle"
4040
size="mini"
41+
show-text
4142
class="progress"
4243
/>
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+
4354
<a-button
44-
class="delete"
55+
type="text"
56+
size="small"
4557
@click="removeSignFile()"
4658
v-if="currentItem.percent === 100"
4759
>
48-
<template #icon><icon-delete /></template>
60+
<template #icon>
61+
<icon-delete/>
62+
</template>
4963
</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>
5664
</div>
5765

5866
<!-- 多文件 -->
@@ -69,19 +77,26 @@
6977
size="mini"
7078
class="progress"
7179
/>
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+
7290
<a-button
73-
class="delete"
91+
type="text"
92+
size="small"
7493
@click="removeFile(idx)"
7594
v-if="file.percent === 100"
7695
>
77-
<template #icon><icon-delete /></template>
96+
<template #icon>
97+
<icon-delete/>
98+
</template>
7899
</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>
85100
</div>
86101
</template>
87102
<script setup>
@@ -94,10 +109,14 @@ import { Message } from '@arco-design/web-vue'
94109
import file2md5 from 'file2md5'
95110
96111
import { useI18n } from 'vue-i18n'
112+
97113
const { t } = useI18n()
98114
99115
const props = defineProps({
100-
modelValue: { type: [ String, Number, Array ], default: () => {} }
116+
modelValue: {
117+
type: [String, Number, Array], default: () => {
118+
}
119+
}
101120
})
102121
const emit = defineEmits(['update:modelValue'])
103122
const config = inject('config')
@@ -106,9 +125,9 @@ const showFileList = ref([])
106125
const signFile = ref()
107126
const currentItem = ref({})
108127
109-
const chunkUpload = async (options) => {
128+
const chunkUpload = async(options) => {
110129
let idx
111-
if (config.multiple) {
130+
if(config.multiple) {
112131
showFileList.value.push(options.fileItem)
113132
idx = showFileList.value.length - 1
114133
} else {
@@ -118,16 +137,16 @@ const chunkUpload = async (options) => {
118137
try {
119138
const file = options.fileItem.file
120139
const hash = await file2md5(file)
121-
if (! file.type) {
140+
if(!file.type) {
122141
Message.error('获取文件类型失败,无法上传')
123142
return
124143
}
125144
const chunks = Math.ceil(file.size / config.chunkSize)
126-
for (let currentChunk = 0; currentChunk < chunks; currentChunk++) {
145+
for(let currentChunk = 0; currentChunk < chunks; currentChunk++) {
127146
const start = currentChunk * config.chunkSize
128147
const end = (start + config.chunkSize >= file.size)
129-
? file.size
130-
: start + config.chunkSize
148+
? file.size
149+
: start + config.chunkSize
131150
const dataForm = new FormData()
132151
dataForm.append('package', file.slice(start, end))
133152
dataForm.append('hash', hash)
@@ -137,14 +156,15 @@ const chunkUpload = async (options) => {
137156
dataForm.append('size', file.size)
138157
dataForm.append('index', currentChunk + 1)
139158
dataForm.append('ext', /[^.]+$/g.exec(file.name)[0])
140-
for (let name in config.requestData) {
159+
for(let name in config.requestData) {
141160
dataForm.append(name, config.requestData[name])
142161
}
143162
const res = await commonApi.chunkUpload(dataForm)
144163
145-
if (res.data && res.data.hash) {
164+
if(res.data && res.data.hash) {
146165
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
148168
showFileList.value[idx].percent = 100
149169
showFileList.value[idx].status = 'complete'
150170
showFileList.value[idx].url = res.data.url
@@ -166,17 +186,19 @@ const chunkUpload = async (options) => {
166186
}
167187
return
168188
}
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) {
172194
showFileList.value[idx].percent += percent
173195
} else {
174196
currentItem.value.status = 'uploading'
175197
currentItem.value.percent += percent
176198
}
177199
}
178200
}
179-
} catch (e) {
201+
} catch(e) {
180202
console.error(e)
181203
Message.error(t('upload.fileHashFail'))
182204
}
@@ -197,34 +219,45 @@ const removeFile = (idx) => {
197219
emit('update:modelValue', files)
198220
}
199221
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) {
203225
const result = await props.modelValue.map(async item => {
204226
return await getFileUrl(config.returnType, item, storageMode)
205227
})
206228
const data = await Promise.all(result)
207229
208230
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+
})
211235
} 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+
})
213244
}
214245
} else {
215246
showFileList.value = []
216247
}
217-
} else if (props.modelValue) {
218-
if (config.returnType === 'url') {
248+
} else if(props.modelValue) {
249+
if(config.returnType === 'url') {
219250
signFile.value = props.modelValue
220251
currentItem.value.url = props.modelValue
252+
currentItem.value.name = (props.modelValue)?.substring((props.modelValue?.lastIndexOf('/') || 0) + 1)
221253
} else {
222254
const result = await getFileUrl(config.returnType, props.modelValue, storageMode)
223255
signFile.value = result.url
224256
currentItem.value.url = result.url
257+
currentItem.value.name = result.origin_name
225258
}
226259
currentItem.value.percent = 100
227-
currentItem.value.status = 'complete'
260+
currentItem.value.status = 'complete'
228261
} else {
229262
removeSignFile()
230263
}
@@ -238,20 +271,21 @@ watch(() => props.modelValue, (val) => {
238271
</script>
239272
<style lang="less" scoped>
240273
.file-list {
241-
position: relative;
242274
background-color: var(--color-primary-light-1);
243275
border-radius: 4px;
244-
height: 36px; line-height: 36px; padding: 0 10px;
276+
height: 36px;
277+
padding: 0 5px;
245278
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;
249283
250-
.progress {
251-
position: absolute;
252-
left: 30px;
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
255289
}
256290
}
257291
</style>

0 commit comments

Comments
 (0)