Przeglądaj źródła

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/SCCommon

lishihao 3 lat temu
rodzic
commit
e730917950

+ 601 - 54
report/dist/index.cjs.js

@@ -246,6 +246,7 @@ const JV = {
     CONTROL_PROP_IDX_VERTICAL_EXCEL: 5,
     CONTROL_PROP_IDX_SHRINK_FIRST: 6,
     CONTROL_PROP_IDX_CLOSE_OUTPUT: 7,
+    CLOSE_OUTPUT_ROW_BUFFER: 4,
     BORDER_STYLE_PROPS: ['LineWeight', 'DashStyle', 'Color'],
     PROP_LINE_WEIGHT: 'LineWeight',
     PROP_DASH_STYLE: 'DashStyle',
@@ -312,7 +313,7 @@ const JV = {
     SIZE_LEGAL: [8.5, 14.0],
     SIZE_16K: [7.75, 10.75],
     SIZE_EXECUTIVE: [7.25, 10.5],
-    OUTPUT_OFFSET: [2, 2, 1, 3],
+    OUTPUT_OFFSET: [1, 1, 1, 1],
     OFFSET_IDX_LEFT: 0,
     OFFSET_IDX_RIGHT: 1,
     OFFSET_IDX_TOP: 2,
@@ -505,7 +506,8 @@ const JpcCommonHelper = {
                 //大于127为中文字
                 currentW = (strVal.charCodeAt(sIdx) > 127) ? chnW : otherW;
                 txtWidth += currentW;
-                if (txtWidth > areaWidth) {
+                if (txtWidth > (areaWidth - 4)) {
+                    //减4个像素是考虑到导出excel的情况
                     rst++;
                     txtWidth = currentW;
                 }
@@ -527,7 +529,8 @@ const JpcCommonHelper = {
             for (let sIdx = 0; sIdx < strVal.length; sIdx++) {
                 currentW = (strVal.charCodeAt(sIdx) > 127) ? chnW : otherW;
                 txtWidth += currentW;
-                if (txtWidth > areaWidth) {
+                if (txtWidth > (areaWidth - 4)) {
+                    //减4个像素是考虑到导出excel的情况
                     if (preSIdx < sIdx) {
                         rst.push(strVal.substr(preSIdx, sIdx - preSIdx));
                         preSIdx = sIdx;
@@ -1655,7 +1658,7 @@ const isEmptyString = (str) => {
     if (str === null || str === undefined) {
         rst = true;
     }
-    else if (typeof str) {
+    else if (typeof str === 'string') {
         let reg = /^\s*$/;
         rst = reg.test(str);
     }
@@ -1670,7 +1673,7 @@ const leftTrim = (str) => {
 const rightTrim = (str) => {
     return str.replace(/(\s*$)/g, "");
 };
-const replaceAll = (targetStr, FindText, RepText) => {
+const replaceAll$1 = (targetStr, FindText, RepText) => {
     let regExp = new RegExp(FindText, "gm");
     return targetStr.replace(regExp, RepText);
 };
@@ -1700,15 +1703,15 @@ const convertToCaptionNum = (num, isCurrency, isTraditionalCap) => {
                 intPartArr.push(capChars[parseInt(numSplitArr[0].charAt(idx))] + unitChars[len - idx - 1]);
             }
             rst = intPartArr.join('');
-            rst = replaceAll(rst, capChars[0] + unitChars[3], capChars[0]); //零千 -> 零
-            rst = replaceAll(rst, capChars[0] + unitChars[2], capChars[0]); //零百 -> 零
-            rst = replaceAll(rst, capChars[0] + unitChars[1], capChars[0]); //零十 -> 零
+            rst = replaceAll$1(rst, capChars[0] + unitChars[3], capChars[0]); //零千 -> 零
+            rst = replaceAll$1(rst, capChars[0] + unitChars[2], capChars[0]); //零百 -> 零
+            rst = replaceAll$1(rst, capChars[0] + unitChars[1], capChars[0]); //零十 -> 零
             //
-            rst = replaceAll(replaceAll(rst, "零零", "零"), "零零", "零");
-            rst = replaceAll(rst, capChars[0] + unitChars[8], unitChars[8]); //零亿 -> 亿
-            rst = replaceAll(rst, capChars[0] + unitChars[4], unitChars[4]); //零万 -> 万
+            rst = replaceAll$1(replaceAll$1(rst, "零零", "零"), "零零", "零");
+            rst = replaceAll$1(rst, capChars[0] + unitChars[8], unitChars[8]); //零亿 -> 亿
+            rst = replaceAll$1(rst, capChars[0] + unitChars[4], unitChars[4]); //零万 -> 万
             //
-            rst = replaceAll(rst, unitChars[8] + unitChars[4], unitChars[8] + capChars[0]); //亿万 -> 亿零
+            rst = replaceAll$1(rst, unitChars[8] + unitChars[4], unitChars[8] + capChars[0]); //亿万 -> 亿零
             if (num === 0) {
                 rst = "零";
             }
@@ -1808,7 +1811,7 @@ var stringUtil = /*#__PURE__*/Object.freeze({
     trim: trim,
     leftTrim: leftTrim,
     rightTrim: rightTrim,
-    replaceAll: replaceAll,
+    replaceAll: replaceAll$1,
     comdify: comdify$1,
     convertToCaptionNum: convertToCaptionNum,
     convertStrToBoolean: convertStrToBoolean,
@@ -2115,7 +2118,6 @@ const JE = {
         }
     },
     removeFieldValue: function (field, dataObj, valIdx) {
-        console.log('===================removeFieldValue');
         if (field.DataNodeName === "NA") {
             if (field.data_field.length > valIdx && valIdx >= 0) {
                 field.data_field.splice(valIdx, 1);
@@ -2128,8 +2130,9 @@ const JE = {
         }
     },
     insertFieldValue: function (field, dataObj, valIdx, newValue) {
-        console.log('===================insertFieldValue');
         if (field.DataNodeName === "NA") {
+            if (!field.data_field)
+                field.data_field = [];
             if (field.data_field.length > valIdx && valIdx >= 0) {
                 field.data_field.splice(valIdx, 0, newValue);
             }
@@ -2145,6 +2148,35 @@ const JE = {
                 dataObj[field.DataNodeName][field.DataSeq][dataObj[field.DataNodeName][field.DataSeq].length] = newValue;
             }
         }
+    },
+    alignFieldDecimal: function (sourceID, destID, $CURRENT_RPT) {
+        // 把source指标的精度align到dest
+        const me = JE;
+        let sourceField = null;
+        if (isNaN(sourceID)) {
+            sourceField = sourceID;
+        }
+        else {
+            sourceField = me.F(sourceID, $CURRENT_RPT);
+        }
+        let destField;
+        if (isNaN(destID)) {
+            destField = destID;
+        }
+        else {
+            destField = me.F(destID, $CURRENT_RPT);
+        }
+        if (sourceField instanceof Object && sourceField && sourceField.Precision) {
+            destField.Precision = sourceField.Precision;
+            destField.fixedPrecisionNum = sourceField.fixedPrecisionNum;
+        }
+    },
+    batchIniFields: function (IDArr, $CURRENT_RPT) {
+        // 批处理查找指标
+        const me = JE;
+        for (let idxF = 0; idxF < IDArr.length; idxF++) {
+            IDArr[idxF] = me.F(IDArr[idxF], $CURRENT_RPT);
+        }
     }
 };
 
@@ -2196,7 +2228,7 @@ let JpcFieldHelper = {
             rst = true;
         }
         else if (map_field && tab_field.Format && tab_field.Format.indexOf("#") >= 0 && (customizeCfg && customizeCfg.fillZero)) {
-            tab_field.Format = replaceAll(tab_field.Format, '#', '0');
+            tab_field.Format = replaceAll$1(tab_field.Format, '#', '0');
             map_field.Format = tab_field.Format;
             rst = true;
         }
@@ -2226,7 +2258,17 @@ let JpcFieldHelper = {
             if (showZero && showZero === 'F') {
                 const val = parseFloat(cell.Value);
                 if (val === 0) {
-                    cell.Value = '';
+                    let chkRst = true;
+                    if (typeof cell.Value === 'string' && cell.Value.length > 1) {
+                        for (let idx = 0; idx < cell.Value.length; idx++) {
+                            if (cell.Value[idx] !== '0' && cell.Value[idx] !== '.') {
+                                chkRst = false;
+                                break;
+                            }
+                        }
+                    }
+                    if (chkRst)
+                        cell.Value = '';
                 }
             }
         }
@@ -2307,6 +2349,24 @@ let JpcFieldHelper = {
 };
 
 let JpcFlowTabHelper = {
+    getRowHeight: function (bands, rptTpl, isEx) {
+        let rst = 0;
+        (!isEx) ? JV.NODE_FLOW_INFO : JV.NODE_FLOW_INFO_EX;
+        let tab = rptTpl.流水式表_信息.流水式表_数据;
+        let band = bands[tab.BandName];
+        if (band) {
+            let maxFieldMeasure = 1.0;
+            if (JV.CAL_TYPE_ABSTRACT === JpcCommonHelper.getPosCalculationType(tab.CalculationType)) {
+                let unitFactor = JpcCommonHelper.getUnitFactor(rptTpl);
+                maxFieldMeasure = 1.0 * rptTpl.流水式表_信息.流水式表_数据.CommonHeight * unitFactor;
+            }
+            else {
+                maxFieldMeasure = (band.Bottom - band.Top) * rptTpl.流水式表_信息.流水式表_数据.CommonHeight / JV.HUNDRED_PERCENT;
+            }
+            rst = maxFieldMeasure;
+        }
+        return rst;
+    },
     getMaxRowsPerPage: function (bands, rptTpl, isEx) {
         let rst = 1;
         let tab;
@@ -3215,8 +3275,336 @@ const fontWidthMap = {
     }
 };
 
+let FData = {};
+let PData = {};
+let DData = {};
+let rpt = {};
+let orgData = {};
+const setupData = ($CURRENT_RPT, $CURRENT_DATA) => {
+    rpt = $CURRENT_RPT;
+    orgData = $CURRENT_DATA;
+};
+const resetData = () => {
+    DData = {};
+    FData = {};
+    PData = {};
+};
+const getFieldValueArray = (field) => {
+    let rst;
+    if (field.DataNodeName === exports.IDataObjProps.NA) {
+        if (!field.data_field) {
+            field.data_field = [];
+        }
+        rst = field.data_field;
+    }
+    else {
+        if (!field.DataNodeName) {
+            console.log('进来了特殊情况');
+            // that means this is a self-defined discrete field!
+            field.DataNodeName = exports.IDataObjProps.discrete_data;
+            // field.DataSeq = dataObj[IDataObjProps.discrete_data];
+            orgData[exports.IDataObjProps.discrete_data].push([]);
+        }
+        rst = orgData[field.DataNodeName][field.DataSeq];
+    }
+    if (rst === null || rst === undefined)
+        rst = [];
+    return rst;
+};
+//获取一般指标的指标对象($CURRENT_RPT.fields中的对象)
+const F = (fieldID) => {
+    if (FData[fieldID]) {
+        return FData[fieldID];
+    }
+    else {
+        for (const dataSet in rpt.fields) {
+            for (const field in rpt.fields[dataSet]) {
+                const newFieldID = field.replace('ID_', '');
+                if (newFieldID === `${fieldID}`) {
+                    FData[fieldID] = rpt.fields[dataSet][field];
+                    DData[fieldID] = getFieldValueArray(rpt.fields[dataSet][field]);
+                    return FData[fieldID];
+                }
+            }
+        }
+    }
+    return false;
+};
+// 获取离散指标的指标对象($CURRENT_RPT.params中的对象,一般是打印页,总页数,当前页数)
+const P = (fieldID) => {
+    if (PData[fieldID]) {
+        return PData[fieldID];
+    }
+    else {
+        for (const field in rpt.params) {
+            const fieldID = field.replace('ID_', '');
+            if (fieldID === fieldID) {
+                PData[fieldID] = rpt.params[field];
+                DData[fieldID] = rpt.params[field].Default_Value;
+                return rpt.params[field];
+            }
+        }
+    }
+    return false;
+};
+// 获取数据,只有一个参数时获取该指标所有数据(数组),两个参数时获取该指标中的第N个数据(值)
+const D = (fieldID, valIndex, newValue) => {
+    if (valIndex || valIndex === 0) {
+        if (DData[fieldID]) {
+            return DData[fieldID][valIndex];
+        }
+        else {
+            if (!F(fieldID))
+                P(fieldID);
+            if (DData[fieldID]) {
+                if (DData[fieldID].length >= valIndex) {
+                    if (!DData[fieldID][valIndex] && DData[fieldID][valIndex] !== 0)
+                        return '';
+                    return DData[fieldID][valIndex];
+                }
+                else {
+                    console.log(`指标id:${fieldID},${valIndex}>${DData[fieldID].length},请检查`);
+                    return '';
+                }
+            }
+            else {
+                console.log(`无ID为${fieldID}的指标,请检查`);
+                return '';
+            }
+        }
+    }
+    else {
+        if (DData[fieldID]) {
+            return DData[fieldID];
+        }
+        else {
+            if (!F(fieldID))
+                P(fieldID);
+            if (DData[fieldID]) {
+                return DData[fieldID];
+            }
+            else {
+                console.log(`无ID为${fieldID}的指标,请检查`);
+                return [];
+            }
+        }
+    }
+};
+//获取相应指标的数据长度
+const L = (arg) => {
+    if (arg in exports.IDataObjProps) {
+        return orgData[arg][0].length;
+    }
+    else {
+        if (DData[arg]) {
+            return DData[arg].length;
+        }
+        else {
+            F(arg);
+            if (DData[arg]) {
+                return DData[arg];
+            }
+            else {
+                console.log(`无ID为${arg}的指标,请检查`);
+                return 0;
+            }
+        }
+    }
+};
+//获取当前页
+const getCurrentPage = () => {
+    let rst = 0;
+    if (rpt && rpt.runTimePageData.currentPage) {
+        rst = rpt.runTimePageData.currentPage;
+    }
+    return rst;
+};
+// 获取总页数
+const getTotalPage = () => {
+    let rst = 0;
+    if (rpt) {
+        rst = rpt.totalPages;
+    }
+    return rst;
+};
+//向目标对象赋值
+const setFieldValue = (field, valIdx, newValue) => {
+    if (field.DataNodeName === "NA") {
+        if (!field.data_field) {
+            field.data_field = [];
+        }
+        field.data_field[valIdx] = newValue;
+    }
+    else if (!field.DataNodeName) {
+        //that means this is a self-defined discrete field!
+        field.DataNodeName = exports.IDataObjProps.discrete_data;
+        field.DataSeq = orgData[exports.IDataObjProps.discrete_data].length;
+        orgData[exports.IDataObjProps.discrete_data].push([]);
+        orgData[field.DataNodeName][field.DataSeq][valIdx] = newValue;
+    }
+    else {
+        orgData[field.DataNodeName][field.DataSeq][valIdx] = newValue;
+    }
+};
+//反向设置原始数据
+const setFieldValueArray = (field, newArr) => {
+    if (newArr instanceof Array) {
+        if (field.DataNodeName === 'NA') {
+            field.data_field = newArr;
+        }
+        else {
+            if (!field.DataNodeName) {
+                // that means this is a self-defined discrete field!
+                field.DataNodeName = exports.IDataObjProps.discrete_data;
+                field.DataSeq = orgData[exports.IDataObjProps.discrete_data].length;
+                orgData[exports.IDataObjProps.discrete_data].push([]);
+            }
+            orgData[field.DataNodeName][field.DataSeq] = newArr;
+        }
+    }
+};
+//反向设置原始数据
+const setFieldDefaultValue = (fieldID, newValue) => {
+    rpt.params[`ID_${fieldID}`].Default_Value = newValue;
+};
+//该函数为共用方法,参数有两套组合:
+// (指标id,更改后的数组)
+// (指标id,需要更改的index,.需要更改的值)
+const setData = (fieldID, arg1, arg2) => {
+    const field = F(fieldID);
+    if (field) {
+        if (arg1 instanceof Array) {
+            if (DData[fieldID]) {
+                DData[fieldID] = arg1;
+                setFieldValueArray(field, arg1);
+            }
+            else {
+                console.log(`无ID为${fieldID}的指标,请检查`);
+            }
+        }
+        else {
+            if (typeof (arg1) === 'number') {
+                if (DData[fieldID]) {
+                    if (arg1 <= DData[fieldID].length) {
+                        DData[fieldID][arg1] = arg2;
+                        setFieldValue(field, arg1, arg2);
+                    }
+                    else {
+                        console.log(`指标id:${fieldID},数据长度为${DData[fieldID].length},第二参数为${arg1},请检查`);
+                    }
+                }
+                else {
+                    console.log(`无ID为${fieldID}的指标,请检查`);
+                }
+            }
+        }
+    }
+    else if (P(fieldID)) {
+        setFieldDefaultValue(fieldID, arg1);
+        DData[fieldID] = arg1;
+    }
+};
+//把数组每个元素都转换成数字
+const getNumberArray = (data) => {
+    const rst = [];
+    for (const item of data) {
+        if (isNaN(Number(item))) {
+            rst.push(0);
+        }
+        else {
+            rst.push(Number(item));
+        }
+    }
+    return rst;
+};
+const removeFieldValue = (fieldID, valIdx) => {
+    const fField = F(fieldID);
+    if (fField) {
+        DData[fieldID].splice(valIdx, 1);
+    }
+    else {
+        console.log(`指标${fieldID}的数据不支持removeFieldValue操作`);
+    }
+};
+const insertFieldValue = (fieldID, valIdx, newValue) => {
+    let field = F(fieldID);
+    if (field) {
+        DData[fieldID].splice(valIdx, 0, newValue);
+    }
+    else {
+        console.log(`指标${fieldID}的数据不支持insertFieldValue操作`);
+    }
+};
+//复制精度
+const copyPrecision = (targetFieldID, orgFieldID) => {
+    copyProperty(targetFieldID, orgFieldID, 'Precision');
+};
+const copyFixedPrecisionNum = (targetFieldID, orgFieldID) => {
+    copyProperty(targetFieldID, orgFieldID, 'fixedPrecisionNum');
+};
+//复制属性
+const copyProperty = (targetFieldID, orgFieldID, property) => {
+    const targetField = F(targetFieldID);
+    const orgField = F(orgFieldID);
+    if (targetField && orgField) {
+        if (orgField[property]) {
+            if (!targetField[property]) {
+                targetField[property] = {};
+            }
+            Object.assign(targetField[property], orgField[property]);
+        }
+        else {
+            console.log(`指标${orgFieldID}不存在${property}属性`);
+        }
+    }
+    else {
+        console.log(`指标${targetFieldID}和${orgFieldID}的数据不支持copyProperty操作`);
+    }
+};
+const setDate = (fieldID, format) => {
+    const date = new ReportDate();
+    setData(fieldID, date.Format(format));
+};
+const DLength = () => {
+    if (orgData && orgData.detail_data)
+        return orgData.detail_data[0].length;
+    return 0;
+};
+var formulasDataSetter = {
+    setupData,
+    P,
+    F,
+    D,
+    getCurrentPage,
+    getTotalPage,
+    L,
+    setFieldValue,
+    setFieldValueArray,
+    removeFieldValue,
+    insertFieldValue,
+    setData,
+    resetData,
+    getNumberArray,
+    copyPrecision,
+    copyFixedPrecisionNum,
+    copyProperty,
+    setDate,
+    DLength
+};
+
 // 计算式执行(不同情况的方法会不同)
+/* eslint-disable import/prefer-default-export */
+const replaceAll = (FindText, RepText, str) => {
+    const regExp = new RegExp(FindText, 'g');
+    return str.replace(regExp, RepText);
+};
 const formulaExec = (runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT) => {
+    formulasDataSetter.setupData($CURRENT_RPT, $CURRENT_DATA);
+    const { P, F, D, L, getCurrentPage, getTotalPage, setFieldValue, setFieldValueArray, removeFieldValue, insertFieldValue, setData, getNumberArray, copyPrecision, copyFixedPrecisionNum, copyProperty, setDate, DLength } = formulasDataSetter;
+    const { isEmptyString, trim, leftTrim, rightTrim, comdify, convertToCaptionNum, convertStrToBoolean, formatNumber, } = stringUtil;
+    const $JV = JV;
+    const $JE = JE;
+    const reportDate = ReportDate;
     for (let execFmlIdx = 0; execFmlIdx < $CURRENT_RPT.formulas.length; execFmlIdx++) {
         if ($CURRENT_RPT.formulas[execFmlIdx].run_type === runType) {
             let expression = $CURRENT_RPT.formulas[execFmlIdx].expression;
@@ -3229,7 +3617,7 @@ const formulaExec = (runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT) =>
                     // console.log(expression);
                     //临时处理
                     if (expression.indexOf(`new Date(`)) {
-                        newExpression = expression.replaceAll(`new Date(`, `new ReportDate(`);
+                        newExpression = replaceAll(/new Date\(/g, `new reportDate(`, expression);
                     }
                     eval(newExpression);
                 }
@@ -3239,8 +3627,40 @@ const formulaExec = (runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT) =>
             }
         }
     }
+    formulasDataSetter.resetData();
+    return {
+        $JE,
+        $JV,
+        P,
+        F,
+        D,
+        L,
+        getCurrentPage,
+        getTotalPage,
+        setFieldValue,
+        setFieldValueArray,
+        removeFieldValue,
+        insertFieldValue,
+        setData,
+        getNumberArray,
+        copyPrecision,
+        copyFixedPrecisionNum,
+        copyProperty,
+        setDate,
+        DLength,
+        isEmptyString,
+        trim,
+        leftTrim,
+        rightTrim,
+        comdify,
+        convertToCaptionNum,
+        convertStrToBoolean,
+        formatNumber,
+        reportDate
+    };
 };
 const combinedGridFormula = ($RUN_TYPE, $TEXT, $TIMES, $CURRENT_RPT) => {
+    const { $JE, $JV, P, F, D, L, getCurrentPage, getTotalPage, setFieldValue, setFieldValueArray, removeFieldValue, insertFieldValue, setData, getNumberArray, copyPrecision, copyFixedPrecisionNum, copyProperty, setDate, DLength, isEmptyString, trim, leftTrim, rightTrim, comdify, convertToCaptionNum, convertStrToBoolean, formatNumber, reportDate } = $CURRENT_RPT.formulasObject;
     if ($CURRENT_RPT.formulas) {
         for (let execFmlIdx = 0; execFmlIdx < $CURRENT_RPT.formulas.length; execFmlIdx++) {
             if ($CURRENT_RPT.formulas[execFmlIdx].run_type === $RUN_TYPE) {
@@ -3257,6 +3677,37 @@ const combinedGridFormula = ($RUN_TYPE, $TEXT, $TIMES, $CURRENT_RPT) => {
             }
         }
     }
+    formulasDataSetter.resetData();
+    return {
+        $JE,
+        $JV,
+        P,
+        F,
+        D,
+        L,
+        getCurrentPage,
+        getTotalPage,
+        setFieldValue,
+        setFieldValueArray,
+        removeFieldValue,
+        insertFieldValue,
+        setData,
+        getNumberArray,
+        copyPrecision,
+        copyFixedPrecisionNum,
+        copyProperty,
+        setDate,
+        DLength,
+        isEmptyString,
+        trim,
+        leftTrim,
+        rightTrim,
+        comdify,
+        convertToCaptionNum,
+        convertStrToBoolean,
+        formatNumber,
+        reportDate
+    };
 };
 
 class JpcFlowTabClass {
@@ -3523,6 +3974,7 @@ class JpcFlowTabClass {
             };
             let private_get_max_lines_of_the_record = function (theRecIdx) {
                 let rst = 1;
+                let maxAmt = 1;
                 for (let loop = 0; loop < me.auto_height_fields_idx.length; loop++) {
                     let tab_field = me.auto_height_fields_idx[loop][1];
                     let data_field = null, map_data_field = JE.F(tab_field.FieldID, $CURRENT_RPT);
@@ -3546,14 +3998,13 @@ class JpcFlowTabClass {
                         }
                         JpcFieldHelper.setValue(data_field, theRecIdx, value);
                         let values = value.split('|');
-                        if (values.length > rst)
-                            rst = values.length;
+                        // if (values.length > rst) rst = values.length; // 考虑到紧凑输出,不能那么快设置rst
                         let font = private_get_font(tab_field.font);
                         let chkFontName = '宋体';
                         let chkFontHeight = 12;
                         if (font) {
                             chkFontName = font[JV.FONT_PROPS[0]];
-                            chkFontHeight = font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]];
+                            chkFontHeight = parseFloat(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]]);
                         }
                         let hasSplitStr = false, splitStrArr = [];
                         let accAmt = 0;
@@ -3567,8 +4018,21 @@ class JpcFlowTabClass {
                                 splitStrArr.push(i);
                             }
                         }
-                        if (accAmt > rst)
-                            rst = accAmt;
+                        if (accAmt > 3) {
+                            // 新优化,计算实际能显示完的真正行数
+                            const rowHeight = JpcFlowTabHelper.getRowHeight(bands, rptTpl, me.isEx);
+                            let tmpFV = ((chkFontHeight + JV.CLOSE_OUTPUT_ROW_BUFFER) * accAmt) / rowHeight;
+                            let tmpAmt = Math.floor(tmpFV);
+                            if (Math.ceil(tmpFV) > tmpAmt) {
+                                tmpAmt++;
+                            }
+                            if (maxAmt < tmpAmt)
+                                maxAmt = tmpAmt;
+                        }
+                        else {
+                            if (maxAmt < accAmt)
+                                maxAmt = accAmt;
+                        }
                         if (hasSplitStr) {
                             let newValArr = [];
                             for (let i = 0; i < values.length; i++) {
@@ -3587,6 +4051,8 @@ class JpcFlowTabClass {
                         //      根据最新需求,暂时不考虑excel类型输出,换回原来逻辑
                     }
                 }
+                if (rst < maxAmt)
+                    rst = maxAmt; // 最后才设置最大结果
                 return rst;
             };
             for (let tabField of tab_fields) {
@@ -3849,7 +4315,10 @@ class JpcFlowTabClass {
                                         private_addPage(segIdx, null, true, false, -1);
                                     }
                                     else {
-                                        private_addPage(segIdx, grpSeqInfo, false, true, ttlSegRecAmtNormal);
+                                        // private_addPage(segIdx, grpSeqInfo, false, true, ttlSegRecAmtNormal);
+                                        //在这里要考虑如果有多页正常的流水数据情况,那么就得考虑这页有多少条普通流水记录,不应该一刀切地用ttlSegRecAmtNormal
+                                        let splitPoint = ttlSegRecAmtNormal - handledRowAmt;
+                                        private_addPage(segIdx, grpSeqInfo, false, true, splitPoint);
                                     }
                                 }
                                 else {
@@ -4411,6 +4880,7 @@ class JpcFlowTabClass {
     }
     ;
     checkCombineEvent($RUN_TYPE, $VER_COMB_ARRAY, $HOR_COMB_ARRAY, $CURRENT_CELL_ITEMS, $CURRENT_RPT) {
+        const { $JE, $JV, P, F, D, L, getCurrentPage, getTotalPage, setFieldValue, setFieldValueArray, removeFieldValue, insertFieldValue, setData, getNumberArray, copyPrecision, copyFixedPrecisionNum, copyProperty, setDate, DLength, isEmptyString, trim, leftTrim, rightTrim, comdify, convertToCaptionNum, convertStrToBoolean, formatNumber, reportDate } = $CURRENT_RPT.formulasObject;
         if ($CURRENT_RPT.formulas) {
             for (let execFmlIdx = 0; execFmlIdx < $CURRENT_RPT.formulas.length; execFmlIdx++) {
                 if ($CURRENT_RPT.formulas[execFmlIdx].run_type === $RUN_TYPE) {
@@ -4427,6 +4897,36 @@ class JpcFlowTabClass {
                 }
             }
         }
+        return {
+            $JE,
+            $JV,
+            P,
+            F,
+            D,
+            L,
+            getCurrentPage,
+            getTotalPage,
+            setFieldValue,
+            setFieldValueArray,
+            removeFieldValue,
+            insertFieldValue,
+            setData,
+            getNumberArray,
+            copyPrecision,
+            copyFixedPrecisionNum,
+            copyProperty,
+            setDate,
+            DLength,
+            isEmptyString,
+            trim,
+            leftTrim,
+            rightTrim,
+            comdify,
+            convertToCaptionNum,
+            convertStrToBoolean,
+            formatNumber,
+            reportDate
+        };
     }
     ;
     outputColumn(rptTpl, dataObj, page, segIdx, bands, unitFactor, multiColIdx, $CURRENT_RPT, customizeCfg) {
@@ -4528,12 +5028,56 @@ class JpcFlowTabClass {
             if (showText) {
                 textArr = textArr.concat(showText.split('|'));
             }
-            if (contentValInfo[3] < textArr.length && contentValInfo[3] >= 0) {
-                showText = textArr[contentValInfo[3]];
+            /*
+if (contentValInfo[3] < textArr.length && contentValInfo[3] >= 0) {
+    showText = textArr[contentValInfo[3]];
+}
+else {
+    showText = '';
+}
+/*/
+            // 因新逻辑要优化自动行高,不再是一个折行占用1row,而是: 
+            // a. 根据实际情况,设置了一个实际的行数值(比如共有10行,根据行高情况,可能只设置了6行的高度,在setupAutoHeightData方法里处理)
+            // b. 这里最大的难题在于跨页分配(预估会有来回调整,目前采用按比例分配原则)
+            // c. 还有个问题就是多个自动行高指标的问题
+            const ACT_ROWS = contentValInfo[4]; //经实际计算,能容纳所有数据的实际行数
+            const CURRENT_ROW = contentValInfo[3]; //从0开始
+            const QUOTA_Rate = textArr.length / ACT_ROWS; //每行显示的加权系数(超过2的话,表示给的行高太多了,需要另外一些特殊处理,后期有需要再加)
+            if (textArr.length <= 3 || ACT_ROWS > textArr.length) {
+                //表示这个一定是附属的autoheight指标,或者数据就只有3行(假如数据3行精简成2行,但刚好处于分页状态,那么无论是前一页或后一页,显示上都很纠结(多出来的一行放哪好?),所以新逻辑的起点要3行以上,少了就不折腾了,老老实实地一个萝卜一个坑)
+                if (CURRENT_ROW < textArr.length && CURRENT_ROW >= 0) {
+                    showText = textArr[CURRENT_ROW];
+                }
+                else {
+                    showText = '';
+                }
             }
             else {
-                showText = '';
+                //这里不管是不是附属autoheight指标,有足够的条件单独处理
+                if (QUOTA_Rate >= 3) {
+                    console.log('压缩率太高了,模板的行高设置小一点');
+                    //压缩超过一半空间的话,说明给的行高度太高了,需要另外一些特殊处理,后期有需要再加
+                }
+                else {
+                    //正常的压缩比例
+                    let startIdx = 0, endIdx = 0;
+                    if (CURRENT_ROW > 0) {
+                        endIdx = Math.round((CURRENT_ROW + 1) * QUOTA_Rate) - 1;
+                        let preEndIdx = 0;
+                        if (CURRENT_ROW > 1) {
+                            //重定位 preEndIdx
+                            preEndIdx = Math.round(CURRENT_ROW * QUOTA_Rate) - 1;
+                        }
+                        startIdx = preEndIdx + 1;
+                    }
+                    //按比例分配
+                    showText = textArr[startIdx];
+                    for (let idx = startIdx + 1; idx <= endIdx; idx++) {
+                        showText += `|${textArr[idx]}`;
+                    }
+                }
             }
+            //*/
             let rst = JpcCommonOutputHelper.createCommonOutput(tab_field, showText, controls);
             rst.area = JpcAreaHelper.outputArea(tab_field.area, band, unitFactor, rows, rowIdx, cols, colIdx, me.multiCols, multiColIdx, true, false);
             rst.isAutoHeight = true;
@@ -6387,6 +6931,7 @@ class JpcExClass {
     params;
     formulas;
     events;
+    formulasObject = {};
     constructor(rptTpl) {
         if (rptTpl.流水式表_信息) {
             this.flowTab = new JpcFlowTabClass(false);
@@ -6411,7 +6956,6 @@ class JpcExClass {
         this.formulas = JpcFunc.createNew(rptTpl);
         this.events = JpcEvent.createNew(rptTpl);
     }
-    ;
     analyzeData(rptTpl, dataObj, defProperties, option, outputType) {
         let me = this, dftPagingOption = option || exports.IPagingOption.normal;
         //1. data object
@@ -6451,7 +6995,6 @@ class JpcExClass {
         //for garbage collection:
         dataHelper = null;
     }
-    ;
     //获取总页数
     paging(rptTpl, dataObj, defProperties, option) {
         let me = this, dftPagingOption = option || exports.IPagingOption.normal;
@@ -6476,17 +7019,15 @@ class JpcExClass {
             me.totalPages = me.billTab.paging(rptTpl, dataObj);
         }
     }
-    ;
     //根据步骤,对formulas中的计算式进行处理,并赋值到相应属性中
     executeFormulas(runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT) {
-        formulaExec(runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT);
+        return formulaExec(runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT);
     }
-    ;
     outputAsPreviewPage(rptTpl, defProperties) {
         let me = this, rst = {};
-        rst.control_collection = private_buildDftControls(rptTpl, (defProperties === null) ? null : defProperties.ctrls);
-        rst.style_collection = private_buildDftStyles(rptTpl, (defProperties === null) ? null : defProperties.styles);
-        rst.font_collection = private_buildDftFonts(rptTpl, (defProperties === null) ? null : defProperties.fonts);
+        rst.control_collection = private_buildDftControls(rptTpl, defProperties === null ? null : defProperties.ctrls);
+        rst.style_collection = private_buildDftStyles(rptTpl, defProperties === null ? null : defProperties.styles);
+        rst.font_collection = private_buildDftFonts(rptTpl, defProperties === null ? null : defProperties.fonts);
         rst.打印页面_信息 = {};
         rst.打印页面_信息.报表名称 = rptTpl.主信息.报表名称;
         rst.打印页面_信息.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
@@ -6507,7 +7048,7 @@ class JpcExClass {
             }
             //1.
             let rstPage = {
-                cells: []
+                cells: [],
             };
             rstPage.page_seq = 1;
             if (me.flowTab) {
@@ -6543,13 +7084,12 @@ class JpcExClass {
         }
         return rst;
     }
-    ;
     outputAsSimpleJSONPageArray(rptTpl, dataObj, startPage, endPage, defProperties, customizeCfg) {
         let me = this, rst = {};
-        if ((startPage > 0) && (startPage <= endPage) && (endPage <= me.totalPages)) {
-            rst.control_collection = private_buildDftControls(rptTpl, (defProperties === null) ? null : defProperties.ctrls);
-            rst.style_collection = private_buildDftStyles(rptTpl, (defProperties === null) ? null : defProperties.styles);
-            rst.font_collection = private_buildDftFonts(rptTpl, (defProperties === null) ? null : defProperties.fonts);
+        if (startPage > 0 && startPage <= endPage && endPage <= me.totalPages) {
+            rst.control_collection = private_buildDftControls(rptTpl, defProperties === null ? null : defProperties.ctrls);
+            rst.style_collection = private_buildDftStyles(rptTpl, defProperties === null ? null : defProperties.styles);
+            rst.font_collection = private_buildDftFonts(rptTpl, defProperties === null ? null : defProperties.fonts);
             rst.打印页面_信息 = {};
             rst.打印页面_信息.报表名称 = rptTpl.主信息.报表名称;
             rst.打印页面_信息.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
@@ -6560,7 +7100,7 @@ class JpcExClass {
             try {
                 for (let page = startPage; page <= endPage; page++) {
                     me.runTimePageData.currentPage = page;
-                    me.executeFormulas('before_output', rptTpl, dataObj, me);
+                    this.formulasObject = me.executeFormulas('before_output', rptTpl, dataObj, me);
                     // console.log('=======================');
                     rst.items.push(me.outputAsSimpleJSONPage(rptTpl, dataObj, bands, page, rst.control_collection, customizeCfg));
                 }
@@ -6585,7 +7125,6 @@ class JpcExClass {
         }
         return rst;
     }
-    ;
     outputAsSimpleJSONPage(rptTpl, dataObj, bands, page, controls, customizeCfg) {
         let me = this, rst = null;
         function getPageMergeBorder() {
@@ -6638,7 +7177,6 @@ class JpcExClass {
         }
         return rst;
     }
-    ;
 }
 //暂定
 const private_buildDftItems = (rptTpl, dftCollection, nodeName) => {
@@ -6648,8 +7186,10 @@ const private_buildDftItems = (rptTpl, dftCollection, nodeName) => {
             const { ID, ...dftCollectionProps } = dftCollection[i];
             rst[dftCollection[i].ID] = { ...dftCollectionProps };
         }
-        const propArray = (nodeName === 'control_collection') ? JV.CONTROL_PROPS : JV.FONT_PROPS;
-        if (rptTpl && rptTpl[nodeName] && rptTpl[nodeName].length) {
+        const propArray = nodeName === 'control_collection' ? JV.CONTROL_PROPS : JV.FONT_PROPS;
+        if (rptTpl &&
+            rptTpl[nodeName] &&
+            rptTpl[nodeName].length) {
             for (let i = 0; i < rptTpl[nodeName].length; i++) {
                 const rptDftItem = rptTpl[nodeName][i];
                 if (rst[rptDftItem.ID] === undefined) {
@@ -6680,7 +7220,8 @@ function private_buildDftStyles(rptTpl, dftStyleCollection) {
     if (dftStyleCollection) {
         for (let i = 0; i < dftStyleCollection.length; i++) {
             const item = {};
-            if (dftStyleCollection[i].border_style && dftStyleCollection[i].border_style.length > 0) {
+            if (dftStyleCollection[i].border_style &&
+                dftStyleCollection[i].border_style.length > 0) {
                 for (let j = 0; j < dftStyleCollection[i].border_style.length; j++) {
                     const borderItem = {};
                     private_CopyBorder(borderItem, dftStyleCollection[i].border_style[j]);
@@ -6689,7 +7230,9 @@ function private_buildDftStyles(rptTpl, dftStyleCollection) {
             }
             rst[dftStyleCollection[i].ID] = item;
         }
-        if (rptTpl && rptTpl.style_collection && rptTpl.style_collection.length > 0) {
+        if (rptTpl &&
+            rptTpl.style_collection &&
+            rptTpl.style_collection.length > 0) {
             for (let i = 0; i < rptTpl.style_collection.length; i++) {
                 const rptDftItem = rptTpl.style_collection[i];
                 if (rst[rptDftItem.ID] === undefined) {
@@ -7046,7 +7589,8 @@ class RptCommon {
             maxLen -= minLen;
         }
         for (let i = 0; i < maxLen; i++) {
-            let value = (i < val1.length ? val1[i] : val1[minLen - 1]) * (i < val2.length ? val2[i] : val2[minLen - 1]);
+            let value = (i < val1.length ? val1[i] : val1[minLen - 1]) *
+                (i < val2.length ? val2[i] : val2[minLen - 1]);
             if (value === null || value === undefined) {
                 value = 0;
             }
@@ -7066,7 +7610,8 @@ class RptCommon {
             maxLen -= minLen;
         }
         for (let i = 0; i < maxLen; i++) {
-            let value = (i < val1.length ? val1[i] : val1[minLen - 1]) / (i < val2.length ? val2[i] : val2[minLen - 1]);
+            let value = (i < val1.length ? val1[i] : val1[minLen - 1]) /
+                (i < val2.length ? val2[i] : val2[minLen - 1]);
             if (fixFormat)
                 value = parseFloat(value.toFixed(fixFormat));
             rst.push(value);
@@ -7083,7 +7628,8 @@ class RptCommon {
             maxLen -= minLen;
         }
         for (let i = 0; i < maxLen; i++) {
-            let value = (i < val1.length ? val1[i] : val1[minLen - 1]) + (i < val2.length ? val2[i] : val2[minLen - 1]);
+            let value = (i < val1.length ? val1[i] : val1[minLen - 1]) +
+                (i < val2.length ? val2[i] : val2[minLen - 1]);
             if (fixFormat)
                 value = parseFloat(value.toFixed(fixFormat));
             rst.push(value);
@@ -7131,7 +7677,8 @@ class RptCommon {
             maxLen -= minLen;
         }
         for (let i = 0; i < maxLen; i++) {
-            let value = (i < val1.length ? val1[i] : val1[minLen - 1]) - (i < val2.length ? val2[i] : val2[minLen - 1]);
+            let value = (i < val1.length ? val1[i] : val1[minLen - 1]) -
+                (i < val2.length ? val2[i] : val2[minLen - 1]);
             if (fixFormat)
                 value = parseFloat(value.toFixed(fixFormat));
             rst.push(value);
@@ -7141,7 +7688,7 @@ class RptCommon {
     formatString(arrVal, formatStr) {
         const rst = [];
         for (const val of arrVal) {
-            rst.push(replaceAll(formatStr, '%S', val));
+            rst.push(replaceAll$1(formatStr, '%S', val));
         }
         return rst;
     }
@@ -7203,7 +7750,7 @@ exports.projectConstList = projectConstList;
 exports.projectFieldConstList = projectFieldConstList;
 exports.rationKeyArray = rationKeyArray;
 exports.rationType = rationType$1;
-exports.replaceAll = replaceAll;
+exports.replaceAll = replaceAll$1;
 exports.rightTrim = rightTrim;
 exports.setupDateFormat = setupDateFormat;
 exports.summaryConstList = summaryConstList;

+ 1 - 1
report/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@sc/report",
-  "version": "3.0.7",
+  "version": "3.0.9",
   "description": "Smartcost Report Relative Module",
   "main": "./dist/index.cjs.js",
   "module": "./dist/index.esm.js",

+ 561 - 360
report/src/core/jpc_ex.ts

@@ -1,4 +1,3 @@
-
 import { JV } from './jpc_value_define';
 import { JpcBand } from './jpc_band';
 import { JpcFlowTabClass as JpcFlowTab } from './jpc_flow_tab';
@@ -10,396 +9,598 @@ import { JpcFunc } from './jpc_function';
 import { JpcEvent } from './jpc_event';
 import { JpcData } from './jpc_data';
 import { JpcCommonHelper } from './helper/jpc_helper_common';
-import { IDefProperties, IFormula, IParams, ICurrent_RPT, ICustomizeCfg, ITargetFields, IRptTpl, IDataObj, IBands, IControlCollection, IStyles, BorderStyle, IFontSubCollection, IControlSubCollection, IRstPage, IMergeBand, IFormulasObject } from '../interface/basic'
-import { IFlowTabClass, IBillTabClass, ICostTabClass } from '../interface/classType';
-import {  IPagingOption } from '../interface/enum';
+import {
+  IDefProperties,
+  IFormula,
+  IParams,
+  ICurrent_RPT,
+  ICustomizeCfg,
+  ITargetFields,
+  IRptTpl,
+  IDataObj,
+  IBands,
+  IControlCollection,
+  IStyles,
+  BorderStyle,
+  IFontSubCollection,
+  IControlSubCollection,
+  IRstPage,
+  IMergeBand,
+  IFormulasObject,
+} from '../interface/basic';
+import {
+  IFlowTabClass,
+  IBillTabClass,
+  ICostTabClass,
+} from '../interface/classType';
+import { IPagingOption } from '../interface/enum';
 import { Key } from 'readline';
-import {formulaExec} from './formulasFun'
-
+import { formulaExec } from './formulasFun';
 
 export class JpcExClass {
-    flowTab!: IFlowTabClass;
-    flowTabEx!: IFlowTabClass;
-    billTab!: IBillTabClass;
-    crossTab!: ICostTabClass;
-    isFollowMode: boolean = false;
-    totalPages: number = 0;
-    exTotalPages: number = 0;
-    runTimePageData: { currentPage?: number };
-    fields: ITargetFields;
-    params: IParams;
-    formulas: IFormula[];
-    events: any;
-    formulasObject :IFormulasObject={};
-
-    constructor(rptTpl: IRptTpl) {
-        if (rptTpl.流水式表_信息) {
-            this.flowTab = new JpcFlowTab(false);
-            this.isFollowMode = false;
-        }
-        if (rptTpl.流水式表_拓展信息) {
-            this.flowTabEx = new JpcFlowTab(true);
-            if (rptTpl.流水式表_拓展信息.流水拓展显示模式 === '紧随模式') {
-                this.isFollowMode = true;
-            }
-        }
-        if (rptTpl.账单式表_信息) {
-            this.billTab = new JpcBillTab();
-        }
-        //let dt1 = new Date();
-        if (rptTpl.交叉表_信息) {
-            this.crossTab = new JpcCrossTab();
-        }
-        this.runTimePageData = {};
-        this.fields = JpcField.createNew(rptTpl);
-        this.params = JpcParam.createNew(rptTpl);
-        this.formulas = JpcFunc.createNew(rptTpl);
-        this.events = JpcEvent.createNew(rptTpl);
-    };
-
-    analyzeData(rptTpl: IRptTpl, dataObj: IDataObj, defProperties: IDefProperties, option: string, outputType: string) {
-        let me = this, dftPagingOption = option || IPagingOption.normal;
-        //1. data object
-        let dataHelper: any = JpcData.createNew();
+  flowTab!: IFlowTabClass;
+  flowTabEx!: IFlowTabClass;
+  billTab!: IBillTabClass;
+  crossTab!: ICostTabClass;
+  isFollowMode: boolean = false;
+  totalPages: number = 0;
+  exTotalPages: number = 0;
+  runTimePageData: { currentPage?: number };
+  fields: ITargetFields;
+  params: IParams;
+  formulas: IFormula[];
+  events: any;
+  formulasObject: IFormulasObject = {};
 
-        // 主要是通过计算rptTpl参数里面的 指标_数据_映射 属性中的公式,赋值于dataObj中的相对应(根据)的属性
-        me.executeFormulas('before_analyzing', rptTpl, dataObj, me); //在分析前运行,主要是增加灵活性,比如:重新编排数据的主从关系
-        if (me.crossTab) {
-            me.executeFormulas('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);
-                }
-            }
+  constructor(rptTpl: IRptTpl) {
+    if (rptTpl.流水式表_信息) {
+      this.flowTab = new JpcFlowTab(false);
+      this.isFollowMode = false;
+    }
+    if (rptTpl.流水式表_拓展信息) {
+      this.flowTabEx = new JpcFlowTab(true);
+      if (rptTpl.流水式表_拓展信息.流水拓展显示模式 === '紧随模式') {
+        this.isFollowMode = true;
+      }
+    }
+    if (rptTpl.账单式表_信息) {
+      this.billTab = new JpcBillTab();
+    }
+    //let dt1 = new Date();
+    if (rptTpl.交叉表_信息) {
+      this.crossTab = new JpcCrossTab();
+    }
+    this.runTimePageData = {};
+    this.fields = JpcField.createNew(rptTpl);
+    this.params = JpcParam.createNew(rptTpl);
+    this.formulas = JpcFunc.createNew(rptTpl);
+    this.events = JpcEvent.createNew(rptTpl);
+  }
 
-            if (me.billTab) {
-                // 先记录下账单式表_信息.账单式表_数据中的数据相对应于从 数据指标_集合 中的相对应的数组序号,后面便于计算
-                // me.billTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
-                //edit by lish,方法中需要的参数只有一个,但是这里存入了4个
-                me.billTab.sorting(rptTpl);
+  analyzeData(
+    rptTpl: IRptTpl,
+    dataObj: IDataObj,
+    defProperties: IDefProperties,
+    option: string,
+    outputType: string
+  ) {
+    let me = this,
+      dftPagingOption = option || IPagingOption.normal;
+    //1. data object
+    let dataHelper: any = JpcData.createNew();
 
-            }
-            //3. formulas
-            // 主要是通过计算rptTpl参数里面的 指标_数据_映射 属性中的公式,赋值于dataObj中的相对应(根据)的属性
-            me.executeFormulas('before_paging', rptTpl, dataObj, me);
+    // 主要是通过计算rptTpl参数里面的 指标_数据_映射 属性中的公式,赋值于dataObj中的相对应(根据)的属性
+    me.executeFormulas('before_analyzing', rptTpl, dataObj, me); //在分析前运行,主要是增加灵活性,比如:重新编排数据的主从关系
+    if (me.crossTab) {
+      me.executeFormulas('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
+          );
         }
-        //4. paging
-        //获取总页数
-        me.paging(rptTpl, dataObj, defProperties, dftPagingOption);
-        //alert('analyzeData was completed!');
-        //for garbage collection:
-        dataHelper = null;
-    };
+      }
+
+      if (me.billTab) {
+        // 先记录下账单式表_信息.账单式表_数据中的数据相对应于从 数据指标_集合 中的相对应的数组序号,后面便于计算
+        // me.billTab.sorting(rptTpl, dataObj, dataHelper.dataSeq.slice(0), me);
+        //edit by lish,方法中需要的参数只有一个,但是这里存入了4个
+        me.billTab.sorting(rptTpl);
+      }
+      //3. formulas
+      // 主要是通过计算rptTpl参数里面的 指标_数据_映射 属性中的公式,赋值于dataObj中的相对应(根据)的属性
+      me.executeFormulas('before_paging', rptTpl, dataObj, me);
+    }
+    //4. paging
     //获取总页数
-    paging(rptTpl: IRptTpl, dataObj: IDataObj, defProperties: IDefProperties, option: string) {
-        let me = this, dftPagingOption = option || IPagingOption.normal;
-        if (me.flowTab) {
-            if (me.isFollowMode) {
-                me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, me.flowTabEx);
-            } else {
-                me.totalPages = me.flowTab.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null);
-                if (me.flowTabEx) {
-                    me.exTotalPages = me.flowTabEx.preSetupPages(rptTpl, dataObj, defProperties, dftPagingOption, me, null);
-                    //console.log('ad-hoc flow pages: ' + me.exTotalPages);
-                }
-                me.totalPages += me.exTotalPages;
-            }
-        } else if (me.crossTab) {
-            //me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, dftPagingOption);
-            me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, IPagingOption.normal); //infinity对交叉表来说无意义
-        } else if (me.billTab) {
-            me.totalPages = me.billTab.paging(rptTpl, dataObj);
+    me.paging(rptTpl, dataObj, defProperties, dftPagingOption);
+    //alert('analyzeData was completed!');
+    //for garbage collection:
+    dataHelper = null;
+  }
+  //获取总页数
+  paging(
+    rptTpl: IRptTpl,
+    dataObj: IDataObj,
+    defProperties: IDefProperties,
+    option: string
+  ) {
+    let me = this,
+      dftPagingOption = option || IPagingOption.normal;
+    if (me.flowTab) {
+      if (me.isFollowMode) {
+        me.totalPages = me.flowTab.preSetupPages(
+          rptTpl,
+          dataObj,
+          defProperties,
+          dftPagingOption,
+          me,
+          me.flowTabEx
+        );
+      } else {
+        me.totalPages = me.flowTab.preSetupPages(
+          rptTpl,
+          dataObj,
+          defProperties,
+          dftPagingOption,
+          me,
+          null
+        );
+        if (me.flowTabEx) {
+          me.exTotalPages = me.flowTabEx.preSetupPages(
+            rptTpl,
+            dataObj,
+            defProperties,
+            dftPagingOption,
+            me,
+            null
+          );
+          //console.log('ad-hoc flow pages: ' + me.exTotalPages);
         }
-    };
+        me.totalPages += me.exTotalPages;
+      }
+    } else if (me.crossTab) {
+      //me.totalPages = me.crossTab.preSetupPages(rptTpl, defProperties, dftPagingOption);
+      me.totalPages = me.crossTab.preSetupPages(
+        rptTpl,
+        defProperties,
+        IPagingOption.normal
+      ); //infinity对交叉表来说无意义
+    } else if (me.billTab) {
+      me.totalPages = me.billTab.paging(rptTpl, dataObj);
+    }
+  }
 
-    //根据步骤,对formulas中的计算式进行处理,并赋值到相应属性中
-    executeFormulas(runType: string, $CURRENT_TEMPLATE: IRptTpl, $CURRENT_DATA: IDataObj, $CURRENT_RPT: ICurrent_RPT) {
-      return formulaExec(runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT);
-    };
+  //根据步骤,对formulas中的计算式进行处理,并赋值到相应属性中
+  executeFormulas(
+    runType: string,
+    $CURRENT_TEMPLATE: IRptTpl,
+    $CURRENT_DATA: IDataObj,
+    $CURRENT_RPT: ICurrent_RPT
+  ) {
+    return formulaExec(runType, $CURRENT_TEMPLATE, $CURRENT_DATA, $CURRENT_RPT);
+  }
 
-    outputAsPreviewPage(rptTpl: IRptTpl, defProperties: IDefProperties) {
-        let me = this, rst: any = {};
-        rst.control_collection = private_buildDftControls(rptTpl, (defProperties === null) ? null : defProperties.ctrls);
-        rst.style_collection = private_buildDftStyles(rptTpl, (defProperties === null) ? null : defProperties.styles);
-        rst.font_collection = private_buildDftFonts(rptTpl, (defProperties === null) ? null : defProperties.fonts);
-        rst.打印页面_信息 = {};
-        rst.打印页面_信息.报表名称 = rptTpl.主信息.报表名称;
-        rst.打印页面_信息.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
-        rst.打印页面_信息.页边距 = rptTpl.主信息.页边距;
-        rst.items = [];
-        let bands = JpcBand.createNew(rptTpl, defProperties);
-        try {
-            function getPageMergeBorder() {
-                let mergeRst = {} as IMergeBand;
-                if (bands.MergeBand) {
-                    let mergedBand = bands.MergeBand;
-                    mergeRst.Left = parseInt(mergedBand.Left.toFixed(0));
-                    mergeRst.Right = parseInt(mergedBand.Right.toFixed(0));
-                    mergeRst.Top = parseInt(mergedBand.Top.toFixed(0));
-                    mergeRst.Bottom = parseInt(mergedBand.Bottom.toFixed(0));
-                }
-                return null;
-            }
-            //1.
-            let rstPage: IRstPage = {
-                cells:[]
-            };
-            rstPage.page_seq = 1;
-            if (me.flowTab) {
-                rstPage.cells = me.flowTab.outputAsPreviewPage(rptTpl, bands, rst.control_collection, me);
-            } else if (me.crossTab) {
-                rstPage.cells = me.crossTab.outputAsPreviewPage(rptTpl, bands, rst.control_collection, me, null as unknown as ICustomizeCfg);//方法中定义了5个参数,这里只传进去了4个参数,故加一个参数,by lish
-            } else if (me.billTab) {
-                rstPage.cells = me.billTab.outputAsPreviewPage(rptTpl, bands, rst.control_collection, me);
-            }
-            let pageMergeBorder = getPageMergeBorder();
-            if (pageMergeBorder) {
-                rstPage.page_merge_border = pageMergeBorder;
-            }
-            rst.items.push(rstPage);
-            //2.
-            if (bands.MergeBand) {
-                let band = bands.MergeBand;
-                let mergedBand :IMergeBand= {
-                    Left : parseInt(band.Left.toFixed(0)),
-                    Right: parseInt(band.Right.toFixed(0)),
-                    Top : parseInt(band.Top.toFixed(0)),
-                    Bottom :parseInt(band.Bottom.toFixed(0)),
-                    style: band.style,
-                } ;
-                rst.MergeBand = mergedBand;
-            }
-        } catch (exception) {
-            console.log(exception);
-        } finally {
-            bands = null;
+  outputAsPreviewPage(rptTpl: IRptTpl, defProperties: IDefProperties) {
+    let me = this,
+      rst: any = {};
+    rst.control_collection = private_buildDftControls(
+      rptTpl,
+      defProperties === null ? null : defProperties.ctrls
+    );
+    rst.style_collection = private_buildDftStyles(
+      rptTpl,
+      defProperties === null ? null : defProperties.styles
+    );
+    rst.font_collection = private_buildDftFonts(
+      rptTpl,
+      defProperties === null ? null : defProperties.fonts
+    );
+    rst.打印页面_信息 = {};
+    rst.打印页面_信息.报表名称 = rptTpl.主信息.报表名称;
+    rst.打印页面_信息.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
+    rst.打印页面_信息.页边距 = rptTpl.主信息.页边距;
+    rst.items = [];
+    let bands = JpcBand.createNew(rptTpl, defProperties);
+    try {
+      function getPageMergeBorder() {
+        let mergeRst = {} as IMergeBand;
+        if (bands.MergeBand) {
+          let mergedBand = bands.MergeBand;
+          mergeRst.Left = parseInt(mergedBand.Left.toFixed(0));
+          mergeRst.Right = parseInt(mergedBand.Right.toFixed(0));
+          mergeRst.Top = parseInt(mergedBand.Top.toFixed(0));
+          mergeRst.Bottom = parseInt(mergedBand.Bottom.toFixed(0));
         }
-        return rst;
-    };
+        return null;
+      }
+      //1.
+      let rstPage: IRstPage = {
+        cells: [],
+      };
+      rstPage.page_seq = 1;
+      if (me.flowTab) {
+        rstPage.cells = me.flowTab.outputAsPreviewPage(
+          rptTpl,
+          bands,
+          rst.control_collection,
+          me
+        );
+      } else if (me.crossTab) {
+        rstPage.cells = me.crossTab.outputAsPreviewPage(
+          rptTpl,
+          bands,
+          rst.control_collection,
+          me,
+          null as unknown as ICustomizeCfg
+        ); //方法中定义了5个参数,这里只传进去了4个参数,故加一个参数,by lish
+      } else if (me.billTab) {
+        rstPage.cells = me.billTab.outputAsPreviewPage(
+          rptTpl,
+          bands,
+          rst.control_collection,
+          me
+        );
+      }
+      let pageMergeBorder = getPageMergeBorder();
+      if (pageMergeBorder) {
+        rstPage.page_merge_border = pageMergeBorder;
+      }
+      rst.items.push(rstPage);
+      //2.
+      if (bands.MergeBand) {
+        let band = bands.MergeBand;
+        let mergedBand: IMergeBand = {
+          Left: parseInt(band.Left.toFixed(0)),
+          Right: parseInt(band.Right.toFixed(0)),
+          Top: parseInt(band.Top.toFixed(0)),
+          Bottom: parseInt(band.Bottom.toFixed(0)),
+          style: band.style,
+        };
+        rst.MergeBand = mergedBand;
+      }
+    } catch (exception) {
+      console.log(exception);
+    } finally {
+      bands = null;
+    }
+    return rst;
+  }
 
-    outputAsSimpleJSONPageArray(rptTpl: IRptTpl, dataObj: IDataObj, startPage: number, endPage: number, defProperties: IDefProperties, customizeCfg: ICustomizeCfg) {
-        let me = this, rst: any = {};
-        if ((startPage > 0) && (startPage <= endPage) && (endPage <= me.totalPages)) {
-            rst.control_collection = private_buildDftControls(rptTpl, (defProperties === null) ? null : defProperties.ctrls);
-            rst.style_collection = private_buildDftStyles(rptTpl, (defProperties === null) ? null : defProperties.styles);
-            rst.font_collection = private_buildDftFonts(rptTpl, (defProperties === null) ? null : defProperties.fonts);
-            rst.打印页面_信息 = {};
-            rst.打印页面_信息.报表名称 = rptTpl.主信息.报表名称;
-            rst.打印页面_信息.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
-            rst.打印页面_信息.页边距 = rptTpl.主信息.页边距;
-            rst.items = [];
-            //初始化band(每个大板块的属性)
-            let bands = JpcBand.createNew(rptTpl, defProperties);
-            try {
-                for (let page = startPage; page <= endPage; page++) {
-                    me.runTimePageData.currentPage = page;
-                   this.formulasObject = me.executeFormulas('before_output', rptTpl, dataObj, me);
-                    // console.log('=======================');
-                    rst.items.push(me.outputAsSimpleJSONPage(rptTpl, dataObj, bands, page, rst.control_collection, customizeCfg));
-                }
-                if (bands.MergeBand) {
-                    let band = bands.MergeBand;
-                    let mergedBand: IMergeBand = {
-                        Left : parseInt(band.Left.toFixed(0)),
-                        Right: parseInt(band.Right.toFixed(0)),
-                        Top : parseInt(band.Top.toFixed(0)),
-                        Bottom : parseInt(band.Bottom.toFixed(0)),
-                        style : band.style,
-                    };
-                   
-                    rst.MergeBand = mergedBand;
-                }
-            } catch (exception) {
-                console.log(exception);
-            } finally {
-                bands = null;
-            }
+  outputAsSimpleJSONPageArray(
+    rptTpl: IRptTpl,
+    dataObj: IDataObj,
+    startPage: number,
+    endPage: number,
+    defProperties: IDefProperties,
+    customizeCfg: ICustomizeCfg
+  ) {
+    let me = this,
+      rst: any = {};
+    if (startPage > 0 && startPage <= endPage && endPage <= me.totalPages) {
+      rst.control_collection = private_buildDftControls(
+        rptTpl,
+        defProperties === null ? null : defProperties.ctrls
+      );
+      rst.style_collection = private_buildDftStyles(
+        rptTpl,
+        defProperties === null ? null : defProperties.styles
+      );
+      rst.font_collection = private_buildDftFonts(
+        rptTpl,
+        defProperties === null ? null : defProperties.fonts
+      );
+      rst.打印页面_信息 = {};
+      rst.打印页面_信息.报表名称 = rptTpl.主信息.报表名称;
+      rst.打印页面_信息.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
+      rst.打印页面_信息.页边距 = rptTpl.主信息.页边距;
+      rst.items = [];
+      //初始化band(每个大板块的属性)
+      let bands = JpcBand.createNew(rptTpl, defProperties);
+      try {
+        for (let page = startPage; page <= endPage; page++) {
+          me.runTimePageData.currentPage = page;
+          this.formulasObject = me.executeFormulas(
+            'before_output',
+            rptTpl,
+            dataObj,
+            me
+          );
+          // console.log('=======================');
+          rst.items.push(
+            me.outputAsSimpleJSONPage(
+              rptTpl,
+              dataObj,
+              bands,
+              page,
+              rst.control_collection,
+              customizeCfg
+            )
+          );
         }
-        return rst;
-    };
+        if (bands.MergeBand) {
+          let band = bands.MergeBand;
+          let mergedBand: IMergeBand = {
+            Left: parseInt(band.Left.toFixed(0)),
+            Right: parseInt(band.Right.toFixed(0)),
+            Top: parseInt(band.Top.toFixed(0)),
+            Bottom: parseInt(band.Bottom.toFixed(0)),
+            style: band.style,
+          };
 
-    outputAsSimpleJSONPage(rptTpl: IRptTpl, dataObj: IDataObj, bands: IBands, page: number, controls: IControlCollection, customizeCfg: ICustomizeCfg) {
-        let me = this, rst: any = null;
-        function getPageMergeBorder() {
-            // let mergeRst = null;
-            let mergeRst  = {} as IMergeBand;
-            if (bands.MergeBand) {
-                let mergedBand = bands.MergeBand;
-                mergeRst.Left = parseInt(mergedBand.Left.toFixed(0));
-                mergeRst.Right = parseInt(mergedBand.Right.toFixed(0));
-                mergeRst.Top = parseInt(mergedBand.Top.toFixed(0));
-                mergeRst.Bottom = parseInt(mergedBand.Bottom.toFixed(0));
-            }
-            return mergeRst;
-            // return false;
+          rst.MergeBand = mergedBand;
         }
-        if (me.totalPages >= page) {
-            rst = {};
-            rst.page_seq = page;
-            //rst.cells = [];
-            let adHocMergePos: any = null;
-            if (me.flowTab) {
-                if (me.totalPages - me.exTotalPages >= page) {
-                    if (me.flowTab.paging_option === JV.PAGING_OPTION_INFINITY) {
-                        adHocMergePos = {};
-                    }
-                    rst.cells = me.flowTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, adHocMergePos, me, customizeCfg);
-                    if (adHocMergePos) {
-                        adHocMergePos.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
-                        rst.page_merge_pos = adHocMergePos;
-                    }
+      } catch (exception) {
+        console.log(exception);
+      } finally {
+        bands = null;
+      }
+    }
+    return rst;
+  }
 
-                } else {
-                    if (!me.isFollowMode) {
-                        rst.cells = me.flowTabEx.outputAsSimpleJSONPage(rptTpl, dataObj, page - (me.totalPages - me.exTotalPages), bands, controls, adHocMergePos, me, customizeCfg);
-                    }
-                }
-            } else if (me.crossTab) {
-                rst.cells = me.crossTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me, customizeCfg);
-            } else if (me.billTab) {
-                rst.cells = me.billTab.outputAsSimpleJSONPage(rptTpl, dataObj, page, bands, controls, me, customizeCfg);
-            }
-            if (!(me.flowTab && me.flowTab.paging_option === IPagingOption.infinity)) {
-                let pageMergeBorder = getPageMergeBorder();
-                if (pageMergeBorder) {
-                    rst.page_merge_border = pageMergeBorder;
-                }
-            }
+  outputAsSimpleJSONPage(
+    rptTpl: IRptTpl,
+    dataObj: IDataObj,
+    bands: IBands,
+    page: number,
+    controls: IControlCollection,
+    customizeCfg: ICustomizeCfg
+  ) {
+    let me = this,
+      rst: any = null;
+    function getPageMergeBorder() {
+      // let mergeRst = null;
+      let mergeRst = {} as IMergeBand;
+      if (bands.MergeBand) {
+        let mergedBand = bands.MergeBand;
+        mergeRst.Left = parseInt(mergedBand.Left.toFixed(0));
+        mergeRst.Right = parseInt(mergedBand.Right.toFixed(0));
+        mergeRst.Top = parseInt(mergedBand.Top.toFixed(0));
+        mergeRst.Bottom = parseInt(mergedBand.Bottom.toFixed(0));
+      }
+      return mergeRst;
+      // return false;
+    }
+    if (me.totalPages >= page) {
+      rst = {};
+      rst.page_seq = page;
+      //rst.cells = [];
+      let adHocMergePos: any = null;
+      if (me.flowTab) {
+        if (me.totalPages - me.exTotalPages >= page) {
+          if (me.flowTab.paging_option === JV.PAGING_OPTION_INFINITY) {
+            adHocMergePos = {};
+          }
+          rst.cells = me.flowTab.outputAsSimpleJSONPage(
+            rptTpl,
+            dataObj,
+            page,
+            bands,
+            controls,
+            adHocMergePos,
+            me,
+            customizeCfg
+          );
+          if (adHocMergePos) {
+            adHocMergePos.纸张宽高 = JpcCommonHelper.getPageSize(rptTpl);
+            rst.page_merge_pos = adHocMergePos;
+          }
+        } else {
+          if (!me.isFollowMode) {
+            rst.cells = me.flowTabEx.outputAsSimpleJSONPage(
+              rptTpl,
+              dataObj,
+              page - (me.totalPages - me.exTotalPages),
+              bands,
+              controls,
+              adHocMergePos,
+              me,
+              customizeCfg
+            );
+          }
+        }
+      } else if (me.crossTab) {
+        rst.cells = me.crossTab.outputAsSimpleJSONPage(
+          rptTpl,
+          dataObj,
+          page,
+          bands,
+          controls,
+          me,
+          customizeCfg
+        );
+      } else if (me.billTab) {
+        rst.cells = me.billTab.outputAsSimpleJSONPage(
+          rptTpl,
+          dataObj,
+          page,
+          bands,
+          controls,
+          me,
+          customizeCfg
+        );
+      }
+      if (
+        !(me.flowTab && me.flowTab.paging_option === IPagingOption.infinity)
+      ) {
+        let pageMergeBorder = getPageMergeBorder();
+        if (pageMergeBorder) {
+          rst.page_merge_border = pageMergeBorder;
         }
-        return rst;
-    };
+      }
+    }
+    return rst;
+  }
 }
 
 //暂定
 const private_buildDftItems = (
-    rptTpl: IRptTpl,
-    dftCollection: IControlSubCollection[] | IFontSubCollection[] | null,
-    nodeName: string 
-) => { 
-    const rst: any = {};
-    if (dftCollection) {
-        for (let i = 0; i < dftCollection.length; i++) {
-            const { ID, ...dftCollectionProps } = dftCollection[i];
-            rst[dftCollection[i].ID] = { ...dftCollectionProps };
-        }
-        const propArray = (nodeName === 'control_collection') ? JV.CONTROL_PROPS : JV.FONT_PROPS;
-        if (rptTpl && rptTpl[nodeName as keyof IRptTpl] && rptTpl[nodeName  as keyof IRptTpl].length) {
-            for (let i = 0; i < rptTpl[nodeName  as keyof IRptTpl].length; i++) {
-                const rptDftItem = rptTpl[nodeName  as keyof IRptTpl][i];
-                if (rst[rptDftItem.ID] === undefined) {
-                    const item: any = {};
-                    for (let j = 0; j < propArray.length; j++) {
-                        item[propArray[j]] = rptDftItem[propArray[j]];
-                    }
-                    rst[rptDftItem.ID] = item;
-                }
-            }
+  rptTpl: IRptTpl,
+  dftCollection: IControlSubCollection[] | IFontSubCollection[] | null,
+  nodeName: string
+) => {
+  const rst: any = {};
+  if (dftCollection) {
+    for (let i = 0; i < dftCollection.length; i++) {
+      const { ID, ...dftCollectionProps } = dftCollection[i];
+      rst[dftCollection[i].ID] = { ...dftCollectionProps };
+    }
+    const propArray =
+      nodeName === 'control_collection' ? JV.CONTROL_PROPS : JV.FONT_PROPS;
+    if (
+      rptTpl &&
+      rptTpl[nodeName as keyof IRptTpl] &&
+      rptTpl[nodeName as keyof IRptTpl].length
+    ) {
+      for (let i = 0; i < rptTpl[nodeName as keyof IRptTpl].length; i++) {
+        const rptDftItem = rptTpl[nodeName as keyof IRptTpl][i];
+        if (rst[rptDftItem.ID] === undefined) {
+          const item: any = {};
+          for (let j = 0; j < propArray.length; j++) {
+            item[propArray[j]] = rptDftItem[propArray[j]];
+          }
+          rst[rptDftItem.ID] = item;
         }
+      }
     }
-    return rst;
-}
+  }
+  return rst;
+};
 
-function private_buildDftControls(rptTpl: IRptTpl, dftControlCollection: IControlSubCollection[] | null) {
-    return private_buildDftItems(rptTpl, dftControlCollection, 'control_collection');
+function private_buildDftControls(
+  rptTpl: IRptTpl,
+  dftControlCollection: IControlSubCollection[] | null
+) {
+  return private_buildDftItems(
+    rptTpl,
+    dftControlCollection,
+    'control_collection'
+  );
 }
 
-function private_buildDftFonts(rptTpl: IRptTpl, dftFontCollection: IFontSubCollection[] | null) {
-    return private_buildDftItems(rptTpl, dftFontCollection, 'font_collection');
+function private_buildDftFonts(
+  rptTpl: IRptTpl,
+  dftFontCollection: IFontSubCollection[] | null
+) {
+  return private_buildDftItems(rptTpl, dftFontCollection, 'font_collection');
 }
 
-function private_buildDftStyles(rptTpl: IRptTpl, dftStyleCollection: IStyles[] | null) {
-    const rst: any = {};
-    function private_CopyBorder(destItem: BorderStyle, srcItem: BorderStyle) {
-        destItem.LineWeight = srcItem.LineWeight;
-        destItem.DashStyle = srcItem.DashStyle;
-        destItem.Color = srcItem.Color;
+function private_buildDftStyles(
+  rptTpl: IRptTpl,
+  dftStyleCollection: IStyles[] | null
+) {
+  const rst: any = {};
+  function private_CopyBorder(destItem: BorderStyle, srcItem: BorderStyle) {
+    destItem.LineWeight = srcItem.LineWeight;
+    destItem.DashStyle = srcItem.DashStyle;
+    destItem.Color = srcItem.Color;
+  }
+  if (dftStyleCollection) {
+    for (let i = 0; i < dftStyleCollection.length; i++) {
+      const item: any = {};
+      if (
+        dftStyleCollection[i].border_style &&
+        dftStyleCollection[i].border_style.length > 0
+      ) {
+        for (let j = 0; j < dftStyleCollection[i].border_style.length; j++) {
+          const borderItem = {} as BorderStyle;
+          private_CopyBorder(borderItem, dftStyleCollection[i].border_style[j]);
+          item[dftStyleCollection[i].border_style[j].Position] = borderItem;
+        }
+      }
+      rst[dftStyleCollection[i].ID] = item;
     }
-    if (dftStyleCollection) {
-        for (let i = 0; i < dftStyleCollection.length; i++) {
-            const item: any = {};
-            if (dftStyleCollection[i].border_style && dftStyleCollection[i].border_style.length > 0) {
-                for (let j = 0; j < dftStyleCollection[i].border_style.length; j++) {
-                    const borderItem = {} as BorderStyle;
-                    private_CopyBorder(borderItem, dftStyleCollection[i].border_style[j]);
-                    item[dftStyleCollection[i].border_style[j].Position] = borderItem;
-                }
+    if (
+      rptTpl &&
+      rptTpl.style_collection &&
+      rptTpl.style_collection.length > 0
+    ) {
+      for (let i = 0; i < rptTpl.style_collection.length; i++) {
+        const rptDftItem: any = rptTpl.style_collection[i];
+        if (rst[rptDftItem.ID] === undefined) {
+          if (rptDftItem.ID.indexOf('_AutoHeightMerge_Top') > 0) {
+            const key = rptDftItem.ID.substr(
+              0,
+              rptDftItem.ID.indexOf('_AutoHeightMerge_Top')
+            );
+            if (rst[key]) {
+              const item: any = {};
+              if (rst[key].Left) {
+                item.Left = {};
+                private_CopyBorder(item.Left, rst[key].Left);
+              }
+              if (rst[key].Right) {
+                item.Right = {};
+                private_CopyBorder(item.Right, rst[key].Right);
+              }
+              if (rst[key].Top) {
+                item.Top = {};
+                private_CopyBorder(item.Top, rst[key].Top);
+              }
+              rst[rptDftItem.ID] = item;
             }
-            rst[dftStyleCollection[i].ID] = item;
-        }
-        if (rptTpl && rptTpl.style_collection && rptTpl.style_collection.length > 0) {
-            for (let i = 0; i < rptTpl.style_collection.length; i++) {
-                const rptDftItem = rptTpl.style_collection[i];
-                if (rst[rptDftItem.ID] === undefined) {
-                    if (rptDftItem.ID.indexOf('_AutoHeightMerge_Top') > 0) {
-                        const key = rptDftItem.ID.substr(0, rptDftItem.ID.indexOf('_AutoHeightMerge_Top'));
-                        if (rst[key]) {
-                            const item: any = {};
-                            if (rst[key].Left) {
-                                item.Left = {};
-                                private_CopyBorder(item.Left, rst[key].Left);
-                            }
-                            if (rst[key].Right) {
-                                item.Right = {};
-                                private_CopyBorder(item.Right, rst[key].Right);
-                            }
-                            if (rst[key].Top) {
-                                item.Top = {};
-                                private_CopyBorder(item.Top, rst[key].Top);
-                            }
-                            rst[rptDftItem.ID] = item;
-                        }
-                    } else if (rptDftItem.ID.indexOf('_AutoHeightMerge_Middle') > 0) {
-                        const key = rptDftItem.ID.substr(0, rptDftItem.ID.indexOf('_AutoHeightMerge_Middle'));
-                        if (rst[key]) {
-                            const item: any = {};
-                            if (rst[key].Left) {
-                                item.Left = {};
-                                private_CopyBorder(item.Left, rst[key].Left);
-                            }
-                            if (rst[key].Right) {
-                                item.Right = {};
-                                private_CopyBorder(item.Right, rst[key].Right);
-                            }
-                            rst[rptDftItem.ID] = item;
-                        }
-                    } else if (rptDftItem.ID.indexOf('_AutoHeightMerge_Bottom') > 0) {
-                        const key = rptDftItem.ID.substr(0, rptDftItem.ID.indexOf('_AutoHeightMerge_Bottom'));
-                        if (rst[key]) {
-                            const item: any = {};
-                            if (rst[key].Left) {
-                                item.Left = {};
-                                private_CopyBorder(item.Left, rst[key].Left);
-                            }
-                            if (rst[key].Right) {
-                                item.Right = {};
-                                private_CopyBorder(item.Right, rst[key].Right);
-                            }
-                            if (rst[key].Bottom) {
-                                item.Bottom = {};
-                                private_CopyBorder(item.Bottom, rst[key].Bottom);
-                            }
-                            rst[rptDftItem.ID] = item;
-                        }
-                    } else {
-                        const item: any = {};
-                        for (let j = 0; j < rptDftItem.border_style.length; j++) {
-                            const borderItem = {} as BorderStyle;
-                            private_CopyBorder(borderItem, rptDftItem.border_style[j]);
-                            item[rptDftItem.border_style[j].Position] = borderItem;
-                        }
-                        rst[rptDftItem.ID] = item;
-                    }
-                }
+          } else if (rptDftItem.ID.indexOf('_AutoHeightMerge_Middle') > 0) {
+            const key = rptDftItem.ID.substr(
+              0,
+              rptDftItem.ID.indexOf('_AutoHeightMerge_Middle')
+            );
+            if (rst[key]) {
+              const item: any = {};
+              if (rst[key].Left) {
+                item.Left = {};
+                private_CopyBorder(item.Left, rst[key].Left);
+              }
+              if (rst[key].Right) {
+                item.Right = {};
+                private_CopyBorder(item.Right, rst[key].Right);
+              }
+              rst[rptDftItem.ID] = item;
+            }
+          } else if (rptDftItem.ID.indexOf('_AutoHeightMerge_Bottom') > 0) {
+            const key = rptDftItem.ID.substr(
+              0,
+              rptDftItem.ID.indexOf('_AutoHeightMerge_Bottom')
+            );
+            if (rst[key]) {
+              const item: any = {};
+              if (rst[key].Left) {
+                item.Left = {};
+                private_CopyBorder(item.Left, rst[key].Left);
+              }
+              if (rst[key].Right) {
+                item.Right = {};
+                private_CopyBorder(item.Right, rst[key].Right);
+              }
+              if (rst[key].Bottom) {
+                item.Bottom = {};
+                private_CopyBorder(item.Bottom, rst[key].Bottom);
+              }
+              rst[rptDftItem.ID] = item;
+            }
+          } else {
+            const item: any = {};
+            for (let j = 0; j < rptDftItem.border_style.length; j++) {
+              const borderItem = {} as BorderStyle;
+              private_CopyBorder(borderItem, rptDftItem.border_style[j]);
+              item[rptDftItem.border_style[j].Position] = borderItem;
             }
+            rst[rptDftItem.ID] = item;
+          }
         }
+      }
     }
-    return rst;
-}
+  }
+  return rst;
+}

+ 10 - 6
report/src/public/ReportDate.ts

@@ -1,12 +1,9 @@
-import { set } from 'lodash';
-
 export class ReportDate extends Date {
- 
   // prototype: any;
 
   // constructor() {
   //   super();
-   
+
   //   set(this.prototype, 'Format', this.Format);
   //   Object.assign(Date, this);
   // }
@@ -21,10 +18,17 @@ export class ReportDate extends Date {
       'q+': Math.floor((this.getMonth() + 3) / 3), // 季度
       S: this.getMilliseconds(), // 毫秒
     };
-    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, `${this.getFullYear()}`.substr(4 - RegExp.$1.length));
+    if (/(y+)/.test(fmt))
+      fmt = fmt.replace(
+        RegExp.$1,
+        `${this.getFullYear()}`.substr(4 - RegExp.$1.length)
+      );
     for (const k in o)
       if (new RegExp(`(${k})`).test(fmt))
-        fmt = fmt.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : `00${o[k]}`.substr(`${o[k]}`.length));
+        fmt = fmt.replace(
+          RegExp.$1,
+          RegExp.$1.length === 1 ? o[k] : `00${o[k]}`.substr(`${o[k]}`.length)
+        );
     return fmt;
   };
 }

+ 13 - 5
report/src/public/rptCommon.ts

@@ -29,7 +29,9 @@ export class RptCommon {
       maxLen -= minLen;
     }
     for (let i = 0; i < maxLen; i++) {
-      let value = (i < val1.length ? val1[i] : val1[minLen - 1]) * (i < val2.length ? val2[i] : val2[minLen - 1]);
+      let value =
+        (i < val1.length ? val1[i] : val1[minLen - 1]) *
+        (i < val2.length ? val2[i] : val2[minLen - 1]);
       if (value === null || value === undefined) {
         value = 0;
       }
@@ -49,7 +51,9 @@ export class RptCommon {
       maxLen -= minLen;
     }
     for (let i = 0; i < maxLen; i++) {
-      let value = (i < val1.length ? val1[i] : val1[minLen - 1]) / (i < val2.length ? val2[i] : val2[minLen - 1]);
+      let value =
+        (i < val1.length ? val1[i] : val1[minLen - 1]) /
+        (i < val2.length ? val2[i] : val2[minLen - 1]);
       if (fixFormat) value = parseFloat(value.toFixed(fixFormat));
       rst.push(value);
     }
@@ -66,7 +70,9 @@ export class RptCommon {
       maxLen -= minLen;
     }
     for (let i = 0; i < maxLen; i++) {
-      let value = (i < val1.length ? val1[i] : val1[minLen - 1]) + (i < val2.length ? val2[i] : val2[minLen - 1]);
+      let value =
+        (i < val1.length ? val1[i] : val1[minLen - 1]) +
+        (i < val2.length ? val2[i] : val2[minLen - 1]);
       if (fixFormat) value = parseFloat(value.toFixed(fixFormat));
       rst.push(value);
     }
@@ -110,7 +116,9 @@ export class RptCommon {
       maxLen -= minLen;
     }
     for (let i = 0; i < maxLen; i++) {
-      let value = (i < val1.length ? val1[i] : val1[minLen - 1]) - (i < val2.length ? val2[i] : val2[minLen - 1]);
+      let value =
+        (i < val1.length ? val1[i] : val1[minLen - 1]) -
+        (i < val2.length ? val2[i] : val2[minLen - 1]);
       if (fixFormat) value = parseFloat(value.toFixed(fixFormat));
       rst.push(value);
     }
@@ -143,4 +151,4 @@ export class RptCommon {
     }
     return rst;
   }
-}
+}

+ 1 - 0
types/.eslintrc.js

@@ -37,5 +37,6 @@ module.exports = {
     'no-shadow': 'off',
     '@typescript-eslint/no-shadow': 'error',
     'max-classes-per-file': 'off',
+    '@typescript-eslint/no-namespace': 'off',
   },
 };

+ 1 - 0
types/src/index.ts

@@ -1 +1,2 @@
 export * from './interface/index';
+export * from './interface/api/index'

+ 46 - 0
types/src/interface/api/approvaApi.ts

@@ -0,0 +1,46 @@
+import { IGatherYsProfileFile, IMatterNode, UploadMsg } from '..';
+
+export namespace PostApprovalCopyGatherYsProfileFiles {
+  export type Params = {
+    fileDataList: {
+      name: string;
+      ext: string;
+      size: any;
+      path: string;
+      createTime: number;
+    }[];
+    gypID: string;
+  };
+
+  export interface Response {
+    fileList: IGatherYsProfileFile[];
+    count: number;
+  }
+}
+
+export namespace GetApprovalGetMatterData {
+  export type Params = {
+    businessID: string;
+    getAllMatter?: boolean; // 是否获取全部matter
+  };
+
+  export type Response = Array<IMatterNode>;
+}
+
+export namespace GetApprovalGetYsProfileTreeWithFile {
+  export type Params = { businessId: string; matterId: string };
+
+  export type Response = Array<IMatterNode>;
+}
+
+export namespace GetApprovalGetGatherYsProfileByBusinessID {
+  export type Params = { businessID: string; matterID: string };
+
+  export type Response = {
+    tree: any[];
+    profileView: boolean;
+    uploadMsg: UploadMsg;
+    cadView: boolean;
+    copy: boolean;
+  };
+}

+ 2 - 0
types/src/interface/api/index.ts

@@ -0,0 +1,2 @@
+export * from './approvaApi';
+export * from './processApi';

+ 11 - 0
types/src/interface/api/processApi.ts

@@ -0,0 +1,11 @@
+export namespace PostGetProcessListByTemplateId {
+  export type Params = {
+    businessID: string;
+    templateIds: string[];
+  };
+
+  export type Response = Array<{
+    templateId: string;
+    referenceProcessId: string;
+  }>;
+}

+ 24 - 0
types/src/interface/budgetCheck.ts

@@ -0,0 +1,24 @@
+export interface IBudgetCheckSidebarListItem {
+  ID: string;
+  title: string;
+  subtitle: string;
+}
+
+export interface IBudgetCheckFormTree {
+  ID: string;
+  name: string;
+  parentID: string;
+  folder: boolean;
+  children?: IBudgetCheckFormTree[];
+}
+
+export interface IBudgetCheckForm {
+  ID: string;
+  businessID: string; // 业务ID
+  approvalID: string; // 流程ID
+  matterID: string; // 事项ID
+  title: string; // 复核表标题
+  subtitle: string; // 复核表副标题
+  executorIDs: string[]; // 关联执行者ID
+  tree: IBudgetCheckFormTree[]; // 复核表结构
+}

+ 31 - 0
types/src/interface/business.ts

@@ -9,9 +9,40 @@ export interface ICostInfo {
   minPassRate: number; // 合格率线
 }
 
+export interface ICostInfoFromFormily {
+  orgFee: number; // 送审金额
+  conclusionFee: number; // 审结金额
+  dynamicFee: number; // 动态金额
+  provisionalFee: number; // 含预留金
+  incFee: number; // 核增金额
+  decFee: number; // 核减金额
+  incRate: number; // 核增率
+  decRate: number; // 核减率
+}
+
 export enum ShowBusinessType {
   ALL_BUSINESS = 'allBusiness', // 全部业务
   MY_CREATE_BUSINESS = 'myCreateBusiness', // 我创建的业务
   MY_PARTICIPATE_BUSINESS = 'myParticipateBusiness', // 我参与的业务
   MY_COLLABORATE_BUSINESS = 'myCollaborateBusiness', // 我协审的业务
 }
+
+// 业务金额字段枚举
+export enum BusinessFee {
+  // 送审金额、原报金额
+  ORIGINAL = 'orgFee',
+  // 审结金额
+  CONCLUSION = 'conclusionFee',
+  // 审增金额
+  INC = 'incFee',
+  // 审减金额
+  DEC = 'decFee',
+  // 动态金额(当前最新金额)
+  DYNAMIC = 'dynamicFee',
+  // 预留金
+  PROVISIONAL = 'provisionalFee',
+}
+
+export interface testAutoBuild {
+  a: string;
+}

+ 2 - 0
types/src/interface/index.ts

@@ -42,3 +42,5 @@ export * from './area';
 export * from './processLog';
 export * from './generalSetting';
 export * from './resultDocument';
+export * from './budgetCheck';
+export * from './uploadMsg'

+ 2 - 1
types/src/interface/platformSwitch.ts

@@ -5,5 +5,6 @@ export interface IPlatformSwitch {// 项目功能开关
     fileFormat: string;// 文件格式
     uploadNumber: number;// 上传数量
     uploadSize: number;// 上传大小
-    cadView: boolean
+    cadView: boolean // cad预览开关
+    copy: boolean  // 拷贝文件开关
 }

+ 4 - 4
types/src/interface/process.ts

@@ -123,6 +123,7 @@ export interface IProcess {
   time?: number; // 当前环节完成时间(仅当审批通过或审批退回时会有时间)
   participantInfo: IParticipantInfo;
   afterAuditMoney?: number; // 审后的金额
+  referenceID?: string; // 流程引用的templateID添加
 }
 
 export interface Members {
@@ -305,10 +306,8 @@ export interface IReturnInfo {
 }
 
 export interface IReturnProcessInfo {
-  returnProcessID?: string;
-  returnProcessReferenceID?: string;
-  nextProcessID?: string;
-  nextProcessReferenceID: string;
+  nextProcessReferenceID?: string;
+  rule?: 'skip' | 'restart';
 }
 
 // 3合1步骤中的一个环节
@@ -377,6 +376,7 @@ export interface IApproval {
   subjectID?: string;
   businessType?: BusinessTypeKey;
   matterListID?: string;
+  institutionID?: string;
 }
 
 export enum ApprovalStatus {

+ 1 - 0
types/src/interface/processLog.ts

@@ -20,6 +20,7 @@ export enum OperateType {
   IMPORT = '导入',
   OPEN = '打开',
   APOSTILLE = '加签',
+  COPY = "拷贝"
 }
 export interface IModifyUser {
   ID: string;

+ 5 - 0
types/src/interface/uploadMsg.ts

@@ -0,0 +1,5 @@
+export interface UploadMsg {
+    accept: string;
+    limit: number;
+    size: number;
+}

+ 2 - 0
types/src/interface/user.ts

@@ -115,6 +115,8 @@ export interface IAPUser {
   lastTryLoginTime?: number; // 上次尝试登陆的时间
   passwordModifyTime?: number; // 密码修改时间
   phrases: string[]; // 常用语
+  idCode: String, // 身份证号码
+  isIdAuth: Boolean, // 身份证是否经过实名认证
 }
 
 // 最近联系人

+ 1 - 1
wise-cost-util/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@sc/wise-cost-util",
-  "version": "1.1.9",
+  "version": "1.1.11",
   "description": "wise-cost项目前后端业务通用工具包",
   "main": "./dist/index.cjs.js",
   "module": "./dist/index.esm.js",