/*
 * Author: 众产®  https://ciy.cn/code
 * Version: 0.7.1
 */
'use strict';
var ciygv = { //全局变量
    zindex: 100000 //弹窗层级
    , messagefn: {} //窗口间消息回调
};
var ciyfn = {};
var ciyclass = {};
//ciydom，所有dom操作封装，逐步替代jquery，各浏览器差异。不再必须支持IE。
//目前作为教学封装。
//通过封装抽象基础调用接口，实现多种区块链应用积累经验，简化浏览器内核，实现区块链浏览器。
//为未来区块链浏览器及独立源码部署，做底层技术储备。
function _ciydomclas(dom, parent) {
    this._ciy = true;
    this.length = 0;
    if (dom === undefined || dom === null || dom === true || dom === false)
        return this;
    if (parent) {
        if (typeof (parent) == 'string')
            parent = document.querySelector(parent);
        else if (parent && parent._ciy)
            parent = parent[0];
        else if (!iselement(parent))
            parent = document;
    }
    if (!parent) {
        if (dom && dom._ciy) {
            for (var i = 0; i < dom.length; i++) {
                this[this.length++] = dom[i];
            }
        } else if (isarray(dom)) {
            for (var i = 0; i < dom.length; i++) {
                this[this.length++] = dom[i];
            }
        } else if (typeof (dom) == 'string') {
            if (dom[0] == '<' && dom[dom.length - 1] == '>') {
                var parser = new DOMParser();
                var doc = parser.parseFromString(dom, 'text/html');
                var fragment = doc.body.firstChild;
                while (fragment) {
                    this[this.length++] = fragment;
                    fragment = fragment.nextSibling;
                }
            } else {
                var doms = document.querySelectorAll(dom);
                for (var i = 0; i < doms.length; i++) {
                    this[this.length++] = doms[i];
                }
            }
        } else if (dom instanceof Document) {
            this[this.length++] = dom;
        } else if (iselement(dom)) {
            this[this.length++] = dom;
        }
    } else {
        if (typeof (dom) == 'string') {
            var doms = parent.querySelectorAll(dom);
            for (var i = 0; i < doms.length; i++) {
                this[this.length++] = doms[i];
            }
        } else if (dom && dom._ciy) {
            for (var i = 0; i < dom.length; i++) {
                if (parent == dom[i] || parent.contains(dom[i]))
                    this[this.length++] = dom[i];
            }
        } else if (isarray(dom)) {
            for (var i = 0; i < dom.length; i++) {
                if (parent == dom[i] || parent.contains(dom[i]))
                    this[this.length++] = dom[i];
            }
        } else {
            if (parent == dom || parent.contains(dom))
                this[this.length++] = dom;
        }
    }
    return this;
}
_ciydomclas.prototype.each = function (fn, delay) {
    if (!delay) {
        for (var i = 0; i < this.length; i++) {
            fn.call(this, this[i], i);
        }
        return;
    }
    var thos = this;
    for (var i = 0; i < this.length; i++) {
        (function (ix) {
            setTimeout(function () {
                fn.call(thos, thos[ix], ix);
            }, delay * ix * 1000);
        })(i);
    }
    return true;
};
_ciydomclas.prototype.node = function () {
    if (!this[0])
        return null;
    return this[0].nodeName.toLowerCase();
};
_ciydomclas.prototype.children = function (selector) {
    if (!this[0])
        return this;
    var doms = this[0].children;
    if (selector === undefined)
        return $5(doms);
    if (typeof (selector) == 'number') {
        if (selector < 0)
            selector = doms.length + selector;
        return $5(doms[selector]);
    }
    var retdoms = [];
    for (var i = 0; i < doms.length; i++) {
        if (doms[i].matches(selector))
            retdoms.push(doms[i]);
    }
    return $5(retdoms);
};
_ciydomclas.prototype.parent = function (selector) {
    if (!this[0])
        return this;
    if (this[0] instanceof Document)
        return $5();
    if (selector === undefined)
        return $5(this[0].parentNode);
    var target;
    if (typeof (selector) != 'string')
        return $5();
    target = this[0].closest(selector);
    return $5(target);
};
_ciydomclas.prototype.offset = function () {
    if (!this[0])
        return this;

    const rect = this[0].getBoundingClientRect();
    const doc = this[0].ownerDocument;
    const win = doc.defaultView || doc.parentWindow;
    const docElem = doc.documentElement;
    return {
        top: rect.top + win.pageYOffset - docElem.clientTop,
        left: rect.left + win.pageXOffset - docElem.clientLeft
    };
};
_ciydomclas.prototype.find = function (ele) {
    if (!this[0])
        return this;
    var doms = this[0].querySelectorAll(ele);
    return $5(doms);
};
_ciydomclas.prototype.prev = function (count) {
    if (!this[0])
        return this;
    var dom = this[0];
    var doms = [];
    count = count || 1;
    while (dom.previousElementSibling) {
        dom = dom.previousElementSibling;
        if (!dom)
            break;
        doms.push(dom);
        if (--count <= 0)
            break;
    }
    return $5(doms);
};
_ciydomclas.prototype.next = function (count) {
    if (!this[0])
        return this;
    var dom = this[0];
    var doms = [];
    count = count || 1;
    while (dom.nextElementSibling) {
        dom = dom.nextElementSibling;
        if (!dom)
            break;
        doms.push(dom);
        if (--count <= 0)
            break;
    }
    return $5(doms);
};
_ciydomclas.prototype.eq = function (num) {
    if (!this[num])
        return $5([]);
    return $5(this[num]);
};
_ciydomclas.prototype.index = function (dom) {
    if (dom && dom._ciy)
        dom = dom[0];
    for (var i = 0; i < this.length; i++) {
        if (this[i] == dom)
            return i;
    }
    return -1;
};
_ciydomclas.prototype.remove = function () {
    this.each(function (dom) {
        if (dom.remove)
            dom.remove();
        else
            dom.parentNode.removeChild(dom);
    });
    for (var i = 0; i < this.length; i++) {
        delete (this[i]);
    }
    this.length = 0;
    return true;
};
_ciydomclas.prototype.setstyle = function (name, csstxt) {
    var doc = window.document;
    if (this[0])
        doc = this[0].ownerDocument || this[0].document || window.document;
    if (doc.getElementById(name))
        return;
    var styleElement = doc.createElement('style');
    styleElement.type = 'text/css';
    styleElement.id = name;
    styleElement.innerText = csstxt.replace(/\n/g, '').replace(/\t/g, '');
    doc.getElementsByTagName('head')[0].appendChild(styleElement);
};
_ciydomclas.prototype.addClass = function (cls) {
    this.each(function (dom) {
        dom.classList.add(cls);
    });
    return this;
};
_ciydomclas.prototype.removeClass = function (cls) {
    this.each(function (dom) {
        dom.classList.remove(cls);
    });
    return this;
};
_ciydomclas.prototype.hasClass = function (cls) {
    if (!this[0])
        return false;
    return this[0].classList.contains(cls);
};
_ciydomclas.prototype.toggleClass = function (cls) {
    this.each(function (dom) {
        dom.classList.toggle(cls);
    });
    return this;
};
_ciydomclas.prototype.attr = function (name, value) {
    if (!this[0] || !iselement(this[0]))
        return null;
    if (value === undefined) {
        if (name in this[0])
            return this[0][name];
        var val = this[0].getAttribute(name);
        if (val === null)
            return null;
        if (val.substring(0, 1) == '{' && val.substring(val.length - 1) == '}') {
            var jsn = ciyfn.tojson(val);
            if (jsn.v !== undefined)
                return jsn.v;
            return val;
        }
        return val;
    }
    this.each(function (dom) {
        if (value === null)
            return dom.removeAttribute(name);
        if (name in dom)
            return dom[name] = value;
        if (typeof (value) == 'string' || typeof (value) == 'number' || typeof (value) == 'boolean')
            return dom.setAttribute(name, value);
        dom.setAttribute(name, ciyfn.jsontostr({ v: value }));
    });
    return this;
};
_ciydomclas.prototype.hasattr = function (name) {
    if (!this[0])
        return null;
    var name = this[0].getAttribute(name);
    if (name === undefined || name === null)
        return false;
    name = name.toLowerCase();
    if (name === '0' || name === 'null' || name === 'false')
        return false;
    return true;
};
_ciydomclas.prototype.css = function (css, val) {
    //  .css() cal全部，.css(name) 返回style单值   .css(name,value) 设置单值
    // .css({}) 设置多值
    if (!this[0])
        return this;
    if (css === undefined) {
        return window.getComputedStyle(this[0]);
    }
    if (typeof (css) == 'string' && val === undefined) {
        return this[0].style[css];
    }
    if (isobj(css)) {
        this.each(function (dom) {
            this._setcssarr(dom, css);
        });
    }
    else if (typeof (css) == 'string' && val !== undefined) {
        this.each(function (dom) {
            dom.style[css] = val;
        });
    }
    return this;
};
_ciydomclas.prototype._setcssarr = function (dom, css) {
    for (var key in css) {
        dom.style[key] = css[key];
    }
};
_ciydomclas.prototype.val = function (val, from) {
    if (val === undefined) {
        if (!this[0])
            return null;
        if (this[0].ciycmp)
            return this[0].ciycmp.value;
        return this[0].value;
    }
    this.each(function (dom) {
        if (dom.ciycmp)
            return dom.ciycmp.setvalue(val, from);
        dom.value = val;
    });
    return this;
};
_ciydomclas.prototype.html = function (html) {
    if (!this[0])
        return '';
    if (html === undefined) {
        return this[0].innerHTML;
    }
    if (typeof (html) == 'string' || typeof (html) == 'number') {
        this[0].innerHTML = html;
    } else if (iselement(html)) {
        this[0].replaceChild(html, this[0].firstChild);
    }
    return this;
};
_ciydomclas.prototype.outhtml = function (html) {
    if (!this[0])
        return '';
    if (html === undefined) {
        return this[0].outerHTML;
    }
    this.each(function (dom) {
        if (typeof (html) == 'string') {
            dom.outerHTML = html;
        } else if (iselement(html)) {
            dom.parentElement.replaceChild(html, dom);
        }
    });
    return this;
};
_ciydomclas.prototype.text = function (text) {
    if (!this[0])
        return '';
    if (text === undefined) {
        return this[0].textContent.trim();
    }
    this.each(function (dom) {
        if (typeof (text) == 'string' || typeof (text) == 'number') {
            dom.innerText = text;
        } else if (iselement(text)) {
            dom.innerText = text.textContent;
        }
    });
    return this;
};
_ciydomclas.prototype._insdom = function (elehtml, pos) {
    if (elehtml === undefined || !this[0])
        return this;
    if (typeof (elehtml) == 'string') {
        this[0].insertAdjacentHTML(pos, elehtml);
    } else if (elehtml && elehtml._ciy) {
        var thos = this;
        elehtml.each(function (dom) {
            thos[0].insertAdjacentElement(pos, dom);
        });
    } else if (iselement(elehtml)) {
        this[0].insertAdjacentElement(pos, elehtml);
    }
    return this;
};
_ciydomclas.prototype.append = function (elehtml) {
    return this._insdom(elehtml, 'beforeend');
};
_ciydomclas.prototype.prepend = function (elehtml) {
    return this._insdom(elehtml, 'afterbegin');
};
_ciydomclas.prototype.before = function (elehtml) {
    return this._insdom(elehtml, 'beforebegin');
};
_ciydomclas.prototype.after = function (elehtml) {
    return this._insdom(elehtml, 'afterend');
};
_ciydomclas.prototype.scroll = function (opn) {
    opn.behavior = 'smooth';
    if (opn.act == 'view') {
        this[0].scrollIntoView(opn);
    } else if (opn.act == 'by') {
        this[0].scrollBy(opn);
    } else {
        this[0].scrollTo(opn);
    }
    return this;
};
_ciydomclas.prototype.on = function (evt, selector, func, isone) {
    if (this.length == 0)
        return;
    if (typeof selector === 'function') {
        func = selector;
        selector = null;
    }
    this.each(function (dom) {
        var listenfn = function (e) {
            var ev = { originalEvent: e };
            ev.fromElement = dom;
            ev.preventDefault = function () {
                if (e.preventDefault)
                    e.preventDefault();
                else
                    e.returnValue = false;
            };
            ev.stopPropagation = function () {
                if (e.stopPropagation)
                    e.stopPropagation();
                else
                    e.cancelBubble = true;
            };
            var props = ['files', 'clipboardData', 'dataTransfer', 'x', 'y', 'clientX', 'clientY', 'offsetX', 'offsetY', 'pageX', 'pageY', 'screenX', 'screenY', 'keyCode', 'altKey', 'ctrlKey', 'shiftKey', 'which', 'wheelDelta', 'detail', 'srcElement', 'toElement', 'target'];
            for (var i = 0; i < props.length; i++) {
                var prop = props[i];
                if (e[prop] !== undefined)
                    ev[prop] = e[prop];
            }
            if (selector) {
                var target;
                if (typeof (selector) == 'string') {
                    if (e.target instanceof Document)
                        target = e.target.documentElement.closest(selector);
                    else
                        target = e.target.closest(selector);
                } else {
                    if (iselement(selector) || (selector._ciy && selector.length > 0)) {
                        if (selector._ciy)
                            selector = selector[0];
                        target = e.target;
                        while (target !== null && target !== selector) {
                            target = target.parentNode;
                        }
                    }
                }
                if (target) {
                    ev.currentTarget = target;

                    func.call(target, ev);
                    if (isone)
                        dom.removeEventListener(evt, listenfn);
                }
            } else {
                ev.currentTarget = dom;
                func.call(dom, ev);
                if (isone)
                    dom.removeEventListener(evt, listenfn);
            }
        };
        dom.addEventListener(evt, listenfn);
        if (!isone) {
            if (!dom._ciylistener)
                dom._ciylistener = [];
            dom._ciylistener.push({ evt: evt, func: listenfn });
        }
    });
    return this;
};
_ciydomclas.prototype.one = function (evt, selector, func) {
    return this.on(evt, selector, func, true);
};
_ciydomclas.prototype.off = function (evt) {
    if (this.length == 0)
        return;
    this.each(function (dom) {
        if (!dom._ciylistener)
            return;
        if (evt) {
            for (var i = dom._ciylistener.length - 1; i >= 0; i--) {
                if (dom._ciylistener[i].evt != evt)
                    continue;
                dom.removeEventListener(evt, dom._ciylistener[i].func);
                dom._ciylistener.splice(i, 1);
            }
            if (dom._ciylistener.length == 0)
                delete dom._ciylistener;
        } else {
            for (var i = dom._ciylistener.length - 1; i >= 0; i--) {
                dom.removeEventListener(dom._ciylistener[i].evt, dom._ciylistener[i].func);
            }
            delete dom._ciylistener;
        }
    });
    return this;
};
_ciydomclas.prototype.trigger = function (evt, data) {
    if (this.length == 0)
        return;
    var opn = {};
    opn.bubbles = true;
    opn.cancelable = true;
    if (data)
        opn.detail = data;
    this.each(function (dom) {
        if (evt == 'click' || evt == 'mousedown' || evt == 'mouseup' || evt == 'mousemove' || evt == 'dblclick' || evt == 'contextmenu') {
            dom.dispatchEvent(new MouseEvent(evt, opn));
        } else {
            dom.dispatchEvent(new Event(evt, opn));
        }
    });
    return this;
};
_ciydomclas.prototype.rect = function () {
    if (!this[0])
        return { top: 0, left: 0, width: 0, height: 0 };
    if (this[0] instanceof Document)
        return { top: 0, left: 0, width: window.innerWidth, height: window.innerHeight };
    return this[0].getBoundingClientRect();
};
_ciydomclas.prototype.width = function () {
    if (!this[0])
        return 0;
    if (this[0] instanceof Document)
        return window.innerWidth;
    return this[0].offsetWidth;
};
_ciydomclas.prototype.height = function () {
    if (!this[0])
        return 0;
    if (this[0] instanceof Document)
        return window.innerHeight;
    return this[0].offsetHeight;
};
_ciydomclas.prototype.winwidth = function () {
    if (!this[0])
        return 0;
    return this[0].ownerDocument.defaultView.innerWidth;
};
_ciydomclas.prototype.winheight = function () {
    if (!this[0])
        return 0;
    return this[0].ownerDocument.defaultView.innerHeight;
};
_ciydomclas.prototype._getdisplay = function (dom) {
    if (!iselement(dom))
        return 'block';
    var dp = window.getComputedStyle(dom).display;
    if (dp != 'none')
        return dp;
    var node = dom.nodeName.toLowerCase();
    if (node == 'div' || node == 'p' || node == 'ul' || node == 'ol' || node == 'header' || node == 'footer' || node == 'section' || node == 'article' || node == 'nav')
        return 'block';
    else if (node == 'table')
        return 'table';
    else
        return 'inline';
};
_ciydomclas.prototype.aniin = function (tranform, sec, display) {
    sec = tofloat(sec);
    if (sec < 0.1)
        sec = 0.5;
    tranform = tranform || '';
    display = display || null;
    var thos = this;
    thos._aniing = true;
    this.each(function (dom) {
        dom.style.opacity = 0;
        dom.style.transform = tranform;
        dom.style.transition = 'none';
        dom.style.display = display ? display : this._getdisplay(dom);
    });
    setTimeout(function () {
        thos.css({ opacity: 1, transform: '', transition: 'all ' + sec + 's' });
    }, 1);
    setTimeout(function () {
        thos._aniing = false;
    }, sec * 1000);
};
_ciydomclas.prototype.aniout = function (tranform, sec, bremove) {
    sec = tofloat(sec);
    if (sec < 0.1)
        sec = 0.5;
    tranform = tranform || '';
    var thos = this;
    this.css({ opacity: 0, transform: tranform, transition: 'all ' + sec + 's' });
    setTimeout(function () {
        if (thos._aniing)
            return;
        if (bremove)
            thos.remove();
        else
            thos.css({ opacity: 1, display: 'none', transform: '', transition: '' });
    }, sec * 1000);
};
_ciydomclas.prototype.show = function (tranform, sec, display) {
    display = display || null;
    sec = tofloat(sec);
    if (sec > 5)
        sec = 0.5;
    if (sec <= 0) {
        this.css({ opacity: 1, display: display ? display : this._getdisplay(this[0]) });
        return this;
    }
    var thos = this;
    if (tranform == 'slide') {
        this._aniing = true;
        this.each(function (dom) {
            if (dom._ciyopacity === undefined) dom._ciyopacity = dom.style.opacity;
            if (dom._ciypadding === undefined) dom._ciypadding = dom.style.padding;
            if (dom._ciyheight === undefined) dom._ciyheight = dom.style.height;
            if (dom._ciytransition === undefined) dom._ciytransition = dom.style.transition;
            if (dom._ciyoverflow === undefined) dom._ciyoverflow = dom.style.overflow;
            dom.style.display = display ? display : this._getdisplay(dom);
            dom.style.opacity = 0;
            var hei = dom.offsetHeight;
            dom.style.height = 0;
            dom.style.padding = '0';
            dom.style.transition = 'all ' + sec + 's';
            setTimeout(function () {
                dom.style.height = hei + 'px';
                dom.style.overflow = 'hidden';
                dom.style.padding = dom._ciypadding;
                dom.style.opacity = dom._ciyopacity;
            }, 0);
        });
        setTimeout(function () {
            thos._aniing = false;
            thos.each(function (dom) {
                dom.style.height = dom._ciyheight;
                dom.style.overflow = dom._ciyoverflow;
                dom.style.transition = dom._ciytransition;
            });
        }, sec * 1000);
        return this;
    }
    if (tranform == 'up')//fade，默认
        tranform = 'translateY(30px)';
    else if (tranform == 'down')
        tranform = 'translateY(-30px)';
    else if (tranform == 'left')
        tranform = 'translateX(-30px)';
    else if (tranform == 'right')
        tranform = 'translateX(30px)';
    else if (tranform == 'small')
        tranform = 'scale(0.5)';
    else if (tranform == 'big')
        tranform = 'scale(2)';
    this.aniin(tranform, sec, display);
    return this;
};
_ciydomclas.prototype.hide = function (tranform, sec, bremove) {
    sec = tofloat(sec);
    if (sec <= 0) {
        if (bremove)
            this.remove();
        else
            this.css({ display: 'none', opacity: 1, transform: '' });
        return this;
    }
    if (tranform == 'slide') {
        this.each(function (dom) {
            var hei = dom.offsetHeight;
            if (dom._ciyheight === undefined) dom._ciyheight = dom.style.height;
            if (dom._ciymarginBottom === undefined) dom._ciymarginBottom = dom.style.marginBottom;
            if (dom._ciytransition === undefined) dom._ciytransition = dom.style.transition;
            if (dom._ciypadding === undefined) dom._ciypadding = dom.style.padding;
            if (dom._ciyborder === undefined) dom._ciyborder = dom.style.border;
            if (dom._ciyoverflow === undefined) dom._ciyoverflow = dom.style.overflow;
            if (dom._ciydisplay === undefined) dom._ciydisplay = dom.style.display;
            dom.style.height = hei + 'px';
            dom.style.display = dom._ciydisplay || 'block';
            dom.style.transition = 'all ' + sec + 's';
            setTimeout(function () {
                dom.style.height = 0;
                dom.style.marginBottom = 0;
                dom.style.border = 'none';
                dom.style.padding = '0';
                dom.style.overflow = 'hidden';
            }, 16);
        });
        var thos = this;
        setTimeout(function () {
            if (thos._aniing)
                return;
            if (bremove)
                thos.remove();
            else {
                thos.each(function (dom) {
                    dom.style.height = dom._ciyheight;
                    dom.style.marginBottom = dom._ciymarginBottom;
                    dom.style.border = dom._ciyborder;
                    dom.style.padding = dom._ciypadding;
                    dom.style.overflow = dom._ciyoverflow;
                    dom.style.display = 'none';
                    dom.style.transition = dom._ciytransition;
                });
            }
        }, sec * 1000 + 50);
        return this;
    }
    if (tranform == 'up')//fade，默认
        tranform = 'translateY(30px)';
    else if (tranform == 'down')
        tranform = 'translateY(-30px)';
    else if (tranform == 'left')
        tranform = 'translateX(-30px)';
    else if (tranform == 'right')
        tranform = 'translateX(30px)';
    else if (tranform == 'small')
        tranform = 'scale(0.5)';
    else if (tranform == 'big')
        tranform = 'scale(2)';
    this.aniout(tranform, sec, bremove);
    return this;
};
_ciydomclas.prototype.toggle = function (tranform, sec, display) {
    if (this.css('display') == 'none')
        this.show(tranform, sec, display);
    else
        this.hide(tranform, sec, false);
};
function $5(dom, parent) {
    if (dom && dom._ciy && parent === undefined)
        return dom;
    return new _ciydomclas(dom, parent);
}

// console.log(isobj(null));
// console.log(isobj(''));
// console.log(isobj(new Date()));
// console.log(isobj(new ciyclass.loading()));
// console.log(isobj(0));
// console.log(isobj(1.2));
// console.log(isobj(undefined));
// console.log(isobj());
// console.log(isobj(false));
// console.log(isobj(true));
// console.log(isobj([]));
function tostr(val, defval) {
    if (!val) {
        if (defval == undefined)
            defval = '';
        return defval;
    }
    return val + '';
}
function toint(val, defval) {
    if (defval == undefined)
        defval = 0;
    var ret = parseInt(val);
    if (isNaN(ret))
        return defval;
    else if (ret == undefined)
        return defval;
    else
        return ret;
}
function tofloat(val, defval) {
    if (defval == undefined)
        defval = 0;
    var ret = parseFloat(val);
    if (isNaN(ret))
        return defval;
    else
        return ret;
}
function tostamp(time) {
    var t;
    if (time instanceof Date)
        t = time;
    else if (time === undefined || time == -1 || time == '-1')
        t = new Date();
    else if (/^\d+$/.test(time)) {
        if (time == 0)
            return 0;
        t = new Date(time * 1000);
    } else if (typeof (time) == 'string')
        t = new Date(time.replace(/\-/g, '/'));
    else
        return 0;
    return toint(t.getTime() / 1000);
}
function isarray(v) {
    var typ = Object.prototype.toString.call(v);
    if (typ === '[object NodeList]')
        return true;
    if (typ === '[object HTMLCollection]')
        return true;
    return typ === '[object Array]';
}
function isobj(v) {
    return Object.prototype.toString.call(v) === '[object Object]';
}
function iselement(v) {
    var typ = Object.prototype.toString.call(v);
    return typ.indexOf('Element') > -1;
}
ciyfn.isemptyobj = function (obj) {
    for (var key in obj) {
        if (obj.hasOwnProperty(key))
            return false;
    }
    return true;
}
ciyfn.split = function (str, sep) {
    if (!str)
        return [];
    str = str + '';
    var arr = str.split(sep);
    for (var i = 0; i < arr.length; i++)
        arr[i] = arr[i].trim();
    return arr;
}
ciyfn.getdictdata = function (datakey, pagedata) {
    //直接数组，字典缓存，静态引用，字符串拼接
    if (isarray(datakey))
        return datakey;
    if (typeof (datakey) != 'string')
        return new Array();
    var datas = ciyfn.getstorage('cata_' + datakey);
    if (isarray(datas))
        return datas;
    if (isobj(pagedata) && pagedata[datakey])
        return pagedata[datakey];
    if (isarray(window[datakey]))
        return window[datakey];
    if (datakey.indexOf(',') == -1 && datakey.indexOf(':') == -1)
        return new Array();
    var svs = ciyfn.split(datakey, ',');
    datas = new Array();
    for (var i = 0; i < svs.length; i++) {
        var ind = svs[i].indexOf(':');
        if (ind == -1) {
            datas.push({
                id: i + 1
                , name: svs[i]
            });
        } else {
            var id = svs[i].substring(0, ind);
            datas.push({
                id: id
                , name: svs[i].substring(ind + 1)
            });
        }
    }
    return datas;
}
ciyfn.filterdictdata = function (data, opn) {
    var retdata = [];
    if (!isarray(data))
        return [];
    if (opn.all)
        retdata.push({ id: '', name: ciyfn.lang(opn.all) });
    if (isarray(opn.first)) {
        for (var i in opn.first)
            retdata.push(opn.first[i]);
    }
    var limit = 0;
    var limit_data = null;
    if (opn.limit) { //2~    10~20    12,13,14
        if (opn.limit.indexOf('~') > -1) {
            limit = 1;
            limit_data = opn.limit.split('~');
        } else {
            limit = 2;
            limit_data = opn.limit.split(',');
        }
    }
    if (opn.filter) {
        var fs = opn.filter.split('=');
        if (fs.length == 2) {
            opn.filter = {
                field: fs[0]
                , value: fs[1]
            };
        } else {
            opn.filter = null;
        }
    }
    if (!isarray(opn.rename))
        opn.rename = null;
    for (var i in data) {
        if (limit == 1) {
            if (limit_data[0] != '' && toint(data[i].id) < toint(limit_data[0]))
                continue;
            if (limit_data[1] != '' && toint(data[i].id) > toint(limit_data[1]))
                continue;
        } else if (limit == 2) {
            if (limit_data.indexOf(data[i].id + '') == -1)
                continue;
        }
        if (opn.filter && (data[i][opn.filter.field] ? data[i][opn.filter.field] : '') != opn.filter.value)
            continue;
        if (opn.rename) {
            for (var j in opn.rename) {
                if (data[i].id == opn.rename[j].id)
                    data[i].name = opn.rename[j].name;
            }
        }
        retdata.push(data[i]);
    }
    return retdata;
}
ciyfn.tojson = function (data) {
    var ret;
    try {
        ret = JSON.parse(data);
    } catch (err) {
        return { errmsg: err.message }
    }
    if (isarray(ret))
        return ret;
    if (ret)
        return ret;
    return { errmsg: 'JSON parse error' };
}
ciyfn.jsontostr = function (data, space) {
    var ret;
    try {
        ret = JSON.stringify(data, null, space);
    } catch (err) {
        return '';
    }
    return ret;
}
ciyfn.sha256 = async function (str) {
    const msgBuffer = new TextEncoder().encode(str);
    const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
ciyfn.sha512 = async function (str) {
    const msgBuffer = new TextEncoder().encode(str);
    const hashBuffer = await crypto.subtle.digest('SHA-512', msgBuffer);
    const hashArray = Array.from(new Uint8Array(hashBuffer));
    return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
ciyfn.loadjs = function (objname, jsurl, donefunc) {
    if (window[objname])
        return donefunc();
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = jsurl;
    script.onload = function () {
        donefunc();
    };
    document.head.appendChild(script);
}
ciyfn.calljsondata = function (url, successfunc, opn) {
    opn = opn || {};
    opn.url = url;
    opn.method = 'GET';
    opn.success = function (data, xhr) {
        var ind = Math.min(data.indexOf('['), data.indexOf('{'));
        if (ind > 0)
            data = data.substring(ind);
        var json = ciyfn.tojson(data);
        if (json.errmsg) {
            if (typeof opn.fail === 'function')
                opn.fail(data, xhr);
            else
                ciyfn.alert('Err:' + json.errmsg);
            return;
        }
        successfunc(json, xhr);
    }
    ciyfn.ajax(opn);
}
ciyfn.callfrequency = function (sec) {
    if (ciygv._callduptime && (new Date().getTime() - ciygv._callduptime < sec * 1000))
        return true;
    ciygv._callduptime = new Date().getTime();
    return false;
}
ciyfn.throttle = function (dom, sec) {
    sec = toint(sec);
    if (sec < 1)
        sec = ciy_vars.dupsec || 3;
    if (ciygv._clickduptime && (new Date().getTime() - ciygv._clickduptime < sec * 1000))
        return true;
    ciygv._clickduptime = new Date().getTime();
    if (dom) {
        var dombtn = $5(dom);
        if (dombtn.node() == 'form')
            dombtn = dombtn.find('[type="submit"]');
        dombtn.addClass('loading');
        ciygv._clickdupdombtn = dombtn;
    }
    ciygv._clickduptime = new Date().getTime();
    return false;
}
ciyfn.callfastfunc = function (dom, confirmmsg, func, postparam, succfunc, failfunc) {
    if (!confirmmsg)
        return cfunc();
    if (ciygv._clickduptime)
        return;
    ciyfn.alert(confirmmsg, function (opn) {
        opn.close();
        if (opn.btn != "关闭")
            cfunc();
    }, { btns: ["继续", "*关闭"] });
    function cfunc() {
        if (ciyfn.throttle(dom)) return;
        ciyfn.callfunc(func, postparam, function (json) {
            if (succfunc == 'reload') {
                ciyfn.toast('操作成功', function () {
                    location.reload();
                });
            } else if (typeof (succfunc) == 'function')
                succfunc(json);
            else
                ciyfn.toast('操作成功');
        }, { fail: failfunc });
    }
}
ciyclass.loading = function () {
    try {
        if (window.parent != window && window.parent.ciyclass.loading)
            return window.parent.ciyclass.loading();
    } catch { }
    var htmldom = '<div class="ciy-layer ciy-loading" style="z-index: ' + (ciygv.zindex++) + ';"></div>';
    htmldom = $5(htmldom);
    $5('body').append(htmldom);
    setTimeout(function () { htmldom.addClass("start") }, 50);
    this.close = function (cls) {
        htmldom.addClass(cls);
        setTimeout(function () { $5('.ciy-loading').remove(); }, 600);
    }
    return this;
}
ciyfn.callfunc = function (funcname, post, successfunc, opn) { //opn  showload,method,fail,complete,header,timeout
    opn = opn || {};
    opn.header = opn.header || {};
    if (typeof (window['ciy_vars']) === 'undefined')
        window.ciy_vars = {};
    if (ciy_vars.tokenfield)
        opn.header['ciyauth'] = ciyfn.getstorage('_' + ciy_vars.tokenfield);
    if (opn.showload === undefined)
        opn.showload = true;
    if (opn.method == 'get' || funcname.indexOf('?') > -1 || funcname.indexOf('://') > -1) {
        opn.url = funcname;
    } else {
        var ind = document.location.pathname.lastIndexOf('/');
        var path = document.location.pathname.substring(1, ind + 1);
        var pagename = document.location.pathname.substring(ind + 1) || 'index.html';
        ind = pagename.lastIndexOf('.');
        if (ind > 0)
            pagename = pagename.substring(0, ind);
        if (funcname.indexOf('.') == -1) {
            funcname = path + pagename + '.' + funcname;
        } else if (funcname.indexOf('/') == -1) {
            funcname = path + funcname;
        }
        opn.url = '/' + funcname;
    }

    opn.data = post || {};
    opn.data._pf = 'PC' + new Date().getTime() + '_' + parseInt(80000000 + Math.random() * 10000000);
    opn.done = function (xhr) {
        ciygv._clickduptime = null;
        if (ciygv._clickdupdombtn) {
            ciygv._clickdupdombtn.removeClass('loading');
            ciygv._clickdupdombtn = null;
        }
        if (typeof opn.complete === 'function')
            opn.complete(xhr);
    }
    opn.success = function (data, xhr) {
        var ind = data.indexOf('{');
        if (ind > 0)
            data = data.substring(ind);
        var json = ciyfn.tojson(data);
        if (json.code == 1) {
            if (opn._load)
                opn._load.close('succ');
            if (ciy_vars.tokenfield) {
                var re = xhr.getResponseHeader('_re');
                if (re && funcname.indexOf('restorage') == -1
                    && document.location.pathname.indexOf('/rigger/cata.html') == -1
                    && document.location.pathname.indexOf('/rigger/admin.html') == -1
                ) {
                    ciyfn.sendsignal(window.top, 'restorage', { show: false });
                }
                if (json['_ciyauth'])
                    ciyfn.setstorage('_' + ciy_vars.tokenfield, json['_ciyauth']);
            }
            if (typeof (successfunc) == 'function')
                successfunc(json, xhr);
        } else if (json.code == 2) {
            if (ciy_vars.loginurl) {
                if (ciy_vars.loginurl)
                    top.location.href = '/' + ciy_vars.loginurl;
            } else {
                ciyfn.alert('No Login');
            }
        } else if (json.code == 3) {
            document.body.innerHTML = '<h1 style="text-align: center;margin-top: 0.5em;color: #ff0000;font-size: 2em;">' + json.errmsg + '</h1>';
        } else {
            if (opn._load)
                opn._load.close('fail');
            if (typeof (opn.fail) === 'function')
                opn.fail(json, xhr);
            else
                ciyfn.alert(json.errmsg);
        }
    }
    if (opn.showload)
        opn._load = new ciyclass.loading();
    ciyfn.ajax(opn);
}
ciyfn.ajax = function (opn) { //IE8 OK
    opn = opn || {};
    var header = opn.header || {};
    if (!header['Content-Type']) //header:{'Content-Type':'application/x-www-form-urlencoded'},
        header['Content-Type'] = 'application/json';
    var url = opn.url || '';
    var timeout = opn.timeout || 10;
    if (timeout < 1)
        timeout = 3;
    if (timeout > 20)
        header['ciy-timeout'] = timeout;

    var method = opn.method || 'POST';
    method = method.toUpperCase();
    if (method == 'GET' && typeof (opn.data) == 'object') {
        var datastr = "";
        for (var p in opn.data)
            datastr += "&" + encodeURIComponent(p) + "=" + encodeURIComponent(opn.data[p]);
        if (url.indexOf('?') == -1)
            url += '?' + datastr.substring(1);
        else
            url += datastr;
    }
    if (document.location.search) {
        if (url.indexOf('?') > -1)
            url += '&' + document.location.search.substring(1);
        else
            url += document.location.search;
    }
    var request = new XMLHttpRequest();
    request.withCredentials = true;
    request.open(method, url, true);
    if (typeof (header) == 'object') {
        for (var i in header) {
            if (header[i] !== undefined)
                request.setRequestHeader(i, "" + header[i]);
        }
    }
    var sendstr = null;
    if (method == 'POST' || method == 'PUT') {
        if (typeof (opn.data) == 'object') {
            if (header['Content-Type'] == 'application/x-www-form-urlencoded') {
                var sendstr = "";
                for (var p in opn.data)
                    sendstr += "&" + encodeURIComponent(p) + "=" + encodeURIComponent(opn.data[p]);
                sendstr = sendstr.substring(1);
            } else
                sendstr = ciyfn.jsontostr(opn.data);
        } else if (opn.data) {
            if (header['Content-Type'] == 'application/json') {
                var json = {};
                var ds = opn.data.split('&');
                for (var d in ds) {
                    var ind = ds[d].indexOf('=');
                    if (ind > 0)
                        json[ds[d].substring(0, ind)] = ds[d].substring(ind + 1);
                }
                sendstr = ciyfn.jsontostr(json);
            } else
                sendstr = "" + opn.data;
        }
    }
    request.timeout = timeout * 1000;
    request.ontimeout = function () {
        clearTimeout(aborttime);
        console.warn('request timeout: ' + timeout + 's');
    };
    request.send(sendstr);
    request.onreadystatechange = function () {
        if (this.readyState === 4) {
            clearTimeout(aborttime);
            if (typeof opn.done === 'function')
                opn.done(this);
            if (this.status >= 200 && this.status < 400) {
                if (typeof opn.success === 'function')
                    opn.success(this.responseText, this);
            } else {
                var errtxt = 'ErrCode:' + this.status;
                if (this.status == 200)
                    errtxt = 'Server Error: ' + this.responseText;
                else if (this.status == 404)
                    errtxt = "404 Not Found: " + this.responseURL;
                else if (this.status == 0)
                    errtxt = "Server No Response.";
                else
                    errtxt = 'ErrCode:' + this.status + "," + this.statusText;
                if (typeof opn.fail === 'function')
                    opn.fail({ errmsg: errtxt }, this);
                else
                    ciyfn.alert(errtxt);
            }
        }
    }
    var aborttime = window.setTimeout(function () {
        console.warn('ajax timeout abort: ' + timeout + 's');
        request.abort("timeout");
    }, timeout * 1000 + 3000);
}
ciyfn.ajaxsync = function (opn) {
    var method = opn.method || 'POST';
    var request;
    if (window.XMLHttpRequest) {
        request = new XMLHttpRequest();
    } else {
        request = new ActiveXObject("Microsoft.XMLHTTP");
    }

    try {
        request.open(method.toUpperCase(), opn.url, false);
        request.setRequestHeader("Content-type", "application/json");
        if (opn.data) {
            if (typeof (opn.data) == 'string')
                request.send(opn.data);
            else
                request.send(JSON.stringify(opn.data));
        } else {
            request.send();
        }
    } catch (err) {
        return {
            "errmsg": "ConnectFail"
        }
    }

    if (request.readyState == 4 && request.status == 200) {
        let res = JSON.parse(request.responseText)
        if (res.code == 0) {
            res.code = 1;
            return res;
        }
        res.errmsg = res.msg || res.message || '未知错误';
        return res;
    }
    return {
        "errmsg": "本地服务连接失败"
    };
}
ciyfn._getform_dom = function (dom) {
    var sep = ',';
    var retdata = {};
    var els = dom.querySelectorAll("input,textarea,select");
    for (var i = 0; i < els.length; i++) {
        if (!els[i].name)
            continue;
        var eltype = els[i].getAttribute('type');
        if (els[i].tagName == 'SELECT') {//即将废弃
            retdata[els[i].name] = els[i].value;
        } else if (eltype == 'file') {
        } else if (eltype == 'radio') {//即将废弃
            if (els[i].checked) {
                retdata[els[i].name] = els[i].value;
            } else if (retdata[els[i].name] === undefined) {
                retdata[els[i].name] = false;
            }
        } else if (eltype == 'checkbox') {//即将废弃
            if (els[i].checked) {
                if (retdata[els[i].name] === undefined) {
                    retdata[els[i].name] = sep + els[i].value + sep;
                } else {
                    retdata[els[i].name] += els[i].value + sep;
                }
            }
        } else {
            if (retdata[els[i].name] === undefined)
                retdata[els[i].name] = els[i].value;
            else
                retdata[els[i].name] += sep + els[i].value;
        }
    }
    return retdata;
}
ciyfn.getform = function (dom, parentTag) {
    while (true) {
        if (dom.tagName == parentTag)
            break;
        if (dom.tagName == 'BODY' || dom.tagName == 'FORM')
            break;
        if (!dom.parentNode)
            break;
        dom = dom.parentNode;
    }
    var retdata = ciyfn._getform_dom(dom);
    return retdata;
}
ciyfn.showimg = function (idx, imgstr, act) {
    ciyfn.alert({
        frame: '/jscss/imgreview.html?idx=' + idx + '&act=' + act + '&imgs=' + encodeURIComponent(imgstr)
        , title: null
        , noclosebtn: true
        , width: 'max'
        , height: 'max'
        , btns: null
    });
}
ciyfn.makeuploadpath = function (mpath, saas) {
    var path = '{Y}/{m}{d}/' + mpath;
    if (saas && saas.saasid && saas.saaspre)
        path = saas.saaspre + toint(saas.saasid / 1000) + '/' + saas.saasid + '/' + path;
    return path;
}
ciyfn.ccode = function (arr, value, field, nonestr) {
    field = field || 'name';
    if (typeof (nonestr) === 'undefined')
        nonestr = '--';
    arr = ciyfn.getdictdata(arr);
    if (typeof (arr) != 'object')
        return '!';
    for (var i = 0; i < arr.length; i++) {
        if (arr[i].id == value) {
            if (field == 'idx')
                return i;
            if (field == '_obj')
                return arr[i];
            if (arr[i][field])
                return arr[i][field];
            return nonestr;
        }
    }
    if (field == '_obj')
        return null;
    if (!value)
        return nonestr;
    return '';
}
ciyfn.scode = function (arr, ids, field) {
    arr = ciyfn.getdictdata(arr);
    if (typeof (arr) != 'object')
        return ['!'];
    ids = ids || '';
    var vals = ids.split(',');
    var rets = [];
    for (var v = 0; v < vals.length; v++) {
        for (var i = 0; i < arr.length; i++) {
            if (arr[i].id != vals[v])
                continue;
            if (field)
                rets.push(arr[i][field]);
            else
                rets.push(arr[i]);
        }
    }
    return rets;
}
ciyfn.mcode = function (arr, value, field) {
    arr = ciyfn.getdictdata(arr);
    if (typeof (arr) != 'object')
        return [];
    var ret = [];
    for (var x = 0; x < 100; x++) {
        var bfind = false;
        for (var i = 0; i < arr.length; i++) {
            if (arr[i].id == value) {
                bfind = true;
                value = arr[i].upid;
                if (field)
                    ret.unshift(arr[i][field]);
                else
                    ret.unshift(arr[i]);
                break;
            }
        }
        if (!bfind)
            break;
    }
    return ret;
}
ciyfn.arr_treemap = function (rows, upid) {
    var tree = [];
    for (var i = 0; i < rows.length; i++) {
        var item = rows[i];
        if (item.upid != upid)
            continue;
        var child = ciyfn.arr_treemap(rows, item.id);
        if (Object.keys(child).length > 0)
            item.child = child;
        tree.push(item);
    }
    return tree;
}
ciyfn.urlparam = function (url) {
    var obj = {};
    if (url) {
        if (url.indexOf('?') == -1)
            return obj;
        url = url.substring(url.indexOf('?'));
    } else
        url = document.location.search;
    if (url[0] != '?')
        return obj;
    var pairs = url.substring(1).split('&');
    for (var p in pairs) {
        var ind = pairs[p].indexOf('=');
        if (ind > -1)
            obj[decodeURIComponent(pairs[p].substring(0, ind))] = decodeURIComponent(pairs[p].substring(ind + 1));
        else
            obj[decodeURIComponent(pairs[p])] = true;
    }
    return obj;
}
ciyfn.sendsignal = function (win, func, data) {
    data = data || {};
    data.func = func;
    if (win)
        win.postMessage(data, '*');
}
ciyfn.inmobile = function () {
    return /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent);
}
ciyclass.mask = function () {
    var thos = this;
    var clickfn = null;
    var maskdom = $5('<div class="ciy-mask"></div>');
    $5('body').prepend(maskdom);
    maskdom.on('click', function (e) {
        if (typeof clickfn == 'function') {
            var ret = clickfn(thos, e);
            if (ret === false)
                return;
            clickfn = null;
        } else
            thos.hide();
    });
    maskdom.on('contextmenu', function (e) {
        thos.hide();
        if (typeof clickfn == 'function') {
            clickfn(thos, e);
            clickfn = null;
        }
        e.preventDefault();
        return false;
    });
    this.show = function (fn, css) {
        if (isobj(css))
            maskdom.css(css);
        clickfn = fn;
        maskdom.css('display', 'block');
    }
    this.hide = function () {
        maskdom.css('display', 'none');
    }
    return this;
}
ciyfn.popmenu = function (e, popmenu) {
    var pmdom;
    if (isarray(popmenu)) {
        var html = '';
        html += '<ul class="ciy-popmenu">';
        for (var i = 0; i < popmenu.length; i++) {
            html += '<li';
            for (var key in popmenu[i]) {
                html += ' data-' + key + '="' + popmenu[i][key] + '"';
            }
            html += '>' + popmenu[i].title + '</li>';
        }
        html += '</ul>';
        pmdom = $5(html);
        pmdom.css('position', 'fixed');
        $5('body').append(pmdom);
    } else {
        pmdom = $5(popmenu);
    }
    $5('body').append(pmdom);
    var winWidth = document.documentElement.clientWidth;
    var winHeight = document.documentElement.clientHeight;
    var mouseX = e.clientX;
    var mouseY = e.clientY;
    pmdom.css({ 'display': 'block' });
    var menuWidth = pmdom.width();
    var menuHeight = pmdom.height();
    var menuLeft, menuTop;
    if (mouseX + menuWidth >= winWidth &&
        mouseY + menuHeight >= winHeight) {
        menuLeft = mouseX - menuWidth;
        menuTop = mouseY - menuHeight;
    } else if (mouseX + menuWidth >= winWidth) {
        menuLeft = mouseX - menuWidth;
        menuTop = mouseY;
    } else if (mouseY + menuHeight >= winHeight) {
        menuLeft = mouseX;
        menuTop = mouseY - menuHeight;
    } else {
        menuLeft = mouseX;
        menuTop = mouseY;
    };
    ciygv.mask.show(function () {
        pmdom.remove();
    }, { zIndex: 10000 });
    pmdom.css({ 'left': menuLeft + "px", 'top': menuTop + "px", 'zIndex': 10001 });
    return pmdom;
}
ciyfn.showmap = function (lat, lng, zoom) {
    ciyfn.alert({
        title: '地图位置',
        width: 'max',
        height: 'max',
        frame: '/jscss/map_loc.html?lat=' + lat + "&lng=" + lng + '&zoom=' + zoom
    });
}
ciyfn.alert = function (content, cb, opn) {
    if (typeof (content) == 'string') {
        opn = opn || {};
        if (typeof (cb) == 'function')
            opn.cb = cb;
        opn.content = content;
        if (opn.maskclose === undefined)
            opn.maskclose = true;
    } else {
        opn = content || {};
        if (typeof (cb) == 'function')
            opn.cb = cb;
        opn.content = opn.content || '';
        if (opn.maskclose === undefined)
            opn.maskclose = false;
    }
    opn.autoheight = opn.autoheight || true;
    try {
        if (!opn.noparent && window.parent != window && window.parent.ciyfn.alert)
            return window.parent.ciyfn.alert(opn);
    } catch { }
    var contentstyle = opn.contentstyle || '';
    if (opn.width) {
        if (opn.width == 'mb')
            contentstyle += 'width: 27em;';
        else if (opn.width == 'pc')
            contentstyle += 'width:' + ((57 * 14 > window.innerWidth) ? '27em' : '57em') + ';';
        else
            contentstyle += 'width: ' + opn.width + ';';
    }
    if (opn.height) {
        if (opn.height == 'mb')
            contentstyle += 'height:' + (window.innerHeight - 80) + 'px;';
        else if (opn.height == 'pc')
            contentstyle += 'height:' + (window.innerHeight - 100) + 'px;';
        else
            contentstyle += 'height: ' + opn.height + ';';
    }
    ciygv.zindex += 3;

    var htmldom = '<div';
    if (opn.stopclick)
        htmldom += ' onclick="event.stopPropagation();"';
    htmldom += ' class="ciy-layer ciy-dialog" style="opacity:0;top:-100vh;z-index: ' + (ciygv.zindex - 1) + ';">';
    if (opn.title !== null) {
        opn.title = opn.title || "温馨提示";
        htmldom += '<div class="title flex flex-center" onselectstart="return false"><div class="flex1">' + ciyfn.lang(opn.title) + '</div>';
        if (!opn.noclosebtn)
            htmldom += '<div class="ciy-close close"></div>';
        htmldom += '</div>';
    } else {
        if (!opn.noclosebtn)
            htmldom += '<div class="abs r0 t0" style="background:var(--bg6);border-radius:50%;z-index:1;padding: 0.3em;"><div class="ciy-close close" style="width: 0.7em;height: 0.7em;"></div></div>';
    }

    if (opn.frame) {
        opn.btns = opn.btns || null;
        htmldom += '<div class="content" style="padding:0;' + contentstyle + '">';
        htmldom += '<iframe src="' + opn.frame + '" style="display:block;width:100%;height:100%;" frameborder="0"></iframe>';
        htmldom += '</div>';
    } else {
        htmldom += '<div class="content"';
        if (contentstyle != '')
            htmldom += ' style="' + contentstyle + '"';
        htmldom += '>' + ciyfn.lang(opn.content) + '</div>';
    }
    if (opn.btns !== null) {
        if (!isarray(opn.btns))
            opn.btns = ["*关闭"];
        var btn = '';
        for (var i = 0; i < opn.btns.length; i++) {
            if (opn.btns[i][0] == '*') //灰色按钮
                btn += "<a class='lang btn def btnalert' data-btn='" + opn.btns[i].substring(1) + "'>" + opn.btns[i].substring(1) + "</a>";
            else if (opn.btns[i][0] == '!') //暗红色按钮
                btn += "<a class='lang btn dag btnalert' data-btn='" + opn.btns[i].substring(1) + "'>" + opn.btns[i].substring(1) + "</a>";
            else if (opn.btns[i][0] == '#') //保存按钮
                btn += "<a class='lang btn warn ctrl_s btnalert' data-btn='" + opn.btns[i].substring(1) + "'>" + opn.btns[i].substring(1) + "</a>";
            else if (opn.btns[i][0] != '<') //普通蓝色按钮
                btn += "<a class='lang btn btnalert' data-btn='" + opn.btns[i] + "'>" + opn.btns[i] + "</a>";
            else
                btn += opn.btns[i]; //html自定义按钮
        }
        htmldom += '<div class="buttons">' + btn + '</div>';
    }
    htmldom += '</div>';
    htmldom = $5(htmldom);
    var domifm = $5("iframe", htmldom);
    if (domifm.length > 0) {
        domifm[0].onload = function (e) {
            var thos = this;
            ciygv.messagefn['alert_done'] = function (msgevent) {
                if (typeof (opn.cb) != 'function')
                    return alertclose();
                opn.cb({
                    dombtn: domifm[0],
                    btn: msgevent.data.btn || '按钮',
                    inputs: msgevent.data.inputs,
                    dom: htmldom,
                    doc: document,
                    close: function () {
                        alertclose();
                    }
                });
            };
            if (opn.autoheight) {
                ciygv.messagefn['alert_mywh'] = function (msgevent) {
                    setrect(msgevent.data.width, msgevent.data.height);
                };
                opn._interval = setInterval(function () {
                    ciyfn.sendsignal(thos.contentWindow, 'alert_getwh');
                }, 300);
            }
            setrect(htmldom.find('.content').height(), 300, true);
        };
    }
    if (opn.btns !== null) {
        htmldom.on('click', '.btnalert', function (e) {
            var inputs = ciyfn._getform_dom(htmldom[0]);
            if (typeof (opn.cb) != 'function')
                return alertclose();
            opn.cb({
                dombtn: e.currentTarget,
                btn: e.currentTarget.getAttribute('data-btn'),
                inputs: inputs,
                dom: htmldom,
                doc: document,
                close: function () {
                    alertclose();
                }
            });
        });
    }
    htmldom.on('click', '.close', function () {
        alertclose();
    });

    ciygv.mask.show(function () {
        if (opn.maskclose) {
            alertclose();
        } else
            return false;
    }, { zIndex: ciygv.zindex - 2 });
    $5('body').append(htmldom);
    if (domifm.length == 0) {
        if (typeof (opn.fn_showed) == 'function')
            opn.fn_showed(document, htmldom);
        var contentdom = htmldom.find('.content')[0];
        opn._interval = setInterval(function () {
            setrect(contentdom.scrollWidth, contentdom.scrollHeight);
        }, 100);
        setrect(contentdom.scrollWidth, contentdom.scrollHeight, true);
    }
    ciyfn.domlang();
    if (opn.width != 'max') {
        //增加拖动效果
        if (opn.title !== null) {
            if (!('ontouchstart' in window)) {
                var dodrag = null;
                htmldom.on('mousedown', '.title', function (ev) {
                    if (ev.target.classList.contains('close'))
                        return;
                    var mainRect = htmldom.rect();
                    dodrag = {};
                    dodrag.mainX = ev.clientX - mainRect.left;
                    dodrag.mainY = ev.clientY - mainRect.top;
                    htmldom.css({ opacity: 0.8 });
                    $5(document).on('mouseup', function () {
                        dodrag = null;
                        htmldom.css({ opacity: 1 });
                        htmldom.off('mouseup');
                        htmldom.off('mousemove');
                    }).on('mousemove', function (ev) {
                        if (dodrag == null)
                            return;
                        htmldom.css({ 'left': ev.pageX - dodrag.mainX - window.scrollX, 'top': ev.pageY - dodrag.mainY - window.scrollY });
                    });
                });
            }
        }
    }
    if (opn.width == 'max' && opn.height == 'max')
        $5('body').css('overflow', 'hidden');
    var lastwh;
    function setrect(newwidth, newheight, bfirst) {
        var titbtnheight = toint(htmldom.find('.title').height()) + toint(htmldom.find('.buttons').height());
        lastwh = lastwh || { w: 0, h: 0 };
        if (Math.abs(newwidth - lastwh.w) < 5 && Math.abs(newheight - lastwh.h) < 5)
            return;
        lastwh = { w: newwidth, h: newheight };
        var ctheight = newheight;
        if (ctheight > window.innerHeight) {
            ctheight = window.innerHeight;
            if (opn.title !== null)
                ctheight -= titbtnheight + 20;
        }
        htmldom.find('.content').css('height', (ctheight + 2) + 'px');
        var dialogcss = {};
        var w = toint(htmldom.find('.content').css().width) + 5;
        if (!opn.width && opn.frame) {
            if ('ontouchstart' in window)
                w = window.innerWidth - 10;
            else
                w = window.innerWidth - 40;
            if (w > newwidth)
                w = newwidth;
        } else if (opn.width == 'max')
            w = window.innerWidth - 10;
        else if (window.innerWidth - w < 30)
            w = window.innerWidth - 30;
        if (w < 300)
            w = 300;
        if (Math.abs(w - toint(htmldom.css().width)) > 6)
            dialogcss.width = w + 'px';
        dialogcss.height = 'auto';
        var h = toint(htmldom.css().height);
        if (opn.height == 'max') {
            h = window.innerHeight - 10;
            dialogcss.height = h + 'px';
            htmldom.find('.content').css('height', (h - titbtnheight) + 'px');
        } else if (window.innerHeight - h <= 20) {
            h = window.innerHeight - 20;
            dialogcss.height = h + 'px';
            htmldom.find('.content').css('height', (h - titbtnheight) + 'px');
        } else {
            htmldom.find('.content').css('height', (h - titbtnheight) + 'px');
        }
        dialogcss.top = ((window.innerHeight - h) / 3) + 'px';
        if (opn.align === 'left') {
            dialogcss.left = '10px';
        } else if (opn.align === 'right') {
            dialogcss.right = '10px';
            dialogcss.left = 'auto';
        } else {
            dialogcss.left = ((window.innerWidth - w) / 2) + 'px';
        }
        htmldom.css(dialogcss);
        if (bfirst) {
            setTimeout(function () {
                htmldom.css({ transition: null, opacity: 1 });//'all .3s'
            }, 0);
            // setTimeout(function () {
            //     htmldom.css({ transition: null });
            // }, 600);
        }
    }

    function alertclose() {
        clearInterval(opn._interval);
        ciygv.mask.hide();
        if (opn.width == 'max' && opn.height == 'max')
            $5('body').css('overflow', '');
        var domifm = $5("iframe", htmldom);
        if (domifm.length > 0) {
            domifm[0].src = 'about:blank';
            try {
                domifm[0].contentWindow.close();
            } catch (err) { }
        }
        htmldom.remove();
    }
    return false;
}
ciyfn.toast = function (content, cb, opn) {
    if (typeof (content) == 'string') {
        opn = opn || {};
        if (typeof (cb) == 'function')
            opn.cb = cb;
        opn.content = content;
    } else {
        opn = content || {};
        if (typeof (cb) == 'function')
            opn.cb = cb;
        opn.content = opn.content || '';
    }
    if (opn.maskclose === undefined)
        opn.maskclose = true;
    try {
        if (window.parent != window && window.parent.ciyfn.toast)
            return window.parent.ciyfn.toast(opn);
    } catch { }
    var htmldom = '<div class="ciy-layer ciy-toast" style="left:-100vw;z-index: ' + ciygv.zindex + ';">' + ciyfn.lang(opn.content) + '</div>';
    htmldom = $5(htmldom);
    if (opn.maskclose) {
        ciygv.mask.show(function () {
            toastclose();
        }, { zIndex: ciygv.zindex++ });
    } else {
        htmldom.on('click', function () {
            toastclose();
        });
    }
    if (opn.timeout === undefined)
        opn.timeout = 2;
    setTimeout(function () {
        toastclose();
    }, opn.timeout * 1000);
    $5('body').append(htmldom);
    var iw = window.innerWidth;
    var ih = window.innerHeight;
    setTimeout(function () {
        htmldom.css({ 'left': ((iw - toint(htmldom.css().width)) / 2) + 'px', 'top': ((ih - htmldom.rect().height) / 3) + 'px' });
    }, 90);
    function toastclose() {
        if (typeof (opn.cb) == 'function')
            opn.cb();
        ciygv.mask.hide();
        htmldom.remove();
    }
    return false;
}
ciyfn.showend = function (opn) {
    if (typeof (opn) === 'string') {
        var strs = opn.split('|');
        opn = {};
        opn.content = strs[0];
        if (strs.length > 1)
            opn.title = strs[1];
    }
    opn.timeout = opn.timeout || 10;

    var dom = $5('.ciy-showend');
    if (dom.length == 0) {
        dom = $5('<div class="ciy-showend"></div>');
        dom.css('zIndex', ciygv.zindex++);
        $5('body').append(dom);
    }
    var istyle = 'background:var(--man5);';
    if (opn.icon == 'fail')
        istyle = 'background:var(--dag5);';
    if (opn.icon == 'warn')
        istyle = 'background:var(--warn5);';
    if (opn.icon == 'msg')
        istyle = 'background:var(--succ5);';
    var html = '<div class="ciy-showend-view"><i style="' + istyle + '"></i><b>×</b>';
    if (opn.title)
        html += '<h3>' + opn.title + '</h3>';
    else
        html += '<div style="height:0.5em;"></div>';
    html += '<div>' + opn.content + '</div><span class="ciy-showend-view-es"></span></div>';
    var viewdom = $5(html);

    viewdom.on('click', 'b', function (e) {
        if (opn._inter)
            clearInterval(opn._inter);
        var medom = e.currentTarget.parentNode;
        medom.style.height = medom.clientHeight + "px";
        medom.style.overflow = 'hidden';
        medom.style.transition = "all .5s";
        setTimeout(function () {
            setTimeout(function () {
                if (medom === null || medom.parentNode === null)
                    return;
                var pdom = medom.parentNode;
                pdom.removeChild(medom);
                if (pdom.children.length == 0)
                    pdom.parentNode.removeChild(pdom);
            }, 500);
            medom.style.marginBottom = 0;
            medom.style.height = 0;
            medom.style.opacity = 0;
        }, 1);
        if (typeof (opn.cb) == 'function')
            opn.cb(opn);
    });
    dom.prepend(viewdom);
    if (opn.timeout >= 1) {
        opn._span = toint(opn.timeout);
        opn._inter = setInterval(function () {
            opn._span--;
            $5('span.ciy-showend-view-es', viewdom).text(opn._span);
        }, 1000);
        setTimeout(function () { $5('b', viewdom).trigger('click') }, opn.timeout * 1000);
    }
}
ciyfn.dropmenu = function (dom) {
    dom = $5(dom);
    if ('ontouchend' in window) {
        dom.on("click", function () {
            if (dom.hasClass('show')) {
                dom.removeClass('show');
                ciygv.mask.hide();
                return;
            }
            var menudom = $5(this);
            showmenu(menudom);
        });
    } else {
        dom.on("mouseenter", function () {
            var menudom = $5(this);
            showmenu(menudom);
            menudom.one("mouseleave", function () {
                menudom.removeClass('show');
                menudom.css('zIndex', null);
                ciygv.mask.hide();
            });
        });
    }
    function showmenu(menudom) {
        ciygv.mask.show(function () {
            menudom.removeClass('show');
        }, { zIndex: 10 });
        menudom.css('zIndex', 30);
        menudom.addClass('show');
        var domrect = menudom.rect();
        var top = domrect.top;
        var left = domrect.left;
        var uldom = $5('ul', menudom);
        var ulrect = uldom.rect();
        uldom.css('inset', null);
        var menuwidth = ulrect.width;
        var menuheight = ulrect.height;
        var direction = menudom.attr('direction');
        if (direction == 'lr')
            left += domrect.width;
        if ($5(document).width() < left + menuwidth) {
            if (direction == 'lr')
                left = domrect.left - menuwidth;
            else
                left = $5(document).width() - menuwidth - 2;
        }
        if (left < 0)
            left = 0;

        if (top + menuheight + 40 < document.documentElement.clientHeight) {
            if (direction != 'lr')
                top += domrect.height;
            uldom.css({ 'position': 'fixed', 'left': left + 'px', 'top': top + 'px', 'bottom': 'auto' });
        } else {
            if (direction == 'lr')
                top += domrect.height;
            if (top < menuheight) {
                var meheight = domrect.height;
                if (document.documentElement.clientHeight > menuheight + meheight)
                    uldom.css({ 'position': 'fixed', 'left': left + 'px', 'top': meheight + 'px', 'bottom': 'auto' });
                else
                    uldom.css({ 'position': 'fixed', 'left': left + 'px', 'top': meheight + 'px', 'bottom': 0, 'overflowY': 'auto' });
            }
            else {
                uldom.css({ 'position': 'fixed', 'left': left + 'px', 'top': (top - menuheight) + 'px', 'bottom': 'auto' });
            }
        }
    }
}
ciyclass.tabcard = function (opn) {
    opn = opn || {};
    var thos = this;
    this.onchange = opn.onchange || null;
    opn.dom = $5(opn.dom);
    if (opn.dom.length == 0)
        return this;
    var lidoms = $5('.ciy-tabcard>ul>li', opn.dom);
    var contentdoms = $5('.ciy-tabcard>div>div.tabcontent', opn.dom);
    if (contentdoms.length > 0 && contentdoms.length != lidoms.length)
        return console.error('tabcard: tabcontent.length != li.length');
    contentdoms.css('display', 'none');
    if (typeof (opn.value) !== 'undefined')
        tocard(opn.value, 'init');
    if (opn.liid > 0) {
        lidoms.each(function (dom, i) {
            if ($5(dom).attr('data-liid') == opn.liid)
                tocard(i, 'init');
        });
    }
    else if ($5('ul>li.active', opn.dom).length == 0)
        tocard(0, 'init');
    else {
        lidoms.each(function (dom, i) {
            if ($5(dom).hasClass('active'))
                tocard(i, 'init');
        });
    }
    opn.dom.on('click', '.ciy-tabcard>ul>li', function (ev) {
        lidoms.removeClass('active');
        if (contentdoms.length > 0)
            contentdoms.css('display', 'none');
        lidoms.each(function (dom, i) {
            if (dom == ev.currentTarget) {
                tocard(i, 'click');
            }
        });
    });
    this.setbyvalue = function (index) {
        if (index < 0 || index >= lidoms.length)
            return;
        tocard(index, 'selectcard');
    }
    this.setbyliid = function (liid) {
        lidoms.each(function (dom, i) {
            if ($5(dom).attr('data-liid') == liid)
                tocard(i, 'selectcard');
        });
    }
    function tocard(i, from) {
        lidoms.removeClass('active');
        if (contentdoms.length > 0)
            contentdoms.css('display', 'none');
        lidoms.eq(i).addClass('active');
        if (contentdoms.length > 0) {
            var disply = contentdoms.eq(i).attr('data-display');
            contentdoms.eq(i).css('display', disply ? disply : 'block');
        }
        if (typeof (thos.onchange) == 'function')
            thos.onchange({ index: i, lidom: lidoms[i], contentdom: contentdoms[i], from: from });
    }
    return this;
}
ciyfn.lazyimg = function () {
    if (+new Date() - ciygv._lazyimg < 500)
        return;
    ciygv._lazyimg = +new Date();
    var imgdoms = document.querySelectorAll('img[data-src]');
    for (var i = 0, len = imgdoms.length; i < len; i++) {
        var rect = imgdoms[i].getBoundingClientRect();
        if (rect.left == 0 && rect.right == 0)
            continue;
        if (rect.top < document.documentElement.clientHeight && !imgdoms[i].src) {
            imgdoms[i].src = imgdoms[i].getAttribute("data-src");
            imgdoms[i].removeAttribute("data-src");
        }
    }
}
ciyfn.getstorage = function (key, def) {
    def = def || '';
    var val = localStorage.getItem(key);
    if (val === undefined || val === null || val === '')
        return def;
    var fst = val.substring(0, 1);
    if (fst != '[' && fst != '{')
        return val;
    return ciyfn.tojson(val);
}
ciyfn.setstorage = function (key, value) {
    if (isarray(value) || isobj(value))
        value = ciyfn.jsontostr(value);
    localStorage.setItem(key, value);
}
ciyfn.removestorage = function (key) {
    localStorage.removeItem(key);
}
ciyfn.savedict = function (arr) {
    for (var code in arr) {
        if (code != 'cata') {
            ciyfn.setstorage('cata_' + code, arr[code]);
            continue;
        }
        for (var c in arr[code]) {
            if (arr[code][c].cbid > 0)
                continue;
            var types = arr[code][c].codeid;
            var codes = new Array();
            for (var d in arr[code]) {
                if (arr[code][d].cbid != arr[code][c].id)
                    continue;
                var cs = {};
                cs.id = arr[code][d].codeid;
                cs.name = arr[code][d].name;
                if (arr[code][d].extdata)
                    cs.extdata = arr[code][d].extdata;
                if (arr[code][d].clas)
                    cs.clas = arr[code][d].clas;
                if (arr[code][d].isuse != 1)
                    cs.isuse = 2;
                if (arr[code][d].upid > 0) {
                    for (var i in arr[code]) {
                        if (arr[code][d].upid == arr[code][i].id) {
                            cs.upid = arr[code][i].codeid;
                            break;
                        }
                    }
                }
                codes.push(cs);
            }
            if (types != '')
                ciyfn.setstorage('cata_' + types, codes);
        }
    }
}
ciyfn.totimepoint = function (time, bsecond) {
    if (time <= 0 || time > 86400)
        return '';
    time--;
    var hour = toint(time / 3600);
    var minute = toint((time - hour * 3600) / 60);
    var ret = ciyfn.topad0(hour) + ':' + ciyfn.topad0(minute);
    if (!bsecond)
        return ret;
    var second = time - hour * 3600 - minute * 60;
    ret += ':' + ciyfn.topad0(second);
    return ret;
}
ciyfn.totimespan = function (time, futstr, befstr) {
    if (futstr === undefined)
        futstr = "后";
    if (befstr === undefined)
        befstr = "前";
    var t;
    if (/^\d+$/.test(time)) {
        if (time == 0)
            return '--';
        t = new Date(time * 1000);
    } else {
        t = new Date(time.replace(/\-/g, '/'));
    }
    if (isNaN(t.getTime()))
        return 'ERR';
    var diffsec = (new Date() - t);
    diffsec = toint(diffsec / 1000);
    if (diffsec > 0)
        return ciyfn.totimesec(diffsec, befstr);
    return ciyfn.totimesec(-diffsec, futstr);
}
ciyfn.totimesec = function (sec, bestr, nowstr) {
    if (bestr === undefined)
        bestr = "";
    if (nowstr === undefined)
        nowstr = ciyfn.lang("刚刚");
    if (sec < 0)
        return '--';
    if (sec < 3) //3秒以内
        return nowstr;
    if (sec < 60) //60秒以内
        return sec + ciyfn.lang("秒") + bestr;
    if (sec < 3600) //60分以内
        return parseInt(sec / 60) + ciyfn.lang("分钟") + bestr;
    if (sec < 86400) //24小时以内
        return parseInt(sec / 3600) + ciyfn.lang("小时") + bestr;
    if (sec < 2592000) //30天以内
        return parseInt(sec / 86400) + ciyfn.lang("天") + bestr;
    if (sec < 31536000) //12月以内
        return parseInt(sec / 2592000) + ciyfn.lang("个月") + bestr;
    return parseInt(sec / 31536000) + ciyfn.lang("年") + bestr;
}
ciyfn.todatetime = function (time, format, zero) {
    if (zero === undefined)
        zero = "--";
    var t;
    if (time instanceof Date)
        t = time;
    else if (time == -1 || time === undefined)
        t = new Date();
    else if (/^\d+$/.test(time)) {
        if (time == 0)
            return zero;
        t = new Date(time * 1000);
    } else {
        t = new Date((time + '').replace(/\-/g, '/'));
    }
    if (isNaN(t.getTime()))
        return '';
    if (!format)
        format = 'Y-m-d H:i';
    var ret = format;
    ret = ret.replace('yyyy', t.getFullYear()).replace('Y', t.getFullYear());
    ret = ret.replace('y', (t.getFullYear() + "").substring(2));
    ret = ret.replace('m', ciyfn.topad0(t.getMonth() + 1));
    ret = ret.replace('n', t.getMonth() + 1);
    ret = ret.replace('d', ciyfn.topad0(t.getDate()));
    ret = ret.replace('j', t.getDate());
    ret = ret.replace('H', ciyfn.topad0(t.getHours()));
    ret = ret.replace('G', t.getHours());
    ret = ret.replace('h', ciyfn.topad0(t.getHours() % 12));
    ret = ret.replace('g', t.getHours() % 12);
    ret = ret.replace('i', ciyfn.topad0(t.getMinutes()));
    ret = ret.replace('sss', ciyfn.topad0(t.getMilliseconds(), 3));
    ret = ret.replace('s', ciyfn.topad0(t.getSeconds()));
    if (t.getHours() < 12)
        ret = ret.replace('A', 'AM').replace('a', 'am');
    else
        ret = ret.replace('A', 'PM').replace('a', 'pm');
    ret = ret.replace('w', t.getDay());
    return ret;
}
ciyfn.todayage = function (time, noday) {
    if (time == 0 || time === undefined)
        return '--';
    var t = new Date(time * 1000);
    var diff = (new Date() - t) / 1000;
    diff = parseInt(diff / 86400) + 1;
    if (diff < 30) //30天以内
        return diff + "天";
    var month = parseInt(diff / 30);
    if (noday)
        return month + '个月';
    return month + '个月 ' + (diff - month * 30) + '天';
}
ciyfn.tofix = function (val, length) {
    //length，正数，小数点保留n位，不去0。
    //负数，小数点保留n位，末尾去零。
    //0，按数长保留，尽量少的位数显示。
    //不填，-4
    var num = parseFloat(val);
    if (isNaN(num))
        num = 0;
    if (length === undefined)
        length = -4;
    if (length == 0) {
        if (num >= 1000)
            return parseInt(num);
        var numlen = (parseInt(num) + '').length;
        length = 4 - numlen;
        if (Math.abs(num % 1) < Math.pow(0.1, length))
            return parseInt(num);
        num = num.toFixed(length);
        var y = '.';
        for (var i = 0; i < length; i++)
            y += "0";
        if (num.substring(num.length - length - 1) == y)
            num = num.substring(0, num.length - length - 1);
        return num;
    } else if (length < 0) {
        length = -length;
        num = num.toFixed(length); //xx.xx
        var numd = num.split('.')[1];
        var numd0 = true;
        for (var i = 0; i < numd.length; i++) {
            if (numd.charAt(i) != '0') {
                numd0 = false;
                break;
            }
        }
        if (numd0)
            num = num.split('.')[0];
        return num;
    }
    num = num.toFixed(length);
    return num;
}

ciyfn.tonumtho = function (num) {
    return parseInt(num).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
ciyfn.tonumdec = function (num, showzero, len) {
    len = len || 2; // 与tofix不同点，小数长度不变，如 1.10
    var m2 = Math.ceil((num - parseInt(num)) * 100);
    if (m2 < 10)
        m2 = '0' + m2;
    else
        m2 = m2 + '';
    if (showzero)
        return '.' + m2;
    if (m2 == '00')
        return '';
    else
        return '.' + m2;
}
ciyfn.objclone = function (obj) {
    if (obj instanceof Array | obj instanceof Object) {
        var copy = (obj instanceof Array) ? [] : {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr))
                copy[attr] = ciyfn.objclone(obj[attr]);
        }
        return copy;
    }
    return obj;
}
ciyfn.objdeepmerge = function (src, desc, btop) {
    if (src === undefined)
        return desc;
    for (const key in desc) {
        if (!desc.hasOwnProperty(key))
            continue;
        if (desc[key] instanceof Array) {
            if (!(src[key] instanceof Array))
                src[key] = [];
            if (key.substring(0, 4) == 'ciy_')
                src[key] = desc[key];
            else {
                let srcidmap = {};
                for (let i in src[key]) {
                    srcidmap[src[key][i].id] = parseInt(i) + 1;
                }
                for (let i in desc[key]) {
                    if (desc[key][i].id && srcidmap[desc[key][i].id]) {
                        src[key][srcidmap[desc[key][i].id] - 1] = ciyfn.objdeepmerge(src[key][srcidmap[desc[key][i].id] - 1], desc[key][i]);
                        continue;
                    }
                    if (btop)
                        src[key].unshift(desc[key][i]);
                    else
                        src[key].push(desc[key][i]);
                }
            }
        } else if (desc[key] instanceof Object) {
            src[key] = ciyfn.objdeepmerge(src[key] || {}, desc[key]);
        } else {
            if (src[key] != desc[key])
                src[key] = desc[key];
        }
    }
    if (desc && !desc.errmsg && src.errmsg)
        delete src.errmsg;
    return src;
}
ciyfn.isfloat0 = function (num) {
    num = parseFloat(num);
    if (isNaN(num))
        return true;
    return (num < 0.001 && num > -0.001);
}
ciyfn.topad0 = function (num, length) {
    length = length || 2;
    if ((num + "").length > length)
        return num;
    return (Array(length).join('0') + num).slice(-length);
}
ciyfn.trim = function (str, char) {
    str = str.trim();
    let start = 0;
    let end = str.length;
    while (start < end && str[start] === char) start++;
    while (end > start && str[end - 1] === char) end--;
    return str.slice(start, end);
}
ciyfn.copyboard = function (txt, cb) {
    if (window.clipboardData) {
        window.clipboardData.clearData();
        clipboardData.setData('Text', txt);
        if (typeof (cb) == 'function')
            cb();
        else
            ciyfn.toast(ciyfn.lang('已复制到剪贴板'));
    } else {
        var input = document.createElement('textarea');
        input.value = txt;
        document.body.appendChild(input);
        input.select();
        if (document.execCommand('Copy')) {
            if (typeof (cb) == 'function')
                cb();
            else
                ciyfn.toast(ciyfn.lang('已复制到剪贴板'));
        } else {
            if (typeof (cb) == 'function')
                cb();
            else
                ciyfn.alert(ciyfn.lang('复制剪贴板失败'));
        }
        document.body.removeChild(input);
    }
}
ciyfn.getstrparam = function (str, split) {
    if (!str)
        return {};
    if (split === undefined)
        split = '|';
    var strs = str.split(split);
    var ret = {};
    for (var i in strs) {
        var ind = strs[i].indexOf('=');
        if (ind == -1)
            continue;
        ret[strs[i].substring(0, ind)] = strs[i].substring(ind + 1);
    }
    return ret;
}
ciyfn.setstrparam = function (obj, split) {
    if (split === undefined)
        split = '|';
    var ret = [];
    for (var key in obj) {
        ret.push(key + '=' + obj[key]);
    }
    return ret.join(split);
}
ciyfn.file_ext = function (file) {
    var ind = file.lastIndexOf(".");
    if (ind == -1)
        return '';
    var ext = file.substring(ind + 1).toUpperCase();
    if (ext == 'JPEG' || ext == 'JPE')
        ext = 'JPG';
    return ext;
}
ciyfn.file_stor = function (url, pre) {
    if (!url)
        return '';
    if (url.substring(0, 4).toLowerCase() == 'http')
        return url;
    return ciy_vars.storlist[url[0]] + url.substring(1) + (pre ? pre : '');
}
ciyfn.isimg = function (ext) {
    if (ext.indexOf('.') > 0)
        ext = ciyfn.file_ext(ext);
    return (["PNG", "JPG", "GIF", "BMP", "WEBP", "SVG"].indexOf(ext) >= 0);
}
ciyfn.nopower = function (mepower, power) {
    //true无权限，false有权限
    if (mepower == '.*.') //超级管理员
        return false;
    power = '.' + power;
    var dotidx = -1;
    for (let i = 0; i < mepower.length; i++) {
        if (mepower[i] !== '.')
            continue;
        if (dotidx > -1 && dotidx + 1 < i) {
            if (power.indexOf(mepower.substring(dotidx, i)) === -1)
                continue;
            return false; //有权限
        }
        dotidx = i;
    }
    return true; //无权限
}
ciyclass.sse = function (opn) {
    if (!window.EventSource)
        return alert('您的浏览器不支持SSE');
    opn = opn || {};
    if (!opn.url)
        return alert('无url参数');
    if (opn.url.indexOf('?') == -1 && opn.url.indexOf('://') == -1) {
        var ind = document.location.pathname.lastIndexOf('/');
        var path = document.location.pathname.substring(1, ind + 1);
        var pagename = document.location.pathname.substring(ind + 1) || 'index.html';
        ind = pagename.lastIndexOf('.');
        if (ind > 0)
            pagename = pagename.substring(0, ind);
        if (opn.url.indexOf('.') == -1) {
            opn.url = path + pagename + '.' + opn.url;
        } else if (opn.url.indexOf('/') == -1) {
            opn.url = path + opn.url;
        }
        opn.url = "/" + opn.url;
    }
    if (isobj(opn.param)) {
        for (var i in opn.param) {
            if (opn.url.indexOf('?') == -1)
                opn.url += '?' + i + '=' + opn.param[i];
            else
                opn.url += '&' + i + '=' + opn.param[i];
        }
    }
    var method = 'GET';
    if (opn.post)
        method = 'POST';
    opn.header = opn.header || {};
    if (!ciy_vars)
        console.log('nofind ciy_vars');
    opn.header['ciyauth'] = ciyfn.getstorage('_' + ciy_vars.tokenfield);

    this.close = () => {
        this.isaborted = true;
        if (this.xhr) {
            this.xhr.abort();
        }
    }
    this.isaborted = false;
    this.xhr = new XMLHttpRequest();
    this.xhr.open(method, opn.url, true);
    for (var i in opn.header) {
        if (opn.header[i] !== undefined)
            this.xhr.setRequestHeader(i, "" + opn.header[i]);
    }
    this.xhr.setRequestHeader('Accept', 'text/event-stream');
    this.xhr.setRequestHeader('Cache-Control', 'no-cache');
    if (opn.headers) {
        for (const [key, value] of Object.entries(opn.headers))
            this.xhr.setRequestHeader(key, value);
    }
    var position = 0;
    this.xhr.onprogress = () => {
        var data = this.xhr.responseText.substring(position);
        position += data.length;
        var datas = data.split('\n\n');
        for (var i = 0; i < datas.length; i++) {
            var dat1 = datas[i];
            if (dat1 === '')
                continue;
            var ind = dat1.indexOf('\n');
            var dat2 = '';
            if (ind > -1) {
                dat2 = dat1.substring(ind + 1);
                dat1 = dat1.substring(0, ind);
            }
            if (dat1.substring(0, 6) != 'data: ') {
                if (typeof (this.recvmsg) == 'function')
                    this.recvmsg(dat1);
                continue;
            }
            dat1 = dat1.substring(6);
            // if (dat1.substring(0, 7) == 'base64,')
            //     dat1 = decodeURIComponent(escape(atob(dat1.substring(7))));
            if (dat2.substring(0, 6) == 'event:') {
                dat2 = dat2.substring(6).trim();
                if (typeof (this.recvfix) == 'function')
                    this.recvfix(dat1, dat2);
                continue;
            }
            if (dat2.substring(0, 3) == 'id:')
                dat2 = dat2.substring(3).trim();
            if (typeof (this.recvmsg) == 'function')
                this.recvmsg(dat1, dat2);
        }
    };

    this.xhr.onreadystatechange = () => {
        console.log('onreadystatechange', this.xhr.readyState);
        if (this.xhr.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
            if (typeof (opn.onopen) == 'function')
                opn.onopen();
            else
                console.log(opn.url + ' SSE连接成功');
        }

        if (this.xhr.readyState === XMLHttpRequest.DONE) {
            if (this.xhr.status >= 400) {
                if (typeof (opn.onerror) == 'function')
                    opn.onerror(this.xhr);
                else
                    console.error(opn.url, this.xhr);
            } else {
                if (typeof (opn.onclose) == 'function')
                    opn.onclose(this.xhr);
                else
                    console.log(opn.url + ' SSE连接已关闭');
            }
        }
    };
    if (opn.post)
        this.xhr.send(ciyfn.jsontostr(opn.post));
    else
        this.xhr.send();
    return this;
}
ciyfn.lang = function (zhstr) {
    if (!zhstr)
        return '';
    if (ciygv.lang === undefined)
        ciygv.lang = ciyfn.getstorage('_lang');
    if (typeof (ciygv.lang) == 'object') {
        if (zhstr.length < 50) {
            if (ciygv.lang[zhstr] !== undefined)
                return ciygv.lang[zhstr];
        }
    }
    return zhstr;
}
ciyfn.setlang = function (lang) {
    if (!lang) {
        ciyfn.removestorage('_lang');
        location.reload();
    } else {
        ciyfn.ajax({
            url: '/jscss/lang/' + lang + '.json'
            , success: function (txt) {
                var json = ciyfn.tojson(txt);
                delete json.code;
                ciyfn.setstorage('_lang', json);
                location.reload();
            }
            , method: 'GET'
        });
    }
}
ciyfn.domlang = function (dom) {
    if (ciygv.lang === undefined)
        ciygv.lang = ciyfn.getstorage('_lang');
    if (typeof (ciygv.lang) != 'object')
        return;
    dom = dom || document;
    $5('.lang', dom).each(function (dom) {
        var zhstr = dom.innerHTML;
        if (!zhstr)
            return;
        zhstr = zhstr.trim();
        $5(dom).removeClass('lang');
        if (zhstr.indexOf('<') > -1)
            return;
        if (zhstr.length < 50) {
            if (ciygv.lang[zhstr] !== undefined)
                dom.textContent = ciygv.lang[zhstr];
        }
    });
    $5('option', dom).each(function () {
        var zhstr = dom.innerHTML;
        if (!zhstr)
            return;
        zhstr = zhstr.trim();
        if (zhstr.indexOf('<') > -1)
            return;
        if (zhstr.length < 50) {
            if (ciygv.lang[zhstr] !== undefined)
                dom.textContent = ciygv.lang[zhstr];
        }
    });
}
ciyclass.anidom = function (doms, key) {
    var anis = {};
    for (var i = 0; i < doms.length; i++) {
        var rect = doms[i].getBoundingClientRect();
        var id = doms[i].getAttribute(key);
        anis[id] = { l: rect.left, t: rect.top };
    }
    this.animate = function (sec) {
        sec = sec || 0.5;
        for (var i = 0; i < doms.length; i++) {
            var id = doms[i].getAttribute(key);
            var ani = anis[id];
            var rect = doms[i].getBoundingClientRect();
            doms[i].style.transition = 'transform 0s';
            doms[i].style.transform = 'translate(' + (ani.l - rect.left) + 'px, ' + (ani.t - rect.top) + 'px)';
            (function (idx) {
                requestAnimationFrame(function () {
                    doms[idx].style.transition = 'transform ' + sec + 's';
                    doms[idx].style.transform = null;
                });
                setTimeout(function () {
                    doms[idx].style.transition = null;
                }, sec * 1000);
            })(i);
        }
    }
    return this;
}
ciyclass.dragdom = function (opn) {
    if (!opn.dom)
        return console.error('dom参数错误');
    opn.dom = $5(opn.dom);
    var dom_sourceDrag = null;
    opn.dom.on('dragstart', function (event) {
        setTimeout(() => {
            event.target.classList.add('dragging');
        }, 0);
        dom_sourceDrag = event.target;
        event.dataTransfer.effectAllowed = 'move'
    });
    opn.dom.on('dragenter', function (event) {
        var ani;
        if (opn.key)
            ani = new ciyclass.anidom(opn.dom[0].children, opn.key);
        event.preventDefault();
        if (event.target === opn.dom[0] || event.target === dom_sourceDrag)
            return;
        var child = [...opn.dom[0].children];
        var sidx = child.indexOf(dom_sourceDrag);
        var tidx = child.indexOf(event.target);
        if (tidx == -1)
            return;
        if (sidx < tidx) {
            opn.dom[0].insertBefore(dom_sourceDrag, event.target.nextElementSibling);
        } else {
            if (event.target.parentNode === opn.dom[0])
                opn.dom[0].insertBefore(dom_sourceDrag, event.target);
        }
        if (opn.key)
            ani.animate(0.5);
    });
    opn.dom.on('dragenter', function (event) {
        event.preventDefault();
    });
    opn.dom.on('dragend', function (event) {
        event.target.classList.remove('dragging');
        if (!opn.sort) {
            if (typeof (opn.fn_sort) == 'function')
                opn.fn_sort();
            return;
        }
        opn.sortgap = opn.sortgap || 100;
        var me = {
            id: dom_sourceDrag.getAttribute(opn.key),
            sort: parseInt(dom_sourceDrag.getAttribute(opn.sort))
        };
        var meprev = null;
        if (dom_sourceDrag.previousElementSibling) {
            meprev = {
                id: dom_sourceDrag.previousElementSibling.getAttribute(opn.key),
                sort: parseInt(dom_sourceDrag.previousElementSibling.getAttribute(opn.sort))
            }
        }
        var menext = null;
        if (dom_sourceDrag.nextElementSibling) {
            menext = {
                id: dom_sourceDrag.nextElementSibling.getAttribute(opn.key),
                sort: parseInt(dom_sourceDrag.nextElementSibling.getAttribute(opn.sort))
            }
        }
        var updates = [];
        if (meprev && menext) {
            var odr = menext.sort - meprev.sort;
            if (odr > 1) {
                var od = meprev.sort + parseInt(odr / 2);
                console.log(menext.sort, meprev.sort, od);
                updates.push({ id: me.id, sort: od });
                dom_sourceDrag.setAttribute(opn.sort, od);
            } else {
                var od = opn.sortgap;
                for (var i = 0; i < opn.dom[0].children.length; i++) {
                    var item = opn.dom[0].children[i];
                    updates.push({ id: item.getAttribute(opn.key), sort: od });
                    item.setAttribute(opn.sort, od);
                    od += opn.sortgap;
                }
            }
        } else if (meprev) {
            updates.push({ id: me.id, sort: meprev.sort + opn.sortgap });
            dom_sourceDrag.setAttribute(opn.sort, meprev.sort + opn.sortgap);
        } else if (menext) {
            updates.push({ id: me.id, sort: menext.sort - opn.sortgap });
            dom_sourceDrag.setAttribute(opn.sort, menext.sort - opn.sortgap);
        }
        //排序后，更新数据库
        if (typeof (opn.fn_sort) == 'function')
            opn.fn_sort(updates);
    });
    return this;
}
ciyfn.pageload = function (func) {
    document.addEventListener('DOMContentLoaded', function () {
        func();
    });
}
document.addEventListener('DOMContentLoaded', function () {
    ciygv.mask = new ciyclass.mask();
    ciyfn.dropmenu(".btn-menu");
    const observer = new MutationObserver(function (mutations) {
        for (var i = 0; i < mutations.length; i++) {
            if (mutations[i].addedNodes && mutations[i].addedNodes.length) {
                ciyfn.domlang();
                setTimeout(function () {
                    ciyfn.lazyimg();
                }, 500);
                return;
            }
        }
    });
    observer.observe(document.body, { childList: true, subtree: true });
    ciyfn.lazyimg();
    ciyfn.domlang();
    window.addEventListener('scroll', function () {
        ciyfn.lazyimg();
    });
    window.addEventListener('message', function (event) {
        if (!event.data.func)
            return;
        if (event.data.func == 'chgtheme')
            ciy_chgtheme(event.data.data);
        else if (event.data.func == 'reload')
            location.reload();
        else if (event.data.func == 'alert_getwh') {
            ciyfn.sendsignal(event.source, 'alert_mywh', { width: document.body.scrollWidth, height: document.body.scrollHeight });
        } else {
            if (typeof (ciygv.messagefn[event.data.func]) == 'function') {
                ciygv.messagefn[event.data.func](event);
            }
        }
    });
    $5(document).on('click', '.help', itm => {
        var help = $5(itm.currentTarget).attr('help');
        ciyfn.alert(help.replace(/\\n/g, '<br>'));
    });
});