|
@@ -0,0 +1,279 @@
|
|
|
|
+'use strict';
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ *
|
|
|
|
+ *
|
|
|
|
+ * @author Mai
|
|
|
|
+ * @date
|
|
|
|
+ * @version
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+(function($){
|
|
|
|
+ $.ledger_att = function (setting) {
|
|
|
|
+ if (!setting.selector) return;
|
|
|
|
+ const obj = $(setting.selector);
|
|
|
|
+ const pageLength = 20;
|
|
|
|
+ let curNode = null, curPage = 0;
|
|
|
|
+ obj.html(
|
|
|
|
+ '<div class="sjs-bar">\n' +
|
|
|
|
+ ' <ul class="nav nav-tabs">\n' +
|
|
|
|
+ ' <li class="nav-item"><a class="nav-link active" data-toggle="tab" href="#att-cur" role="tab" att-type="cur" id="att-cur-button">当前节点</a></li>\n' +
|
|
|
|
+ ' <li class="nav-item"><a class="nav-link" data-toggle="tab" href="#att-all" role="tab" att-type="all">所有附件</a></li>\n' +
|
|
|
|
+ ' <li class="nav-item ml-auto pt-1">\n' +
|
|
|
|
+ ' <a href="javascript:void(0);" id="batch-download" class="btn btn-sm btn-primary" type="curr">批量下载</a>\n' +
|
|
|
|
+ ' <span id="showPage" style="display: none"><a href="javascript:void(0);" class="page-select ml-3" content="pre"><i class="fa fa-chevron-left"></i></a> <span id="att-cur-page">1</span>/<span id="att-total-page">10</span> <a href="javascript:void(0);" class="page-select mr-3" content="next"><i class="fa fa-chevron-right"></i></a></span>\n' +
|
|
|
|
+ (setting.readOnly ? '' : ' <a href="#upload" data-toggle="modal" data-target="#upload" class="btn btn-sm btn-outline-primary ml-3">上传</a>\n') +
|
|
|
|
+ ' </li>\n' +
|
|
|
|
+ ' </ul>\n' +
|
|
|
|
+ '</div>\n' +
|
|
|
|
+ '<div class="sjs-sh tab-content">\n' +
|
|
|
|
+ ' <div class="tab-pane active" id="att-cur" style="height: 100%">\n' +
|
|
|
|
+ ' <div style="overflow:auto; overflow-x:hidden; height: 100%">\n' +
|
|
|
|
+ ' <div class="mt-1 mb-1" id="att-cur-hint"></div>\n' +
|
|
|
|
+ ' <table class="table table-sm table-bordered table-hover" style="word-break:break-all; table-layout: fixed">\n' +
|
|
|
|
+ ' <thead><tr><th width="25"><input type="checkbox" class="check-all-file"><th>文件名</th><th width="80">上传</th><th width="80">操作</th></tr></thead>\n' +
|
|
|
|
+ ' <tbody id="cur-att-list" class="list-table"></tbody>\n' +
|
|
|
|
+ ' </table>\n' +
|
|
|
|
+ ' </div>\n' +
|
|
|
|
+ ' </div>\n' +
|
|
|
|
+ ' <div class="tab-pane" id="att-all" style="height: 100%">\n' +
|
|
|
|
+ ' <div style="overflow:auto; overflow-x:hidden; height: 100%">\n' +
|
|
|
|
+ ' <table class="table table-sm table-bordered table-hover" style="word-break:break-all; table-layout: fixed">\n' +
|
|
|
|
+ ' <thead><tr><th width="25"><input type="checkbox" class="check-all-file"></th><th>文件名</th><th width="80">上传</th><th width="80">操作</th></tr></thead>\n' +
|
|
|
|
+ ' <tbody id="all-att-list" class="list-table"></tbody>\n' +
|
|
|
|
+ ' </table>\n' +
|
|
|
|
+ ' </div>\n' +
|
|
|
|
+ ' </div>\n' +
|
|
|
|
+ '</div>'
|
|
|
|
+ );
|
|
|
|
+ autoFlashHeight();
|
|
|
|
+ $('#att-cur-button')[0].click();
|
|
|
|
+
|
|
|
|
+ let allAtts = [], nodeIndexes = {};
|
|
|
|
+
|
|
|
|
+ const getAttHtml = function(att, tipNode = false) {
|
|
|
|
+ const html = [];
|
|
|
|
+ html.push('<tr>');
|
|
|
|
+ html.push(`<td width="25"><input type="checkbox" class="check-file" file-id=${att.id}></td>`);
|
|
|
|
+ let nodeInfo = '';
|
|
|
|
+ if (tipNode && att.node) nodeInfo = `${att.node.code || att.node.b_code || ''}/${att.node.name || ''}`;
|
|
|
|
+ const tipHtml = nodeInfo ? `${nodeInfo}\n${att.in_time}` : att.in_time;// nodeInfo ? `${nodeInfo}<br/>${att.in_time}` : att.in_time;
|
|
|
|
+ const tipType = 'title='; //'data-toggle="tooltip" data-html="true" data-placement="left" data-original-title=';
|
|
|
|
+ html.push(`<td><div class="d-flex"><a href="javascript:void(0)" ${tipType}"${tipHtml}" class="pl-0 col-11" file-id=${att.id}>${att.filename}${att.fileext}</a></div></td>`);
|
|
|
|
+ html.push(`<td>${att.username}</td>`);
|
|
|
|
+ const canDel = setting.readOnly ? false : att.uid === userID && (!setting.checked || att.extra_upload);
|
|
|
|
+ html.push('<td width="80">',
|
|
|
|
+ `<a class="ml-1" href="javascript:void(0)" ${tipType}"定位" name="att-locate" file-id="${att.id}"><i class="fa fa-crosshairs"></i></a>`,
|
|
|
|
+ att.viewpath ? `<a class="ml-1" href="${att.viewpath}" ${tipType}"预览" target="_blank"><i class="fa fa-eye"></i></a>` : '',
|
|
|
|
+ `<a class="ml-1" href="javascript:void(0)" ${tipType}"下载" onclick="AliOss.downloadFile('${att.filepath}', '${att.filename}${att.fileext}')"><i class="fa fa-download"></i></a>`,
|
|
|
|
+ canDel ? `<a class="ml-1 text-danger" href="javascript:void(0)" name="att-delete" file-id="${att.id}"><i class="fa fa-close" ${tipType}"删除"></i></a>` : '',
|
|
|
|
+ '</td>');
|
|
|
|
+ html.push('</tr>');
|
|
|
|
+ return html.join('');
|
|
|
|
+ };
|
|
|
|
+ const refreshCurAttHtml = function () {
|
|
|
|
+ const html = [];
|
|
|
|
+ const atts = (nodeIndexes[curNode[setting.key]]) || [];
|
|
|
|
+ for (const att of atts) {
|
|
|
|
+ html.push(getAttHtml(att));
|
|
|
|
+ }
|
|
|
|
+ $('#cur-att-list').html(html.join());
|
|
|
|
+ $('[data-toggle="tooltip"]').tooltip();
|
|
|
|
+ };
|
|
|
|
+ const refreshAllAttHtml = function () {
|
|
|
|
+ let curPage = parseInt($('#att-cur-page').text());
|
|
|
|
+ if (allAtts.length === 0 && curPage !== 0) curPage = 0;
|
|
|
|
+ if (allAtts.length > 0 && curPage === 0) curPage = 1;
|
|
|
|
+ $('#att-cur-page').text(curPage);
|
|
|
|
+ const pageNum = Math.ceil(allAtts.length/pageLength);
|
|
|
|
+ $('#att-total-page').text(pageNum);
|
|
|
|
+ const currPageAttData = allAtts.slice((curPage-1)*pageLength, curPage*pageLength);
|
|
|
|
+ const html = [];
|
|
|
|
+ for(const att of currPageAttData) {
|
|
|
|
+ html.push(getAttHtml(att, true));
|
|
|
|
+ }
|
|
|
|
+ $('#all-att-list').html(html.join());
|
|
|
|
+ $('[data-toggle="tooltip"]').tooltip();
|
|
|
|
+ };
|
|
|
|
+ const getAllAttHtml = function (page = 1) {
|
|
|
|
+ curPage = allAtts.length ? page : 0;
|
|
|
|
+ $('#att-cur-page').text(curPage);
|
|
|
|
+ refreshAllAttHtml();
|
|
|
|
+ };
|
|
|
|
+ const getCurAttHtml = function (node) {
|
|
|
|
+ curNode = node;
|
|
|
|
+ $('#att-cur-hint').text(`${curNode.code || curNode.b_code || ''}/${curNode.name || ''}`);
|
|
|
|
+ refreshCurAttHtml();
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ // 选中行
|
|
|
|
+ $('body').on('click', '#all-att-list tr', function() {
|
|
|
|
+ $('#all-att-list tr').removeClass('bg-light');
|
|
|
|
+ $(this).addClass('bg-light');
|
|
|
|
+ });
|
|
|
|
+ $('body').on('click', '#cur-att-list tr', function() {
|
|
|
|
+ $('#cur-att-list tr').removeClass('bg-light');
|
|
|
|
+ $(this).addClass('bg-light');
|
|
|
|
+ });
|
|
|
|
+ // 切换 当前节点/所有附件
|
|
|
|
+ $('#fujian .nav-link').on('click', function () {
|
|
|
|
+ const tabPanel = $(this).attr('att-type');
|
|
|
|
+ if (tabPanel !== 'all') {
|
|
|
|
+ $('#showPage').hide();
|
|
|
|
+ $('#batch-download').prop('type', 'curr');
|
|
|
|
+ } else {
|
|
|
|
+ $('#showPage').show();
|
|
|
|
+ $('#batch-download').prop('type', 'all')
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // 切换页数
|
|
|
|
+ $('.page-select').on('click', function () {
|
|
|
|
+ const totalPageNum = parseInt($('#att-total-page').text());
|
|
|
|
+ const lastPageNum = parseInt($('#att-cur-page').text());
|
|
|
|
+ const status = $(this).attr('content');
|
|
|
|
+ if (status === 'pre' && lastPageNum > 1) {
|
|
|
|
+ getAllAttHtml(lastPageNum-1);
|
|
|
|
+ $('#showAttachment').hide();
|
|
|
|
+ $('#att-all .check-all-file').prop('checked', false)
|
|
|
|
+ } else if (status === 'next' && lastPageNum < totalPageNum) {
|
|
|
|
+ getAllAttHtml(lastPageNum+1);
|
|
|
|
+ $('#showAttachment').hide();
|
|
|
|
+ $('#att-all .check-all-file').prop('checked', false)
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // 批量下载
|
|
|
|
+ $('#batch-download').click(function() {
|
|
|
|
+ const self = this;
|
|
|
|
+ const files = [];
|
|
|
|
+ const type = $(this).prop('type');
|
|
|
|
+ let node = '';
|
|
|
|
+ if (type === 'curr') {
|
|
|
|
+ node = '#cur-att-list .check-file:checked'
|
|
|
|
+ } else {
|
|
|
|
+ node = '#all-att-list .check-file:checked'
|
|
|
|
+ }
|
|
|
|
+ $(node).each(function() {
|
|
|
|
+ const fid = $(this).attr('file-id');
|
|
|
|
+ const att = allAtts.find(function (item) {
|
|
|
|
+ return item.id === parseInt(fid);
|
|
|
|
+ });
|
|
|
|
+ att && files.push(att);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (files.length === 0) return;
|
|
|
|
+
|
|
|
|
+ $(self).attr('disabled', 'true');
|
|
|
|
+ AliOss.zipFiles(files, setting.zipName, (fails) => {
|
|
|
|
+ $(self).removeAttr('disabled');
|
|
|
|
+ if (fails.length === 0) {
|
|
|
|
+ toastr.success('下载成功');
|
|
|
|
+ } else {
|
|
|
|
+ toastr.warning(`下载成功(${fails.length}个文件下载失败)`);
|
|
|
|
+ }
|
|
|
|
+ }, () => {
|
|
|
|
+ $(self).removeAttr('disabled');
|
|
|
|
+ toastr.error('批量下载失败');
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ // 上传附件
|
|
|
|
+ $('#upload-file-btn').click(function () {
|
|
|
|
+ const files = $('#upload-file')[0].files;
|
|
|
|
+ const formData = new FormData();
|
|
|
|
+ formData.append('lid', curNode[setting.key]);
|
|
|
|
+ for (const file of files) {
|
|
|
|
+ if (file === undefined) {
|
|
|
|
+ toastr.error('未选择上传文件!');
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ const filesize = file.size;
|
|
|
|
+ if (filesize > 30 * 1024 * 1024) {
|
|
|
|
+ toastr.error('存在上传文件大小过大!');
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ const fileext = '.' + file.name.toLowerCase().split('.').splice(-1)[0];
|
|
|
|
+ if (whiteList.indexOf(fileext) === -1) {
|
|
|
|
+ toastr.error('只能上传指定格式的附件!');
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ formData.append('size', filesize);
|
|
|
|
+ formData.append('file[]', file);
|
|
|
|
+ }
|
|
|
|
+ postDataWithFile(setting.uploadUrl, formData, function (data) {
|
|
|
|
+ // 插入到attData中
|
|
|
|
+ data.forEach(d => {
|
|
|
|
+ d.node = curNode;
|
|
|
|
+ allAtts.push(d);
|
|
|
|
+ _addToNodeIndex(d, true);
|
|
|
|
+ });
|
|
|
|
+ // 重新生成List
|
|
|
|
+ refreshAllAttHtml();
|
|
|
|
+ refreshCurAttHtml();
|
|
|
|
+
|
|
|
|
+ $('#upload').modal('hide');
|
|
|
|
+ }, function () {
|
|
|
|
+ toastr.error('附件上传失败');
|
|
|
|
+ });
|
|
|
|
+ $('#upload-file').val('');
|
|
|
|
+ });
|
|
|
|
+ $('body').on('click', 'a[name=att-locate]', function () {
|
|
|
|
+ const fid = this.getAttribute('file-id');
|
|
|
|
+ const att = allAtts.find(item => item.id === parseInt(fid));
|
|
|
|
+ setting.locate && setting.locate(att);
|
|
|
|
+ });
|
|
|
|
+ $('body').on('click', 'a[name=att-delete]', function () {
|
|
|
|
+ const fid = this.getAttribute('file-id');
|
|
|
|
+ const data = {id: fid};
|
|
|
|
+ postData(setting.deleteUrl, data, function (result) {
|
|
|
|
+ // 删除
|
|
|
|
+ const att_index = allAtts.findIndex(item => { return item.id === parseInt(fid); });
|
|
|
|
+ const att = allAtts[att_index];
|
|
|
|
+ allAtts.splice(att_index, 1);
|
|
|
|
+ const xi = nodeIndexes[att.node[setting.key]];
|
|
|
|
+ xi.splice(xi.findIndex(x => { return x.id === parseInt(fid); }), 1);
|
|
|
|
+ // 重新生成List
|
|
|
|
+ if (allAtts.length === 1) {
|
|
|
|
+ getAllAttHtml();
|
|
|
|
+ } else {
|
|
|
|
+ refreshAllAttHtml();
|
|
|
|
+ }
|
|
|
|
+ refreshCurAttHtml();
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ // 监听附件check是否选中
|
|
|
|
+ $('.list-table').on('click', '.check-file', function() {
|
|
|
|
+ const checkedList = $(this).parents('.list-table').children().find('input:checked');
|
|
|
|
+ const childs = $(this).parents('.list-table').children().length;
|
|
|
|
+ const checkBox = $(this).parents('.list-table').parent().find('.check-all-file');
|
|
|
|
+ if (checkedList.length === childs) {
|
|
|
|
+ checkBox.prop("checked", true);
|
|
|
|
+ } else {
|
|
|
|
+ checkBox.prop("checked", false);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ $('.check-all-file').click(function() {
|
|
|
|
+ const isCheck = $(this).is(':checked');
|
|
|
|
+ $(this).parents('table').find('.list-table').each(function() {
|
|
|
|
+ $(this).find('input:checkbox').prop("checked", isCheck);
|
|
|
|
+ })
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ const _addToNodeIndex = function(att, isTop = false) {
|
|
|
|
+ const id = att[setting.key];
|
|
|
|
+ if (!nodeIndexes[id]) {
|
|
|
|
+ nodeIndexes[id] = [];
|
|
|
|
+ }
|
|
|
|
+ let xi = nodeIndexes[id];
|
|
|
|
+ isTop ? xi.unshift(att) : xi.push(att);
|
|
|
|
+ };
|
|
|
|
+ const loadDatas = function (datas) {
|
|
|
|
+ for (const d of datas) {
|
|
|
|
+ allAtts.push(d);
|
|
|
|
+ _addToNodeIndex(d);
|
|
|
|
+ }
|
|
|
|
+ getAllAttHtml();
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ return { loadDatas, getCurAttHtml }
|
|
|
|
+ };
|
|
|
|
+})(jQuery);
|