123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- 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> ' + _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);
|