gs-jjsp-web/bns/js/studyExam/studyTaskEditForm.js

556 lines
19 KiB
JavaScript

let form, layer, demo1, dataObj = {};
let fileArr = []; // 保存的文件路径
let delFileArr = []; // 删除的文件路径
let publishStatus = '0'; // 发布状态默认0-待发布
// 全局变量记录上传状态
let isUploading = false;
let allowWindowClose = false;
// 配置常量
const MAX_FILE_COUNT2 = 10;
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();
dataObj = JSON.parse(params);
layui.use(['form', 'layer', 'upload', 'element'], function () {
layer = layui.layer;
form = layui.form;
upload = layui.upload;
element = layui.element;
setStudyObject();
if (dataObj.id) {
form.val('formInfo', dataObj);
let studyObject = dataObj.studyObject.split(',');
demo1.setValue(studyObject)
getStudyTask(dataObj.id);
}
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);
}
// 生成更可靠的文件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_COUNT2,
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 = $(`
<tr id="file-${file.id}" data-uid="${file.uid}">
<td class="file-name">${file.name}</td>
<td class="file-size">${formatFileSize(file.size)}</td>
<td>
<div class="progress-container">
<div class="progress-bar">0%</div>
</div>
</td>
<td>
<span class="file-status status-waiting">
<span class="status-icon"></span>
<span class="status-text">等待上传</span>
</span>
</td>
<td>
<a href="javascript:;" class="file-action" data-id="${file.id}">删除</a>
</td>
</tr>
`);
$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();
$('#startUpload').prop('disabled', true);
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({
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 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]}`;
}
// 更新文件计数器
function updateFileCounter() {
const $counter = $('#fileCounter');
$counter.text(`已选择 ${currentFileCount}/${MAX_FILE_COUNT} 个文件`);
if (currentFileCount >= MAX_FILE_COUNT) {
$counter.addClass('warning');
} else {
$counter.removeClass('warning');
}
}
// 删除文件
function delFile(that, obj) {
$(that).parents('tr').remove();
delFileArr.push({
fileUrl:obj.fileUrl,
fileUrlNew:obj.fileUrlNew,
id:obj.id
})
MAX_FILE_COUNT = MAX_FILE_COUNT + 1;
updateFileCounter();
let length = $('#fileList2 tr').length;
if (length === 0) {
$('#fileList2').append('<tr><td colspan="3" class="no-files">暂无数据</td></tr>');
}
}
// 提交
function submitApply(data) {
if (fileArr.length === 0 && $('#fileList2 .files').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;
params.id = dataObj.id;
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); // 关闭提示层
$('.save').removeClass("layui-btn-disabled").attr("disabled", false);
$('.cancel').removeClass("layui-btn-disabled").attr("disabled", false);
error(xhr)
}, null, token);
}
// 保存
function saveData2(type) {
publishStatus = type + '';
$('#formSubmit').trigger('click')
}
// 获取学习任务详情
function getStudyTask() {
let loadingMsg = layer.msg('数据加载中,请稍等...', { icon: 16, shade: 0.01, time: '0' });
let url = dataUrl + "proteam/pot/studyTask/getStudyTaskById";
let params = { id: dataObj.id };
ajaxRequest2(url, "POST", params, true, function (result) {
console.log(result);
layer.close(loadingMsg); // 关闭提示层
if (result.code === 200) {
initFileData(result.data.studyFileVoList);
} else {
layer.msg(result.msg, { icon: 2 })
}
}, function (xhr) {
layer.close(loadingMsg); // 关闭提示层
error(xhr)
}, null, token);
// 初始化已上传的文件
function initFileData(data) {
let html = '';
$.each(data, function (index, item) {
html += "<tr class='files'>" +
"<td>" + item.filePreviousName + "</td>" +
"<td>" + formatFileSize(item.fileSize || 0) + "</td>" +
"<td>" +
"<a href='javascript:;' style='margin: 0 5px;' onclick='viewFile(this," + JSON.stringify(item) + ")'>预览</a>" +
"<a href='javascript:;' style='margin: 0 5px;color:#e74c3c' onclick='delFile(this," + JSON.stringify(item) + ")'>删除</a>"
"</td>" +
"</tr>"
})
$('#fileList2').append(html);
MAX_FILE_COUNT = 10 - data.length;
$('#fileCounter').html(`已选择 0/${MAX_FILE_COUNT}个文件`);
}
}
// 获取学习任务相关配置参数
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 viewFile(that,item) {
var fileExt = (item.fileUrlNew || item.fileUrl).split('.').pop().toLowerCase();
if (fileExt === 'pdf') { // pdf 预览
sessionStorage.setItem("fileUrlNew", item.fileUrlNew || item.fileUrl);
let href = '../../pdfjs/web/viewer2.html'
layui.layer.open({
title: 'PDF预览',
type: 2,
area: ['95%', '95%'], // 弹出框的宽高
fixed: false, // 是否固定
maxmin: true, // 是否允许最大化
shade: 0, // 隐藏弹框的遮罩层
content: href, // pdf的地址
move:false
})
}
else if (fileExt === 'mp4') {
let videoUrl = photoUrl + item.fileUrl + '?token=' + token;
layer.open({
type: 1,
title: '视频预览 - ' + item.filePreviousName,
content: '<video controls autoplay style="width: 98%;height: 96%;object-fit: contain;margin: 1% 1% 0 1%;"><source src="' + videoUrl + '" type="video/mp4"></video>',
area: ['95%', '95%'], // 弹出框的宽高
move:false
});
}
}
// 关闭页面
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);
}
}