Переглянути джерело

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

zhangweicheng 4 роки тому
батько
коміт
e4889fc881

Різницю між файлами не показано, бо вона завелика
+ 0 - 3652
report/package-lock.json


+ 1 - 1
report/package.json

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

+ 262 - 0
report/src/core/formulasDataSetter.ts

@@ -0,0 +1,262 @@
+import { Fields, ICurrent_RPT, IDataObj, IGroupField, IParam } from "../index";
+import { IParams } from "../interface/basic";
+import { IDataObjProps } from '../interface/enum';
+
+let FData: Record<string, IGroupField> = {};
+let PData: Record<string, IParam> = {};
+let DData: Record<string, any> = {};
+let rpt = <ICurrent_RPT>{};
+let orgData = <IDataObj>{};
+
+const setupData = ($CURRENT_RPT: ICurrent_RPT, $CURRENT_DATA: IDataObj) => {
+    rpt = $CURRENT_RPT;
+    orgData = $CURRENT_DATA;
+}
+const resetData = () => {
+    DData = {};
+    FData = {};
+    PData = {};
+}
+const getFieldValueArray = (field: IGroupField) => {
+    let rst: any;
+    if (field.DataNodeName === 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 = IDataObjProps.discrete_data;
+            // field.DataSeq = dataObj[IDataObjProps.discrete_data];
+            orgData[IDataObjProps.discrete_data].push([]);
+        }
+        rst = orgData[field.DataNodeName][field.DataSeq];
+    }
+    if (rst === null || rst === undefined) rst = [];
+    return rst;
+}
+
+//获取一般指标的指标对象($CURRENT_RPT.fields中的对象)
+const F = (fieldID: number) => {
+    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: number) => {
+    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]
+                return rpt.params[field];
+            }
+        }
+    }
+    return false;
+}
+
+// 获取数据,只有一个参数时获取该指标所有数据(数组),两个参数时获取该指标中的第N个数据(值)
+const D = (fieldID: number, valIndex?: number, newValue?: any) => {
+    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) {
+                    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 {
+            F(fieldID);
+            if (DData[fieldID]) {
+                return DData[fieldID];
+            } else {
+                console.log(`无ID为${fieldID}的指标,请检查`)
+                return []
+            }
+        }
+    }
+}
+
+//获取相应指标的数据长度
+const L = (arg: any) => {
+    if(arg in 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: IGroupField, valIdx: number, newValue: any) => {
+    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 = IDataObjProps.discrete_data;
+        field.DataSeq = orgData[IDataObjProps.discrete_data].length;
+        orgData[IDataObjProps.discrete_data].push([]);
+        orgData[field.DataNodeName][field.DataSeq][valIdx] = newValue;
+    } else {
+        orgData[field.DataNodeName][field.DataSeq][valIdx] = newValue;
+    }
+}
+//反向设置原始数据
+const setFieldValueArray = (field: IGroupField, newArr: any[]) => {
+    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 = IDataObjProps.discrete_data;
+                field.DataSeq = orgData[IDataObjProps.discrete_data].length;
+                orgData[IDataObjProps.discrete_data].push([]);
+            }
+            orgData[field.DataNodeName][field.DataSeq] = newArr;
+        }
+    }
+}
+//反向设置原始数据
+const setFieldDefaultValue = (fieldID: number, newValue: any) => {
+    rpt.params[`ID_${fieldID}`].Default_Value = newValue;
+}
+
+
+//该函数为共用方法,参数有两套组合:
+// (指标id,更改后的数组)
+// (指标id,需要更改的index,.需要更改的值)
+const setData = (fieldID: number, arg1: number[] | number, arg2?: number | string) => {
+    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 (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);
+    }
+}
+//把数组每个元素都转换成数字
+const getNumberArray=(data:string[]|undefined[]|[]|number[])=>{
+    const rst:number[]=[];
+    for(const item of data){
+        if(isNaN(Number(item))){
+            rst.push(0);
+        }else{
+            rst.push(Number(item));
+        }
+        
+    }
+    return rst;
+}
+
+
+const removeFieldValue = (fieldID: number, valIdx: number) => {
+    if (!DData[fieldID]) {
+        F(fieldID);
+    }
+    DData[fieldID].splice(valIdx, 1);
+}
+
+const insertFieldValue = (fieldID: number, valIdx: number, newValue: number) => {
+    if (!DData[fieldID]) {
+        F(fieldID);
+    }
+    DData[fieldID].splice(valIdx, 0, newValue);
+}
+
+export default {
+    setupData,
+    P,
+    F,
+    D,
+    getCurrentPage,
+    getTotalPage,
+    L,
+    setFieldValue,
+    setFieldValueArray,
+    removeFieldValue,
+    insertFieldValue, 
+    setData, 
+    resetData,
+    getNumberArray
+}
+
+

+ 37 - 6
report/src/core/jpc_ex.ts

@@ -14,10 +14,13 @@ import JpcData from './jpc_data';
 import JpcCommonHelper from './helper/jpc_helper_common';
 import JpcCommonHelper from './helper/jpc_helper_common';
 import useReportDate from '../public/ReportDate'
 import useReportDate from '../public/ReportDate'
 
 
-import { IDefProperties, IFormula, IParams, ICurrent_RPT, ICurrent_DATA, ICustomizeCfg, ITargetFields, IRptTpl, IDataObj, IBands, IControlCollection, IStyles, BorderStyle, IFontSubCollection, IControlSubCollection, IPreviewPage, IRstPage, IMergeBand } from '../interface/basic'
+import { IDefProperties, IFormula, IParams, ICurrent_RPT, ICustomizeCfg, ITargetFields, IRptTpl, IDataObj, IBands, IControlCollection, IStyles, BorderStyle, IFontSubCollection, IControlSubCollection, IRstPage, IMergeBand } from '../interface/basic'
 import { IFlowTabClass, IBillTabClass, ICostTabClass } from '../interface/classType';
 import { IFlowTabClass, IBillTabClass, ICostTabClass } from '../interface/classType';
-import { IControlProps, IFontProps, IPagingOption, IPositionProps } from '../interface/enum';
+import {  IPagingOption } from '../interface/enum';
 import { Key } from 'readline';
 import { Key } from 'readline';
+import formulasDataSetter from './formulasDataSetter'
+import stringUtil from '../public/stringUtil'
+
 const JV=$JV;
 const JV=$JV;
 class JpcExClass {
 class JpcExClass {
     flowTab!: IFlowTabClass;
     flowTab!: IFlowTabClass;
@@ -124,8 +127,34 @@ class JpcExClass {
     //根据步骤,对formulas中的计算式进行处理,并赋值到相应属性中
     //根据步骤,对formulas中的计算式进行处理,并赋值到相应属性中
     executeFormulas(runType: string, $CURRENT_TEMPLATE: IRptTpl, $CURRENT_DATA: IDataObj, $CURRENT_RPT: ICurrent_RPT) {
     executeFormulas(runType: string, $CURRENT_TEMPLATE: IRptTpl, $CURRENT_DATA: IDataObj, $CURRENT_RPT: ICurrent_RPT) {
         let execFmlMe = this;
         let execFmlMe = this;
+        formulasDataSetter.setupData($CURRENT_RPT, $CURRENT_DATA);
+        const {
+            P,
+            F,
+            D,
+            L,
+            getCurrentPage, 
+            getTotalPage,
+            setFieldValue,
+            setFieldValueArray,
+            removeFieldValue,
+            insertFieldValue,
+            setData,
+            getNumberArray
+        } = formulasDataSetter;
+        const {
+            isEmptyString,
+            trim,
+            leftTrim,
+            rightTrim,
+            replaceAll,
+            comdify,
+            convertToCaptionNum,
+            convertStrToBoolean,
+            formatNumber,
+        } = stringUtil;
+        
         for (let execFmlIdx = 0; execFmlIdx < execFmlMe.formulas.length; execFmlIdx++) {
         for (let execFmlIdx = 0; execFmlIdx < execFmlMe.formulas.length; execFmlIdx++) {
-            //remark: 搞这么复杂的变量名是为了防止与表达式起冲突(如循环变量i,j,k,容易造成变量冲突且不容易看出问题)
             if (execFmlMe.formulas[execFmlIdx].run_type === runType) {
             if (execFmlMe.formulas[execFmlIdx].run_type === runType) {
                 let expression = execFmlMe.formulas[execFmlIdx].expression;
                 let expression = execFmlMe.formulas[execFmlIdx].expression;
                 if (expression) {
                 if (expression) {
@@ -133,8 +162,8 @@ class JpcExClass {
                     let $ME = execFmlMe.formulas[execFmlIdx];
                     let $ME = execFmlMe.formulas[execFmlIdx];
                     // console.log("current expression idx: " + execFmlIdx);
                     // console.log("current expression idx: " + execFmlIdx);
                     // console.log(expression);
                     // console.log(expression);
-
                     try {
                     try {
+                        const {format}=$ME;
                         const $JE = JE;
                         const $JE = JE;
                         const ReportDate = useReportDate;
                         const ReportDate = useReportDate;
                         console.log(expression);
                         console.log(expression);
@@ -142,8 +171,9 @@ class JpcExClass {
                         if (expression.indexOf('Date()') > -1) {
                         if (expression.indexOf('Date()') > -1) {
                             eval(expression.replace('Date()', 'ReportDate()'));
                             eval(expression.replace('Date()', 'ReportDate()'));
                         } else {
                         } else {
-                            eval(expression);
-                        }
+                            
+                            eval(expression);}
+                       
 
 
                     } catch (ex) {
                     } catch (ex) {
                         console.log(ex);
                         console.log(ex);
@@ -151,6 +181,7 @@ class JpcExClass {
                 }
                 }
             }
             }
         }
         }
+        formulasDataSetter.resetData();
     };
     };
 
 
     outputAsPreviewPage(rptTpl: IRptTpl, defProperties: IDefProperties) {
     outputAsPreviewPage(rptTpl: IRptTpl, defProperties: IDefProperties) {

+ 1 - 0
report/src/interface/basic.ts

@@ -211,6 +211,7 @@ export interface ITargetFields {
     从数据指标_拓展集合: ITargetDataSet;
     从数据指标_拓展集合: ITargetDataSet;
     离散指标_集合: ITargetDataSet;
     离散指标_集合: ITargetDataSet;
     无映射离散指标_集合: ITargetDataSet;
     无映射离散指标_集合: ITargetDataSet;
+    [key:string]:ITargetDataSet;
 }
 }
 
 
 interface IOutputAsPreviewPage {
 interface IOutputAsPreviewPage {

+ 1 - 0
report/src/interface/enum.ts

@@ -5,6 +5,7 @@ export enum IDataObjProps {
     discrete_data = 'discrete_data',    // 离散指标_集合
     discrete_data = 'discrete_data',    // 离散指标_集合
     master_data = 'master_data',        //主数据指标_集合
     master_data = 'master_data',        //主数据指标_集合
     master_data_ex = 'master_data_ex',  //主数据指标_拓展集合
     master_data_ex = 'master_data_ex',  //主数据指标_拓展集合
+    NA='NA'
 }
 }
 
 
 export enum IEventType {
 export enum IEventType {

+ 215 - 0
report/src/public/old_scMathUtil.ts

@@ -0,0 +1,215 @@
+/**
+ * Created by Tony on 2017/4/14.
+ */
+'use strict';
+
+export default {
+    innerRoundTo: function(num: number, digit: number){
+        let lFactor = Math.pow(10, digit);
+        let fOffSet = 0.5;
+        let sign = '';
+        // 处理符号
+        if (num < 0){
+            sign = '-';
+            num = Math.abs(num);
+        }
+        // 计算
+        let result = Math.floor((num / lFactor) + fOffSet).toString();
+        let iLength = result.length;
+        // 因为数值被转为整数计算,当目标位数在小数点后,且数值小于0,需要补齐前面的位数
+        if (iLength < -digit){
+            result = this.zeroString(-digit) + result;
+        }
+        // 当目标位数在小数点前,需要补齐后面的位数
+        else if ((digit > 0) && (iLength < digit)){
+            result = result + this.zeroString(digit);
+        }
+        iLength = result.length;
+        // 获得小数点前的数字
+        let r1 = result.substring(0, iLength + digit);
+        // 获得小数点后的数字
+        let r2 = result.substring(iLength + digit, iLength);
+        // 拼出完整结果
+        return Number(sign + r1 + '.' + r2);
+    },
+    // 原来直接用num.toString(2),如果小数段最后位数是0,会被舍掉,导致进位计算bug
+    // 改为自己计算二进制,固定为53位。
+    // 经验证速度没有差别
+    // 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
+    floatToBin: function(num: number): string {
+        let sign = '';
+        let dNum = num;
+        // 符号位
+        if (num < 0) {
+            sign = '-';
+            dNum = -num;
+        };
+        // 解析整数段
+        let iNum = Math.floor(dNum);
+        let iFactor;
+        let sResult1 = '';
+        // 计算二进制整数段
+        while (iNum > 0){
+            iFactor = iNum % 2;
+            iNum = Math.floor(iNum / 2);
+            sResult1 = iFactor + sResult1;
+        }
+        // 判断是否有整数段
+        let bIntZero = sResult1 === '';
+        if (bIntZero){
+            sResult1 = '0';
+        }
+        // 解析小数段
+        let fNum = dNum - Math.floor(dNum);
+        let sResult2 = '';
+        if (fNum > 0){
+            // 双精度浮点数,尾数总长52位,因为第一位总是1,存储时已经被隐藏,所以有效位数为53位
+            // 由于js未对浮点数做优化,所以在有运算的情况下,误差会被放大,因此放弃一位有效位数来消除误差,二进制有效位数50位,十进制有效位数15位
+            const floatLength = 50;
+
+            let iLength;
+            // js的bug,浮点数直接取小数可能不能获得精确值,只有转成字符串,截取字符串中的小数段
+            let sNum = dNum.toString(10);
+            let iDot = sNum.indexOf('.');
+            sNum = '0' + sNum.substring(iDot, sNum.length);
+            fNum = Number(sNum);
+            // 有整数段,则小数位数为全部位数-整数位数
+            if (!bIntZero){
+                iLength = floatLength - sResult1.length;
+            }
+            else{
+                iLength = floatLength;
+            }
+            // 计算二进制小数段
+            while (iLength > 0){
+                fNum = fNum * 2;
+                iFactor = Math.floor(fNum);
+                fNum = fNum % 1;
+                sResult2 = sResult2 + iFactor;
+                if (iFactor > 0){
+                    bIntZero = false;
+                }
+                if (bIntZero && (iFactor === 0)){
+                    continue;
+                }
+                iLength--;
+            }
+        }
+        return sign + sResult1 + '.' + sResult2;
+    },
+    binToFloat: function(bin: string): string {
+        let result = 0;
+        let iLength = bin.length;
+        let sign = '';
+        if (iLength > 0 && bin[0]==='-'){
+            sign = '-';
+            bin = bin.substring(1, iLength);
+        }
+        iLength = bin.length;
+        let iDot = bin.indexOf('.');
+        if (iDot >= 0) {
+            for (let i = 0; i < iLength; i++) {
+                let num = Number(bin[i]);
+                let idx = iDot - i;
+                if (idx === 0) {
+                    continue
+                };
+                if (idx > 0) {
+                    idx -= 1
+                };
+                let r = Math.pow(2, idx);
+                result += num * r;
+            }
+        }
+        else {
+            result = parseInt(bin, 2);
+        };
+        return sign + result;
+    },
+    zeroString: function(length: number){
+        let result = '';
+        for (let i = 0; i < length; i++){
+            result = result + '0';
+        };
+        return result;
+    },
+    incMantissa: function(bin: string): string {
+        let result = bin;
+        const me = this;
+        let iDot = bin.indexOf('.');
+        if (iDot < 0) {
+            return result
+        };
+        let iLength = bin.length;
+        iLength = bin.length;
+        for (let i = iLength - 1; i > iDot; i--){
+            let num = Number(bin[i]);
+            if (num === 0){
+                num = 1;
+                let bin1 = bin.substring(0, i);
+                let bin2 = me.zeroString(iLength - (i + 1));//bin.substring(i + 1, iLength);
+                result = bin1 + num.toString() + bin2;
+                break;
+            }
+
+        };
+        return result;
+    },
+
+    roundTo: function(num: number, digit: number) {
+        let me = this;
+        // let str1 = me.floatToBin(num);
+        // let str2 = me.incMantissa(str1);
+        // return me.innerRoundTo( parseFloat(me.binToFloat(str2)), digit);
+        return me.innerRoundTo( parseFloat(me.binToFloat( me.incMantissa( me.floatToBin(num)))), digit);
+    },
+    isNumber : function (obj: any) {
+        return obj === +obj;
+    },
+    roundForObj:function(obj: any, decimal: number) {
+        let me = this;
+        let value;
+        if(me.isNumber(obj)){
+            value = me.roundTo(obj,-decimal)
+        }else {
+            value = me.roundTo(Number(obj),-decimal);
+        }
+        return value
+    },
+    roundToString:function(obj: any, decimal: number){
+        let me = this;
+        let value;
+        if(me.isNumber(obj)){
+            value = me.roundTo(obj,-decimal)
+        }else {
+            value = me.roundTo(Number(obj),-decimal);
+        }
+        return value.toFixed(decimal);
+    },
+    // isNumOrFormula:function (text: any) {
+    //     let value = Number(text);
+    //     if(value ==0 ) return value;
+    //     if (!value) {
+    //         try {
+    //             let exp = new Expression('');
+    //             exp.Expression(text);
+    //             value = Number(exp.Evaluate());
+    //         } catch (error) {
+    //             value = 0;
+    //         }
+    //     }
+    //     if(text == null || text == ''){
+    //         value = 0;
+    //     }
+    //     return value;
+    // },
+    isDef:function (v: any) {
+        return v !== undefined && v !== null;
+    },
+    //获取ID引用
+    getFIDArr: function (exp: any) {
+        let fidRex = /@[\d,a-z,A-Z,-]{36}/g;
+        let fidArr = exp.match(fidRex);
+        return this.isDef(fidArr) ? fidArr : [];
+    }
+};

+ 137 - 0
report/src/public/old_stringUtil.ts

@@ -0,0 +1,137 @@
+'use strict';
+
+export default {
+    isEmptyString: function(str: string) {
+        let rst = false;
+        if (str === null || str === undefined) {
+            rst = true;
+        } else if (typeof str) {
+            let reg = /^\s*$/;
+            rst = reg.test(str);
+        }
+        return rst;
+    },
+    trim: function(str: string) {
+        return str.replace(/(^\s*)|(\s*$)/g, "");
+    },
+    leftTrim: function(str: string) {
+        return str.replace(/(^\s*)/g,"");
+    },
+    rightTrim: function(str: string) {
+        return str.replace(/(\s*$)/g,"");
+    },
+    replaceAll: function (targetStr: string, FindText: string, RepText: string) {
+        let regExp = new RegExp(FindText, "gm");
+        return targetStr.replace(regExp, RepText);
+    },
+    comdify: function(numStr: string){
+        let re = /\d{1,3}(?=(\d{3})+$)/g;
+        return numStr.replace(/^(\d+)((\.\d+)?)$/,function(s,s1,s2){return s1.replace(re,"$&,")+s2;});
+    },
+    convertToCaptionNum: function(num: any, isCurrency: boolean, isTraditionalCap: boolean) {
+        let me = this, rst = "";
+        if (/^\d*(\.\d*)?$/.test(num)) {
+            let capChars, unitChars;
+            if (isTraditionalCap) {
+                capChars = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
+                unitChars = ["" , "拾", "佰", "仟", "萬", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万"];
+            } else {
+                capChars = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
+                unitChars = ["" , "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千", "万"];
+            }
+
+            let numSplitArr = ("" + num).replace(/(^0*)/g, "").split(".");
+            if (numSplitArr[0] === "") numSplitArr[0] = "0";
+            let len = numSplitArr[0].length;
+            let intPartArr = [];
+            if (len <= 13) {
+                for (let idx = 0; idx < len; idx++) {
+                    intPartArr.push(capChars[ parseInt(numSplitArr[0].charAt(idx) )] + unitChars[len - idx - 1]);
+                }
+                rst = intPartArr.join('');
+                rst = me.replaceAll(rst, capChars[0] + unitChars[3], capChars[0]); //零千 -> 零
+                rst = me.replaceAll(rst, capChars[0] + unitChars[2], capChars[0]); //零百 -> 零
+                rst = me.replaceAll(rst, capChars[0] + unitChars[1], capChars[0]); //零十 -> 零
+                //
+                rst = me.replaceAll(me.replaceAll(rst, "零零", "零"), "零零", "零");
+                rst = me.replaceAll(rst, capChars[0] + unitChars[8], unitChars[8]); //零亿 -> 亿
+                rst = me.replaceAll(rst, capChars[0] + unitChars[4], unitChars[4]); //零万 -> 万
+                //
+                rst = me.replaceAll(rst, unitChars[8] + unitChars[4], unitChars[8] + capChars[0]); //亿万 -> 亿零
+                if (num === 0) {
+                    rst = "零";
+                } else if (rst.length > 1 && rst.charAt(rst.length - 1) === '零') {
+                    rst = rst.slice(0, rst.length - 1);
+                }
+                //小数部分处理
+                if (numSplitArr.length > 1) {
+                    len = numSplitArr[1].length;
+                    if (parseInt(numSplitArr[1]) === 0) {
+                        rst = rst + (isCurrency?"元整":"");
+                    } else {
+                        if (isCurrency && len > 2) len = 2;
+                        let fractionStr = [];
+                        for (let idx = 0; idx < len; idx++) {
+                            fractionStr.push(capChars[ parseInt(numSplitArr[1].charAt(idx))]+ (isCurrency?((idx === 0)?"角":"分"):""));
+                        }
+                        rst = rst + (isCurrency?"元":"点") + fractionStr.join("");
+                    }
+                } else {
+                    rst = rst + (isCurrency?"元整":"");
+                }
+            } else {
+                rst = "Number is too big!";
+            }
+        } else {
+            rst = "Number is wrong!";
+        }
+        return rst;
+    },
+    convertStrToBoolean: function(str: string) {
+        let rst = false, me = this;
+        if (!me.isEmptyString(str)) {
+            let upperStr = str.toUpperCase();
+            if (upperStr === 'T' || upperStr === 'Y' || upperStr === 'YES' || upperStr === 'TRUE') {
+                rst = true;
+            }
+        }
+        return rst;
+    },
+    formatNumber: function(formatStr: string, val: any) {
+        let rst = val;
+        if (formatStr) {
+            if (!(isNaN(parseFloat(val)))) {
+                let dotIdx = formatStr.indexOf(".");
+                if (dotIdx >= 0) {
+                    let tmpStr = parseFloat(val).toFixed(formatStr.length - dotIdx - 1);
+                    let digStr = formatStr.substr(dotIdx + 1, formatStr.length - dotIdx);
+                    for (let sIdx = digStr.length - 1; sIdx >= 0; sIdx--) {
+                        if (digStr[sIdx] === '#') {
+                            if (tmpStr.length > 0 && tmpStr[tmpStr.length - 1] === '0') {
+                                tmpStr = tmpStr.substr(0, tmpStr.length - 1);
+                            } else {
+                                break;
+                            }
+                        } else {
+                            break;
+                        }
+                    }
+                    if (tmpStr[tmpStr.length - 1] === '.') tmpStr = tmpStr.substr(0, tmpStr.length - 1);
+                    rst = tmpStr;
+                } else {
+                    rst = parseFloat(val).toFixed(0);
+                }
+                let commaIdx = formatStr.indexOf(",");
+                if (commaIdx >= 0) {
+                    rst = comdify(val.toString());
+                }
+            }
+        }
+        return rst;
+    },
+}
+
+function comdify(numStr: string){
+    let re = /\d{1,3}(?=(\d{3})+$)/g;
+    return numStr.replace(/^(\d+)((\.\d+)?)$/, function(s,s1,s2){return s1.replace(re,"$&,")+s2;});
+}

+ 211 - 201
report/src/public/scMathUtil.ts

@@ -1,215 +1,225 @@
 /**
 /**
  * Created by Tony on 2017/4/14.
  * Created by Tony on 2017/4/14.
  */
  */
-'use strict';
+const zeroString = (length: number) => {
+    let result = '';
+    for (let i = 0; i < length; i++) {
+        result = result + '0';
+    };
+    return result;
+}
 
 
-export default {
-    innerRoundTo: function(num: number, digit: number){
-        let lFactor = Math.pow(10, digit);
-        let fOffSet = 0.5;
-        let sign = '';
-        // 处理符号
-        if (num < 0){
-            sign = '-';
-            num = Math.abs(num);
-        }
-        // 计算
-        let result = Math.floor((num / lFactor) + fOffSet).toString();
-        let iLength = result.length;
-        // 因为数值被转为整数计算,当目标位数在小数点后,且数值小于0,需要补齐前面的位数
-        if (iLength < -digit){
-            result = this.zeroString(-digit) + result;
-        }
-        // 当目标位数在小数点前,需要补齐后面的位数
-        else if ((digit > 0) && (iLength < digit)){
-            result = result + this.zeroString(digit);
-        }
-        iLength = result.length;
-        // 获得小数点前的数字
-        let r1 = result.substring(0, iLength + digit);
-        // 获得小数点后的数字
-        let r2 = result.substring(iLength + digit, iLength);
-        // 拼出完整结果
-        return Number(sign + r1 + '.' + r2);
-    },
-    // 原来直接用num.toString(2),如果小数段最后位数是0,会被舍掉,导致进位计算bug
-    // 改为自己计算二进制,固定为53位。
-    // 经验证速度没有差别
-    // 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
-    floatToBin: function(num: number): string {
-        let sign = '';
-        let dNum = num;
-        // 符号位
-        if (num < 0) {
-            sign = '-';
-            dNum = -num;
-        };
-        // 解析整数段
-        let iNum = Math.floor(dNum);
-        let iFactor;
-        let sResult1 = '';
-        // 计算二进制整数段
-        while (iNum > 0){
-            iFactor = iNum % 2;
-            iNum = Math.floor(iNum / 2);
-            sResult1 = iFactor + sResult1;
+const innerRoundTo = (num: number, digit: number) => {
+    let lFactor = Math.pow(10, digit);
+    let fOffSet = 0.5;
+    let sign = '';
+    // 处理符号
+    if (num < 0) {
+        sign = '-';
+        num = Math.abs(num);
+    }
+    // 计算
+    let result = Math.floor((num / lFactor) + fOffSet).toString();
+    let iLength = result.length;
+    // 因为数值被转为整数计算,当目标位数在小数点后,且数值小于0,需要补齐前面的位数
+    if (iLength < -digit) {
+        result = zeroString(-digit) + result;
+    }
+    // 当目标位数在小数点前,需要补齐后面的位数
+    else if ((digit > 0) && (iLength < digit)) {
+        result = result + zeroString(digit);
+    }
+    iLength = result.length;
+    // 获得小数点前的数字
+    let r1 = result.substring(0, iLength + digit);
+    // 获得小数点后的数字
+    let r2 = result.substring(iLength + digit, iLength);
+    // 拼出完整结果
+    return Number(sign + r1 + '.' + r2);
+}
+// 原来直接用num.toString(2),如果小数段最后位数是0,会被舍掉,导致进位计算bug
+// 改为自己计算二进制,固定为53位。
+// 经验证速度没有差别
+// 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
+const floatToBin = (num: number): string => {
+    let sign = '';
+    let dNum = num;
+    // 符号位
+    if (num < 0) {
+        sign = '-';
+        dNum = -num;
+    };
+    // 解析整数段
+    let iNum = Math.floor(dNum);
+    let iFactor;
+    let sResult1 = '';
+    // 计算二进制整数段
+    while (iNum > 0) {
+        iFactor = iNum % 2;
+        iNum = Math.floor(iNum / 2);
+        sResult1 = iFactor + sResult1;
+    }
+    // 判断是否有整数段
+    let bIntZero = sResult1 === '';
+    if (bIntZero) {
+        sResult1 = '0';
+    }
+    // 解析小数段
+    let fNum = dNum - Math.floor(dNum);
+    let sResult2 = '';
+    if (fNum > 0) {
+        // 双精度浮点数,尾数总长52位,因为第一位总是1,存储时已经被隐藏,所以有效位数为53位
+        // 由于js未对浮点数做优化,所以在有运算的情况下,误差会被放大,因此放弃一位有效位数来消除误差,二进制有效位数50位,十进制有效位数15位
+        const floatLength = 50;
+
+        let iLength;
+        // js的bug,浮点数直接取小数可能不能获得精确值,只有转成字符串,截取字符串中的小数段
+        let sNum = dNum.toString(10);
+        let iDot = sNum.indexOf('.');
+        sNum = '0' + sNum.substring(iDot, sNum.length);
+        fNum = Number(sNum);
+        // 有整数段,则小数位数为全部位数-整数位数
+        if (!bIntZero) {
+            iLength = floatLength - sResult1.length;
         }
         }
-        // 判断是否有整数段
-        let bIntZero = sResult1 === '';
-        if (bIntZero){
-            sResult1 = '0';
+        else {
+            iLength = floatLength;
         }
         }
-        // 解析小数段
-        let fNum = dNum - Math.floor(dNum);
-        let sResult2 = '';
-        if (fNum > 0){
-            // 双精度浮点数,尾数总长52位,因为第一位总是1,存储时已经被隐藏,所以有效位数为53位
-            // 由于js未对浮点数做优化,所以在有运算的情况下,误差会被放大,因此放弃一位有效位数来消除误差,二进制有效位数50位,十进制有效位数15位
-            const floatLength = 50;
-
-            let iLength;
-            // js的bug,浮点数直接取小数可能不能获得精确值,只有转成字符串,截取字符串中的小数段
-            let sNum = dNum.toString(10);
-            let iDot = sNum.indexOf('.');
-            sNum = '0' + sNum.substring(iDot, sNum.length);
-            fNum = Number(sNum);
-            // 有整数段,则小数位数为全部位数-整数位数
-            if (!bIntZero){
-                iLength = floatLength - sResult1.length;
+        // 计算二进制小数段
+        while (iLength > 0) {
+            fNum = fNum * 2;
+            iFactor = Math.floor(fNum);
+            fNum = fNum % 1;
+            sResult2 = sResult2 + iFactor;
+            if (iFactor > 0) {
+                bIntZero = false;
             }
             }
-            else{
-                iLength = floatLength;
-            }
-            // 计算二进制小数段
-            while (iLength > 0){
-                fNum = fNum * 2;
-                iFactor = Math.floor(fNum);
-                fNum = fNum % 1;
-                sResult2 = sResult2 + iFactor;
-                if (iFactor > 0){
-                    bIntZero = false;
-                }
-                if (bIntZero && (iFactor === 0)){
-                    continue;
-                }
-                iLength--;
+            if (bIntZero && (iFactor === 0)) {
+                continue;
             }
             }
+            iLength--;
         }
         }
-        return sign + sResult1 + '.' + sResult2;
-    },
-    binToFloat: function(bin: string): string {
-        let result = 0;
-        let iLength = bin.length;
-        let sign = '';
-        if (iLength > 0 && bin[0]==='-'){
-            sign = '-';
-            bin = bin.substring(1, iLength);
+    }
+    return sign + sResult1 + '.' + sResult2;
+}
+const binToFloat = (bin: string): string => {
+    let result = 0;
+    let iLength = bin.length;
+    let sign = '';
+    if (iLength > 0 && bin[0] === '-') {
+        sign = '-';
+        bin = bin.substring(1, iLength);
+    }
+    iLength = bin.length;
+    let iDot = bin.indexOf('.');
+    if (iDot >= 0) {
+        for (let i = 0; i < iLength; i++) {
+            let num = Number(bin[i]);
+            let idx = iDot - i;
+            if (idx === 0) {
+                continue
+            };
+            if (idx > 0) {
+                idx -= 1
+            };
+            let r = Math.pow(2, idx);
+            result += num * r;
         }
         }
-        iLength = bin.length;
-        let iDot = bin.indexOf('.');
-        if (iDot >= 0) {
-            for (let i = 0; i < iLength; i++) {
-                let num = Number(bin[i]);
-                let idx = iDot - i;
-                if (idx === 0) {
-                    continue
-                };
-                if (idx > 0) {
-                    idx -= 1
-                };
-                let r = Math.pow(2, idx);
-                result += num * r;
-            }
+    }
+    else {
+        result = parseInt(bin, 2);
+    };
+    return sign + result;
+}
+
+const incMantissa = (bin: string): string => {
+    let result = bin;
+    let iDot = bin.indexOf('.');
+    if (iDot < 0) {
+        return result
+    };
+    let iLength = bin.length;
+    iLength = bin.length;
+    for (let i = iLength - 1; i > iDot; i--) {
+        let num = Number(bin[i]);
+        if (num === 0) {
+            num = 1;
+            let bin1 = bin.substring(0, i);
+            let bin2 = zeroString(iLength - (i + 1));//bin.substring(i + 1, iLength);
+            result = bin1 + num.toString() + bin2;
+            break;
         }
         }
-        else {
-            result = parseInt(bin, 2);
-        };
-        return sign + result;
-    },
-    zeroString: function(length: number){
-        let result = '';
-        for (let i = 0; i < length; i++){
-            result = result + '0';
-        };
-        return result;
-    },
-    incMantissa: function(bin: string): string {
-        let result = bin;
-        const me = this;
-        let iDot = bin.indexOf('.');
-        if (iDot < 0) {
-            return result
-        };
-        let iLength = bin.length;
-        iLength = bin.length;
-        for (let i = iLength - 1; i > iDot; i--){
-            let num = Number(bin[i]);
-            if (num === 0){
-                num = 1;
-                let bin1 = bin.substring(0, i);
-                let bin2 = me.zeroString(iLength - (i + 1));//bin.substring(i + 1, iLength);
-                result = bin1 + num.toString() + bin2;
-                break;
-            }
 
 
-        };
-        return result;
-    },
+    };
+    return result;
+}
 
 
-    roundTo: function(num: number, digit: number) {
-        let me = this;
-        // let str1 = me.floatToBin(num);
-        // let str2 = me.incMantissa(str1);
-        // return me.innerRoundTo( parseFloat(me.binToFloat(str2)), digit);
-        return me.innerRoundTo( parseFloat(me.binToFloat( me.incMantissa( me.floatToBin(num)))), digit);
-    },
-    isNumber : function (obj: any) {
-        return obj === +obj;
-    },
-    roundForObj:function(obj: any, decimal: number) {
-        let me = this;
-        let value;
-        if(me.isNumber(obj)){
-            value = me.roundTo(obj,-decimal)
-        }else {
-            value = me.roundTo(Number(obj),-decimal);
-        }
-        return value
-    },
-    roundToString:function(obj: any, decimal: number){
-        let me = this;
-        let value;
-        if(me.isNumber(obj)){
-            value = me.roundTo(obj,-decimal)
-        }else {
-            value = me.roundTo(Number(obj),-decimal);
-        }
-        return value.toFixed(decimal);
-    },
-    // isNumOrFormula:function (text: any) {
-    //     let value = Number(text);
-    //     if(value ==0 ) return value;
-    //     if (!value) {
-    //         try {
-    //             let exp = new Expression('');
-    //             exp.Expression(text);
-    //             value = Number(exp.Evaluate());
-    //         } catch (error) {
-    //             value = 0;
-    //         }
-    //     }
-    //     if(text == null || text == ''){
-    //         value = 0;
-    //     }
-    //     return value;
-    // },
-    isDef:function (v: any) {
-        return v !== undefined && v !== null;
-    },
-    //获取ID引用
-    getFIDArr: function (exp: any) {
-        let fidRex = /@[\d,a-z,A-Z,-]{36}/g;
-        let fidArr = exp.match(fidRex);
-        return this.isDef(fidArr) ? fidArr : [];
+const roundTo = (num: number, digit: number) => {
+
+    // let str1 = me.floatToBin(num);
+    // let str2 = me.incMantissa(str1);
+    // return me.innerRoundTo( parseFloat(me.binToFloat(str2)), digit);
+    return innerRoundTo(parseFloat(binToFloat(incMantissa(floatToBin(num)))), digit);
+}
+const isNumber = (obj: any) => {
+    return obj === +obj;
+}
+const roundForObj = (obj: any, decimal: number) => {
+
+    let value;
+    if (isNumber(obj)) {
+        value = roundTo(obj, -decimal)
+    } else {
+        value = roundTo(Number(obj), -decimal);
     }
     }
-};
+    return value
+}
+const roundToString = (obj: any, decimal: number) => {
+
+    let value;
+    if (isNumber(obj)) {
+        value = roundTo(obj, -decimal)
+    } else {
+        value = roundTo(Number(obj), -decimal);
+    }
+    return value.toFixed(decimal);
+}
+// isNumOrFormula:function (text: any) {
+//     let value = Number(text);
+//     if(value ==0 ) return value;
+//     if (!value) {
+//         try {
+//             let exp = new Expression('');
+//             exp.Expression(text);
+//             value = Number(exp.Evaluate());
+//         } catch (error) {
+//             value = 0;
+//         }
+//     }
+//     if(text == null || text == ''){
+//         value = 0;
+//     }
+//     return value;
+// },
+const isDef = (v: any) => {
+    return v !== undefined && v !== null;
+}
+//获取ID引用
+const getFIDArr = (exp: any) => {
+    let fidRex = /@[\d,a-z,A-Z,-]{36}/g;
+    let fidArr = exp.match(fidRex);
+    return isDef(fidArr) ? fidArr : [];
+}
+export default {
+    innerRoundTo,
+    floatToBin,
+    binToFloat,
+    incMantissa,
+    roundTo,
+    isNumber,
+    roundForObj,
+    roundToString,
+    isDef,
+    getFIDArr
+
+}

+ 123 - 118
report/src/public/stringUtil.ts

@@ -1,137 +1,142 @@
-'use strict';
 
 
-export default {
-    isEmptyString: function(str: string) {
-        let rst = false;
-        if (str === null || str === undefined) {
-            rst = true;
-        } else if (typeof str) {
-            let reg = /^\s*$/;
-            rst = reg.test(str);
+const isEmptyString = (str: string) => {
+    let rst = false;
+    if (str === null || str === undefined) {
+        rst = true;
+    } else if (typeof str) {
+        let reg = /^\s*$/;
+        rst = reg.test(str);
+    }
+    return rst;
+}
+const trim = (str: string) => {
+    return str.replace(/(^\s*)|(\s*$)/g, "");
+}
+const leftTrim = (str: string) => {
+    return str.replace(/(^\s*)/g, "");
+}
+const rightTrim = (str: string) => {
+    return str.replace(/(\s*$)/g, "");
+}
+const replaceAll = (targetStr: string, FindText: string, RepText: string) => {
+    let regExp = new RegExp(FindText, "gm");
+    return targetStr.replace(regExp, RepText);
+}
+const comdify = (numStr: string) => {
+    let re = /\d{1,3}(?=(\d{3})+$)/g;
+    return numStr.replace(/^(\d+)((\.\d+)?)$/, function (s, s1, s2) { return s1.replace(re, "$&,") + s2; });
+}
+const convertToCaptionNum = (num: any, isCurrency: boolean, isTraditionalCap: boolean) => {
+    let rst = "";
+    if (/^\d*(\.\d*)?$/.test(num)) {
+        let capChars, unitChars;
+        if (isTraditionalCap) {
+            capChars = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
+            unitChars = ["", "拾", "佰", "仟", "萬", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万"];
+        } else {
+            capChars = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
+            unitChars = ["", "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千", "万"];
         }
         }
-        return rst;
-    },
-    trim: function(str: string) {
-        return str.replace(/(^\s*)|(\s*$)/g, "");
-    },
-    leftTrim: function(str: string) {
-        return str.replace(/(^\s*)/g,"");
-    },
-    rightTrim: function(str: string) {
-        return str.replace(/(\s*$)/g,"");
-    },
-    replaceAll: function (targetStr: string, FindText: string, RepText: string) {
-        let regExp = new RegExp(FindText, "gm");
-        return targetStr.replace(regExp, RepText);
-    },
-    comdify: function(numStr: string){
-        let re = /\d{1,3}(?=(\d{3})+$)/g;
-        return numStr.replace(/^(\d+)((\.\d+)?)$/,function(s,s1,s2){return s1.replace(re,"$&,")+s2;});
-    },
-    convertToCaptionNum: function(num: any, isCurrency: boolean, isTraditionalCap: boolean) {
-        let me = this, rst = "";
-        if (/^\d*(\.\d*)?$/.test(num)) {
-            let capChars, unitChars;
-            if (isTraditionalCap) {
-                capChars = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
-                unitChars = ["" , "拾", "佰", "仟", "萬", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "万"];
-            } else {
-                capChars = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
-                unitChars = ["" , "十", "百", "千", "万", "十", "百", "千", "亿", "十", "百", "千", "万"];
-            }
 
 
-            let numSplitArr = ("" + num).replace(/(^0*)/g, "").split(".");
-            if (numSplitArr[0] === "") numSplitArr[0] = "0";
-            let len = numSplitArr[0].length;
-            let intPartArr = [];
-            if (len <= 13) {
-                for (let idx = 0; idx < len; idx++) {
-                    intPartArr.push(capChars[ parseInt(numSplitArr[0].charAt(idx) )] + unitChars[len - idx - 1]);
-                }
-                rst = intPartArr.join('');
-                rst = me.replaceAll(rst, capChars[0] + unitChars[3], capChars[0]); //零千 -> 零
-                rst = me.replaceAll(rst, capChars[0] + unitChars[2], capChars[0]); //零百 -> 零
-                rst = me.replaceAll(rst, capChars[0] + unitChars[1], capChars[0]); //零十 -> 零
-                //
-                rst = me.replaceAll(me.replaceAll(rst, "零零", "零"), "零零", "零");
-                rst = me.replaceAll(rst, capChars[0] + unitChars[8], unitChars[8]); //零亿 -> 亿
-                rst = me.replaceAll(rst, capChars[0] + unitChars[4], unitChars[4]); //零万 -> 万
-                //
-                rst = me.replaceAll(rst, unitChars[8] + unitChars[4], unitChars[8] + capChars[0]); //亿万 -> 亿零
-                if (num === 0) {
-                    rst = "零";
-                } else if (rst.length > 1 && rst.charAt(rst.length - 1) === '零') {
-                    rst = rst.slice(0, rst.length - 1);
-                }
-                //小数部分处理
-                if (numSplitArr.length > 1) {
-                    len = numSplitArr[1].length;
-                    if (parseInt(numSplitArr[1]) === 0) {
-                        rst = rst + (isCurrency?"元整":"");
-                    } else {
-                        if (isCurrency && len > 2) len = 2;
-                        let fractionStr = [];
-                        for (let idx = 0; idx < len; idx++) {
-                            fractionStr.push(capChars[ parseInt(numSplitArr[1].charAt(idx))]+ (isCurrency?((idx === 0)?"角":"分"):""));
-                        }
-                        rst = rst + (isCurrency?"元":"点") + fractionStr.join("");
-                    }
+        let numSplitArr = ("" + num).replace(/(^0*)/g, "").split(".");
+        if (numSplitArr[0] === "") numSplitArr[0] = "0";
+        let len = numSplitArr[0].length;
+        let intPartArr = [];
+        if (len <= 13) {
+            for (let idx = 0; idx < len; idx++) {
+                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(replaceAll(rst, "零零", "零"), "零零", "零");
+            rst = replaceAll(rst, capChars[0] + unitChars[8], unitChars[8]); //零亿 -> 亿
+            rst = replaceAll(rst, capChars[0] + unitChars[4], unitChars[4]); //零万 -> 万
+            //
+            rst = replaceAll(rst, unitChars[8] + unitChars[4], unitChars[8] + capChars[0]); //亿万 -> 亿零
+            if (num === 0) {
+                rst = "零";
+            } else if (rst.length > 1 && rst.charAt(rst.length - 1) === '零') {
+                rst = rst.slice(0, rst.length - 1);
+            }
+            //小数部分处理
+            if (numSplitArr.length > 1) {
+                len = numSplitArr[1].length;
+                if (parseInt(numSplitArr[1]) === 0) {
+                    rst = rst + (isCurrency ? "元整" : "");
                 } else {
                 } else {
-                    rst = rst + (isCurrency?"元整":"");
+                    if (isCurrency && len > 2) len = 2;
+                    let fractionStr = [];
+                    for (let idx = 0; idx < len; idx++) {
+                        fractionStr.push(capChars[parseInt(numSplitArr[1].charAt(idx))] + (isCurrency ? ((idx === 0) ? "角" : "分") : ""));
+                    }
+                    rst = rst + (isCurrency ? "元" : "点") + fractionStr.join("");
                 }
                 }
             } else {
             } else {
-                rst = "Number is too big!";
+                rst = rst + (isCurrency ? "元整" : "");
             }
             }
         } else {
         } else {
-            rst = "Number is wrong!";
+            rst = "Number is too big!";
         }
         }
-        return rst;
-    },
-    convertStrToBoolean: function(str: string) {
-        let rst = false, me = this;
-        if (!me.isEmptyString(str)) {
-            let upperStr = str.toUpperCase();
-            if (upperStr === 'T' || upperStr === 'Y' || upperStr === 'YES' || upperStr === 'TRUE') {
-                rst = true;
-            }
+    } else {
+        rst = "Number is wrong!";
+    }
+    return rst;
+}
+const convertStrToBoolean = (str: string) => {
+    let rst = false;
+    if (!isEmptyString(str)) {
+        let upperStr = str.toUpperCase();
+        if (upperStr === 'T' || upperStr === 'Y' || upperStr === 'YES' || upperStr === 'TRUE') {
+            rst = true;
         }
         }
-        return rst;
-    },
-    formatNumber: function(formatStr: string, val: any) {
-        let rst = val;
-        if (formatStr) {
-            if (!(isNaN(parseFloat(val)))) {
-                let dotIdx = formatStr.indexOf(".");
-                if (dotIdx >= 0) {
-                    let tmpStr = parseFloat(val).toFixed(formatStr.length - dotIdx - 1);
-                    let digStr = formatStr.substr(dotIdx + 1, formatStr.length - dotIdx);
-                    for (let sIdx = digStr.length - 1; sIdx >= 0; sIdx--) {
-                        if (digStr[sIdx] === '#') {
-                            if (tmpStr.length > 0 && tmpStr[tmpStr.length - 1] === '0') {
-                                tmpStr = tmpStr.substr(0, tmpStr.length - 1);
-                            } else {
-                                break;
-                            }
+    }
+    return rst;
+}
+const formatNumber = (formatStr: string, val: any) => {
+    let rst = val;
+    if (formatStr) {
+        if (!(isNaN(parseFloat(val)))) {
+            let dotIdx = formatStr.indexOf(".");
+            if (dotIdx >= 0) {
+                let tmpStr = parseFloat(val).toFixed(formatStr.length - dotIdx - 1);
+                let digStr = formatStr.substr(dotIdx + 1, formatStr.length - dotIdx);
+                for (let sIdx = digStr.length - 1; sIdx >= 0; sIdx--) {
+                    if (digStr[sIdx] === '#') {
+                        if (tmpStr.length > 0 && tmpStr[tmpStr.length - 1] === '0') {
+                            tmpStr = tmpStr.substr(0, tmpStr.length - 1);
                         } else {
                         } else {
                             break;
                             break;
                         }
                         }
+                    } else {
+                        break;
                     }
                     }
-                    if (tmpStr[tmpStr.length - 1] === '.') tmpStr = tmpStr.substr(0, tmpStr.length - 1);
-                    rst = tmpStr;
-                } else {
-                    rst = parseFloat(val).toFixed(0);
-                }
-                let commaIdx = formatStr.indexOf(",");
-                if (commaIdx >= 0) {
-                    rst = comdify(val.toString());
                 }
                 }
+                if (tmpStr[tmpStr.length - 1] === '.') tmpStr = tmpStr.substr(0, tmpStr.length - 1);
+                rst = tmpStr;
+            } else {
+                rst = parseFloat(val).toFixed(0);
+            }
+            let commaIdx = formatStr.indexOf(",");
+            if (commaIdx >= 0) {
+                rst = comdify(val.toString());
             }
             }
         }
         }
-        return rst;
-    },
+    }
+    return rst;
 }
 }
 
 
-function comdify(numStr: string){
-    let re = /\d{1,3}(?=(\d{3})+$)/g;
-    return numStr.replace(/^(\d+)((\.\d+)?)$/, function(s,s1,s2){return s1.replace(re,"$&,")+s2;});
-}
+
+export default {
+    isEmptyString,
+    trim,
+    leftTrim,
+    rightTrim,
+    replaceAll,
+    comdify,
+    convertToCaptionNum,
+    convertStrToBoolean,
+    formatNumber,
+}