125 lines
3.0 KiB
Vue
125 lines
3.0 KiB
Vue
<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', status === 'failed' ? 'error' : '']">{{ statusText }}</div>
|
|
<a-progress :percent="percent" :stroke-width="10" :status="getProgressStatus" />
|
|
</div>
|
|
</div>
|
|
</transition>
|
|
</Teleport>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, watch, computed } from "vue";
|
|
import { Progress as AProgress } from "@arco-design/web-vue";
|
|
import { ProgressStatus } from ".";
|
|
|
|
// 状态变量
|
|
const visible = ref(false);
|
|
const percent = ref(0);
|
|
const statusText = ref("正在上传,请稍候");
|
|
const status = ref<ProgressStatus>("uploading"); // 使用 ProgressStatus 类型
|
|
|
|
// 监听 percent 变化,更新状态文本
|
|
watch(percent, (newPercent) => {
|
|
const clampedPercent = Math.min(newPercent, 1); // 确保 percent 不超过 1
|
|
percent.value = clampedPercent; // 更新实际的 percent 值
|
|
|
|
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 ? "normal" : "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 = parseFloat((p / 100).toFixed(2)); // 保留两位小数
|
|
}
|
|
|
|
defineExpose({
|
|
open,
|
|
close,
|
|
setPercent,
|
|
setStatus: (newStatus: ProgressStatus) => {
|
|
status.value = newStatus; // 使用 ProgressStatus 类型
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<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>
|