let fileArr = []; // 保存的文件路径 let delFileArr = []; // 删除的文件路径 // 全局变量记录上传状态 let isUploading = false; let allowWindowClose = false; // 配置常量 let MAX_FILE_COUNT = 10; // 最大上传数量 const CHUNK_SIZE = 5 * 1024 * 1024; // 分片大小 5MB let fileSingleSizeLimit = 5 * 1024 * 1024 * 1024; let currentFileCount = 0; let uploader = null; let isAllUpload = true; // 文件是否已全部上传完成 function setParams() { getFileParameter(); $('#fileCounter').html(`已选择 0/${MAX_FILE_COUNT}个文件`); // 显示Toast提示 function showToast(message, type = 'error') { const $toast = $('#toast'); $toast.text(message).css('background-color', `var(--${type}-color)`); $toast.fadeIn(300); setTimeout(() => { $toast.fadeOut(300); }, 3000); } // 更新文件计数器 function updateFileCounter() { const $counter = $('#fileCounter'); $counter.text(`已选择 ${currentFileCount}/${MAX_FILE_COUNT} 个文件`); if (currentFileCount >= MAX_FILE_COUNT) { $counter.addClass('warning'); } else { $counter.removeClass('warning'); } } // 生成更可靠的文件UID function generateFileUID(file) { // 使用更稳定的属性组合生成UID return [ file.name.replace(/[^a-zA-Z0-9]/g, '_'), file.size, file.lastModifiedDate ? file.lastModifiedDate.getTime() : Date.now(), WebUploader.Base.guid() ].join('_').substring(0, 100); // 限制长度防止过长 } // 初始化WebUploader function initUploader() { uploader = WebUploader.create({ headers: { 'Authorization': token, 'encryption': 'encryption', }, auto: false, swf: '../../js/public/webuploader/Uploader.swf', server: dataUrl + 'proteam/pot/upload/uploadFile', pick: '#picker', chunked: true, chunkSize: CHUNK_SIZE, chunkTimeout: 120000, // 增加分片上传超时时间 threads: 3, fileNumLimit: MAX_FILE_COUNT, fileSizeLimit: 5 * 1024 * 1024 * 1024, fileSingleSizeLimit: fileSingleSizeLimit, duplicate: true, chunkRetry: 3, // 增加重试次数 disableGlobalDnd: true, prepareNextFile: false, finishTriggerFlag: 'successOnly', accept: { title: '所有文件', extensions: 'pdf|jpg|jpeg|png', mimeTypes: 'application/pdf,image/jpeg,image/png' }, formData: { uid: 'will-be-replaced' }, chunkAccept: function (res) { return res.status === 'chunk_uploaded' || res.status === 'complete' || res.status === 'chunk_existed' || res.status === 'merging_in_progress'; // 处理合并中的状态 } }); // 文件添加成功 uploader.on('fileQueued', function (file) { if (currentFileCount >= MAX_FILE_COUNT) { uploader.removeFile(file, true); showToast(`最多只能上传${MAX_FILE_COUNT}个文件`, 'warning'); return; } // 生成更可靠的UID file.uid = generateFileUID(file); currentFileCount++; updateFileCounter(); $('#startUpload').prop('disabled', false); $('#noFiles').hide(); // 添加文件到列表 const $fileList = $('#fileList'); const $tr = $(` ${file.name} ${formatFileSize(file.size)}
0%
等待上传 删除 `); $fileList.append($tr); // 绑定删除事件 $tr.find('.file-action').click(function () { const fileId = $(this).data('id'); const file = uploader.getFile(fileId); /* if (file && file.getStatus() === 'progress') { if (!confirm('文件正在上传中,确定要取消上传吗?')) { return; } } */ uploader.removeFile(fileId, true); $(`#file-${fileId}`).remove(); currentFileCount--; updateFileCounter(); if (currentFileCount === 0) { $('#noFiles').show(); $('#startUpload').prop('disabled', true); } delFileData(fileId); }); }); // 上传前设置UID uploader.on('uploadBeforeSend', function (block, data) { data.uid = block.file.uid; }); // 文件上传进度 uploader.on('uploadProgress', function (file, percentage) { const percent = Math.round(percentage * 100); const $tr = $(`#file-${file.id}`); $tr.find('.progress-bar') .css('width', `${percent}%`) .text(`${percent}%`); $tr.find('.file-status') .removeClass('status-waiting status-error status-success') .addClass('status-uploading') .find('.status-text').text('上传中'); }); // 分片上传成功 uploader.on('uploadAccept', function (file, response) { // 处理分片已存在的情况 if (response.status === 'chunk_existed') { console.log(`分片已存在: ${file.name} chunk ${response.chunk}`); return false; // 告诉WebUploader这个分片已经处理过了 } return true; }); // 文件开始上传时隐藏删除按钮 uploader.on('uploadStart', function (file) { $('#file-' + file.id + ' .file-action').hide(); isUploading = true; allowWindowClose = false; isAllUpload = false; }); // 文件上传成功 uploader.on('uploadSuccess', function (file, response) { const $tr = $(`#file-${file.id}`); if (response.status === 'merging_in_progress') { $tr.find('.file-status .status-text').text('合并中...'); return; } $('#file-' + file.id + ' .file-action').show(); if (response.status === 'success') { $tr.find('.file-status') .removeClass('status-waiting status-uploading status-error') .addClass('status-success') .find('.status-text').text('上传成功'); $tr.find('.file-action').show(); fileArr.push({ upload_id:file.id, filePath: response.path, fileSize: response.size, fileName: file.name, fileNewName: response.filename, fileId: response.filename.split('.')[0] }); } }); // 文件上传失败 uploader.on('uploadError', function (file, reason) { const $tr = $(`#file-${file.id}`); let errorMessage = '上传失败'; // 解析错误原因 if (reason === '404') { errorMessage = '上传接口不存在'; } else if (reason === '500') { errorMessage = '服务器内部错误'; } else if (reason.message) { errorMessage = reason.message; } else if (reason.responseText) { try { const res = JSON.parse(reason.responseText); errorMessage = res.message || '上传失败'; } catch (e) { errorMessage = reason.responseText; } } $tr.find('.file-status') .removeClass('status-waiting status-uploading') .addClass('status-error') .find('.status-text').text('上传失败'); $tr.find('.progress-bar').css('background-color', 'var(--danger-color)'); $tr.find('.file-action').show(); // 对于特定错误自动重试 if (reason === '404' || reason === '500') { setTimeout(() => { uploader.retry(file); }, 2000); } showToast(`文件 "${file.name}" 上传失败: ${errorMessage}`, 'error'); }); // 重试逻辑 uploader.on('error', function (type, file) { if (type === 'serverError' || type === 'uploadError') { // 服务器错误时延迟重试 setTimeout(() => { uploader.retry(file); }, 3000); } else if (type === 'chunkError') { // 分片错误时立即重试 uploader.retry(file); } }); // 上传完成 uploader.on('uploadComplete', function (file) { // 可以在这里做一些清理工作 }); // 所有文件上传完成 uploader.on('uploadFinished', function () { $('#startUpload').prop('disabled', true); isUploading = false; allowWindowClose = true; showToast('所有文件上传完成', 'success'); isAllUpload = true; // 检查是否有文件上传失败 const failedFiles = uploader.getFiles('error'); if (failedFiles.length > 0) { showToast(`${failedFiles.length}个文件上传失败,请重试`, 'warning'); } }); // 错误处理 uploader.on('error', function (type) { let errorMsg = ''; switch (type) { case 'F_EXCEED_SIZE': errorMsg = '文件大小超过限制'; break; case 'Q_EXCEED_NUM_LIMIT': errorMsg = `最多只能上传${MAX_FILE_COUNT}个文件`; break; case 'Q_TYPE_DENIED': errorMsg = '文件类型不允许'; break; case 'F_DUPLICATE': errorMsg = '文件已经存在队列中'; break; case 'F_EMPTY': errorMsg = '空文件不能上传'; break; case 'serverError': errorMsg = '服务器错误,请稍后重试'; break; case 'uploadError': errorMsg = '上传过程中发生错误'; break; case 'chunkError': errorMsg = '分片上传失败'; break; default: errorMsg = '上传出错: ' + type; } showToast(errorMsg, 'error'); }); } // 初始化上传器 initUploader(); // 开始上传按钮 $('#startUpload').click(function () { if (uploader.getFiles().length === 0) { showToast('请先选择文件', 'warning'); return; } uploader.upload(); showToast('开始上传文件...', 'success'); }); } // 删除保存的文件数据 function delFileData(idToDelete) { if (fileArr.length === 0) return; const index = fileArr.findIndex(item => item.upload_id === idToDelete); if (index !== -1) { const obj = fileArr[index]; delFileArr.push({ fileId: obj.fileId, fileName: obj.fileName, filePath:obj.filePath }); fileArr.splice(index, 1); console.log(delFileArr); } } // 获取文件上传数量限制 function getFileParameter() { let url = dataUrl + "proteam/pot/workPermit/getFileParameter"; let params = {}; ajaxRequest2(url, "POST", params, false, function (result) { console.log(result); if (result.code === 200) { if(result.data){ MAX_FILE_COUNT = result.data; } } }, function (xhr) { layer.close(loadingMsg); // 关闭提示层 error(xhr) }, null, token); } // 格式化文件大小 function formatFileSize(bytes) { if (bytes === 0) return '0 B'; const units = ['B', 'KB', 'MB', 'GB', 'TB']; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${units[i]}`; }