Browse Source

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/YangHuOperation

zhongzewei 6 years ago
parent
commit
acb4b2e0ab

+ 2 - 1
modules/all_models/vehicle_vessel_tax_items.js

@@ -15,7 +15,8 @@ const vehicleVesselTax = new Schema({
     ID: String,
     code: String,
     name: String,
-    spec: String,
+    type: Number,
+    specs: String,
     unit: String,
     vehicleVesselTax: Number, //车船税
     useTax: Number, //使用税

+ 39 - 7
modules/reports/rpt_component/helper/jpc_helper_cross_tab.js

@@ -1,4 +1,5 @@
 let JV = require('../jpc_value_define');
+let JE = require('../jpc_rte');
 let JpcCommonHelper = require('./jpc_helper_common');
 
 let JpcCrossTabHelper = {
@@ -27,7 +28,7 @@ let JpcCrossTabHelper = {
     },
     sortFieldValue: function(sIDX, eIDX, sortOrder, dataField, dataValSeq) {
         let tmpSeq = [];
-        if ((sortOrder) && (sortOrder != JV.TAB_FIELD_PROP_SORT_VAL_NOSORT)) {
+        if ((sortOrder) && (sortOrder !== JV.TAB_FIELD_PROP_SORT_VAL_NOSORT)) {
             if (sIDX >= 0 && eIDX >= sIDX && dataValSeq.length > eIDX) {
                 let reversed = 1;
                 if (sortOrder === JV.TAB_FIELD_PROP_SORT_VAL_DESC) {
@@ -38,7 +39,8 @@ let JpcCrossTabHelper = {
                 }
                 tmpSeq.sort(function(idx1, idx2) {
                     let rst = 0;
-                    if (isNaN(parseFloat(dataField[idx1])) || isNaN(parseFloat(dataField[idx1]))) {
+                    // if (isNaN(parseFloat(dataField[idx1])) || isNaN(parseFloat(dataField[idx1]))) {
+                    if (typeof (dataField[idx1]) === 'string' || typeof (dataField[idx1]) === 'string' ) {
                         if (dataField[idx1] > dataField[idx2]) {
                             rst = reversed;
                         } else if (dataField[idx1] < dataField[idx2]) {
@@ -72,12 +74,12 @@ let JpcCrossTabHelper = {
         }
         return rst;
     },
-    sortTabFields: function(tabFields, fieldSeqs, data_details, dataSeq) {
+    sortTabFields: function(tabFields, fieldSeqs, data_details, dataSeq, $CURRENT_RPT) {
         let me = this;
         let sIDX = 0, eIDX = -1, isFirstSort = true;
         for (let i = 0; i < tabFields.length; i++) {
             let tabField = tabFields[i];
-            if (tabField[JV.TAB_FIELD_PROP_SORT] != JV.TAB_FIELD_PROP_SORT_VAL_NOSORT) {
+            if (tabField[JV.TAB_FIELD_PROP_SORT] !== JV.TAB_FIELD_PROP_SORT_VAL_NOSORT) {
                 if (isFirstSort) {
                     isFirstSort = false;
                     //first field, should sort all data items
@@ -85,14 +87,34 @@ let JpcCrossTabHelper = {
                         sIDX = 0;
                         eIDX = dataSeq[j].length - 1;
                         //sort the field value here
-                        me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                        if (typeof(fieldSeqs[i]) === "object") {
+                            let exFirstField = JE.F(fieldSeqs[i][JV.PROP_ID], $CURRENT_RPT);
+                            if (exFirstField) {
+                                me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT], exFirstField[JV.PROP_AD_HOC_DATA], dataSeq[j]);
+                            } else {
+                                //不排序(健壮性)
+                            }
+                        } else {
+                            me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                        }
+                        // me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
                     }
                 } else {
                     //then sort the rest fields one by one
                     for (let j = 0; j < dataSeq.length; j++) {
                         let chkFields = [];
                         for (let k = 0; k < i; k++) {
-                            chkFields.push(data_details[fieldSeqs[k]]);
+                            if (typeof(fieldSeqs[k]) === "object") {
+                                let exField = JE.F(fieldSeqs[k][JV.PROP_ID], $CURRENT_RPT);
+                                if (exField) {
+                                    chkFields.push(exField[JV.PROP_AD_HOC_DATA]);
+                                } else {
+                                    chkFields.push(null);
+                                }
+                            } else {
+                                chkFields.push(data_details[fieldSeqs[k]]);
+                            }
+                            // chkFields.push(data_details[fieldSeqs[k]]);
                         }
                         sIDX = 0, eIDX = -1;
                         for (let m = 1; m < dataSeq[j].length; m++) {
@@ -103,7 +125,17 @@ let JpcCrossTabHelper = {
                             };
                             if (eIDX >= sIDX) {
                                 if (eIDX != sIDX) {
-                                    me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                                    if (typeof(fieldSeqs[i]) === "object") {
+                                        let exOtherField = JE.F(fieldSeqs[i][JV.PROP_ID], $CURRENT_RPT);
+                                        if (exOtherField) {
+                                            me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT], exOtherField[JV.PROP_AD_HOC_DATA], dataSeq[j]);
+                                        } else {
+                                            //不排序(健壮性)
+                                        }
+                                    } else {
+                                        me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
+                                    }
+                                    // me.sortFieldValue(sIDX, eIDX, tabField[JV.TAB_FIELD_PROP_SORT],data_details[fieldSeqs[i]], dataSeq[j]);
                                 }
                                 sIDX = m;
                                 eIDX = m - 1; //for protection purpose

+ 155 - 65
modules/reports/rpt_component/jpc_cross_tab.js

@@ -102,7 +102,7 @@ JpcCrossTabSrv.prototype.createNew = function(){
             }
         }
     }
-    function private_SortAndOptimize(rptTpl, dataObj, dataSeq, sortTab, rstFieldsIdx) {
+    function private_SortAndOptimize(rptTpl, dataObj, dataSeq, sortTab, rstFieldsIdx, $CURRENT_RPT) {
         let result = [];
         let tab = rptTpl[JV.NODE_CROSS_INFO][sortTab];
         if (tab) {
@@ -111,7 +111,7 @@ JpcCrossTabSrv.prototype.createNew = function(){
             let fields = [];
             JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, tab[JV.PROP_CROSS_FIELDS], fields, rstFieldsIdx);
             let data_details = dataObj[JV.DATA_DETAIL_DATA];
-            JpcCrossTabHelper.sortTabFields(fields, rstFieldsIdx, data_details, dataSeq);
+            JpcCrossTabHelper.sortTabFields(fields, rstFieldsIdx, data_details, dataSeq, $CURRENT_RPT);
             //2. distinguish sort tab fields value
             let b1 = false;
             for (let i = 0; i < dataSeq.length; i++) {
@@ -123,9 +123,17 @@ JpcCrossTabSrv.prototype.createNew = function(){
                     for (let j = 1; j < dataSeq[i].length; j++) {
                         b1 = false;
                         for (let k = 0; k < rstFieldsIdx.length; k++) {
-                            if (data_details[rstFieldsIdx[k]][dataSeq[i][j - 1]] !== data_details[rstFieldsIdx[k]][dataSeq[i][j]]) {
-                                b1 = true;
-                                break;
+                            if (typeof(rstFieldsIdx[k]) === 'object') {
+                                let map_data_field = JE.F(rstFieldsIdx[k][JV.PROP_ID], $CURRENT_RPT);
+                                if (map_data_field[JV.PROP_AD_HOC_DATA][dataSeq[i][j - 1]] !== map_data_field[JV.PROP_AD_HOC_DATA][dataSeq[i][j]]) {
+                                    b1 = true;
+                                    break;
+                                }
+                            } else {
+                                if (data_details[rstFieldsIdx[k]][dataSeq[i][j - 1]] !== data_details[rstFieldsIdx[k]][dataSeq[i][j]]) {
+                                    b1 = true;
+                                    break;
+                                }
                             }
                         }
                         if (b1) {
@@ -195,18 +203,26 @@ JpcCrossTabSrv.prototype.createNew = function(){
         me.pageStatusLst = [];
         me.paging_option = JV.PAGING_OPTION_NORMAL;
     };
-    JpcCrossTabResult.sorting = function(rptTpl, dataObj, dataSeq) {
+    JpcCrossTabResult.sorting = function(rptTpl, dataObj, dataSeq, $CURRENT_RPT) {
         let me = this;
         //IMPORTANT: the data should be sorted in SQL/NoSQL level!
-        me.sortedRowSequence = private_SortAndOptimize(rptTpl, dataObj, dataSeq, JV.NODE_CROSS_ROW, me.row_fields_idx);
-        me.sortedColSequence = private_SortAndOptimize(rptTpl, dataObj, dataSeq, JV.NODE_CROSS_COL, me.col_fields_idx);
+        me.sortedRowSequence = private_SortAndOptimize(rptTpl, dataObj, dataSeq, JV.NODE_CROSS_ROW, me.row_fields_idx, $CURRENT_RPT);
+        me.sortedColSequence = private_SortAndOptimize(rptTpl, dataObj, dataSeq, JV.NODE_CROSS_COL, me.col_fields_idx, $CURRENT_RPT);
         me.sortedContentSequence = private_SortForDisplayContent(rptTpl, me.sortedRowSequence, me.sortedColSequence, me.content_fields_idx);
         JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL_SUM][JV.PROP_CROSS_FIELDS], null, me.col_sum_fields_idx);
         //pre-sum the data(for col sum display)
         let data_details = dataObj[JV.DATA_DETAIL_DATA],
             data_fields = [];
         for (let i = 0; i < me.col_sum_fields_idx.length; i++) {
-            let data_field = data_details[me.col_sum_fields_idx[i]];
+            let data_field = null;
+            if (typeof me.col_sum_fields_idx[i] === 'object') {
+                let exField = JE.F(me.col_sum_fields_idx[i][JV.PROP_ID], $CURRENT_RPT);
+                if (exField) {
+                    data_field = exField[JV.PROP_AD_HOC_DATA];
+                }
+            } else {
+                data_field = data_details[me.col_sum_fields_idx[i]];
+            }
             data_fields.push(data_field);
         }
         for (let i = 0; i < me.sortedRowSequence.length; i++) { //seg level
@@ -244,25 +260,25 @@ JpcCrossTabSrv.prototype.createNew = function(){
         JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_SUM_EXT][JV.PROP_CROSS_FIELDS], null, me.row_sum_extension_fields_idx);
         if (me.paging_option === JV.PAGING_OPTION_INFINITY) {
             /*
-            rst = segCnt;
-            pageStatus[JV.STATUS_SEGMENT_START] = true;
-            pageStatus[JV.STATUS_SEGMENT_END] = true;
-            pageStatus[JV.STATUS_CROSS_ROW_END] = true;
-            pageStatus[JV.STATUS_CROSS_COL_END] = true;
-            for (let segIdx = 0; segIdx < segCnt; segIdx++) {
-                if (segIdx === segCnt - 1) {
-                    pageStatus[JV.STATUS_REPORT_END] = true;
-                }
-                if (segIdx > 0) {
-                    pageStatus[JV.STATUS_REPORT_START] = false;
-                }
-                me.pageStatusLst.push(pageStatus.slice(0));
-                pageIdx++;
-                private_addTabValue(me.dispValueIdxLst_Row, me.sortedRowSequence, segIdx, 0, me.sortedRowSequence[segIdx].length, me.dispSerialIdxLst_Row, me.col_sum_fields_value_total, me.dispSumValueLst_Col);
-                private_addTabValue(me.dispValueIdxLst_Col, me.sortedColSequence, segIdx, 0, me.sortedColSequence[segIdx].length, null, null, null);
-                private_addContentValue(me.dispValueIdxLst_Content, me.sortedContentSequence, segIdx, 0, me.sortedRowSequence[segIdx].length, 0, me.sortedColSequence[segIdx].length, me.page_seg_map, pageIdx);
-            }
-            //*/
+             rst = segCnt;
+             pageStatus[JV.STATUS_SEGMENT_START] = true;
+             pageStatus[JV.STATUS_SEGMENT_END] = true;
+             pageStatus[JV.STATUS_CROSS_ROW_END] = true;
+             pageStatus[JV.STATUS_CROSS_COL_END] = true;
+             for (let segIdx = 0; segIdx < segCnt; segIdx++) {
+             if (segIdx === segCnt - 1) {
+             pageStatus[JV.STATUS_REPORT_END] = true;
+             }
+             if (segIdx > 0) {
+             pageStatus[JV.STATUS_REPORT_START] = false;
+             }
+             me.pageStatusLst.push(pageStatus.slice(0));
+             pageIdx++;
+             private_addTabValue(me.dispValueIdxLst_Row, me.sortedRowSequence, segIdx, 0, me.sortedRowSequence[segIdx].length, me.dispSerialIdxLst_Row, me.col_sum_fields_value_total, me.dispSumValueLst_Col);
+             private_addTabValue(me.dispValueIdxLst_Col, me.sortedColSequence, segIdx, 0, me.sortedColSequence[segIdx].length, null, null, null);
+             private_addContentValue(me.dispValueIdxLst_Content, me.sortedContentSequence, segIdx, 0, me.sortedRowSequence[segIdx].length, 0, me.sortedColSequence[segIdx].length, me.page_seg_map, pageIdx);
+             }
+             //*/
         } else {
             for (let segIdx = 0; segIdx < segCnt; segIdx++) {
                 //2.1. seg level initialize
@@ -321,12 +337,78 @@ JpcCrossTabSrv.prototype.createNew = function(){
         bands = null;
         return rst;
     };
-    JpcCrossTabResult.outputAsPreviewPage = function (rptTpl, bands, controls, $CURRENT_RPT) {
+    JpcCrossTabResult.outputAsPreviewPage = function (rptTpl, bands, controls, $CURRENT_RPT, customizeCfg) {
         let me = this, rst = [];
         let pageStatus = [true, true, true, true, true, true, true, true];
         me.pageStatusLst.push(pageStatus);
         // JpcFieldHelper.findAndPutDataFieldIdx(rptTpl, rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_FLOW_FIELDS], null, me.disp_fields_idx, false);
         JpcBandHelper.setBandArea(bands, rptTpl, pageStatus, true, false);
+        let maxRowRec = JpcCrossTabHelper.getMaxRowsPerPage(bands, rptTpl);
+        let maxColRec = JpcCrossTabHelper.getMaxColsPerPage(bands, rptTpl);
+        let unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+        //1. 交叉行
+        rst = rst.concat(me.outputPreviewRowTab(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, unitFactor));
+        //2. 交叉列
+        rst = rst.concat(me.outputPreviewColTab(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxColRec, unitFactor));
+        //3. 交叉数据
+        rst = rst.concat(me.outputPreviewContent(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, maxColRec, unitFactor));
+        //4. 交叉行拓展
+        rst = rst.concat(me.outputPreviewTabExt(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, unitFactor));
+        //5. 交叉行拓展合计
+        rst = rst.concat(me.outputPreviewSumTabExt(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, unitFactor));
+        //6. 交叉列合计
+        rst = rst.concat(me.outputPreviewTabSum(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, JV.NODE_CROSS_COL_SUM, unitFactor));
+        //7. 离散
+        rst = rst.concat(JpcDiscreteHelper.outputPreviewDiscreteInfo(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_DISCRETE_INFO], bands, unitFactor, pageStatus));
+        return rst;
+    };
+    JpcCrossTabResult.outputPreviewRowTab = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, unitFactor) {
+        return this.private_OutputPreviewCommon(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, 1, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW], unitFactor);
+    };
+    JpcCrossTabResult.outputPreviewColTab = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxColRec, unitFactor) {
+        return this.private_OutputPreviewCommon(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, 1, maxColRec, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_COL], unitFactor);
+    };
+    JpcCrossTabResult.outputPreviewContent = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, maxColRec, unitFactor) {
+        return this.private_OutputPreviewCommon(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, maxColRec, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_CONTENT], unitFactor);
+    };
+    JpcCrossTabResult.outputPreviewTabSum = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, tabNodeName, unitFactor) {
+        return this.private_OutputPreviewCommon(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, 1, rptTpl[JV.NODE_CROSS_INFO][tabNodeName], unitFactor);
+    };
+    JpcCrossTabResult.outputPreviewTabExt = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, unitFactor) {
+        //交叉行拓展
+        return this.private_OutputPreviewCommon(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, 1, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_EXT], unitFactor);
+    };
+    JpcCrossTabResult.outputPreviewSumTabExt = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, unitFactor) {
+        //交叉行拓展合计
+        return this.private_OutputPreviewCommon(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, 1, rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW_SUM_EXT], unitFactor);
+    };
+    JpcCrossTabResult.private_OutputPreviewCommon = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg, maxRowRec, maxColRec, tab, unitFactor) {
+        let me = this, rst = [];
+        let band = bands[tab[JV.PROP_BAND_NAME]];
+        if (band) {
+            let tab_fields = tab[JV.PROP_CROSS_FIELDS];
+            for (let rowIdx = 0; rowIdx < maxRowRec; rowIdx++) {
+                for (let i = 0; i < tab_fields.length; i++) {
+                    let tab_field = tab_fields[i];
+                    if (!(tab_field[JV.PROP_HIDDEN])) {
+                        for (let colIdx = 0; colIdx < maxColRec; colIdx++) {
+                            if (tab_field[JV.PROP_IS_SERIAL]) {
+                                rst.push(me.outputTabField(band, tab_field, [rowIdx + 1], 0, -1, maxRowRec, rowIdx, maxColRec, colIdx, unitFactor, false, controls));
+                            } else {
+                                rst.push(me.outputTabField(band, tab_field, null, -1, -1, maxRowRec, rowIdx, maxColRec, colIdx, unitFactor, false, controls));
+                            }
+                        }
+                    }
+                }
+                if (tab[JV.PROP_TEXTS]) {
+                    for (let j = 0; j < tab[JV.PROP_TEXTS].length; j++) {
+                        for (let colIdx = 0; colIdx < maxColRec; colIdx++) {
+                            rst.push(JpcTextHelper.outputText(tab[JV.PROP_TEXTS][j], band, unitFactor, maxRowRec, rowIdx, maxColRec, colIdx, 1, 0));
+                        }
+                    }
+                }
+            }
+        }
         return rst;
     };
     JpcCrossTabResult.outputAsSimpleJSONPage = function(rptTpl, dataObj, page, bands, controls, $CURRENT_RPT, customizeCfg) {
@@ -334,33 +416,33 @@ JpcCrossTabSrv.prototype.createNew = function(){
         let unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
         if (me.paging_option === JV.PAGING_OPTION_INFINITY) {
             /*
-            let segIdx = page - 1;
-            //1 calculate the band position
-            JpcBandHelper.setBandArea(bands, rptTpl, me.pageStatusLst[page - 1]);
-            //2. then reset the band height
-            let tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_CONTENT];
-            let crossContentBand = bands[tab[JV.PROP_BAND_NAME]];
-            let actH = JpcCrossTabHelper.getActualRowsHeight(bands, rptTpl, me.sortedRowSequence, page);
-            let actW = JpcCrossTabHelper.getActualColsWidth(bands, rptTpl, me.sortedColSequence, page);
-            let offsetY = actH - (crossContentBand.Bottom - crossContentBand.Top);
-            let offsetX = actW - (crossContentBand.Right - crossContentBand.Left);
-            JpcBandHelper.resetBandPos(rptTpl[JV.NODE_BAND_COLLECTION], bands, crossContentBand, offsetX, offsetY);
+             let segIdx = page - 1;
+             //1 calculate the band position
+             JpcBandHelper.setBandArea(bands, rptTpl, me.pageStatusLst[page - 1]);
+             //2. then reset the band height
+             let tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_CONTENT];
+             let crossContentBand = bands[tab[JV.PROP_BAND_NAME]];
+             let actH = JpcCrossTabHelper.getActualRowsHeight(bands, rptTpl, me.sortedRowSequence, page);
+             let actW = JpcCrossTabHelper.getActualColsWidth(bands, rptTpl, me.sortedColSequence, page);
+             let offsetY = actH - (crossContentBand.Bottom - crossContentBand.Top);
+             let offsetX = actW - (crossContentBand.Right - crossContentBand.Left);
+             JpcBandHelper.resetBandPos(rptTpl[JV.NODE_BAND_COLLECTION], bands, crossContentBand, offsetX, offsetY);
 
-            //2.1 Row-Tab
-            tabRstLst.push(me.outputRowTab(rptTpl, dataObj, page, bands, unitFactor, controls));
-            //2.2 Col-Tab
-            tabRstLst.push(me.outputColTab(rptTpl, dataObj, page, bands, unitFactor, controls));
-            //2.3 Content-Tab
-            tabRstLst.push(me.outputContent(rptTpl, dataObj, page, bands, unitFactor, controls));
-            //2.4 Sum-Tab Row
-            //2.4 Sum-tab Col
-            tabRstLst.push(me.outputTabSum(rptTpl, dataObj, page, bands, unitFactor, JV.NODE_CROSS_COL_SUM, controls));
-            //2.x row tab ext
-            tabRstLst.push(me.outputTabExt(rptTpl, dataObj, page, bands, unitFactor, controls));
-            tabRstLst.push(me.outputSumTabExt(rptTpl, dataObj, page, bands, unitFactor, segIdx, controls));
-            //2.5 Discrete
-            tabRstLst.push(JpcDiscreteHelper.outputDiscreteInfo(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[page - 1], segIdx, 1, 0, $CURRENT_RPT, customizeCfg));
-            //*/
+             //2.1 Row-Tab
+             tabRstLst.push(me.outputRowTab(rptTpl, dataObj, page, bands, unitFactor, controls));
+             //2.2 Col-Tab
+             tabRstLst.push(me.outputColTab(rptTpl, dataObj, page, bands, unitFactor, controls));
+             //2.3 Content-Tab
+             tabRstLst.push(me.outputContent(rptTpl, dataObj, page, bands, unitFactor, controls));
+             //2.4 Sum-Tab Row
+             //2.4 Sum-tab Col
+             tabRstLst.push(me.outputTabSum(rptTpl, dataObj, page, bands, unitFactor, JV.NODE_CROSS_COL_SUM, controls));
+             //2.x row tab ext
+             tabRstLst.push(me.outputTabExt(rptTpl, dataObj, page, bands, unitFactor, controls));
+             tabRstLst.push(me.outputSumTabExt(rptTpl, dataObj, page, bands, unitFactor, segIdx, controls));
+             //2.5 Discrete
+             tabRstLst.push(JpcDiscreteHelper.outputDiscreteInfo(rptTpl[JV.NODE_CROSS_INFO][JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[page - 1], segIdx, 1, 0, $CURRENT_RPT, customizeCfg));
+             //*/
         } else {
             let segIdx = JpcCommonHelper.getSegIdxByPageIdx(page, me.page_seg_map);
             //1 calculate the band position
@@ -387,12 +469,6 @@ JpcCrossTabSrv.prototype.createNew = function(){
         }
         return rst;
     };
-    JpcCrossTabResult.outputPreviewRowTab = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg) {
-        //
-    };
-    JpcCrossTabResult.outputPreviewColTab = function(rptTpl, bands, controls, $CURRENT_RPT, customizeCfg) {
-        //
-    };
     JpcCrossTabResult.outputRowTab = function(rptTpl, dataObj, page, bands, unitFactor, controls, $CURRENT_RPT, customizeCfg) {
         let me = this, rst = [];
         let tab = rptTpl[JV.NODE_CROSS_INFO][JV.NODE_CROSS_ROW];
@@ -407,9 +483,16 @@ JpcCrossTabSrv.prototype.createNew = function(){
                 let flexiblePrecisionRefObj = null, flexibleRefField = null, precision_ref_data = null;
                 for (let i = 0; i < me.row_fields_idx.length; i++) {
                     let tab_field = tab_fields[i];
-                    let data_field = data_details[me.row_fields_idx[i]];
-                    let map_data_field = JE.F(tab_field[JV.PROP_FIELD_ID], $CURRENT_RPT);
                     if (!(tab_field[JV.PROP_HIDDEN])) {
+                        let data_field = null;
+                        let map_data_field = JE.F(tab_field[JV.PROP_FIELD_ID], $CURRENT_RPT);
+                        if (typeof me.row_fields_idx[i] !== 'object') {
+                            data_field = data_details[me.row_fields_idx[i]];
+                        } else {
+                            if (map_data_field) {
+                                data_field = map_data_field[JV.PROP_AD_HOC_DATA];
+                            }
+                        }
                         let rows = valuesIdx.length;
                         for (let rowIdx = 0; rowIdx < rows; rowIdx++) {
                             if (map_data_field && map_data_field[JV.PROP_PRECISION] && map_data_field.flexiblePrecisionRefObj) {
@@ -446,9 +529,16 @@ JpcCrossTabSrv.prototype.createNew = function(){
                 let flexiblePrecisionRefObj = null, flexibleRefField = null, precision_ref_data = null;
                 for (let i = 0; i < me.col_fields_idx.length; i++) {
                     let tab_field = tab_fields[i];
-                    let data_field = data_details[me.col_fields_idx[i]];
-                    let map_data_field = JE.F(tab_field[JV.PROP_FIELD_ID], $CURRENT_RPT);
                     if (!(tab_field[JV.PROP_HIDDEN])) {
+                        let data_field = null;
+                        let map_data_field = JE.F(tab_field[JV.PROP_FIELD_ID], $CURRENT_RPT);
+                        if (typeof me.col_fields_idx[i] !== 'object') {
+                            data_field = data_details[me.col_fields_idx[i]];
+                        } else {
+                            if (map_data_field) {
+                                data_field = map_data_field[JV.PROP_AD_HOC_DATA];
+                            }
+                        }
                         let cols = valuesIdx.length;
                         for (let colIdx = 0; colIdx < cols; colIdx++) {
                             if (map_data_field && map_data_field[JV.PROP_PRECISION] && map_data_field.flexiblePrecisionRefObj) {

+ 21 - 17
modules/reports/rpt_component/jpc_ex.js

@@ -168,26 +168,30 @@ JpcExSrv.prototype.createNew = function(){
         let me = this, dftPagingOption = option||JV.PAGING_OPTION_NORMAL;
         //1. data object
         let dataHelper = JpcData.createNew();
-        dataHelper.analyzeData(rptTpl, dataObj);
-        //2. tab object
-        //pre-condition: the data should be sorted in SQL/NoSQL level!
-        //let dt1 = new Date();
-        if (me.flowTab) {
-            me.flowTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
-            if (me.flowTabEx) {
-                me.flowTabEx.sorting(rptTpl, dataObj, dataHelper.exDataSeq.slice(0));
-            }
-        }
-        if (me.billTab) {
-            me.billTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
-        }
+        me.executeFormulas(JV.RUN_TYPE_BEFORE_ANALYZING, rptTpl, dataObj, me); //在分析前运行,主要是增加灵活性,比如:重新编排数据的主从关系
         if (me.crossTab) {
+            me.executeFormulas(JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me);
+            dataHelper.analyzeData(rptTpl, dataObj);
             me.crossTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
+        } else {
+            dataHelper.analyzeData(rptTpl, dataObj);
+            //2. tab object
+            //pre-condition: the data should be sorted in SQL/NoSQL level!
+            //let dt1 = new Date();
+            if (me.flowTab) {
+                me.flowTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
+                if (me.flowTabEx) {
+                    me.flowTabEx.sorting(rptTpl, dataObj, dataHelper.exDataSeq.slice(0), me);
+                }
+            }
+            if (me.billTab) {
+                me.billTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
+            }
+            //let dt2 = new Date();
+            //alert(dt2 - dt1);
+            //3. formulas
+            me.executeFormulas(JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me);
         }
-        //let dt2 = new Date();
-        //alert(dt2 - dt1);
-        //3. formulas
-        me.executeFormulas(JV.RUN_TYPE_BEFORE_PAGING, rptTpl, dataObj, me);
         //4. paging
         me.paging(rptTpl, dataObj, defProperties, dftPagingOption, outputType);
         //alert('analyzeData was completed!');

+ 99 - 54
modules/reports/rpt_component/jpc_flow_tab.js

@@ -199,7 +199,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
             if (typeof(me.seg_sum_fields_idx[i]) === "object") {
                 let exField = JE.F(me.seg_sum_fields_idx[i][JV.PROP_ID], $CURRENT_RPT);
                 if (exField) {
-                    data_fields.push(exField["data_field"]);
+                    data_fields.push(exField[JV.PROP_AD_HOC_DATA]);
                 } else {
                     data_fields.push(null);
                 }
@@ -737,59 +737,10 @@ JpcFlowTabSrv.prototype.createNew = function(){
             vIdx.push([-1, JV.DISPLAY_VAL_TYPE_NORMAL, JV.BLANK_VALUE_INDEX]);
         }
         let unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
-        // me.multiCols = 1 * rptTpl[JV.NODE_FLOW_INFO][JV.PROP_MULTI_COLUMN];
-        let newMultiCols = 1 * rptTpl[JV.NODE_FLOW_INFO][JV.PROP_MULTI_COLUMN];
         // 2.2 Column tab
-        let private_colone_cells = function(orgCells) {
-            let newRst = [];
-            let newCopyCells = [];
-            newCopyCells.push(orgCells);
-            if (newMultiCols > 1) {
-                let minX = 10000, maxX = -10;
-                for (let cell of orgCells) {
-                    if (minX > parseInt(cell[JV.PROP_AREA][JV.PROP_LEFT])) minX = cell[JV.PROP_AREA][JV.PROP_LEFT];
-                    if (maxX < parseInt(cell[JV.PROP_AREA][JV.PROP_RIGHT])) maxX = cell[JV.PROP_AREA][JV.PROP_RIGHT];
-                }
-                let newW = maxX - minX, newSegW = newW / newMultiCols;
-                for (let i = 1; i < newMultiCols; i++) {
-                    let cells = [];
-                    for (let cell of orgCells) {
-                        let copyCell = {Value: cell.Value, area: {}, font: cell[JV.PROP_FONT], control: cell[JV.PROP_CONTROL], style: cell[JV.PROP_STYLE]};
-                        cells.push(copyCell);
-                        copyCell[JV.PROP_AREA][JV.PROP_LEFT] = cell[JV.PROP_AREA][JV.PROP_LEFT];
-                        copyCell[JV.PROP_AREA][JV.PROP_RIGHT] = cell[JV.PROP_AREA][JV.PROP_RIGHT];
-                        copyCell[JV.PROP_AREA][JV.PROP_TOP] = cell[JV.PROP_AREA][JV.PROP_TOP];
-                        copyCell[JV.PROP_AREA][JV.PROP_BOTTOM] = cell[JV.PROP_AREA][JV.PROP_BOTTOM];
-                    }
-                    newCopyCells.push(cells);
-                }
-                for (let ci = 0; ci < newCopyCells.length; ci++) {
-                    for (let cCell of newCopyCells[ci]) {
-                        cCell[JV.PROP_AREA][JV.PROP_LEFT] = Math.round(minX + newSegW * ci + (cCell[JV.PROP_AREA][JV.PROP_LEFT] - minX) / newMultiCols);
-                        cCell[JV.PROP_AREA][JV.PROP_RIGHT] = Math.round(minX + newSegW * ci + (cCell[JV.PROP_AREA][JV.PROP_RIGHT] - minX) / newMultiCols);
-                    }
-                }
-            }
-            for (let cCells of newCopyCells) {
-                for (let dCell of cCells) {
-                    newRst.push(dCell);
-                }
-            }
-            return newRst;
-        };
-        let tmpColCells = me.outputColumn(rptTpl, null, 1, 0, bands, unitFactor, 0);
-        if (newMultiCols > 1) {
-            tmpColCells = private_colone_cells(tmpColCells);
-        }
-        rst = rst.concat(tmpColCells);
+        rst = rst.concat(me.outputColumn(rptTpl, null, 1, 0, bands, unitFactor, 0));
         // 2.1 Content-Tab
-        let tmpContentCells = me.outputPreviewContent(rptTpl, bands, unitFactor, controls, pageStatus, maxRowRec);
-        if (newMultiCols > 1) {
-            tmpContentCells = private_colone_cells(tmpContentCells);
-        } else {
-            // rst = rst.concat(me.outputPreviewContent(rptTpl, bands, unitFactor, controls, pageStatus, maxRowRec));
-        }
-        rst = rst.concat(tmpContentCells);
+        rst = rst.concat(me.outputPreviewContent(rptTpl, bands, unitFactor, controls, pageStatus, maxRowRec));
         // 2.3 Sum Seg
         rst = rst.concat(me.outputPreviewSegSum(rptTpl, bands, unitFactor, controls, pageStatus));
         // 2.4 Sum Page
@@ -868,6 +819,87 @@ JpcFlowTabSrv.prototype.createNew = function(){
         }
         return rst;
     };
+    JpcFlowTabResult.combinePageCells = function (rstPageCells, verticalCombinePos, horizonCombinePos) {
+        // let me = this;
+        if (verticalCombinePos.length > 0 || horizonCombinePos.length > 1) {
+            let cacheObj = {vCache:{}, hCache: {}, hCacheStr: []};
+            let removeCellIds = [];
+            for (let vPosArr of verticalCombinePos) {
+                let pStr = "_" + vPosArr[0] + "_" + vPosArr[1];
+                cacheObj.vCache[pStr] = [];
+            }
+            //horizonCombinePos不需要预记
+            for (let idx = 0; idx < rstPageCells.length; idx++) {
+                let cell = rstPageCells[idx];
+                for (let vPosArr of verticalCombinePos) {
+                    if (cell[JV.PROP_AREA][JV.PROP_LEFT] === vPosArr[0] && cell[JV.PROP_AREA][JV.PROP_RIGHT] === vPosArr[1]) {
+                        cacheObj.vCache["_" + vPosArr[0] + "_" + vPosArr[1]].push(idx);
+                    }
+                }
+                for (let hPosArr of horizonCombinePos) {
+                    if (cell[JV.PROP_AREA][JV.PROP_LEFT] === hPosArr[0] && cell[JV.PROP_AREA][JV.PROP_RIGHT] === hPosArr[1]) {
+                        let hpStr = "_" + cell[JV.PROP_AREA][JV.PROP_TOP] + "_" + cell[JV.PROP_AREA][JV.PROP_BOTTOM];
+                        if (cacheObj.hCacheStr.indexOf(hpStr) < 0) {
+                            cacheObj.hCache[hpStr] = [];
+                            cacheObj.hCacheStr.push(hpStr);
+                        }
+                        cacheObj.hCache[hpStr].push(idx);
+                    }
+                }
+            }
+            if (verticalCombinePos.length > 0) {
+                for (let vPosArr of verticalCombinePos) {
+                    let pStr = "_" + vPosArr[0] + "_" + vPosArr[1];
+                    //rstPageCells的结果已经是按顺序排列了,这里不用再排序
+                    if (cacheObj.vCache[pStr] && cacheObj.vCache[pStr].length > 0) {
+                        let preCell = rstPageCells[cacheObj.vCache[pStr][0]];
+                        for (let cIdx = 1; cIdx < cacheObj.vCache[pStr].length; cIdx++) {
+                            if (preCell.Value === "") {
+                                preCell = rstPageCells[cacheObj.vCache[pStr][cIdx]];
+                            } else {
+                                if (preCell.Value === rstPageCells[cacheObj.vCache[pStr][cIdx]].Value) {
+                                    preCell[JV.PROP_AREA][JV.PROP_BOTTOM] = rstPageCells[cacheObj.vCache[pStr][cIdx]][JV.PROP_AREA][JV.PROP_BOTTOM];
+                                    removeCellIds.push(cacheObj.vCache[pStr][cIdx]);
+                                } else {
+                                    preCell = rstPageCells[cacheObj.vCache[pStr][cIdx]];
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (horizonCombinePos.length > 1) {
+                if (cacheObj.hCacheStr.length > 0) {
+                    for (let hStr of cacheObj.hCacheStr) {
+                        let preCell = rstPageCells[cacheObj.hCache[hStr][0]];
+                        for (let cIdx = 1; cIdx < cacheObj.hCache[hStr].length; cIdx++) {
+                            if (preCell.Value === "") {
+                                preCell = rstPageCells[cacheObj.hCache[hStr][cIdx]];
+                            } else {
+                                if (preCell.Value === rstPageCells[cacheObj.hCache[hStr][cIdx]].Value) {
+                                    if (preCell[JV.PROP_AREA][JV.PROP_RIGHT] < rstPageCells[cacheObj.hCache[hStr][cIdx]][JV.PROP_AREA][JV.PROP_RIGHT]) {
+                                        preCell[JV.PROP_AREA][JV.PROP_RIGHT] = rstPageCells[cacheObj.hCache[hStr][cIdx]][JV.PROP_AREA][JV.PROP_RIGHT];
+                                    } else {
+                                        preCell[JV.PROP_AREA][JV.PROP_LEFT] = rstPageCells[cacheObj.hCache[hStr][cIdx]][JV.PROP_AREA][JV.PROP_LEFT];
+                                    }
+                                    removeCellIds.push(cacheObj.hCache[hStr][cIdx]);
+                                } else {
+                                    preCell = rstPageCells[cacheObj.hCache[hStr][cIdx]];
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (removeCellIds.length > 0) {
+                //这次真的要排序了
+                removeCellIds.sort(); //默认方式即可
+                for (let idx = removeCellIds.length - 1; idx >= 0; idx--) {
+                    rstPageCells.splice(removeCellIds[idx], 1);
+                }
+            }
+        }
+    };
     JpcFlowTabResult.outputPreviewContent = function(rptTpl, bands, unitFactor, controls, pageStatus, maxRec) {
         let me = this, rst = [];
         let tab = rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT];
@@ -892,6 +924,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         let FLOW_NODE_STR = me.isEx?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
         let tab = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_CONTENT];
         let tabEx = (rptTpl[JV.NODE_FLOW_INFO_EX])?rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_CONTENT]:null;
+        let verticalCombinePos = [], horizonCombinePos = []; //合并特性用
         let band = bands[tab[JV.PROP_BAND_NAME]];
         if (band) {
             let pageStatus = me.pageStatusLst[page - 1];
@@ -903,10 +936,10 @@ JpcFlowTabSrv.prototype.createNew = function(){
                 let contentValuesIdx = me.dispValueIdxLst[page - 1];
                 let page_sum_data_fields = [];
                 for (let i = 0; i < me.page_sum_fields_idx.length; i++) {
-                    if (typeof(me.page_sum_fields_idx[i])=="object") {
+                    if (typeof(me.page_sum_fields_idx[i]) === "object") {
                         let exField = JE.F(me.page_sum_fields_idx[i][JV.PROP_ID], $CURRENT_RPT);
                         if (exField) {
-                            page_sum_data_fields.push(exField["data_field"]);
+                            page_sum_data_fields.push(exField[JV.PROP_AD_HOC_DATA]);
                         } else {
                             page_sum_data_fields.push(null);
                         }
@@ -968,6 +1001,17 @@ JpcFlowTabSrv.prototype.createNew = function(){
                                 }
                             }
                         }
+                        if (rowIdx === 0 && tab_field[JV.PROP_COMBINE_TYPE] !== undefined && tab_field[JV.PROP_COMBINE_TYPE] !== null) {
+                            let rstCellItem = rst[rst.length - 1];
+                            let cbfPos = [];
+                            cbfPos.push(rstCellItem[JV.PROP_AREA][JV.PROP_LEFT]);
+                            cbfPos.push(rstCellItem[JV.PROP_AREA][JV.PROP_RIGHT]);
+                            if (tab_field[JV.PROP_COMBINE_TYPE] === 'vertical') {
+                                verticalCombinePos.push(cbfPos);
+                            } else if (tab_field[JV.PROP_COMBINE_TYPE] === 'horizon') {
+                                horizonCombinePos.push(cbfPos);
+                            }
+                        }
                     }
                     if (contentValuesIdx[rowIdx][0] === JV.TYPE_FOLLOW_MODE) {
                         for (let idx_ex = 0; idx_ex < tab_fields_ex.length; idx_ex++) {
@@ -1055,6 +1099,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         for (let idIdx = eliminateCells.length - 1; idIdx >= 0; idIdx--) {
             rst.splice(eliminateCells[idIdx], 1);
         }
+        me.combinePageCells(rst, verticalCombinePos, horizonCombinePos);
         return rst;
     };
     JpcFlowTabResult.outputColumn = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, multiColIdx) {

+ 15 - 4
modules/reports/util/rpt_excel_util.js

@@ -275,24 +275,35 @@ function writeStyles(stylesObj){
 }
 function writeSharedString(sharedStrList){
     let rst = [];
+    let pri_func_write = function(cellVal) {
+        if (cellVal !== null) {
+            if ((typeof cellVal === 'string') && cellVal.indexOf(' ') === 0) {
+                rst.push('<si><t xml:space="preserve">' + cellVal + '</t></si>');
+            } else {
+                rst.push('<si><t>' + cellVal + '</t></si>');
+            }
+        }
+    };
     if (sharedStrList && sharedStrList.length > 0) {
         rst.push(dftHeadXml + '\r\n');
         rst.push('<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="' + sharedStrList.length + '" uniqueCount="' + sharedStrList.length + '">');
         let regExp = new RegExp("<", "gm");
         for (let i = 0; i < sharedStrList.length; i++) {
-            //rst.push('<si><t>' + sharedStrList[i] + '</t></si>');
             if (typeof sharedStrList[i] === 'string') {
                 //转换特殊字符,如 < , 则需要转义一下
                 sharedStrList[i] = sharedStrList[i].replace(regExp, "&lt;");
                 if (sharedStrList[i].indexOf('|') >= 0) {
                     //rst.push('<si><t>' + sharedStrList[i].split('|').join('\r\n') + '</t></si>');
-                    rst.push('<si><t>' + sharedStrList[i].split('|').join('\n') + '</t></si>');
+                    // rst.push('<si><t>' + sharedStrList[i].split('|').join('\n') + '</t></si>');
+                    pri_func_write(sharedStrList[i].split('|').join('\n'));
                 } else {
-                    rst.push('<si><t>' + sharedStrList[i] + '</t></si>');
+                    // rst.push('<si><t>' + sharedStrList[i] + '</t></si>');
+                    pri_func_write(sharedStrList[i]);
                 }
                 // rst.push('<si><t>' + sharedStrList[i].replace('|','\r\n') + '</t></si>');
             } else {
-                rst.push('<si><t>' + sharedStrList[i] + '</t></si>');
+                // rst.push('<si><t>' + sharedStrList[i] + '</t></si>');
+                pri_func_write(sharedStrList[i]);
             }
         }
         rst.push('</sst>');

+ 93 - 30
modules/reports/util/rpt_yanghu_data_util.js

@@ -1238,6 +1238,10 @@ function setupFunc(obj, prop, ownRawObj) {
     obj[prop].getSubRateProperty = ext_getRateProperty;
     obj[prop].getRateProperty = ext_getRateProperty;
     obj[prop].getBlank = ext_getBlank;
+    obj[prop].getRatioDataProperty = ext_getRatioDataProperty;
+    obj[prop].getRatioDataParentProperty = ext_getRatioDataParentProperty;
+    obj[prop].getRatioDataPriceMapProperty = ext_getRatioDataPriceMapProperty;
+
     if (prop === projectConst.CALC_PROGRAM) obj[prop].getCalcProperty = ext_getCalcProperty;
     if (prop === projectConst.FEERATE) obj[prop].getFeeRate = ext_getFeeRate;
 }
@@ -1344,46 +1348,105 @@ function ext_getRateProperty(propKey) {
     return rst;
 }
 
-function ext_getPropety(propKey) {
+function ext_getRatioDataProperty(propKey) {
+    //获取工料机的组成物属性
     let rst = [], parentObj = this;
     let dtObj = parentObj["myOwnRawDataObj"];
     if (propKey && dtObj) {
         for (let dItem of getActDataArr(dtObj)) {
             let doc = (dItem._doc === null || dItem._doc === undefined)?dItem:dItem._doc;
-            if (propKey instanceof Array) {
-                //备注:这里的key数组表示取value的优先级
-                for (let pi = 0; pi < propKey.length; pi++) {
-                    if (doc.hasOwnProperty("property")) {
-                        if (doc["property"].hasOwnProperty(propKey[pi])) {
-                            rst.push(doc["property"][propKey[pi]]);
-                            break;
-                        }
-                    } else if (doc.hasOwnProperty(propKey[pi])) {
-                        rst.push(doc[propKey[pi]]);
+            for (let ratioItem of doc.ratio_data) {
+                rst.push(ratioItem[propKey]);
+            }
+        }
+    }
+    return rst;
+}
+
+function pri_push_property(propKey, doc, rst) {
+    if (propKey instanceof Array) {
+        //备注:这里的key数组表示取value的优先级
+        for (let pi = 0; pi < propKey.length; pi++) {
+            if (doc.hasOwnProperty("property")) {
+                if (doc["property"].hasOwnProperty(propKey[pi])) {
+                    rst.push(doc["property"][propKey[pi]]);
+                    break;
+                }
+            } else if (doc.hasOwnProperty(propKey[pi])) {
+                rst.push(doc[propKey[pi]]);
+                break;
+            } else {
+                let lenBefore = rst.length;
+                getDeepProperty(propKey[pi], doc, rst);
+                if (rst.length === (lenBefore + 1)) {
+                    if (rst[lenBefore] !== null && rst[lenBefore] !== undefined && rst[lenBefore] !== "") {
                         break;
                     } else {
-                        let lenBefore = rst.length;
-                        getDeepProperty(propKey[pi], doc, rst);
-                        if (rst.length === (lenBefore + 1)) {
-                            if (rst[lenBefore] !== null && rst[lenBefore] !== undefined && rst[lenBefore] !== "") {
-                                break;
-                            } else {
-                                rst.splice(-1, 1); //删除末尾一条数据,给后面留空间
-                            }
-                        }
+                        rst.splice(-1, 1); //删除末尾一条数据,给后面留空间
                     }
-                    if (pi === propKey.length - 1) rst.push('');
-                }
-            } else {
-                if (doc.hasOwnProperty("property") && doc["property"].hasOwnProperty(propKey)) {
-                    rst.push(doc["property"][propKey]);
-                } else if (doc.hasOwnProperty(propKey)) {
-                    rst.push(doc[propKey]);
-                } else {
-                    // rst.push('');
-                    getDeepProperty(propKey, doc, rst);
                 }
             }
+            if (pi === propKey.length - 1) rst.push('');
+        }
+    } else {
+        if (doc.hasOwnProperty("property") && doc["property"].hasOwnProperty(propKey)) {
+            rst.push(doc["property"][propKey]);
+        } else if (doc.hasOwnProperty(propKey)) {
+            rst.push(doc[propKey]);
+        } else {
+            getDeepProperty(propKey, doc, rst);
+        }
+    }
+}
+
+function ext_getRatioDataParentProperty(propKey) {
+    //获取组成物的父项属性
+    let rst = [], parentObj = this;
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if (propKey && dtObj) {
+        for (let dItem of getActDataArr(dtObj)) {
+            let doc = (dItem._doc === null || dItem._doc === undefined)?dItem:dItem._doc;
+            for (let ratioItem of doc.ratio_data) {
+                pri_push_property(propKey, doc, rst);
+            }
+        }
+    }
+    return rst;
+}
+
+function ext_getRatioDataPriceMapProperty(propKey) {
+    //获取组成物的单价映射属性
+    let rst = [], parentObj = this;
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if (propKey && dtObj) {
+        let unitPriceMap = dtObj.data.unitPriceMap;
+        let upmDoc = (unitPriceMap._doc === null || unitPriceMap._doc === undefined)?unitPriceMap:unitPriceMap._doc;
+        for (let dItem of getActDataArr(dtObj)) {
+            let doc = (dItem._doc === null || dItem._doc === undefined)?dItem:dItem._doc;
+            for (let ratioItem of doc.ratio_data) {
+                let connectionKeys = [];
+                connectionKeys.push(ratioItem.code);
+                connectionKeys.push(ratioItem.name);
+                connectionKeys.push((ratioItem.specs === "")?"null":ratioItem.specs);
+                connectionKeys.push(ratioItem.unit);
+                connectionKeys.push(ratioItem.type);
+                connectionKeys.join("|-|");
+                let strPK = connectionKeys.join("|-|");
+                let dtlDoc = (upmDoc[strPK]._doc)?upmDoc[strPK]._doc:upmDoc[strPK];
+                rst.push(dtlDoc[propKey]);
+            }
+        }
+    }
+    return rst;
+}
+
+function ext_getPropety(propKey) {
+    let rst = [], parentObj = this;
+    let dtObj = parentObj["myOwnRawDataObj"];
+    if (propKey && dtObj) {
+        for (let dItem of getActDataArr(dtObj)) {
+            let doc = (dItem._doc === null || dItem._doc === undefined)?dItem:dItem._doc;
+            pri_push_property(propKey, doc, rst);
         }
     }
     return rst;

+ 2 - 0
public/web/rpt_value_define.js

@@ -120,6 +120,7 @@ const JV = {
     PROP_POSITION: "Position",
     PROP_HIDDEN: "Hidden",
     PROP_IS_SERIAL: "isSerial",
+    PROP_COMBINE_TYPE: "combineType",
     PROP_IS_AUTO_HEIGHT: "isAutoHeight",
     PROP_FONT: "font",
     PROP_CONTROL: "control",
@@ -198,6 +199,7 @@ const JV = {
     PROP_INSERTED_GRP_REC: "insertedGrpRecAmt",
     PROP_GRP_LINES: "group_lines_amt",
 
+    RUN_TYPE_BEFORE_ANALYZING: "before_analyzing",
     RUN_TYPE_BEFORE_PAGING: "before_paging",
     RUN_TYPE_BEFORE_OUTPUT: "before_output",
 

+ 10 - 2
web/maintain/report/html/rpt_tpl_dtl_field_loc.html

@@ -21,8 +21,12 @@
             <div class="row" id="element_hidden">
                 <!--
                 <div class="form-group col-md-2">
-                    <label>排序类型</label>
-                    <select class="form-control" id="elementSortType" onchange=""><option>ascend</option><option>descend</option></select>
+                    <label>指标排序(升序)</label>
+                    <div class="form-check">
+                        <label class="form-check-label">
+                            <input type="checkbox" class="form-check-input" id="eleFieldSort" onchange="rpt_tpl_cfg_helper.crossSortOrderChange(this)">
+                        </label>
+                    </div>
                 </div>
                 -->
                 <div class="form-group col-md-1">
@@ -41,6 +45,10 @@
                         </label>
                     </div>
                 </div>
+                <div class="form-group col-md-2">
+                    <label>排序类型</label>
+                    <select class="form-control" id="elementSortType" onchange="rpt_tpl_cfg_helper.crossSortOrderChange(this)"><option>无排序</option><option>升序</option><option>降序</option></select>
+                </div>
             </div>
             <div class="row" id="element_font">
                 <div class="form-group col-md-3">

+ 5 - 1
web/maintain/report/html/rpt_tpl_dtl_info.html

@@ -52,7 +52,11 @@
             <div class="row" id="element_adhoc_flags">
                 <div class="input-group col-2">
                     <div class="input-group-addon">额外标记</div>
-                    <select class="form-control input-sm" id="element_flags_select" onchange="zTreeOprObj.onChangeFlag('taxType', this)"><option value ="NA">N/A</option><option value ="1">一般计税</option><option value ="2">简易计税</option><option value ="3">预算</option><option value ="4">工程量清单</option></select>
+                    <select class="form-control input-sm" id="element_flags_select" onchange="zTreeOprObj.onChangeFlag('taxType', this)"><option value ="NA">N/A</option><option value ="1">一般计税</option><option value ="2">简易计税</option></select>
+                </div>
+                <div class="input-group col-2">
+                    <div class="input-group-addon">工程类型</div>
+                    <select class="form-control input-sm" id="element_prjFlags_select" onchange="zTreeOprObj.onChangeFlag('valuationType', this)"><option value ="NA">N/A</option><option value ="bill">预算</option><option value ="ration">工程量清单</option></select>
                 </div>
             </div>
         </div>

+ 6 - 3
web/maintain/report/js/rpt_tpl_calculation.js

@@ -28,8 +28,9 @@ let calculationTreeOprObj = {
     },
     buildRunType: function() {
         let et = $("#exprRunType");
-        et.append("<option value='" + JV.RUN_TYPE_BEFORE_PAGING + "'>预运行</option>");
-        et.append("<option value='" + JV.RUN_TYPE_BEFORE_OUTPUT + "'>实时运行</option>");
+        et.append("<option value='" + JV.RUN_TYPE_BEFORE_PAGING + "'>默认运行</option>");
+        et.append("<option value='" + JV.RUN_TYPE_BEFORE_OUTPUT + "'>每页实时运行</option>");
+        et.append("<option value='" + JV.RUN_TYPE_BEFORE_ANALYZING + "'>数据分析前运行</option>");
     },
     buildTreeData: function (rptTpl) {
         let me = this, rst = {"Name": "计算式", items: []};
@@ -91,8 +92,10 @@ let calculationTreeOprObj = {
             $("#exprDetail")[0].style.display = "";
             if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_PAGING) {
                 $("#exprRunType")[0].selectedIndex = 0;
-            } else {
+            } else if (treeNode[JV.PROP_RUN_TYPE] === JV.RUN_TYPE_BEFORE_OUTPUT) {
                 $("#exprRunType")[0].selectedIndex = 1;
+            } else {
+                $("#exprRunType")[0].selectedIndex = 2;
             }
             $("#exprFormat")[0].value = (treeNode["format"])?treeNode["format"]:"";
             $("#exprContent")[0].value = treeNode[JV.PROP_EXPRESSION];

+ 27 - 0
web/maintain/report/js/rpt_tpl_cfg_helper.js

@@ -124,6 +124,17 @@ let rpt_tpl_cfg_helper = {
             } else {
                 $("#eleFieldSerial").get(0).checked = false;
             }
+            if (treeNode[JV.TAB_FIELD_PROP_SORT] !== null && treeNode[JV.TAB_FIELD_PROP_SORT] !== undefined) {
+                if (treeNode[JV.TAB_FIELD_PROP_SORT] === JV.TAB_FIELD_PROP_SORT_VAL_ASC) {
+                    $("#elementSortType").get(0).selectedIndex = 1;
+                } else if (treeNode[JV.TAB_FIELD_PROP_SORT] === JV.TAB_FIELD_PROP_SORT_VAL_DESC) {
+                    $("#elementSortType").get(0).selectedIndex = 2;
+                } else {
+                    $("#elementSortType").get(0).selectedIndex = 0;
+                }
+            } else {
+                $("#elementSortType").get(0).selectedIndex = 0;
+            }
             //setup font
             let fontDom = $("#elementFonts").get(0);
             fontDom.removeAttribute("disabled");
@@ -202,6 +213,22 @@ let rpt_tpl_cfg_helper = {
     crossRowIsSerialChange: function (dom) {
         dataInfoMapTreeOprObj.currentNode[JV.PROP_IS_SERIAL] = dom.checked;
     },
+    crossSortOrderChange: function (dom) {
+        switch (dom.selectedIndex) {
+            case 0:
+                dataInfoMapTreeOprObj.currentNode[JV.TAB_FIELD_PROP_SORT] = JV.TAB_FIELD_PROP_SORT_VAL_NOSORT;
+                break;
+            case 1:
+                dataInfoMapTreeOprObj.currentNode[JV.TAB_FIELD_PROP_SORT] = JV.TAB_FIELD_PROP_SORT_VAL_ASC;
+                break;
+            case 2:
+                dataInfoMapTreeOprObj.currentNode[JV.TAB_FIELD_PROP_SORT] = JV.TAB_FIELD_PROP_SORT_VAL_DESC;
+                break;
+            default:
+                dataInfoMapTreeOprObj.currentNode[JV.TAB_FIELD_PROP_SORT] = JV.TAB_FIELD_PROP_SORT_VAL_ASC;
+                break;
+        }
+    },
     fontChange: function(dom) {
         let me = rpt_tpl_cfg_helper, fontAttr = dom.value;
         //dataInfoMapTreeOprObj.currentNode

+ 34 - 4
web/maintain/report/js/rpt_tpl_data_map.js

@@ -297,12 +297,12 @@ let dataInfoMapTreeOprObj = {
             rootFieldNode.items[1].items = []; //文本集合
             if (contentData[JV.PROP_CROSS_FIELDS] && contentData[JV.PROP_CROSS_FIELDS].length > 0) {
                 for (let fieldItem of contentData[JV.PROP_CROSS_FIELDS]) {
-                    rootFieldNode.items[0].push(me.private_build_field_node(fieldItem, rptTpl));
+                    rootFieldNode.items[0].items.push(me.private_build_field_node(fieldItem, rptTpl));
                 }
             }
             if (contentData[JV.PROP_TEXTS] && contentData[JV.PROP_TEXTS].length > 0) {
                 for (let txt of contentData[JV.PROP_TEXTS]) {
-                    rootFieldNode.items[1].push(me.private_build_text_node(txt));
+                    rootFieldNode.items[1].items.push(me.private_build_text_node(txt));
                 }
             }
         }
@@ -402,6 +402,8 @@ let dataInfoMapTreeOprObj = {
         else destination[JV.PROP_IS_AUTO_HEIGHT] = false;
         if (source[JV.PROP_HIDDEN]) destination[JV.PROP_HIDDEN] = true;
         if (source[JV.PROP_IS_SERIAL]) destination[JV.PROP_IS_SERIAL] = true;
+        if (source[JV.TAB_FIELD_PROP_SORT]) destination[JV.TAB_FIELD_PROP_SORT] = source[JV.TAB_FIELD_PROP_SORT];
+        if (source[JV.PROP_COMBINE_TYPE]) destination[JV.PROP_COMBINE_TYPE] = source[JV.PROP_COMBINE_TYPE];
         if (source[JV.PROP_AREA]) {
             destination[JV.PROP_AREA] = {};
             me.private_copy_area(source[JV.PROP_AREA], destination[JV.PROP_AREA]);
@@ -584,9 +586,10 @@ let dataInfoMapTreeOprObj = {
     onBeforeDrop: function(treeId, treeNodes, targetNode, moveType){
         let rst = false;
         if (targetNode.Name === JV.NODE_FLOW_CONTENT || targetNode.Name === JV.NODE_BILL_CONTENT || targetNode.Name === JV.NODE_CROSS_CONTENT
-            || targetNode.Name === JV.NODE_CROSS_ROW || targetNode.Name === JV.NODE_CROSS_COL
+            || targetNode.Name === JV.NODE_CROSS_ROW || targetNode.Name === JV.NODE_CROSS_COL || targetNode.Name === JV.NODE_CROSS_COL_SUM
+            || targetNode.Name === JV.NODE_CROSS_ROW_SUM
             || targetNode.Name === "离散字段集" || targetNode.Name === "统计指标集" || targetNode.Name === "分组判断指标集"
-            || targetNode.Name === "分组字段集") {
+            || targetNode.Name === "分组字段集" || targetNode.Name === "字段集") {
             rst = true;
         }
         return rst;
@@ -630,6 +633,10 @@ let dataInfoMapTreeOprObj = {
         }
         return rst;
     },
+    checkIfCanAddFieldCombine: function (treeNode) {
+        let rst = (treeNode.getParentNode() !== null && treeNode.getParentNode().Name === `流水式表_数据`);
+        return rst;
+    },
     bandSelectChange: function(dom, treeNodeId) {
         let me = dataInfoMapTreeOprObj, node = me.treeObj.getNodeByTId(treeNodeId);
         if (dom.selectedIndex > 0) {
@@ -638,6 +645,14 @@ let dataInfoMapTreeOprObj = {
             node[JV.PROP_BAND_NAME] = "";
         }
     },
+    combineSelectChange: function(dom, treeNodeId) {
+        let me = dataInfoMapTreeOprObj, node = me.treeObj.getNodeByTId(treeNodeId);
+        if (dom.selectedIndex > 0) {
+            node[JV.PROP_COMBINE_TYPE] = dom.value;
+        } else {
+            node[JV.PROP_COMBINE_TYPE] = null;
+        }
+    },
     addDiyDom: function (treeId, treeNode) {
         let me = dataInfoMapTreeOprObj, aObj = $("#" + treeNode.tId + IDMark_A);
         //加band selection
@@ -645,6 +660,21 @@ let dataInfoMapTreeOprObj = {
             //准备加selection
             let addBandStr = "<select class='selDemo' id='diySelect_" +treeNode.tId+ "' onchange='dataInfoMapTreeOprObj.bandSelectChange(this, \"" + treeNode.tId + "\")'></select>";
             aObj.after(addBandStr);
+        } else if (me.checkIfCanAddFieldCombine(treeNode)) {
+            let addBandStr = "<select class='selDemo' id='diyCombineSelect_" +treeNode.tId+ "' onchange='dataInfoMapTreeOprObj.combineSelectChange(this, \"" + treeNode.tId + "\")'><option value='none'>请选择</option><option value='vertical'>纵向合并</option><option value='horizon'>横向合并</option></select>";
+            aObj.after(addBandStr);
+            let selectCombineObj = $("#diyCombineSelect_" +treeNode.tId);
+            if (treeNode.hasOwnProperty(JV.PROP_COMBINE_TYPE)) {
+                if (treeNode[JV.PROP_COMBINE_TYPE] === 'vertical') {
+                    selectCombineObj[0].selectedIndex = 1;
+                } else if (treeNode[JV.PROP_COMBINE_TYPE] === 'horizon') {
+                    selectCombineObj[0].selectedIndex = 2;
+                } else {
+                    selectCombineObj[0].selectedIndex = 0;
+                }
+            } else {
+                selectCombineObj[0].selectedIndex = 0;
+            }
         }
     },
     addHoverDom: function(treeId, treeNode) {

+ 8 - 0
web/maintain/report/js/rpt_tpl_main.js

@@ -880,8 +880,16 @@ let zTreeOprObj = {
                             } else {
                                 $("#element_flags_select")[0].selectedIndex = 0;
                             }
+                            if (me.currentNode.flags.hasOwnProperty('valuationType')) {
+                                let vType = me.currentNode.flags['valuationType'];
+                                if (vType === 'bill') $("#element_prjFlags_select")[0].selectedIndex = 1
+                                else $("#element_prjFlags_select")[0].selectedIndex = 2;
+                            } else {
+                                $("#element_prjFlags_select")[0].selectedIndex = 0;
+                            }
                         } else {
                             $("#element_flags_select")[0].selectedIndex = 0;
+                            $("#element_prjFlags_select")[0].selectedIndex = 0;
                         }
 
                         if ($("#rpt_tpl_visual_tab")[0].className === "nav-link p-1 active") {

+ 2 - 1
web/users/js/user.js

@@ -13,6 +13,7 @@ $(document).ready(function() {
         let selector = $(this).parent().parent();
         selector.next("input:hidden").val(value);
         selector.prev("button").children("lable").text(string);
+        $('#searchUser').submit();
         //selector.prev("button").html(string + ' <span class="caret"></span>');
     });
     $("#deleteConfirm").click(async function () {
@@ -125,4 +126,4 @@ async function updateUser(compilationID,type) {
 
     }
 
-}
+}

+ 2 - 2
web/users/views/user/index.html

@@ -13,7 +13,7 @@
     </div>
     <div class="content-wrap">
         <div class="c-header">
-            <form class="form-inline" method="get" action="">
+            <form class="form-inline" method="get" action="" id="searchUser">
                 <!--最近使用定额-->
                 <div class="btn-group">
                     <button type="button" class="btn btn-default dropdown-toggle btn-sm" data-toggle="dropdown"
@@ -200,4 +200,4 @@
     let compilationList = JSON.parse('<%- compilationString %>');
     let adminName = '<%- adminName %>';
 </script>
-<script type="text/javascript" src="/web/users/js/user.js"></script>
+<script type="text/javascript" src="/web/users/js/user.js"></script>