Prechádzať zdrojové kódy

动态投资,增幅计算允许用户配置,计算调整

MaiXinRong 1 mesiac pred
rodič
commit
3764cd666c

+ 0 - 1
app/controller/tender_controller.js

@@ -737,7 +737,6 @@ module.exports = app => {
             ctx.redirect(ctx.request.header.referer);
         }
 
-
         /**
          * 设置标段计量类型并调整到标段概况(Get)
          *

+ 75 - 2
app/public/js/budget_compare.js

@@ -49,6 +49,14 @@ $(document).ready(() => {
     const getStackedBarTip = function (data) {
         return data.stackedBarTips.join('\n');
     };
+    const comparePhase = [
+        { key: 'gu', name: '投资估算', dgn1: 'gu_dgn_qty1', dgn2: 'gu_dgn_qty2', tp: 'gu_tp'},
+        { key: 'gai', name: '设计概算', dgn1: 'gai_dgn_qty1', dgn2: 'gai_dgn_qty2', tp: 'gai_tp'},
+        { key: 'yu', name: '施工图预算', dgn1: 'yu_dgn_qty1', dgn2: 'yu_dgn_qty2', tp: 'yu_tp'},
+        { key: 'zb', name: '招标预算', dgn1: 'zb_dgn_qty1', dgn2: 'zb_dgn_qty2', tp: 'zb_tp'},
+        { key: 'tz', name: '台账', dgn1: 'dgn_qty1', dgn2: 'dgn_qty2', tp: 'total_price'},
+        { key: 'final', name: '预估决算', dgn1: 'final_dgn_qty1', dgn2: 'final_dgn_qty2', tp: 'final_tp'},
+    ];
     const spreadSetting = {
         cols: [
             {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 150, formatter: '@', cellType: 'tree'},
@@ -73,8 +81,8 @@ $(document).ready(() => {
             {title: '|经济指标', colSpan: '|1', rowSpan: '|1', field: 'final_dgn_price', hAlign: 2, width: 80, type: 'Number', bc_type: 'number', visible: false},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'final_tp', hAlign: 2, width: 80, type: 'Number', bc_type: 'number', visible: false},
             {title: '数据对比', colSpan: '1', rowSpan: '2', field: 'stackedBar', hAlign: 0, width: 300, cellType: 'stackedBar', stackedBarCover: false, bc_type: 'grid', visible: false, getTip: getStackedBarTip},
-            {title: '增幅%|数量1/数量2', colSpan: '2|1', rowSpan: '1|1', field: 'grow_dgn_qty', hAlign: 2, width: 80},
-            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'grow_tp', hAlign: 2, width: 80, type: 'Number'},
+            {title: '增幅%|数量1/数量2', colSpan: '2|1', rowSpan: '1|1', field: 'compare_dgn_qty', hAlign: 2, width: 80},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'compare_tp', hAlign: 2, width: 80, type: 'Number'},
         ],
         emptyRows: 0,
         headRows: 2,
@@ -91,6 +99,27 @@ $(document).ready(() => {
     sjsSettingObj.setFxTreeStyle(spreadSetting, sjsSettingObj.FxTreeStyle.jz);
     let sfSelect;
     const compareObj = {
+        comparePhase1: 'gai',
+        comparePhase2: 'final',
+        getCompareSelectHtml() {
+            const html = [];
+            for (const cp of comparePhase) {
+                html.push(`<option value="${cp.key}">${cp.name}</option>`);
+            }
+            return html.join('');
+        },
+        initCompare() {
+            const selectHtml = this.getCompareSelectHtml();
+            $('#compare1').html(selectHtml);
+            $('#compare2').html(selectHtml);
+        },
+        getCompareHint(phase1, phase2) {
+            if (!phase1) phase1 = this.comparePhase1;
+            if (!phase2) phase2 = this.comparePhase2;
+            const cp1 = comparePhase.find(x => { return x.key === phase1; });
+            const cp2 = comparePhase.find(x => { return x.key === phase2; });
+            return `增减幅度=(${cp2.name}-${cp1.name})/${cp1.name}*100%`;
+        },
         curFinalId() {
             return this.finalInfo ? this.finalInfo.id : undefined;
         },
@@ -233,6 +262,7 @@ $(document).ready(() => {
             const expandTag = getLocalCache('revise-compare-level');
             if (expandTag) compareObj.expand(compareTree, expandTag);
             this.calcStackedBar(compareTree);
+            this.reCalculateCompareData(compareTree);
             SpreadJsObj.loadSheetData(compareSheet, SpreadJsObj.DataType.Tree, compareTree);
         },
         loadFinalData(result, msg) {
@@ -251,9 +281,28 @@ $(document).ready(() => {
             const expandTag = getLocalCache('revise-compare-level');
             if (expandTag) compareObj.expand(finalTree, expandTag);
             this.calcStackedBar(finalTree);
+            this.reCalculateCompareData(finalTree);
             SpreadJsObj.loadSheetData(compareSheet, SpreadJsObj.DataType.Tree, finalTree);
             if (sfSelect) sfSelect.reloadSelect(this.finalInfo.tender);
         },
+        reCalculateCompareData(calcTree) {
+            const tree = calcTree || compareSheet.zh_tree;
+            if (!tree) return;
+
+            const cp1 = comparePhase.find(x => { return x.key === this.comparePhase1; });
+            const cp2 = comparePhase.find(x => { return x.key === this.comparePhase2; });
+            treeCalc.calculateAll(tree, function(node) {
+                node.compare_dgn_qty1 = node[cp1.dgn1] ? ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node[cp2.dgn1], node[cp1.dgn1]), node[cp1.dgn1], 4), 100) : 0;
+                node.compare_dgn_qty2 = node[cp1.dgn2] ? ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node[cp2.dgn1], node[cp1.dgn1]), node[cp1.dgn1], 4), 100) : 0;
+                node.compare_dgn_qty = node.compare_dgn_qty1
+                    ? (node.compare_dgn_qty2 ? node.compare_dgn_qty1 + '/' + node.compare_dgn_qty2 : node.compare_dgn_qty1)
+                    : (node.compare_dgn_qty2 ? '/' + node.compare_dgn_qty2 : '');
+                node.compare_tp = node[cp1.tp] ? ZhCalc.mul(ZhCalc.div(ZhCalc.sub(node[cp2.tp], node[cp1.tp]), node[cp1.tp], 4), 100) : 0;
+            });
+
+            const index = spreadSetting.cols.findIndex(x => { return x.field === 'compare_dgn_qty'});
+            SpreadJsObj.reloadColData(compareSheet, index, 2);
+        },
         loadCacheData(){
             let stackedBarCache = getLocalCache(stackedBarKey);
             if (stackedBarCache === null) stackedBarCache = 'gai_tp,total_price,final_tp';
@@ -295,6 +344,7 @@ $(document).ready(() => {
         }
     };
     compareObj.loadCacheData();
+    compareObj.initCompare();
     SpreadJsObj.initSheet(compareSheet, spreadSetting);
 
     function compareCode(str1, str2, symbol = '-') {
@@ -517,4 +567,27 @@ $(document).ready(() => {
         Cookies.set(ckColSetting, JSON.stringify(customDisplay), 30*24*60*60*1000);
         $('#row-view').modal('hide');
     });
+
+    $('#compare-set').on('show.bs.modal', function() {
+        $('#compare1').val(compareObj.comparePhase1);
+        $('#compare2').val(compareObj.comparePhase2);
+        $('#compare-active-hint').html(compareObj.getCompareHint());
+    });
+    $('#compare1').change(() => {
+        const phase1 = $('#compare1').val();
+        const phase2 = $('#compare2').val();
+        $('#compare-active-hint').html(compareObj.getCompareHint(phase1, phase2));
+    });
+    $('#compare2').change(() => {
+        const phase1 = $('#compare1').val();
+        const phase2 = $('#compare2').val();
+        $('#compare-active-hint').html(compareObj.getCompareHint(phase1, phase2));
+    });
+    $('#compare-set-ok').click(() => {
+        compareObj.comparePhase1 = $('#compare1').val();
+        compareObj.comparePhase2 = $('#compare2').val();
+        $('#compare-hint').html(compareObj.getCompareHint());
+        compareObj.reCalculateCompareData();
+        $('#compare-set').modal('hide');
+    })
 });

+ 5 - 4
app/public/js/path_tree.js

@@ -2304,8 +2304,8 @@ const treeCalc = {
         const setting = tree.setting;
         return Math.max.apply(Math, tree.datas.map(function (o) { return o[setting.level] }));
     },
-    calculateNode: function (tree, node) {
-        if (node.children && node.children.length > 0) {
+    calculateNode: function (tree, node, customFun) {
+        if (node.children && node.children.length > 0 && tree.setting.calcFields) {
             const gather = {};
             node.children.forEach(c => {
                 for (const cf of tree.setting.calcFields) {
@@ -2332,6 +2332,7 @@ const treeCalc = {
         if (tree.setting.calcFun) {
             tree.setting.calcFun(node);
         }
+        if (customFun) customFun(node);
     },
     calculateLevelNode: function (tree, level) {
         const setting = tree.setting;
@@ -2340,13 +2341,13 @@ const treeCalc = {
             this.calculateNode(tree, node);
         }
     },
-    calculateAll: function (tree) {
+    calculateAll: function (tree, customFun) {
         const [maxLevel, levelMap] = this.mapTreeNode(tree);
         for (let i = maxLevel; i >= 0; i--) {
             const levelNodes = levelMap[i];
             if (levelNodes && levelNodes.length > 0) {
                 for (const node of levelNodes) {
-                    this.calculateNode(tree, node);
+                    this.calculateNode(tree, node, customFun);
                 }
             }
         }

+ 6 - 0
app/view/budget/compare.ejs

@@ -89,6 +89,12 @@
                 </div>
             </div>
             <div class="ml-auto ml-number">
+                <div class="d-inline-block ml-2">
+                    <div class="alert text-warning p-1" id="compare-hint">增减幅度=(预估决算-设计概算)/设计概算*100%</div>
+                </div>
+                <div class="d-inline-block border-right">
+                    <button href="#compare-set" class="btn btn-sm btn-ligth text-primary" data-toggle="modal" data-target="#compare-set"><i class="fa fa-cog"></i></button>
+                </div>
                 <div class="d-inline-block">
                     <button href="#row-view" class="btn btn-sm btn-ligth text-primary" data-toggle="modal" data-target="#row-view"><i class="fa fa-table"></i> 列显示</button>
                 </div>

+ 37 - 0
app/view/budget/compare_modal.ejs

@@ -49,4 +49,41 @@
             </div>
         </div>
     </div>
+</div>
+<div class="modal fade" id="compare-set" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">设置</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label class="mb-2">增减幅度</label>
+                    <div class="col-6 mb-2">
+                        <div class="input-group input-group-sm">
+                            <div class="input-group-prepend">
+                                <span class="input-group-text" style="width:80px">对比阶段1</span>
+                            </div>
+                            <select class="form-control form-control-sm" id="compare1">
+                            </select>
+                        </div>
+                    </div>
+                    <div class="col-6 mb-2">
+                        <div class="input-group input-group-sm">
+                            <div class="input-group-prepend">
+                                <span class="input-group-text" style="width:80px">对比阶段2</span>
+                            </div>
+                            <select class="form-control form-control-sm" id="compare2">
+                            </select>
+                        </div>
+                    </div>
+                    <div class="alert-warning ml-3 p-1 pl-2" id="compare-active-hint">增减幅度=(预估决算-设计概算)/设计概算*100%</div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-sm btn-primary" id="compare-set-ok">确认</button>
+            </div>
+        </div>
+    </div>
 </div>

+ 1 - 1
app/view/spss/check_tz.ejs

@@ -38,7 +38,7 @@
             <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 id="main-resize" class="resize-y"  r-Type="height" div1="#bills-spread" div2="#main-bottom" store-id="check-tz" store-version="1.0.0" min="100"></div>
                 <div class="bc-bar mb-1">
                     <ul class="nav nav-tabs">
                         <li class="nav-item">