新增商品拼团
This commit is contained in:
@@ -2,7 +2,8 @@
|
||||
<template>
|
||||
<el-upload v-model:file-list="fileList" list-type="picture-card" :before-upload="handleBeforeUpload"
|
||||
:http-request="handleUpload" :on-success="handleSuccess" :on-progress="handleProgress" :on-error="handleError"
|
||||
:on-exceed="handleExceed" :accept="props.accept" :limit="props.limit" multiple :auto-upload="true">
|
||||
:on-exceed="handleExceed" :accept="props.accept" :limit="props.limit" multiple :auto-upload="true"
|
||||
:on-change="handleFileChange">
|
||||
<el-icon>
|
||||
<Plus />
|
||||
</el-icon>
|
||||
@@ -32,9 +33,9 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, onMounted, PropType, computed } from "vue";
|
||||
import { ref, watch, onMounted, PropType } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { UploadRawFile, UploadRequestOptions, UploadUserFile } from "element-plus";
|
||||
import { UploadRawFile, UploadRequestOptions, UploadUserFile, UploadFileStatus } from "element-plus";
|
||||
import FileAPI, { FileInfo } from "@/api/account/common";
|
||||
|
||||
// 定义Props
|
||||
@@ -49,7 +50,7 @@ const props = defineProps({
|
||||
},
|
||||
limit: {
|
||||
type: Number,
|
||||
default: 10,
|
||||
default: 9,
|
||||
},
|
||||
maxFileSize: {
|
||||
type: Number,
|
||||
@@ -62,7 +63,7 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
// 定义Emits
|
||||
const emit = defineEmits(['upDataEvent', 'uploadAllSuccess']); // 新增:所有图片上传完成事件
|
||||
const emit = defineEmits(['upDataEvent', 'uploadAllSuccess']);
|
||||
|
||||
// 响应式数据
|
||||
const previewVisible = ref(false);
|
||||
@@ -76,9 +77,8 @@ const modelValue = defineModel<string[]>("modelValue", {
|
||||
});
|
||||
|
||||
const fileList = ref<UploadUserFile[]>([]);
|
||||
// 新增:批量上传计数
|
||||
const pendingUploadCount = ref(0); // 待上传文件数
|
||||
const completedUploadCount = ref(0); // 已完成上传数
|
||||
// 修复:用Map跟踪每个文件的上传状态(key=uid,value=是否完成),替代计数
|
||||
const uploadingFiles = ref<Map<string, { status: 'pending' | 'success' | 'error', file: UploadUserFile }>>(new Map());
|
||||
|
||||
/**
|
||||
* 删除图片
|
||||
@@ -87,6 +87,11 @@ function handleRemove(imageUrl: string) {
|
||||
const index = modelValue.value.indexOf(imageUrl);
|
||||
if (index !== -1) {
|
||||
modelValue.value.splice(index, 1);
|
||||
// 同步删除fileList和上传状态跟踪
|
||||
const fileItem = fileList.value[index];
|
||||
if (fileItem?.uid) {
|
||||
uploadingFiles.value.delete(fileItem.uid);
|
||||
}
|
||||
fileList.value.splice(index, 1);
|
||||
}
|
||||
}
|
||||
@@ -94,12 +99,28 @@ function handleRemove(imageUrl: string) {
|
||||
/**
|
||||
* 上传进度
|
||||
*/
|
||||
function handleProgress(event: any) {
|
||||
console.log("文件上传进度", Math.round(event.percent));
|
||||
function handleProgress(event: any, uploadFile: UploadUserFile) {
|
||||
console.log(`文件${uploadFile.name}上传进度`, Math.round(event.percent));
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传前校验 & 初始化待上传文件
|
||||
* 修复:文件状态变化时跟踪(替代beforeUpload手动push)
|
||||
*/
|
||||
function handleFileChange(file: UploadUserFile, files: UploadUserFile[]) {
|
||||
// 仅跟踪新增的、待上传的文件
|
||||
if (file.status === 'ready' && !uploadingFiles.value.has(file.uid)) {
|
||||
uploadingFiles.value.set(file.uid, {
|
||||
status: 'pending',
|
||||
file
|
||||
});
|
||||
emit('upDataEvent', true); // 开始上传,触发loading
|
||||
}
|
||||
// 同步fileList(避免重复)
|
||||
fileList.value = files;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传前校验(仅保留校验逻辑,不再手动修改fileList)
|
||||
*/
|
||||
function handleBeforeUpload(file: UploadRawFile) {
|
||||
// 1. 文件类型校验
|
||||
@@ -125,19 +146,6 @@ function handleBeforeUpload(file: UploadRawFile) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 新增:初始化待上传文件到fileList,确保uid匹配
|
||||
const uploadFile: UploadUserFile = {
|
||||
uid: file.uid, // 关键:复用文件原生uid
|
||||
name: file.name,
|
||||
status: "ready",
|
||||
raw: file,
|
||||
};
|
||||
fileList.value.push(uploadFile);
|
||||
|
||||
// 4. 新增:增加待上传计数
|
||||
pendingUploadCount.value++;
|
||||
emit('upDataEvent', true); // 开始上传,触发loading
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -173,46 +181,74 @@ function handleExceed(files: File[], uploadFiles: UploadUserFile[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 单文件上传成功回调
|
||||
* 修复:单文件上传成功回调(精准更新+批量完成判断)
|
||||
*/
|
||||
const handleSuccess = (fileInfo: FileInfo, uploadFile: UploadUserFile) => {
|
||||
// 1. 修复:通过uid精准匹配文件
|
||||
const index = fileList.value.findIndex((file) => file.uid === uploadFile.uid);
|
||||
if (index !== -1) {
|
||||
fileList.value[index].url = fileInfo as string; // 确保fileInfo是字符串类型
|
||||
fileList.value[index].status = "success";
|
||||
// 同步更新modelValue(若index超出当前长度,push;否则替换)
|
||||
if (index >= modelValue.value.length) {
|
||||
modelValue.value.push(fileInfo as string);
|
||||
} else {
|
||||
modelValue.value[index] = fileInfo as string;
|
||||
// 1. 精准匹配文件并更新状态
|
||||
if (uploadingFiles.value.has(uploadFile.uid)) {
|
||||
uploadingFiles.value.set(uploadFile.uid, {
|
||||
status: 'success',
|
||||
file: uploadFile
|
||||
});
|
||||
// 2. 更新fileList的url和状态
|
||||
const index = fileList.value.findIndex((f) => f.uid === uploadFile.uid);
|
||||
if (index !== -1) {
|
||||
fileList.value[index].url = fileInfo as string;
|
||||
fileList.value[index].status = "success" as UploadFileStatus;
|
||||
// 3. 同步更新modelValue(确保追加,而非替换)
|
||||
if (!modelValue.value.includes(fileInfo as string)) {
|
||||
modelValue.value.push(fileInfo as string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 新增:完成计数+判断所有上传完成
|
||||
completedUploadCount.value++;
|
||||
if (completedUploadCount.value === pendingUploadCount.value) {
|
||||
ElMessage.success("所有图片上传成功!");
|
||||
emit('uploadAllSuccess', modelValue.value); // 所有图片上传完成,emit成功事件
|
||||
// 重置计数
|
||||
pendingUploadCount.value = 0;
|
||||
completedUploadCount.value = 0;
|
||||
emit('upDataEvent', false); // 结束loading
|
||||
}
|
||||
// 4. 检查是否所有上传中的文件都完成
|
||||
checkAllUploadCompleted();
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传失败回调
|
||||
*/
|
||||
const handleError = (error: any) => {
|
||||
console.error("上传失败:", error);
|
||||
ElMessage.error("上传失败: " + (error.message || "未知错误"));
|
||||
// 重置计数+结束loading
|
||||
pendingUploadCount.value = 0;
|
||||
completedUploadCount.value = 0;
|
||||
emit('upDataEvent', false);
|
||||
const handleError = (error: any, uploadFile: UploadUserFile) => {
|
||||
console.error(`文件${uploadFile.name}上传失败:`, error);
|
||||
ElMessage.error(`文件${uploadFile.name}上传失败: ` + (error.message || "未知错误"));
|
||||
|
||||
// 更新失败文件状态
|
||||
if (uploadingFiles.value.has(uploadFile.uid)) {
|
||||
uploadingFiles.value.set(uploadFile.uid, {
|
||||
status: 'error',
|
||||
file: uploadFile
|
||||
});
|
||||
}
|
||||
|
||||
// 检查是否所有上传中的文件都完成(失败也算完成)
|
||||
checkAllUploadCompleted();
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增:检查所有上传文件是否完成(成功/失败都算完成)
|
||||
*/
|
||||
function checkAllUploadCompleted() {
|
||||
// 过滤出还在pending的文件
|
||||
const pendingFiles = Array.from(uploadingFiles.value.values()).filter(item => item.status === 'pending');
|
||||
|
||||
// 没有pending文件 → 所有上传完成
|
||||
if (pendingFiles.length === 0 && uploadingFiles.value.size > 0) {
|
||||
// 过滤出成功的文件URL
|
||||
const successUrls = Array.from(uploadingFiles.value.values())
|
||||
.filter(item => item.status === 'success')
|
||||
.map(item => item.file.url)
|
||||
.filter(Boolean) as string[];
|
||||
|
||||
ElMessage.success(`上传完成!成功${successUrls.length}张,失败${uploadingFiles.value.size - successUrls.length}张`);
|
||||
emit('uploadAllSuccess', modelValue.value); // 触发全部完成事件
|
||||
emit('upDataEvent', false); // 结束loading
|
||||
|
||||
// 重置上传状态跟踪(关键:避免多次触发)
|
||||
uploadingFiles.value.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预览图片
|
||||
*/
|
||||
@@ -228,22 +264,22 @@ const handlePreviewClose = () => {
|
||||
previewVisible.value = false;
|
||||
};
|
||||
|
||||
// 监听modelValue同步fileList
|
||||
// 修复:监听modelValue同步fileList(避免重复uid)
|
||||
watch(modelValue, (newValue) => {
|
||||
fileList.value = newValue.map((url) => ({
|
||||
url,
|
||||
uid: Date.now() + Math.random(), // 为已有图片生成唯一uid
|
||||
status: "success"
|
||||
}) as UploadUserFile);
|
||||
uid: `init-${Date.now()}-${Math.random()}`, // 为初始化图片生成唯一uid(避免和上传文件冲突)
|
||||
status: "success" as UploadFileStatus
|
||||
}));
|
||||
}, { immediate: true });
|
||||
|
||||
onMounted(() => {
|
||||
// 初始化fileList
|
||||
fileList.value = modelValue.value.map((url) => ({
|
||||
url,
|
||||
uid: Date.now() + Math.random(),
|
||||
status: "success"
|
||||
}) as UploadUserFile);
|
||||
uid: `init-${Date.now()}-${Math.random()}`,
|
||||
status: "success" as UploadFileStatus
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user