/**
 * <p>
 *  消费税不定行表间校验，多批次的校验
 * </p>
 * @param formula，公式
 * @param sbsjMap，报表填写数据
 * @param jsonData
 * @param bz,true：条件校验，false：公式校验
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/5 10:44
 */
function xfsMultiLineBjjyCommon(formula, sbsjMap, jsonData, bz) {
    var sbsjMapJson = JSON.stringify(sbsjMap);
    var sbsjMap2 = JSON.parse(sbsjMapJson);
    var lastPremise = formula;
    var map = {};//第一个map，对比的主对象（里面只有一个key),  参数结构：Map<value,Map<zspmDm,sjResult>>
    var map1 = {};//第二个map，对比的辅对象(里面有多个key),参数结构：Map<value,Map<zspmDm,sjResult>>
    var countMap = {};// 参数结构：Map<zspmDm,sjResult>

    var reg = /(\$\{.*?\})/g; // 匹配${**}字符，最后一个g表示要全局匹配所有结果
    var result = formula.match(reg);  //返回符合的字体串数组

    var srt = {};// Map<zspmDm,sjResult>
    var srtZspmMc = {};// Map<zspmDm,zspmMc>

    // 遍历所有的${**}的值
    var pcDm = "";// 针对税种级别的多批次处理
    var mulva1 = null;
    var bbqc = [];// 报表全程
    $.each(result, function (index, value) {

        var srt1 = {};// Map<zspmDm,sjResult>
        var va = value.split(",");

        var va1 = va[0].replace("${", "");// 校验值报表代码取得
        //多批次报表类型，在校验的时候找对批次在定位取值
        if ('11303,11304,10427,10104,10413,10419,11503,11504,11505,11506,11508,29708,29709'.indexOf(va1.substring(0, 5)) >= 0 && pcDm == "") {
            var mulkey = getSbsjMapKey(Object.keys(sbsjMap), va1);
            // 证明没有va1这张表的填写数据，默认按0处理
            if (mulkey == '' || mulkey == "" || mulkey == null || mulkey == undefined) {
                lastPremise = lastPremise.replace(value, "0.00");
                return true;
            }
            var bb = mulkey.substring(0, mulkey.lastIndexOf("_")); // 没有报表批次的前缀
            var bbPc = mulkey.substring(mulkey.lastIndexOf("_") + 1); // 报表批次
            pcDm = "_" + bb.substring(bb.lastIndexOf("_") + 1) + "_" + bbPc; // 获取税种批次及报表批次
            mulva1 = va1.substring(0, 5);
        }
        // 单表多批次的处理：10414_048,及其控制的表
        if ("10414_048,10414_049,10414_050,10414_051,10414_052,10414_053,10414_054,10414_055,10414_056,10414_057,10414_058,10414_059,10414_060,10414_061".indexOf(va1.substring(0, 9)) >= 0 && pcDm == "") {
            var mulkey = getSbsjMapKey(Object.keys(sbsjMap), va1);
            // mulkey为空证明10414_048控制的子表没有填写，没有填写就不需要触发校验了，
            // 后续公式处理“${”符号的时候，会直接返回false，根据本方法的规则，不论最终结果返回什么都是返回true，所以不会让规则去弹出校验了
            if (mulkey == '' || mulkey == "" || mulkey == null || mulkey == undefined) {
                return false;
            }
            var bb = mulkey.substring(0, mulkey.lastIndexOf("_")); // 没有报表批次的前缀
            var bbPc = mulkey.substring(mulkey.lastIndexOf("_") + 1); // 报表批次
            pcDm = "_" + bb.substring(bb.lastIndexOf("_") + 1) + "_" + bbPc; // 获取税种批次及报表批次
            mulva1 = va1.substring(0, 9);
        }


        va1 = getPcKey(va1, pcDm, Object.keys(sbsjMap));
        // 报表数据是否有这张报表，没有赋个默认值
        if (JSON.stringify(Object.keys(sbsjMap)).indexOf(va1) < 0) {
            if (/[0-9]/.test(lastPremise)) {
                // 赋值"0.00"
                lastPremise = lastPremise.replace(value, "0.00");
            }
        } else {
            var va2 = va[1].replace("}", "");// 公式取值路径
            var va3 = va2.split("|");// 根据|分割，若lenth是2，则需要先匹配载比对，若是为1为直接比对
            var res = va3[0]; // 对比的值
            var sj = res.substring(res.lastIndexOf(".") + 1); // 比对的字段

            // 根据最后一个点切割
            var res1 = res.indexOf(".") >= 0 ? res.substring(0, res.lastIndexOf(".")) : res; // 比对字段所在的list位置
            // 获取sbsjMap包含va1的key值
            var key = getSbsjMapKey(Object.keys(sbsjMap), va1);
            var data = sbsjMap[key];
            var list = strToFun(res1, data);// 取得list数组
            if (list != null && list.length != 0) {
                var compareVa = null;
                if (va3.length >= 2) {
                    compareVa = va3[1]; // 匹配的字段
                }

                srt1 = {};
                // 如果匹配字段不为空
                if (compareVa != null) {
                    $.each(list, function (i, da) {
                        var zspmDm;
                        var sjResult = strToFun(res1 + "[" + i + "]." + sj, data);// 校验值取得
                        if (sjResult == null) {
                            sjResult = 0.00;
                        } else if (/[a-zA-Z]+/.test(sjResult)) {
                            sjResult = "'" + sjResult + "'";
                        }
                        zspmDm = strToFun(res1 + "[" + i + "]." + compareVa, data);// 校验值取得
                        if (zspmDm != null && zspmDm != "") {
                            // 20200515 by Ldy 因为消费税的zspm类的校验需要拼装zspmMc了，所以做此调整
                            var zspmMc = strToFun(res1 + "[" + i + "].zspmMc", data);// 校验值取得

                            if (Object.keys(map).length == 0) {
                                srt[zspmDm] = sjResult;
                                srtZspmMc[zspmDm] = zspmMc + "_" + i;
                                countMap[zspmDm] = sjResult;
                            } else {
                                srt1[zspmDm] = sjResult;
                                if (srt[zspmDm] != null && srt[zspmDm] != undefined) {
                                    delete countMap[zspmDm];
                                } else {
                                    countMap[zspmDm] = sjResult;
                                }
                            }
                        }
                    });
                    if (Object.keys(map).length == 0) {
                        map[value] = srt;

                    }
                    if (srt1 != null && Object.keys(srt1).length > 0) {
                        map1[value] = srt1;
                    }
                } else {
                    var va4 = strToFun(res, data);// 校验值取得
                    if (va4 == null) {
                        va4 = 0.00;
                    } else if (/[a-zA-Z]+/.test(va4)) {
                        va4 = "'" + va4 + "'";
                    }
                    lastPremise = lastPremise.replace(value, va4);
                }
            } else {
                // 如果第一个数据是空，则继续插入值
                if (Object.keys(map).length == 0) {
                    map[value] = null;
                }
                lastPremise = lastPremise.replace(value, "0.00");
            }

        }
        if (pcDm != null && pcDm != "") {
            bbqc.push(va1);
        }
    });
    if (mulva1 != null && mulva1 != "" && mulva1 != undefined) {
        if (bbqc != null && bbqc.length > 0) {
            $.each(bbqc, function (i, d) {
                delete sbsjMap2[d]; // 取完第一个批次 然后删除掉这份批次的数据
            });
        }

        compareMap(lastPremise, map, map1, jsonData, bz, srtZspmMc, pcDm); // 不能有条件校验
        if (JSON.stringify(Object.keys(sbsjMap2)).indexOf(mulva1 + pcDm) >= 0) {
            xfsMultiLineBjjyCommon(formula, sbsjMap2, jsonData, bz);
        }
        return true;
    } else {
        if (lastPremise.indexOf("${") >= 0 && (map == null || Object.keys(map).length == 0) && (map1 == null || Object.keys(map1).length == 0)) {
            // 走到这个方法应该是非多行校验，【目前的其他规则是：多批次】
            // 识别到"${"这个符号后，按照正常规则的方式处理，有"${"这个符号代表没有填写这张表，需要弹出校验。
            return true;
        }
        var ba = compareMap(lastPremise, map, map1, jsonData, bz, srtZspmMc);
        // 条件校验
        if (bz) {
            return ba;
        } else {
            // 公式校验
            if (!ba) {
                ba = true; //  当公式结果返回的是false时，将直接返回true以防整个返回结果增加一条重发校验。
            }
            return ba;
        }
    }
}

/**
 * <p>
 *判断keys中是否包含va1，若包含返回具体的key
 * </p>
 * @param keys
 * @param va1
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/9 14:28
 */
function getSbsjMapKey(keys, va1) {
    if (keys == null || keys.length == 0) {
        return "";
    }
    var key = Enumerable.From(keys).Where(function (k) {
        return k.indexOf(va1) >= 0
    }).ToArray();
    if (key == null || key == "" || key == undefined || key.length == 0) {
        return "";
    } else {
        return typeof key == 'String' ? key : key[0];
    }
}

function getPcKey(va1, pcDm, keys) {
    var result = null;
    if (keys == null || keys.length == 0) {
        return "";
    }
    var key = Enumerable.From(keys).Where(function (k) {
        return k.indexOf(va1) >= 0
    }).ToArray();

    $.each(key, function (i, d) {
        if (d.indexOf(pcDm) >= 0) {
            result = d;
            return false;
        }
    });

    return result;
}

/**
 * <p>
 *不定行Map中的value值之间的对比
 * </p>
 * @param lastPremise ,公式
 * @param map，对比的主对象
 * @param compareMap ，需要对比的对象
 * @param jsonData
 * @param bz
 * @param MapZspmMc, 主对象对应的zspmMc
 * @param pcDm, 批次代码
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/9 21:34
 */
function compareMap(lastPremise, map, compareMap, jsonData, bz, MapZspmMc, pcDm) {
    var result = lastPremise;

    // 根据年报来区分使用map还是list
    var resultMap = {};

    if (map != null && Object.keys(map).length > 0 && map[Object.keys(map)[0]] != null) {
        var objKey = Object.keys(map)[0];
        var obj = map[objKey];
        if (obj == null || obj == undefined) {
            return true;
        }
        $.each(obj, function (zspmKey, se) {
            lastPremise = lastPremise.replace(objKey, se);
            // 20200930 添加判断长度
            if (compareMap != null && Object.keys(compareMap).length > 0) {
                $.each(compareMap, function (premise, map) {
                    var value = map[zspmKey];
                    if (value == null || value == '' || value == undefined) {
                        value = "0.00";
                    }
                    // 正则匹配前，处理一下这个字符串是否有特殊字符
                    premise = regExpSpecialStr(premise);
                    lastPremise = lastPremise.replace(new RegExp(premise, 'g'), value);
                });
            }
            // 征收品目名称
            var zspmMc = getZspmMcBykey(zspmKey, MapZspmMc);
            resultMap[zspmMc] = lastPremise;

            lastPremise = result;
        });
        return countResult(resultMap, bz, jsonData, pcDm);
    } else {
        // 走到这块证明没有需要比对的数据，则直接校验公式结果
        resultMap = [];
        resultMap.push(lastPremise);
        return countResult(resultMap, bz, jsonData, pcDm);
    }
}

/**
 * <p>
 *将特殊字符转义一下，目前只有$,{,},|这几个特殊字符，若以后还有在维护
 * </p>
 * @param null
 * @return
 * @throws
 * @author DyLuo
 * @date 2021/4/26 13:55
 */
function regExpSpecialStr(str) {
    return str.replace("$", "\\$").replace("{", "\\{").replace("}", "\\}").replace("|", "\\|");


}

/**
 *获取征收项目名称
 * @param zspmKey
 * @param MapZspmMc
 */
function getZspmMcBykey(zspmKey, MapZspmMc) {
    var zspmMc = null;
    $.each(MapZspmMc, function (key, value) {
        if (key == zspmKey) {
            zspmMc = value;
            return false;
        }
    });
    return zspmMc;
}

/**
 * <p>
 *计算最终结果
 * </p>
 * @param obj
 * @param bz
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/5/15 11:43
 */
function countResult(obj, bz, jsonData, pcDm) {
    var tipValue = jsonData.tip;
    var ba = false;
    $.each(obj, function (zspmMc, da) {
        var tip = tipValue;
        try {
            if (da.indexOf("${") >= 0) {
                ba = false;
            } else {
                var regString = /[a-zA-Z]+/; //验证大小写26个字母任意字母最少出现1次。
                if ((regString.test(da) || CheckChinese(da)) && (regString.test(da) && (!/[0-9]/.test(da)))) {
                    ba = campareChinese(da);
                } else {
                    var re = formulaCount(da); // 浮点数做判断
                    ba = eval(re);
                }
            }
        } catch (e) {
            console.log("计算公式异常:" + e)
        }
        // bz 是flase是公式校验
        if (!bz && (!ba)) {
            var mc = null;
            zspmMc = zspmMc.toString();
            if (zspmMc.indexOf("_") >= 0) {
                mc = zspmMc.substring(zspmMc.indexOf("_") + 1);// 征收品目名称所有的list下标
            }
            var newPcDm = null;
            if (pcDm != null && pcDm != "" && pcDm != undefined) {
                // newPcDm = pcDm.substring(1, pcDm.lastIndexOf("_"));// 不要前面的"_"
                newPcDm = pcDm.substring(1);// 不要前面的"_"
                tip = tip.replace("$pcDm", newPcDm);
            }
            tip = tip.replace(/\${mcList}/g, zspmMc.substring(0, zspmMc.indexOf("_")));
            var final = {
                "id": jsonData.id,
                "zsxmDm": jsonData.zsxmDm,
                "bblxDm": jsonData.bblxDm,
                "bbDm": jsonData.bbDm,
                "version": jsonData.versionNumber,
                "tip": tip,
                "flag": jsonData.flag,
                "targetCellId": jsonData.targetCellId,
                "zspmList": mc,
                "pcDm": newPcDm,
                "bbMc": jsonData.bbMc,
                "shbz": jsonData.shbz,
                "shsmbz": jsonData.shsmbz

            };
            bjjyResultList.push(final);
        }
    });
    return ba;
}

/**
 * <p>
 *所得税年报表间校验处理
 * </p>
 * @param formula
 * @param sbsjMap
 * @param jsonData
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/11 14:37
 */
function sdsNbMultiLineBjjyCommon(formula, sbsjMap, jsonData) {
    var lastPremise = formula;
    var reg = /(\$\{.*?\})/g; // 匹配${**}字符，最后一个g表示要全局匹配所有结果
    var result = formula.match(reg);  //返回符合的字体串数组
    var bbmcPath = [];
    var srt1 = {};// Map<name,List> 多个key
    var mcPath = null;
    var srt = {};// Map<name,List> 只有一个key
    // 遍历所有的${**}的值
    $.each(result, function (index, value) {

        var va = value.split(",");
        var va1 = va[0].replace("${", "");// 校验值报表代码取得

        // 报表数据是否有这张报表，没有赋个默认值
        if (JSON.stringify(Object.keys(sbsjMap)).indexOf(va1) < 0) {
            if (/[0-9]/.test(lastPremise)) {
                // 赋值"0.00"
                lastPremise = lastPremise.replace(value, "0.00");
            }
        } else {
            var va2 = va[1].replace("}", "");// 公式取值路径
            var va3 = va2.split("|");// 根据|分割，若lenth是2，则需要先匹配载比对，若是为1为直接比对
            var res = va3[0]; // 比对字段所在的map位置 结构如下：map{"compareVa":["key是匹配字段,value是list<String>对象"],"bbMc":"报表名称"}

            var arr = [];
            // 获取sbsjMap包含va1的key值
            $.each(sbsjMap, function (i, data) {
                if (i.toString().indexOf(va1) >= 0) {
                    var bbMc = null;
                    var list = strToFun(res, data);// 获取map结构数据
                    // 如果匹配字段不为空
                    if (va3.length >= 2) {
                        list = strToFun(res + "." + va3[1], data);// 获取list结构数据
                        bbMc = strToFun(res + ".bbmc", data);// 取的需要拼装的bbMc
                        if (bbMc != null && bbMc != undefined) {
                            mcPath = mcPathByMc(list); // 单表对比的时候使用,注意注意注意，单表单表单表
                        }
                    }

                    if (Object.keys(srt).length == 0) { //非多批次主体
                        if (bbMc != null && bbMc != undefined) {
                            srt[bbMc] = list;
                            bbmcPath.push(va1.substring(va1.lastIndexOf("_") + 1))

                        } else if (va1.indexOf("10420_005") >= 0) {
                            //如果报表是10420——005这张表，则默认设置一个bbmc，因为这张表的结构没有bbmc
                            bbMc = "G101000关联关系表";
                            srt[bbMc] = list;
                        }
                    } else if (bbMc != null && bbMc != undefined) { //比较辅体 srt1是个map，多个key值的被比较数据
                        if (srt1[bbMc] != null && srt1[bbMc].length > 0) {
                            list.push(srt1[bbMc]);
                        }
                        srt1[bbMc] = list;
                        bbmcPath.push(va1.substring(va1.lastIndexOf("_") + 1))
                    } else {
                        //比较多批次辅体
                        arr.push(list);
                    }
                }
            });
            if (arr.length > 0) {
                srt1['001'] = arr; //设置默认批次，此方法不对比批次号，对比的是所有批次中的值
            }
        }
    });
    // 比对
    var ba = compareList(lastPremise, srt, srt1, jsonData, bbmcPath, mcPath);
    return ba;
}

/**
 * <p>
 *将list中的对象路径用map对象来存储,map{"mc":"mcPath"}
 * </p>
 * @param list
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/28 10:54
 */
function mcPathByMc(list) {
    var map = {};
    if (list != null) {
        $.each(list, function (key, value) {
            map[value] = key;
        });
    }
    return map;
}


/**
 * <p>
 *不定行List之间的对比。tip拼装
 * </p>
 * @param lastPremise
 * @param map
 * @param compareMap
 * @param jsonData
 * @param bbmcPath
 * @param mcPath
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/12 9:11
 */
function compareList(lastPremise, map, compareMap, jsonData, bbmcPath, mcPath) {
    var tip = jsonData.tip;
    var bbmcList = [];
    var mcList = [];
    // 若有一个数组为空时，则不去进行以下校验。
    if (Object.keys(map).length > 0 && Object.keys(compareMap).length > 0) {
        var objKey = Object.keys(map)[0];
        var obj = map[objKey]; //list对象
        var arrRes = null;
        $.each(compareMap, function (key, value) {
            var list1 = value;
            if (tip.indexOf("$bbmcList") >= 0) {
                list1 = obj;
            }

            // 求出并集
            var unionRes = Enumerable.From(obj).Union(value).ToArray();
            // 求出list1不包含并集结果中的那些，则求list1和unionRes差集
            var list2 = unionRes;
            if (list1.length < unionRes.length) {
                list2 = list1;
                list1 = unionRes;
            }

            arrRes = Enumerable.From(list1).Except(list2).ToArray();
            if (arrRes != null && arrRes != undefined && arrRes.length > 0) {
                bbmcList.push(key);
            }

        });
// 拼接有两种：
        // 第一种：当有不一样的内容出现（arrRes）并且需要比对的参数是一个（compareMap），只拼装不一样的内容.
        if (arrRes != null && arrRes != undefined && arrRes.length > 0 && tip.indexOf("$mcList") >= 0) {
            mcList = selPathByValue(arrRes, mcPath);
            if (mcList == null || mcList == "" || mcList == undefined || mcList == "undefined") {// 如果mcPath没有这个值的路径，则置为空。
                mcList = [];
            }
            tip = tip.replace("$mcList", arrRes.join(','));
            jsonData.tip = tip;
            jsonData.mcList = mcList.join(',');// 对比的内容路径

            bjjyResultList.push(jsonData);
        } else if (bbmcList != null && bbmcList != undefined && bbmcList.length > 0 && tip.indexOf("$bbmcList") >= 0) {
            //     第二种：当有不一样的内容出现（arrRes）并且需要比对的参数是多个（compareMap），只拼装bbMC
            tip = tip.replace("$bbmcList", bbmcList.join(','));
            jsonData.tip = tip;
            jsonData.bbmcList = bbmcPath.join(','); // 报表的名称
            bjjyResultList.push(jsonData);
        }
    }
    return true;
}

/**
 * <p>
 * 根据mc查询mc所在的下标
 * </p>
 * @param arrRes
 * @param mcPath
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/28 11:00
 */
function selPathByValue(arrRes, mcPath) {
    var list = [];
    $.each(arrRes, function (key, value) {
        list.push(mcPath[value]);
    });
    return list;
}

/**
 * <p>
 *不定行条件必报校验处理
 * </p>
 * @param formula
 * @param sbsjMap
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/19 9:34
 */
function MultiLine(formula, sbsjMap) {
    var lastPremise = formula;
    var reg = /(\$\{.*?\})/g; // 匹配${**}字符，最后一个g表示要全局匹配所有结果
    var result = formula.match(reg);  //返回符合的字体串数组

    // 遍历所有的${**}的值
    $.each(result, function (index, value) {
        var va = value.split(",");
        var va1 = va[0].replace("${", "");// 校验值报表代码取得

        // 报表数据是否有这张报表，没有赋个默认值
        if (JSON.stringify(Object.keys(sbsjMap)).indexOf(va1) < 0) {
            if (/[0-9]/.test(lastPremise)) {
                // 赋值"0.00"
                lastPremise = lastPremise.replace(value, "0.00");
            }
        } else {
            var va2 = va[1].replace("}", "");// 公式取值路径
            var va3 = va2.split("|");// 根据|分割，若lenth是2，则需要先匹配载比对，若是为1为直接比对
            var res = va3[0]; // 比对字段所在的list位置 结构如下：
            if (va3.length >= 2) {
                var res1 = va3[1];
                // 获取sbsjMap包含va1的key值
                $.each(sbsjMap, function (i, data) {
                    var endRes = null;
                    var oneValue = "";
                    if (i.toString().indexOf(va1) >= 0) {
                        var list = strToFun(res, data);// 获取对的list数据
                        if (list != null && list != "" && list != undefined && list != "undefined") {
                            $.each(list, function (ii, da) {
                                endRes = strToFun(res + "[" + ii + "]." + res1, data) + "";// 获取对的list数据
                                if (endRes != null && endRes != "" && endRes != undefined && endRes != "undefined") {
                                    if (endRes === "1") {
                                        oneValue = endRes;
                                        return false; // 跳出循环 有一个这个字段是有值的，则跳出循环，因为这种情况的校验，电子申报只弹出一个校验。
                                    }

                                }
                            });
                        }
                        if (oneValue != "") {
                            lastPremise = lastPremise.replace(value, oneValue);
                            return false; // 跳出循环
                        } else {
                            lastPremise = lastPremise.replace(value, "0");

                        }

                    }
                });
            }
        }
    });
    var ba = false;
    var regString = /[a-zA-Z]+/; //验证大小写26个字母任意字母最少出现1次。
    if (regString.test(lastPremise) && (!/[0-9]/.test(lastPremise))) {
        ba = eval(lastPremise);
    } else {
        var re = formulaCount(lastPremise); // 其余类型做判断
        ba = eval(re);
    }
    return ba;
}

/**
 * <p>
 *多批次对比
 * </p>
 * @param formula
 * @param sbsjMap
 * @param jsonData
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/27 17:15
 */
function multiPatchMultiLineBjjyCommon(formula, sbsjMap, jsonData) {
    var lastPremise = formula;
    var reg = /(\$\{.*?\})/g; // 匹配${**}字符，最后一个g表示要全局匹配所有结果
    var result = formula.match(reg);  //返回符合的字体串数组
    var srt1 = {};// Map<name,List> 多个key
    var srt = {};// Map<name,List> 只有一个key
    // 遍历所有的${**}的值
    $.each(result, function (index, value) {

        var va = value.split(",");
        var va1 = va[0].replace("${", "");// 校验值报表代码取得

        // 报表数据是否有这张报表，没有赋个默认值
        if (JSON.stringify(Object.keys(sbsjMap)).indexOf(va1) < 0) {
            if (/[0-9]/.test(lastPremise)) {
                // 赋值"0.00"
                lastPremise = lastPremise.replace(value, "0.00");
            }
        } else {
            var va2 = va[1].replace("}", "");// 公式取值路径
            var va3 = va2.split("|");// 根据|分割，若lenth是2，则需要先匹配载比对，若是为1为直接比对
            var res = va3[0]; // 比对字段所在的map位置 结构如下：map{"compareVa":["key是匹配字段,value是list<String>对象"],"bbMc":"报表名称"}

            // 获取sbsjMap包含va1的key值
            $.each(sbsjMap, function (i, data) {
                if (i.toString().indexOf(va1) >= 0) {
                    var pdDm = i.substring(i.lastIndexOf("_") + 1); // 获取报表批次号 若多批次号取值顺序有变化，请联系赵乐昌。

                    var list = strToFun(res, data);// 获取map结构数据
                    var bbMc = null;
                    // 如果匹配字段不为空
                    if (va3.length >= 2) {
                        list = strToFun(res + "." + va3[1], data);// 获取list结构数据
                        bbMc = strToFun(res + ".bbmc", data);// 取的需要拼装的bbMc
                    }
                    if (bbMc == null || bbMc == "" || bbMc == undefined) { //多批次主体
                        srt[pdDm] = list;
                    } else {
                        // 非多批次
                        srt1[va1] = list;
                    }

                }
            });
        }
    });
    // 比对
    var ba = multiPatchCompareList(srt, srt1, jsonData);
    return ba;
}

/**
 * <p>
 *多批次比较非多批次的多组数据
 * </p>
 * @param map
 * @param compareMap
 * @param jsonData
 * @return
 * @throws
 * @author DyLuo
 * @date 2019/12/27 17:25
 */
function multiPatchCompareList(map, compareMap, jsonData) {
    var commonTip = jsonData.tip;
    var res = [];
    $.each(map, function (key1, value1) {
        var tip = commonTip;
        // key:批次号，value：当前批次有的字符串
        $.each(compareMap, function (key, value) {
            // value,是多张表中需要比对的list
            if (JSON.stringify(value).indexOf(value1) > 0) {
                //  如果他包含，则跳出当前循环
                res.push("false");
            } else {
                res.push("true");
            }

        });
        var br = res.join("&&");
        if (eval(br)) {
            tip = tip.replace("$pcDm", key1);
            tip = tip.replace("$mcList", value1);
            // 因为循环一直在用一个tip，所以直接new一个新对象然后在push进去
            var final = {
                "id": jsonData.id,
                "zsxmDm": jsonData.zsxmDm,
                "bblxDm": jsonData.bblxDm,
                "bbDm": jsonData.bbDm,
                "version": jsonData.versionNumber,
                "tip": tip,
                "flag": jsonData.flag,
                "targetCellId": jsonData.targetCellId,
                "pcDm": key1,
                "bbMc": jsonData.bbMc,
                "shbz": jsonData.shbz,
                "shsmbz": jsonData.shsmbz

            };
            bjjyResultList.push(final);
        }
    });
    return true;
}

function sdsTwoListBjjyCommon(formula, sbsjMap, jsonData) {
    var lastPremise = formula;
    var reg = /(\$\{.*?\})/g; // 匹配${**}字符，最后一个g表示要全局匹配所有结果
    var result = formula.match(reg);  //返回符合的字体串数组
    var srt = []; //第一个list
    var srt1 = [];// 第2个list
    var list1Path = {};

    // 遍历所有的${**}的值
    $.each(result, function (index, value) {

        var va = value.split(",");
        var va1 = va[0].replace("${", "");// 校验值报表代码取得

        // 报表数据是否有这张报表，没有赋个默认值
        if (JSON.stringify(Object.keys(sbsjMap)).indexOf(va1) < 0) {
            if (/[0-9]/.test(lastPremise)) {
                // 赋值"0.00"
                lastPremise = lastPremise.replace(value, "0.00");
            }
        } else {
            var va2 = va[1].replace("}", "");// 公式取值路径
            var va3 = va2.split("|");// 根据|分割，若lenth是2，则需要先匹配载比对，若是为1为直接比对
            var res = va3[0]; // 比对字段所在的map位置 结构如下：map{"compareVa":["key是匹配字段,value是list<String>对象"],"bbMc":"报表名称"}

            // 获取sbsjMap包含va1的key值
            var key = getSbsjMapKey(Object.keys(sbsjMap), va1);
            var data = sbsjMap[key];
            var list = strToFun(res + "." + va3[1], data);// 获取list结构数据
            var mcPath = mcPathByMc(list); // 单表对比的时候使用,注意注意注意，单表单表单表

            if (srt.length == 0) { //第一个list
                srt = list;
                list1Path = mcPath;
            } else {
                srt1 = list; // 第二个list

            }
        }
    });
    // 比对
    var ba = twoListcompare(lastPremise, srt, srt1, jsonData, list1Path);
    return ba;
}

/**
 * 兩個list之間對比的校驗
 * @param lastPremise
 * @param srt
 * @param srt1
 * @param jsonData
 * @param list1Path
 * @returns {boolean}
 */
function twoListcompare(lastPremise, srt, srt1, jsonData, list1Path) {
    if (srt.length > 0 && srt1.length > 0) {
        var list1 = srt1;
        // 兩個list的交集
        var unionRes = Enumerable.From(srt).Union(srt1).ToArray();
        var list2 = unionRes;
        if (list1.length < unionRes.length) {
            list2 = list1;
            list1 = unionRes;
        }
        // 然後交集和第一list的差集，查出他和第一list不同的值
        var arrRes = Enumerable.From(list1).Except(list2).ToArray();
        // 如果有差集，则证明有不同，需要弹出校验
        if (arrRes != null && arrRes != undefined && arrRes.length > 0) {
            var tip = jsonData.tip;
            // 根据这个值来找对应的所知json位置
            var mcList = selPathByValue(arrRes, list1Path);
            if (mcList == null || mcList == "" || mcList == undefined || mcList == "undefined") {// 如果mcPath没有这个值的路径，则置为空。
                mcList = [];
            }
            tip = tip.replace("$mcList", arrRes.join(','));
            jsonData.tip = tip;
            jsonData.mcList = mcList.join(',');// 对比的内容路径
            bjjyResultList.push(jsonData);
        }
    }
    return true;
}

/**
 * <p>
 *涉税平台多行处理，（处理附税，处理多行求和）
 * </p>
 * @param jsonData
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/6/22 10:27
 */
function ssfwptMultiLine(jsonData, bbsj, hznsqy) {
    // 进行读取公式，计算公式结果
    var lastPremise = jsonData.formula;
    var reg = /(\$\{.*?\})/g; // 匹配${**}字符，最后一个g表示要全局匹配所有结果
    var result = jsonData.formula.match(reg);  //返回符合的字体串数组
    var srt = {};// Map<zspmDm,sjResult>
    var map = {};// Map<value,Map<zspmDm,sjResult>>
    var bblxBz = "";
    // 遍历所有的${**}的值
    $.each(result, function (index, value) {
        var va = value.split(",");
        var va1 = va[0].replace("${", "");// 校验值报表代码取得

        // 如果是增值税，则赋值，反之是消费税，则赋值消费税标识
        if (bblxBz == "" && va1.substring(0, 3) == "101") {
            bblxBz = "101";
        } else if (bblxBz == "" && va1.substring(0, 3) == "103") {
            bblxBz = "103";
        }

        // 报表数据是否有这张报表，没有赋个默认值
        if (JSON.stringify(Object.keys(bbsj)).indexOf(va1) < 0) {
            if (/[0-9]/.test(lastPremise)) {
                // 赋值"0.00"
                lastPremise = lastPremise.replace(value, "0.00");
            }
        } else {
            // 获取sbsjMap包含va1的key值,并直接获取这张报表的数据
            var key = getSbsjMapKey(Object.keys(bbsj), va1);
            if (key == "" || key == undefined || key == null) {
                return true; // 跳出当前循环
            }

            var data = bbsj[key];
            var va2 = va[1].replace("}", "");// 公式取值路径
            //  取多行值
            if (va2.indexOf("_") < 0) {
                var va3 = va2.split("|");// 根据|分割，若lenth是2，则需要先匹配载比对，若是为1为直接比对
                var res = va3[0]; // 对比的值
                var sj = res.substring(res.lastIndexOf(".") + 1); // 比对的字段

                // 根据最后一个点切割
                var res1 = res.substring(0, res.lastIndexOf(".")); // 比对字段所在的list位置
                var list = strToFun(res1, data);// 取得list数组
                if (list != null && list.length != 0) {
                    var compareVa = null;
                    if (va3.length >= 2) {
                        compareVa = va3[1]; // 匹配的字段
                    }

                    // 如果匹配字段不为空
                    if (compareVa != null) {
                        $.each(list, function (i, da) {
                            var zspmDm;
                            var sjResult = strToFun(res1 + "[" + i + "]." + sj, data);// 校验值取得
                            zspmDm = strToFun(res1 + "[" + i + "]." + compareVa, data);// 校验值取得
                            if (zspmDm != null && zspmDm != "") {
                                // 如果有这个zspm代码
                                if (JSON.stringify(Object.keys(srt)).indexOf(zspmDm) >= 0) {
                                    var ss = srt[zspmDm];
                                    sjResult = sjResult + "+" + ss;
                                }
                                srt[zspmDm] = sjResult;
                            }
                        });
                        map[value] = srt;
                    } else {
                        var va4 = strToFun(res, data);// 校验值取得
                        if (va4 == null) {
                            va4 = 0.00;
                        } else if (/[a-zA-Z]+/.test(va4)) {
                            va4 = "'" + va4 + "'";
                        }
                        lastPremise = lastPremise.replace(value, va4);
                    }
                }
            } else {
                // 取总和
                var val = va2.split("_");
                var listResult = val[0];// list所在位置
                var paramResult = val[1]; // 要求和的参数
                var sjResult = strToFun(listResult, data);// 校验值取得
                var formula = "";
                $.each(sjResult, function (i, da) {
                    var sj = strToFun(paramResult, da);// 校验值取得
                    formula = sj + "+" + formula;
                });

                var sumResult = fourArithmeticOperations(formula, 10);
                lastPremise = lastPremise.replace(value, sumResult);

            }
        }
    });

    return ssfwptMultiLineResult(lastPremise, map, jsonData, bblxBz, hznsqy);
}

/**
 * <p>
 * 涉税平台的税种间校验，附税特殊处理
 * </p>
 * @param lastPremise
 * @param map
 * @param jsonData
 * @return
 * @throws
 * @author DyLuo
 * @date 2020/6/22 10:17
 */
function ssfwptMultiLineResult(lastPremise, map, jsonData, bblxBz, hznsqy) {
    var objKey = Object.keys(map)[0];
    var obj = map[objKey]; //map对象
    var finalFormula = lastPremise;
    $.each(obj, function (zspmDm, value) {
        var tip = "";
        if (bblxBz != "") {
            if (bblxBz == "101" && hznsqy == "N") {
                switch (zspmDm) {
                    case "101090101":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》增值税-城建税（市区）第1列应≥《增值税纳税申报表(适用于一般纳税人)》应补退税额、《增值税纳税申报表（适用于小规模）》应补退税额、《原油天然气增值税申报表》应补退税额、《增值税预缴税款表》预征税额的合计数!!";
                        break;
                    case "302030100":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》增值税-教育费附加第1列应≥《增值税纳税申报表(适用于一般纳税人)》应补退税额、《增值税纳税申报表（适用于小规模）》应补退税额、《原油天然气增值税申报表》应补退税额、《增值税预缴税款表》预征税额的合计数!!";
                        break;
                    case "302160100":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》增值税-地方教育附加第1列应≥《增值税纳税申报表(适用于一般纳税人)》应补退税额、《增值税纳税申报表（适用于小规模）》应补退税额、《原油天然气增值税申报表》应补退税额、《增值税预缴税款表》预征税额的合计数!!";
                        break;
                }
            } else if (bblxBz == "101" && hznsqy == "Y") {
                switch (zspmDm) {
                    case "101090101":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》增值税-城建税（市区）第1列应 大于等于《汇总纳税企业增值分配表》该企业的分配额、《增值税预缴税款表》预征税额的合计数!!";
                        break;
                    case "302030100":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》增值税-教育费附加第1列应 大于等于《汇总纳税企业增值分配表》该企业的分配额、《增值税预缴税款表》预征税额的合计数!!";
                        break;
                    case "302160100":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》增值税-地方教育附加第1列应 大于等于《汇总纳税企业增值分配表》该企业的分配额、《增值税预缴税款表》预征税额的合计数!!";
                        break;
                }
            } else if (bblxBz == "103") {
                switch (zspmDm) {
                    case "101090103":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》消费税-城建税第3列应≥烟类、酒类、成品油类、小汽车类、其他类、卷烟（批发）类、电池类、涂料类的《消费税纳税申报表》应补退税额的合计!!";
                        break;
                    case "302030300":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》消费税-教育费附加第3列应≥烟类、酒类、成品油类、小汽车类、其他类、卷烟（批发）类、电池类、涂料类的《消费税纳税申报表》应补退税额的合计!!";
                        break;
                    case "302160300":
                        tip = "《城建税、教育费附加、地方教育附加税（费）》消费税-地方教育附加第3列应≥烟类、酒类、成品油类、小汽车类、其他类、卷烟（批发）类、电池类、涂料类的《消费税纳税申报表》应补退税额的合计!!";
                        break;
                }
            }
            lastPremise = lastPremise.replace(objKey, value);
            var re = formulaCount(lastPremise, jsonData.checkType)
            if (!eval(re) && tip != "") {
                var final = {
                    "id": jsonData.id,
                    "zsxmDm": jsonData.zsxmDm,
                    "bblxDm": jsonData.bblxDm,
                    "bbDm": jsonData.bbDm,
                    "version": jsonData.versionNumber,
                    "tip": tip,
                    "flag": jsonData.flag,
                    "targetCellId": jsonData.targetCellId,
                    "bbMc": jsonData.bbMc,
                    "shbz": jsonData.shbz
                };
                tax.push(final);
            }
            lastPremise = finalFormula;
        }
    });
    return false;
}