|
|
@@ -69,9 +69,10 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
-import { defineExpose } from 'vue';
|
|
|
-import { ref, computed, reactive, onMounted, watch, defineProps, defineEmits } from 'vue';
|
|
|
-import { UploadFilled } from '@element-plus/icons-vue';
|
|
|
+import {computed, defineEmits, defineExpose, defineProps, reactive, ref, watch} from 'vue';
|
|
|
+import {UploadFilled} from '@element-plus/icons-vue';
|
|
|
+import {ElMessage, ElMessageBox} from "element-plus";
|
|
|
+import {uploadChunk} from '@/api/smsb/source/minioData';
|
|
|
|
|
|
// 允许的文件类型白名单
|
|
|
const ALLOWED_EXTENSIONS = {
|
|
|
@@ -119,9 +120,7 @@ const ossId = computed({
|
|
|
const uploadStates = reactive<Record<string | number, UploadState>>({});
|
|
|
|
|
|
// 分片上传相关常量
|
|
|
-const CHUNK_SIZE = 1 * 1024 * 1024; // 1MB
|
|
|
-import { ElMessage, ElMessageBox } from "element-plus";
|
|
|
-import { uploadChunk } from '@/api/smsb/source/minioData';
|
|
|
+const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB
|
|
|
|
|
|
const isUploading = computed(() => {
|
|
|
return Object.values(uploadStates).some((state) => state.status === 'uploading');
|
|
|
@@ -162,7 +161,7 @@ function handleUploadSuccess(response: any) {
|
|
|
|
|
|
function handleFileChange(uploadFile: any, uploadFiles: any[]) {
|
|
|
if (!isFileTypeAllowed(uploadFile.name)) {
|
|
|
- ElMessage.error(`不支持的文件类型: ${uploadFile.name},仅支持图片(jpg,png等)、音频(mp3,wav等)和视频(mp4,mov等)文件`);
|
|
|
+ ElMessage.error(`不支持的文件类型: ${uploadFile.name},仅支持图片(jpg/jpeg,png)和视频(mp4,avi)文件`);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
@@ -212,7 +211,7 @@ async function sendChunkRequest(formData: FormData, fileUid: string | number, ch
|
|
|
currentState.status = "success";
|
|
|
ElMessage.success(`${file.name} 上传并合并成功!`);
|
|
|
}
|
|
|
- }, 5000);
|
|
|
+ }, 600000);
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
@@ -230,7 +229,7 @@ async function sendChunkRequest(formData: FormData, fileUid: string | number, ch
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-async function uploadFileChunks(file: any) {
|
|
|
+async function uploadFileChunks(file: any, tag: number, sourceTreeIds: Array<number | string>) {
|
|
|
const rawFile = file.raw;
|
|
|
if (!rawFile) {
|
|
|
uploadStates[file.uid].status = "error";
|
|
|
@@ -250,55 +249,33 @@ async function uploadFileChunks(file: any) {
|
|
|
uploadedChunks: new Set(),
|
|
|
finalUrl: null,
|
|
|
};
|
|
|
- // 先上传前 N-1 个分片
|
|
|
- const chunkPromises: Promise<void>[] = [];
|
|
|
- for (let chunkIndex = 0; chunkIndex < totalChunks - 1; chunkIndex++) {
|
|
|
- const start = chunkIndex * CHUNK_SIZE;
|
|
|
- const end = Math.min(start + CHUNK_SIZE, rawFile.size);
|
|
|
- const chunk = rawFile.slice(start, end);
|
|
|
- const formData = new FormData();
|
|
|
- formData.append("file", chunk, `${file.name}.chunk${chunkIndex}`);
|
|
|
- formData.append("filename", file.name);
|
|
|
- formData.append("chunkIndex", String(chunkIndex));
|
|
|
- formData.append("totalChunks", String(totalChunks));
|
|
|
- formData.append("fileSize", String(rawFile.size));
|
|
|
- formData.append("fileType", rawFile.type || "application/octet-stream");
|
|
|
- formData.append("uploadId", uploadId);
|
|
|
- // 打印每个分片的参数
|
|
|
- // console.log('[分片上传] chunk params', {
|
|
|
- // uploadId,
|
|
|
- // filename: file.name,
|
|
|
- // chunkIndex,
|
|
|
- // totalChunks,
|
|
|
- // fileSize: rawFile.size,
|
|
|
- // fileType: rawFile.type || "application/octet-stream"
|
|
|
- // });
|
|
|
- chunkPromises.push(sendChunkRequest(formData, fileUid, chunkIndex, file));
|
|
|
- }
|
|
|
+
|
|
|
try {
|
|
|
- // 等待前 N-1 个分片全部上传
|
|
|
- const results = await Promise.allSettled(chunkPromises);
|
|
|
- const failedChunk = results.find((result) => result.status === "rejected");
|
|
|
- if (failedChunk) {
|
|
|
- uploadStates[fileUid].status = "error";
|
|
|
- uploadStates[fileUid].errorMessage = uploadStates[fileUid].errorMessage || "一个或多个分片上传失败";
|
|
|
- // ElMessage.error(`${file.name} 上传失败: ${uploadStates[fileUid]?.errorMessage}`);
|
|
|
- return;
|
|
|
+ // 同步上传所有分片
|
|
|
+ for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
|
|
|
+ const start = chunkIndex * CHUNK_SIZE;
|
|
|
+ const end = Math.min(start + CHUNK_SIZE, rawFile.size);
|
|
|
+ const chunk = rawFile.slice(start, end);
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append("file", chunk, `${file.name}.chunk${chunkIndex}`);
|
|
|
+ formData.append("filename", file.name);
|
|
|
+ formData.append("chunkIndex", String(chunkIndex));
|
|
|
+ formData.append("totalChunks", String(totalChunks));
|
|
|
+ formData.append("fileSize", String(rawFile.size));
|
|
|
+ formData.append("fileType", rawFile.type || "application/octet-stream");
|
|
|
+ formData.append("uploadId", uploadId);
|
|
|
+ formData.append("tag",String(tag));
|
|
|
+ formData.append("sourceTreeIds", sourceTreeIds);
|
|
|
+
|
|
|
+
|
|
|
+ // 等待当前分片上传完成
|
|
|
+ await sendChunkRequest(formData, fileUid, chunkIndex, file);
|
|
|
+
|
|
|
+ // 更新进度
|
|
|
+ const progress = Math.round(((chunkIndex + 1) / totalChunks) * 100);
|
|
|
+ uploadStates[fileUid].progress = progress;
|
|
|
}
|
|
|
- // 前 N-1 个分片全部成功后,上传最后一个分片
|
|
|
- const lastChunkIndex = totalChunks - 1;
|
|
|
- const start = lastChunkIndex * CHUNK_SIZE;
|
|
|
- const end = Math.min(start + CHUNK_SIZE, rawFile.size);
|
|
|
- const lastChunk = rawFile.slice(start, end);
|
|
|
- const lastFormData = new FormData();
|
|
|
- lastFormData.append("file", lastChunk, `${file.name}.chunk${lastChunkIndex}`);
|
|
|
- lastFormData.append("filename", file.name);
|
|
|
- lastFormData.append("chunkIndex", String(lastChunkIndex));
|
|
|
- lastFormData.append("totalChunks", String(totalChunks));
|
|
|
- lastFormData.append("fileSize", String(rawFile.size));
|
|
|
- lastFormData.append("fileType", rawFile.type || "application/octet-stream");
|
|
|
- lastFormData.append("uploadId", uploadId);
|
|
|
- await sendChunkRequest(lastFormData, fileUid, lastChunkIndex, file);
|
|
|
+
|
|
|
// 判断所有分片是否都上传成功
|
|
|
const finalState = uploadStates[fileUid];
|
|
|
if (finalState && finalState.status === "uploading") {
|
|
|
@@ -325,7 +302,7 @@ async function uploadFileChunks(file: any) {
|
|
|
}
|
|
|
|
|
|
// 多文件上传入口,弹窗确认
|
|
|
-async function handleUpload() {
|
|
|
+async function handleUpload(tag: number, sourceTreeIds: Array<number | string>) {
|
|
|
const filesToUpload = fileList.value.filter(
|
|
|
(file) =>
|
|
|
file.uid !== undefined &&
|
|
|
@@ -362,7 +339,7 @@ async function handleUpload() {
|
|
|
};
|
|
|
}
|
|
|
});
|
|
|
- const allUploadPromises = filesToUpload.map((file) => uploadFileChunks(file));
|
|
|
+ const allUploadPromises = filesToUpload.map((file) => uploadFileChunks(file, tag, sourceTreeIds));
|
|
|
await Promise.allSettled(allUploadPromises);
|
|
|
const successfulUploads = fileUidsToUpload.filter(
|
|
|
uid => uploadStates[uid]?.status === "success"
|
|
|
@@ -380,7 +357,7 @@ async function handleUpload() {
|
|
|
if (stillProcessing > 0) {
|
|
|
summaryMessage += ` ${stillProcessing} 个仍在处理中。`;
|
|
|
}
|
|
|
- // ElMessage.info(summaryMessage);
|
|
|
+ ElMessage.info(summaryMessage);
|
|
|
} catch {
|
|
|
ElMessage.info("上传已取消");
|
|
|
}
|