/**
 * <p>
 *读取json文件中的json数据
 * </p>
 * @param sbsjMap中的key 传的是bbDm_version,例如：10101_001_10,value:报表填写数据（json）
 * @param checkType 表间校验和条件必填表校验区分标志，true：表间校验。false：必填表校验,2：通知
 * @param path :json文件外部路径
 * @param special_handle ：map结构，一个是企业所有的报表代码，一个是企业在本软件申报过的税种 sbgz 1是更正，2 是正常
 * @return 返回字符串是错误提示信息，返回数组：是校验信息；空数组：则这个bbDm_version没有校验信息
 * @throws
 * @author DyLuo
 * @date 2019/11/21 13:25
 */
var bjjyResultList = [];
var bjjyByAjax = function (sbsjMap, checkType, path, special_handle) {
    if (sbsjMap == null || sbsjMap == "") {
        return "传入的数据为空！";
    }
    if (special_handle != null && special_handle != "") {
        special_handle = JSON.parse(special_handle);
    }

    // 读取json文件中的json数据，筛选出满足条件的数据
    var result = [];
    $.ajax({
        type: "GET",//请求方式
        url: path,//地址，就是json文件的请求路径
        dataType: "json",//数据类型可以为 text xml json  script  jsonp
        async: false,
        success: function (data) { // 返回的json文件中的数据
            result = data;
        },
        error: function () {
        }
    });

    var formulaBz = checkType || checkType == "2" ? true : false;
    var conditionBz = !checkType ? true : false;

    bjjyResultList = [];
    // 获取sbsjMap的所有key
    var keys = Object.keys(sbsjMap);
    // linq过滤result
    result = dataFilter(result, keys);
    // 若是该标志为Y，则他只有10420——002的表，需要把002的校验过滤掉，若为N,则不需要校验，因为他有10420整个类型的表
    if (keys.toString().indexOf("10414") >= 0 && sbsjMap.glbBz == "Y") {
        result = dataFilterSdsbd(result, '10420_002');
    }
    // 如果保存数据中没有传所得税年报表单，并且，关联表标志是N，则过滤掉10414——003，,10414——004的校验，因为这种情况可能是没有申报所得税年报，也有可能是只申报关联表了
    if (keys.toString().indexOf("10414_002") < 0 && sbsjMap.glbBz == "N") {
        result = dataFilterSdsbd(result, '10414_003,10414_004');
    }
    var noticeBz = false;//是否展示通知弹框
    if (result != undefined && result != "undefined" && result != null && result.length != 0) {
        for (var i = 0; i < result.length; i++) {
            var type = result[i].checkType;
            // 判断企业是否有该报表，有则继续校验，无，则不去校验
            if (special_handle != null && special_handle.bbDmList != null) {
                var bb = getSbsjMapKey(special_handle.bbDmList, result[i].bbDm);
                if (bb == null || bb == "") {
                    continue; // 跳出本次循环
                }
            }
            //如果参数key和数据中的报表匹配，则返回该对象
            if (JSON.stringify(keys).indexOf(result[i].bbDm + "_" + result[i].versionNumber) >= 0) {
                // 表间校验和通知的规则一样。
                if (formulaBz && (type.indexOf("0") >= 0)) {
                    // 如果是通知，则只执行type为06的校验
                    if (checkType == "2" && type != "06") {
                        continue; // 跳出本次循环
                    }
                    // 验证数据，如果为true，则验证公式
                    if (doFormula(result[i].premise, sbsjMap, true, type, result[i], special_handle)) {
                        // 验证公式，如果为true，则返回提示信息
                        if (doFormula(result[i].formula, sbsjMap, false, type, result[i], special_handle)) {
                            // 返回该表的提示信息
                            var final = {
                                "id": result[i].id,
                                "zsxmDm": result[i].zsxmDm,
                                "bblxDm": result[i].bblxDm,
                                "bbDm": result[i].bbDm,
                                "version": result[i].versionNumber,
                                "tip": result[i].tip,
                                "flag": result[i].flag,
                                "targetCellId": result[i].targetCellId,
                                "bbMc": result[i].bbMc,
                                "shbz": result[i].shbz,
                                "shsmbz": result[i].shsmbz

                            };
                            if (checkType == "2" && type == "06") {
                                noticeBz = true; // 如果是通知标识，则告诉前台需要展示弹框通知。
                                break;
                            } else if (type != "06") {
                                bjjyResultList.push(final);
                            }
                        }
                    }
                }
                //  条件必填校验
                if (conditionBz && (type.indexOf("0") < 0)) {
                    // 验证数据，如果为true，则验证公式
                    if (doFormula(result[i].premise, sbsjMap, true, type, result[i], special_handle)) {
                        // 验证公式，如果为true，则返回提示信息
                        if (conditionCheck(result[i], sbsjMap, special_handle)) {
                            // 返回该表的提示信息
                            var final = {
                                "id": result[i].id,
                                "zsxmDm": result[i].zsxmDm,
                                "bblxDm": result[i].bblxDm,
                                "bbDm": result[i].bbDm,
                                "version": result[i].versionNumber,
                                "tip": result[i].tip,
                                "flag": result[i].flag,
                                "targetCellId": result[i].targetCellId,
                                "bbMc": result[i].bbMc,
                                "shbz": result[i].shbz,
                                "shsmbz": result[i].shsmbz

                            };
                            bjjyResultList.push(final);
                        }
                    }
                }
            }
        }
    }
    if (checkType == "2") {
        return noticeBz; // 如果是通知标识，则告诉前台需要展示弹框通知。
    }
    return bjjyResultList;
};


/**
 * <p>
 *过滤表间校验数据
 * </p>
 * @param bjjyData
 * @param sbsjkeys
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/11/25 11:14
 */
function dataFilter(bjjyData, sbsjkeys) {
    var newArr = Enumerable.From(bjjyData).Where(function (sbsj) {
        return JSON.stringify(sbsjkeys).indexOf(sbsj.bbDm + "_" + sbsj.versionNumber) >= 0
    }).ToArray();
    return newArr;
}

/**
 * <p>
 * 根据报表类型过滤
 * </p>
 * @param result
 * @param bblxList
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/5/30 13:26
 */
function filterByBblxDM(result, bblxList) {
    var newArr = Enumerable.From(result).Where(function (sbsj) {
        return JSON.stringify(bblxList).indexOf(sbsj.bblxDm) >= 0
    }).ToArray();
    return newArr;
}

/**
 * <p>
 *过滤bjjyData中包含的所有key的数据
 * </p>
 * @param bjjyData
 * @param key
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/11/25 11:14
 */
function dataFilterSdsbd(bjjyData, key) {
    var newArr = Enumerable.From(bjjyData).Where(function (sbsj) {
        return key.indexOf(sbsj.bbDm) < 0
    }).ToArray();
    return newArr;
}

/**
 * <p>
 *是否有公式校验
 * </p>
 * @param formula，这个报表的公式校验
 * @param sbsjMap，key:bbDm_Version,value:bbsj（json）
 * @param bz,如果true是数据校验，false，公式校验，若是公式结果是false，则需要弹出信息,所以需要返回ture结果
 * @param checkType:处理类型，
 * 1：报表条件必填表校验 2:报表内数据条件必填 3：所得税年报不定行条件校验
 * 0：表间校验
 * 01：消费税不定行表间校验 02：所得税年报不定行表间校验 03:附税负数置为0 ,
 * 04:多批次不定行比较,05:两个list作比较，06:通知，
 * 07：如果填写这张表，则表间不自动设置默认值0，08：多批次校验时，如果是数字则不将所有批次的值加起来
 * 09：带括号规则校验
 * 001：控制空值的默认值,002:控制百分数跟小数对比的时候精度问题，已最大的位数调整,003:除法四舍五入为10位
 * 06:通知
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/11/21 13:06
 */
function doFormula(formula, sbsjMap, bz, checkType, jsonData, special_handle) {
    var sfgz = special_handle.sfgz;
    // 如果验证为空，则直接进入公式验证
    if (formula == null || formula == "") {
        return true;
    } else {
        //替换所有空格
        formula = formula.replace(/\s/g, "");
    }
    var finalFormula = false;
    if (checkType == '01') {
        // 消费税多行匹配比较公式
        finalFormula = xfsMultiLineBjjyCommon(formula, sbsjMap, jsonData, bz);
    } else if (checkType == '02') { //  条件校验必须是空，只有公式校验
        // 年报所得税多行处理
        finalFormula = sdsNbMultiLineBjjyCommon(formula, sbsjMap, jsonData);
    } else if (checkType == '04') { //  条件校验必须是空，只有公式校验
        // 多批次报表所有的内容，分别对比多个列表的内容，判断是否相等。
        finalFormula = multiPatchMultiLineBjjyCommon(formula, sbsjMap, jsonData);
    } else if (checkType == '05') {//  条件校验必须是空，只有公式校验
        //  所得税年报两个list对比
        finalFormula = sdsTwoListBjjyCommon(formula, sbsjMap, jsonData);
    } else if (checkType == '3') {
        // 不定行条件校验
        finalFormula = MultiLine(formula, sbsjMap);
    } else if (checkType == '09') {
        // 带括号的校验
        finalFormula = khbjjyCommon(formula, sbsjMap, checkType);
    } else {
        if (!(sfgz == "1" && checkType == "03")) {
            // 正常公式比较
            finalFormula = bjjyCommon(formula, sbsjMap, checkType);
        }
    }

    if (bz) {
        return finalFormula;
    } else {
        // 如果是更正申报，增值税、附税、消费税间表间校验都不触发。增值税和消费税未发现有税种间的校验，只有附税有，正好标识都是03
        if (sfgz == "1" && checkType == "03") {
            finalFormula = true;
        }
        return !finalFormula;
    }
}

/**
 * <p>
 *校验公式
 * </p>
 * @param premise，这个报表的公式校验
 * @param sbsjMap，key:bbDm_Version,value:bbsj（json）
 * @param checkType
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/11/21 13:08
 */
function bjjyCommon(premise, sbsjMap, checkType) {
    var lastPremise = premise;
    var reg = /(\$\{.*?\})/g; //"\."匹配“.”字符，"d+"匹配多个数字，最后一个g表示要全局匹配所有结果
    var result = premise.match(reg);  //返回符合的字体串数组
    $.each(result, function (index, value) {
        var va = value.split(",");
        var va1 = va[0].replace("${", "");// 校验值报表代码取得
        var va2 = va[1].replace("}", "");// 校验值表内路径取得

        // 没有这个表的数据则默认置为0
        if (JSON.stringify(Object.keys(sbsjMap)).indexOf(va1) < 0) {
            if (checkType != "07" && checkType != "4") {
                // 2019.12.3 by DyLuo 跟张天翼确认，如果需要申报的报表，跟未填写的报表有校验，则将为填写的报表置为0或者null；
                // 赋值"0.00"
                lastPremise = lastPremise.replace(value, "0.00");
            }
        } else {
            // 获取sbsjMap包含va1的key值
            var va4 = 0; // 2019.12.10 附税是多个批次，也就是说包含11602的key会有多个，需要把这几个批次所有的值加在一起
            $.each(sbsjMap, function (i, data) {
                if (i.toString().indexOf(va1) >= 0) {
                    var va3 = strToFun(va2, data);// 校验值取得
                    if (va3 == null || va3 == "" || va3 == "undefined" || va3 == undefined) {
                        // 若是特殊的类型001 并且该值为空，则默认值按照'NN'处理
                        if (checkType == "001") {
                            va3 = 'NN';
                        } else {
                            va3 = "0.00";

                        }
                    }

                    if (va4 != 0 && /[0-9]/.test(va4) && checkType != "08") {
                        va4 = va4 + "+" + va3;
                    } else if (/[a-zA-Z]+/.test(va3)) {
                        va4 = "'" + va3 + "'";
                    } else {
                        va4 = va3;
                    }
                    // 附税的特殊表间校验，公式中除了附税表取值不处理，其余表的取值，若值为负数，将负数按0处理
                    if (checkType == "03" && /[0-9]/.test(va4) && va4 < 0 && va1.substring(0, va1.lastIndexOf("_")) != '11602') {
                        va4 = "0";
                    }
                    va4 = (va4 + "").replace(new RegExp(/,|，/g), ""); // 将值中的所有的逗号都替换为空
                }
            });
            lastPremise = lastPremise.replace(value, va4);

        }
    });

    var ba = false;
    try {
        // 如果是这个标志，并出现这个字符，证明没有填写数据，那应该让条件校验过去，去触发条件必报校验。
        if (checkType == "4" && lastPremise.indexOf("${") >= 0) {
            return true;
        }

        if (lastPremise.indexOf("${") >= 0) {
            // 出现这个字符，则证明该企业没有这张报表，所以不需要校验
            return true;
        }

        var regString = /[a-zA-Z]+/; //验证大小写26个字母任意字母最少出现1次。或者包含汉字
        if ((regString.test(lastPremise) || CheckChinese(lastPremise)) && (regString.test(lastPremise) && (!/[0-9]/.test(lastPremise)))) {
            ba = campareChinese(lastPremise);
        } else {
            var re = formulaCount(lastPremise, checkType); // 其余类型做判断
            ba = eval(re);
        }
    } catch (e) {
        console.log("计算公式异常:" + e);
        try {
            var re = formulaCount(lastPremise, checkType); // 其余类型做判断
        } catch (err) {

        }

    }
    return ba;
}

/**
 * 定位字符串在数组的某个位置，并取出该位置的值
 * @param str
 * @param mapPageData
 * @returns {*}
 */
var strToFun = function (str, mapPageData) {
    var _self = mapPageData;
    var json = new Function("_self", "return _self." + str.replace("this.", ""));
    return json(_self);
};

/**
 * <p>
 * 精准计算公式
 * </p>
 * @param lastFormula
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/11/23 10:59
 */
function formulaCount(lastFormula, checkType) {
    var first = lastFormula;
    // 如果公式中中有中括号
    var zkh = /(\【.*?\】)/g;
    var zkhResult = first.match(zkh);  //返回符合的字体串数组
    // 如果没有中括号就找小括号
    if (zkhResult == null || zkhResult.length == 0) {
        var xkh = /(\(.*?\))/g;
        zkhResult = first.match(xkh);  //返回符合的字体串数组
        if (zkhResult == null || zkhResult.length == 0) {
            var xkh = /(\（.*?\）)/g;
            zkhResult = first.match(xkh);  //返回符合的字体串数组
        }
    }
    // 小括号也没有，则直接正常计算公式
    if (zkhResult == null || zkhResult.length == 0) {
        first = getResultValue(lastFormula, checkType, first);
    } else {
        $.each(zkhResult, function (index, zkhValue) {
            // 根据小括号进行拆分
            var xkh = /(\(.*?\))/g;
            var xkhResult = zkhValue.match(xkh);  //返回符合的字体串数组
            //中文小括号
            if (xkhResult == null || xkhResult.length == 0) {
                var xkh = /(\（.*?\）)/g;
                xkhResult = zkhValue.match(xkh);
            }
            // 如果没有小括号，则按照正常逻辑
            if (xkhResult == null || xkhResult.length == 0) {
                first = getResultValue(zkhValue, checkType, lastFormula);
            } else {
                $.each(xkhResult, function (index, xkhValue) {
                    var lastReusult = getResultValue(xkhValue, checkType, xkhValue);
                    lastReusult = lastReusult.replace(/\(/g, "").replace(/\)/g, "");
                    var result = eval(lastReusult);// 算出括号最后结构
                    first = first.replace(xkhValue, result);
                    zkhValue = zkhValue.replace(xkhValue, result);
                });
            }
            // 如果有最外层有！
            var formulaResult = first;
            if (first.indexOf("!【") >= 0) {
                formulaResult = formulaResult.replace("!【", "【");
            }
            // 括号公式算完之后，判断是否还有不带公式的计算，如果有，则计算不带括号的公式
            if (first.indexOf("(") < 0 && (first.indexOf(">") >= 0 || first.indexOf("<") >= 0 || first.indexOf("==") >= 0 || first.indexOf(">=") >= 0 || first.indexOf("<=") >= 0 || first.indexOf("!=") >= 0)) {
                first = getResultValue(formulaResult, checkType, first);
                zkhValue = zkhValue.replace(formulaResult, first);
            }
            // 去掉最外层的中括号
            if (zkhValue.indexOf("【") >= 0) {
                if (zkhValue.indexOf("!【") >= 0) {
                    zkhValue = zkhValue.replace("!【", "【");
                }
                var zkhResult = zkhValue;
                zkhResult = zkhResult.replace(/\【/g, "").replace(/\】/g, "");
                zkhResult = eval(zkhResult);// 算出括号最后结构
                first = first.replace(zkhValue, zkhResult);
            }
        });
        // 括号公式算完之后，判断是否还有不带公式的计算，如果有，则计算不带括号的公式
        if (first.indexOf(">") >= 0 || first.indexOf("<") >= 0 || first.indexOf("==") >= 0 || first.indexOf(">=") >= 0 || first.indexOf("<=") >= 0 || first.indexOf("!=") >= 0) {
            first = getResultValue(lastFormula, checkType, first);
        }
    }
    return first;
}

function getResultValue(lastFormula, checkType, first) {
    // 判断是否包含||、&&，如果有则切分，分开切不是很好处理，所以为了统一切分，将所有的||、&&全部替换为|符号
    lastFormula = lastFormula.replace(/\|\|/g, "|").replace(/&&/g, "|");
    lastFormula = lastFormula.replace(/\(/g, "").replace(/\)/g, "").replace(/\【/g, "").replace(/\】/g, "");
    // 中文小括号
    lastFormula = lastFormula.replace(/\（/g, "").replace(/\）/g, "");

    var sqlitFirt = lastFormula.split("|");  //返回符合的字体串数组
    $.each(sqlitFirt, function (index, value) {
        var regString = /[a-zA-Z]+/; //验证大小写26个字母任意字母最少出现1次。
        if (regString.test(value) || CheckChinese(value)) {
            var ba = campareChinese(value);
            first = first.replace(value, ba);

        } else {
            first = symbolFun(value, first, checkType);
        }
    });
    return first;
}

/**
 * <p>
 * 普通公式计算
 * </p>
 * @param value
 * @param first
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/11/23 14:10
 */
function symbolFun(value, first, checkType) {
    var second = value;
    // 判断是否包含>=、<=、==，!=,>,<如果有则切分，分开切不是很好处理，所以为了统一切分，将所有的>=、<=、==，!=,>,<全部替换为|符号
    value = value.replace(/>=/g, "|").replace(/<=/g, "|").replace(/==/g, "|").replace(/!=/g, "|").replace(/>/g, "|").replace(/</g, "|");
    value = value.replace(/,/g, "");// 替换掉数字间所有的逗号

    // 比较值的大小
    var compareResult;
    var sqlitSecond = value.split("|");
    var rr = true;
    if (second.indexOf(">=") >= 0) {
        compareResult = copmpareTo(sqlitSecond[0], sqlitSecond[1], checkType);
        if (compareResult < 0) {
            rr = false;
        }
    } else if (second.indexOf("<=") >= 0) {
        compareResult = copmpareTo(sqlitSecond[0], sqlitSecond[1], checkType);
        if (compareResult > 0) {
            rr = false;
        }
    } else if (second.indexOf("!=") >= 0) {
        compareResult = copmpareTo(sqlitSecond[0], sqlitSecond[1], checkType);
        if (compareResult == 0) {
            rr = false;
        }
    } else if (second.indexOf("==") >= 0) {
        compareResult = copmpareTo(sqlitSecond[0], sqlitSecond[1], checkType);
        if (compareResult != 0) {
            rr = false;
        }
    } else if (second.indexOf(">") >= 0) {
        compareResult = copmpareTo(sqlitSecond[0], sqlitSecond[1], checkType);
        if (compareResult <= 0) {
            rr = false;
        }
    } else if (second.indexOf("<") >= 0) {
        compareResult = copmpareTo(sqlitSecond[0], sqlitSecond[1], checkType);
        if (compareResult >= 0) {
            rr = false;
        }
    } else {
        compareResult = copmpareTo(sqlitSecond[0], sqlitSecond[1], checkType, "Y");
        rr = compareResult;
    }
    first = first.replace(second, rr);

    return first;
}

/**
 * <p>
 * 条件表判断
 * </p>
 * @param formula
 * @param sbsjMap
 * @param special_handle
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/11/26 17:19
 */
function conditionCheck(jsonData, sbsjMap, special_handle) {
    var bbsj = JSON.stringify(Object.keys(sbsjMap));
    var glbBz = sbsjMap.glbBz;
    var formula = jsonData.formula;
    var bblxDm = jsonData.bblxDm;
    if (formula == null || formula == "") {
        return true;
    }
    var data = formula.split("|");
    var result = [];
    var bbSbzt = null;
    var gzsbBz = null;
    if (special_handle != null && special_handle != "") {
        bbSbzt = special_handle.ysbBblx;
        gzsbBz = special_handle.sfgz
    }
    // 2020-4-27 跟张天翼确认，更正申报时，增值税、消费税和附税所有税种间的校验都不触发。
    if (gzsbBz == "1" && bblxDm == '11602') {
        return false;
    }


// 特殊校验，判断10414和10420是否同时申报，glbBz == 'Y'时，则是没有带着关联表一起申报
    if (glbBz == 'Y' && data[0] == '10420_002') {
        if (bbsj.indexOf('10420_003') >= 0 && bbsj.indexOf('10420_004') >= 0
            || (jsonData.checkType == "4" && bbsj.indexOf('10420_002') >= 0)
            || (jsonData.checkType == "5")
        ) {
            return false;
        } else {
            return true;
        }
    } else if (glbBz == 'N' && data[0] == '10420_002' && jsonData.checkType == "5") {
        // 如果带着关联表一起申报，并且关联表表单是否都选择了否。则弹出校验
        return true;
    }

    $.each(data, function (index, value) {
        // 判断表数据中是否有这张报表，有则返回false，不需要提示校验，没有，则返回true，需要提示校验。
        if (bbsj.indexOf(value) >= 0) {
            result.push("false");
        } else if (gzsbBz == "1" && value == '11602_001') { // 2020-04-27 根据bug17836调整，如果是更正申报，则 10101_017的条件必填校验不能触发
            result.push("false");
            return false; // 因为关于这个校验的，被校验的只有一个报表条件，所以直接跳出循环也行
        } else {
            // 如果是true 则是没有报表json数据，
            // 需要进行以下判断，判断是否是已申报。
            if (getSbsjMapKey(special_handle.bbDmList, value) != "") {
                if (bbSbzt != null && bbSbzt != undefined && Object.keys(bbSbzt).length > 0) {
                    $.each(bbSbzt, function (zsxmDm, bblxSbzt) {
                        // 报表是该企业有的，并且申报状态list中含有该bblxDm，如果申报信息中不包含value，则证明这税种中没有这个bblx
                        var sbzt = bblxSbzt[value.substring(0, 5)];
                        if (sbzt == "Y") {
                            result.push("false");
                            return false; // 找到对应的bblx就可以跳出本次循环，不用在继续执行下一次循环了
                        } else if (sbzt == "N") {
                            // 没有申报的数据，则返回true
                            result.push("true");
                        }
                    });
                } else {
                    // 没有申报的数据，则返回true
                    result.push("true");
                }
            } else {
                // 若是这张表不是该企业有的，则不去校验。
                result.push("false");
            }

        }
    });

    var br = result.join("||");

    return eval(br);
}

/**
 * <p>
 *判断字符串是否包含汉字
 * </p>
 * @param val
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/1/2 16:39
 */
function CheckChinese(val) {
    var reg = new RegExp("[\\u4E00-\\u9FFF]+", "g");
    if (reg.test(val)) {
        return true;
    } else {
        return false;
    }
}

/**
 * <p>
 *比较非数值型变量
 * </p>
 * @param value
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/1/2 17:48
 */
function campareChinese(value) {
    var flag = false;
    var lastFormula = value;
    // 判断是否包含||、&&，如果有则切分，分开切不是很好处理，所以为了统一切分，将所有的||、&&全部替换为|符号
    lastFormula = lastFormula.replace(/\|\|/g, "|").replace(/&&/g, "|");

    var sqlitFirt = lastFormula.split("|");  //返回符合的字体串数组
    $.each(sqlitFirt, function (index, val) {
        var arr = [];
        if (val.indexOf("==") >= 0) {
            arr = val.split("==");
            if (arr[0] == arr[1]) {
                flag = true;
            } else {
                flag = false;
            }
        } else if (val.indexOf("!=") >= 0) {
            arr = val.split("!=");
            if (arr[0] != arr[1]) {
                flag = true;
            } else {
                flag = false;
            }
        } else {
            flag = eval(val);
        }
        value = value.replace(val, flag)
    });
    return eval(value);
}

/**
 * <p>
 *电子申报2020年3月需求  申报增加弹出框
 * </p>
 * @param 2020年按月属期为3、4、5月的小规模申报表以及按季属期为第一季度和第二季度的申报表。
 * @return
 * @throws
 * @author zzt
 * @date 2020年4月10日15:16:33
 */
function fgInfo() {
    parent.layer.open({
        type: 1,
        title: ['通告', 'font-size:18px;text-align: center;'],
        area: ['550px', '500px'],
        btnAlign: 'c',
        closeBtn: 0,
        btn: ['确定'],//按钮
        content: '尊敬的纳税人：<br>\n' +
        '&emsp;&emsp;按照国家税务总局的有关规定，小规模纳税人在2021年12月31日前，对原适用3%征收率征税增值税的，适用减按1%征收率。由于您本期填写了原3%征收率对应的销售额栏次（即第1至第3栏存在数据），且未填写相关减税栏次，有可能存在多缴税款的情况。为保障您在申报时应享尽享优惠政策，请您仔细阅读以下文字，按照实际情况进行准确申报。<br>\n' +
        '          &emsp;&emsp;1.如果您本期属于小微企业，请您将本属期内已开具或代开的1%征收率的增值税专用发票收入（不含税金额）乘以2%，填写在“本期应纳税额减征额”及《增值税减免税申报明细表》减税项目相应栏次（减税代码请填写0001011608）。<br>\n' +
        '          &emsp;&emsp;小微企业是指按月申报的，月销售额不超过10万元或按季申报的，季销售额不超过30万元的小规模纳税人。<br>\n' +
        '          &emsp;&emsp;2.如果您本期不属于小微企业，请您将本属期内适用1%征收率的不含税收入乘以2%（该收入包含代开和自开的全部发票收入，以及未开票收入），填写在“本期应纳税额减征额”及《增值税减免税申报明细表》减税项目相应栏次（减税代码请填写0001011608）。<br>\n' +
        '          &emsp;&emsp;您可以参考<a href="javascript:void(0);" onclick="javascript:window.open(`https://sbjs.tjsat.gov.cn/sbjsweb/xgmsbyd.html`)">相关案例</a>进行填报，也可以拨打12366或向主管税务机关进行咨询。<br><br>\n' +
        '&emsp;&emsp;<input type="checkbox" name="readCheckbox">' + '我已阅读并了解上述申报表填写要求。',
        yes: function (index) {
            if (parent.$("input[name='readCheckbox']").is(':checked')) {
                parent.layer.close(index);
            } else {
                parent.layer.msg('请勾选[我已阅读并了解上述申报表填写要求。]', {time: 2000});
                return false
            }
        }
    });
}

/**
 * <p>
 *税务局2021年2月需求  科技型企业未享受研发费用加计扣除校验需求
 * </p>
 * @param 年报10414专属
 * @return
 * @throws
 * @author zzt
 * @date 2021年2月5日15:13:21
 */
function kjjjkcInfo() {
    parent.layer.open({
        type: 1,
        title: ['提示', 'font-size:18px;text-align: center;'],
        area: ['700px', '320px'],
        btnAlign: 'c',
        closeBtn: 0,
        btn: ['确定并继续申报', '返回'],//按钮
        content: '&emsp;&emsp;尊敬的纳税人：<br>\n' +
        '&emsp;&emsp;&emsp;&emsp;贵公司属于科技型企业，按照相关政策文件规定，企业发生的符合条件的研发支出，<br>' +
        '&emsp;&emsp;可享受研发费用加计扣除所得税优惠政策。贵公司本年度未申报享受研发费用加计扣除<br>' +
        '&emsp;&emsp;的原因为:<br><br>' +
        '&emsp;&emsp;&emsp;&emsp;<input type="radio" value="1" name="kjJjKcRadio" checked>' + '1.已知晓研发加计优惠政策，但因自身原因放弃享受。<br><br>' +
        '&emsp;&emsp;&emsp;&emsp;<input type="radio" value="2" name="kjJjKcRadio">' + '2.已知晓研发加计优惠政策，但未发生或未归集符合条件的研发费。<br><br>' +
        '&emsp;&emsp;&emsp;&emsp;<input type="radio" value="3" name="kjJjKcRadio">' + '3.已知晓研发加计优惠政策，但因其他原因放弃享受。',
        yes: function (index) {
            parent.layer.close(index);
            console.log(parent.$("input[name='kjJjKcRadio']:checked").val())
            // if (parent.$("input[name='readCheckbox']").is(':checked')) {
            //     parent.layer.close(index);
            // } else {
            //     parent.layer.msg('请勾选[我已阅读并了解上述申报表填写要求。]', {time: 2000});
            //     return false
            // }
        },
        btn2: function (index) {
            parent.layer.close(index);
            console.log(parent.$("input[name='kjJjKcRadio']:checked").val())
            // if (parent.$("input[name='readCheckbox']").is(':checked')) {
            //     parent.layer.close(index);
            // } else {
            //     parent.layer.msg('请勾选[我已阅读并了解上述申报表填写要求。]', {time: 2000});
            //     return false
            // }
        }
    });
}

/**
 * <p>
 * 涉税平台税种间校验【涉税的表间校验和在线改造用的是一套，所以将税种间的校验拆出来，涉税用此方法校验税种间校验】
 * 税种间表间校验和必报表校验
 * </p>
 * @param bblxList 选择的报表类型
 * @param path 税种间校验json地址
 * @param special_handle 格式同表间校验
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/5/30 13:27
 */
var tax = [];

function taxCheck(bblxList, path, special_handle) {
    tax = [];
    var bbsj = special_handle.bbjy_data;
    if (bbsj == undefined || bbsj == null || bbsj == "") {
        return tax;
    }
    // 读取json文件中的json数据，筛选出满足条件的数据
    var result = [];
    $.ajax({
        type: "GET",//请求方式
        url: path,//地址，就是json文件的请求路径
        dataType: "json",//数据类型可以为 text xml json  script  jsonp
        async: false,
        success: function (data) { // 返回的json文件中的数据
            result = data;
        },
        error: function () {
        }
    });
    // linq过滤result
    // result = filterByBblxDM(result, bblxList);
    // 获取sbsjMap的所有key
    var keys = Object.keys(bbsj);
    // linq过滤result
    result = dataFilter(result, keys);
    // 若是该标志为Y，则他只有10420——002的表，需要把002的校验过滤掉，若为N,则不需要校验，因为他有10420整个类型的表
    if (keys.toString().indexOf("10414") >= 0 && bbsj.glbBz == "Y") {
        result = dataFilterSdsbd(result, '10420_002');
    }
    //遍历税种间校验
    $.each(result, function (id, json) {
        // 税种间的表间校验
        if (json.checkType.indexOf("0") >= 0 && json.checkType != "03") {
            // 验证数据，如果为true，则验证公式
            if (doFormula(json.premise, bbsj, true, json.checkType, json, special_handle)) {
                // 验证公式，如果为true，则返回提示信息
                if (doFormula(json.formula, bbsj, false, json.checkType, json, special_handle)) {
                    // 返回该表的提示信息
                    var final = {
                        "id": json.id,
                        "zsxmDm": json.zsxmDm,
                        "bblxDm": json.bblxDm,
                        "bbDm": json.bbDm,
                        "version": json.versionNumber,
                        "tip": json.tip,
                        "flag": json.flag,
                        "targetCellId": json.targetCellId,
                        "bbMc": json.bbMc,
                        "shbz": json.shbz,
                        "shsmbz": json.shsmbz

                    };
                    tax.push(final);
                }
            }
        } else if (json.checkType.indexOf("0") < 0 || json.checkType == "03") { // 税种间的必报校验
            if (doFormula(json.premise, bbsj, true, json.checkType, json, special_handle)) {
                if (taxCheckResult(json, bblxList, special_handle, bbsj)) {
                    // 返回该表的提示信息
                    var final = {
                        "id": json.id,
                        "zsxmDm": json.zsxmDm,
                        "bblxDm": json.bblxDm,
                        "bbDm": json.bbDm,
                        "version": json.versionNumber,
                        "tip": json.tip,
                        "flag": json.flag,
                        "targetCellId": json.targetCellId
                    };
                    tax.push(final);
                }
            }
        }
    });
    return tax;

}

/**
 * <p>
 *涉税平台的税种间校验（包含税种间取值校验和税种间校验）
 * </p>
 * @param jsonData
 * @param bblxList
 * @param special_handle
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/6/22 10:28
 */
function taxCheckResult(jsonData, bblxList, special_handle, bbsj) {
    var bbsjKey = JSON.stringify(Object.keys(bbsj));
    var checkType = jsonData.checkType;
    var glbBz = bbsj.glbBz;
    // 需要判断是否是汇总企业
    var hznsqy = special_handle.hznsqy;
    if (checkType == "03") {
        // 读取公式，计算公式结果
        return ssfwptMultiLine(jsonData, bbsj, hznsqy);
    } else {
        var formula = jsonData.formula; // 一个报表类型或者多个报表类型
        var bblxDm = jsonData.bblxDm;
        if (formula == null || formula == "") {
            return true;
        }
        var data = formula.split("|");
        var result = [];
        var bbSbzt = null;
        var gzsbBz = null;
        if (special_handle != null && special_handle != "") {
            bbSbzt = special_handle.ysbBblx;
            gzsbBz = special_handle.sfgz
        }
        // 2020-4-27 跟张天翼确认，更正申报时，增值税、消费税和附税所有税种间的校验都不触发。
        if (gzsbBz == "1" && bblxDm == '11602') {
            return false;
        }

        // 特殊校验，判断10414和10420是否同时申报，glbBz == 'Y'时，则是没有带着关联表一起申报
        if (glbBz == 'Y' && data[0] == '10420_002') {
            if (bbsjKey.indexOf('10420_003') >= 0 && bbsjKey.indexOf('10420_004') >= 0
                || (jsonData.checkType == "4" && bbsjKey.indexOf('10420_002') >= 0)
                || (jsonData.checkType == "5")
            ) {
                return false;
            } else {
                return true;
            }
        } else if (glbBz == 'N' && data[0] == '10420_002' && jsonData.checkType == "5") {
            // 如果带着关联表一起申报，并且关联表表单是否都选择了否。则弹出校验
            return true;
        }

        $.each(data, function (index, value) {
            // 判断表数据中是否有这张报表，有则返回false，不需要提示校验，没有，则返回true，需要提示校验。
            var bblx = value.substring(0, 5);
            if (bbsjKey.indexOf(bblx) >= 0) {
                result.push("false");
            } else if (gzsbBz == "1" && bblx == '11602') { // 2020-04-27 根据bug17836调整，如果是更正申报，则 10101_017的条件必填校验不能触发
                result.push("false");
                return false;
            } else {
                // 如果是true 则是没有报表json数据，
                if (getSbsjMapKey(special_handle.bbDmList, value) != "") {
                    // 需要进行以下判断，判断是否是已申报。
                    if (bbSbzt != null && bbSbzt != undefined && Object.keys(bbSbzt).length > 0) {
                        $.each(bbSbzt, function (zsxmDm, bblxSbzt) {
                            // 申报状态list中含有该bblxDm
                            var sbzt = bblxSbzt[bblx];
                            if (sbzt == "Y") {
                                result.push("false");
                                return false; // 找到对应的bblx就可以跳出本次循环，不用在继续执行下一次循环了
                            } else if (sbzt == "N") {
                                // 没有申报的数据，则返回true
                                result.push("true");
                            }
                        });
                    } else {
                        // 没有申报的数据，则返回true
                        result.push("true");
                    }
                } else {
                    // 若是这张表不是该企业有的，则不去校验。
                    result.push("false");
                }

            }
        });
        var br = result.join("||");
        return eval(br);
    }

}

/**
 * <p>
 *带括号的公式
 * </p>
 * @param null
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/10/24 13:58
 */
function khbjjyCommon(premise, sbsjMap, checkType) {
    var lastPremise = premise;

    // 根据中括号进行拆分
    var zkh = /(\【.*?\】)/g;
    var zkhResult = premise.match(zkh);  //返回符合的字体串数组
    // 如果没有中括号就找小括号
    if (zkhResult == null || zkhResult.length == 0) {
        var xkh = /(\(.*?\))/g;
        zkhResult = premise.match(xkh);  //返回符合的字体串数组
    }
    if (zkhResult == null || zkhResult.length == 0) {
        var xkh = /(\（.*?\）)/g;
        zkhResult = premise.match(xkh);  //返回符合的字体串数组
    }
    if (zkhResult == null || zkhResult.length == 0) {
        lastPremise = getValue(lastPremise, premise, checkType, sbsjMap);
    } else {
        $.each(zkhResult, function (index, zkhValue) {
            // 根据小括号进行拆分
            var xkh = /(\(.*?\))/g;
            var xkhResult = zkhValue.match(xkh);  //返回符合的字体串数组
            if (xkhResult == null || xkhResult.length == 0) {
                var xkh = /(\（.*?\）)/g;
                xkhResult = zkhValue.match(xkh);  //返回符合的字体串数组
            }
            // 如果没有小括号，则按照正常逻辑
            if (xkhResult == null || xkhResult.length == 0) {
                lastPremise = getValue(lastPremise, zkhValue, checkType, sbsjMap);
            } else {
                $.each(xkhResult, function (index, xkhValue) {
                    lastPremise = getValue(lastPremise, xkhValue, checkType, sbsjMap);
                });
            }

        });
    }


    var ba = false;
    try {
        if (lastPremise.indexOf("${") >= 0) {
            // 出现这个字符，则证明该企业没有这张报表，所以不需要校验
            return true;
        }

        var regString = /[a-zA-Z]+/; //验证大小写26个字母任意字母最少出现1次。或者包含汉字
        if ((regString.test(lastPremise) && (!/[0-9]/.test(lastPremise))) || CheckChinese(lastPremise)) {
            ba = campareChinese(lastPremise);
        } else {
            var re = formulaCount(lastPremise, checkType); // 其余类型做判断
            ba = eval(re);
        }
    } catch (e) {
        console.log("计算公式异常:" + e);
        try {
            var re = formulaCount(lastPremise, checkType); // 其余类型做判断
        } catch (err) {

        }

    }
    return ba;
}

function getValue(lastPremise, xkhValue, checkType, sbsjMap) {
    var reg = /(\$\{.*?\})/g; //"\."匹配“.”字符，"d+"匹配多个数字，最后一个g表示要全局匹配所有结果
    var result = xkhValue.match(reg);  //返回符合的字体串数组
    $.each(result, function (index, value) {
        var va = value.split(",");
        var va1 = va[0].replace("${", "");// 校验值报表代码取得
        var va2 = va[1].replace("}", "");// 校验值表内路径取得

        // 没有这个表的数据则默认置为0
        if (JSON.stringify(Object.keys(sbsjMap)).indexOf(va1) < 0) {
            if (checkType != "07") {
                // 2019.12.3 by DyLuo 跟张天翼确认，如果需要申报的报表，跟未填写的报表有校验，则将为填写的报表置为0或者null；
                // 赋值"0.00"
                lastPremise = lastPremise.replace(value, "0.00");
            }
        } else {
            // 获取sbsjMap包含va1的key值
            var va4 = 0; // 2019.12.10 附税是多个批次，也就是说包含11602的key会有多个，需要把这几个批次所有的值加在一起
            $.each(sbsjMap, function (i, data) {
                if (i.toString().indexOf(va1) >= 0) {
                    var va3 = strToFun(va2, data);// 校验值取得
                    if (va3 == null || va3 == "" || va3 == "undefined" || va3 == undefined) {
                        // 若是特殊的类型001 并且该值为空，则默认值按照'NN'处理
                        if (checkType == "001") {
                            va3 = 'NN';
                        } else {
                            va3 = "0.00";

                        }
                    }

                    if (va4 != 0 && /[0-9]/.test(va4) && checkType != "08") {
                        va4 = va4 + "+" + va3;
                    } else if (/[a-zA-Z]+/.test(va3)) {
                        va4 = "'" + va3 + "'";
                    } else {
                        va4 = va3;
                    }
                    // 附税的特殊表间校验，公式中除了附税表取值不处理，其余表的取值，若值为负数，将负数按0处理
                    if (checkType == "03" && /[0-9]/.test(va4) && va4 < 0 && va1.substring(0, va1.lastIndexOf("_")) != '11602') {
                        va4 = "0";
                    }
                    va4 = (va4 + "").replace(new RegExp(/,|，/g), ""); // 将值中的所有的逗号都替换为空
                }
            });
            lastPremise = lastPremise.replace(value, va4);

        }
    });
    var result = lastPremise;
    if (lastPremise.indexOf("$") >= 0) {
        result = getValue(result, lastPremise, checkType, sbsjMap);
    }

    return result;

}