Ver código fonte

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

TonyKang 5 anos atrás
pai
commit
e2c6cb56af

+ 4 - 0
app/const/spread.js

@@ -292,6 +292,10 @@ const stageNoCl = {
         font: '12px 微软雅黑',
     }
 };
+// 期 -- 部位台账
+const stageBwtz = {
+
+};
 // 期 -- 清单汇总
 const stageGather = {
     gcl: {

+ 33 - 9
app/controller/stage_controller.js

@@ -261,14 +261,27 @@ module.exports = app => {
 
         async getStageData(ctx) {
             try {
-                const ledgerData = await this._getStageLedgerData(ctx);
-                const posData = await this._getStagePosData(ctx);
-                const detailData = await this._getStageDetailData(ctx);
-                const changeData = await this._getStageChangeData(ctx);
-
-                ctx.body = {err: 0, msg: '', data: {
-                    ledgerData, posData, detailData, changeData,
-                }};
+                const data = JSON.parse(ctx.request.body.data);
+                const filter = data.filter.split(';');
+                const responseData = { err: 0, msg: '', data: {} };
+                for (const f of filter) {
+                    switch (f) {
+                        case 'ledger':
+                            responseData.data.ledgerData = await this._getStageLedgerData(ctx);
+                            break;
+                        case 'pos':
+                            responseData.data.posData = await this._getStagePosData(ctx);
+                            break;
+                        case 'detail':
+                            responseData.data.detailData = await this._getStageDetailData(ctx);
+                            break;
+                        case 'change':
+                            responseData.data.changeData = await this._getStageChangeData(ctx);
+                            break;
+                    }
+                }
+
+                ctx.body = responseData;
             } catch (err) {
                 this.log(err);
                 ctx.body = {err: 1, msg: err.toString(), data: null};
@@ -617,7 +630,6 @@ module.exports = app => {
             }
         }
 
-
         /**
          * 合同支付 (Get)
          * @param ctx
@@ -1158,6 +1170,18 @@ module.exports = app => {
             }
         }
 
+        async bwtz(ctx) {
+            try {
+                await this._getStageAuditViewData(ctx);
+                const renderData = await this._getDefaultRenderData(ctx);
+                renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.stage.bwtz);
+                await this.layout('stage/bwtz.ejs', renderData);
+            } catch (err) {
+                this.log(err);
+                ctx.redirect('/tender/' + ctx.tender.id + '/measure/stage/' + ctx.params.order);
+            }
+        }
+
         /**
          * 报表
          * @param ctx

+ 6 - 2
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'];
+        this.imFields = ['uuid', 'doc_code', 'peg', 'bw', 'xm', 'drawing_code', 'calc_memo', 'calc_img', 'position'];
         this.splitChar = '-';
     }
 
@@ -391,6 +391,7 @@ class StageIm {
                 pre_jl: node.pre_gather_tp, pre_contract_jl: node.pre_contract_tp, pre_qc_jl: node.pre_qc_tp,
                 end_jl: node.end_gather_tp, end_contract_jl: node.end_contract_tp, end_qc_jl: node.end_qc_tp,
                 peg: peg ? this._getPegStr(peg.name) : '', drawing_code: this._getDrawingCode(node),
+                position: '',
             };
             if (this.ctx.stage.im_gather && node.check) {
                 im.bw = this._getZlGatherBw(node, peg);
@@ -497,7 +498,8 @@ class StageIm {
                     jl: 0, contract_jl: 0, qc_jl: 0,
                     pre_jl: 0, pre_contract_jl: 0, pre_qc_jl: 0,
                     end_jl: 0, end_contract_jl: 0, end_qc_jl: 0,
-                    peg: peg ? this._getPegStr(peg.name) : ''
+                    peg: peg ? this._getPegStr(peg.name) : '',
+                    position: '',
                 };
                 if (this.ctx.stage.im_gather && node.check) {
                     im.check = true;
@@ -557,6 +559,7 @@ class StageIm {
                         xm: pp.name,
                         drawing_code: pp.drawing_code,
                         changes: [],
+                        position: pp.position,
                     };
                     im.calc_memo = '本期计量:' + im.jl + ' ' + im.unit;
                     this._checkCustomDetail(im);
@@ -584,6 +587,7 @@ class StageIm {
                     xm: node.name,
                     drawing_code: this._getDrawingCode(p),
                     changes: [],
+                    position: '',
                 };
                 im.calc_memo = '本期计量:' + im.jl + ' ' + im.unit;
                 this._checkCustomDetail(im);

+ 0 - 2
app/public/js/gcl_gather.js

@@ -40,8 +40,6 @@ const gclGatherModel = (function () {
     const gclList = [], leafXmjs = [];
     const mergeChar = ';';
 
-
-
     /**
      * 将所有数据加载至树结构
      *

+ 1 - 1
app/public/js/ledger.js

@@ -1269,7 +1269,7 @@ $(document).ready(function() {
             callback: function () {
                 ledgerSpread.refresh();
                 let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
-                $(".sp-wrap").height(bcontent-40);
+                $(".sp-wrap").height(bcontent-30);
                 posSpread.refresh();
             }
         });

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

@@ -79,7 +79,7 @@ $(document).ready(() => {
             callback: function () {
                 ledgerSpread.refresh();
                 let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
-                $(".sp-wrap").height(bcontent-40);
+                $(".sp-wrap").height(bcontent-30);
                 posSpread.refresh();
             }
         });

+ 1 - 1
app/public/js/ledger_gather.js

@@ -185,7 +185,7 @@ $(document).ready(() => {
         callback: function () {
             gclSpread.refresh();
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-40);
+            $(".sp-wrap").height(bcontent-30);
             leafXmjSpread.refresh();
         }
     });

+ 1 - 1
app/public/js/measure_compare.js

@@ -123,7 +123,7 @@ $(document).ready(() => {
         callback: function () {
             billsSpread.refresh();
             let bcontent = $(".bcontent-wrap").length > 0 ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-40);
+            $(".sp-wrap").height(bcontent-30);
             posSpread.refresh();
         }
     });

+ 82 - 0
app/public/js/path_tree.js

@@ -1256,6 +1256,84 @@ const createNewPathTree = function (type, setting) {
         }
     }
 
+    class FilterTree extends BaseTree {
+        addData(data, fields) {
+            const item = {};
+            for (const prop in data) {
+                if (fields.indexOf(prop) >= 0) {
+                    item[prop] = data[prop];
+                }
+            }
+            const keyName = itemsPre + item[this.setting.id];
+            if (!this.items[keyName]) {
+                item.children = [];
+                item.is_leaf = true;
+                item.expanded = true;
+                item.visible = true;
+                this.items[keyName] = item;
+                this.datas.push(item);
+                if (item[setting.pid] === setting.rootId) {
+                    this.children.push(item);
+                } else {
+                    const parent = this.getParent(item);
+                    if (parent) {
+                        parent.is_leaf = false;
+                        parent.children.push(item);
+                    }
+                }
+            } else {
+                return this.items[keyName];
+            }
+            return item;
+        }
+    }
+
+    class GatherTree extends BaseTree {
+        clearDatas () {
+            this.items = {};
+            this.nodes = [];
+            this.datas = [];
+            this.children = [];
+        }
+
+        get newId() {
+            if (!this._maxId) {
+                this._maxId = 0;
+            }
+            this._maxId++;
+            return this._maxId;
+        }
+
+        addNode(data, parent) {
+            data[this.setting.pid] = parent ? parent[this.setting.id] : this.setting.rootId;
+            let item = _.find(this.items, data);
+            if (item) return item;
+
+            item = data;
+            item[this.setting.id] = this.newId;
+            const keyName = itemsPre + item[this.setting.id];
+            item.children = [];
+            item.is_leaf = true;
+            item.expanded = true;
+            item.visible = true;
+            this.items[keyName] = item;
+            this.datas.push(item);
+            if (parent) {
+                item[this.setting.fullPath] = parent[this.setting.fullPath] + '-' + item[this.setting.id];
+                item[this.setting.level] = parent[this.setting.level] + 1;
+                item[this.setting.order] = parent.children.length + 1;
+                parent.is_leaf = false;
+                parent.children.push(item);
+            } else {
+                item[this.setting.fullPath] = '' + item[this.setting.id];
+                item[this.setting.level] = 1;
+                item[this.setting.order] = this.children.length + 1;
+                this.children.push(item);
+            }
+            return item;
+        }
+    }
+
     if (type === 'base') {
         return new BaseTree(setting);
     } else if (type === 'fx') {
@@ -1270,6 +1348,10 @@ const createNewPathTree = function (type, setting) {
         return new MeasureTree(setting);
     } else if (type === 'master') {
         return new MasterTree(setting);
+    } else if (type === 'filter') {
+        return new FilterTree(setting);
+    } else if (type === 'gather') {
+        return new GatherTree(setting);
     }
 };
 

+ 1 - 1
app/public/js/revise.js

@@ -1397,7 +1397,7 @@ $(document).ready(() => {
         callback: function () {
             billsSpread.refresh();
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-40);
+            $(".sp-wrap").height(bcontent-30);
             posSpread.refresh();
         }
     });

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

@@ -159,7 +159,7 @@ $(document).ready(() => {
         callback: function () {
             billsSpread.refresh();
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-40);
+            $(".sp-wrap").height(bcontent-30);
             posSpread.refresh();
         }
     });

+ 197 - 0
app/public/js/shares/bills_pos_convert.js

@@ -0,0 +1,197 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const billsPosConvertModel = (function () {
+    // 需要汇总计算的字段
+    const tpFields = ['total_price', 'contract_tp', 'qc_tp',
+        'pre_contract_tp', 'pre_qc_tp', 'end_contract_tp', 'end_qc_tp'];
+    const baseCalcFields = ['quantity', 'contract_qty', 'qc_qty', 'gather_qty',
+        'pre_contract_qty', 'pre_qc_qty', 'pre_gather_qty', 'end_contract_qty', 'end_qc_qty', 'end_gather_qty'];
+    // 基础数据
+    const bpcTreeSetting = {
+        id: 'ledger_id',
+        pid: 'ledger_pid',
+        order: 'order',
+        level: 'level',
+        rootId: -1,
+        keys: ['id', 'tender_id', 'ledger_id'],
+        stageId: 'id',
+        updateFields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp']
+    };
+    const bpcTree = createNewPathTree('stage', bpcTreeSetting);
+    const bpcPosSetting = {
+        id: 'id', ledgerId: 'lid',
+        updateFields: ['contract_qty', 'qc_qty'],
+    };
+    const bpcPos = new StagePosData(bpcPosSetting);
+    let bpcChange;
+
+    // 结果
+    const resultTreeSetting = {
+        id: 'ledger_id',
+        pid: 'ledger_pid',
+        order: 'order',
+        level: 'level',
+        rootId: -1,
+        fullPath: 'full_path',
+    };
+    const resultTree = createNewPathTree('filter', resultTreeSetting);
+
+    // 加载基础数据
+    function loadLedgerData (ledger) {
+        // 加载树结构数据
+        bpcTree.loadDatas(ledger);
+    }
+    function loadPosData(pos) {
+        bpcPos.loadDatas(pos);
+    }
+    function loadData(ledger, pos, change) {
+        loadLedgerData(ledger);
+        loadPosData(pos);
+        bpcChange = change;
+    }
+
+    function convertXmj(node) {
+        return resultTree.addData(node, ['ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
+            'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'drawing_code', 'postil', 'memo']);
+    }
+    function loadField(node, data, fields) {
+        for (const prop in data) {
+            if (fields.indexOf(prop) >= 0) node[prop] = data[prop];
+        }
+    }
+    function convertGcl(node, xmj) {
+        if (!xmj) return;
+
+        if (!xmj.unitTree) {
+            xmj.unitTree = createNewPathTree('gather', resultTreeSetting);
+        }
+        const pos = bpcPos.getLedgerPos(node.id);
+        if (pos && pos.length > 0) {
+            for (const p of pos) {
+                const posUnit = xmj.unitTree.addNode({pos_name: p.name,
+                    b_code: null, name: null, unit: null, unit_price: null});
+                const gclUnit = xmj.unitTree.addNode({pos_name: null,
+                    b_code: node.b_code, name: node.name, unit: node.unit, unit_price: node.unit_price
+                }, posUnit);
+                loadField(gclUnit, p, baseCalcFields);
+                if (!gclUnit.changes) gclUnit.changes = [];
+                for (const c of bpcChange) {
+                    if (c.lid === node.id && c.pid === p.id && c.qty && c.qty !== 0) {
+                        gclUnit.changes.push(c);
+                    }
+                }
+            }
+        } else {
+            const unit = xmj.unitTree.addNode({pos_name: null,
+                b_code: node.b_code, name: node.name, unit: node.unit, unit_price: node.unit_price});
+            loadField(unit, node, baseCalcFields);
+            if (!unit.changes) unit.changes = [];
+            for (const c of bpcChange) {
+                if (c.lid === node.id && c.pid == -1 && c.qty && c.qty !== 0) {
+                    unit.changes.push(c);
+                }
+            }
+        }
+    }
+    function recursiveConvertNode(nodes, xmj = null) {
+        if (!nodes || !nodes instanceof Array || nodes.length === 0) return;
+
+        for (const node of nodes) {
+            let cXmj = xmj;
+            if (node.b_code && node.b_code !== '') {
+                if (!node.children || node.children.length === 0) {
+                    convertGcl(node, xmj);
+                }
+            } else {
+                cXmj = convertXmj(node);
+            }
+            recursiveConvertNode(node.children, cXmj);
+        }
+    }
+
+    function calculateChild(node) {
+        node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
+        node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_gather_qty);
+        node.end_contract_qty = ZhCalc.add(node.contract_qty, node.pre_contract_qty);
+        node.end_qc_qty = ZhCalc.add(node.qc_qty, node.pre_qc_qty);
+        node.end_gather_qty = ZhCalc.add(node.gather_qty, node.pre_gather_qty);
+
+        node.total_price = ZhCalc.mul(node.unit_price, node.quantity);
+        node.contract_tp = ZhCalc.mul(node.unit_price, node.contract_qty);
+        node.qc_tp = ZhCalc.mul(node.unit_price, node.qc_qty);
+        node.gather_tp = ZhCalc.mul(node.unit_price, node.gather_qty);
+        node.pre_contract_tp = ZhCalc.mul(node.unit_price, node.pre_contract_qty);
+        node.pre_qc_tp = ZhCalc.mul(node.unit_price, node.pre_qc_qty);
+        node.pre_gather_tp = ZhCalc.mul(node.unit_price, node.pre_gather_qty);
+        node.end_contract_tp = ZhCalc.mul(node.unit_price, node.end_contract_qty);
+        node.end_qc_tp = ZhCalc.mul(node.unit_price, node.end_qc_qty);
+        node.end_gather_tp = ZhCalc.mul(node.unit_price, node.end_gather_qty);
+
+        node.final_tp = ZhCalc.add(node.total_price, node.end_qc_tp);
+        node.end_gather_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.final_tp, 4), 100);
+
+        node.bgl_code = _.uniq(_.map(node.changes, 'c_code')).join(';');
+    }
+    function calculateNode(node, children) {
+        for (const child of children) {
+            node.total_price = ZhCalc.add(node.total_price, child.total_price);
+            node.contract_tp = ZhCalc.add(node.contract_tp, child.contract_tp);
+            node.qc_tp = ZhCalc.add(node.qc_tp, child.qc_tp);
+            node.gather_tp = ZhCalc.add(node.gather_tp, child.gather_tp);
+            node.pre_contract_tp = ZhCalc.add(node.pre_contract_tp, child.pre_contract_tp);
+            node.pre_qc_tp = ZhCalc.add(node.pre_qc_tp, child.pre_qc_tp);
+            node.pre_gather_tp = ZhCalc.add(node.pre_gather_tp, child.pre_gather_tp);
+            node.end_contract_tp = ZhCalc.add(node.end_contract_tp, child.end_contract_tp);
+            node.end_qc_tp = ZhCalc.add(node.end_qc_tp, child.end_qc_tp);
+            node.end_gather_tp = ZhCalc.add(node.end_gather_tp, child.end_gather_tp);
+        }
+        node.final_tp = ZhCalc.add(node.total_price, node.end_qc_tp);
+        node.end_gather_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.final_tp, 4), 100);
+    }
+    function recursiveCalcUnitNodes(nodes) {
+        if (!nodes || !nodes instanceof Array || nodes.length === 0) return;
+
+        for (const node of nodes) {
+            recursiveCalcUnitNodes(node.children);
+            if (node.children && node.children.length > 0) {
+                calculateNode(node, node.children);
+            } else {
+                calculateChild(node);
+            }
+        }
+    }
+    function recursiveCalculateAndSort(nodes) {
+        if (!nodes || !nodes instanceof Array || nodes.length === 0) return;
+
+        for (const node of nodes) {
+            recursiveCalculateAndSort(node.children);
+            if (node.unitTree) {
+                node.unitTree.sortTreeNode();
+                recursiveCalcUnitNodes(node.unitTree.children);
+                calculateNode(node, node.unitTree.children, tpFields);
+            } else if (node.children && node.children.length > 0) {
+                calculateNode(node, node.children, tpFields);
+            }
+        }
+    }
+    function CalculateAndSortResult() {
+        resultTree.sortTreeNode();
+        recursiveCalculateAndSort(resultTree.children);
+    }
+    // 转换数据
+    function convert() {
+        recursiveConvertNode(bpcTree.children);
+        CalculateAndSortResult();
+        return resultTree;
+    }
+
+    return { loadData, convert }
+})();

+ 52 - 8
app/public/js/shares/merge_peg.js

@@ -10,6 +10,7 @@
  */
 
 const NewMergePeg = function (setting) {
+    let siHandle;
     const spread = SpreadJsObj.createNewSpread($('#mp-spread')[0]);
     const sheet = spread.getActiveSheet();
     const spreadSetting = {
@@ -115,13 +116,15 @@ const NewMergePeg = function (setting) {
             spreadObj.mergePeg(row);
         },
         editEnded: function (e, info) {
-            if (info.col === spCol || info.col === epCol) {
-                if (info.editingText.length > 10) {
-                    info.sheet.setText(info.row, info.col, info.editingText.substring(0, 10));
-                }
-            } else if (info.col === posCol) {
-                if (info.editingText.length > 50) {
-                    info.sheet.setText(info.row, info.col, info.editingText.substring(0, 50));
+            if (info.editingText) {
+                if (info.col === spCol || info.col === epCol) {
+                    if (info.editingText.length > 10) {
+                        info.sheet.setText(info.row, info.col, info.editingText.substring(0, 10));
+                    }
+                } else if (info.col === posCol) {
+                    if (info.editingText.length > 50) {
+                        info.sheet.setText(info.row, info.col, info.editingText.substring(0, 50));
+                    }
                 }
             }
             spreadObj.mergePeg(info.row);
@@ -138,13 +141,52 @@ const NewMergePeg = function (setting) {
                 rows.push(iRow);
             }
             spreadObj.mergePeg(rows);
-        }
+        },
+        checkEmptyRow: function () {
+            let nonEmptyRow = -1, count = sheet.getRowCount();
+            for (let iRow = count - 1; iRow >= 0; iRow--) {
+                const sp = sheet.getText(iRow, spCol);
+                const ep = sheet.getText(iRow, epCol);
+                const p = sheet.getText(iRow, posCol);
+                if (sp !== '' || ep !== '' || p !== '') {
+                    nonEmptyRow = iRow;
+                    break;
+                }
+            }
+            if (nonEmptyRow >= 0 && count - nonEmptyRow <= 3) {
+                sheet.addRows(nonEmptyRow + 1, 4 + nonEmptyRow - count);
+            }
+        },
     };
     spread.bind(spreadNS.Events.EditStarting, spreadObj.editStarting);
     spread.bind(spreadNS.Events.ClipboardPasted, spreadObj.clipboardPasted);
     spread.bind(spreadNS.Events.EditEnded, spreadObj.editEnded);
     SpreadJsObj.addDeleteBind(spread, spreadObj.deletePress);
     SpreadJsObj.addCutEvents(spread, spreadObj.cut);
+    $.contextMenu({
+        selector: '#mp-spread',
+        build: function ($trigger, e) {
+            const target = SpreadJsObj.safeRightClickSelection($trigger, e, spread);
+            return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
+        },
+        items: {
+            'create': {
+                name: '新增行',
+                icon: 'fa-sign-in',
+                callback: function (key, opt) {
+                    sheet.addRows(sheet.getRowCount(), 1);
+                },
+            },
+            'delete': {
+                name: '删除行',
+                icon: 'fa-remove',
+                callback: function (key, opt) {
+                    const sel = sheet.getSelections()[0];
+                    sheet.deleteRows(sel.row, sel.rowCount);
+                },
+            },
+        }
+    });
 
     // 勾选位置
     $('#mp-with-pos').click(() => {spreadObj.mergePeg();});
@@ -171,11 +213,13 @@ const NewMergePeg = function (setting) {
         if (setting.callback) {
             setting.callback(spreadObj.getPegs());
         }
+        clearInterval(siHandle);
         $('#merge-peg').modal('hide');
     });
 
     const showModal = function () {
         $('#merge-peg').modal('show');
+         siHandle = setInterval(spreadObj.checkEmptyRow, 500);
     };
     return {show: showModal};
 };

+ 2 - 2
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -1202,9 +1202,9 @@ const SpreadJsObj = {
             const AutoTipCellType = function () {};
             // 继承 TipCellType
             AutoTipCellType.prototype = SpreadJsObj.CellType.getTipCellType();
-            const proto = AutoTipCellType.prototype
+            const proto = AutoTipCellType.prototype;
             proto.showTip = function (hitinfo, text) {
-                return text && text !== '' && this.getTextDisplayWidth(hitinfo, text) > hitinfo.cellRect.widthidth;
+                return text && text !== '' && this.getTextDisplayWidth(hitinfo, text) > hitinfo.cellRect.width;
             };
 
             return new AutoTipCellType();

+ 7 - 2
app/public/js/stage.js

@@ -1318,13 +1318,13 @@ $(document).ready(() => {
         callback: function () {
             slSpread.refresh();
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-40);
+            $(".sp-wrap").height(bcontent-30);
             spSpread.refresh();
         }
     });
 
     // 加载计量单元数据 - 暂时统一加载,如有需要,切换成动态加载并缓存
-    postData(window.location.pathname + '/load', null, function (result) {
+    postData(window.location.pathname + '/load', { filter: 'ledger;pos;detail;change' }, function (result) {
         // 加载树结构
         stageTree.loadDatas(result.ledgerData);
         // stageTree.loadCurStageData(curStageData);
@@ -2243,6 +2243,7 @@ $(document).ready(() => {
                 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();
                 postData(window.location.pathname + '/detail/save', updateData, function (result) {
@@ -2470,6 +2471,10 @@ $(document).ready(() => {
             $('#show-bw-name').text(bwName);
             $('#bw-name').val(bwName);
 
+            const position = data && data.position ? data.position : '';
+            $('#show-position').text(position);
+            $('#position').val(position);
+
             const peg = data && data.peg ? data.peg : '';
             $('#show-peg').text(peg);
             $('#peg').val(peg);

+ 69 - 0
app/public/js/stage_bwtz.js

@@ -0,0 +1,69 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+$(document).ready(() => {
+    const preUrl = window.location.pathname.split('/').slice(0, 6).join('/');
+    autoFlashHeight();
+    const xmjSpread = SpreadJsObj.createNewSpread($('#xmj-spread')[0]);
+    const xmjSheet = xmjSpread.getActiveSheet();
+    SpreadJsObj.initSheet(xmjSheet, xmjSpreadSetting);
+
+    const unitSpread = SpreadJsObj.createNewSpread($('#unit-spread')[0]);
+    const unitSheet = unitSpread.getActiveSheet();
+    SpreadJsObj.initSheet(unitSheet, unitSpreadSetting);
+
+    const unitTreeObj = {
+        loadCurUnitData: function () {
+            const node = SpreadJsObj.getSelectObject(xmjSheet);
+            if (node && node.unitTree) {
+                SpreadJsObj.loadSheetData(unitSheet, SpreadJsObj.DataType.Tree, node.unitTree);
+            } else {
+                SpreadJsObj.initSheet(unitSheet, unitSpreadSetting);
+            }
+        }
+    };
+    xmjSpread.bind(spreadNS.Events.SelectionChanged, unitTreeObj.loadCurUnitData);
+
+    postData(preUrl + '/load', { filter: 'ledger;pos;change' }, function (result) {
+        billsPosConvertModel.loadData(result.ledgerData, result.posData, result.changeData);
+        const xmjTree = billsPosConvertModel.convert();
+        SpreadJsObj.loadSheetData(xmjSheet, SpreadJsObj.DataType.Tree, xmjTree);
+        unitTreeObj.loadCurUnitData();
+    });
+
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
+        callback: function (info) {
+            if (info.mini) {
+                $('.panel-title').addClass('fluid');
+                $('#sub-menu').removeClass('panel-sidebar');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+            }
+            autoFlashHeight();
+            xmjSpread.refresh();
+            unitSpread.refresh();
+        }
+    });
+    // 加载上下窗口resizer
+    $.divResizer({
+        select: '#main-resize',
+        callback: function () {
+            xmjSpread.refresh();
+            let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
+            $(".sp-wrap").height(bcontent-30);
+            unitSpread.refresh();
+        }
+    });
+});

+ 1 - 1
app/public/js/stage_change.js

@@ -157,7 +157,7 @@ $(document).ready(() => {
         callback: function () {
             changeSpread.refresh();
             let bcontent = $(".bcontent-wrap").length > 0 ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-40);
+            $(".sp-wrap").height(bcontent-30);
             if ($('#qingdan').hasClass('active')) {
                 billsSpread.refresh();
                 posSpread.refresh();

+ 1 - 1
app/public/js/stage_compare.js

@@ -114,7 +114,7 @@ $(document).ready(function () {
         callback: function () {
             ledgerSpread.refresh();
             let bcontent = $(".bcontent-wrap").length > 0 ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-40);
+            $(".sp-wrap").height(bcontent-30);
             posSpread.refresh();
         }
     });

+ 1 - 1
app/public/js/stage_gather.js

@@ -196,7 +196,7 @@ $(document).ready(function () {
         callback: function () {
             gclSpread.refresh();
             let bcontent = $(".bcontent-wrap") ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-40);
+            $(".sp-wrap").height(bcontent-30);
             leafXmjSpread.refresh();
         }
     });

+ 6 - 2
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'];
+    const imFields = ['uuid', 'doc_code', 'peg', 'bw', 'xm', 'drawing_code', 'calc_memo', 'calc_img', 'position'];
     const splitChar = '-';
     const mergeChar = ';';
     let stage, imType, details, changes, ImData, pre;
@@ -411,6 +411,7 @@ const stageIm = (function () {
                 jl: node.gather_tp, contract_jl: node.contract_tp, qc_jl: node.qc_tp,
                 //im_code: getNewImCode(),
                 peg: peg ? getPegStr(peg.name) : '', drawing_code: getDrawingCode(node),
+                position: '',
             };
             if (stage.im_gather && node.check) {
                 im.bw = getZlGatherBw(node, peg);
@@ -512,7 +513,8 @@ const stageIm = (function () {
                 im = {
                     lid: node.id, pid: '', code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
                     jl: 0, contract_jl: 0, qc_jl: 0,
-                    peg: peg ? getPegStr(peg.name) : ''
+                    peg: peg ? getPegStr(peg.name) : '',
+                    position: '',
                 };
                 if (stage.im_gather && node.check) {
                     im.bw = getZlGatherBw(node, peg);
@@ -557,6 +559,7 @@ const stageIm = (function () {
                         xm: pp.name,
                         drawing_code: pp.drawing_code,
                         changes: [],
+                        position: pp.position,
                     };
                     im.calc_memo = '本期计量:' + im.jl + ' ' + im.unit;
                     checkCustomDetail(im);
@@ -581,6 +584,7 @@ const stageIm = (function () {
                     xm: node.name,
                     drawing_code: getDrawingCode(p),
                     changes: [],
+                    position: '',
                 };
                 im.calc_memo = '本期计量:' + im.jl + ' ' + im.unit;
                 checkCustomDetail(im);

+ 2 - 0
app/router.js

@@ -184,6 +184,8 @@ module.exports = app => {
     app.post('/tender/:id/measure/stage/:order/audit/start', sessionAuth, tenderCheck, stageCheck, 'stageController.startAudit');
     app.post('/tender/:id/measure/stage/:order/audit/check', sessionAuth, tenderCheck, stageCheck, 'stageController.checkAudit');
     app.get('/tender/:id/measure/stage/:order/audit/check/again', sessionAuth, tenderCheck, stageCheck, 'stageController.checkAuditAgain');
+    // 部位台账
+    app.get('/tender/:id/measure/stage/:order/bwtz', sessionAuth, tenderCheck, stageCheck, 'stageController.bwtz');
     // 清单汇总
     app.get('/tender/:id/measure/stage/:order/gather', sessionAuth, tenderCheck, stageCheck, 'stageController.gather');
     // 审核比较

+ 9 - 4
app/service/stage_pos.js

@@ -225,22 +225,26 @@ module.exports = app => {
             const result = {ledger: [], pos: [], stageUpdate: true}, ledgerCalc = [];
             const datas = data instanceof Array ? data : [data];
             const orgPos = await this.ctx.service.pos.getPosDataByIds(this._.map(datas, 'pid'));
-            const orgStagePos = await this.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, {pid: this._.map(datas, 'pid')});
+            const orgStagePos = await this.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id,
+                {pid: this._.map(datas, 'pid')});
 
             const transaction = await this.db.beginTransaction();
             try {
                 for (const d of datas) {
-                    if (d.sgfh_qty !== undefined || d.qtcl_qty !== undefined || d.sjcl_qty !== undefined || d.contract_qty !== undefined || d.qc_qty !== undefined) {
+                    if (d.sgfh_qty !== undefined || d.qtcl_qty !== undefined || d.sjcl_qty !== undefined
+                        || d.contract_qty !== undefined || d.qc_qty !== undefined) {
                         if (!bills || bills.id !== data.lid) {
                             bills = await this.ctx.service.ledger.getDataById(d.lid);
                             precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, bills.unit);
                         }
                     }
-                    if (d.name !== undefined || d.sgfh_qty !== undefined || d.qtcl_qty !== undefined || d.sjcl_qty !== undefined || d.drawing_code !== undefined) {
+                    if (d.name !== undefined || d.drawing_code !== undefined || d.position !== undefined
+                        || d.sgfh_qty !== undefined || d.qtcl_qty !== undefined || d.sjcl_qty !== undefined) {
                         const op = this._.find(orgPos, {id: d.pid});
                         if (op.add_stage !== this.ctx.stage.id) throw '不可修改数据';
                         const p = {id: d.pid};
                         if (d.name !== undefined) p.name = d.name;
+                        if (d.position !== undefined) p.position = d.position;
                         if (d.sgfh_qty !== undefined || d.qtcl_qty !== undefined || d.sjcl_qty !== undefined) {
                             p.sgfh_qty = d.sgfh_qty !== undefined ? d.sgfh_qty : op.sgfh_qty;
                             p.sjcl_qty = d.sjcl_qty !== undefined ? d.sjcl_qty : op.sjcl_qty;
@@ -293,7 +297,8 @@ module.exports = app => {
                     }
                     result.pos.push(d.pid);
                     if ((d.sgfh_qty !== undefined || d.qtcl_qty !== undefined || d.sjcl_qty !== undefined ||
-                            d.contract_qty === undefined || d.qc_qty === undefined) && (result.ledger.indexOf(d.lid) === -1)) {
+                            d.contract_qty === undefined || d.qc_qty === undefined)
+                         && (result.ledger.indexOf(d.lid) === -1)) {
                         result.ledger.push(d.lid);
                     }
                 }

+ 3 - 3
app/view/change/info.ejs

@@ -63,10 +63,10 @@
         text-align: center !important;
     }
     .change-title {
-        font-size: 16px;
+        font-size: 12px;
         margin: 0;
-        height: 50px;
-        line-height: 50px;
+        height: 34px;
+        line-height: 34px;
         display: block;
     }
 </style>

+ 1 - 1
app/view/report/index.ejs

@@ -26,7 +26,7 @@
         <div class="c-body">
             <div class="row">
                 <div class="col-auto pr-0" id="tree-view" style="width: 17%">
-                    <div class="sjs-height-1">
+                    <div class="sjs-height-1" style="overflow: auto">
                         <div class="text-center"></div>
                         <ul id="rptTplTree" class="ztree"></ul>
                     </div>

+ 101 - 0
app/view/stage/bwtz.ejs

@@ -0,0 +1,101 @@
+<% include ./stage_sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main d-flex justify-content-between">
+            <% include ./stage_sub_mini_menu.ejs %>
+            <div>
+                <div class="d-inline-block">
+                    部位台帐
+                </div>
+            </div>
+            <div class="ml-auto">
+            </div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header p-0"></div>
+        <div class="c-body">
+            <div class="sjs-height-1" id="xmj-spread">
+            </div>
+            <div class="bcontent-wrap" id="main-bottom">
+                <div id="main-resize" class="resize-y" r-Type="height" div1="#xmj-spread" div2="#main-bottom" store-id="stage-bwtz" store-version="1.0.0" min="100"></div>
+                <div class="bc-bar mb-1">
+                    <ul class="nav nav-tabs">
+                        <li class="nav-item">
+                            <a class="nav-link active" data-toggle="tab" href="#jldyjlqd" role="tab">计量单元/计量清单</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="sp-wrap" id="unit-spread">
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+<script>
+    const xmjSpreadSetting = {
+        cols: [
+            {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', cellType: 'tree'},
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@'},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', cellType: 'unit'},
+            <% if (ctx.tender.info.display.ledger.dgnQty) { %>
+            {title: '项目节数量|数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|数量2',  colSpan: '|1', rowSpan: '|1', field: 'dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
+            {title: '经济指标',  colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number'},
+            <% } %>
+            {title: '台账金额', colSpan: '1', rowSpan: '2', field: 'total_price', hAlign: 2, width: 70, type: 'Number'},
+            {title: '本期计量金额|合同计量', colSpan: '3|1', rowSpan: '1|1', field: 'contract_tp', hAlign: 2, width: 70, type: 'Number'},
+            {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_tp', hAlign: 2, width: 70, type: 'Number'},
+            {title: '|完成计量', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 70, type: 'Number'},
+            {title: '截止本期计量金额|合同计量', colSpan: '4|1', rowSpan: '1|1', field: 'end_contract_tp', hAlign: 2, width: 70, type: 'Number'},
+            {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 70, type: 'Number'},
+            {title: '|完成计量', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 70, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 70, type: 'Number'},
+            {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
+            {title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+    };
+    const unitSpreadSetting = {
+        cols: [
+            {title: '计量单元', colSpan: '1', rowSpan: '2', field: 'pos_name', hAlign: 0, width: 120, formatter: '@', cellType: 'tree'},
+            {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@'},
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@'},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', cellType: 'unit'},
+            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number'},
+            {title: '台账|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'contract_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期数量变更|数量', colSpan: '3|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'qc_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|变更令', colSpan: '|1', rowSpan: '|1', field: 'bgl_code', hAlign: 2, width: 60, formatter: '@', cellType: 'ellipsisAutoTip'},
+            {title: '本期完成计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '截止本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '截止本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
+            {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
+            {title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+    };
+</script>

+ 8 - 1
app/view/stage/index.ejs

@@ -128,6 +128,7 @@
                                 <tr><th>部位</th><td id="show-bw-name"></td></tr>
                                 <tr><th>起止桩号</th><td id="show-peg"></td></tr>
                                 <tr><th>细目</th><td id="show-xm-name"></td></tr>
+                                <tr><th>位置</th><td id="show-position"></td></tr>
                                 <tr><th>图册号</th><td id="show-drawing-code"></td></tr>
                                 <tr><th colspan="2">计算式说明</th></tr>
                                 <tr><td colspan="2" id="show-calc-memo" style="word-wrap:break-word"></td></tr>
@@ -147,7 +148,7 @@
                                     <div class="input-group-prepend">
                                         <span class="input-group-text" id="type-title-qc">本期变更计量数量</span>
                                     </div>
-                                    <input type="text" class="form-control" value="" id="qc-jl"readonly="">
+                                    <input type="text" class="form-control" value="" id="qc-jl" readonly="">
                                 </div>
                                 <div class="input-group input-group-sm mb-2">
                                     <div class="input-group-prepend">
@@ -181,6 +182,12 @@
                                 </div>
                                 <div class="input-group input-group-sm mb-2">
                                     <div class="input-group-prepend">
+                                        <span class="input-group-text"style="width: 66px">位置</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" id="position">
+                                </div>
+                                <div class="input-group input-group-sm mb-2">
+                                    <div class="input-group-prepend">
                                         <span class="input-group-text" style="width: 66px">图册号</span>
                                     </div>
                                     <input type="text" class="form-control" value="" id="drawing-code">

+ 7 - 0
app/view/stage/stage_sub_menu.ejs

@@ -26,6 +26,13 @@
         </div>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
+                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/bwtz') { %>active<% } %>">
+                    <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/bwtz"><span class="ml-3">部位台帐</span></a>
+                </li>
+            </ul>
+        </div>
+        <div class="nav-box">
+            <ul class="nav-list list-unstyled">
                 <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/change') { %>active<% } %>">
                     <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/change"><span class="ml-3">变更概况</span></a>
                 </li>

+ 7 - 0
app/view/stage/stage_sub_mini_menu.ejs

@@ -26,6 +26,13 @@
         </div>
         <div class="nav-box">
             <ul class="nav-list list-unstyled">
+                <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/bwtz') { %>active<% } %>">
+                    <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/bwtz"><span class="ml-3">部位台帐</span></a>
+                </li>
+            </ul>
+        </div>
+        <div class="nav-box">
+            <ul class="nav-list list-unstyled">
                 <li class="<% if (ctx.url === '/tender/' + ctx.tender.id + '/measure/stage/' + ctx.stage.order + '/change') { %>active<% } %>">
                     <a href="/tender/<%- ctx.tender.id %>/measure/stage/<%- stage.order %>/change"><span class="ml-3">变更概况</span></a>
                 </li>

+ 17 - 0
config/web.js

@@ -283,6 +283,23 @@ const JsFiles = {
                 ],
                 mergeFile: 'stage_pay',
             },
+            bwtz: {
+                files: [
+                    "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
+                    "/public/js/decimal.min.js",
+                ],
+                mergeFiles: [
+                    "/public/js/sub_menu.js",
+                    "/public/js/div_resizer.js",
+                    "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/zh_calc.js",
+                    "/public/js/path_tree.js",
+                    "/public/js/shares/bills_pos_convert.js",
+                    "/public/js/stage_bwtz.js",
+                    "/public/js/stage_audit.js",
+                ],
+                mergeFile: 'stage_bwtz',
+            },
             change: {
                 files: [
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",