4
0
Fork 0
dcat-admin/resources/assets/dcat/extra/upload.js

442 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import Helper from './Upload/Helper'
import Request from './Upload/Request'
import Input from './Upload/Input'
import Status from './Upload/Status'
import AddFile from './Upload/AddFile'
import AddUploadedFile from './Upload/AddUploadedFile'
/**
* WebUploader 上传组件
*
* @see http://fex.baidu.com/webuploader/
*/
(function (w, $) {
let Dcat = w.Dcat;
class Uploader {
constructor(options) {
this.options = options = $.extend({
wrapper: '.web-uploader', // 图片显示容器选择器
addFileButton: '.add-file-button', // 继续添加按钮选择器
inputSelector: '',
isImage: false,
preview: [], // 数据预览
server: '',
updateServer: '',
autoUpload: false,
sortable: false,
deleteUrl: '',
deleteData: {},
thumbHeight: 160,
elementName: '',
disabled: false, // 禁止任何上传编辑
autoUpdateColumn: false,
removable: false, // 是否允许直接删除服务器图片
downloadable: false, // 是否允许下载文件
dimensions: {
// width: 100, // 图片宽限制
// height: 100, // 图片高限制
// min_width: 100, //
// min_height: 100,
// max_width: 100,
// max_height: 100,
// ratio: 3/2, // 宽高比
},
lang: {
exceed_size: '文件大小超出',
interrupt: '上传暂停',
upload_failed: '上传失败,请重试',
selected_files: '选中:num个文件共:size。',
selected_has_failed: '已成功上传:success个文件:fail个文件上传失败<a class="retry" href="javascript:"";">重新上传</a>失败文件或<a class="ignore" href="javascript:"";">忽略</a>',
selected_success: '共:num个(:size),已上传:success个。',
dot: '',
failed_num: '失败:fail个。',
pause_upload: '暂停上传',
go_on_upload: '继续上传',
start_upload: '开始上传',
upload_success_message: '已成功上传:success个文件',
go_on_add: '继续添加',
Q_TYPE_DENIED: '对不起,不允许上传此类型文件',
Q_EXCEED_NUM_LIMIT: '对不起,已超出文件上传数量限制,最多只能上传:num个文件',
F_EXCEED_SIZE: '对不起,当前选择的文件过大',
Q_EXCEED_SIZE_LIMIT: '对不起,已超出文件大小限制',
F_DUPLICATE: '文件重复',
confirm_delete_file: '您确定要删除这个文件吗?',
},
upload: { // web-uploader配置
formData: {
_id: null, // 唯一id
},
thumb: {
width: 160,
height: 160,
quality: 70,
allowMagnify: true,
crop: true,
preserveHeaders: false,
// 为空的话则保留原有图片格式。
// 否则强制转换成指定的类型。
// IE 8下面 base64 大小不能超过 32K 否则预览失败,而非 jpeg 编码的图片很可
// 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg
type: 'image/jpeg'
},
}
}, options);
let _this = this;
// WebUploader
// @see http://fex.baidu.com/webuploader/
_this.uploader = WebUploader.create(options.upload);
_this.$selector = $(options.selector);
_this.updateColumn = options.upload.formData.upload_column || ('webup' + Dcat.helpers.random());
_this.relation = options.upload.formData._relation; // 一对多关联关系名称
// 帮助函数
let helper = new Helper(this),
// 请求处理
request = new Request(this),
// 状态管理
status = new Status(this),
// 添加文件
addFile = new AddFile(this),
// 添加已上传文件
addUploadedFile = new AddUploadedFile(this),
// 表单
input = new Input(this);
_this.helper = helper;
_this.request = request;
_this.status = status;
_this.addFile = addFile;
_this.addUploadedFile = addUploadedFile;
_this.input = input;
// 翻译
_this.lang = Dcat.Translator(options.lang);
// 所有文件的进度信息key为file id
_this.percentages = {};
// 临时存储上传失败的文件key为file id
_this.faildFiles = {};
// 临时存储添加到form表单的文件
_this.formFiles = {};
// 添加的文件数量
_this.fileCount = 0;
// 添加的文件总大小
_this.fileSize = 0;
if (typeof options.upload.formData._id === "undefined" || ! options.upload.formData._id) {
options.upload.formData._id = _this.updateColumn + Dcat.helpers.random();
}
}
// 初始化
build() {
let _this = this,
uploader = _this.uploader,
options = _this.options,
$wrap = _this.$selector.find(options.wrapper),
// 图片容器
$queue = $('<ul class="filelist"></ul>').appendTo($wrap.find('.queueList')),
// 状态栏,包括进度和控制按钮
$statusBar = $wrap.find('.statusBar'),
// 文件总体选择信息。
$info = $statusBar.find('.info'),
// 上传按钮
$upload = $wrap.find('.upload-btn'),
// 没选择文件之前的内容。
$placeholder = $wrap.find('.placeholder'),
$progress = $statusBar.find('.upload-progress').hide();
// jq选择器
_this.$wrapper = $wrap;
_this.$files = $queue;
_this.$statusBar = $statusBar;
_this.$uploadButton = $upload;
_this.$placeholder = $placeholder;
_this.$progress = $progress;
_this.$infoBox = $info;
if (options.upload.fileNumLimit > 1 && ! options.disabled) {
// 添加“添加文件”的按钮,
uploader.addButton({
id: options.addFileButton,
label: '<i class="feather icon-folder"></i> &nbsp;' + _this.lang.trans('go_on_add')
});
}
// 拖拽时不接受 js, txt 文件。
_this.uploader.on('dndAccept', function (items) {
var denied = false,
len = items.length,
i = 0,
// 修改js类型
unAllowed = 'text/plain;application/javascript ';
for (; i < len; i++) {
// 如果在列表里面
if (~unAllowed.indexOf(items[i].type)) {
denied = true;
break;
}
}
return !denied;
});
// 进度条更新
uploader.onUploadProgress = function (file, percentage) {
_this.percentages[file.id][1] = percentage;
_this.status.updateProgress();
};
// uploader.onBeforeFileQueued = function (file) {};
// 添加文件
uploader.onFileQueued = function (file) {
_this.fileCount++;
_this.fileSize += file.size;
if (_this.fileCount === 1) {
// 隐藏 placeholder
$placeholder.addClass('element-invisible');
$statusBar.show();
}
// 添加文件
_this.addFile.render(file);
_this.status.switch('ready');
// 更新进度条
_this.status.updateProgress();
if (!options.disabled && options.autoUpload) {
// 自动上传
uploader.upload()
}
};
// 删除文件事件监听
uploader.onFileDequeued = function (file) {
_this.fileCount--;
_this.fileSize -= file.size;
if (! _this.fileCount && !Dcat.helpers.len(_this.formFiles)) {
_this.status.switch('pending');
}
_this.removeUploadFile(file);
};
uploader.on('all', function (type, obj, reason) {
switch (type) {
case 'uploadFinished':
_this.status.switch('confirm');
// 保存已上传的文件名到服务器
_this.request.update();
break;
case 'startUpload':
_this.status.switch('uploading');
break;
case 'stopUpload':
_this.status.switch('paused');
break;
case 'uploadAccept':
if (_this._uploadAccept(obj, reason) === false) {
return false;
}
break;
}
});
uploader.onError = function (code) {
switch (code) {
case 'Q_TYPE_DENIED':
Dcat.error(_this.lang.trans('Q_TYPE_DENIED'));
break;
case 'Q_EXCEED_NUM_LIMIT':
Dcat.error(_this.lang.trans('Q_EXCEED_NUM_LIMIT', {num: options.upload.fileNumLimit}));
break;
case 'F_EXCEED_SIZE':
Dcat.error(_this.lang.trans('F_EXCEED_SIZE'));
break;
case 'Q_EXCEED_SIZE_LIMIT':
Dcat.error(_this.lang.trans('Q_EXCEED_SIZE_LIMIT'));
break;
case 'F_DUPLICATE':
Dcat.warning(_this.lang.trans('F_DUPLICATE'));
break;
default:
Dcat.error('Error: ' + code);
}
};
// 上传按钮点击
$upload.on('click', function () {
let state = _this.status.state;
if ($(this).hasClass('disabled')) {
return false;
}
if (state === 'ready') {
uploader.upload();
} else if (state === 'paused') {
uploader.upload();
} else if (state === 'uploading') {
uploader.stop();
}
});
// 重试按钮
$info.on('click', '.retry', function () {
uploader.retry();
});
// 忽略按钮
$info.on('click', '.ignore', function () {
for (let i in _this.faildFiles) {
uploader.removeFile(i, true);
delete _this.faildFiles[i];
}
});
// 初始化
_this.status.switch('init');
}
_uploadAccept(obj, reason) {
let _this = this,
options = _this.options;
// 上传失败返回false
if (! reason || ! reason.status) {
_this.helper.showError(reason);
_this.faildFiles[obj.file.id] = obj.file;
return false;
}
if (reason.data && reason.data.merge) {
// 分片上传
return;
}
// 上传成功保存新文件名和路径到file对象
obj.file.serverId = reason.data.id;
obj.file.serverName = reason.data.name;
obj.file.serverPath = reason.data.path;
obj.file.serverUrl = reason.data.url || null;
_this.addUploadedFile.add(obj.file);
_this.input.add(reason.data.id);
let $li = _this.getFileView(obj.file.id);
if (! _this.isImage()) {
$li.find('.file-action').hide();
$li.find('[data-file-act="delete"]').show();
}
if (options.sortable) {
$li.find('[data-file-act="order"]').removeClass('d-none').show();
}
if (options.downloadable) {
let $download = $li.find('[data-file-act="download"]');
$download.removeClass('d-none').show();
$download.attr('data-id', obj.file.serverUrl);
}
}
// 预览
preview() {
let _this = this,
options = _this.options,
i;
for (i in options.preview) {
let path = options.preview[i].path, ext;
if (path.indexOf('.')) {
ext = path.split('.').pop();
}
let file = {
serverId: options.preview[i].id,
serverUrl: options.preview[i].url,
serverPath: path,
ext: ext,
fake: 1,
};
_this.status.switch('incrOriginalFileNum');
_this.status.switch('decrFileNumLimit');
// 添加文件到预览区域
_this.addUploadedFile.render(file);
_this.addUploadedFile.add(file);
}
}
// 重新渲染已上传文件
reRenderUploadedFiles() {
let _this = this;
_this.$files.html('');
_this.addUploadedFile.reRender();
}
// 重置按钮位置
refreshButton() {
this.uploader.refresh();
}
// 获取文件视图选择器
getFileViewSelector(fileId) {
return this.options.elementName.replace(/[\[\]]*/g, '_') + '-' + fileId;
}
getFileView(fileId) {
return $('#' + this.getFileViewSelector(fileId));
}
// 负责view的销毁
removeUploadFile(file) {
let _this = this,
$li = _this.getFileView(file.id);
delete _this.percentages[file.id];
_this.status.updateProgress();
$li.off().find('.file-panel').off().end().remove();
}
// 上传字段名称
getColumn() {
return this.updateColumn
}
// 判断是否是图片上传
isImage() {
return this.options.isImage
}
}
Dcat.Uploader = function (options) {
return new Uploader(options)
};
})(window, jQuery);