瀏覽代碼

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

Tony Kang 1 年之前
父節點
當前提交
15a8935a27

+ 7 - 1
app/controller/payment_controller.js

@@ -991,7 +991,7 @@ module.exports = app => {
                     tender_id: ctx.paymentTender.id,
                     tr_id: ctx.trInfo.id,
                     td_id: ctx.detail.id,
-                }
+                };
                 while ((stream = await parts()) !== undefined) {
                     // 判断用户是否选择上传文件
                     if (!stream.filename) {
@@ -1011,11 +1011,13 @@ module.exports = app => {
                         filepath,
                         extra_upload,
                     };
+                    if (parts.field.safe_id) fileData.safe_id = parts.field.safe_id;
                     const result = await ctx.service.paymentDetailAtt.save(original_data, fileData, ctx.session.sessionUser.accountId);
                     if (!result) {
                         throw '导入数据库保存失败';
                     }
                     fileData.uid = ctx.session.sessionUser.accountId;
+                    fileData.u_name = ctx.session.sessionUser.name;
                     fileData.id = result.insertId;
                     fileData.orginpath = ctx.app.config.fujianOssPath + filepath;
                     delete fileData.filepath;
@@ -1023,6 +1025,7 @@ module.exports = app => {
                         fileData.filepath = `/payment/${original_data.tender_id}/detail/${original_data.td_id}/file/${fileData.id}/download`;
                     } else {
                         fileData.filepath = ctx.app.config.fujianOssPath + filepath;
+                        fileData.viewpath = ctx.app.config.fujianOssPath + filepath;
                     }
                     files.push(fileData);
                     ++index;
@@ -1206,6 +1209,9 @@ module.exports = app => {
                         case 'auditFlow':
                             responseData.data[f] = await ctx.service.paymentDetailAudit.getViewFlow(ctx.detail);
                             break;
+                        case 'att':
+                            responseData.data[f] = await ctx.service.paymentDetailAtt.getPaymentDetailAttachment(ctx.detail.id, 'DESC');
+                            break;
                         default:
                             responseData.data[f] = [];
                             break;

+ 1 - 1
app/controller/report_controller.js

@@ -558,7 +558,7 @@ module.exports = app => {
             if (!rptTpl || rptTpl.length !== 1) {
                 throw '获取模板失败';
             }
-            const source_type = rptTpl.source_type;
+            const source_type = rptTpl[0].source_type;
             rptTpl = JSON.parse(rptTpl[0].rpt_content);
             rptTpl.source_type = source_type || sourceTypeConst.defaultSourceType;
             rptTpl.id = params.rpt_tpl_id;

+ 14 - 7
app/public/js/file_detail.js

@@ -25,16 +25,13 @@ $(document).ready(function() {
             this.dragTree.recursiveFun(this.dragTree.children, x => {
                 if (x.children && x.children.length > 0) {
                     x.total_file_count = x.children.reduce((pre, c) => {
+                        if (x.filing_type === 1) console.log('reduce', c.name, c.total_file_count);
                         return pre + c.total_file_count
                     }, 0);
-                    // x.total_file_count = x.children.map(y => {
-                    //     return y.total_file_count;
-                    // }).reduce((pre, value) => {
-                    //     return pre + value
-                    // }, 0);
                 } else {
-                    x.total_file_count = x.file_count;
+                    x.total_file_count = x.file_count || 0;
                 }
+                if (x.filing_type === 1) console.log(x.name, x.total_file_count);
             });
         }
         _loadFilingSourceNode() {
@@ -169,10 +166,20 @@ $(document).ready(function() {
             });
         }
         delFiling(node, callback) {
+            const parent = node.getParentNode();
             const self = this;
             postData('filing/del', { id: node.id }, function(result) {
+                self.updateFilingFileCount(node, 0);
                 self.dragTree.loadPostData(result);
                 self.filingTree.removeNode(node);
+                self.calcTotalFileCount();
+                if (parent) {
+                    const path = parent.getPath();
+                    for (const p of path) {
+                        p.name = p.source_node.name + (p.source_node.total_file_count > 0 ? `(${p.source_node.total_file_count})` : '');
+                        filingObj.filingTree.updateNode(p);
+                    }
+                }
                 if (callback) callback();
             });
         }
@@ -183,7 +190,7 @@ $(document).ready(function() {
             return result;
         }
         updateFilingFileCount(filing, count) {
-            let differ = count - filing.source_node.file_count;
+            let differ = count - (filing.source_node.file_count || 0);
             filing.source_node.file_count = count;
             filing.source_node.total_file_count = count;
             filing.name = filing.source_node.name + (filing.source_node.total_file_count > 0 ? `(${filing.source_node.total_file_count})` : '');

+ 214 - 3
app/public/js/payment_safe.js

@@ -131,6 +131,7 @@ $(document).ready(function() {
         loadRelaData() {
             this.refreshOperationValid();
             SpreadJsObj.saveTopAndSelect(this.sheet, this.ckBillsSpread);
+            attObj.setSafeBills();
         }
         refreshTree(data) {
             const sheet = this.sheet;
@@ -572,9 +573,221 @@ $(document).ready(function() {
         };
     }
 
+    class AttObj {
+        constructor() {
+            this.atts = [];
+            this.billsIndexes = {};
+            this.pageCount = 15;
+            this.activeTab = 'cur';
+            this.curPageIndex = 1;
+            this.curTotalPage = 1;
+            this.allPageIndex = 1;
+            this.allTotalPage = 1;
+        }
+        refreshShowPage() {
+            const prefix = this.activeTab;
+            $('#totalPage').html(this[prefix + 'TotalPage']);
+            $('#currentPage').html(this[prefix + 'PageIndex']);
+            if (this[prefix + 'TotalPage'] > 1) {
+                $('#showPage').show();
+            } else {
+                $('#showPage').hide();
+            }
+        }
+        reCalcPage() {
+            this.allTotalPage = Math.ceil(this.atts.length / this.pageCount);
+            const curNode = SpreadJsObj.getSelectObject(billsObj.sheet);
+            const curAttIndex = this.billsIndexes[curNode.safe_id] || [];
+            this.curTotalPage = Math.ceil(curAttIndex.length / this.pageCount);
+            this.refreshShowPage();
+        }
+        loadDatas(datas) {
+            for (const d of datas) {
+                this.atts.push(d);
+                if (!this.billsIndexes[d.safe_id]) {
+                    this.billsIndexes[d.safe_id] = [];
+                }
+                this.billsIndexes[d.safe_id].push(d);
+            }
+            this.refreshTable();
+        }
+        loadUpdateAtt(files) {
+            for (const d of files) {
+                this.atts.unshift(d);
+                if (!this.billsIndexes[d.safe_id]) {
+                    this.billsIndexes[d.safe_id] = [];
+                }
+                this.billsIndexes[d.safe_id].unshift(d);
+            }
+        }
+        loadDeleteAtt(file) {
+            let fileIndex = this.atts.findIndex(x => { return x.id === file.id; });
+            this.atts.splice(fileIndex, 1);
+            if (this.billsIndexes[file.safe_id]) {
+                fileIndex = this.billsIndexes[file.safe_id].findIndex(x => { return x.id === file.id; });
+                this.billsIndexes[file.safe_id].splice(fileIndex, 1);
+            }
+        }
+        getFileHtml(file) {
+            const html = [];
+            const downHtml = `<a href="javascript: void(0);" onclick="AliOss.downloadFile('${file.filepath}', '${file.filename + file.fileext}')" class="mr-1"><i class="fa fa-download fa-fw"></i></a>`;
+            const delHtml = file.uid === userID ? `<a href="javascript: void(0);" class="mr-1 text-danger" name="del-file" file_id="${file.id}"><i class="fa fa-trash-o fa-fw"></i></a>` : '';
+            html.push('<tr>');
+            html.push(`<td><input type="checkbox" name="check-att" file_id="${file.id}"></td>`);
+            html.push(`<td><div class="d-flex justify-content-between align-items-center table-file"><a href="javascript: void(0);" file_id="${file.id}">${file.filename}${file.fileext}</a><div class="btn-group-table" style="display: none;">${downHtml}${delHtml}</div></div></td>`);
+            html.push(`<td>${file.u_name}</td>`);
+            html.push('</tr>');
+            return html.join('');
+        }
+        refreshCurTable() {
+            const curNode = SpreadJsObj.getSelectObject(billsObj.sheet);
+            const html = [];
+            if (curNode) {
+                const attIndex = this.billsIndexes[curNode.safe_id] || [];
+                const beginIndex = (this.allPageIndex - 1) * this.pageCount;
+                const endIndex = (this.allPageIndex) * this.pageCount - 1;
+                for (const [i, ai] of attIndex.entries()) {
+                    if (i < beginIndex) continue;
+                    if (i > endIndex) continue;
+                    html.push(this.getFileHtml(ai));
+                }
+            }
+
+            $('#cur-att-list').html(html.join(''));
+        }
+        refreshAllTable() {
+            const html = [];
+            const attIndex = this.atts;
+            const beginIndex = (this.allPageIndex - 1) * this.pageCount;
+            const endIndex = (this.allPageIndex) * this.pageCount - 1;
+            for (const [i, ai] of attIndex.entries()) {
+                if (i < beginIndex) continue;
+                if (i > endIndex) continue;
+                html.push(this.getFileHtml(ai));
+            }
+            $('#all-att-list').html(html.join(''));
+        }
+        prePage(){
+            const pageIndex = this.activeTab + 'PageIndex';
+            if (this[pageIndex] <= 1) return;
+            this[pageIndex] = this[pageIndex] - 1;
+            this.refreshShowTable();
+            this.refreshShowPage();
+        }
+        nextPage() {
+            const pageIndex = this.activeTab + 'PageIndex';
+            if (this[pageIndex] >= this[this.activeTab + 'TotalPage']) return;
+            this[pageIndex] = this[pageIndex] + 1;
+            this.refreshShowTable();
+            this.refreshShowPage();
+        }
+        refreshTable() {
+            this.reCalcPage();
+            this.refreshCurTable();
+            this.refreshAllTable();
+        }
+        refreshShowTable() {
+            if (this.activeTab === 'cur') {
+                this.refreshCurTable();
+            } else {
+                this.refreshAllTable();
+            }
+        }
+        batchDownload() {
+            const checkes = $('[name=check-att]:checked');
+            const files = [], fileIds = [];
+            for (const c of checkes) {
+                const file = this.atts.find(x => { return x.id === parseInt(c.getAttribute('file_id'))});
+                if (file && fileIds.indexOf(file.id) < 0) {
+                    fileIds.push(file.id);
+                    files.push({ filename: file.filename, fileext: file.fileext, filepath: c.viewpath || file.filepath});
+                }
+            }
+            AliOss.zipFiles(files, '安全生产费-附件.zip');
+        }
+        uploadAtt(files, callback) {
+            const curNode = SpreadJsObj.getSelectObject(billsObj.sheet);
+            const formData = new FormData();
+            if (curNode) formData.append('safe_id', curNode.safe_id);
+            for (const file of files) {
+                if (file === undefined) {
+                    toastr.error('未选择上传文件。');
+                    return false;
+                }
+                if (file.size > 30 * 1024 * 1024) {
+                    toastr.error('上传文件大小超过30MB。');
+                    return false;
+                }
+                const fileext = '.' + file.name.toLowerCase().split('.').splice(-1)[0];
+                if (whiteList.indexOf(fileext) === -1) {
+                    toastr.error('仅支持office文档、图片、压缩包格式,请勿上传' + fileext + '格式文件。');
+                    return false;
+                }
+                formData.append('size', file.size);
+                formData.append('file[]', file);
+            }
+            postDataWithFile('file/upload', formData, function (files) {
+                attObj.loadUpdateAtt(files);
+                attObj.refreshTable();
+                if (callback) callback();
+            });
+        }
+        deleteAtt(file_id) {
+            const file = this.atts.find(x => { return x.id === file_id; });
+            if (!file) return;
+
+            postData('file/delete', {id: file_id}, function() {
+                attObj.loadDeleteAtt(file);
+                attObj.refreshTable();
+            })
+        }
+        setTab(tab) {
+            this.activeTab = tab;
+            this.refreshShowPage();
+        }
+        setSafeBills() {
+            this.curPageIndex = 1;
+            this.reCalcPage();
+            this.refreshCurTable();
+        }
+    }
+    const attObj = new AttObj();
+    $('#upload-ok').click(function() {
+        const input = $('#upload-file');
+        attObj.uploadAtt(input[0].files, function() {
+            $(input).val('');
+            $('#upload').modal('hide');
+        });
+    });
+    $('#batch-download-att').click(() => {
+        attObj.batchDownload();
+    });
+    $('body').on('mouseenter', ".table-file", function(){
+        $(this).children(".btn-group-table").css("display","block");
+    });
+    $('body').on('mouseleave', ".table-file", function(){
+        $(this).children(".btn-group-table").css("display","none");
+    });
+    $('body').on('click', '[name=del-file]', function() {
+       attObj.deleteAtt(parseInt(this.getAttribute('file_id')));
+    });
+    $('.page-select').click(function() {
+        const content = this.getAttribute('content');
+        if (content === 'pre') {
+            attObj.prePage();
+        } else if (content === 'next') {
+            attObj.nextPage();
+        }
+    });
+    $('[fujian-content]').click(function() {
+        const content = this.getAttribute('fujian-content');
+        attObj.setTab(content.replace('-att', ''));
+    });
+
     // 加载安全生产费数据
-    postData('load', { filter: 'bills' }, function(result) {
+    postData('load', { filter: 'bills;att' }, function(result) {
         billsObj.loadData(result.bills);
+        attObj.loadDatas(result.att);
     });
 
     const stdGclSetting = {
@@ -677,8 +890,6 @@ $(document).ready(function() {
             if (tab.attr('content') === '#std-gcl') {
                 if (!stdGcl) stdGcl = $.stdLib(stdGclSetting);
                 stdGcl.spread.refresh();
-            } else if (tab.attr('content') === '#fujian') {
-                // todo 附件
             }
         } else { // 收起工具栏
             tab.removeClass('active');

+ 1 - 1
app/public/js/shares/drag_tree.js

@@ -398,7 +398,7 @@ const createDragTree = function (setting) {
                 array.splice(index, 1);
             };
             for (const data of datas) {
-                const node = this.getItems(data[this.setting.id]);
+                const node = this.getItems(data);
                 if (node) {
                     freeDatas.push(node);
                     node.deleteIndex = this.nodes.indexOf(node);

+ 2 - 0
app/router.js

@@ -764,6 +764,8 @@ module.exports = app => {
     app.get('/payment/:id/safe/:did/compare', sessionAuth, paymentTenderCheck, paymentDetailCheck, 'paymentController.safeCompare');
     app.post('/payment/:id/safe/:did/load', sessionAuth, paymentTenderCheck, paymentDetailCheck, 'paymentController.safeLoad');
     app.post('/payment/:id/safe/:did/update', sessionAuth, paymentTenderCheck, paymentDetailCheck, 'paymentController.safeUpdate');
+    app.post('/payment/:id/safe/:did/file/upload', sessionAuth, paymentTenderCheck, paymentDetailCheck, 'paymentController.uploadDetailFile');
+    app.post('/payment/:id/safe/:did/file/delete', sessionAuth, paymentTenderCheck, paymentDetailCheck, 'paymentController.deleteDetailFile');
 
 
     // 企业微信回调

+ 1 - 1
app/service/payment_detail.js

@@ -339,7 +339,7 @@ module.exports = app => {
 
         async doCheckDetail(id) {
             const accountId = this.ctx.session.sessionUser.accountId;
-            const auditPermission = await this.service.paymentPermissionAudit.getOnePermission(this.session.sessionUser.is_admin, accountId);
+            const auditPermission = await this.service.paymentPermissionAudit.getOnePermission(this.ctx.session.sessionUser.is_admin, accountId);
             if (!auditPermission) throw '权限不足';
 
             const detail = await this.getDataById(id);

+ 1 - 0
app/service/payment_detail_att.js

@@ -59,6 +59,7 @@ module.exports = app => {
                     item.filepath = `/payment/${item.tender_id}/detail/${item.td_id}/file/${item.id}/download`;
                 } else {
                     item.filepath = this.ctx.app.config.fujianOssPath + item.filepath;
+                    item.viewpath = item.filepath;
                 }
                 return item;
             });

+ 1 - 1
app/service/payment_detail_audit.js

@@ -662,7 +662,7 @@ module.exports = app => {
         async getAuditPayment(auditorId) {
             const sql =
                 'SELECT pda.`aid`, pda.`times`, pda.`order`, pda.`begin_time`, pda.`end_time`, pda.`tender_id`, pda.`tr_id`, pda.`td_id`,' +
-                '    pd.`code` As `scode`, pd.`order` As `sorder`, pd.`status` As `sstatus`,' +
+                '    pd.`code` As `scode`, pd.`order` As `sorder`, pd.`status` As `sstatus`, pd.type,' +
                 '    pr.`rpt_name` As `rpt_name`,' +
                 '    t.`name`, t.`pid`, t.`uid` ' +
                 '  FROM ?? AS pda ' +

+ 1 - 1
app/service/payment_safe_bills.js

@@ -14,7 +14,7 @@ const SafeBillsFields = {
     textFields: ['b_code', 'name', 'unit', 'spec', 'invoice_code', 'memo'],
     calcFields: ['unit_price', 'cur_qty', 'cur_tp', 'end_qty', 'end_tp'],
     fixedFields: ['safe_id', 'tender_id', 'pre_qty', 'pre_tp', 'cur_read_qty', 'cur_read_tp', 'cur_his', 'add_user_id', 'add_time'],
-    treeFields: ['id', 'detail_id', 'tree_id', 'tree_pid', 'tree_level', 'tree_order', 'tree_full_path', 'tree_is_leaf'],
+    treeFields: ['id', 'detail_id', 'safe_id', 'tree_id', 'tree_pid', 'tree_level', 'tree_order', 'tree_full_path', 'tree_is_leaf'],
 };
 SafeBillsFields.editQueryFields = [...SafeBillsFields.treeFields, ...SafeBillsFields.textFields, ...SafeBillsFields.calcFields, 'pre_qty', 'pre_tp'];
 SafeBillsFields.readQueryFields = [...SafeBillsFields.treeFields, ...SafeBillsFields.textFields, 'unit_price', 'pre_qty', 'pre_tp', 'cur_read_qty', 'cur_read_tp'];

+ 2 - 2
app/service/rpt_tpl.js

@@ -28,7 +28,7 @@ module.exports = app => {
                 value: id,
                 operate: '=',
             });
-            this.sqlBuilder.columns = ['id', 'rpt_type', 'rpt_tpl_name', 'rpt_content'];
+            this.sqlBuilder.columns = ['id', 'rpt_type', 'rpt_tpl_name', 'rpt_content', 'source_type'];
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
             const list = await this.db.query(sql, sqlParam);
             return list;
@@ -40,7 +40,7 @@ module.exports = app => {
                 value: rpt_ids,
                 operate: 'in',
             });
-            this.sqlBuilder.columns = ['id', 'rpt_type', 'rpt_tpl_name', 'rpt_content'];
+            this.sqlBuilder.columns = ['id', 'rpt_type', 'rpt_tpl_name', 'rpt_content', 'source_type'];
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName);
             const list = await this.db.query(sql, sqlParam);
             return list;

+ 16 - 0
app/view/dashboard/index.ejs

@@ -233,18 +233,34 @@
                                             <% if (audit.sstatus !== acStage.status.checkNo) { %>
                                                 <tr data-type="10">
                                                     <td><span class="bg-new-payment text-new-payment badge text-width">支付审批</span></td>
+                                                    <% if (audit.type) { %>
+                                                    <td><a href="/payment/<%- audit.tender_id %>/list/<%- audit.tr_id %>"><%- audit.name %> <%- audit.rpt_name %></a> <a href="/payment/<%- audit.tender_id %>/safe/<%- audit.td_id %>/bills"><%- audit.scode %></a></td>
+                                                    <% } else { %>
                                                     <td><a href="/payment/<%- audit.tender_id %>/list/<%- audit.tr_id %>"><%- audit.name %> <%- audit.rpt_name %></a> <a href="/payment/<%- audit.tender_id %>/detail/<%- audit.td_id %>"><%- audit.scode %></a></td>
+                                                    <% } %>
                                                     <td>第<%- audit.sorder %>期</td>
                                                     <td><%- ctx.moment(audit.begin_time).format('YYYY/MM/DD HH:mm') %></td>
+                                                    <% if (audit.type) { %>
+                                                    <td><a href="/payment/<%- audit.tender_id %>/safe/<%- audit.td_id %>/bills" class="btn btn-outline-primary btn-sm btn-table" role="button"><% if (audit.sstatus === acStage.status.checkNoPre) { %>重新<% } %>审 批</a></td>
+                                                    <% } else { %>
                                                     <td><a href="/payment/<%- audit.tender_id %>/detail/<%- audit.td_id %>" class="btn btn-outline-primary btn-sm btn-table" role="button"><% if (audit.sstatus === acStage.status.checkNoPre) { %>重新<% } %>审 批</a></td>
+                                                    <% } %>
                                                 </tr>
                                             <% } else { %>
                                                 <tr data-type="10">
                                                     <td><span class="bg-new-payment text-new-payment badge text-width">支付审批</span></td>
+                                                    <% if (audit.type) { %>
+                                                    <td><a href="/payment/<%- audit.tender_id %>/list"><%- audit.name %> <%- audit.rpt_name %></a> <a href="/payment/<%- audit.tender_id %>/safe/<%- audit.td_id %>/bills"><%- audit.scode %></a></td>
+                                                    <% } else {%>
                                                     <td><a href="/payment/<%- audit.tender_id %>/list"><%- audit.name %> <%- audit.rpt_name %></a> <a href="/payment/<%- audit.tender_id %>/detail/<%- audit.td_id %>"><%- audit.scode %></a></td>
+                                                    <% } %>
                                                     <td>第<%- audit.sorder %>期</td>
                                                     <td><%- ctx.moment(audit.end_time).format('YYYY/MM/DD HH:mm') %></td>
+                                                    <% if (audit.type) { %>
+                                                    <td><a href="/payment/<%- audit.tender_id %>/safe/<%- audit.td_id %>/bills" class="btn btn-outline-warning btn-sm btn-table text-warning" role="button">重新上报</a></td>
+                                                    <% } else {%>
                                                     <td><a href="/payment/<%- audit.tender_id %>/detail/<%- audit.td_id %>" class="btn btn-outline-warning btn-sm btn-table text-warning" role="button">重新上报</a></td>
+                                                    <% } %>
                                                 </tr>
                                             <% } %>
                                         <% } %>

+ 11 - 86
app/view/payment_safe/index.ejs

@@ -52,114 +52,38 @@
                         <div class="sjs-bar">
                             <ul class="nav nav-tabs">
                                 <li class="nav-item">
-                                    <a class="nav-link active" data-toggle="tab" href="#dqjiedian" role="tab" fujian-content="dqjiedian">当前节点</a>
+                                    <a class="nav-link active" data-toggle="tab" href="#cur-att" role="tab" fujian-content="cur-att">当前节点</a>
                                 </li>
                                 <li class="nav-item">
-                                    <a class="nav-link" data-toggle="tab" href="#syfujian" role="tab" fujian-content="syfujian">所有附件</a>
+                                    <a class="nav-link" data-toggle="tab" href="#all-att" role="tab" fujian-content="all-att">所有附件</a>
                                 </li>
                                 <li class="nav-item ml-auto pt-1">
-                                    <button  id="bach-download" class="btn btn-sm btn-primary" type="curr">批量下载</button>
+                                    <button  id="batch-download-att" class="btn btn-sm btn-primary" type="curr">批量下载</button>
                                     <!--所有附件 翻页-->
                                     <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="currentPage">1</span>/<span id="totalPage">10</span> <a href="javascript:void(0);" class="page-select mr-3" content="next"><i class="fa fa-chevron-right"></i></a></span>
-                                    <a href="#upload" data-toggle="modal" data-target="#upload"  class="btn btn-sm btn-outline-primary ml-3">上传</a>
+                                    <a href="#upload" data-toggle="modal" data-target="#upload" class="btn btn-sm btn-outline-primary ml-3">上传</a>
                                 </li>
                             </ul>
                         </div>
-                        <a href="javascript: void(0);" id="zipDown" download style="display: none;"></a>
                         <div class="tab-content">
-                            <div class="tab-pane active" id="dqjiedian">
-                                <div class="sjs-height-3" style="overflow:auto; overflow-x:hidden;">
+                            <div class="tab-pane active" id="cur-att">
+                                <div class="sjs-sh-3" style="overflow:auto; overflow-x:hidden;">
                                     <table class="table table-sm table-bordered table-hover" style="word-break:break-all; table-layout: fixed">
                                         <tr><th width="25"><input type="checkbox" class="check-all-file"><th>文件名</th><th width="80">上传</th></tr>
-                                        <tbody id="nodelist-table" class="list-table">
+                                        <tbody id="cur-att-list" class="list-table">
                                         </tbody>
                                     </table>
                                 </div>
                             </div>
-                            <div class="tab-pane" id="syfujian">
-                                <div class="sjs-height-3" style="overflow:auto; overflow-x:hidden;">
+                            <div class="tab-pane" id="all-att">
+                                <div class="sjs-sh-3" style="overflow:auto; overflow-x:hidden;">
                                     <table class="table table-sm table-bordered table-hover" style="word-break:break-all; table-layout: fixed">
                                         <tr><th width="25"><input type="checkbox" class="check-all-file"></th><th>文件名</th><th width="80">上传</th></tr>
-                                        <tbody id="alllist-table" class="list-table">
+                                        <tbody id="all-att-list" class="list-table">
                                         </tbody>
                                     </table>
                                 </div>
                             </div>
-                            <div class="sjs-bottom">
-                                <div class="resize-y" id="file-spr" r-Type="height" div1=".sjs-height-3" div2=".sjs-bottom" title="调整大小"><!--调整上下高度条--></div>
-                                <br>
-                                <div class="tab-content" id="showAttachment" style="display: none" file-id="">
-                                    <div class="sjs-bottom-2">
-                                        <a href="javascript:void(0);" target="_blank" style="display: none" id="load-file"></a>
-                                        <div class="d-flex justify-content-end mb-1" id="btn-att">
-                                            <a href="javascript:void(0);" content="location" class="btn btn-sm btn-outline-primary" style="margin-right: 5px">定位</a>
-                                            <a href="javascript:void(0);" content="view" class="btn btn-sm btn-outline-primary" style="margin-right: 5px">查看</a>
-                                            <!--默认 有删除权限-->
-                                            <a href="javascript:void(0);" content="del" class="btn btn-sm text-danger" style="display: none; margin-right: 5px">删除</a>
-                                            <!--默认 有编辑权限-->
-                                            <a href="javascript:void(0);" content="edit" class="btn btn-sm btn-outline-primary" style="display: none; margin-right: 5px">编辑</a>
-                                            <!--编辑模式-->
-                                            <a href="javascript:void(0);" content="save" class="btn btn-sm btn-outline-success mr-1" style="display: none; margin-right: 5px">保存</a>
-                                            <a href="javascript:void(0);" content="cancel" class="btn btn-sm btn-outline-secondary" style="display: none; margin-right: 5px">取消</a>
-                                        </div>
-                                        <!--显示信息-->
-                                        <table class="table table-sm table-bordered" id="show-att" style="word-break:break-all; table-layout: fixed">
-                                            <tbody>
-                                            <tr><th>文件名</th><td colspan="3">asdasd.jpg</td></tr>
-                                            <tr><th>所在节点</th><td colspan="3" id="show-att-node">1 第一部分 建筑安装工程非</td></tr>
-                                            <!-- <tr><td colspan="4"><a href="javascript:void(0);" target="_blank"><span>下载附件</span></a></td></tr> -->
-                                            <tr><th>上传者</th><td>张三</td><th>上传时间</th><td>2018-10-20</td></tr>
-                                            <tr><th>备注</th><td colspan="3"></td></tr>
-                                            </tbody>
-                                        </table>
-                                        <div id="edit-att" style="display: none">
-                                            <!--编辑模式-->
-                                            <div class="form-group">
-                                                <div class="input-group input-group-sm">
-                                                    <div class="input-group-prepend">
-                                                        <span class="input-group-text">文件名</span>
-                                                    </div>
-                                                    <input type="text" class="form-control form-control-sm" value="asdasd">
-                                                    <div class="input-group-append">
-                                                        <span class="input-group-text">.jpg</span>
-                                                    </div>
-                                                </div>
-                                            </div>
-                                            <div class="form-group">
-                                                <div class="input-group input-group-sm">
-                                                    <div class="input-group-prepend">
-                                                        <span class="input-group-text">所在节点</span>
-                                                    </div>
-                                                    <input type="text" class="form-control form-control-sm" value="1 第一部分 建筑安装工程非" readonly="">
-                                                </div>
-                                            </div>
-                                            <div class="form-group">
-                                                <div class="input-group input-group-sm">
-                                                    <div class="input-group-prepend">
-                                                        <span class="input-group-text">上传时间</span>
-                                                    </div>
-                                                    <input type="text" class="form-control form-control-sm" value="2018-10-20" readonly="">
-                                                </div>
-                                            </div>
-                                            <div class="form-group">
-                                                <div class="input-group input-group-sm">
-                                                    <div class="input-group-prepend">
-                                                        <span class="input-group-text">备注</span>
-                                                    </div>
-                                                    <input type="text" class="form-control form-control-sm" value="">
-                                                </div>
-                                            </div>
-                                            <div class="form-group">
-                                                <label>替换文件</label>
-                                                <div class="custom-file">
-                                                    <input type="file" class="custom-file-input" id="change-att-btn">
-                                                    <label class="custom-file-label" data-browse="浏览" for="customFile">选择文件</label>
-                                                </div>
-                                            </div>
-                                        </div>
-                                    </div>
-                                </div>
-                            </div>
                         </div>
                     </div>
                 </div>
@@ -183,4 +107,5 @@
     const stdBills = JSON.parse(unescape('<%- escape(JSON.stringify(stdBills)) %>'));
     const tenderId = parseInt('<%- ctx.paymentTender.id %>');
     const detailId = parseInt('<%- ctx.detail.id %>');
+    const whiteList = JSON.parse('<%- JSON.stringify(ctx.app.config.multipart.whitelist) %>');
 </script>

+ 20 - 1
app/view/payment_safe/modal.ejs

@@ -1,2 +1,21 @@
 <% include ../shares/delete_hint_modal.ejs %>
-<% include ../payment/audit_modal.ejs %>
+<% include ../payment/audit_modal.ejs %>
+<div class="modal fade" id="upload" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">上传附件</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label for="formGroupExampleInput">单个文件大小限制:30MB,支持<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="doc,docx,xls,xlsx,ppt,pptx,pdf">office等文档格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="jpg,png,bmp">图片格式</span>、<span data-toggle="tooltip" data-placement="bottom" title="" data-original-title="rar,zip">压缩包格式</span></label>
+                    <input type="file" class="" id="upload-file" multiple>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary btn-sm" id="upload-ok">确认</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 1 - 1
config/web.js

@@ -1198,7 +1198,7 @@ const JsFiles = {
                     '/public/js/shares/sjs_setting.js',
                     '/public/js/shares/cs_tools.js',
                     '/public/js/zh_calc.js',
-                    '/public/js/zip_oss.js',
+                    '/public/js/shares/ali_oss.js',
                     '/public/js/path_tree.js',
                     '/public/js/std_lib.js',
                     '/public/js/payment_detail_audit.js',

+ 38 - 1
sql/update.sql

@@ -12,4 +12,41 @@ ALTER TABLE `zh_rpt_tpl`
 ADD COLUMN `source_type`  int(11) UNSIGNED NOT NULL DEFAULT 1 COMMENT '数据源类型' AFTER `rpt_content`;
 
 ALTER TABLE `zh_rpt_mapping_field`
-ADD COLUMN `source_type`  int(11) UNSIGNED NOT NULL COMMENT '数据源类型' AFTER `items`;
+ADD COLUMN `source_type`  int(11) UNSIGNED NOT NULL COMMENT '数据源类型' AFTER `items`;
+
+ALTER TABLE `zh_payment_detail_attachment`
+ADD COLUMN `safe_id`  varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '安全生产费清单id(uuid)(zh_payment_safe_bills.safe_id)' AFTER `extra_upload`;
+
+CREATE TABLE `zh_payment_safe_bills` (
+  `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'uuid',
+  `safe_id` varchar(36) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT 'uuid(不同期保持统一)',
+  `tender_id` int(11) unsigned NOT NULL COMMENT '标段id',
+  `detail_id` int(11) unsigned NOT NULL,
+  `tree_id` int(11) NOT NULL COMMENT '节点id',
+  `tree_pid` int(11) NOT NULL COMMENT '父节点id',
+  `tree_level` tinyint(4) NOT NULL COMMENT '层级',
+  `tree_order` mediumint(4) NOT NULL COMMENT '同级排序',
+  `tree_full_path` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '层级定位辅助字段parent.full_path.ledger_id',
+  `tree_is_leaf` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '是否叶子节点,界面显示辅助字段',
+  `b_code` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '编号',
+  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '名称',
+  `unit` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '单位',
+  `spec` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '规格',
+  `unit_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '单价',
+  `pre_qty` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '截止上期数量',
+  `pre_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '截止上期金额',
+  `cur_qty` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '本期数量',
+  `cur_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '本期金额',
+  `end_qty` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '截止本期数量',
+  `end_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '截止本期金额',
+  `invoice_code` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '发票号',
+  `memo` varchar(1000) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '备注',
+  `add_user_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '创建人',
+  `add_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `update_user_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '最后编辑人',
+  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后编辑时间',
+  `cur_read_qty` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '本期数量-只读',
+  `cur_read_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '本期金额-只读',
+  `cur_his` json DEFAULT NULL COMMENT '本期历史',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;