Jelajahi Sumber

Merge branch 'master' of http://192.168.1.41:3000/maixinrong/Calculation

laiguoran 5 tahun lalu
induk
melakukan
ed8fe40e86

+ 2 - 0
app/const/deal_pay.js

@@ -30,6 +30,8 @@ const calcBase = [
     {name: '签约开工预付款', code: 'kgyfk', sort: 2},
     {name: '签约材料预付款', code: 'clyfk', sort: 2},
     {name: '本期完成计量', code: 'bqwc', limit: true, sort: 10},
+    {name: '本期合同计量', code: 'bqht', limit: true, sort: 10},
+    {name: '本期变更计量', code: 'bqbg', limit: true, sort: 10},
     {name: '100章本期完成计量', code: 'ybbqwc', limit: true, sort: 1},
 ];
 

+ 4 - 0
app/controller/stage_controller.js

@@ -723,6 +723,7 @@ module.exports = app => {
                         check_calc: false,
                         contract_tp: payCalculator.cur.contract_tp, qc_tp: payCalculator.cur.qc_tp,
                         yf_tp: payCalculator.yf.tp,
+                        sf_tp: payCalculator.sf.tp
                     }, {id: this.ctx.stage.id});
                 }
                 await this.layout('stage/pay.ejs', renderData, 'stage/pay_modal.ejs');
@@ -762,6 +763,7 @@ module.exports = app => {
                             check_calc: false,
                             contract_tp: payCalculator.cur.contract_tp, qc_tp: payCalculator.cur.qc_tp,
                             yf_tp: payCalculator.yf.tp,
+                            sf_tp: payCalculator.sf.tp
                         }, {id: this.ctx.stage.id});
 
                         break;
@@ -778,6 +780,7 @@ module.exports = app => {
                                 check_calc: false,
                                 contract_tp: payCalculator.cur.contract_tp, qc_tp: payCalculator.cur.qc_tp,
                                 yf_tp: payCalculator.yf.tp,
+                                sf_tp: payCalculator.sf.tp
                             }, {id: this.ctx.stage.id});
                         } else {
                             if (data.updateData instanceof Array) {
@@ -795,6 +798,7 @@ module.exports = app => {
                             check_calc: false,
                             contract_tp: payCalculator.cur.contract_tp, qc_tp: payCalculator.cur.qc_tp,
                             yf_tp: payCalculator.yf.tp,
+                            sf_tp: payCalculator.sf.tp
                         }, {id: this.ctx.stage.id});
                         break;
                 }

+ 7 - 2
app/lib/ledger.js

@@ -157,14 +157,19 @@ class baseTree {
      * @returns {Array}
      */
     getPosterity (node) {
+        let posterity;
         if (node.full_path !== '') {
             const reg = new RegExp('^' + node.full_path + '-');
-            return this.datas.filter(function (x) {
+            posterity = this.datas.filter(function (x) {
                 return reg.test(x.full_path);
             });
         } else {
-            return this._recursiveGetPosterity(node);
+            posterity = this._recursiveGetPosterity(node);
         }
+        posterity.sort(function (x, y) {
+            return self.getNodeIndex(x) - self.getNodeIndex(y);
+        });
+        return posterity;
     };
 
     /**

+ 50 - 24
app/lib/stage_im.js

@@ -61,7 +61,7 @@ class StageIm {
         this.ImData = [];
         this.ImBillsData = [];
         //
-        this.imFields = ['uuid', 'doc_code', 'peg', 'bw', 'xm', 'drawing_code', 'calc_memo', 'calc_img', 'position'];
+        this.imFields = ['uuid', 'doc_code', 'peg', 'bw', 'xm', 'drawing_code', 'calc_memo', 'calc_img', 'position', 'jldy'];
         this.splitChar = '-';
     }
 
@@ -255,8 +255,9 @@ class StageIm {
                 (!im.pos_name || im.pos_name === d.pos_name);
         });
         if (cd) {
+            im.custom_define = cd.custom_define ? cd.custom_define.split(',') : this.imFields;
             this._.assignInWith(im, cd, function(oV, sV, key) {
-                return self.imFields.indexOf(key) > -1 && sV !== undefined && sV !== null ? sV : oV;
+                return im.custom_define.indexOf(key) > -1 && sV !== undefined && sV !== null ? sV : oV;
             });
         }
     }
@@ -273,6 +274,10 @@ class StageIm {
             }
             im.calc_memo = memo.join('\n');
         } else if (im.gclBills && im.gclBills.length > 0) {
+            const self = this;
+            im.gclBills.sort(function (x, y) {
+                return self.ctx.helper.compareCode(x.b_code, y.b_code);
+            });
             const memo = [];
             for (const [i, b] of im.gclBills.entries()) {
                 if (b.pos && b.pos.length > 0) {
@@ -435,6 +440,32 @@ class StageIm {
         }
     }
 
+    _addBwBillsGclBills(im, bills) {
+        if (!im.gclBills) im.gclBills = [];
+        let gcl = im.gclBills.find(function (x) {
+            return (!bills.b_code || bills.b_code === x.b_code) &&
+                (!bills.name || bills.name === x.name) &&
+                (!bills.unit || bills.unit === x.unit) &&
+                checkZero(this.ctx.helper.sub(bills.unit_price, x.unit_price));
+        });
+        if (!gcl) {
+            gcl = {b_code: bills.b_code, name: bills.name, unit: bills.unit, unit_price: bills.unit_price};
+            im.gclBills.push(gcl);
+        }
+        gcl.contract_jl = this.ctx.helper.add(gcl.contract_jl, bills.contract_jl);
+        gcl.qc_jl = this.ctx.helper.add(gcl.qc_jl, bills.qc_jl);
+        gcl.jl = this.ctx.helper.add(gcl.jl, bills.jl);
+    }
+    _calculateBwBillsIm(im) {
+        const tp_decimal = this.ctx.tender.info.decimal.tp;
+        im.contract_jl = 0;
+        im.qc_jl = 0;
+        for (const b of im.gclBills) {
+            im.contract_jl = this.ctx.helper.add(im.contract_jl, this.ctx.helper.mul(b.contract_jl, b.unit_price, tp_decimal));
+            im.qc_jl = this.ctx.helper.add(im.qc_jl, this.ctx.helper.mul(b.qc_jl, b.unit_price, tp_decimal));
+        }
+        im.jl = this.ctx.helper.add(im.contract_jl, im.qc_jl);
+    }
     _getBwBillsIm(node, peg, index, bw) {
         const im = {
             lid: node.id, pid: '', code: node.code, name: node.name, pos_name: '',
@@ -470,7 +501,6 @@ class StageIm {
     _generateBwBillsImData (node) {
         if (!node.gather_tp && !node.contract_tp && !node.qc_tp) return;
 
-        const tp_decimal = this.ctx.tender.info.decimal.tp;
         const nodeIndex = gsTree.getNodeIndex(node);
         const peg = this._getPegNode(node);
         const nodeImData = [], posterity = gsTree.getPosterity(node);
@@ -488,23 +518,19 @@ class StageIm {
 
                     const im = this._getBwBillsPosIm(nodeImData, node, peg, nodeIndex, bw, pp.name);
 
+                    this._addBwBillsGclBills(im, {
+                        b_code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
+                        jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty
+                    });
+
                     for (const c of changes) {
                         if (c.lid === p.id && c.pid == pp.id && c.qty && c.qty !== 0) {
                             im.changes.push(c);
                         }
                     }
 
-                    im.jl = ZhCalc.add(im.jl, ZhCalc.mul(pp.gather_qty, p.unit_price, tp_decimal));
-                    im.contract_jl = ZhCalc.add(im.contract_jl, ZhCalc.mul(pp.contract_qty, p.unit_price, tp_decimal));
-                    im.qc_jl = ZhCalc.add(im.qc_jl, ZhCalc.mul(pp.qc_qty, p.unit_price, tp_decimal));
-                    if (pp.drawing_code) im.drawing_code.push(pp.drawing_code);
-                    if (pp.position) im.position.push(pp.position);
-
-                    im.gclBills.push({
-                        bid: p.id,
-                        b_code: p.b_code, name: p.name, unit: p.unit,
-                        jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty
-                    });
+                    if (pp.drawing_code && im.drawing_code instanceof Array) im.drawing_code.push(pp.drawing_code);
+                    if (pp.position && im.position instanceof Array) im.position.push(pp.position);
                 }
             } else {
                 for (const c of changes) {
@@ -513,23 +539,23 @@ class StageIm {
                     }
                 }
 
-                imDefault.jl = ZhCalc.add(imDefault.jl, p.gather_qty);
-                imDefault.contract_jl = ZhCalc.add(imDefault.contract_jl, p.contract_qty);
-                imDefault.qc_jl = ZhCalc.add(imDefault.qc_jl, p.qc_qty);
+                imDefault.contract_jl = this.ctx.helper.add(imDefault.contract_jl, p.contract_qty);
+                imDefault.qc_jl = this.ctx.helper.add(imDefault.qc_jl, p.qc_qty);
 
-                imDefault.gclBills.push({
-                    bid: p.id,
-                    b_code: p.b_code, name: p.name, unit: p.unit,
-                    jl: p.gather_tp, contract_jl: p.contract_tp, qc_jl: p.qc_tp
+                this._addBwBillsGclBills(imDefault, {
+                    b_code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
+                    jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_jl,
                 });
             }
         }
-        if (imDefault.jl) {
+        if (imDefault.contract_jl || imDefault.qc_jl) {
+            imDefault.jl = this.ctx.helper.add(imDefault.contract_jl, imDefault.qc_jl);
             ImData.push(imDefault);
         }
         for (const im of nodeImData) {
-            im.drawing_code = im.drawing_code.join(mergeChar);
-            im.position = im.position.join(mergeChar);
+            this._calculateBwBillsIm(im);
+            im.drawing_code = this.ctx.helper._.uniq(im.drawing_code).join(mergeChar);
+            im.position = this.ctx.helper._.uniq(im.position).join(mergeChar);
             ImData.push(im);
         }
     }

+ 13 - 13
app/public/css/main.css

@@ -8,8 +8,8 @@ body {
 .dropdown-menu {
     font-size: 12px
 }
-.btn.disabled, .btn:disabled {
-  color:#999
+.btn.text-primary.disabled, .btn.text-primary:disabled {
+  color:#666!important
 }
 .btn,.btn-group {
   vertical-align: baseline;
@@ -80,23 +80,23 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 /*滚动条*/
 /* 滚动条 */
 /*水平滚动条的样式*/
-/*::-webkit-scrollbar-thumb:horizontal {
+/*::-webkit-scrollbar-thumb:horizontal { 
 	width: 5px;
 	background-color: #e9ecef;
 	-webkit-border-radius: 0;
 }*/
 /*滚动条的背景颜色,滚动条的圆角宽度*/
 /*::-webkit-scrollbar-track-piece {
-	background-color: #efefef;
-	-webkit-border-radius: 0;
+	background-color: #efefef; 
+	-webkit-border-radius: 0; 
 }*/
 /*滚动条的宽度,滚动条的高度*/
 /*::-webkit-scrollbar {
-	width: 14px;
-	height: 14px;
+	width: 14px; 
+	height: 14px; 
 }*/
 /*垂直滚动条的样式*/
-/*::-webkit-scrollbar-thumb:vertical {
+/*::-webkit-scrollbar-thumb:vertical { 
 	height: 50px;
 	background-color: #e9ecef;
 	-webkit-border-radius: 0;
@@ -105,7 +105,7 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 	border: 1px solid #ced4da;
 }*/
 /*滚动条的hover样式*/
-/*::-webkit-scrollbar-thumb:hover {
+/*::-webkit-scrollbar-thumb:hover { 
 	height: 50px;
 	background-color: #ced4da;
 	-webkit-border-radius: 0;
@@ -672,7 +672,7 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
   font-size: 14px
 }
 .bd-toc {
-
+  
     position: sticky;
     top:3rem;
     height: calc(100vh - 10rem);
@@ -827,7 +827,7 @@ body{
   line-height: 30px;
 }
 .panel-title > .title-main .btn.pull-right {
-    margin: 5px 0 0 0
+    margin: 5px 0 0 0 
 }
 .panel-content{
   padding-top:35px;
@@ -1048,6 +1048,6 @@ a.maintain-icon .fa{
     }
 }
 
-a.maintain-icon:hover .fa{
+a.maintain-icon:hover .fa{ 
     animation-iteration-count:0
-}
+}

+ 105 - 2
app/public/js/ledger.js

@@ -23,6 +23,7 @@ const invalidFields = {
     posCalc: ['sgfh_qty', 'sgfh_tp', 'sjcl_qty', 'sjcl_tp', 'qtcl_qty', 'qtcl_tp'],
     posXmj: ['code'],
 };
+const exprField = ['sgfh_qty', 'sgfh_tp', 'sjcl_qty'];
 function transExpr(expr) {
     return expr.replace('=', '').replace('%', '/100');
 }
@@ -475,6 +476,7 @@ $(document).ready(function() {
                         } else {
                             try {
                                 data[col.field] = math.evaluate(transExpr(newValue));
+                                if (exprField.indexOf(col.field) >= 0) data[col.field + '']
                             } catch(err) {
                                 toastr.error('输入的表达式非法');
                                 SpreadJsObj.reLoadRowData(info.sheet, info.row);
@@ -1360,6 +1362,44 @@ $(document).ready(function() {
     }
     //绑定计量单元编辑事件
     const posOperationObj = {
+        /**
+         * 刷新顶部按钮是否可用
+         * @param sheet
+         * @param selections
+         */
+        refreshOperationValid: function (sheet, selection) {
+            const setObjEnable = function (obj, enable) {
+                if (enable) {
+                    obj.removeClass('disabled');
+                } else {
+                    obj.addClass('disabled');
+                }
+            };
+            const invalidAll = function () {
+                setObjEnable($('a[name=pos-opr][type=up-move]'), false);
+                setObjEnable($('a[name=pos-opr][type=down-move]'), false);
+            };
+            const sel = selection ? selection[0] : sheet.getSelections()[0];
+            const row = sel ? sel.row : -1;
+            const first = sheet.zh_data[row];
+            if (!first) {
+                invalidAll();
+                return;
+            }
+            let last = first;
+            if (sel.rowCount > 1 && first) {
+                for (let r = 1; r < sel.rowCount; r++) {
+                    const rNode = sheet.zh_data[sel.row + r];
+                    if (!rNode) break;
+                    last = rNode;
+                }
+            }
+            const preNode = sheet.zh_data[row - 1];
+            const valid = !sheet.zh_setting.readOnly;
+
+            setObjEnable($('a[name=pos-opr][type=up-move]'), valid && first && preNode);
+            setObjEnable($('a[name=pos-opr][type=down-move]'), valid && first && (sheet.zh_data.indexOf(last) < sheet.zh_data.length - 1));
+        },
         editStarting: function (e, info) {
             posOperationObj.ledgerTreeNode = SpreadJsObj.getSelectObject(ledgerSpread.getActiveSheet());
         },
@@ -1394,6 +1434,65 @@ $(document).ready(function() {
                 SpreadJsObj.loadSheetData(posSpread.getActiveSheet(), 'data', []);
             }
             posOperationObj.loadExprToInput();
+            posOperationObj.refreshOperationValid(posSpread.getActiveSheet());
+        },
+        baseOpr: function (sheet, type) {
+            const data = {
+                updateType: type === 'delete' ? type : 'update',
+                updateData: [],
+            };
+            const selection = sheet.getSelections();
+            const row = selection[0].row, count = selection[0].rowCount;
+            const first = sheet.zh_data[row];
+            if (type === 'delete') {
+                for (let iRow = 0; iRow < count; iRow++) {
+                    const posData = sheet.zh_data[iRow + row];
+                    if (posData) {
+                        data.updateData.push(sheet.zh_data[iRow + row].id);
+                    }
+                }
+            } else if (type === 'up-move') {
+                const pre = sheet.zh_data[row - 1], preUpdate = {id: pre.id};
+                for (let iRow = 0; iRow < count; iRow++) {
+                    const posData = sheet.zh_data[iRow + row];
+                    if (posData) {
+                        data.updateData.push({id: posData.id, lid: posData.lid, porder: sheet.zh_data[iRow + row - 1].porder});
+                        preUpdate.porder = posData.porder;
+                    }
+                }
+                data.updateData.push(preUpdate);
+            } else if (type === 'down-move') {
+                const next = sheet.zh_data[row + count], nextUpdate = {id: next.id};
+                for (let iRow = count - 1; iRow >= 0; iRow--) {
+                    const posData = sheet.zh_data[iRow + row];
+                    if (posData) {
+                        data.updateData.push({id: posData.id, lid: posData.lid, porder: sheet.zh_data[iRow + row + 1].porder});
+                        nextUpdate.porder = posData.porder;
+                    }
+                }
+                data.updateData.push(nextUpdate);
+
+            }
+            if (data.updateData.length > 0) {
+                postData('/tender/' + getTenderId() + '/pos/update', data, function (result) {
+                    if (type === 'delete') {
+                        pos.removeDatas(result.pos);
+                        sheet.deleteRows(row, count);
+                        const loadResult = ledgerTree.loadPostData(result.ledger);
+                        treeOperationObj.refreshTree(ledgerSpread.getActiveSheet(), loadResult);
+                        treeOperationObj.refreshOperationValid(ledgerSpread.getActiveSheet());
+                    } else {
+                        pos.updateDatas(result.pos);
+
+                        const sel = selection[0];
+                        if (sel) {
+                            sheet.setSelection(sheet.zh_data.indexOf(first), sel.col, sel.rowCount, sel.colCount);
+                            SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, sheet.zh_data.indexOf(first)]);
+                        }
+                        posOperationObj.loadCurPosData();
+                    }
+                });
+            }
         },
         /**
          * 编辑单元格响应事件
@@ -1648,6 +1747,7 @@ $(document).ready(function() {
         },
         selectionChanged: function (e, info) {
             posOperationObj.loadExprToInput();
+            posOperationObj.refreshOperationValid(posSpread.getActiveSheet());
         },
         addPegs: function (pegs) {
             if (!pegs || pegs.length <= 0) return;
@@ -1668,6 +1768,9 @@ $(document).ready(function() {
     };
     posSpread.bind(spreadNS.Events.SelectionChanged, posOperationObj.selectionChanged);
     if (!posSpreadSetting.readOnly) {
+        $('a[name="pos-opr"]').click(function () {
+            posOperationObj.baseOpr(posSpread.getActiveSheet(), this.getAttribute('type'));
+        });
         $('#pos-expr').bind('change mouseleave', function () {
             if (document.activeElement.id !== "pos-expr") return;
 
@@ -1949,8 +2052,8 @@ $(document).ready(function() {
                         searchSpread: ledgerSpread,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
                                 {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
                                 {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
                                 {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},

+ 2 - 2
app/public/js/ledger_audit.js

@@ -179,8 +179,8 @@ $(document).ready(() => {
                         searchSpread: ledgerSpread,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
                                 {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
                                 {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
                                 {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},

+ 8 - 2
app/public/js/path_tree.js

@@ -455,14 +455,20 @@ const createNewPathTree = function (type, setting) {
          * @returns {Array}
          */
         getPosterity(node) {
+            const self = this;
+            let posterity;
             if (node.full_path !== '') {
                 const reg = new RegExp('^' + node.full_path + '-');
-                return this.datas.filter(function (x) {
+                posterity = this.datas.filter(function (x) {
                     return reg.test(x.full_path);
                 });
             } else {
-                return this._recursiveGetPosterity(node);
+                posterity = this._recursiveGetPosterity(node);
             }
+            posterity.sort(function (x, y) {
+                return self.getNodeIndex(x) - self.getNodeIndex(y);
+            });
+            return posterity;
         };
         /**
          * 查询node是否是父节点的最后一个子节点

+ 117 - 16
app/public/js/revise.js

@@ -126,12 +126,12 @@ $(document).ready(() => {
                 }
             };
             const invalidAll = function () {
-                setObjEnable($('a[type=add]'), false);
-                setObjEnable($('a[type=delete]'), false);
-                setObjEnable($('a[type=up-move]'), false);
-                setObjEnable($('a[type=down-move]'), false);
-                setObjEnable($('a[type=up-level]'), false);
-                setObjEnable($('a[type=down-level]'), false);
+                setObjEnable($('a[nam=base-opr][type=add]'), false);
+                setObjEnable($('a[nam=base-opr][type=delete]'), false);
+                setObjEnable($('a[nam=base-opr][type=up-move]'), false);
+                setObjEnable($('a[nam=base-opr][type=down-move]'), false);
+                setObjEnable($('a[nam=base-opr][type=up-level]'), false);
+                setObjEnable($('a[nam=base-opr][type=down-level]'), false);
             };
             const sel = selection ? selection[0] : sheet.getSelections()[0];
             const row = sel ? sel.row : -1;
@@ -165,20 +165,20 @@ $(document).ready(() => {
             const preNode = tree.getPreSiblingNode(first);
             const valid = !sheet.zh_setting.readOnly;
 
-            setObjEnable($('a[type=add]'), valid && first && first.level > 1);
-            setObjEnable($('a[type=delete]'), valid && first && sameParent && first.level > 1 && !nodeUsed);
-            setObjEnable($('a[type=up-move]'), valid && first && sameParent && first.level > 1 && preNode);
-            setObjEnable($('a[type=down-move]'), valid && first && sameParent && first.level > 1 && !tree.isLastSibling(last));
+            setObjEnable($('a[nam=base-opr][type=add]'), valid && first && first.level > 1);
+            setObjEnable($('a[nam=base-opr][type=delete]'), valid && first && sameParent && first.level > 1 && !nodeUsed);
+            setObjEnable($('a[nam=base-opr][type=up-move]'), valid && first && sameParent && first.level > 1 && preNode);
+            setObjEnable($('a[nam=base-opr][type=down-move]'), valid && first && sameParent && first.level > 1 && !tree.isLastSibling(last));
             if (isTz) {
                 const posRange = last ? pos.getLedgerPos(last.id) : [];
-                setObjEnable($('a[type=up-level]'), valid && first && sameParent && tree.getParent(first) && !nodeUsed
+                setObjEnable($('a[nam=base-opr][type=up-level]'), valid && first && sameParent && tree.getParent(first) && !nodeUsed
                     && first.level > 2 && ((!posRange || posRange.length === 0) || tree.isLastSibling(last)));
                 const preNodePosRange = preNode ? pos.getLedgerPos(preNode.id) : [];
-                setObjEnable($('a[type=down-level]'), valid && first && sameParent && !nodeUsed
+                setObjEnable($('a[nam=base-opr][type=down-level]'), valid && first && sameParent && !nodeUsed
                     && first.level > 1 && preNode && (!preNodePosRange || preNodePosRange.length === 0));
             } else {
-                setObjEnable($('#up-level'), valid && first && sameParent && first.level > 2 && tree.getParent(first));
-                setObjEnable($('#down-level'), valid && first && sameParent && first.level > 1 && preNode);
+                setObjEnable($('a[nam=base-opr][type=up-level]'), valid && first && sameParent && first.level > 2 && tree.getParent(first));
+                setObjEnable($('a[nam=base-opr][type=down-level]'), valid && first && sameParent && first.level > 1 && preNode);
             }
             setObjEnable($('#cut'), valid);
             setObjEnable($('#paste'), valid);
@@ -1031,6 +1031,39 @@ $(document).ready(() => {
     }
     // 计量单元 相关方法&绑定spreadjs事件
     const posSpreadObj = {
+        refreshOperationValid: function (sheet, selection) {
+            const setObjEnable = function (obj, enable) {
+                if (enable) {
+                    obj.removeClass('disabled');
+                } else {
+                    obj.addClass('disabled');
+                }
+            };
+            const invalidAll = function () {
+                setObjEnable($('a[name=pos-opr][type=up-move]'), false);
+                setObjEnable($('a[name=pos-opr][type=down-move]'), false);
+            };
+            const sel = selection ? selection[0] : sheet.getSelections()[0];
+            const row = sel ? sel.row : -1;
+            const first = sheet.zh_data[row];
+            if (!first) {
+                invalidAll();
+                return;
+            }
+            let last = first;
+            if (sel.rowCount > 1 && first) {
+                for (let r = 1; r < sel.rowCount; r++) {
+                    const rNode = sheet.zh_data[sel.row + r];
+                    if (!rNode) break;
+                    last = rNode;
+                }
+            }
+            const preNode = sheet.zh_data[row - 1];
+            const valid = !sheet.zh_setting.readOnly;
+
+            setObjEnable($('a[name=pos-opr][type=up-move]'), valid && first && preNode);
+            setObjEnable($('a[name=pos-opr][type=down-move]'), valid && first && (sheet.zh_data.indexOf(last) < sheet.zh_data.length - 1));
+        },
         loadExprToInput: function () {
             const sel = posSheet.getSelections()[0];
             if (!sel) return;
@@ -1062,6 +1095,70 @@ $(document).ready(() => {
             }
             SpreadJsObj.resetFieldReadOnly(posSheet);
             posSpreadObj.loadExprToInput();
+            posSpreadObj.refreshOperationValid(posSheet);
+        },
+        baseOpr: function (sheet, type) {
+            const data = {
+                postType: 'pos',
+                posPostType: type === 'delete' ? type : 'update',
+                postData: [],
+            };
+            const selection = sheet.getSelections();
+            const row = selection[0].row, count = selection[0].rowCount;
+            const first = sheet.zh_data[row];
+            if (type === 'delete') {
+                for (let iRow = 0; iRow < count; iRow++) {
+                    const posData = sheet.zh_data[iRow + row];
+                    if (posData) {
+                        if (posData.used) {
+                            toastr.error('"' + posData.name + '"已计量,请勿删除');
+                            return;
+                        }
+                        data.postData.push(sheet.zh_data[iRow + row].id);
+                    }
+                }
+            } else if (type === 'up-move') {
+                const pre = sheet.zh_data[row - 1], preUpdate = {id: pre.id};
+                for (let iRow = 0; iRow < count; iRow++) {
+                    const posData = sheet.zh_data[iRow + row];
+                    if (posData) {
+                        data.postData.push({id: posData.id, lid: posData.lid, porder: sheet.zh_data[iRow + row - 1].porder});
+                        preUpdate.porder = posData.porder;
+                    }
+                }
+                data.postData.push(preUpdate);
+            } else if (type === 'down-move') {
+                const next = sheet.zh_data[row + count], nextUpdate = {id: next.id};
+                for (let iRow = count - 1; iRow >= 0; iRow--) {
+                    const posData = sheet.zh_data[iRow + row];
+                    if (posData) {
+                        data.postData.push({id: posData.id, lid: posData.lid, porder: sheet.zh_data[iRow + row + 1].porder});
+                        nextUpdate.porder = posData.porder;
+                    }
+                }
+                data.postData.push(nextUpdate);
+
+            }
+            if (data.postData.length > 0) {
+                postData(window.location.pathname + '/update', data, function (result) {
+                    if (type === 'delete') {
+                        pos.removeDatas(result.pos);
+                        sheet.deleteRows(row, count);
+                        const loadResult = billsTree.loadPostData(result.ledger);
+                        billsTreeSpreadObj.refreshTree(billsSheet, loadResult);
+                        billsTreeSpreadObj.refreshOperationValid(billsSheet);
+                        posSpreadObj.refreshOperationValid(posSheet);
+                    } else {
+                        pos.updateDatas(result.pos);
+                        const sel = selection[0];
+                        if (sel) {
+                            sheet.setSelection(sheet.zh_data.indexOf(first), sel.col, sel.rowCount, sel.colCount);
+                            SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, sheet.zh_data.indexOf(first)]);
+                        }
+                        posSpreadObj.loadCurPosData();
+                    }
+                });
+            }
         },
         editStarting: function (e, info) {
             posSpreadObj.billsNode = SpreadJsObj.getSelectObject(billsSheet);
@@ -1335,6 +1432,7 @@ $(document).ready(() => {
         },
         selectionChanged: function (e, info) {
             posSpreadObj.loadExprToInput();
+            posSpreadObj.refreshOperationValid(posSheet);
         },
         addPegs: function (pegs) {
             if (!pegs || pegs.length <= 0) return;
@@ -1355,6 +1453,9 @@ $(document).ready(() => {
     };
     posSpread.bind(spreadNS.Events.SelectionChanged, posSpreadObj.selectionChanged);
     if (!readOnly && isTz) {
+        $('a[name="pos-opr"]').click(function () {
+            posSpreadObj.baseOpr(posSheet, this.getAttribute('type'));
+        });
         $('#pos-expr').bind('change mouseleave', function () {
             if (this.readOnly) return;
             if (document.activeElement.id !== 'pos-expr') return;
@@ -2107,8 +2208,8 @@ $(document).ready(() => {
                         searchSpread: billsSpread,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
                                 {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
                                 {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
                                 {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},

+ 2 - 2
app/public/js/revise_history.js

@@ -226,8 +226,8 @@ $(document).ready(() => {
                         searchSpread: billsSpread,
                         resultSpreadSetting: {
                             cols: [
-                                {title: '项目节编号', field: 'code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
-                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 120, formatter: '@', readOnly: true},
+                                {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@', readOnly: true},
+                                {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
                                 {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@', readOnly: true},
                                 {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@', readOnly: true},
                                 {title: '单价', field: 'unit_price', hAlign: 2, width: 50, readOnly: true},

+ 56 - 15
app/public/js/shares/cs_tools.js

@@ -275,12 +275,27 @@ const showSideTools = function (show) {
         if (!setting.searchRangeStr) setting.searchRangeStr = '项目节编号/清单编号/名称';
         const resultId = setting.id + '-search-result';
         const obj = $(setting.selector);
+        let filter = [];
+        if (setting.searchOver || setting.searchEmpty) {
+            filter.push('<select class="form-control form-control-sm" id="search-filter">');
+            filter.push('<option value="">台账</option>');
+            if (setting.searchOver) filter.push('<option value="over">超计</option>');
+            if (setting.searchEmpty) filter.push('<option value="less">漏计</option>');
+            filter.push('</select>');
+            // filter.push('<div class="input-group-prepend">');
+            // filter.push('<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">台帐</button>');
+            // filter.push('<div class="dropdown-menu">');
+            // filter.push('<a class="dropdown-item" href="javascripty: void(0)" id="search-bills">台账</a>');
+            // filter.push('<a class="dropdown-item" href="javascripty: void(0)" id="search-over">超计</a>');
+            // filter.push('<a class="dropdown-item" href="javascripty: void(0)" id="search-less">漏计</a>');
+            // filter.push('</div>');
+            // filter.push('</div>');
+        }
         obj.html(
             '                        <div class="sjs-bar">\n' +
             '                            <div class="input-group input-group-sm pb-1">\n' +
             '                                <div class="input-group-prepend">\n' +
-            (setting.searchOver ? '                                    <div class="input-group-text"><input type="radio" name="searchType" id="over"> 超计</div>\n' : '') +
-            (setting.searchEmpty ? '                                    <div class="input-group-text"><input type="radio" name="searchType" id="empty"> 漏计</div>\n' : '') +
+            filter.join('') +
             '                                </div>' +
             '                                <input id="searchKeyword" type="text" class="form-control" placeholder="可查找 ' + setting.searchRangeStr + '" aria-label="Recipient\'s username" aria-describedby="button-addon2">\n' +
             '                                <div class="input-group-append">\n' +
@@ -297,6 +312,16 @@ const showSideTools = function (show) {
         SpreadJsObj.forbiddenSpreadContextMenu('#' + resultId, resultSpread);
         const searchSheet = setting.searchSpread.getActiveSheet();
         let searchResult = [];
+        const search = function () {
+            const filter = $('#search-filter').val();
+            if (filter === 'over') {
+                searchOver();
+            } else if (filter === 'less') {
+                searchLess();
+            } else {
+                searchBills();
+            }
+        };
         const searchBills = function () {
             const keyword = $('#searchKeyword', obj).val();
             searchResult = [];
@@ -320,42 +345,60 @@ const showSideTools = function (show) {
             }
         };
         const searchOver = function () {
+            const keyword = $('#searchKeyword', obj).val();
             searchResult = [];
             const sortData = SpreadJsObj.getSortData(searchSheet);
             for (const node of sortData) {
                 if (node.children && node.children.length > 0) continue;
                 if (setting.checkOver && setting.checkOver(node)) {
-                    const data = JSON.parse(JSON.stringify(node));
-                    data.visible = true;
-                    searchResult.push(data);
+                    if (!keyword ||
+                        (node.code && node.code.indexOf(keyword) > -1) ||
+                        (node.b_code && node.b_code.indexOf(keyword) > -1) ||
+                        (node.name && node.name.indexOf(keyword) > -1)) {
+                        const data = JSON.parse(JSON.stringify(node));
+                        data.visible = true;
+                        searchResult.push(data);
+                    }
                 }
             }
             calculateCompletePercent(searchResult);
             SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
         };
         const searchEmpty = function () {
+            const keyword = $('#searchKeyword', obj).val();
             searchResult = [];
             const sortData = SpreadJsObj.getSortData(searchSheet);
             for (const node of sortData) {
                 if (node.children && node.children.length > 0) continue;
                 if (setting.checkEmpty && setting.checkEmpty(node)) {
-                    const data = JSON.parse(JSON.stringify(node));
-                    data.visible = true;
-                    searchResult.push(data);
+                    if (!keyword ||
+                        (node.code && node.code.indexOf(keyword) > -1) ||
+                        (node.b_code && node.b_code.indexOf(keyword) > -1) ||
+                        (node.name && node.name.indexOf(keyword) > -1)) {
+                        const data = JSON.parse(JSON.stringify(node));
+                        data.visible = true;
+                        searchResult.push(data);
+                    }
                 }
             }
             calculateCompletePercent(searchResult);
             SpreadJsObj.loadSheetData(resultSpread.getActiveSheet(), 'data', searchResult);
         };
         const searchLess = function () {
+            const keyword = $('#searchKeyword', obj).val();
             searchResult = [];
             const sortData = SpreadJsObj.getSortData(searchSheet);
             for (const node of sortData) {
                 if (node.children && node.children.length > 0) continue;
                 if (setting.checkLess && setting.checkLess(node)) {
-                    const data = JSON.parse(JSON.stringify(node));
-                    data.visible = true;
-                    searchResult.push(data);
+                    if (!keyword ||
+                        (node.code && node.code.indexOf(keyword) > -1) ||
+                        (node.b_code && node.b_code.indexOf(keyword) > -1) ||
+                        (node.name && node.name.indexOf(keyword) > -1)) {
+                        const data = JSON.parse(JSON.stringify(node));
+                        data.visible = true;
+                        searchResult.push(data);
+                    }
                 }
             }
             calculateCompletePercent(searchResult);
@@ -363,11 +406,9 @@ const showSideTools = function (show) {
         };
 
         $('input', obj).bind('keydown', function (e) {
-            if (e.keyCode == 13) searchBills();
+            if (e.keyCode == 13) search();
         });
-        $('button', obj).bind('click', () => {searchBills()});
-        $('#over', obj).bind('change', () => {searchOver()});
-        $('#empty', obj).bind('change', () => {searchLess()});
+        $('button', obj).bind('click', () => {search()});
         resultSpread.getActiveSheet().bind(spreadNS.Events.CellDoubleClick, function (e, info) {
             const sheet = info.sheet;
             const data = sheet.zh_data;

+ 92 - 11
app/public/js/stage.js

@@ -1758,6 +1758,9 @@ $(document).ready(() => {
             this.detailObj = {
                 selectionChanged: function (e, info) {
                     self.reLoadDetailData();
+                    if (!info.oldSelections || !info.oldSelections[0] || info.oldSelections[0].row !== info.newSelections[0].row) {
+                        self.loadLocateInfo();
+                    }
                 },
                 editEnded: function(e, info) {
                     if (info.sheet.zh_setting) {
@@ -1776,8 +1779,14 @@ $(document).ready(() => {
                                 updateData.name = data.name;
                                 updateData.unit = data.unit;
                                 updateData.unit_price = data.unit_price;
+                                updateData.pid = data.pid;
                                 updateData.pos_name = data.pos_name;
                             }
+                            if (data.custom_define.indexOf('doc_code') === -1) {
+                                updateData.custom_define = data.custom_define;
+                                updateData.custom_define.push('doc_code');
+                                updateData.custom_define = updateData.custom_define.join(',');
+                            }
                             updateData.doc_code = info.editingText === null ? '' : info.editingText;
                             postData(window.location.pathname + '/detail/save', updateData, function (result) {
                                 stageIm.loadUpdateDetailData(result);
@@ -1816,8 +1825,14 @@ $(document).ready(() => {
                                     updateData.name = data.name;
                                     updateData.unit = data.unit;
                                     updateData.unit_price = data.unit_price;
+                                    updateData.pid = data.pid;
                                     updateData.pos_name = data.pos_name;
                                 }
+                                if (data.custom_define.indexOf('doc_code') === -1) {
+                                    updateData.custom_define = data.custom_define;
+                                    updateData.custom_define.push('doc_code');
+                                    updateData.custom_define = updateData.custom_define.join(',');
+                                }
                                 updateData.doc_code = info.sheet.getText(curRow, info.cellRange.col).replace('\n', '');
                                 datas.push(updateData);
                             }
@@ -1882,6 +1897,7 @@ $(document).ready(() => {
                                 updateData.name = data.name;
                                 updateData.unit = data.unit;
                                 updateData.unit_price = data.unit_price;
+                                updateData.pid = data.pid;
                                 updateData.pos_name = data.pos_name;
                             }
                             if (regRst) {
@@ -1889,6 +1905,11 @@ $(document).ready(() => {
                             } else {
                                 updateData.doc_code = text.replace('\n', '');
                             }
+                            if (data.custom_define.indexOf('doc_code') === -1) {
+                                updateData.custom_define = data.custom_define;
+                                updateData.custom_define.push('doc_code');
+                                updateData.custom_define = updateData.custom_define.join(',');
+                            }
                             datas.push(updateData);
                         }
                     }
@@ -1913,6 +1934,7 @@ $(document).ready(() => {
 
             this._initImTypeSetRela();
             this._initModifyDetail();
+            this._initLocateRela();
             // 草图相关
             this._initImageRela();
             this.reBuildImData();
@@ -1953,7 +1975,7 @@ $(document).ready(() => {
                 $('#type-title-contract').text('本期合同计量数量');
                 $('#type-title-qc').text('本期变更计量数量');
             }
-            if (stage.im_type === imType.bb.value) {
+            if (stage.im_type === imType.bb.value || stage.im_type === imType.bw.value) {
                 $('#show-jldy').parent().show();
                 $('#jldy').parent().show();
                 $('#show-xm-name').parent().hide();
@@ -2037,7 +2059,7 @@ $(document).ready(() => {
                         $('#type-title-contract').text('本期合同计量数量');
                         $('#type-title-qc').text('本期变更计量数量');
                     }
-                    if (stage.im_type === imType.bb.value) {
+                    if (stage.im_type === imType.bb.value || stage.im_type === imType.bw.value) {
                         $('#show-jldy').parent().show();
                         $('#jldy').parent().show();
                         $('#show-xm-name').parent().hide();
@@ -2071,7 +2093,7 @@ $(document).ready(() => {
                         defaultRowHeight: 21,
                         headerFont: '12px 微软雅黑',
                         font: '12px 微软雅黑',
-                    }
+                    };
                     sjsSettingObj.setFxTreeStyle(setting, sjsSettingObj.FxTreeStyle.jz);
                     SpreadJsObj.initSheet(self.gsSpread.getActiveSheet(), setting);
                     self.gsSpread.bind(spreadNS.Events.ButtonClicked, function (e, info) {
@@ -2192,6 +2214,35 @@ $(document).ready(() => {
                 });
             });
         }
+        _initLocateRela() {
+            const self = this;
+            $('#im-locate2bills').click(function () {
+                const curIndex = parseInt($('#im-locate-info')[0].innerText.split('/')[0]);
+                const select = SpreadJsObj.getSelectObject(self.spread.getActiveSheet());
+                if (select && select.source) {
+                    SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), select.source[curIndex-1].id, true);
+                }
+            });
+            $('#im-locate-pre').click(function () {
+                const curIndex = parseInt($('#im-locate-info')[0].innerText.split('/')[0]);
+                const select = SpreadJsObj.getSelectObject(self.spread.getActiveSheet());
+                if (select && select.source) {
+                    const targetIndex = math.max(curIndex-1, 1);
+                    SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), select.source[targetIndex-1].id, true);
+                    $('#im-locate-info')[0].innerText = targetIndex + '/' + select.source.length;
+                }
+            });
+            $('#im-locate-next').click(function () {
+                const curIndex = parseInt($('#im-locate-info')[0].innerText.split('/')[0]);
+                const select = SpreadJsObj.getSelectObject(self.spread.getActiveSheet());
+                if (select && select.source) {
+                    const targetIndex = math.min(curIndex+1, select.source.length);
+                    SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), select.source[targetIndex-1].id, true);
+                    $('#im-locate-info')[0].innerText = targetIndex + '/' + select.source.length;
+                }
+
+            });
+        }
         _initModifyDetail() {
             const self = this;
             // 编辑
@@ -2209,9 +2260,11 @@ $(document).ready(() => {
                     if (!org[field]) {
                         if (newValue !== '') {
                             update[field] = newValue;
+                            if (data.custom_define.indexOf(field) === -1) update.custom_define.push(field);
                         }
                     } else if (newValue !== org[field]){
                         update[field] = newValue;
+                        if (data.custom_define.indexOf(field) === -1) update.custom_define.push(field);
                     }
                 }
 
@@ -2219,19 +2272,31 @@ $(document).ready(() => {
                 const updateData = {lid: data.lid, pid: data.pid};
                 if (data.uuid) {
                     updateData.uuid = data.uuid;
+                    updateData.custom_define = data.custom_define;
                 } else {
                     updateData.code = data.code;
                     updateData.name = data.name;
                     updateData.unit = data.unit;
                     updateData.unit_price = data.unit_price;
+                    updateData.pid = data.pid;
                     updateData.pos_name = data.pos_name;
-                }
-                updateData.bw = $('#bw-name').val();
-                updateData.peg = $('#peg').val();
-                updateData.xm = $('#xm-name').val();
-                updateData.position = $('#position').val();
-                updateData.drawing_code = $('#drawing-code').val();
-                updateData.calc_memo = $('#calc-memo').val();
+                    updateData.custom_define = [];
+                }
+                check('bw', $('#bw-name'), data, updateData);
+                check('peg', $('#peg'), data, updateData);
+                check('xm', $('#xm'), data, updateData);
+                check('position', $('#position'), data, updateData);
+                check('jldy', $('#jldy'), data, updateData);
+                check('drawing_code', $('#drawing-code'), data, updateData);
+                check('calc_memo', $('#calc-memo'), data, updateData);
+                updateData.custom_define = updateData.custom_define.join(',');
+                // updateData.bw = $('#bw-name').val();
+                // updateData.peg = $('#peg').val();
+                // updateData.xm = $('#xm-name').val();
+                // updateData.position = $('#position').val();
+                // updateData.jldy = $('#jldy').val();
+                // updateData.drawing_code = $('#drawing-code').val();
+                // updateData.calc_memo = $('#calc-memo').val();
                 postData(window.location.pathname + '/detail/save', updateData, function (result) {
                     stageIm.loadUpdateDetailData(result);
                     self.reLoadDetailData();
@@ -2376,8 +2441,14 @@ $(document).ready(() => {
                         updateData.name = data.name;
                         updateData.unit = data.unit;
                         updateData.unit_price = data.unit_price;
+                        updateData.pid = data.pid;
                         updateData.pos_name = data.pos_name;
                     }
+                    if (data.custom_define.indexOf('calc_img') === -1) {
+                        updateData.custom_define = data.custom_define;
+                        updateData.custom_define.push('calc_img');
+                        updateData.custom_define = updateData.custom_define.join(',');
+                    }
                     updateData.img = canvas.toDataURL('image/png');
                     updateData.imgInfo = itemInfo;
                     postData(window.location.pathname + '/detail/merge-img', updateData, function (result) {
@@ -2406,6 +2477,7 @@ $(document).ready(() => {
             const imData = stageIm.buildImData();
             SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, imData);
             this.reLoadDetailData();
+            this.loadLocateInfo();
         }
         loadStageLedgerUpdateData(data) {
             const imData = stageIm.loadUpdateLedgerData(data);
@@ -2422,6 +2494,15 @@ $(document).ready(() => {
             SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, imData);
             this.reLoadDetailData();
         }
+        loadLocateInfo() {
+            const select = SpreadJsObj.getSelectObject(this.sheet);
+            if (select.source.length > 1) {
+                $('#im-locate2bills').next().show();
+            } else {
+                $('#im-locate2bills').next().hide();
+            }
+            $('#im-locate-info')[0].innerText = '1/' + select.source.length;
+        }
         reLoadDetailData() {
             const data = SpreadJsObj.getSelectObject(this.spread.getActiveSheet());
 
@@ -2615,7 +2696,7 @@ $(document).ready(() => {
                     searchEmpty: true,
                     resultSpreadSetting: {
                         cols: [
-                            {title: '项目节编号', field: 'code', hAlign: 0, width: 120, formatter: '@'},
+                            {title: '项目节编号', field: 'code', hAlign: 0, width: 90, formatter: '@'},
                             {title: '清单编号', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
                             {title: '名称', field: 'name', width: 150, hAlign: 0, formatter: '@'},
                             {title: '单位', field: 'unit', width: 50, hAlign: 1, formatter: '@'},

+ 66 - 21
app/public/js/stage_im.js

@@ -9,7 +9,7 @@
  */
 
 const stageIm = (function () {
-    const imFields = ['uuid', 'doc_code', 'peg', 'bw', 'xm', 'drawing_code', 'calc_memo', 'calc_img', 'position'];
+    const imFields = ['uuid', 'doc_code', 'peg', 'bw', 'xm', 'drawing_code', 'calc_memo', 'calc_img', 'position', 'jldy'];
     const splitChar = '-';
     const mergeChar = ';';
     let stage, imType, decimal, details, changes, ImData, pre;
@@ -265,8 +265,9 @@ const stageIm = (function () {
                 (!im.pos_name || im.pos_name === d.pos_name);
         });
         if (cd) {
+            im.custom_define = cd.custom_define ? cd.custom_define.split(',') : imFields;
             _.assignInWith(im, cd, function (oV, sV, key) {
-                return (imFields.indexOf(key) > -1 && sV !== undefined && sV !== null) ? sV : oV;
+                return (im.custom_define.indexOf(key) > -1 && sV !== undefined && sV !== null) ? sV : oV;
             });
         }
     }
@@ -283,6 +284,9 @@ const stageIm = (function () {
             }
             im.calc_memo = memo.join('\n');
         } else if (im.gclBills && im.gclBills.length > 0) {
+            im.gclBills.sort(function (x, y) {
+                return compareCode(x.b_code, y.b_code);
+            });
             const memo = [];
             for (const [i, b] of im.gclBills.entries()) {
                 if (b.pos && b.pos.length > 0) {
@@ -428,6 +432,8 @@ const stageIm = (function () {
                 peg: peg ? getPegStr(peg.name) : '', drawing_code: getDrawingCode(node),
                 position: '',
                 lIndex: nodeIndex,
+                custom_define: [],
+                source: [{id: node.ledger_id, code: node.code, b_code: node.b_code}],
             };
             if (stage.im_gather && node.check) {
                 im.bw = getZlGatherBw(node, peg);
@@ -445,6 +451,31 @@ const stageIm = (function () {
         }
     }
 
+    function addBwBillsGclBills(im, bills) {
+        if (!im.gclBills) im.gclBills = [];
+        let gcl = im.gclBills.find(function (x) {
+            return (!bills.b_code || bills.b_code === x.b_code) &&
+                (!bills.name || bills.name === x.name) &&
+                (!bills.unit || bills.unit === x.unit) &&
+                checkZero(ZhCalc.sub(bills.unit_price, x.unit_price));
+        });
+        if (!gcl) {
+            gcl = {b_code: bills.b_code, name: bills.name, unit: bills.unit, unit_price: bills.unit_price};
+            im.gclBills.push(gcl);
+        }
+        gcl.contract_jl = ZhCalc.add(gcl.contract_jl, bills.contract_jl);
+        gcl.qc_jl = ZhCalc.add(gcl.qc_jl, bills.qc_jl);
+        gcl.jl = ZhCalc.add(gcl.jl, bills.jl);
+    }
+    function calculateBwBillsIm(im) {
+        im.contract_jl = 0;
+        im.qc_jl = 0;
+        for (const b of im.gclBills) {
+            im.contract_jl = ZhCalc.add(im.contract_jl, ZhCalc.mul(b.contract_jl, b.unit_price, decimal.tp));
+            im.qc_jl = ZhCalc.add(im.qc_jl, ZhCalc.mul(b.qc_jl, b.unit_price, decimal.tp));
+        }
+        im.jl = ZhCalc.add(im.contract_jl, im.qc_jl);
+    }
     function generateBwBillsImData (node) {
         if (node.gather_tp) {
             const nodeIndex = gsTree.getNodeIndex(node);
@@ -459,6 +490,8 @@ const stageIm = (function () {
                 lIndex: nodeIndex,
                 bw: bw, jldy: node.name,
                 changes: [], gclBills: [],
+                custom_define: [],
+                source: [{id: node.ledger_id, code: node.code, b_code: node.b_code}],
             };
             checkCustomDetail(imDefault);
             for (const p of posterity) {
@@ -481,28 +514,28 @@ const stageIm = (function () {
                                 lIndex: nodeIndex,
                                 bw: bw, jldy: pp.name,
                                 changes: [], gclBills: [],
+                                custom_define: [],
+                                source: [],
                             };
                             nodeImData.push(im);
                             checkCustomDetail(im);
                         }
+                        im.source.push({id: p.ledger_id, code: p.code, b_code: p.b_code});
 
                         for (const c of changes) {
                             if (c.lid === p.id && c.pid == pp.id && c.qty && c.qty !== 0) {
                                 im.changes.push(c);
                             }
                         }
-
-                        im.jl = ZhCalc.add(im.jl, ZhCalc.mul(pp.gather_qty, p.unit_price, decimal.tp));
-                        im.contract_jl = ZhCalc.add(im.contract_jl, ZhCalc.mul(pp.contract_qty, p.unit_price, decimal.tp));
-                        im.qc_jl = ZhCalc.add(im.qc_jl, ZhCalc.mul(pp.qc_qty, p.unit_price, decimal.tp));
-                        if (pp.drawing_code) im.drawing_code.push(pp.drawing_code);
-                        if (pp.position) im.position.push(pp.position);
-
-                        im.gclBills.push({
-                            bid: p.id,
-                            b_code: p.b_code, name: p.name, unit: p.unit,
+                        addBwBillsGclBills(im, {
+                            b_code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
                             jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty
                         });
+
+                        if (pp.drawing_code && im.drawing_code instanceof Array)
+                            im.drawing_code.push(pp.drawing_code);
+                        if (pp.position && im.position instanceof Array)
+                            im.position.push(pp.position);
                     }
                 } else {
                     for (const c of changes) {
@@ -511,23 +544,23 @@ const stageIm = (function () {
                         }
                     }
 
-                    imDefault.jl = ZhCalc.add(imDefault.jl, p.gather_qty);
                     imDefault.contract_jl = ZhCalc.add(imDefault.contract_jl, p.contract_qty);
                     imDefault.qc_jl = ZhCalc.add(imDefault.qc_jl, p.qc_qty);
 
-                    imDefault.gclBills.push({
-                        bid: p.id,
-                        b_code: p.b_code, name: p.name, unit: p.unit,
-                        jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_qty
+                    addBwBillsGclBills(imDefault, {
+                        b_code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
+                        jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_jl,
                     });
                 }
             }
-            if (imDefault.jl) {
+            if (imDefault.contract_jl || imDefault.qc_jl) {
+                imDefault.jl = ZhCalc.add(imDefault.contract_jl, imDefault.qc_jl);
                 ImData.push(imDefault);
             }
             for (const im of nodeImData) {
-                im.drawing_code = im.drawing_code.join(mergeChar);
-                im.position = im.position.join(mergeChar);
+                calculateBwBillsIm(im);
+                im.drawing_code = _.uniq(im.drawing_code).join(mergeChar);
+                im.position = _.uniq(im.position).join(mergeChar);
                 ImData.push(im);
             }
         }
@@ -621,6 +654,8 @@ const stageIm = (function () {
                     peg: peg ? getPegStr(peg.name) : '',
                     position: '',
                     lIndex: nodeIndex,
+                    custom_define: [],
+                    source: [],
                 };
                 if (stage.im_gather && node.check) {
                     im.bw = getZlGatherBw(node, peg);
@@ -635,6 +670,7 @@ const stageIm = (function () {
                 checkCustomDetail(im);
                 ImData.push(im);
             }
+            im.source.push({id: p.ledger_id, code: p.code, b_code: p.b_code});
             //if (!stage.im_gather || !node.check) {
                 generateZlLeafXmjData(p, im, 'gather_qty');
             //}
@@ -661,13 +697,15 @@ const stageIm = (function () {
                         lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price, pid: pp.id,
                         jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty,
                         //im_code: getNewImCode(),
-                        bw: bw,
+                        bw: bw, jldy: pp.name,
                         peg: CheckPeg(pp.name) ? getPegStr(pp.name) : (peg ? getPegStr(peg.name) : ''),
                         xm: pp.name,
                         drawing_code: pp.drawing_code,
                         changes: [],
                         position: pp.position,
                         lIndex: nodeIndex,
+                        custom_define: [],
+                        source: [{id: p.ledger_id, code: p.code, b_code: p.b_code}],
                     };
                     im.calc_memo = '本期计量:' + (checkZero(im.jl) ? 0 : im.jl) + ' ' + im.unit;
                     checkCustomDetail(im);
@@ -694,6 +732,8 @@ const stageIm = (function () {
                     changes: [],
                     position: '',
                     lIndex: gsTree.getNodeIndex(node),
+                    custom_define: [],
+                    source: [{id: p.ledger_id, code: p.code, b_code: p.b_code}],
                 };
                 im.calc_memo = '本期计量:' + (checkZero(im.jl) ? 0 : im.jl) + ' ' + im.unit;
                 checkCustomDetail(im);
@@ -752,6 +792,11 @@ const stageIm = (function () {
             });
         }
         for (const [i, im] of ImData.entries()) {
+            if (im.source.length > 1) {
+                im.source.sort(function (x, y) {
+                    return compareCode(x.b_code, y.b_code);
+                });
+            }
             getCalcMemo(im);
             getChangeInfo(im);
             im.im_code = pre + getNumberFormat(stage.order, 2) + splitChar + getNumberFormat(i + 1, 3)

+ 2 - 2
app/public/js/stage_pay.js

@@ -399,7 +399,7 @@ $(document).ready(() => {
             const num = text ? _.toNumber(text) : null;
             let expr = text ? (num ? null : text) : null;
             expr = expr ? $.trim(expr).replace('\t', '').replace('=', '').toLowerCase(): null;
-            const [valid, msg] = this._checkExprValid(expr, ['bqwc', 'ybbqwc']);
+            const [valid, msg] = this._checkExprValid(expr, ['bqwc', 'ybbqwc', 'bqht', 'bqbg']);
             if (!valid) return [valid, msg];
 
             if (payBase.isStarted(payNode)) {
@@ -425,7 +425,7 @@ $(document).ready(() => {
             const num = text ? _.toNumber(text) : null;
             let expr = text ? (num ? null : text) : null;
             expr = expr ? $.trim(expr).replace('\t', '').replace('=', '').toLowerCase(): null;
-            const [valid, msg] = this._checkExprValid(expr, ['bqwc', 'ybbqwc']);
+            const [valid, msg] = this._checkExprValid(expr, ['bqwc', 'ybbqwc', 'bqht', 'bqbg']);
             if (!valid) return [valid, msg];
 
             if (payBase.isStarted(payNode)) {

+ 1 - 1
app/public/report/js/rpt_custom.js

@@ -267,7 +267,7 @@ const rptCustomObj = (function () {
             STAGE_AUDIT = result.stageAudit;
             rptSignatureHelper.originalRoleRelList = zTreeOprObj._parseRoleRelList(result.signatureRelInfo[0].rel_content);
             if (current_stage_status === 3) {
-                rptSignatureHelper.mergeSignDate(pageRst, ROLE_REL_LIST);
+                rptSignatureHelper.mergeSignDate(pageRst, ROLE_REL_LIST, true);
                 rptSignatureHelper.mergeSignature(pageRst, ROLE_REL_LIST);
                 rptSignatureHelper.mergeSignAudit(pageRst, ROLE_REL_LIST, STAGE_AUDIT);
             }

+ 1 - 1
app/public/report/js/rpt_jspdf.js

@@ -59,7 +59,7 @@ let JpcJsPDFHelper = {
 
         let newPageMergeBand = private_getIniPageMergeBorder(pageObj[JV.BAND_PROP_MERGE_BAND]);
         if (current_stage_status === 3) {
-            rptSignatureHelper.mergeSignDate(pageObj, signatureRelArr);
+            rptSignatureHelper.mergeSignDate(pageObj, signatureRelArr, false);
             // rptSignatureHelper.mergeSignature(pageObj, signatureRelArr); // 这里merge的意义不大
             rptSignatureHelper.mergeSignAudit(pageObj, signatureRelArr, signAuditArr);
         }

+ 2 - 1
app/public/report/js/rpt_main.js

@@ -312,7 +312,7 @@ let zTreeOprObj = {
                     ROLE_REL_LIST = me._parseRoleRelList(result.signatureRelInfo[0].rel_content);
                     rptSignatureHelper.originalRoleRelList = me._parseRoleRelList(result.signatureRelInfo[0].rel_content);
                     if (current_stage_status === 3) {
-                        rptSignatureHelper.mergeSignDate(pageRst, ROLE_REL_LIST);
+                        rptSignatureHelper.mergeSignDate(pageRst, ROLE_REL_LIST, true);
                         rptSignatureHelper.mergeSignature(pageRst, ROLE_REL_LIST);
                         rptSignatureHelper.mergeSignAudit(pageRst, ROLE_REL_LIST, STAGE_AUDIT);
                     }
@@ -601,6 +601,7 @@ let rptControlObj = {
                     function(result){
                         // closeWaitingView();
                         $.bootstrapLoading.end();
+                        STAGE_AUDIT = result.stageAudit;
                         let pageSize = rptControlObj.getCurrentPageSize();
                         for (const signatureRel of result.signatureRelInfo) {
                             signatureRelArr.push(JSON.parse(signatureRel.rel_content));

+ 1 - 1
app/public/report/js/rpt_print.js

@@ -48,7 +48,7 @@ let rptPrintHelper = {
                         // }
 
                         if (current_stage_status === 3) {
-                            rptSignatureHelper.mergeSignDate(result.data[idx], singleSignatureRelArr);
+                            rptSignatureHelper.mergeSignDate(result.data[idx], singleSignatureRelArr, false);
                             rptSignatureHelper.mergeSignature(result.data[idx], singleSignatureRelArr);
                             rptSignatureHelper.mergeSignAudit(result.data[idx], singleSignatureRelArr, result.stageAudit);
                         }

+ 5 - 2
app/public/report/js/rpt_signature.js

@@ -555,7 +555,7 @@ let rptSignatureHelper = {
             }
         }
     },
-    mergeSignDate: function (pageData, currRoleRelList) {
+    mergeSignDate: function (pageData, currRoleRelList, isMergeOrgAlso) {
         if (currRoleRelList && currRoleRelList.length > 0 && STAGE_AUDIT && STAGE_AUDIT.length > 0) {
             for (let rridx = 0; rridx < currRoleRelList.length; rridx++) {
                 const role_rel = currRoleRelList[rridx];
@@ -563,7 +563,10 @@ let rptSignatureHelper = {
                     //*
                     let dftDate = _getSignDateByAllScenarios(role_rel.acc_id);
                     role_rel.sign_date = dftDate;
-                    rptSignatureHelper.originalRoleRelList[rridx].sign_date = dftDate;
+                    if (isMergeOrgAlso) {
+                        rptSignatureHelper.originalRoleRelList[rridx].sign_date = dftDate;
+                        //备注:在多选导出的情况下,originalRoleRelList不需要merge
+                    }
                     /*/
                     let hasAudit = false;
                     for (const stg_audit of STAGE_AUDIT) {

+ 30 - 4
app/service/stage.js

@@ -176,7 +176,9 @@ module.exports = app => {
                     const tpData = await this.ctx.service.stageBills.getSumTotalPrice(stage);
                     stage.contract_tp = tpData.contract_tp;
                     stage.qc_tp = tpData.qc_tp;
-                    stage.yf_tp = await this.ctx.service.stagePay.getYfTotalPrice(stage);
+                    const tp = await this.ctx.service.stagePay.getSpecialTotalPrice(stage);
+                    stage.yf_tp = tp.yf;
+                    stage.sf_tp = tp.sf;
                 }
             }
         }
@@ -213,11 +215,23 @@ module.exports = app => {
                     const tpData = await this.ctx.service.stageBills.getSumTotalPrice(stage);
                     stage.contract_tp = tpData.contract_tp;
                     stage.qc_tp = tpData.qc_tp;
-                    stage.yf_tp = await this.ctx.service.stagePay.getYfTotalPrice(stage);
+                    const tp = await this.ctx.service.stagePay.getSpecialTotalPrice(stage);
+                    stage.yf_tp = tp.yf;
+                    stage.sf_tp = tp.sf;
                     stage.tp = this.ctx.helper.add(stage.contract_tp, stage.qc_tp);
                     stage.end_tp = this.ctx.helper.add(stage.pre_tp, stage.tp);
                 }
             }
+            for (const s of stages) {
+                if (s.yf_tp && s.sf_tp === 0) {
+                    const sf = await this.ctx.service.stagePay.getHistorySf(s);
+                    if (sf) {
+                        await this.ctx.service.stage.update({ sf_tp: sf.tp, pre_sf_tp: sf.pre_tp}, {id: s.id});
+                    }
+                    s. sf_tp = sf.tp;
+
+                }
+            }
             return stages;
         }
 
@@ -346,6 +360,7 @@ module.exports = app => {
             const calcBase = JSON.parse(JSON.stringify(payConst.calcBase));
             const param = tenderInfo.deal_param;
             for (const cb of calcBase) {
+                const sum = await this.ctx.service.stageBills.getSumTotalPrice(stage);
                 switch (cb.code) {
                     case 'htj':
                         cb.value = param.contractPrice;
@@ -363,9 +378,14 @@ module.exports = app => {
                         cb.value = param.materialAdvance;
                         break;
                     case 'bqwc':
-                        const sum = await this.ctx.service.stageBills.getSumTotalPrice(stage);
                         cb.value = this.ctx.helper.add(sum.contract_tp, sum.qc_tp);
                         break;
+                    case 'bqht':
+                        cb.value = sum.contract_tp;
+                        break;
+                    case 'bqbg':
+                        cb.value = sum.qc_tp;
+                        break;
                     case 'ybbqwc':
                         const sumGcl = await this.ctx.service.stageBills.getSumTotalPriceGcl(stage, '^1[0-9]{2}-');
                         cb.value = this.ctx.helper.add(sumGcl.contract_tp, sumGcl.qc_tp);
@@ -459,6 +479,7 @@ module.exports = app => {
         async getMaterialCalcBase(stage_list, tenderInfo) {
             const calcBase = JSON.parse(JSON.stringify(payConst.calcBase));
             const param = tenderInfo.deal_param;
+            const sum = await this.ctx.service.stageBills.getSumTotalPriceByMaterial(stage_list);
             for (const cb of calcBase) {
                 switch (cb.code) {
                     case 'htj':
@@ -477,9 +498,14 @@ module.exports = app => {
                         cb.value = param.materialAdvance;
                         break;
                     case 'bqwc':
-                        const sum = await this.ctx.service.stageBills.getSumTotalPriceByMaterial(stage_list);
                         cb.value = this.ctx.helper.add(sum.contract_tp, sum.qc_tp);
                         break;
+                    case 'bqht':
+                        cb.value = sum.contract_tp;
+                        break;
+                    case 'bqbg':
+                        cb.value = sum.contract_tp;
+                        break;
                     case 'ybbqwc':
                         const sumGcl = await this.ctx.service.stageBills.getSumTotalPriceGclByMaterial(stage_list, '^1[0-9]{2}-');
                         cb.value = this.ctx.helper.add(sumGcl.contract_tp, sumGcl.qc_tp);

+ 9 - 4
app/service/stage_audit.js

@@ -218,7 +218,7 @@ module.exports = app => {
             try {
                 await transaction.update(this.tableName, {id: audit.id, status: auditConst.status.checking, begin_time: new Date()});
                 // 计算原报最终数据
-                const yfPay = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
+                const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
                 // 复制一份下一审核人数据
                 await this.ctx.service.stagePay.copyAuditStagePays(this.ctx.stage, this.ctx.stage.times, 1, transaction);
                 await this.ctx.service.stageJgcl.updateHistory(this.ctx.stage, transaction);
@@ -231,6 +231,7 @@ module.exports = app => {
                     contract_tp: tpData.contract_tp,
                     qc_tp: tpData.qc_tp,
                     yf_tp: yfPay.tp,
+                    sf_tp: sfPay.tp,
                     cache_time_r: this.ctx.stage.cache_time_l,
                 });
 
@@ -274,7 +275,7 @@ module.exports = app => {
             try {
                 await transaction.update(this.tableName, {id: audit.id, status: checkData.checkType, opinion: checkData.opinion, end_time: time});
                 // 计算并合同支付最终数据
-                const yfPay = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
+                const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
                 // 无下一审核人表示,审核结束
                 if (nextAudit) {
                     // 复制一份下一审核人数据
@@ -290,6 +291,7 @@ module.exports = app => {
                         contract_tp: tpData.contract_tp,
                         qc_tp: tpData.qc_tp,
                         yf_tp: yfPay.tp,
+                        sf_tp: sfPay.tp,
                         cache_time_r: this.ctx.stage.cache_time_l,
                     });
 
@@ -323,6 +325,7 @@ module.exports = app => {
                         contract_tp: tpData.contract_tp,
                         qc_tp: tpData.qc_tp,
                         yf_tp: yfPay.tp,
+                        sf_tp: sfPay.tp,
                         cache_time_r: this.ctx.stage.cache_time_l,
                     });
 
@@ -385,7 +388,7 @@ module.exports = app => {
             const transaction = await this.db.beginTransaction();
             try {
                 // 计算并合同支付最终数据
-                const yfPay = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
+                const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
                 await transaction.update(this.tableName, {id: audit.id, status: checkData.checkType, opinion: checkData.opinion, end_time: time});
                 // 同步 期信息
                 await transaction.update(this.ctx.service.stage.tableName, {
@@ -394,6 +397,7 @@ module.exports = app => {
                     qc_tp: tpData.qc_tp,
                     times: times + 1,
                     yf_tp: yfPay.tp,
+                    sf_tp: sfPay.tp,
                     cache_time_r: this.ctx.stage.cache_time_l,
                 });
                 // 拷贝新一次审核流程列表
@@ -461,7 +465,7 @@ module.exports = app => {
             const transaction = await this.db.beginTransaction();
             try {
                 // 计算并合同支付最终数据
-                const yfPay = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
+                const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
                 // 同步 期信息
                 await transaction.update(this.ctx.service.stage.tableName, {
                     id: stageId,
@@ -469,6 +473,7 @@ module.exports = app => {
                     qc_tp: tpData.qc_tp,
                     times: times,
                     yf_tp: yfPay.tp,
+                    sf_tp: sfPay.tp,
                     cache_time_r: this.ctx.stage.cache_time_l,
                 });
                 await transaction.update(this.tableName, {id: audit.id, status: checkData.checkType, opinion: checkData.opinion, end_time: time});

+ 12 - 3
app/service/stage_pay.js

@@ -244,10 +244,11 @@ module.exports = app => {
                 await transaction.updateRows(this.ctx.service.pay.tableName, srUpdate);
             }
             const yf = this._.find(stagePays, {ptype: payConst.payType.yf});
-            return yf;
+            const sf = this._.find(stagePays, {ptype: payConst.payType.sf});
+            return [yf, sf];
         }
 
-        async getYfTotalPrice(stage) {
+        async getSpecialTotalPrice(stage) {
             if (!stage) throw '计算数据错误';
             const stagePays = await this.getStagePays(stage);
             const PayCalculator = require('../lib/pay_calc');
@@ -255,7 +256,15 @@ module.exports = app => {
             const payCalculator = new PayCalculator(this.ctx, stage, tenderInfo);
             await payCalculator.calculateAll(stagePays);
             const yf = this._.find(stagePays, {ptype: payConst.payType.yf});
-            return yf ? yf.tp : 0;
+            const sf = this._.find(stagePays, {ptype: payConst.payType.sf});
+            return { yf: yf ? yf.tp : 0, sf: sf ? sf.tp : 0 };
+        }
+
+        async getHistorySf(stage) {
+            if (!stage) return 0;
+            const stagePays = await this.getStageLastestPays(stage.id);
+            const sf = this._.find(stagePays, {ptype: payConst.payType.sf});
+            return sf;
         }
 
         /**

+ 15 - 9
app/view/ledger/explode.ejs

@@ -21,15 +21,15 @@
                     </div>
                 </div>
                 <div class="d-inline-block">
-                    <a href="javascript:void(0)" id="insert" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="新增"><i class="fa fa-plus" aria-hidden="true"></i></a>
-                    <a href="javascript:void(0)" id="delete" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
-                    <a href="javascript:void(0)" id="up-level" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
-                    <a href="javascript:void(0)" id="down-level" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
-                    <a href="javascript:void(0)" id="down-move" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
-                    <a href="javascript:void(0)" id="up-move" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
-                    <a href="javascript:void(0)" id="copy" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="复制"><i class="fa fa-files-o" aria-hidden="true"></i></a>
-                    <a href="javascript:void(0)" id="cut" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="剪切"><i class="fa fa-scissors" aria-hidden="true"></i></a>
-                    <a href="javascript:void(0)" id="paste" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="粘贴"><i class="fa fa-clipboard" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="insert" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="新增"><i class="fa fa-plus" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="delete" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="up-level" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="down-level" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="down-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="up-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="copy" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="复制"><i class="fa fa-files-o" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="cut" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="剪切"><i class="fa fa-scissors" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" id="paste" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="粘贴"><i class="fa fa-clipboard" aria-hidden="true"></i></a>
                 </div>
                 <div class="d-inline-block">
                     <div class="input-group input-group-sm ml-2">
@@ -78,6 +78,12 @@
                             <li class="nav-item">
                                 <a class="nav-link active" href="javascript:void(0)">计量单元</a>
                             </li>
+                            <li class="ml-2 nav-item">
+                                <div class="d-inline-flex">
+                                    <a href="javascript: void(0);" name="pos-opr" type="down-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                                    <a href="javascript: void(0);" name="pos-opr" type="up-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                                </div>
+                            </li>
                             <li class="nav-item" id="pos-search">
                             </li>
                             <li class="nav-item">

+ 4 - 0
app/view/measure/stage.ejs

@@ -28,6 +28,8 @@
                         <th class="text-center">本期完成计量</th>
                         <th class="text-center">截止上期完成计量</th>
                         <th class="text-center">截止本期完成计量</th>
+                        <th class="text-center">本期应付</th>
+                        <th class="text-center">本期实付</th>
                         <th class="text-center">审批进度</th>
                         <th class="text-center">操作</th>
                     </tr>
@@ -48,6 +50,8 @@
                         <td class="text-right"><%- (s.tp ? s.tp : '')%></td>
                         <td class="text-right"><%- (s.pre_tp ? s.pre_tp : '')%></td>
                         <td class="text-right"><%- (s.end_tp ? s.end_tp : '')%></td>
+                        <td class="text-right"><%- (s.yf_tp ? s.yf_tp : '') %></td>
+                        <td class="text-right"><%- (s.sf_tp ? s.sf_tp : '') %></td>
                         <td class="<%- auditConst.auditProgressClass[s.status] %>">
                             <% if (s.curAuditor) { %>
                             <a href="#sp-list" data-toggle="modal" data-target="#sp-list" s-order="<%- s.order %>"><%- s.curAuditor.name %><%if (s.curAuditor.role !== '' && s.curAuditor.role !== null) { %>-<%- s.curAuditor.role %><% } %></a>

+ 15 - 9
app/view/revise/info.ejs

@@ -23,15 +23,15 @@
                     </div>
                 </div>
                 <div class="d-inline-block">
-                    <a href="javascript: void(0);" name="base-opr" type="add" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="新增"><i class="fa fa-plus" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" name="base-opr" type="delete" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" name="base-opr" type="up-level" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" name="base-opr" type="down-level" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" name="base-opr" type="down-move" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" name="base-opr" type="up-move" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" name="cpc" type="copy" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="复制"><i class="fa fa-files-o" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" name="cpc" type="cut" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="剪切"><i class="fa fa-scissors" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" name="cpc" type="paste" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="粘贴"><i class="fa fa-clipboard" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="base-opr" type="add" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="新增"><i class="fa fa-plus" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="base-opr" type="delete" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="base-opr" type="up-level" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="base-opr" type="down-level" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="base-opr" type="down-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="base-opr" type="up-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="cpc" type="copy" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="复制"><i class="fa fa-files-o" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="cpc" type="cut" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="剪切"><i class="fa fa-scissors" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" name="cpc" type="paste" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="粘贴"><i class="fa fa-clipboard" aria-hidden="true"></i></a>
                 </div>
                 <div class="d-inline-block">
                     <div class="input-group input-group-sm ml-2">
@@ -83,6 +83,12 @@
                             <li class="nav-item">
                                 <a class="nav-link active" href="javascript:void(0)">计量单元</a>
                             </li>
+                            <li class="ml-2 nav-item">
+                                <div class="d-inline-flex">
+                                    <a href="javascript: void(0);" name="pos-opr" type="down-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                                    <a href="javascript: void(0);" name="pos-opr" type="up-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                                </div>
+                            </li>
                             <li class="nav-item" id="pos-search">
                             </li>
                             <li class="nav-item">

+ 14 - 2
app/view/stage/index.ejs

@@ -57,7 +57,7 @@
                             <li class="nav-item">
                                 <div class="ml-2">
                                     <div class="input-group input-group-sm">
-                                        <div class="input-group-prepend">
+                                        <div class="input-group-prepend" style="display: none">
                                             <div class="input-group-text">
                                                 <div class="form-group form-check mb-0">
                                                     <input type="checkbox" class="form-check-input group-checkbox" id="pos-over-search">
@@ -105,7 +105,19 @@
                     <!--中间计量-->
                     <div id="zhongjian" class="tab-pane tab-select-show">
                         <div class="sjs-bar">
-                            <button class="btn btn-sm btn-outline-primary pull-right" href="#choose" data-toggle="modal" data-target="#choose">设置生成规则</button>
+                            <div class="row px-3">
+                                <button class="btn btn-sm btn-outline-primary" id="im-locate2bills">定位</button>
+                                <div class="input-group input-group-sm col-6">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text" id="im-locate-info">1/20</span>
+                                    </div>
+                                    <div class="input-group-append">
+                                        <button class="btn btn-outline-secondary" type="button" title="上一个" id="im-locate-pre"><i class="fa fa-angle-double-left"></i></button>
+                                        <button class="btn btn-outline-secondary" type="button" title="下一个" id="im-locate-next"><i class="fa fa-angle-double-right"></i></button>
+                                    </div>
+                                </div>
+                                <button class="btn btn-sm btn-outline-primary ml-auto" href="#choose" data-toggle="modal" data-target="#choose">设置生成规则</button>
+                            </div>
                         </div>
                         <div class="sjs-height-5" id="detail-spread" style="overflow:hidden">
                         </div>

+ 4 - 4
app/view/stage/pay.ejs

@@ -5,10 +5,10 @@
             <% include ./stage_sub_mini_menu.ejs %>
             <div>
                 <div class="d-inline-block">
-                    <a href="javascript: void(0);" id="add" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="新增"><i class="fa fa-plus" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" id="del" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" id="down-move" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
-                    <a href="javascript: void(0);" id="up-move" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" id="add" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="新增"><i class="fa fa-plus" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" id="del" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" id="down-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                    <a href="javascript: void(0);" id="up-move" class="btn btn-sm btn-light text-primary" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
                 </div>
                 <div class="d-inline-block">
                     <div class="input-group input-group-sm ml-2">

+ 25 - 1
sql/update.sql

@@ -5,4 +5,28 @@ UPDATE `zh_stage_pay` sp
   WHERE (sp.`start_stage_order` < s.`order` OR ((not IsNULL(sp.pre_tp)) AND sp.pre_tp) AND sp.`pre_used` = 0 AND p.`ptype` = 1;
 
 ALTER TABLE `zh_stage_detail`
-ADD COLUMN `pos_name`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '计量单元名称' AFTER `position`;
+ADD COLUMN `pos_name`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '计量单元名称' AFTER `position`;
+
+ALTER TABLE `zh_formula`
+MODIFY COLUMN `sid`  int(11) NOT NULL DEFAULT -1 COMMENT '期id' AFTER `tid`,
+MODIFY COLUMN `rid`  varchar(50) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '' COMMENT '修订id' AFTER `sid`,
+MODIFY COLUMN `formula`  varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '表达式' AFTER `table_field`,
+ADD COLUMN `valid`  tinyint(1) NOT NULL DEFAULT 1 COMMENT '是否可用' AFTER `formula`;
+
+ALTER TABLE `zh_stage_detail`
+ADD COLUMN `custom_define`  varchar(1000) CHARACTER SET ascii COLLATE ascii_general_ci NULL DEFAULT '' COMMENT '修改过的字段' AFTER `pos_name`;
+
+ALTER TABLE `zh_ledger`
+MODIFY COLUMN `sgfh_qty`  decimal(24,8) NULL DEFAULT NULL COMMENT '施工复核 - 数量' AFTER `deal_tp`,
+MODIFY COLUMN `sgfh_tp`  decimal(24,8) NULL DEFAULT NULL COMMENT '施工复核 - 金额' AFTER `sgfh_qty`,
+ADD COLUMN `sgfh_expr`  varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NULL DEFAULT '' COMMENT '施工复核-公式' AFTER `is_tp`,
+ADD COLUMN `sjcl_expr`  varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NULL DEFAULT '' COMMENT '设计错漏-公式' AFTER `sgfh_expr`,
+ADD COLUMN `qtcl_expr`  varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NULL DEFAULT '' COMMENT '其他错漏-公式' AFTER `sjcl_qty`;
+
+
+ALTER TABLE `zh_revise_bills`
+MODIFY COLUMN `sgfh_qty`  decimal(24,8) NULL DEFAULT NULL COMMENT '施工复核 - 数量' AFTER `deal_tp`,
+MODIFY COLUMN `sgfh_tp`  decimal(24,8) NULL DEFAULT NULL COMMENT '施工复核 - 金额' AFTER `sgfh_qty`,
+ADD COLUMN `sgfh_expr`  varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NULL DEFAULT '' COMMENT '施工复核-公式' AFTER `is_tp`,
+ADD COLUMN `sjcl_expr`  varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NULL DEFAULT '' COMMENT '设计错漏-公式' AFTER `sgfh_expr`,
+ADD COLUMN `qtcl_expr`  varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NULL DEFAULT '' COMMENT '其他错漏-公式' AFTER `sjcl_qty`;