This commit is contained in:
oneao committed 2026-04-24 17:28:11 +08:00
1 parent 07e0001b87
commit 46cbb2f50d
543 files changed
+32576 -4231

No files matched your search

@@ -0,0 +1,38 @@
import { createApp } from 'vue'
import UploadProgress from './index.vue'
let app: ReturnType<typeof createApp> | null = null
let instance: any = null
export function showUploadProgress(status: ProgressStatus = 'uploading') {
if (!app) {
const container = document.createElement('div')
document.body.appendChild(container)
app = createApp(UploadProgress)
instance = app.mount(container)
}
instance.open()
instance.setStatus(status) // 外部传入状态
}
export function updateUploadProgress(percent: number, status: ProgressStatus = 'uploading') {
if (instance) {
instance.setPercent(percent)
instance.setStatus(status) // 外部传入状态
if (percent >= 100) {
setTimeout(() => {
closeUploadProgress()
}, 800) // 100%后等一下再关闭,显得自然
}
}
}
export function closeUploadProgress() {
if (instance) {
instance.close()
}
}
export type ProgressStatus = 'uploading' | 'completed' | 'failed'
@@ -0,0 +1,128 @@
<script setup lang="ts">
import type { ProgressStatus } from '.'
import { computed, ref, watch } from 'vue'
// 状态变量
const visible = ref(false)
const percent = ref(0)
const statusText = ref('正在上传,请稍候')
const status = ref<ProgressStatus>('uploading')
// 监听 percent 变化,更新状态文本
watch(percent, (newPercent) => {
const clampedPercent = Math.min(newPercent, 1)
percent.value = clampedPercent
if (clampedPercent === 1) {
status.value = 'completed'
}
else if (clampedPercent < 1 && status.value !== 'failed') {
status.value = 'uploading'
}
})
// 监听上传状态变化,更新状态文本
watch(status, (newStatus) => {
if (newStatus === 'completed') {
statusText.value = '上传完毕'
}
else if (newStatus === 'uploading') {
statusText.value = '正在上传,请稍候 . . .'
}
else if (newStatus === 'failed') {
statusText.value = '上传失败,请稍后再试 . . .'
}
})
// 获取进度条状态,上传失败时显示为 "exception"
const getProgressStatus = computed(() => {
if (status.value === 'failed') {
return 'exception'
}
return percent.value < 1 ? '' : 'success'
})
// 控制上传进度的函数
function open() {
percent.value = 0
visible.value = true
status.value = 'uploading' // 开始上传时重置状态
statusText.value = '正在上传,请稍候 . . .'
}
function close() {
visible.value = false
}
function setPercent(p: number) {
percent.value = Number.parseFloat((p / 100).toFixed(2)) // 保留两位小数
}
defineExpose({
open,
close,
setPercent,
setStatus: (newStatus: ProgressStatus) => {
status.value = newStatus // 使用 ProgressStatus 类型
},
})
</script>
<template>
<Teleport to="body">
<transition name="fade">
<div v-if="visible" class="upload-progress-mask">
<div class="upload-progress-card">
<div class="upload-progress-title" :class="[status === 'failed' ? 'error' : '']">
{{ statusText }}
</div>
<el-progress :percentage="percent" :stroke-width="10" :status="getProgressStatus" />
</div>
</div>
</transition>
</Teleport>
</template>
<style scoped>
.upload-progress-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
z-index: 3000;
display: flex;
justify-content: center;
align-items: center;
}
.upload-progress-card {
background: #ffffff;
padding: 40px 50px;
border-radius: 12px;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.3);
text-align: center;
min-width: 320px;
}
.upload-progress-title {
font-size: 22px;
font-weight: bold;
margin-bottom: 30px;
color: #333;
}
.upload-progress-title.error {
color: red; /* 上传失败时,字体颜色变为红色 */
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>