Bläddra i källkod

多期比较,工程量清单汇总

MaiXinRong 2 år sedan
förälder
incheckning
28d30e1918
4 ändrade filer med 218 tillägg och 58 borttagningar
  1. 18 4
      app/public/js/gcl_gather.js
  2. 110 2
      app/public/js/measure_compare.js
  3. 89 52
      app/view/measure/compare.ejs
  4. 1 0
      config/web.js

+ 18 - 4
app/public/js/gcl_gather.js

@@ -11,11 +11,11 @@
 
 const gclGatherModel = (function () {
     // 需要汇总计算的字段
-    const ledgerGatherFields = ['quantity', 'total_price', 'deal_qty', 'deal_tp',
+    let ledgerGatherFields = ['quantity', 'total_price', 'deal_qty', 'deal_tp',
         'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty',
         'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_qc_minus_qty',
         'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_qc_minus_qty'];
-    const posGatherFields = ['quantity', 'contract_qty', 'qc_qty', 'gather_qty','qc_minus_qty',
+    let posGatherFields = ['quantity', 'contract_qty', 'qc_qty', 'gather_qty','qc_minus_qty',
         'pre_contract_qty', 'pre_qc_qty', 'pre_gather_qty', 'pre_qc_minus_qty',
         'end_contract_qty', 'end_qc_qty', 'end_gather_qty', 'end_qc_minus_qty'];
     // 初始化 清单树
@@ -46,6 +46,11 @@ const gclGatherModel = (function () {
         tpDecimal = decimal.tp;
     }
 
+    function loadGatherField(ledger, pos) {
+        if (ledger) ledgerGatherFields = ledger;
+        if (pos) posGatherFields = pos;
+    }
+
     /**
      * 将所有数据加载至树结构
      *
@@ -82,8 +87,16 @@ const gclGatherModel = (function () {
 
     function gatherfields(obj, src, fields) {
         if (obj && src) {
-            for (const f of fields) {
-                obj[f] = ZhCalc.add(obj[f], src[f]);
+            if (fields instanceof Array) {
+                for (const f of fields) {
+                    obj[f] = ZhCalc.add(obj[f], src[f]);
+                }
+            } else if (typeof fields === "function") {
+                for (const prop in src) {
+                    if (fields(prop)) {
+                        obj[prop] = ZhCalc.add(obj[prop], src[prop]);
+                    }
+                }
             }
         }
     }
@@ -573,6 +586,7 @@ const gclGatherModel = (function () {
     }
 
     return {
+        loadGatherField,
         loadDecimal,
         loadLedgerData,
         loadPosData,

+ 110 - 2
app/public/js/measure_compare.js

@@ -49,6 +49,55 @@ const posSpreadSetting = {
     readOnly: true,
     selectedBackColor: '#fffacd',
 };
+
+const gclSpreadSetting = {
+    baseCols: [
+        {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
+        {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 230, 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: 'deal_bills_qty', hAlign: 2, width: 60, type: 'Number'},
+        {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'deal_bills_tp', 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'},
+    ],
+    extraCols: [
+        {title: '%s|数量', colSpan: '2|1', rowSpan: '1|1', field: '{%s}_qty{%d}', hAlign: 2, width: 60, type: 'Number', },
+        {title: '|金额', colSpan: '|1', rowSpan: '|1', field: '{%s}_tp{%d}', hAlign: 2, width: 60, type: 'Number', },
+    ],
+    emptyRows: 0,
+    headRows: 2,
+    headRowHeight: [25, 25],
+    headColWidth: [30],
+    defaultRowHeight: 21,
+    headerFont: '12px 微软雅黑',
+    font: '12px 微软雅黑',
+    readOnly: true,
+};
+const leafXmjSpreadSetting = {
+    baseCols: [
+        {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 100, formatter: '@'},
+        {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, type: 'Number'},
+        {title: '单位工程', colSpan: '1', rowSpan: '2', field: 'dwgc', hAlign: 0, width: 80, formatter: '@'},
+        {title: '分部工程', colSpan: '1', rowSpan: '2', field: 'fbgc', hAlign: 0, width: 80, formatter: '@'},
+        {title: '分项工程', colSpan: '1', rowSpan: '2', field: 'fxgc', hAlign: 0, width: 80, formatter: '@'},
+        {title: '细目', colSpan: '1', rowSpan: '2', field: 'jldy', hAlign: 0, width: 80, formatter: '@'},
+        {title: '计量单元', colSpan: '1', rowSpan: '2', field: 'bwmx', hAlign: 0, width: 80, formatter: '@'},
+        {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
+    ],
+    extraCols: [
+        {title: '%s数量', colSpan: '1', rowSpan: '2', field: '{%s}_qty{%d}', hAlign: 2, width: 60},
+    ],
+    emptyRows: 0,
+    headRows: 2,
+    headRowHeight: [25, 25],
+    headColWidth: [30],
+    defaultRowHeight: 21,
+    headerFont: '12px 微软雅黑',
+    font: '12px 微软雅黑',
+    readOnly: true,
+};
+
 function initSpreadSettingWithRoles(compareRoles) {
     function setSpreadSettingCols(setting, fieldSufs, Roles) {
         function addExtraCols(fieldSuf, Role) {
@@ -80,6 +129,8 @@ function initSpreadSettingWithRoles(compareRoles) {
     }
     setSpreadSettingCols(billsSpreadSetting, fieldSufs, roles);
     setSpreadSettingCols(posSpreadSetting, fieldSufs, roles);
+    setSpreadSettingCols(gclSpreadSetting, fieldSufs, roles);
+    setSpreadSettingCols(leafXmjSpreadSetting, fieldSufs, roles);
 }
 function calculateStageLedgerData(datas) {
     for (const d of datas) {
@@ -106,6 +157,17 @@ $(document).ready(() => {
     if (thousandth) sjsSettingObj.setTpThousandthFormat(posSpreadSetting);
     SpreadJsObj.initSheet(posSheet, posSpreadSetting);
 
+    let gclGatherData;
+    const gclSpread = SpreadJsObj.createNewSpread($('#gcl-spread')[0]);
+    const gclSheet = gclSpread.getActiveSheet();
+    sjsSettingObj.setFxTreeStyle(gclSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(gclSpreadSetting);
+    SpreadJsObj.initSheet(gclSheet, gclSpreadSetting);
+    const leafXmjSpread = SpreadJsObj.createNewSpread($('#leaf-xmj-spread')[0]);
+    const leafXmjSheet = leafXmjSpread.getActiveSheet();
+    if (thousandth) sjsSettingObj.setTpThousandthFormat(leafXmjSpreadSetting);
+    SpreadJsObj.initSheet(leafXmjSheet, leafXmjSpreadSetting);
+
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
@@ -129,11 +191,20 @@ $(document).ready(() => {
         select: '#main-resize',
         callback: function () {
             billsSpread.refresh();
-            let bcontent = $(".bcontent-wrap").length > 0 ? $(".bcontent-wrap").height() : 0;
-            $(".sp-wrap").height(bcontent-30);
+            let bcontent = $("#xmujie").length > 0 ? $("#xmujie").height() : 0;
+            $("#pos-spread").height(bcontent-30);
             posSpread.refresh();
         }
     });
+    $.divResizer({
+        select: '#gcl-resize',
+        callback: function () {
+            gclSpread.refresh();
+            let bcontent = $("#leafxmj-bottom").length > 0 ? $("#leafxmj-bottom").height() : 0;
+            $("#leaf-xmj-spread").height(bcontent-30);
+            leafXmjSpread.refresh();
+        }
+    });
 
     const cTree = createNewPathTree('master', {
         id: 'ledger_id',
@@ -160,6 +231,20 @@ $(document).ready(() => {
         cPos.loadDatas(result.main.pos);
         SpreadJsObj.loadSheetData(billsSheet, SpreadJsObj.DataType.Tree, cTree);
         loadPosData(0);
+
+        const checkField = function (x) {
+            if (x === 'quantity') return true;
+            if (x === 'total_price') return true;
+            if (x.indexOf('_qty') >= 0) return true;
+            if (x.indexOf('_tp') >= 0) return true;
+            return false;
+        };
+        gclGatherModel.loadGatherField(checkField, checkField);
+        gclGatherModel.loadLedgerData(result.main.ledger);
+        gclGatherModel.loadPosData(result.main.pos);
+        gclGatherData = gclGatherModel.gatherGclData();
+        SpreadJsObj.loadSheetData(gclSheet, SpreadJsObj.DataType.Data, gclGatherData);
+        loadLeafXmjData(0);
     }, null, true);
     function loadPosData(iRow) {
         const node = iRow ? billsSheet.zh_tree.nodes[iRow] : SpreadJsObj.getSelectObject(billsSheet);
@@ -167,6 +252,15 @@ $(document).ready(() => {
         SpreadJsObj.loadSheetData(posSheet, SpreadJsObj.DataType.Data, posRange);
         SpreadJsObj.resetTopAndSelect(posSheet);
     }
+    function loadLeafXmjData(iRow) {
+        const gcl = iRow ? gclSheet.zh_data[iRow] : SpreadJsObj.getSelectObject(gclSheet);
+        if (gcl) {
+            SpreadJsObj.loadSheetData(leafXmjSheet, SpreadJsObj.DataType.Data, gcl.leafXmjs);
+        } else {
+            SpreadJsObj.loadSheetData(leafXmjSheet, SpreadJsObj.DataType.Data, []);
+        }
+        SpreadJsObj.resetTopAndSelect(leafXmjSheet);
+    }
     billsSheet.bind(spreadNS.Events.SelectionChanged, function (e, info) {
         if (info.newSelections) {
             const iNewRow = info.newSelections[0].row;
@@ -197,6 +291,15 @@ $(document).ready(() => {
             SpreadJsObj.loadSheetData(billsSheet, SpreadJsObj.DataType.Tree, cTree);
             SpreadJsObj.initSheet(posSheet, posSpreadSetting);
             loadPosData();
+
+            SpreadJsObj.reLoadSheetHeader(gclSheet);
+            SpreadJsObj.reLoadSheetHeader(leafXmjSheet);
+
+            gclGatherModel.loadLedgerData(cTree.datas);
+            gclGatherModel.loadPosData(cPos.datas);
+            gclGatherData = gclGatherModel.gatherGclData();
+            SpreadJsObj.loadSheetData(gclSheet, SpreadJsObj.DataType.Data, gclGatherData);
+            loadLeafXmjData(0);
         }
         let loadData = [], showData = [], trs = $('tr[stage-id]');
         for (let order = 0, iLength = trs.length; order < iLength; order++) {
@@ -273,5 +376,10 @@ $(document).ready(() => {
         SpreadJsObj.reloadColData(billsSheet, 7, compareStages.length * 2);
         SpreadJsObj.reLoadSheetHeader(posSheet);
         SpreadJsObj.reloadColData(posSheet, 2, compareStages.length);
+
+        SpreadJsObj.reLoadSheetHeader(gclSheet);
+        SpreadJsObj.reloadColData(billsSheet, 9, compareStages.length * 2);
+        SpreadJsObj.reLoadSheetHeader(leafXmjSheet);
+        SpreadJsObj.reloadColData(posSheet, 9, compareStages.length);
     })
 });

+ 89 - 52
app/view/measure/compare.ejs

@@ -4,66 +4,103 @@
         <div class="title-main d-flex">
             <% include ../tender/tender_sub_mini_menu.ejs %>
             <div>
-                <div class="d-inline-block">
-                    <div class="dropdown">
-                        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                            <i class="fa fa-list-ol"></i> 显示层级
-                        </button>
-                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
-                            <a class="dropdown-item" name="showLevel" tag="1" href="javascirpt: void(0);">第一层</a>
-                            <a class="dropdown-item" name="showLevel" tag="2" href="javascirpt: void(0);">第二层</a>
-                            <a class="dropdown-item" name="showLevel" tag="3" href="javascirpt: void(0);">第三层</a>
-                            <a class="dropdown-item" name="showLevel" tag="4" href="javascirpt: void(0);">第四层</a>
-                            <a class="dropdown-item" name="showLevel" tag="5" href="javascirpt: void(0);">第五层</a>
-                            <a class="dropdown-item" name="showLevel" tag="last" href="javascirpt: void(0);">最底层</a>
-                            <a class="dropdown-item" name="showLevel" tag="leafXmj" href="javascirpt: void(0);">只显示项目节</a>
-                        </div>
-                    </div>
-                </div>
-                <div class="d-inline-block">
-                    <button href="#cate-set" class="btn btn-sm btn-light text-primary" data-toggle="modal" data-target="#select-qi"><i class="fa fa-clone"></i> 选择比较期</button>
-                </div>
-                <% if (ctx.app.config.is_debug) { %>
-                <div class="d-inline-block ml-3">
-                    <a id="exportExcel" class="btn btn-primary btn-sm" href="javascript: void(0)">导出清单汇总Excel</a>
-                </div>
-                <% } %>
-                <div class="d-inline-block ml-3">
-                    期数据来源:
-                    <div class="form-check form-check-inline">
-                        <input class="form-check-input" type="radio" id="radio_contract" value="contract" name="compare-data">
-                        <label class="form-check-label" for="radio_contract">合同</label>
-                    </div>
-                    <div class="form-check form-check-inline">
-                        <input class="form-check-input" type="radio" id="radio_qc" value="qc" name="compare-data">
-                        <label class="form-check-label" for="radio_qc">变更</label>
-                    </div>
-                    <div class="form-check form-check-inline">
-                        <input class="form-check-input" type="radio" id="radio_gather" value="gather" checked name="compare-data">
-                        <label class="form-check-label" for="radio_gather">完成</label>
-                    </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="#tz" role="tab">台账</a>
+                        </li>
+                        <li class="nav-item">
+                            <a class="nav-link" data-toggle="tab" href="#gcl" role="tab">工程量清单</a>
+                        </li>
+                        <li class="nav-item">
+                            <div>
+                                <div class="d-inline-block">
+                                    <div class="dropdown">
+                                        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                            <i class="fa fa-list-ol"></i> 显示层级
+                                        </button>
+                                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+                                            <a class="dropdown-item" name="showLevel" tag="1" href="javascirpt: void(0);">第一层</a>
+                                            <a class="dropdown-item" name="showLevel" tag="2" href="javascirpt: void(0);">第二层</a>
+                                            <a class="dropdown-item" name="showLevel" tag="3" href="javascirpt: void(0);">第三层</a>
+                                            <a class="dropdown-item" name="showLevel" tag="4" href="javascirpt: void(0);">第四层</a>
+                                            <a class="dropdown-item" name="showLevel" tag="5" href="javascirpt: void(0);">第五层</a>
+                                            <a class="dropdown-item" name="showLevel" tag="last" href="javascirpt: void(0);">最底层</a>
+                                            <a class="dropdown-item" name="showLevel" tag="leafXmj" href="javascirpt: void(0);">只显示项目节</a>
+                                        </div>
+                                    </div>
+                                </div>
+                                <div class="d-inline-block">
+                                    <button href="#cate-set" class="btn btn-sm btn-light text-primary" data-toggle="modal" data-target="#select-qi"><i class="fa fa-clone"></i> 选择比较期</button>
+                                </div>
+                                <% if (ctx.app.config.is_debug) { %>
+                                <div class="d-inline-block ml-3">
+                                    <a id="exportExcel" class="btn btn-primary btn-sm" href="javascript: void(0)">导出清单汇总Excel</a>
+                                </div>
+                                <% } %>
+                                <div class="d-inline-block ml-3">
+                                    期数据来源:
+                                    <div class="form-check form-check-inline">
+                                        <input class="form-check-input" type="radio" id="radio_contract" value="contract" name="compare-data">
+                                        <label class="form-check-label" for="radio_contract">合同</label>
+                                    </div>
+                                    <div class="form-check form-check-inline">
+                                        <input class="form-check-input" type="radio" id="radio_qc" value="qc" name="compare-data">
+                                        <label class="form-check-label" for="radio_qc">变更</label>
+                                    </div>
+                                    <div class="form-check form-check-inline">
+                                        <input class="form-check-input" type="radio" id="radio_gather" value="gather" checked name="compare-data">
+                                        <label class="form-check-label" for="radio_gather">完成</label>
+                                    </div>
+                                </div>
+                            </div>
+                        </li>
+                    </ul>
                 </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="bills-spread">
-            </div>
-            <div class="bcontent-wrap" id="main-bottom">
-                <div id="main-resize" class="resize-y"  r-Type="height" div1="#bills-spread" div2="#main-bottom" store-id="compare-main" 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="#xmujie" role="tab">计量单元</a>
-                        </li>
-                    </ul>
+            <div class="tab-content">
+                <div class="tab-pane active" id="tz">
+                    <div class="sjs-height-1" id="bills-spread">
+                    </div>
+                    <div class="bcontent-wrap" id="main-bottom">
+                        <div id="main-resize" class="resize-y"  r-Type="height" div1="#bills-spread" div2="#main-bottom" store-id="compare-main" 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="#xmujie" role="tab">计量单元</a>
+                                </li>
+                            </ul>
+                        </div>
+                        <div class="tab-content">
+                            <div class="tab-pane active" id="xmujie">
+                                <div class="sp-wrap" id="pos-spread">
+                                </div>
+                            </div>
+                        </div>
+                    </div>
                 </div>
-                <div class="tab-content">
-                    <div class="tab-pane active" id="xmujie">
-                        <div class="sp-wrap" id="pos-spread">
+                <div class="tab-pane active" id="gcl">
+                    <div class="sjs-height-1" id="gcl-spread">
+                    </div>
+                    <div class="bcontent-wrap" id="leafxmj-bottom">
+                        <div id="gcl-resize" class="resize-y" r-Type="height" div1="#gcl-spread" div2="#leafxmj-bottom" store-id="compare-stages-gcl" 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="#xmujie" role="tab">所属项目节</a>
+                                </li>
+                            </ul>
+                        </div>
+                        <div class="tab-content">
+                            <div class="tab-pane active" id="xmujie">
+                                <div class="sp-wrap" id="leaf-xmj-spread">
+                                </div>
+                            </div>
                         </div>
                     </div>
                 </div>

+ 1 - 0
config/web.js

@@ -611,6 +611,7 @@ const JsFiles = {
                     '/public/js/shares/sjs_setting.js',
                     '/public/js/zh_calc.js',
                     '/public/js/path_tree.js',
+                    '/public/js/gcl_gather.js',
                     '/public/js/measure_compare.js',
                 ],
                 mergeFile: 'measure_compare',