This commit is contained in:
oneao committed 2025-12-11 17:31:05 +08:00
1 parent 68e0785ec6
commit 57c0d98f11
189 files changed
+34329

No files matched your search

@@ -0,0 +1,39 @@
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();
}
}
// 如果你有 ProgressStatus 类型的需求,确保你导出它
export type ProgressStatus = "uploading" | "completed" | "failed";
@@ -0,0 +1,124 @@
<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>