// 工具方法

if (!window.FUtil) {
    window.FUtil = {};
}
$.extend(window.FUtil, {
    /**
     * 获取数组中指定属性的最大值
     * @param {Array} arr 数组
     * @param {String} key 指定属性
     * @returns {Number} 最大数值
     * @example [{key:166},{key:200},{key:33}]=>getMax(arr,'key);=>200
     */
    getMax: function (arr, key) {
        var max = 0,
            len = arr.length;
        for (var i = 0; i < len; i++) {
            var item = arr[i][key];
            if (max < item) max = item;
        }
        return max;
    },
    /**
     * 获取数组中指定属性的最小值
     * @param {Array} arr 数组
     * @param {String} key 指定属性
     * @returns {Number} 最小值
     * @example [{key:166},{key:200},{key:33}]=>getMax(arr,'key);=>33
     */
    getMin: function (arr, key) {
        if (arr.length === 0) return;
        var min = arr[0][key],
            len = arr.length;
        for (var i = 1; i < len; i++) {
            var item = arr[i][key];
            if (min > item) min = item;
        }
        return min;
    },
    /**
     * 获取数组指定属性的和
     * @param {Array} arr 数组
     * @param {String} key 指定属性
     * @returns {Number} 和
     * @example [{key:166},{key:200},{key:33}]=>getSum(arr,'key);=>399
     */
    getSum: function (arr, key) {
        var sum = 0,
            len = arr.length;
        for (var i = 0; i < len; i++) {
            sum += arr[i][key];
        }
        return sum;
    },
    /**
     * 获取数组中指定属性的数组
     * @param {Array} arr 源数组
     * @param {String} key 指定属性
     * @returns {Array} 目标数组
     * @example [{key:166},{key:200},{key:33}]=>getValArr(arr,'key);=>[166,200,33]
     */
    getValArr: function (arr, key) {
        var val = [],
            len = arr.length;
        for (var i = 0; i < len; i++) {
            val.push(arr[i][key]);
        }
        return val;
    },
    /**
     * 快速渲染数字及文本
     * @param {String} space 命名空间
     * @param {Object} data 数据
     * @param {Function} filterFn 过滤函数，处理渲染结果，比如加单位
     */
    renderNum: function (space, data, filterFn) {
        for (var i in data) {
            if (Object.prototype.hasOwnProperty.call(data, i)) {
                var $dom = $('#' + space + '-' + i);
                if ($dom.length > 0) {
                    $dom.text(filterFn ? filterFn(data[i]) : data[i]);
                }
            }
        }
    },
    /**
     * 获取百分比
     * @param {Number} max 总数
     * @param {Number} data 数据
     * @param {Number} fixed 精确到小数点位数，可不传，默认为0
     * @param {Number} unit 配置单位，可不传，默认%，不要百分号传""
     */
    getPercent: function (max, data, fixed, unit) {
        var _fixed = fixed || 0,
            unit = unit == "" ? "" : (unit || '%');
        return max == 0 ? percent = 0 + unit : (data / max * 100).toFixed(_fixed) + unit;
    },
    /**
     * 图表自动切换展示tooltip
     * @param {Object} chart 图表实例
     * @param {Number} length 图表数据量
     * @param {Number} interval 切换间隔，单位ms
     */
    showTooltip: function (chart, length, interval) {
        chart.dataLength = length;
        chart.currentIndex = 0;
        clearInterval(chart.timer);
        chart.interval = interval || 3000;
        chart.timer = setInterval(function () {
            if (chart.currentIndex === chart.dataLength) {
                chart.currentIndex = 0;
            }
            chart.dispatchAction({
                type: 'showTip',
                seriesIndex: 0,
                dataIndex: chart.currentIndex
            });
            chart.currentIndex++;
        }, chart.interval);
    },
    // 鼠标悬浮到图表，停止showTooltip
    chartHover: function (chart, length, interval) {
        chart.on('mouseover', function () {
            clearInterval(chart.timer);
        });
        chart.on('mouseout', function () {
            FUtil.showTooltip(chart, length, interval);
        });
    },
    // 数字千分位转换
    addCommas: function (n) {
        if (isNaN(n)) {
            return '-';
        }
        n = (n + '').split('.');
        return n[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') +
            (n.length > 1 ? ('.' + n[1]) : '');
    },
    // 生成随机数
    randNum: function (m, n) {
        if (!n) {
            return Math.floor(Math.random() * m);
        } else {
            var c = n - m + 1;
            return Math.floor(Math.random() * c + m);
        }
    },
    // echarts自适应
    echartsResize: function () {
        var echartsResizeTimer = null;
        return function () {
            $(window).on('resize', function () {
                // 获取所有echarts容器的jQuery对象
                var $echarts = $('[_echarts_instance_]');
                if (echartsResizeTimer) clearTimeout(echartsResizeTimer);
                echartsResizeTimer = setTimeout(function () {
                    $.each($echarts, function (i, e) {
                        // 调用echarts的api获取图表实例，执行缩放
                        var chart = echarts.getInstanceByDom(e);
                        chart.resize();
                    });
                }, 50);
            });
        };
    },
    /**
     * 定时切换地图高亮
     * @param {Object}chartInstance 图表实例
     * @param {Number} length 数据长度
     */
    areaHight: function (chartInstance, length, interval) {
        chartInstance.dataLen = length;
        chartInstance.curData = 0;
        chartInstance.arr = [];
        chartInstance.interval = interval || 3000;
        // 数据下标组成数组
        for (var i = 0; i < chartInstance.dataLen; i++) {
            chartInstance.arr.push(i);
        }
        clearInterval(chartInstance.hightTimer);
        chartInstance.hightTimer = setInterval(function () {
            if (chartInstance.curData === chartInstance.dataLen) {
                chartInstance.curData = 0;
            }
            // 取消高亮
            chartInstance.dispatchAction({
                type: 'downplay',
                seriesIndex: 0,
                dataIndex: chartInstance.arr
            });
            // 高亮地图区域
            chartInstance.dispatchAction({
                type: 'highlight',
                seriesIndex: 0,
                dataIndex: chartInstance.curData
            });
            chartInstance.curData++;
        }, chartInstance.interval);
    },
    /**
     * 地图图表专用：鼠标悬浮到地图，停止showTooltip
     * @param {Object} chart 图表实例
     * @param {Number} length 图表数据量
     */
    mapChartHover: function (chart, length) {
        chart.on('mouseover', function () {
            clearInterval(chart.hightTimer);
        });
        chart.on('mouseout', function () {
            FUtil.areaHight(chart, length, chart.interval || 3000);
        });
    },
    /**
     * echarts渐变色,适用双色渐变，可根据实际需求改写,方向参数可不传，默认水平方向渐变
     * @param {String} color1 jquery dom对象
     * @param {String} color2 html字符串
     * @param {direction} 0：左右，1：上下
     */
    linearColor: function (color1, color2, direction) {
        var x1, y1 = 0, x2 = 0, y2;
        if ((direction || 0) == 0) {
            x1 = 1;
            y2 = 0;
        } else {
            x1 = 0;
            y2 = 1;
        }
        return new echarts.graphic.LinearGradient(x1, y1, x2, y2,
            [{
                offset: 0,
                color: color1
            }, {
                offset: 1,
                color: color2
            }]
        );
    },
    // 滚动列表
    scrollList: function ($dom, htmlStr) {
        $dom.empty().append(htmlStr);
        if (!$dom.isScroll) {
            $dom.isScroll = true;
            $dom.parent().scrollbox();
        }
    },
    // 点击高亮
    act: function ($dom, fn) {
        if ($dom.hasClass('active')) {
            return;
        } else {
            var ctx = this,
                args = Array.prototype.slice.call(arguments, 2);
            $dom.addClass('active').siblings().removeClass('active');
            args.unshift($dom)
            fn && fn.apply(ctx, args);
        }
    },
    /**
     *将字符串按照固定的字数截取
     * @param {String} str 需要处理的字符串
     * @param {Number} num 截断间隔
     * @param {Str} split 需要插入的字符，不传默认换行符 '\n'
     */
    splitStr: function (str, num, split) {
        var splitStr = split || '\n',
            reg = new RegExp('(\\S{' + num + '})', 'g'),
            reg2 = new RegExp('(\\' + splitStr + ')$'),
            fmtStr = str.replace(reg, '$1' + splitStr);
        return fmtStr.replace(reg2, '');
    },
    /**
     * 数组分组，用于多页面渲染
     * @param {Number} num 每组元素的数量
     * @param {Array} arr 需要处理的数组
     */
    getArrTrans: function (arr, num) {
        var resultArr = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            var page = Math.floor(i / num);
            if (!resultArr[page]) {
                resultArr[page] = [];
            }
            resultArr[page].push(arr[i]);
        }
        return resultArr;
    },
    /**
     * 根据value查找key
     * @param {Object} object 需要查找的对象
     * @param {Function} predicate 查询条件
     */
    findKey: function (object, predicate) {
        var result;
        if (object == null) {
            return result;
        }
        Object.keys(object).some(function (key) {
            var value = object[key];
            if (predicate(value, key, object)) {
                result = key;
                return true;
            }
        });
        return result;
    },
    /**
     * 动态载入、更新数字，需要引入插件countUp.js
     * @param {String} space 命名空间
     * @param {Number} data 数据
     * @param {Object} options 插件自定义配置，可不传
     */
    animateRender: function (space, data, options) {
        for (var i in data) {
            if (Object.prototype.hasOwnProperty.call(data, i)) {
                var $dom = $('#' + space + '-' + i),
                    d = data[i] - 0;
                if ($dom.length > 0) {
                    if (!isNaN(d)) {
                        var dotIdx = String(data[i]).indexOf('.'), //获取小数点的位置
                            decimal = 0; // 默认整数
                        if (dotIdx > -1) {
                            decimal = String(data[i]).length - dotIdx - 1; //获取小数点后的个数
                        }
                        var countUpOption = $.extend({}, {
                            //定义是否开启缓动
                            useEasing: true,
                            //是否开启分组
                            useGrouping: false,
                            decimalPlaces: decimal
                        }, options || {});
                        if (!$dom.data('countUp')) {
                            var num = new CountUp(space + '-' + i, data[i], countUpOption);
                            if (!num.error) {
                                //开启滚动
                                num.start();
                            } else {
                                // eslint-disable-next-line no-console
                                console.log(num.error);
                            }
                            //  = num;
                            $dom.data('countUp', num);
                        } else {
                            $dom.data('countUp').update(data[i]);
                        }
                    } else {
                        $dom.text(data[i]);
                    }
                }
            }
        }
    },
    /**
     * 载入状态，类似renderNum
     * @param {String} space 命名空间
     * @param {Number} data 数据
     * @param {String} stateCls 状态名称前缀，不传默认'state'
     */
    renderState: function (space, data, stateCls) {
        for (var i in data) {
            if (Object.prototype.hasOwnProperty.call(data, i)) {
                var $dom = $('#' + space + '-' + i);
                if ($dom.length > 0) {
                    $dom.attr('data-' + (stateCls || 'state'), data[i]);
                }
            }
        }
    },
    /**
     * 定位调试辅助方法
     * @param {Object} $dom jquery dom对象
     * @param {Boolean} isCss 是否转换为css
     */
    getPos: function ($dom, isCss) {
        $dom.on('click', function (e) {
            var pos = this.getBoundingClientRect(),
                psdStr = '[' + (e.pageX - pos.x - window.scrollX) + ',' + (e.pageY - pos.y - window.scrollY) + ']';
            if (isCss) {
                psdStr = 'left: ' + (e.pageX - pos.x - window.scrollX) + 'px;top: ' + (e.pageY - pos.y - window.scrollY) + 'px;';
            }
            console.log(psdStr);
            // eslint-disable-next-line no-console
            var target = document.createElement('div');
            target.id = 'tempTarget';
            target.style.opacity = '0';
            target.style.position = 'absolute';
            target.innerText = psdStr;
            var range = document.createRange();
            var target2 = document.body.appendChild(target);
            try {
                range = document.createRange();
                range.selectNode(target);
                window.getSelection().removeAllRanges();
                window.getSelection().addRange(range);
                document.execCommand('copy');
                window.getSelection().removeAllRanges();
                // eslint-disable-next-line no-catch-shadow
            } catch (error) { }
            target.remove();
            target2.remove();
        });
    },
    /**
     * 删除链接中的html后缀
     * @param {String} url 需要处理的url字符串
     */
    removeHtml: function (url) {
        return url.replace(/\.html/ig, '');
    },
    /**
     * 饼图自动切换
     * @param {Object} curChart 图表实例
     * @param {Number} chartLength 数据长度
     * @param {Number} timer 切换时间
     */
    pieAuto: function (curChart, chartLength, timer) {
        var mytimer = timer || 3000;
        var app = {
            currentIndex: -1
        };
        clearInterval(curChart.timer);
        curChart.timer = setInterval(function () {
            var dataLen = chartLength;
            // 取消之前高亮的图形
            curChart.dispatchAction({
                type: 'downplay',
                seriesIndex: 0,
                dataIndex: app.currentIndex
            });
            app.currentIndex = (app.currentIndex + 1) % dataLen;
            // 高亮当前图形
            curChart.dispatchAction({
                type: 'highlight',
                seriesIndex: 0,
                dataIndex: app.currentIndex
            });
            // 显示 tooltip
            curChart.dispatchAction({
                type: 'showTip',
                seriesIndex: 0,
                dataIndex: app.currentIndex
            });
        }, mytimer);
    },

    /**
     * 函数防抖
     * @param func 执行函数
     * @param delay 延迟时间，不传默认160ms
     */
    debounce: function (func, delay) {
        var timeout;
        return function (e) {
            clearTimeout(timeout);
            var context = this,
                args = arguments;
            timeout = setTimeout(function () {
                func.apply(context, args);
            }, delay || 160)
        };
    },
    // 去除html标签中的换行符和空格
    clearHtml: function (html) {
        return html.replace(/(\r\n|\n|\r)/g, "")
            .replace(/[\t ]+\</g, "<")
            .replace(/\>[\t ]+\</g, "><")
            .replace(/\>[\t ]+$/g, ">");
    },
    /**
     * 美化滚动条
     * @param {*} dom 滚动条容器class或者id
     * @param {*} subdom 直接子元素
     * @param {*} param 滚动条配置参数，不传则使用opt默认样式
     */
    niceScroll: function (dom, subdom, param) {
        var opt = $.extend({
            cursorwidth: "6px",
            cursorborder: 0,
            cursorcolor: "#00b9e7",
            background: "rgba(37,144,235,0.4)",
            autohidemode: false
        }, param);
        if (subdom != "") {
            dom.niceScroll(subdom, opt);
        } else {
            dom.niceScroll(opt);
        }
    },
    /**
     * 重置滚动条
     * @param {*} dom 滚动条容器class或者id
     */
    resetNiceScroll: function (dom) {
        dom.getNiceScroll().resize();
    },
    /**
     * tab切换
     * @param {*} dom tab切换dom对象
     * @param {*} opts 配置项
     */
    tabview: function (dom, opts) {
        $(dom).each(function (index, el) {
            $(this).Tab($.extend({
                hd: ".hdl",
                bd: ".bdl",
                event: "click",
                activeClass: "active",
                target: "target"
            }, opts));
        });
    },
    // 判断浏览器是否为IE9以下
    isIE9Below: function () {
        if (navigator.appName === 'Microsoft Internet Explorer') {
            if (parseInt(navigator.appVersion.split(";")[1].replace(/[ ]/g, "").replace("MSIE", "")) < 9) {
                return true;
            } else {
                return false;
            }
        }
    },
    /**
     * 日期比较
     * @param {*} stime 开始日期
     * @param {*} etime 结束日期
     */
    checkEndTime: function (stime, etime) {
        var start = new Date(stime.replace("-", "/").replace("-", "/")),
            end = new Date(etime.replace("-", "/").replace("-", "/"));
        if (end < start) {
            return false;
        }
        return true;
    },
    /**
     * 按照格式输出日期，如：yyyy-MM-dd HH:mm:ss
     * @param {*} date 日期对象
     * @param {*} fmt 格式
     */
    dateFormat: function (date, fmt) {
        var o = {
            "M+": date.getMonth() + 1, //月份
            "d+": date.getDate(), //日
            "h+": date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, //小时
            "H+": date.getHours(), //小时
            "m+": date.getMinutes(), //分
            "s+": date.getSeconds(), //秒
            "q+": Math.floor((date.getMonth() + 3) / 3), //季度
            "S": date.getMilliseconds() //毫秒
        };
        var week = {
            "0": "\u65e5",
            "1": "\u4e00",
            "2": "\u4e8c",
            "3": "\u4e09",
            "4": "\u56db",
            "5": "\u4e94",
            "6": "\u516d"
        };
        if (/(y+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
        }
        if (/(E+)/.test(fmt)) {
            fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "\u661f\u671f" : "\u5468") : "") + week[date.getDay() + ""]);
        }
        for (var k in o) {
            if (new RegExp("(" + k + ")").test(fmt)) {
                fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
            }
        }
        return fmt;
    },
    /**
     * 获取url参数值
     * @param {*} name 
     */
    getUrlParams: function (name) {
        var params = {},

            query = location.search.substring(1),
            arr = query.split('&'),
            rt;

        $.each(arr, function (i, item) {
            var tmp = item.split('='),
                key = tmp[0],
                val = decodeURIComponent(tmp[1]);

            if (typeof params[key] == 'undefined') {
                params[key] = val;

            } else if (typeof params[key] == 'string') {
                params[key] = [params[key], val];

            } else {
                params[key].push(val);
            }
        });

        rt = name ? params[name] : params;

        return rt;
    },
    // 是否为移动端
    isMobile: function () {
        var ua = navigator.userAgent;

        var detect = {
            // 是否为移动终端
            mobile: !!ua.match(/AppleWebKit.*Mobile.*/),
            // ios终端
            ios: !!ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
            // android终端或者uc浏览器
            android: ua.indexOf('Android') > -1 || ua.indexOf('Linux') > -1,
            // 是否为iPhone或者QQHD浏览器
            iPhone: ua.indexOf('iPhone') > -1,
            // 是否iPad
            iPad: ua.indexOf('iPad') > -1
        };

        return (detect.mobile || detect.ios || detect.android || detect.iPhone || detect.iPad);
    },
    /**
     * 设置左右等高
     * @param {*} left 左侧容器
     * @param {*} right 右侧容器
     */
    setEqualHeight: function (left, right) {
        var l = $(left).height(),
            r = $(right).height();
        $(left + "," + right).css('height', l > r ? l : r);
    },
    /**
     * 排序
     * @param {*} data 数组
     * @param {*} key 排序字段，默认"value"
     * @param {*} order 排序顺序，默认降序"0"
     */
    sort: function (data, sortField, order) {
        // var order = order || 0,
            sortField = sortField || "value";
        var compare = function (key) {
            return function (value1, value2) {
                var val1 = value1[key];
                var val2 = value2[key];
                if (order == 0) {
                    return val2 - val1;
                } else {
                    return val1 - val2;
                }
            }
        }
        return data.sort(compare(sortField))
    },
    /**
     * 文字滚动
     * @param {*} dom 文字滚动的class
     * @param {*} config 配置项
     */
    liMarquee: function (dom, config) {
        var dom = dom || ".text-scroll";
        $(dom).liMarquee($.extend({
            runshort: false,
            scrollamount: 20
        }, config));
    },
    /**
     * 进度条动画
     * @param {*} space 命名空间
     * @param {*} speed 速度，默认200
     * @param {*} callback 回调
     */
    progressBar: function (space, speed, callback) {
        $("." + space + "-" + "percent").each(function (i, e) {
            $(this).stop().animate({
                "width": $(this).attr("data-width")
            }, speed || 200, function () {
                callback
            });
        });
    },
    /**
     * @name 判断数据是否为数组
     * @param {Object|Array} data
     * @return {Booleam} 返回值
     */
    isArray: function (data) {
        return Object.prototype.toString.call(data) === "[object Array]";
    },
    /**
     * mustache 模板渲染
     * @param {*} id 模板id
     * @param {*} data 数据
     */
    mustache: function (id, data) {
        var isArray = this.isArray(data);
        data = isArray ? {
            data: data
        } : data;
        var dom = document.getElementById(id);
        var tpl = dom ? dom.innerHTML : dom;
        return Mustache.render(tpl, data);
    },
    /**
     * @name 为状态添加显隐判断
     * @param {Object|Array} data
     */
    setStatusVisible: function (data, key, status) {
        if (FUtil.isArray(data)) {
            $(data).each(function () {
                FUtil.setStatusVisible(this, key, status);
            });
        } else {
            for (var k in status) {
                if (FUtil.isArray(status[k])) {
                    $(status[k]).each(function () {
                        if (this == data[key]) {
                            data[k] = true;
                        }
                    });
                } else {
                    data[k] = status[k] == data[key];
                }
            }
        }
    },
    /**
     * @name 为状态添加文字表述
     * @param {Object|Array} data
     * @example
     *      var data= [{status:1},{status:2},...]
     *      Util.setStatusText(data,'status','statusText',{
     *          1:'待提交',
     *          2:'提交完成'
     *      })
     *      // [{status:1,statusText:'待提交'},{status:2,statusText:'提交完成'},...]
     */
    setStatusText: function (data, key, name, status) {
        if (Util.isArray(data)) {
            $(data).each(function () {
                Util.setStatusText(this, key, name, status);
            });
        } else {
            for (var k in status) {
                if (data[key] == k) data[name] = status[k];
            }
        }
    },
    /**
     * @name 根据关键字自定义字符串
     * @param {Object|Array} data 数据
     * @param {String} value 关键字
     * @param {String} replace 自定义规则  - {{name}} 中的 name 表示需要查找的值的字段名
     * @return {array} 带有高亮的数组
     * @example
     *      var data =[{name:'我要给这段话中的这段话添加高亮'}]
     *      Util.replaceStrByKey(data,'这段话','<span style="color:#f00">{{name}}</span>')
     *      // [{name:'我要给这段话中的这段话添加高亮',replaceName:"我要给<span stype="color:#f00">这段话<span>中的<span stype="color:#f00">这段话<span>添加高亮"}]
     */
    replaceStrByKey: function (data, key, replace) {
        var value = key.toString().replace(/\s*/g, ""),
            regValue = new RegExp(value, "g"),
            matchName = replace.match(/{{([\s\S]*?)}}/),
            name = matchName[1].replace(/\s*/g, ""),
            replaceName = matchName[0],
            regName = new RegExp(replaceName, "g");

        if (Util.isArray(data)) {
            $.each(data, function () {
                var v = this[name].toString();
                this["search" + name] = v.replace(regValue, function (str) {
                    return "<span>" + str + "</span>";
                });
            });
        } else {
            var v = data[name].toString();
            data["replace" + name] = v.replace(regValue, function (str) {
                return replace.replace(regName, str);
            });
        }

        return data;
    },
    /**
     * @name 将JSON字符串解析为Object
     * @param {String} data JSON字符串
     */
    parseJSON: function (data) {
        return typeof data == "string" ? JSON.parse(data) : data;
    },
    /**
     * 获取目标的类型
     * @param {*} obj 
     */
    getType: function (obj) {
        var s = Object.prototype.toString.call(obj);
        return s.substring(8, s.length - 1).toLowerCase();
    },
    /**
     *  设置多Y轴同步分割段数
     * @param {*} chart 图表实例
     * @param {*} data 图表数据
     * @param {*} keyArr value的key值['key1','key2',...]
     * @param {*} segment 分割段数，默认5
     */
    alignSplitLine: function (chart, data, keyArr, segment) {
        var option = [];
        $.each(keyArr, function (i, e) {
            var max = parseInt(FUtil.getMax(data, e)),
                maxArr = (max + "").split(""),
                numlength = maxArr.length,
                value = 0;
            if (max < 1000) {
                value = (parseInt(maxArr[0]) + 1) * Math.pow(10, numlength - 1);
            } else {
                value = parseInt(maxArr[0]) * Math.pow(10, numlength - 1) + (parseInt(maxArr[1]) + 1) * Math.pow(10, numlength - 2);
            }
            option.push({
                max: value,
                interval: value / (segment || 5)
            });
        });
        chart.setOption({
            yAxis: option
        });
    },
    /**
     * 读秒倒计时
     * @param {number} K 
     * @param {string} id 
     * @param {function} successcallback 
     */
    secondCountDown: function (K, id, successcallback) {
        document.getElementById(id).innerText = K;
        K = K - 1;
        if (K >= 0) {
            var timer = setTimeout(function () {
                FUtil.secondCountDown(K, id, successcallback);
            }, 1000);
        } else {
            successcallback();
        }
    },
    /**
     * 页面resize事件优化
     * @param {*} callback 回调
     * @param {*} time 响应时间
     */
    pageResize: function (callback, time) {
        var resizeTimer = null;
        $(window).on('resize', function () {
            if (resizeTimer) {
                clearTimeout(resizeTimer);
            }
            resizeTimer = setTimeout(function () {
                callback();
            }, time || 400);
        });
    },
    /**
     * layer弹出层
     * @param {*} config 配置项
     * @param {*} isParent 是否parent打开,默认false
     */
    layer: function (config, isParent) {
        var openState = isParent || false;
        var par = $.extend({
            type: 2,
            title: false,
            closeBtn: false,
            shadeClose: false
        }, config);
        openState ? parent.layer.open(par) : layer.open(par)
    },
    /**
      * @name 渲染分页
      * @param {id} string 分页标签的id
      * @param {Nubmer}  pageindex 当前页
      * @param {Nubmer} pagesize 每页条目数
      * @param {Nubmer}  total 总页数
      * @param {object}  option 配置项
      * @param {Function} fn 分页按钮点击之后触发的函数
      */
    renderPager: function (id, pageindex, pagesize, total, fn, option) {
        var $pager = $(document.getElementById(id));
        if ($pager.pagination()) {
            $pager.pagination("setPageIndex", pageindex);
            $pager.pagination("setPageSize", pagesize);
            $pager.pagination("render", total);
        } else {
            $pager.pagination($.extent({
                pageIndex: pageindex,
                pageSize: pagesize,
                total: total,
                showInfo: true,
                showInfo: true,
                showJump: true,
                showPageSizes: true,
                pageSizeItems: [5, 10, 15, 20],
                infoFormat: "总条数：{total} 　",
                pageElementSort: ['$page', '$size', '$jump', '$info'],
            }, option));
            $pager.on("pageClicked jumpClicked pageSizeChanged", function (e, data) {
                fn && fn(data.pageIndex, data.pageSize);
            });
        }
        $pager.toggle(pagesize < total);
    },
    /**
     * 请求数据
     * @param {Object} options 对象，包含url、请求类型、请求参数
     * @param {Function} successFn 成功回调
     * @param {Object} extraParams 额外请求参数
     */
    ajax: function (options, successFn, extraParams) {
        options = $.extend({}, {
            type: 'post',
            dataType: 'json',
            contentType: "application/json",
        }, options);

        $.ajax(options).done(function (data) {
            successFn && successFn(data.custom, extraParams);
        }).fail(function (err) {
            console.log('接口请求失败 ', err);
        });
    },
    /**
     * chosen下拉框通用渲染方法
     * @param {*} dom id或class
     * @param {*} data 数据
     */
    setChosenData: function (dom, data) {
        var $dom = $(dom),
            tips = $dom.attr("data-placeholder");
        $dom.empty();
        if (!(tips == "" || tips == undefined)) {
            $dom.html('<option value=""></option>');
        }
        $.each(data, function (i, e) {
            $dom.append('<option value="' + e.value + '">' + e.name + '</option>');
        });
        $dom.trigger("chosen:updated"); //更新
    },
    /**
     * 高亮关键字
     * @param {*} id 容器id
     * @param {*} key 高亮文字,字符串（多个关键字可用|分开）
     * @param {*} color 高亮颜色
     */
    setHighlightKey: function (id, key, color) {
        var $dom = $(id),
            strArr = key.split("|");
        $dom.each(function (index, element) {
            var $this = $(this);
            if (FUtil.isArray(strArr)) {
                $.each(strArr, function (i, e) {
                    $this.html(setKey(e, $this.html()));
                });
            } else {
                $this.html(setKey(strArr, $this.html()));
            }
        });
        function setKey(name, str) {
            var reg = "/" + name + "/g";
            str = str.replace(eval(reg), "<span style='color:" + color + "'>" + name + "</span>");
            return str
        }
    },
    /**
     * 自定义提示框
     * @param {*} $dom 元素dom
     * @param {*} data 数据-数组
     * @param {*} direction 方向，1,2,3,4(上，右，下，左)
     */
    layerTooltip: function ($dom, data, direction) {
        $dom.on('mouseover', function (event) {
            var $this = $(this),
                index = $this.index(),
                thisImg = FUtil.mustache("cus-tip-tmpl", data[index]);
            // 显示提示
            layer.tips(thisImg, $this, {
                skin: 'layer-tooltip',
                tips: [direction || 1, 'rgba(0,0,0,0)'],
                time: 10000000
            });
        });
        $dom.on('mouseleave', function (event) {
            // 关闭提示
            var index = layer.tips();
            layer.close(index);
        });
    },

    // 滚动加载数字
    renderNumber: function ($dom, number) {
    if (("" + number).split(".").length > 1) {
      var decimal_places = ("" + number).split(".")[1].length;
      var decimal_factor = decimal_places === 0 ? 1 : decimal_places * 10;
      $dom.animateNumber({
        number: number * decimal_factor,
        numberStep: function (now, tween) {
          var floored_number = now / decimal_factor,
            target = $(tween.elem);
          if (decimal_places > 0) {
            floored_number = floored_number.toFixed(decimal_places);
          }
          target.text(floored_number);
        }
      }, 1000);
    } else {
      $dom.animateNumber({
        number: parseInt(number)
      }, 1000);
    }
  },
  /**
   * 加载滚动数字
   * @param {Object} $dom dom容器
   * @param {Number} data 数值
   * @param {Number} figure 长度
   */
  scrollNum: function ($dom, data, figure) {
    if (!$dom.isInited) {
      $dom.isInited = true;
      $dom.ScrollNumber({
        number: data,
        figure: figure || 6
      });
    } else {
      $dom.ScrollNumber('refresh', data);
    }
  },
});