升级.net8
This commit is contained in:
@ -3,16 +3,22 @@
|
||||
* 上传组件
|
||||
*/
|
||||
|
||||
layui.define(['lay','layer'], function(exports){
|
||||
layui.define(['lay', 'layer'], function(exports){
|
||||
"use strict";
|
||||
|
||||
var $ = layui.$;
|
||||
var lay = layui.lay;
|
||||
var layer = layui.layer;
|
||||
var device = layui.device();
|
||||
|
||||
// 模块名
|
||||
var MOD_NAME = 'upload';
|
||||
var MOD_INDEX = 'layui_'+ MOD_NAME +'_index'; // 模块索引名
|
||||
|
||||
// 外部接口
|
||||
var upload = {
|
||||
config: {}, // 全局配置项
|
||||
index: layui[MOD_NAME] ? (layui[MOD_NAME].index + 10000) : 0, // 索引
|
||||
// 设置全局项
|
||||
set: function(options){
|
||||
var that = this;
|
||||
@ -26,8 +32,13 @@ layui.define(['lay','layer'], function(exports){
|
||||
};
|
||||
|
||||
// 操作当前实例
|
||||
var thisUpload = function(){
|
||||
var thisModule = function(){
|
||||
var that = this;
|
||||
var options = that.config;
|
||||
var id = options.id;
|
||||
|
||||
thisModule.that[id] = that; // 记录当前实例对象
|
||||
|
||||
return {
|
||||
upload: function(files){
|
||||
that.upload.call(that, files);
|
||||
@ -40,7 +51,6 @@ layui.define(['lay','layer'], function(exports){
|
||||
};
|
||||
|
||||
// 字符常量
|
||||
var MOD_NAME = 'upload';
|
||||
var ELEM = 'layui-upload';
|
||||
var THIS = 'layui-this';
|
||||
var SHOW = 'layui-show';
|
||||
@ -52,10 +62,12 @@ layui.define(['lay','layer'], function(exports){
|
||||
var ELEM_IFRAME = 'layui-upload-iframe';
|
||||
var ELEM_CHOOSE = 'layui-upload-choose';
|
||||
var ELEM_DRAG = 'layui-upload-drag';
|
||||
var UPLOADING = 'UPLOADING';
|
||||
|
||||
// 构造器
|
||||
var Class = function(options){
|
||||
var that = this;
|
||||
that.index = ++upload.index;
|
||||
that.config = $.extend({}, that.config, upload.config, options);
|
||||
that.render();
|
||||
};
|
||||
@ -85,15 +97,51 @@ layui.define(['lay','layer'], function(exports){
|
||||
"limit-size": null // 限制 size 属性的提示 --- function
|
||||
}
|
||||
};
|
||||
|
||||
// 重载实例
|
||||
Class.prototype.reload = function(options){
|
||||
var that = this;
|
||||
that.config = $.extend({}, that.config, options);
|
||||
that.render(true);
|
||||
};
|
||||
|
||||
// 初始渲染
|
||||
Class.prototype.render = function(options){
|
||||
Class.prototype.render = function(rerender){
|
||||
var that = this;
|
||||
var options = that.config;
|
||||
|
||||
// 若 elem 非唯一
|
||||
var elem = $(options.elem);
|
||||
if (elem.length > 1) {
|
||||
layui.each(elem, function() {
|
||||
upload.render($.extend({}, options, {
|
||||
elem: this
|
||||
}));
|
||||
});
|
||||
return that;
|
||||
}
|
||||
|
||||
// 合并 lay-options 属性上的配置信息
|
||||
$.extend(options, lay.options(elem[0], {
|
||||
attr: elem.attr('lay-data') ? 'lay-data' : null // 兼容旧版的 lay-data 属性
|
||||
}));
|
||||
|
||||
// 若重复执行 render,则视为 reload 处理
|
||||
if (!rerender && elem[0] && elem.data(MOD_INDEX)) {
|
||||
var newThat = thisModule.getThis(elem.data(MOD_INDEX));
|
||||
if(!newThat) return;
|
||||
|
||||
return newThat.reload(options);
|
||||
}
|
||||
|
||||
options.elem = $(options.elem);
|
||||
options.bindAction = $(options.bindAction);
|
||||
|
||||
// 初始化 id 属性 - 优先取 options > 元素 id > 自增索引
|
||||
options.id = 'id' in options ? options.id : (
|
||||
elem.attr('id') || that.index
|
||||
);
|
||||
|
||||
that.file();
|
||||
that.events();
|
||||
};
|
||||
@ -218,30 +266,56 @@ layui.define(['lay','layer'], function(exports){
|
||||
var request = function(sets){
|
||||
var formData = new FormData();
|
||||
|
||||
// 恢复文件状态
|
||||
var resetFileState = function(file) {
|
||||
if (sets.unified) {
|
||||
layui.each(items, function(index, file){
|
||||
delete file[UPLOADING];
|
||||
});
|
||||
} else {
|
||||
delete file[UPLOADING];
|
||||
}
|
||||
};
|
||||
|
||||
// 追加额外的参数
|
||||
layui.each(options.data, function(key, value){
|
||||
value = typeof value === 'function' ? value() : value;
|
||||
value = typeof value === 'function'
|
||||
? sets.unified ? value() : value(sets.index, sets.file)
|
||||
: value;
|
||||
formData.append(key, value);
|
||||
});
|
||||
|
||||
// 添加 file 到表单域
|
||||
sets.unified ? layui.each(items, function(index, file){
|
||||
formData.append(options.field, file);
|
||||
}) : formData.append(options.field, sets.file);
|
||||
/*
|
||||
* 添加 file 到表单域
|
||||
*/
|
||||
|
||||
// 是否统一上传
|
||||
if (sets.unified) {
|
||||
layui.each(items, function(index, file){
|
||||
if (file[UPLOADING]) return;
|
||||
file[UPLOADING] = true; // 上传中的标记
|
||||
formData.append(options.field, file);
|
||||
});
|
||||
} else { // 逐一上传
|
||||
if (sets.file[UPLOADING]) return;
|
||||
formData.append(options.field, sets.file);
|
||||
sets.file[UPLOADING] = true; // 上传中的标记
|
||||
}
|
||||
|
||||
// ajax 参数
|
||||
var opts = {
|
||||
url: options.url,
|
||||
type: 'post', // 统一采用 post 上传
|
||||
data: formData,
|
||||
dataType: options.dataType || 'json',
|
||||
contentType: false,
|
||||
processData: false,
|
||||
dataType: 'json',
|
||||
headers: options.headers || {},
|
||||
success: function(res){ // 成功回调
|
||||
options.unified ? (successful += that.fileLength) : successful++;
|
||||
done(sets.index, res);
|
||||
allDone();
|
||||
allDone(sets.index);
|
||||
resetFileState(sets.file);
|
||||
},
|
||||
error: function(e){ // 异常回调
|
||||
options.unified ? (failed += that.fileLength) : failed++;
|
||||
@ -249,10 +323,12 @@ layui.define(['lay','layer'], function(exports){
|
||||
'Upload failed, please try again.',
|
||||
'status: '+ (e.status || '') +' - '+ (e.statusText || 'error')
|
||||
].join('<br>'));
|
||||
error(sets.index);
|
||||
allDone();
|
||||
error(sets.index, e.responseText);
|
||||
allDone(sets.index);
|
||||
resetFileState(sets.file);
|
||||
}
|
||||
};
|
||||
|
||||
// 进度条
|
||||
if(typeof options.progress === 'function'){
|
||||
opts.xhr = function(){
|
||||
@ -310,21 +386,41 @@ layui.define(['lay','layer'], function(exports){
|
||||
}
|
||||
}, 30);
|
||||
};
|
||||
|
||||
|
||||
// 强制返回的数据格式
|
||||
var forceConvert = function(src) {
|
||||
if(options.force === 'json'){
|
||||
if(typeof src !== 'object'){
|
||||
try {
|
||||
return {
|
||||
status: "CONVERTED",
|
||||
data: JSON.parse(src)
|
||||
};
|
||||
} catch(e){
|
||||
that.msg(text['data-format-error']);
|
||||
return {
|
||||
status: "FORMAT_ERROR",
|
||||
data: {}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return { status: "DO_NOTHING", data: {} }
|
||||
}
|
||||
|
||||
// 统一回调
|
||||
var done = function(index, res){
|
||||
that.elemFile.next('.'+ ELEM_CHOOSE).remove();
|
||||
elemFile.value = '';
|
||||
|
||||
if(options.force === 'json'){
|
||||
if(typeof res !== 'object'){
|
||||
try {
|
||||
res = JSON.parse(res);
|
||||
} catch(e){
|
||||
res = {};
|
||||
return that.msg(text['data-format-error']);
|
||||
}
|
||||
}
|
||||
var convert = forceConvert(res);
|
||||
|
||||
switch(convert.status) {
|
||||
case "CONVERTED":
|
||||
res = convert.data;
|
||||
break;
|
||||
case "FORMAT_ERROR":
|
||||
return;
|
||||
}
|
||||
|
||||
typeof options.done === 'function' && options.done(res, index || 0, function(files){
|
||||
@ -333,13 +429,24 @@ layui.define(['lay','layer'], function(exports){
|
||||
};
|
||||
|
||||
// 统一网络异常回调
|
||||
var error = function(index){
|
||||
var error = function(index, res){
|
||||
if(options.auto){
|
||||
elemFile.value = '';
|
||||
}
|
||||
|
||||
var convert = forceConvert(res);
|
||||
|
||||
switch(convert.status) {
|
||||
case "CONVERTED":
|
||||
res = convert.data;
|
||||
break;
|
||||
case "FORMAT_ERROR":
|
||||
return;
|
||||
}
|
||||
|
||||
typeof options.error === 'function' && options.error(index || 0, function(files){
|
||||
that.upload(files);
|
||||
});
|
||||
}, res);
|
||||
};
|
||||
|
||||
var check;
|
||||
@ -377,20 +484,42 @@ layui.define(['lay','layer'], function(exports){
|
||||
var newFile = new File([file], filename);
|
||||
that.files = that.files || {};
|
||||
that.files[index] = newFile;
|
||||
},
|
||||
// 获取本次选取的文件
|
||||
getChooseFiles: function(){
|
||||
return that.chooseFiles;
|
||||
}
|
||||
};
|
||||
|
||||
// 提交上传
|
||||
var send = function(){
|
||||
// 上传前的回调 - 如果回调函数明确返回 false,则停止上传
|
||||
if(options.before && (options.before(args) === false)) return;
|
||||
|
||||
// IE 兼容处理
|
||||
if(device.ie){
|
||||
return device.ie > 9 ? ajaxSend() : iframeSend();
|
||||
var send = function(){
|
||||
var ready = function(){
|
||||
// IE 兼容处理
|
||||
if(device.ie){
|
||||
return device.ie > 9 ? ajaxSend() : iframeSend();
|
||||
}
|
||||
ajaxSend();
|
||||
}
|
||||
// 上传前的回调 - 如果回调函数明确返回 false 或 Promise.reject,则停止上传
|
||||
if(typeof options.before === 'function'){
|
||||
upload.util.promiseLikeResolve(options.before(args))
|
||||
.then(function(result){
|
||||
if(result !== false){
|
||||
ready();
|
||||
} else {
|
||||
if(options.auto){
|
||||
elemFile.value = '';
|
||||
}
|
||||
}
|
||||
}, function(error){
|
||||
if(options.auto){
|
||||
elemFile.value = '';
|
||||
}
|
||||
error !== undefined && layui.hint().error(error);
|
||||
})
|
||||
}else{
|
||||
ready();
|
||||
}
|
||||
|
||||
ajaxSend();
|
||||
};
|
||||
|
||||
// 文件类型名称
|
||||
@ -406,7 +535,8 @@ layui.define(['lay','layer'], function(exports){
|
||||
? ((elemFile.value.match(/[^\/\\]+\..+/g)||[]) || '')
|
||||
: value;
|
||||
|
||||
if(value.length === 0) return;
|
||||
// 若文件域值为空
|
||||
if (value.length === 0) return;
|
||||
|
||||
// 根据文件类型校验
|
||||
switch(options.accept){
|
||||
@ -433,7 +563,7 @@ layui.define(['lay','layer'], function(exports){
|
||||
break;
|
||||
default: // 图片文件
|
||||
layui.each(value, function(i, item){
|
||||
if(!RegExp('.\\.('+ (exts || 'jpg|png|gif|bmp|jpeg|svg') +')$', 'i').test(escape(item))){
|
||||
if(!RegExp('.\\.('+ (exts || 'jpg|png|gif|bmp|jpeg|svg|webp') +')$', 'i').test(escape(item))){
|
||||
return check = true;
|
||||
}
|
||||
});
|
||||
@ -493,24 +623,6 @@ layui.define(['lay','layer'], function(exports){
|
||||
send();
|
||||
};
|
||||
|
||||
//重置方法
|
||||
Class.prototype.reload = function(options){
|
||||
options = options || {};
|
||||
delete options.elem;
|
||||
delete options.bindAction;
|
||||
|
||||
var that = this;
|
||||
var options = that.config = $.extend({}, that.config, upload.config, options);
|
||||
var next = options.elem.next();
|
||||
|
||||
//更新文件域相关属性
|
||||
next.attr({
|
||||
name: options.name,
|
||||
accept: options.acceptMime,
|
||||
multiple: options.multiple
|
||||
});
|
||||
};
|
||||
|
||||
//事件处理
|
||||
Class.prototype.events = function(){
|
||||
var that = this;
|
||||
@ -541,23 +653,70 @@ layui.define(['lay','layer'], function(exports){
|
||||
elemFile.after('<span class="layui-inline '+ ELEM_CHOOSE +'">'+ value +'</span>');
|
||||
};
|
||||
|
||||
// 合并 lay-options/lay-data 属性配置项
|
||||
var extendAttrs = function(){
|
||||
var othis = $(this);
|
||||
var data = othis.attr('lay-data') || othis.attr('lay-options'); // 优先兼容旧版本
|
||||
/**
|
||||
* 判断文件是否加入排队
|
||||
* @param {File} file
|
||||
* @return {boolean}
|
||||
*/
|
||||
var checkFile = function (file) {
|
||||
var result = true;
|
||||
layui.each(that.files, function (index, item) {
|
||||
result = !(item.name === file.name);
|
||||
if(!result) return true;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
if(data){
|
||||
that.config = $.extend({}, options, lay.options(this, {
|
||||
attr: othis.attr('lay-data') ? 'lay-data' : null
|
||||
}));
|
||||
/**
|
||||
* 扩展文件信息
|
||||
* @template {File | FileList} T
|
||||
* @param {T} obj
|
||||
* @return {T}
|
||||
*/
|
||||
var extendInfo = function (obj) {
|
||||
|
||||
var extInfo = function (file) {
|
||||
//文件扩展名
|
||||
file.ext = file.name.substr(file.name.lastIndexOf('.') + 1).toLowerCase();
|
||||
// 文件大小
|
||||
file.sizes = upload.util.parseSize(file.size);
|
||||
// 可以继续扩展
|
||||
}
|
||||
};
|
||||
|
||||
//FileList对象
|
||||
if (obj instanceof FileList) {
|
||||
layui.each(obj, function (index, item) {
|
||||
extInfo(item);
|
||||
});
|
||||
} else {
|
||||
extInfo(obj);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查获取文件
|
||||
* @param {FileList} files
|
||||
* @return {Array<File>|FileList}
|
||||
*/
|
||||
var getFiles = function (files) {
|
||||
files = files || [];
|
||||
if (!files.length) return [];
|
||||
if (!that.files) return extendInfo(files);
|
||||
var result = [];
|
||||
layui.each(files, function (index, item) {
|
||||
if (checkFile(item)) {
|
||||
result.push(extendInfo(item));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
// 点击上传容器
|
||||
options.elem.off('upload.start').on('upload.start', function(){
|
||||
var othis = $(this);
|
||||
|
||||
extendAttrs.call(this);
|
||||
that.config.item = othis;
|
||||
that.elemFile[0].click();
|
||||
});
|
||||
@ -574,10 +733,9 @@ layui.define(['lay','layer'], function(exports){
|
||||
})
|
||||
.off('upload.drop').on('upload.drop', function(e, param){
|
||||
var othis = $(this);
|
||||
var files = param.originalEvent.dataTransfer.files || [];
|
||||
var files = getFiles(param.originalEvent.dataTransfer.files);
|
||||
|
||||
othis.removeAttr('lay-over');
|
||||
extendAttrs.call(this);
|
||||
setChooseFile(files);
|
||||
|
||||
options.auto ? that.upload() : setChooseText(files); // 是否自动触发上传
|
||||
@ -585,11 +743,13 @@ layui.define(['lay','layer'], function(exports){
|
||||
}
|
||||
|
||||
// 文件选择
|
||||
that.elemFile.off('upload.change').on('upload.change', function(){
|
||||
var files = this.files || [];
|
||||
that.elemFile.on('change', function(){
|
||||
var files = getFiles(this.files);
|
||||
|
||||
if(files.length === 0) return;
|
||||
|
||||
extendAttrs.call(this);
|
||||
setChooseFile(files);
|
||||
|
||||
options.auto ? that.upload() : setChooseText(files); // 是否自动触发上传
|
||||
});
|
||||
|
||||
@ -597,19 +757,19 @@ layui.define(['lay','layer'], function(exports){
|
||||
options.bindAction.off('upload.action').on('upload.action', function(){
|
||||
that.upload();
|
||||
});
|
||||
|
||||
|
||||
|
||||
// 防止事件重复绑定
|
||||
if(options.elem.data('haveEvents')) return;
|
||||
|
||||
that.elemFile.on('change', function(){
|
||||
$(this).trigger('upload.change');
|
||||
});
|
||||
|
||||
if(options.elem.data(MOD_INDEX)) return;
|
||||
|
||||
|
||||
// 目标元素 click 事件
|
||||
options.elem.on('click', function(){
|
||||
if(that.isFile()) return;
|
||||
$(this).trigger('upload.start');
|
||||
});
|
||||
|
||||
// 目标元素 drop 事件
|
||||
if(options.drag){
|
||||
options.elem.on('dragover', function(e){
|
||||
e.preventDefault();
|
||||
@ -622,17 +782,67 @@ layui.define(['lay','layer'], function(exports){
|
||||
});
|
||||
}
|
||||
|
||||
// 手动上传时触发上传的元素 click 事件
|
||||
options.bindAction.on('click', function(){
|
||||
$(this).trigger('upload.action');
|
||||
});
|
||||
|
||||
options.elem.data('haveEvents', true);
|
||||
// 绑定元素索引
|
||||
options.elem.data(MOD_INDEX, options.id);
|
||||
};
|
||||
|
||||
/**
|
||||
* 上传组件辅助方法
|
||||
*/
|
||||
upload.util = {
|
||||
/**
|
||||
* 文件大小处理
|
||||
* @param {number | string} size -文件大小
|
||||
* @param {number} [precision] - 数值精度
|
||||
* @return {string}
|
||||
*/
|
||||
parseSize: function (size, precision) {
|
||||
precision = precision || 2;
|
||||
if (null == size || !size) {
|
||||
return '0';
|
||||
}
|
||||
var unitArr = ["Bytes", "Kb", "Mb", "Gb", "Tb", "Pb", "Eb", "Zb", "Yb"];
|
||||
var index;
|
||||
var formatSize = typeof size === 'string' ? parseFloat(size) : size;
|
||||
index = Math.floor(Math.log(formatSize) / Math.log(1024));
|
||||
size = formatSize / Math.pow(1024, index);
|
||||
size = size % 1 === 0 ? size : parseFloat(size.toFixed(precision));//保留的小数位数
|
||||
return size + unitArr[index];
|
||||
},
|
||||
/**
|
||||
* 将给定的值转换为一个 JQueryDeferred 对象
|
||||
*/
|
||||
promiseLikeResolve:function(value){
|
||||
var deferred = $.Deferred();
|
||||
|
||||
if(value && typeof value.then === 'function'){
|
||||
value.then(deferred.resolve, deferred.reject);
|
||||
}else{
|
||||
deferred.resolve(value);
|
||||
}
|
||||
return deferred.promise();
|
||||
}
|
||||
}
|
||||
|
||||
// 记录所有实例
|
||||
thisModule.that = {}; // 记录所有实例对象
|
||||
|
||||
// 获取当前实例对象
|
||||
thisModule.getThis = function(id){
|
||||
var that = thisModule.that[id];
|
||||
if(!that) hint.error(id ? (MOD_NAME +' instance with ID \''+ id +'\' not found') : 'ID argument required');
|
||||
return that;
|
||||
};
|
||||
|
||||
// 核心入口
|
||||
upload.render = function(options){
|
||||
var inst = new Class(options);
|
||||
return thisUpload.call(inst);
|
||||
return thisModule.call(inst);
|
||||
};
|
||||
|
||||
exports(MOD_NAME, upload);
|
||||
|
Reference in New Issue
Block a user