mirror of
https://gitee.com/lijingbo-2021/open-anylink-web.git
synced 2025-12-30 02:52:26 +00:00
音频消息样式下载优化
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
<script setup>
|
||||
import { onMounted, computed } from 'vue'
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import AudioFileIcon from '@/assets/svg/audiofile.svg'
|
||||
import { formatFileSize } from '@/js/utils/common'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { CircleCheckFilled, WarningFilled } from '@element-plus/icons-vue'
|
||||
|
||||
const props = defineProps(['url', 'fileName', 'size'])
|
||||
const emits = defineEmits(['load'])
|
||||
@@ -13,6 +15,56 @@ const formatSize = computed(() => {
|
||||
onMounted(() => {
|
||||
emits('load') //向父组件暴露load事件
|
||||
})
|
||||
|
||||
const isDownloading = ref(false)
|
||||
const isDownloadComplete = ref(false)
|
||||
const isDownloadError = ref(false)
|
||||
const progress = ref(0)
|
||||
|
||||
const onDownload = async () => {
|
||||
isDownloading.value = true
|
||||
isDownloadComplete.value = false
|
||||
isDownloadError.value = false
|
||||
progress.value = 0
|
||||
try {
|
||||
const response = await fetch(props.url)
|
||||
if (!response.ok) {
|
||||
ElMessage.error('文件资源异常,请稍后再试。')
|
||||
isDownloading.value = false
|
||||
isDownloadError.value = true
|
||||
return
|
||||
}
|
||||
const contentLength = response.headers.get('content-length')
|
||||
const total = contentLength ? parseInt(contentLength, 10) : 0
|
||||
let loaded = 0
|
||||
|
||||
const reader = response.body.getReader()
|
||||
const chunks = []
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const { done, value } = await reader.read()
|
||||
if (done) break
|
||||
chunks.push(value)
|
||||
loaded += value.length
|
||||
progress.value = total > 0 ? (loaded / total) * 100 : 0
|
||||
}
|
||||
const blob = new Blob(chunks)
|
||||
const url = URL.createObjectURL(blob)
|
||||
|
||||
const a = document.createElement('a')
|
||||
a.href = url
|
||||
a.download = props.fileName
|
||||
a.click()
|
||||
|
||||
URL.revokeObjectURL(url)
|
||||
isDownloading.value = false
|
||||
isDownloadComplete.value = true
|
||||
} catch (error) {
|
||||
ElMessage.error('下载文件时出错,请稍后再试。')
|
||||
isDownloading.value = false
|
||||
isDownloadError.value = true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -24,7 +76,37 @@ onMounted(() => {
|
||||
</span>
|
||||
<div class="footer">
|
||||
<div class="size" :title="formatSize">{{ formatSize }}</div>
|
||||
<a :href="props.url" :download="props.fileName">下载</a>
|
||||
<div v-if="props.url" class="download">
|
||||
<span
|
||||
v-if="!isDownloading && !isDownloadComplete && !isDownloadError"
|
||||
@click="onDownload"
|
||||
style="cursor: pointer"
|
||||
>
|
||||
下载
|
||||
</span>
|
||||
<div
|
||||
v-else-if="isDownloading"
|
||||
class="loading-ring"
|
||||
:style="{ '--progress': progress + '%' }"
|
||||
>
|
||||
<div class="progress"></div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="!isDownloading && isDownloadComplete"
|
||||
class="check-success"
|
||||
title="已下载"
|
||||
>
|
||||
<CircleCheckFilled />
|
||||
</div>
|
||||
<div
|
||||
v-else-if="!isDownloading && isDownloadError"
|
||||
class="check-fail"
|
||||
title="点击重试"
|
||||
@click="onDownload"
|
||||
>
|
||||
<WarningFilled />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,6 +138,54 @@ onMounted(() => {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
|
||||
.download {
|
||||
width: 32px;
|
||||
color: blue;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.loading-ring {
|
||||
position: relative;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
.progress {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-ring:not(.completed) {
|
||||
background: conic-gradient(#007bff 0% var(--progress), #ccc var(--progress) 100%);
|
||||
}
|
||||
|
||||
.loading-ring.completed {
|
||||
background: #007bff;
|
||||
}
|
||||
|
||||
.check-success {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: #95d475;
|
||||
}
|
||||
|
||||
.check-fail {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: red;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user