import {defineStore} from 'pinia' import {ref, onMounted} from 'vue' import axios from 'axios' import SparkMD5 from 'spark-md5' import tool from '@/utils/tool' import {message} from 'ant-design-vue' import sysConfig from '@/config/index' import resourceAuditApi from '@/api/resourceAudit.js' import EventBus from "@/utils/EventBus"; export const miniyunStore = defineStore({ id: 'miniyun', state: () => ({ pauseFlags: {}, // 控制每个文件是否暂停 { md5: true/false } uploadingTasks: {}, // 正在上传的任务 { md5: true } checkingFiles: new Set(), // 正在检查的文件MD5 checkedFiles: new Map(), // 已检查的文件结果缓存 //当前选中的文件 currentFile: null, spinning: false, chunkSize: 5 * 1024 * 1024, uploadedSize: 0, // 已上传文件大小(字节) chunkCount: 0, chunksUploaded: 0, fileMd5: '', // // const emit = defineEmits(['onUpLoading', 'onSuccess']) progress: { strokeColor: { '0%': '#108ee9', '100%': '#87d068' }, strokeWidth: 3, format: (percent) => `${parseFloat(percent.toFixed(2))}%`, class: 'test' }, allChunks: 0, // 文件的md5值 successfulChunkPercents: 0, // 上传成功的分片百分比 fileSuffix: '', // 文件后缀 chunkList: [], // 文件后缀 uploadList: [], // 文件后缀 fileList: [],// 文件后缀 uploadFileList: [], // 文件后缀 uploadChunks: [],// 文件后缀 uploadFileListTemp: [], upLoadTag: false, // 文件的md5值 startTime: 0, // 开始时间戳(毫秒 totalSize: 0, // 开始时间戳(毫秒 tempIndex: 0, //文件数据放一起 fileForms: [], }), getters: { getFileForms: (state) => state.fileForms, getPauseFlags: (state) => state.pauseFlags, }, actions: { async addFileForms(fileForm) { this.fileForms.push(fileForm) for (let i = 0; i < fileForm.uploadFileList.length; i++) { await this.checkMd5List(fileForm.uploadFileList[i]) await this.uploadSingleFile(fileForm.uploadFileList[i]) } //准备开启去下载 // for (let i = 0; i < fileForm.uploadFileList.length; i++) { // this.tempIndex+=1 // fileForm.uploadFileList[i].tempIndex = this.tempIndex // this.uploadFileListTemp.push(fileForm.uploadFileList[i]) // } }, handlerRemoveItem(mmyIndex, mmmyIndex) { // let myIndex = -1 // for (let i = 0; i < this.uploadFileListTemp.length; i++) { // if(this.uploadFileListTemp[i].tempIndex == item.tempIndex){ // myIndex = i // } // } // if(myIndex != -1){ // this.uploadFileListTemp.splice(myIndex, 1) // } // let mmyIndex = -1 // let mmmyIndex = -1 // for (let i = 0; i < this.fileForms.length; i++) { // for (let ii = 0; ii < this.fileForms[i].uploadFileList.length; ii++) { // if(this.fileForms[i].uploadFileList[ii].tempIndex == item.tempIndex){ // mmyIndex = i // mmmyIndex = ii // } // } // } // if(mmyIndex != -1 && mmmyIndex != -1){ // this.fileForms[mmyIndex].uploadFileList.splice(mmmyIndex, 1) // } this.fileForms[mmyIndex].uploadFileList.splice(mmmyIndex, 1) }, pauseUpload(md5) { this.pauseFlags[md5] = true }, resumeUpload(md5) { this.pauseFlags[md5] = false }, async checkMd5List(uploadFile) { // 标记文件正在检查 this.checkingFiles.add(uploadFile.md5) const md5List = [{ md5: uploadFile.md5, size: uploadFile.size, chunkSize: uploadFile.chunks.length, fileName: uploadFile.name, fileSuffix: uploadFile.fileSuffix, affiliationFuncType : 0 }] await axios .post(sysConfig.API_URL + '/api/webapp/minio/checkMd5List', md5List, {headers: {Token: tool.data.get('TOKEN')}}) .then((res) => { console.log('文件上传返回结果:', res.data) // return var list = res.data if (list.length !== 0) { let upList = [] for (let item of list) { console.log('item回来的', JSON.stringify(item)) if (uploadFile.md5 === item.md5) { uploadFile.userFileId = item.userFileId //重要的步骤 if (item.userFileId) { uploadFile.percents = 100 this.checkedFiles.set(uploadFile.md5, { userFileId: item.userFileId, status: 'uploaded' }) // emit('onSuccess', uploadFile) } // upList.push(item) } } console.log('upList是:', upList) // uploadFileList.value.push(uploadFile) // emit('onSuccess', uploadFileList.value) } // 从正在检查列表中移除 this.checkingFiles.delete(uploadFile.md5) return uploadFile // 文件均存在minio中了,无需上传 // if (uploadFileList.value.length === 0) { // successfulChunkPercents.value = 100 // alert('文件上传成功') // } }) .catch((error) => { console.log('检查返回错误', error) // 从正在检查列表中移除 this.checkingFiles.delete(uploadFile.md5) throw error }) }, async uploadFilesChunk(data, onSuccess) { console.log('进入了uploadFileChunk方法...') let retryTime = 5 //重试次数 const formData = new FormData() formData.append('md5', data.md5) // formData.append('md5', md5) formData.append('chunkIndex', data.chunkIndex) formData.append('chunk', data.chunk) formData.append('chunkSize', data.chunkSize) formData.append('fileSuffix', data.fileSuffix) formData.append('fileName', data.fileName) formData.append('affiliationFuncType', data.affiliationFuncType) return axios .post(sysConfig.API_URL + '/api/webapp/minio/upload', formData, { headers: {'Content-Type': 'multipart/form-data', Token: tool.data.get('TOKEN')} }) .then((res) => onSuccess()) .catch((error) => { console.log('上传分片失败了...', error) if (retryTime > 0) { retryTime-- return this.uploadChunk(data, onSuccess) } }) }, // 上传分片 旧 async uploadChunk(data, onSuccess) { let retryTime = 5 //重试次数 const formData = new FormData() // formData.append('identifier', fileMd5.value) formData.append('md5', data.md5) // formData.append('md5', md5) formData.append('chunkIndex', data.chunkIndex) formData.append('chunk', data.chunk) formData.append('chunkSize', data.chunkSize) formData.append('fileSuffix', data.fileSuffix) formData.append('fileName', data.fileName) formData.append('affiliationFuncType', data.affiliationFuncType) return axios .post(sysConfig.API_URL + '/api/webapp/minio/upload', formData, { headers: {'Content-Type': 'multipart/form-data', Token: tool.data.get('TOKEN')} }) .then((res) => onSuccess()) .catch((error) => { if (retryTime > 0) { retryTime-- return this.uploadChunk(data, onSuccess) } }) }, calculateSpeed(startTime, uploadedSize) { const currentTime = new Date().getTime() const timeElapsed = (currentTime - startTime) / 1000 // 单位:秒 if (timeElapsed > 0) { const speed = uploadedSize / timeElapsed // 单位:字节/秒 return speed } return 0 }, estimateRemainingTime(startTime, uploadedSize, totalSize) { console.log('疑问', ' 总的 ', totalSize, ' 变化的 ', uploadedSize) const remainingSize = totalSize - uploadedSize // 剩余文件大小 const speed = this.calculateSpeed(startTime, uploadedSize) // 平均上传速度(字节/秒) if (speed > 0) { const remainingTimeSeconds = remainingSize / speed // 剩余时间(秒) return remainingTimeSeconds } return Infinity // 如果上传速度为 0,则无法估算 }, formatTime(seconds) { const minutes = Math.floor(seconds / 60) const secs = Math.floor(seconds % 60) if (minutes == 0 && secs == 0) { return '' } return `${minutes} 分 ${secs} 秒` }, async uploadSingleFile(fileObj) { const file = fileObj const md5 = file.md5 // const index = uploadFileList.value.findIndex((item) => item.md5 === md5) // // if (index === -1) return const item = fileObj if (item && item.userFileId) { this.getUp(fileObj) return } // // 如果是暂停状态则不执行上传 // while (pauseFlags.value[md5]) { // await new Promise((resolve) => setTimeout(resolve, 500)) // } // 添加到正在上传任务中 // uploadingTasks.value[md5] = true file.startTime = new Date().getTime() file.uploadedSize = 0 const chunkPromises = [] for (let i = 0; i < item.chunks.length; i++) { let chunk = item.chunks[i] while (this.pauseFlags[md5]) { await new Promise((resolve) => setTimeout(resolve, 500)) } chunkPromises.push( await this.uploadFilesChunk( { affiliationFuncType : 0, md5, chunk, chunkIndex: i + 1, fileSuffix: item.fileSuffix, chunkSize: item.chunks.length, fileName: item.name }, () => { // chunksUploaded.value++ // uploadChunks.value++ // successfulChunkPercents.value = 100 * (uploadChunks.value / allChunks.value).toFixed(2) item.uploadedSize += chunk.size // 更新已上传大小 const remainingTime = this.estimateRemainingTime(item.startTime, item.uploadedSize, item.size) console.log(`预计剩余时间: ${this.formatTime(remainingTime)}`) // item.percents = (100 * (uploadChunks.value / item.chunks.length)).toFixed(2) item.time = this.formatTime(remainingTime) const percent = ((i + 1) / item.chunks.length) * 100 item.percents = percent.toFixed(2) console.log(`我得名字: `, item.name, ' i ', i, ' item.chunks.length ', item.chunks.length) // item.time = formatTime(estimateRemainingTime()) } ) ) } await Promise.all(chunkPromises) item.affiliationFuncType = 0 // 合并分片 const mergeResult = await axios.post( sysConfig.API_URL + `/api/webapp/minio/merge?md5=${md5}&fileSuffix=${item.fileSuffix}&chunkTotal=${item.chunks.length}&fileName=${item.name}&fileSize=${item.size}&affiliationFuncType=${item.affiliationFuncType}`, null, {headers: {Token: tool.data.get('TOKEN')}} ) console.log('怎么说呢', ' 啊网络请求 ', mergeResult) fileObj.userFileId = mergeResult.data.userFileId fileObj.percents = 100 // uploadingTasks.value[item.md5] = false // item.time = '上传完成' // 尝试恢复一个被暂停的任务 // autoResumePausedUpload() // upLoadTag.value = false // emit('onSuccess', uploadFileList.value) this.getUp(fileObj) }, async getUp(fileObj) { for (let i = 0; i < this.fileForms.length; i++) { console.log('怎么说呢', this.fileForms[i].upTag != undefined,' 里面的 ', this.fileForms[i], ' 外面的1 ', fileObj) if (this.fileForms[i].upTag == undefined) { let count = 0 let list = [] for (let ii = 0; ii < this.fileForms[i].uploadFileList.length; ii++) { console.log('怎么说呢', ' 里面的 ', this.fileForms[i], ' 外面的2 ', fileObj) let item = this.fileForms[i].uploadFileList[ii] if (item.userFileId != undefined && item.percents == 100){ count ++ list.push(item.userFileId) } } if(this.fileForms[i].uploadFileList.length == count){ let formData = this.fileForms[i] formData.userfileIds = list.join(',') //去上传 let res = await resourceAuditApi.stuLinkResourceRecordAdd(formData) // .then((res) => { // Modal.success({ content: '资源上传成功' }) // }) // .catch((err) => { // Modal.success({ content: '资源上传失败' }) // console.log(err) // }) console.log('上传至hi偶',res) this.fileForms[i].upTag = true EventBus.emit('onUpTag') } } } } }, })