let form, layer, demo1, dataObj = {}; let fileArr = []; // 保存的文件路径 let delFileArr = []; // 删除的文件路径 let publishStatus = '0'; // 发布状态默认0-待发布 // 全局变量记录上传状态 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(params) { getFileParameter(); $('#fileCounter').html(`已选择 0/${MAX_FILE_COUNT}个文件`); dataObj = JSON.parse(params); layui.use(['form', 'layer', 'element'], function () { layer = layui.layer; form = layui.form; element = layui.element; setStudyObject(); form.on('submit(formData)', function (data) { submitApply(data); }); form.render(); }); // 显示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'); } } // 格式化文件大小 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]}`; } // 生成更可靠的文件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: 'mp4|ppt|pptx|pdf', mimeTypes: 'video/mp4,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/pdf' }, 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({ id: file.id, fileUrl: response.path, fileSize: response.size, filePreviousName: file.name, fileName: 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.id === idToDelete); if (index !== -1) { const obj = fileArr[index]; delFileArr.push({ fileId: obj.fileId, fileName: obj.fileName, fileUrl:obj.fileUrl }); fileArr.splice(index, 1); } } } // 学习对象 function setStudyObject() { demo1 = xmSelect.render({ el: '#demo1', language: 'zn', layVerify: 'required', layVerType: 'msg', data: [ { name: '值班员', value: '2' }, { name: '地市人员', value: '3' }, ] }) layui.form.render(); } // 提交 function submitApply(data) { if (fileArr.length === 0) { return layer.msg('未上传学习课件', { icon: 5 }); } if(!isAllUpload){ return layer.msg('课件未全部上传完成,请稍后重试', { icon: 5 }); } let url = dataUrl + "proteam/pot/studyTask/addOrUpdateStudyTask"; let params = Object.assign({}, data.field); params.studyObject = demo1.getValue('valueStr'); params.delFiles = JSON.stringify(delFileArr); params.files = JSON.stringify(fileArr); params.publishStatus = publishStatus; console.log(params); let loadingMsg = layer.msg('正在提交保存,请稍等...', { icon: 16, shade: 0.01, time: '0' }); $('.save').addClass("layui-btn-disabled").attr("disabled", true); $('.cancel').addClass("layui-btn-disabled").attr("disabled", true); ajaxRequest2(url, "POST", params, true, function (result) { layer.close(loadingMsg); // 关闭提示层 console.log(result); if (result.code === 200) { top.layer.msg(result.msg, { icon: 1 }) closePage(1); } else { $('.save').removeClass("layui-btn-disabled").attr("disabled", false); $('.cancel').removeClass("layui-btn-disabled").attr("disabled", false); layer.msg(result.msg, { icon: 2 }) } }, function (xhr) { layer.close(loadingMsg); // 关闭提示层 error(xhr) $('.save').removeClass("layui-btn-disabled").attr("disabled", false); $('.cancel').removeClass("layui-btn-disabled").attr("disabled", false); }, null, token); } // 获取学习任务相关配置参数 function getFileParameter() { let url = dataUrl + "proteam/pot/studyTask/getFileParameter"; let params = {}; ajaxRequest2(url, "POST", params, false, function (result) { console.log(result); if (result.code === 200) { if(result.data.fileSize){ fileSingleSizeLimit = parseInt(result.data.fileSize) * 1024 * 1024; } if(result.data.fileNum){ MAX_FILE_COUNT = parseInt(result.data.fileNum); } } }, function (xhr) { layer.close(loadingMsg); // 关闭提示层 error(xhr) }, null, token); } // 保存 function saveData2(type) { publishStatus = type + ''; $('#formSubmit').trigger('click') } // 关闭页面 function closePage(type) { if (isUploading && !allowWindowClose) { return layer.msg('文件正在上传中,请勿关闭页面', { icon: 7 }); } let index = parent.layer.getFrameIndex(window.name); //先得到当前 iframe层的索引 parent.layer.close(index); //再执行关闭 if (type === 1) { parent.query(1); } }