Wwenlong12告警清理
12015175创建于 2024年3月29日历史提交
<!DOCTYPE html>

<html lang="en">



<head>

    <meta charset="UTF-8">

    <title>Report-Diff</title>

    <style>

        * {

            box-sizing: border-box;

        }



        html,

        body {

            height: 100%;

            margin: 0;

            padding: 0;

        }



        lit-tabs {

            padding-top: 10px;

        }



        lit-tabpane {

            padding: 20px;

        }

    </style>

</head>



<body>

    <script type="module">

        window.getShadowRoot = (el) => {

            if (el.parentNode) {

                return window.getShadowRoot(el.parentNode)

            } else {

                return el;

            }

        };

        window.getShadowElement = (el) => {

            if (el.parentElement) {

                return window.getShadowElement(el.parentElement)

            } else {

                return el;

            }

        };

        class LitIcon extends HTMLElement {

            static get observedAttributes() {

                return ["name", "size", "color", "path"]

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{

            font-size: inherit;

            display: inline-block;

            transition: .3s;

         }

         :host([spin]){

            animation: rotate 1.75s linear infinite;

         }

         @keyframes rotate {

            to{

                transform: rotate(360deg);

            }

         }

         .icon{

            display: block;

            width: 1em;

            height: 1em;

            margin: auto;

            fill: currentColor;

            overflow: hidden;

         }

        </style>

        <svg style="display: none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

            <symbol id="icon-ellipsis" viewBox="0 0 1024 1024"><path d="M232 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path><path d="M512 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path><path d="M792 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path></symbol>

            <symbol id="icon-doubleleft" viewBox="0 0 1024 1024"><path d="M272.9 512l265.4-339.1c4.1-5.2 0.4-12.9-6.3-12.9h-77.3c-4.9 0-9.6 2.3-12.6 6.1L186.8 492.3c-9.1 11.6-9.1 27.9 0 39.5l255.3 326.1c3 3.9 7.7 6.1 12.6 6.1H532c6.7 0 10.4-7.7 6.3-12.9L272.9 512z"></path><path d="M576.9 512l265.4-339.1c4.1-5.2 0.4-12.9-6.3-12.9h-77.3c-4.9 0-9.6 2.3-12.6 6.1L490.8 492.3c-9.1 11.6-9.1 27.9 0 39.5l255.3 326.1c3 3.9 7.7 6.1 12.6 6.1H836c6.7 0 10.4-7.7 6.3-12.9L576.9 512z"></path></symbol>

            <symbol id="icon-doubleright" viewBox="0 0 1024 1024"><path d="M533.2 492.3L277.9 166.1c-3-3.9-7.7-6.1-12.6-6.1H188c-6.7 0-10.4 7.7-6.3 12.9L447.1 512 181.7 851.1c-4.1 5.2-0.4 12.9 6.3 12.9h77.3c4.9 0 9.6-2.3 12.6-6.1l255.3-326.1c9.1-11.7 9.1-27.9 0-39.5z"></path><path d="M837.2 492.3L581.9 166.1c-3-3.9-7.7-6.1-12.6-6.1H492c-6.7 0-10.4 7.7-6.3 12.9L751.1 512 485.7 851.1c-4.1 5.2-0.4 12.9 6.3 12.9h77.3c4.9 0 9.6-2.3 12.6-6.1l255.3-326.1c9.1-11.7 9.1-27.9 0-39.5z"></path></symbol>

            <symbol id="icon-close-circle-fill" viewBox="0 0 1024 1024"><path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m165.4 618.2l-66-0.3L512 563.4l-99.3 118.4-66.1 0.3c-4.4 0-8-3.5-8-8 0-1.9 0.7-3.7 1.9-5.2l130.1-155L340.5 359c-1.2-1.5-1.9-3.3-1.9-5.2 0-4.4 3.6-8 8-8l66.1 0.3L512 464.6l99.3-118.4 66-0.3c4.4 0 8 3.5 8 8 0 1.9-0.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path></symbol>

<!--            <symbol id="icon-left" viewBox="0 0 1024 1024"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8c-16.4 12.8-16.4 37.5 0 50.3l450.8 352.1c5.3 4.1 12.9 0.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></symbol>-->

<!--            <symbol id="icon-right" viewBox="0 0 1024 1024"><path d="M765.7 486.8L314.9 134.7c-5.3-4.1-12.9-0.4-12.9 6.3v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1c16.4-12.8 16.4-37.6 0-50.4z"></path></symbol>-->

        </svg>

        <svg class="icon" id="icon" aria-hidden="true" viewBox="0 0 ${this.view} ${this.view}">

             ${this.path ? '<path id="path"></path>' : '<use id="use"></use>'}

        </svg>

        `

            }



            get view() {

                return this.getAttribute("view") || 1024;

            }



            get name() {

                return this.getAttribute("name");

            }



            get path() {

                return this.getAttribute("path");

            }



            set name(value) {

                this.setAttribute("name", value);

            }



            set path(value) {

                this.setAttribute("path", value);

            }



            get size() {

                return this.getAttribute("size") || "";

            }



            get color() {

                return this.getAttribute("color") || "";

            }



            set size(value) {

                this.setAttribute("size", value);

            }



            set color(value) {

                this.setAttribute("color", value);

            }



            get spin() {

                return this.hasAttribute('spin');

            }



            set spin(value) {

                if (value) {

                    this.setAttribute('spin', '')

                } else {

                    this.removeAttribute('spin');

                }

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {

                this.icon = this.shadowRoot.getElementById("icon");

                this.use = this.shadowRoot.querySelector("use")

                this.d = this.shadowRoot.querySelector("path");

                this.size && (this.size = this.size);

                this.color && (this.color = this.color);

                this.name && (this.name = this.name);

                this.path && (this.path = this.path);

            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {

                if (name === "name" && this.use) {

                    this.use.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', `#icon-${newValue}`);

                }

                if (name === "path" && this.d) {

                    this.d.setAttribute("d", newValue);

                }

                if (name === "color" && this.icon) {

                    this.icon.style.color = newValue;

                }

                if (name === "size" && this.icon) {

                    this.icon.style.fontSize = newValue + "px";

                }

            }

        }

        if (!customElements.get('lit-icon')) {

            customElements.define('lit-icon', LitIcon);

        }



        class LitInput extends HTMLElement {

            static get observedAttributes() {

                return [

                    'placeholder',//显示提示文字

                    'block',//属性将使按钮适合其父宽度。

                    'icon',//图标,如果配置了 slot='prefix' icon将失效

                    'bordered',//是否有边框

                    'allow-clear',//是否有清除

                    'rows',//表示行数,默认input 设置rows 后 显示为textarea

                    'maxlength',//允许输入多少个字符 默认没有限制

                    'type',//password  number  text

                    'pattern',//正则表达式

                    'error-text',//错误提示文字

                    'error-placement',//错误提示文字方向

                    'required',//是否开始验证

                    'value',//值

                ];

            }

            get value() {

                return this.getAttribute('value') || '';

            }



            set value(value) {

                this.setAttribute('value', value);

            }

            get required() {

                return this.hasAttribute('required');

            }



            set required(value) {

                if (value) {

                    this.setAttribute('required', "");

                } else {

                    this.removeAttribute('required');

                }

            }

            get pattern() {

                return this.getAttribute('pattern') || '';

            }



            set pattern(value) {

                this.setAttribute('pattern', value);

            }

            get errorText() {

                return this.getAttribute('error-text') || '该项为必填项';

            }

            set errorText(value) {

                this.setAttribute('error-text', value)

            }

            get errorPlacement() {

                return this.getAttribute('error-placement') || 'top';

            }

            set errorPlacement(value) {

                this.setAttribute('error-placement', value)

            }

            get type() {

                return this.getAttribute('type');

            }

            set type(value) {

                this.setAttribute('type', value);

            }

            get maxlength() {

                return this.getAttribute('maxlength') || '';

            }



            set maxlength(value) {

                this.setAttribute('maxlength', value)

            }

            get rows() {

                return this.getAttribute('rows');

            }

            set rows(value) {

                this.setAttribute('rows', value);

            }

            get allowClear() {

                return this.hasAttribute('allow-clear');

            }



            set allowClear(value) {

                if (value) {

                    this.setAttribute('allow-clear', '');

                } else {

                    this.removeAttribute('allow-clear');

                }

            }



            get bordered() {

                return this.getAttribute('bordered') || "true";

            }



            set bordered(value) {

                if (value) {

                    this.setAttribute('bordered', 'true');

                } else {

                    this.setAttribute('bordered', 'false')

                }

            }



            get icon() {

                return this.getAttribute('icon') || null;

            }



            set icon(value) {

                this.setAttribute('icon', value)

            }



            get block() {

                return this.hasAttribute('block')

            }



            set block(value) {

                if (value) {

                    this.setAttribute('block', '');

                } else {

                    this.removeAttribute('block')

                }

            }



            get placeholder() {

                return this.getAttribute('placeholder') || '';

            }



            set placeholder(value) {

                this.setAttribute('placeholder', value);

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

:host{

    ${this.bordered === 'true' ? 'border: 1px solid #e9e9e9;' : ''}

    display: inline-flex;

    box-sizing: border-box;

    position:relative;

    align-items: ${this.rows ? 'flex-start' : 'center'};

    transition: all .3s;

    border-radius: 2px;

    font-size: 14px;

    color: #333;

    ${this.block ? 'display: flex;' : ''}

    box-sizing: border-box;

 }

 :host(:hover){

    ${this.bordered === 'true' ? 'border: 1px solid #65b687;' : ''}

    ${this.bordered === 'true' ? 'box-shadow: 0 0 10px #65b68766;' : ''}

 }

 *{

    box-sizing: border-box;

 }

 .input{

    outline: none;

    border: 0px;

    font-size: inherit;

    color: inherit;

    width: 100%;

    height: 100%;

    vertical-align:middle;

    line-height:inherit;

    height:inherit;

    padding: 6px 6px 6px ${this.icon ? '6px' : '11px'};

    max-height: inherit;

    box-sizing: border-box;

 }

 /*去掉type=number 后面的增减箭头*/

input::-webkit-outer-spin-button,

input::-webkit-inner-spin-button {

    -webkit-appearance: none;



}



input[type='number'] {

    -moz-appearance: textfield;

}



 lit-tips{

    flex: 1;

    height: 100%;

    width: 100%;

 }

 lit-tips{

    flex: 1;

    align-items: center;

 }

:host(:not([allow-clear])) .clear-btn{

    display: flex;

    visibility: hidden;

    transition: all .3s;

    opacity: 0;

}

:host([allow-clear]) .clear-btn{

    opacity: 0;

    position:absolute;

    right: 0;

    top: .5rem;

    visibility: hidden;

    transition: all .3s;

    display: flex;

    margin-right: 6px;

    transform: translateY(0%);

    color: #bfbfbf;

}

:host([allow-clear]) .clear-btn:hover{

    color: #8c8c8c;

}



.area{

    outline: none;

    border: 0px;

    width: 100%;

    font-size: inherit;

    vertical-align:middle;

    min-height: calc(2rem);

    max-height: calc(${this.rows} * 1rem);

    padding: 6px 6px 6px ${this.icon ? '6px' : '11px'};

    box-sizing: border-box;

    resize:vertical;

}



:host(:not([type=password])) .pwd-btn,

:host(:not([type=tel])) .pwd-btn{

    display: none;

    visibility: hidden;

    transition: all .3s;

    opacity: 0;

}

:host([type=password]) .pwd-btn,

:host([type=tel]) .pwd-btn{

    opacity: 1;

    position:absolute;

    right: 0;

    top: .5rem;

    visibility: visible;

    transition: all .3s;

    display: flex;

    margin-right: 6px;

    transform: translateY(0%);

    color: #bfbfbf;

}

/*:host([type=password]) input{*/

/*    -webkit-text-security:none;*/

/*    text-security:none;*/

/*}*/

:host([type=password]) .pwd-btn:hover,

:host([type=tel]) .pwd-btn:hover{

    color: #8c8c8c;

}



</style>

<slot name="prefix">${this.icon ? `<lit-icon name="${this.icon}" style="margin-left: 11px;color: inherit;font-size: inherit;${this.rows ? 'transform: translateY(50%);' : ''}"></lit-icon>` : ``}</slot>

<lit-tips tips="${this.errorText}" placement="${this.errorPlacement}" color="#f4615c" offset="12px" show="false">

    ${this.hasAttribute('rows') ?

                        `<textarea class="area" rows="${this.rows}" value="${this.value}" placeholder="${this.placeholder}" cols="27" maxlength="${this.maxlength}" onscroll="this.rows++;"></textarea>`

                        :

                        `<input type="${this.type}" value="${this.value}" class="input" placeholder="${this.placeholder}"  >`}



    <lit-icon class="clear-btn" name="close-circle-fill"></lit-icon>

    <lit-icon class="pwd-btn" name="eye-fill"></lit-icon>

</lit-tips>

<slot name="suffix" ></slot>

        `

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {

                this.reg = new RegExp(this.pattern);

                this.inputElement = this.shadowRoot.querySelector('.input');

                this.areaElement = this.shadowRoot.querySelector('.area');

                this.clearElement = this.shadowRoot.querySelector('.clear-btn');

                this.pwdElement = this.shadowRoot.querySelector('.pwd-btn');



                this.pwdElement.onclick = (e) => {

                    if (this.inputElement.getAttribute('type') === 'password') {

                        this.pwdElement.name = 'eyeclose-fill';

                        this.inputElement.setAttribute('type', 'tel');

                    } else if (this.inputElement.getAttribute('type') === 'tel') {

                        this.inputElement.setAttribute('type', 'password');

                        this.pwdElement.name = 'eye-fill';

                    }

                }



                if (this.areaElement) {

                    this.clearElement.onclick = e => {

                        this.areaElement.value = '';

                        this.clearElement.style.visibility = 'hidden';

                        this.clearElement.style.opacity = '0';

                        this.value = this.areaElement.value;

                        this.dispatchEvent(new CustomEvent('onClear', e));

                        this.clearError();

                    }

                    this.areaElement.oninput = e => {

                        if (this.allowClear) {

                            if (this.areaElement.value.length > 0) {

                                this.clearElement.style.visibility = 'visible';

                                this.clearElement.style.opacity = '1';

                            } else {

                                this.clearElement.style.visibility = 'hidden';

                                this.clearElement.style.opacity = '0';

                            }

                        }

                        this.value = this.areaElement.value;

                        this.verify();

                        this.dispatchEvent(new CustomEvent('input', e));

                    }

                    this.areaElement.onchange = e => {

                        this.value = this.areaElement.value;

                        this.verify();

                        this.dispatchEvent(new CustomEvent('change', e));

                    }

                    this.areaElement.onfocus = e => {

                        this.value = this.areaElement.value;

                        this.verify();

                        this.dispatchEvent(new CustomEvent('focus', e));

                    }

                    this.areaElement.onblur = e => {

                        this.value = this.areaElement.value;

                        this.dispatchEvent(new CustomEvent('blur', e));

                    }

                    this.areaElement.onkeydown = e => {

                        if (e.key === 'Enter') {

                            this.value = this.areaElement.value;

                            this.verify();

                            this.dispatchEvent(new CustomEvent('onPressEnter', e));

                        }

                        this.dispatchEvent(new CustomEvent('keydown', e));

                    }

                    this.areaElement.onkeyup = e => {

                        this.dispatchEvent(new CustomEvent('keyup', e));

                    }

                    this.areaElement.onselect = e => {

                        this.dispatchEvent(new CustomEvent('select', e));

                    }

                    this.areaElement.onclick = e => {

                        this.dispatchEvent(new CustomEvent('click', e));

                    }

                }

                if (this.inputElement) {

                    this.clearElement.onclick = e => {

                        this.inputElement.value = '';

                        this.clearElement.style.visibility = 'hidden';

                        this.clearElement.style.opacity = '0';

                        this.value = this.inputElement.value;

                        this.dispatchEvent(new CustomEvent('onClear', e));

                        this.clearError();

                    }

                    this.inputElement.oninput = e => {

                        if (this.allowClear) {

                            if (this.inputElement.value.length > 0) {

                                this.clearElement.style.visibility = 'visible';

                                this.clearElement.style.opacity = '1';

                            } else {

                                this.clearElement.style.visibility = 'hidden';

                                this.clearElement.style.opacity = '0';

                            }

                        }

                        this.value = this.inputElement.value;

                        this.verify();

                        this.dispatchEvent(new CustomEvent('input', e));

                    }

                    this.inputElement.onchange = e => {

                        this.value = this.inputElement.value;

                        this.verify();

                        this.dispatchEvent(new CustomEvent('change', e));

                    }

                    this.inputElement.onfocus = e => {

                        this.value = this.inputElement.value;

                        this.verify();

                        this.dispatchEvent(new CustomEvent('focus', e));

                    }

                    this.inputElement.onblur = e => {

                        this.dispatchEvent(new CustomEvent('blur', e));

                    }

                    this.inputElement.onkeydown = e => {

                        if (e.key === 'Enter') {

                            this.value = this.inputElement.value;

                            this.verify();

                            this.dispatchEvent(new CustomEvent('onPressEnter', e));

                        }

                        this.dispatchEvent(new CustomEvent('keydown', e));

                    }

                    this.inputElement.onkeyup = e => {

                        this.dispatchEvent(new CustomEvent('keyup', e));

                    }

                    this.inputElement.onselect = e => {

                        this.dispatchEvent(new CustomEvent('select', e));

                    }

                    this.inputElement.onclick = e => {

                        this.dispatchEvent(new CustomEvent('click', e));

                    }

                }



            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {

                if (name === 'value') {

                    // console.log(name,oldValue,newValue);

                    // console.log(this.inputElement);

                    if (this.inputElement) {

                        this.inputElement.value = newValue

                    } else if (this.areaElement) {

                        this.areaElement.value = newValue;

                    }

                }

            }

            verify() {

                if (this.required) {

                    let result;

                    if (this.hasAttribute('rows')) {

                        result = this.reg.test(this.areaElement.value);

                    } else {

                        result = this.reg.test(this.inputElement.value);

                    }

                    if (result) {

                        this.shadowRoot.querySelector('lit-tips').show = 'false'

                    } else {

                        this.shadowRoot.querySelector('lit-tips').show = 'true'

                    }

                    return result;

                } else {

                    return true;

                }

            }

            clearError() {

                this.shadowRoot.querySelector('lit-tips').show = 'false'

            }

        }

        if (!customElements.get('lit-input')) {

            customElements.define('lit-input', LitInput);

        }



        class LitLoading extends HTMLElement {

            static get observedAttributes() { return ['color', 'size'] }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{

            font-size:inherit;

            display:inline-flex;

            align-items: center;

            justify-content:center;

            color:var(--themeColor,#42b983);

        }

        .loading{

            display: block;

            width: 1em;

            height: 1em;

            margin: auto;

            animation: rotate 1.4s linear infinite;

        }

        .circle {

            stroke: currentColor;

            animation:  progress 1.4s ease-in-out infinite;

            stroke-dasharray: 80px, 200px;

            stroke-dashoffset: 0px;

            transition:.3s;

        }

        :host(:not(:empty)) .loading{

            margin:.5em;

        }

        @keyframes rotate{

            to{

                transform: rotate(360deg);

            }

        }

        @keyframes progress {

            0% {

              stroke-dasharray: 1px, 200px;

              stroke-dashoffset: 0px;

            }

            50% {

              stroke-dasharray: 100px, 200px;

              stroke-dashoffset: -15px;

            }

            100% {

              stroke-dasharray: 100px, 200px;

              stroke-dashoffset: -125px;

            }

        }

        </style>

        <svg class="loading" id="loading" viewBox="22 22 44 44"><circle class="circle" cx="44" cy="44" r="20.2" fill="none" stroke-width="3.6"></circle></svg>

        <slot></slot>

        `

            }



            get size() {

                return this.getAttribute('size') || '';

            }



            get color() {

                return this.getAttribute('color') || '';

            }



            set size(value) {

                this.setAttribute('size', value);

            }



            set color(value) {

                this.setAttribute('color', value);

            }



            connectedCallback() {

                this.loading = this.shadowRoot.getElementById('loading');

                this.size && (this.size = this.size);

                this.color && (this.color = this.color);

            }



            attributeChangedCallback(name, oldValue, newValue) {

                if (name == 'color' && this.loading) {

                    this.loading.style.color = newValue;

                }

                if (name == 'size' && this.loading) {

                    this.loading.style.fontSize = newValue + 'px';

                }

            }

        }

        if (!customElements.get('lit-loading')) {

            customElements.define('lit-loading', LitLoading);

        }



        class LitPagination extends HTMLElement {

            static get observedAttributes() {

                return [

                    "current",//当前页码

                    "total",//总条数

                    "page-size",//每页条数

                    "disabled",//禁用分页

                    'show-size-changer',//显示每页条目数select

                    'show-quick-jumper',//显示跳至多少页

                    'page-size-options',//指定每页可以显示多少条 默认 [10,20,50,100]

                    'simple',//简洁模式

                ]

            }

            get pageSizeOptions() {

                return this.getAttribute('page-size-options');

            }

            set pageSizeOptions(value) {

                this.setAttribute('page-size-options', '');

            }



            get current() {

                return this.getAttribute('current') || '1';

            }



            set current(value) {

                this.setAttribute('current', value);

            }



            get total() {

                return this.getAttribute('total') || '50';

            }



            set total(value) {

                this.setAttribute('total', value);

            }



            get pageSize() {

                return this.getAttribute('page-size') || '10';

            }



            set pageSize(value) {

                this.setAttribute('page-size', value);

            }



            get disabled() {

                return this.hasAttribute('disabled');

            }



            set disabled(value) {

                if (value) {

                    this.setAttribute('disabled', '');

                } else {

                    this.removeAttribute('disabled');

                }

            }



            get showSizeChanger() {

                return this.hasAttribute('show-size-changer')

            }



            set showSizeChanger(value) {

                if (value) {

                    this.setAttribute('show-size-changer', '');

                } else {

                    this.removeAttribute('show-size-changer');

                }

            }



            get showQuickJumper() {

                return this.hasAttribute('show-quick-jumper')

            }



            set showQuickJumper(value) {

                if (value) {

                    this.setAttribute('show-quick-jumper', '');

                } else {

                    this.removeAttribute('show-quick-jumper');

                }

            }



            get simple() {

                return this.hasAttribute('simple');

            }



            set simple(value) {

                if (value) {

                    this.setAttribute('simple', '');

                } else {

                    this.removeAttribute('simple');

                }

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

<style>

:host{

     display: flex;

     width: max-content;

}

.root{

    display: inline-flex;

    /*grid-template-columns: repeat(auto-fill,35px);*/

    /*column-gap: 8px;*/

    /*row-gap: 8px;*/

    user-select: none;

}

.item{

    box-sizing: border-box;

    color: #333;

    transition: all .3s;

    width: 35px;

    height: 35px;

    margin-left: 6px;

    padding: 6px 10px;

    border: 1px solid #ececec;

    border-radius: 3px;

    cursor: pointer;

    display: inline-flex;

    align-items: center;

    justify-content: center;

}

.item-dir{

    color: #333;

    transition: all .3s;

    padding: 5px 10px;

    /*border: 1px solid #ececec;*/

    /*border-radius: 3px;*/

    cursor: pointer;

    display: inline-flex;

    align-items: center;

    justify-content: center;

}

.item:not([disable]):hover{

    color:#42b983;

    border: 1px solid #42b983;

}

.item[selected]{

    color:#42b983;

    border: 1px solid #42b983;

}

.item[disable]{

    /*background-color: #f5f5f5;*/

    fill: #c7c7c7;

    color: #c7c7c7;

    cursor: not-allowed;

}



:host([show-quick-jumper]) .jump-root{

    grid-column: span 4;

    margin-left: 6px;

    display: inline-flex;

    align-items: center;

}

:host(:not([show-quick-jumper])) .jump-root{

    display: none;

}



:host([show-size-changer]) .pages-change{

    display: inline-flex;

    grid-column: span 3;

    width: 120px;

    margin-left: 6px;

    font-size: .9rem;

}

:host(:not([show-size-changer])) .pages-change{

    display: none;

}

</style>

<div style="display: grid;grid-template-columns: max-content 1fr;">

    <div style="display: inline-flex;align-items: center" id="showTotal">

        <slot id="st" name="showTotal"></slot>

    </div>

    <div class="root">

<!--        <lit-icon class="item left-arrow" name="left" ></lit-icon>-->

        <svg class="item left-arrow" viewBox="0 0 1024 1024" aria-hidden="true" >

            <path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8c-16.4 12.8-16.4 37.5 0 50.3l450.8 352.1c5.3 4.1 12.9 0.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path>

        </svg>

        <div class="item first">1</div>

        <lit-icon class="item-dir double-left" name="ellipsis" ></lit-icon>

<!--        <svg class="item-dir double-left" viewBox="0 0 1024 1024" aria-hidden="true" style="width: 16px;width: 16px;">-->

<!--            <path d="M232 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path><path d="M512 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path><path d="M792 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path>-->

<!--        </svg>-->

        <div class="item one">2</div>

        <div class="item two">3</div>

        <div class="item three">4</div>

        <div class="item four">5</div>

        <div class="item five">6</div>

        <lit-icon class="item-dir double-right" name="ellipsis" ></lit-icon>

<!--        <svg class="item-dir double-right" viewBox="0 0 1024 1024" aria-hidden="true" style="width: 16px;width: 16px;">-->

<!--            <path d="M232 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path><path d="M512 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path><path d="M792 511m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"></path>-->

<!--        </svg>-->

        <div class="item last">1</div>

<!--        <lit-icon class="item right-arrow" name="right"></lit-icon>-->

        <svg class="item right-arrow" viewBox="0 0 1024 1024" aria-hidden="true" >

            <path d="M765.7 486.8L314.9 134.7c-5.3-4.1-12.9-0.4-12.9 6.3v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1c16.4-12.8 16.4-37.6 0-50.4z"></path>

        </svg>

        <lit-select class="pages-change" default-value="10"></lit-select>

        <div class="jump-root">

            <label style="font-size: .9rem;color: #333;margin-right: 5px">跳至</label>

            <lit-input type="number" class="jump" style="width: 80px;height: 100%"></lit-input>

            <label style="font-size: .9rem;color: #333;margin-left: 5px">页</label>

        </div>

    </div>



</div>



        `

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {

                this.slotShowTotal = null;

                this.rootElement = this.shadowRoot.querySelector('.root');

                let st = this.shadowRoot.querySelector('#st');

                st.addEventListener('slotchange', () => {

                    let elements = st.assignedElements();

                    if (elements.length > 0) {

                        this.slotShowTotal = elements[0];

                    }

                    if (this.slotShowTotal) {

                        let cloneNode = this.slotShowTotal.render({

                            total: this._total,

                            range: [1, this._pages],

                        }).content.cloneNode(true);

                        this.shadowRoot.querySelector('#showTotal').append(cloneNode);

                    }

                })

                this.leftArrow = this.shadowRoot.querySelector('.left-arrow');

                this.first = this.shadowRoot.querySelector('.first');

                this.doubleLeft = this.shadowRoot.querySelector('.double-left');

                this.one = this.shadowRoot.querySelector('.one');

                this.two = this.shadowRoot.querySelector('.two');

                this.three = this.shadowRoot.querySelector('.three');

                this.four = this.shadowRoot.querySelector('.four');

                this.five = this.shadowRoot.querySelector('.five');

                this.doubleRight = this.shadowRoot.querySelector('.double-right');

                this.last = this.shadowRoot.querySelector('.last');

                this.rightArrow = this.shadowRoot.querySelector('.right-arrow');

                this.pagesChange = this.shadowRoot.querySelector('.pages-change');

                this.jump = this.shadowRoot.querySelector('.jump');

                this.nodes = [this.one, this.two, this.three, this.four, this.five]



                let jsonArray = JSON.parse(this.pageSizeOptions);

                if (jsonArray) {

                    this.pagesChange.dataSource = jsonArray.map(a => {

                        return { key: a, val: `${a} 条/页`, }

                    });

                    this.pagesChange.value = jsonArray[0] + '';

                    this.pageSize = jsonArray[0] + '';

                } else {

                    this.pagesChange.dataSource = [10, 20, 50, 100].map(a => {

                        return { key: a, val: `${a} 条/页`, }

                    });

                    this.pagesChange.value = '10';

                    this.pageSize = '10';

                }



                this.jump.addEventListener('onPressEnter', e => {

                    if (e.target.value) {

                        this.current = e.target.value;

                        e.target.value = '';

                        this.match();

                    }

                });

                this.pagesChange.onchange = e => {

                    // console.log(e.detail);

                    this.pageSize = e.detail.value;

                    this.match();

                    if (this.slotShowTotal) {

                        let cloneNode = this.slotShowTotal.render({

                            total: this._total,

                            range: [1, this._pages],

                        }).content.cloneNode(true);

                        this.shadowRoot.querySelector('#showTotal').lastElementChild.remove();

                        this.shadowRoot.querySelector('#showTotal').append(cloneNode);

                    }

                    this.dispatchEvent(new CustomEvent('onShowSizeChange', {

                        detail: {

                            current: parseInt(this.current),

                            size: parseInt(this.pageSize)

                        }

                    }))

                }



                this.leftArrow.onclick = (e) => {

                    if (this._current > 1) {

                        this.current = `${this._current - 1}`

                        this.match();

                    }

                }

                this.rightArrow.onclick = (e) => {

                    if (this._current < this._pages) {

                        this.current = `${this._current + 1}`

                        this.match();

                    }

                }

                let nodeClickHandler = e => {

                    this.current = `${e.currentTarget.val}`;

                    this.match();

                };

                this.first.onclick = nodeClickHandler;

                this.nodes.forEach(a => a.onclick = nodeClickHandler);

                this.last.onclick = nodeClickHandler;

                this.doubleLeft.onmouseover = e => {

                    e.target.name = 'doubleleft';

                }

                this.doubleLeft.onmouseout = e => {

                    e.target.name = 'ellipsis'

                }

                this.doubleLeft.onclick = e => {

                    let k = this._current - 5;

                    if (k < 1) k = 1;

                    this.current = `${k}`;

                    this.match();

                }

                this.doubleRight.onmouseover = e => {

                    e.target.name = 'doubleright';

                }

                this.doubleRight.onmouseout = e => {

                    e.target.name = 'ellipsis'

                }

                this.doubleRight.onclick = e => {

                    let k = this._current + 5;

                    if (k > this._pages) k = this._pages;

                    this.current = `${k}`;

                    this.match();

                }

                this.match();

            }



            match() {

                this._current = parseInt(this.current);

                this._total = parseInt(this.total);

                this._pageSize = parseInt(this.pageSize);

                this._pages = Math.ceil(this._total / this._pageSize)

                if (this._current > this._pages) {

                    this._current = this._pages;

                    this.current = `${this._pages}`;

                } else if (this._current < 1) {

                    this._current = 1;

                    this.current = `1`;

                }

                //是否展示 pageSize 切换器,当 total 大于 50 时默认为 true

                // if(this._total>50) this.setAttribute('show-size-changer', '');



                // console.log(`${this._total} ${this._current}/${this._pages} ${this._pageSize}`);

                if (this._current === 1) {

                    this.leftArrow.setAttribute('disable', '');

                } else {

                    this.leftArrow.removeAttribute('disable');

                }

                if (this._current === this._pages) {

                    this.rightArrow.setAttribute('disable', '');

                } else {

                    this.rightArrow.removeAttribute('disable');

                }

                this.hiddenNode(this.first, this.last, this.one, this.two, this.three, this.four, this.five, this.doubleLeft, this.doubleRight)

                if (this._pages <= 5) {

                    for (let i = 0; i < this._pages; i++) {

                        this.displayNode(this.nodes[i]);

                        this.item(this.nodes[i], i + 1);

                    }

                } else if (this._pages === 6) {

                    this.displayNode(this.first);

                    this.item(this.first, 1);

                    for (let i = 0; i < this._pages; i++) {

                        this.displayNode(this.nodes[i]);

                        this.item(this.nodes[i], i + 2);

                    }

                } else {

                    this.displayNode(this.one, this.two, this.three, this.four, this.five)

                    if (this._current - 3 > 1 && this._current + 3 < this._pages) { // 左边溢出 右边溢出

                        this.displayNode(this.first, this.last, this.doubleLeft, this.doubleRight);

                        this.item(this.first, 1);

                        this.item(this.last, this._pages);

                        this.item(this.one, this._current - 2);

                        this.item(this.two, this._current - 1);

                        this.item(this.three, this._current);

                        this.item(this.four, this._current + 1);

                        this.item(this.five, this._current + 2);

                    } else if (this._current - 3 === 1 && this._current + 3 < this._pages) {//左边刚好 右边溢出

                        this.displayNode(this.first, this.last, this.doubleRight);

                        this.item(this.first, 1)

                        this.item(this.last, this._pages)

                        for (let i = 0; i < this.nodes.length; i++) {

                            this.item(this.nodes[i], i + 2);

                        }

                    } else if (this._current - 3 < 1 && this._current + 3 < this._pages) {  //左边不够 右边溢出

                        this.displayNode(this.last, this.doubleRight);

                        this.item(this.last, this._pages)

                        for (let i = 0; i < this.nodes.length; i++) {

                            this.item(this.nodes[i], i + 1);

                        }

                    } else if (this._current - 3 > 1 && this._current + 3 === this._pages) {// 左边溢出 右边刚好

                        this.displayNode(this.first, this.last, this.doubleLeft);

                        this.item(this.first, 1);

                        this.item(this.last, this._pages);

                        this.item(this.nodes[0], this._pages - 5);

                        this.item(this.nodes[1], this._pages - 4);

                        this.item(this.nodes[2], this._pages - 3);

                        this.item(this.nodes[3], this._pages - 2);

                        this.item(this.nodes[4], this._pages - 1);

                    } else if (this._current - 3 === 1 && this._current + 3 === this._pages) {// 左边刚好 右边刚好

                        this.displayNode(this.first, this.last);

                        this.item(this.first, 1);

                        for (let i = 0; i < this._pages; i++) {

                            this.displayNode(this.nodes[i]);

                            this.item(this.nodes[i], i + 2);

                        }

                        this.item(this.last, 7);

                    } else if (this._current - 3 < 1 && this._current + 3 === this._pages) {// 左边不够 右边刚好

                        this.displayNode(this.last);

                        this.item(this.last, this._pages)

                        for (let i = 0; i < this.nodes.length; i++) {

                            this.item(this.nodes[i], i + 1);

                        }

                    } else if (this._current - 3 > 1 && this._current + 3 > this._pages) { //左边溢出 右边不够

                        this.displayNode(this.first, this.doubleLeft)

                        this.item(this.first, 1);

                        this.item(this.nodes[0], this._pages - 4);

                        this.item(this.nodes[1], this._pages - 3);

                        this.item(this.nodes[2], this._pages - 2);

                        this.item(this.nodes[3], this._pages - 1);

                        this.item(this.nodes[4], this._pages - 0);

                    } else if (this._current - 3 === 1 && this._current + 3 > this._pages) { //左边刚好 右边不够

                        this.displayNode(this.first);

                        this.item(this.first, 1);

                        this.item(this.nodes[0], this._pages - 4);

                        this.item(this.nodes[1], this._pages - 3);

                        this.item(this.nodes[2], this._pages - 2);

                        this.item(this.nodes[3], this._pages - 1);

                        this.item(this.nodes[4], this._pages - 0);

                    } else if (this._current - 3 < 1 && this._current + 3 > this._pages) { //左边不够 右边不够

                        //限定了 pages>6 这种情况不存在

                    }

                }

            }



            item(el, val) {

                el.val = val;

                el.textContent = val;

                if (val === this._current) {

                    el.setAttribute('selected', '');

                } else {

                    el.removeAttribute('selected');

                }

            }



            displayNode() {

                [...arguments].forEach(a => a.style.display = 'flex');

            }



            hiddenNode(n) {

                [...arguments].forEach(a => a.style.display = 'none');

            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {

            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {

                if (name === 'current') {

                    this.dispatchEvent(new CustomEvent('onChange', {

                        detail: {

                            page: parseInt(newValue),

                            pageSize: this._pageSize

                        }

                    }));

                } else if (name === 'total') {

                    this.dispatchEvent(new CustomEvent('onChange', {

                        detail: {

                            total: parseInt(newValue),

                            current: this._current,

                            pageSize: this._pageSize

                        }

                    }));

                    this.match()

                }



            }

        }

        if (!customElements.get('lit-pagination')) {

            customElements.define('lit-pagination', LitPagination);

        }



        class LitSelect extends HTMLElement {

            static get observedAttributes() {

                return [

                    'value',//默认值

                    'default-value',//默认值

                    'placeholder',//placeholder

                    'disabled',

                    'loading',//是否处于加载状态

                    'allow-clear',//是否允许清除

                    'show-search',//是否允许搜索

                    'list-height',//设置弹窗滚动高度 默认256px

                    'border',//是否显示边框

                    'mode',// mode='multiple'多选

                ];

            }



            get value() {

                return this.getAttribute('value') || this.defaultValue;

            }



            set value(value) {

                this.setAttribute('value', value);

            }



            get border() {

                return this.getAttribute('border') || 'true';

            }



            set border(value) {

                if (value) {

                    this.setAttribute('border', 'true');

                } else {

                    this.setAttribute('border', 'false');

                }

            }



            get listHeight() {

                return this.getAttribute('list-height') || '256px';

            }



            set listHeight(value) {

                this.setAttribute('list-height', value);

            }



            get defaultPlaceholder() {

                return this.getAttribute('placeholder') || '请选择';

            }



            get showSearch() {

                return this.hasAttribute('show-search');

            }



            set defaultValue(value) {

                this.setAttribute('default-value', value);

            }



            get defaultValue() {

                return this.getAttribute('default-value') || '';

            }



            set placeholder(value) {

                this.setAttribute('placeholder', value);

            }



            get placeholder() {

                return this.getAttribute('placeholder') || this.defaultPlaceholder;

            }



            get loading() {

                return this.hasAttribute('loading');

            }



            set loading(value) {

                if (value) {

                    this.setAttribute('loading', '');

                } else {

                    this.removeAttribute('loading')

                }

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

:host{

    display: inline-flex;

    position: relative;

    overflow: visible;

    cursor: pointer;

    transition: all .3s;

    border-radius: 2px;

    outline: none;

    -webkit-user-select:none ;

    -moz-user-select:none;

    user-select:none;

    /*width: 100%;*/

}

:host(:not([border])),

:host([border='true']){

    border: 1px solid #dcdcdc;

}

input{

    border: 0;

    outline: none;

    background-color: transparent;

    cursor: pointer;

    transition: all .3s;

    -webkit-user-select:none ;

    -moz-user-select:none;

    user-select:none;

    display: inline-flex;

}

:host(:not([mode]))  input{

    width: 100%;

}

:host([mode])  input{

    padding: 6px 0px;

}

:host([mode])  .root{

    padding: 1px 8px;

}

.root{

    position: relative;

    padding: 6px 8px;

    display: flex;

    align-items: center;

    justify-content: space-between;

    transition: all .3s;

    border-radius: 2px;

    background-color: #fff;

    outline: none;

    font-size: 1rem;

    z-index: 2;

    -webkit-user-select:none ;

    -moz-user-select:none;

    user-select:none;

    width: 100%;

}

.body{

    max-height: ${this.listHeight};

    position: absolute;

    top: 100%;

    z-index: 99;

    padding-top: 5px;

    margin-top: 2px;

    background-color: #fff;

    width: 100%;

    transition: all 0.2s;

    transform: scaleY(.6);

    visibility: hidden;

    opacity: 0;

    transform-origin: top center;

    display: block;

    flex-direction: column;

    box-shadow: 0 5px 15px 0px #00000033;

    border-radius: 2px;

    overflow: auto;

}

.icon{

    pointer-events: none;

}

.noSelect{

  -webkit-touch-callout:none; /* iOS Safari */

  -webkit-user-select:none;

  -khtml-user-select:none;    /* Konqueror */

  -moz-user-select:none;      /* Firefox */

  -ms-user-select:none;       /* Internet Explorer/Edge */

  user-select:none;           /* Non-prefixed version */

}



:host(:not([border]):not([disabled]):focus),

:host([border='true']:not([disabled]):focus),

:host(:not([border]):not([disabled]):hover),

:host([border='true']:not([disabled]):hover){

    border:1px solid #42b983

}

:host(:not([disabled]):focus) .body,

:host(:not([disabled]):focus-within) .body{

    transform: scaleY(1);

    opacity: 1;

    z-index: 99;

    visibility: visible;

}

:host(:not([disabled]):focus)  input{

    color: #bebebe;

}

:host(:not([border])[disabled]) *,

:host([border='true'][disabled]) *{

    background-color: #f5f5f5;

    color: #b7b7b7;

    cursor: not-allowed;

}

:host([border='false'][disabled]) *{

    color: #b7b7b7;

    cursor: not-allowed;

}

:host([loading]) .loading{

    display: flex;

}

:host([loading]) .icon{

    display: none;

}

:host(:not([loading])) .loading{

    display: none;

}

:host(:not([loading])) .icon{

    display: flex;

}

:host(:not([allow-clear])) .clear{

    display: none;

}

.clear{

    display: none;

    color: #bfbfbf;

}

.clear:hover{

    color: #8c8c8c;

}

.search{

    display: none;

    color: #bfbfbf;

}

.multipleRoot{

    display: flex;

    flex-direction: column;

    flex-wrap: wrap;

    flex-flow: wrap;

    align-items: center;

    width: 100%;

}

.tag{

    display: inline-flex;

    align-items: center;

    background-color: #f5f5f5;

    padding: 1px 4px;

    height: auto;

    font-size: .75rem;

    font-weight: bold;

    color: #242424;

    overflow: auto;

    position: relative;

    margin-right: 4px;

    margin-top: 1px;

    margin-bottom: 1px;

}

.tag-close{

    font-size: .8rem;

    padding: 2px;

    margin-left: 0px;

    color: #999999;

}

.tag-close:hover{

    color: #333;

}



</style>

<div class="root noSelect" tabindex="0" hidefocus="true">

    <div class="multipleRoot">

        <input placeholder="${this.placeholder}" style="" autocomplete="off" ${this.showSearch ? '' : 'readonly'} tabindex="0">

    </div><!--多选-->

    <lit-loading class="loading" size="12"></lit-loading>

    <!--<lit-icon class="icon" name='down' color="#c3c3c3"></lit-icon>-->

    <svg class="icon" viewBox="0 0 1024 1024" aria-hidden="true" style="width: 16px;width: 16px;fill: #c3c3c3">

        <path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3 0.1-12.7-6.4-12.7z"></path>

    </svg>

<!--    <lit-icon class="clear" name='close-circle-fill'></lit-icon>-->

    <svg class="clear" viewBox="0 0 1024 1024" aria-hidden="true" style="width: 16px;width: 16px;">

        <path d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64z m165.4 618.2l-66-0.3L512 563.4l-99.3 118.4-66.1 0.3c-4.4 0-8-3.5-8-8 0-1.9 0.7-3.7 1.9-5.2l130.1-155L340.5 359c-1.2-1.5-1.9-3.3-1.9-5.2 0-4.4 3.6-8 8-8l66.1 0.3L512 464.6l99.3-118.4 66-0.3c4.4 0 8 3.5 8 8 0 1.9-0.7 3.7-1.9 5.2L553.5 514l130 155c1.2 1.5 1.9 3.3 1.9 5.2 0 4.4-3.6 8-8 8z"></path>

    </svg>

<!--    <lit-icon class="search" name='search'></lit-icon>-->

    <svg class="search" viewBox="0 0 1024 1024" aria-hidden="true" style="width: 16px;width: 16px;">

        <path d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6c3.2 3.2 8.4 3.2 11.6 0l43.6-43.5c3.2-3.2 3.2-8.4 0-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"></path>

    </svg>

</div>

<div class="body">

    <slot></slot>

    <slot name="footer"></slot>

</div>

        `

            }



            isMultiple() {

                return this.hasAttribute('mode') && this.getAttribute('mode') === 'multiple'

            }



            newTag(value, text) {

                let tag = document.createElement('div');

                let icon = document.createElement('lit-icon');

                icon.classList.add('tag-close')

                icon.name = 'close'

                let span = document.createElement('span');

                tag.classList.add('tag');

                span.dataset['value'] = value;

                span.textContent = text;

                tag.append(span);

                tag.append(icon);

                icon.onclick = ev => {

                    tag.parentElement.removeChild(tag);

                    this.querySelector(`lit-select-option[value=${value}]`).removeAttribute('selected')

                    if (this.shadowRoot.querySelectorAll('.tag').length == 0) {

                        this.inputElement.style.width = 'auto';

                        this.inputElement.placeholder = this.defaultPlaceholder;

                    }

                    ev.stopPropagation();

                }

                tag.value = value;

                tag.dataset['value'] = value;

                tag.text = text;

                tag.dataset['text'] = text;

                return tag;

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {

                this.tabIndex = 0;//设置当前组件为可以获取焦点

                this.focused = false;

                this.inputElement = this.shadowRoot.querySelector('input');

                this.inputElement.style.width = '100%'

                this.clearElement = this.shadowRoot.querySelector('.clear');

                this.iconElement = this.shadowRoot.querySelector('.icon');

                this.searchElement = this.shadowRoot.querySelector('.search');

                this.multipleRootElement = this.shadowRoot.querySelector('.multipleRoot');

                // console.log(this.multipleRootElement);

                //点击清理 清空input值,展示placeholder,

                this.clearElement.onclick = ev => {

                    if (this.isMultiple()) {

                        let delNodes = []

                        this.multipleRootElement.childNodes.forEach(a => {

                            if (a.tagName === 'DIV') {

                                delNodes.push(a);

                            }

                        })

                        for (let i = 0; i < delNodes.length; i++) {

                            delNodes[i].remove();

                        }

                        if (this.shadowRoot.querySelectorAll('.tag').length == 0) {

                            this.inputElement.style.width = 'auto';

                            this.inputElement.placeholder = this.defaultPlaceholder;

                        }

                    }

                    this.querySelectorAll('lit-select-option').forEach(a => a.removeAttribute('selected'));

                    this.inputElement.value = ''

                    this.clearElement.style.display = 'none';

                    this.iconElement.style.display = 'flex';

                    this.blur();

                    ev.stopPropagation();//这里不会因为点击清理而触发 选择栏目显示或者隐藏

                    this.dispatchEvent(new CustomEvent('onClear', { detail: ev }))//向外派发清理事件

                }

                //初始化时遍历所有的option节点

                this.initOptions();

                //当前控件点击时 如果时select本身 需要显示 或 隐藏选择栏目,通过this.focused变量控制(默认为false)

                this.onclick = ev => {

                    if (ev.target.tagName === 'LIT-SELECT') {

                        if (!this.focused) {

                            this.inputElement.focus();

                            this.focused = true;

                        } else {

                            this.blur();

                            this.focused = false;

                        }

                    }

                }

                this.onmouseover = this.onfocus = ev => {

                    // console.log('onmouseover',ev);

                    if (this.hasAttribute('allow-clear')) {

                        if (this.inputElement.value.length > 0 || this.inputElement.placeholder !== this.defaultPlaceholder) {

                            this.clearElement.style.display = 'flex'

                            this.iconElement.style.display = 'none';

                        } else {

                            this.clearElement.style.display = 'none'

                            this.iconElement.style.display = 'flex';

                        }

                    }

                }

                this.onmouseout = this.onblur = ev => {

                    // console.log('onmouseout',ev);

                    if (this.hasAttribute('allow-clear')) {

                        this.clearElement.style.display = 'none';

                        this.iconElement.style.display = 'flex';

                    }

                    this.focused = false;

                }

                //输入框获取焦点时,value值 暂存于 placeholder  然后value值清空,这样值会以placeholder形式灰色展示,鼠标位于第一个字符

                this.inputElement.onfocus = ev => {

                    if (this.hasAttribute('disabled')) return;//如果控件处于disabled状态 直接忽略

                    if (this.inputElement.value.length > 0) {

                        this.inputElement.placeholder = this.inputElement.value;

                        this.inputElement.value = ''

                    }

                    if (this.hasAttribute('show-search')) {//如果有show-search属性 需要显示放大镜,隐藏向下的箭头

                        this.searchElement.style.display = 'flex';

                        this.iconElement.style.display = 'none';

                    }

                    this.querySelectorAll('lit-select-option').forEach(a => {//input获取焦点时显示所有可选项,相当于清理了搜索结果

                        a.style.display = 'flex';

                    })

                }

                //当输入框失去焦点的时候 placeholder 的值 保存到value上,input显示值

                this.inputElement.onblur = ev => {

                    if (this.hasAttribute('disabled')) return;//如果控件处于disabled状态 直接忽略

                    if (this.isMultiple()) {

                        if (this.hasAttribute('show-search')) {//如果有show-search属性 失去焦点需要 隐藏放大镜图标,显示默认的向下箭头图标

                            this.searchElement.style.display = 'none';

                            this.iconElement.style.display = 'flex';

                        }

                    } else {

                        if (this.inputElement.placeholder !== this.defaultPlaceholder) {//如果placeholder为 请输入(默认值)不做处理

                            this.inputElement.value = this.inputElement.placeholder; //placeholder 保存的值放入 value中

                            this.inputElement.placeholder = this.defaultPlaceholder;//placeholder 值为 默认值(请输入)

                        }

                        if (this.hasAttribute('show-search')) {//如果有show-search属性 失去焦点需要 隐藏放大镜图标,显示默认的向下箭头图标

                            this.searchElement.style.display = 'none';

                            this.iconElement.style.display = 'flex';

                        }

                    }

                }

                //输入框每次文本变化 会匹配搜索的option 显示或者隐藏,达到搜索的效果

                this.inputElement.oninput = ev => {

                    // console.log(ev.target.value);

                    let els = [...this.querySelectorAll('lit-select-option')];

                    if (!ev.target.value) {

                        els.forEach(a => a.style.display = 'flex');

                    } else {

                        els.forEach(a => {

                            let value = a.getAttribute('value');

                            // console.log(value.toLowerCase(), ev.target.value.toLowerCase());

                            if (value.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1 ||

                                a.textContent.toLowerCase().indexOf(ev.target.value.toLowerCase()) !== -1) {

                                a.style.display = 'flex';

                            } else {

                                a.style.display = 'none';

                            }

                        })

                    }

                }

                //输入框按下回车键,自动输入当前搜索出来的第一行,及display!='none'的第一个,搜索会隐藏其他行

                this.inputElement.onkeydown = ev => {

                    if (ev.key === 'Backspace') {

                        if (this.isMultiple()) {

                            let tag = this.multipleRootElement.lastElementChild.previousElementSibling;

                            if (tag) {

                                console.log(tag.value);

                                this.querySelector(`lit-select-option[value=${tag.value}]`).removeAttribute('selected');

                                tag.remove()

                                if (this.shadowRoot.querySelectorAll('.tag').length == 0) {

                                    this.inputElement.style.width = 'auto';

                                    this.inputElement.placeholder = this.defaultPlaceholder;

                                }

                            }

                        } else {

                            this.clear();

                            this.dispatchEvent(new CustomEvent('onClear', { detail: ev }))//向外派发清理事件

                        }

                    } else if (ev.key === 'Enter') {

                        let filter = [...this.querySelectorAll('lit-select-option')].filter(a => a.style.display !== 'none');

                        if (filter.length > 0) {

                            this.inputElement.value = filter[0].textContent;

                            this.inputElement.placeholder = filter[0].textContent;

                            this.blur();

                            this.dispatchEvent(new CustomEvent('change', {

                                detail: {

                                    selected: true,

                                    value: filter[0].getAttribute('value'),

                                    text: filter[0].textContent

                                }

                            }));//向外层派发change事件,返回当前选中项

                        }

                    }

                }

            }



            initOptions() {

                this.querySelectorAll('lit-select-option').forEach(a => {

                    //如果节点的值为 当前控件的默认值 defalut-value则 显示该值对应的option文本

                    if (this.isMultiple()) {

                        a.setAttribute('check', '');

                        if (a.getAttribute('value') === this.defaultValue) {

                            let tag = this.newTag(a.getAttribute('value'), a.textContent);

                            this.multipleRootElement.insertBefore(tag, this.inputElement);

                            this.inputElement.placeholder = '';

                            this.inputElement.value = '';

                            this.inputElement.style.width = '1px';

                            a.setAttribute('selected', '');

                        }

                        // this.inputElement.focus();

                    } else {

                        if (a.getAttribute('value') === this.defaultValue) {

                            this.inputElement.value = a.textContent;

                            a.setAttribute('selected', '');

                        }

                    }

                    //每个option设置onSelected事件 接受当前点击的option

                    a.addEventListener('onSelected', (e) => {

                        // console.log(e.detail);

                        //所有option设置为未选中状态

                        if (this.isMultiple()) {//多选

                            if (a.hasAttribute('selected')) {

                                // console.log(e.detail.value);

                                let tag = this.shadowRoot.querySelector(`div[data-value=${e.detail.value}]`);

                                // console.log(tag);

                                tag.parentElement.removeChild(tag);

                                e.detail.selected = false;

                            } else {

                                let tag = this.newTag(e.detail.value, e.detail.text);

                                this.multipleRootElement.insertBefore(tag, this.inputElement);

                                this.inputElement.placeholder = '';

                                this.inputElement.value = '';

                                this.inputElement.style.width = '1px';

                            }

                            if (this.shadowRoot.querySelectorAll('.tag').length == 0) {

                                this.inputElement.style.width = 'auto';

                                this.inputElement.placeholder = this.defaultPlaceholder;

                            }

                            this.inputElement.focus();

                        } else {//单选

                            [...this.querySelectorAll('lit-select-option')].forEach(a => a.removeAttribute('selected'))

                            this.blur();//失去焦点,隐藏选择栏目列表

                            this.inputElement.value = e.detail.text;

                        }

                        //设置当前option为选择状态

                        if (a.hasAttribute('selected')) {

                            a.removeAttribute('selected')

                        } else {

                            a.setAttribute('selected', '')

                        }

                        //设置input的值为当前选择的文本

                        this.dispatchEvent(new CustomEvent('change', { detail: e.detail }));//向外层派发change事件,返回当前选中项

                    })

                })

            }



            //js调用清理选项

            clear() {

                this.inputElement.value = '';

                this.inputElement.placeholder = this.defaultPlaceholder;

            }



            //重置为默认值

            reset() {

                this.querySelectorAll('lit-select-option').forEach(a => {

                    //如果节点的值为 当前控件的默认值 defalut-value则 显示该值对应的option文本

                    [...this.querySelectorAll('lit-select-option')].forEach(a => a.removeAttribute('selected'))

                    if (a.getAttribute('value') === this.defaultValue) {

                        this.inputElement.value = a.textContent;

                        a.setAttribute('selected', '');

                    }

                })

            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {

                if (name === 'value' && this.inputElement) {

                    if (newValue) {

                        [...this.querySelectorAll('lit-select-option')].forEach(a => {

                            if (a.getAttribute('value') === newValue) {

                                a.setAttribute('selected', '');

                                this.inputElement.value = a.textContent;

                            } else {

                                a.removeAttribute('selected')

                            }

                        })

                    } else {

                        this.clear();

                    }

                }

            }



            set dataSource(value) {

                value.forEach(a => {

                    let option = document.createElement('lit-select-option');

                    option.setAttribute('value', a.key);

                    option.textContent = a.val;

                    this.append(option)

                })

                this.initOptions();

            }



        }

        if (!customElements.get('lit-select')) {

            customElements.define('lit-select', LitSelect);

        }



        class LitSelectGroup extends HTMLElement {

            static get observedAttributes() {

                return ['label']

            }



            get label() {

                return this.getAttribute('label') || '';

            }



            set label(value) {

                this.setAttribute('label', value);

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{

            display: flex;

            flex-direction: column;

            /*padding-left: 10px;*/

        }

        .lab{

            padding: 8px 10px 8px 10px;

            font-size: .5rem;

            color: #8c8c8c;

        }

        ::slotted(lit-select-option){

            padding-left: 20px;

        }

        </style>

        <div class="lab">${this.label}</div>

        <slot></slot>

        `

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {



            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {



            }

        }

        if (!customElements.get('lit-select-group')) {

            customElements.define('lit-select-group', LitSelectGroup);

        }



        class LitSelectOption extends HTMLElement {

            static get observedAttributes() {

                return ['selected', 'disabled', 'check']

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{

            display: flex;

            padding: 8px 10px;

            transition: all .3s;

            color: #333;

            tab-index: -1;

            overflow: scroll;

            align-items: center;

            justify-content: space-between;

        }

        :host(:not([disabled])[selected]){

            background-color: #e9f7fe;

            font-weight: bold;

        }

        :host(:not([disabled]):not([selected]):hover){

            background-color: #f5f5f5;

        }

        :host([disabled]){

            cursor: not-allowed;

            color: #bfbfbf;

        }

        :host([selected][check]) .check{

             display: flex;

        }

        :host(:not([selected])) .check{

             display: none;

        }

        :host(:not([check])) .check{

            display: none;

        }

        </style>

        <slot></slot>

        <lit-icon class="check" name="check"></lit-icon>

        `

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {

                if (!this.hasAttribute('disabled')) {

                    this.onclick = ev => {

                        this.dispatchEvent(new CustomEvent('onSelected', {

                            detail: {

                                selected: true,

                                value: this.getAttribute('value'),

                                text: this.textContent

                            }

                        }))

                    }

                }



            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {



            }

        }

        if (!customElements.get('lit-select-option')) {

            customElements.define('lit-select-option', LitSelectOption);

        }



        class LitTable extends HTMLElement {

            static get observedAttributes() {

                return ['scroll-y', 'selectable', 'defaultOrderColumn']

            }



            get selectable() {

                return this.hasAttribute('selectable');

            }



            set selectable(value) {

                if (value) {

                    this.setAttribute('selectable', '');

                } else {

                    this.removeAttribute('selectable');

                }

            }



            get scrollY() {

                return this.getAttribute('scroll-y') || 'auto';

            }



            set scrollY(value) {

                this.setAttribute('scroll-y', value);

            }



            get dataSource() {

                return this.ds || [];

            }



            set dataSource(value) {

                this.ds = value;

                if (this.hasAttribute('tree')) {

                    this.renderTreeTable();

                } else {

                    this.renderTable();

                }

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

<style>

:host{

    display: grid;

    grid-template-columns: repeat(1,1fr);

    overflow: auto;

    /*width: 500px;*/

    width: 100%;

    height: 100%;

}

.tr{

    display: grid;

    transition: all .3s;

}

.tr:nth-of-type(even){

    background-color: #fcfcfc;

}

/*.tr:not(:last-of-type):not(:first-of-type){*/

/*    border-top: 1px solid #f0f0f0;*/

/*}*/

/*.tr:last-of-type{*/

/*    border-top: 1px solid #f0f0f0;*/

/*    border-bottom: 1px solid #f0f0f0;*/

/*}*/

.tr{

    background-color: #fff;

}

.tr:hover{

    background-color: #f3f3f3; /*antd #fafafa 42b983*/

}

.td{

    background-color: inherit;

    box-sizing: border-box;

    padding: 10px;

    display: flex;

    justify-content: flex-start;

    align-items: center;

    width: 100%;

    height: auto;

    /*overflow: auto;*/

    border-left: 1px solid #f0f0f0;

}

.td-order{

    /*background: green;*/

}

.td-order:before{



}

.td:last-of-type{

    border-right: 1px solid #f0f0f0;

}

.table{

     color: #262626;

}

:host(:not([noheader])) .thead{

    display: grid;

    position: sticky;

    top: 0;

    font-weight: bold;

    font-size: .9rem;

    color: #fff;

    /*width: 100%;*/

    background-color: #42b983;

    z-index: 1;

}

/*配置有 noheader 表示不限时表头,tbody上添加 border-top*/

:host([noheader]) .thead{

    display: none;

    position: sticky;

    top: 0;

    font-weight: bold;

    font-size: .9rem;

    color: #fff;

    /*width: 100%;*/

    background-color: #42b983;

    z-index: 1;

}

:host([noheader]) .tbody{

    border-top: 1px solid #f0f0f0;

}



.tbody{

    width: 100%;

    height: ${this.scrollY};

    display: grid;

    grid-template-columns: 1fr;

    row-gap: 1px;

    column-gap: 1px;

    background-color: #f0f0f0;

    border-bottom: 1px solid #f0f0f0;

    /*overflow:  auto;*/

    ${this.scrollY === 'auto' ? '' : 'overflow-y: auto'};

}

.th{

    display: grid;

    background-color: #42b983;

    /*position: sticky;*/

    /*top: 0;*/

}



.tree-icon{

    font-size: 1.2rem;

    width: 20px;

    height: 20px;

    padding-right: 5px;

    padding-left: 5px;

    cursor: pointer;

}

.tree-icon:hover{

    color: #42b983;

}

.row-checkbox,row-checkbox-all{



}



.up-svg{

    position: absolute;

    right: 5px;

    top: 8px;

    width: 15px;

    height: 15px;

}

.down-svg{

    position: absolute;

    right: 5px;

    bottom: 8px;

    width: 15px;

    height: 15px;

}

</style>



<slot id="slot" style="display: none"></slot>

<div class="table">

    <div class="thead"></div>

    <div class="tbody"></div>

</div>

        `



            }



            /*根据column[]嵌套结构得到 grid css布局描述*/



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {

                this.st = this.shadowRoot.querySelector('#slot');

                this.tableElement = this.shadowRoot.querySelector('.table');

                this.theadElement = this.shadowRoot.querySelector('.thead');

                this.tbodyElement = this.shadowRoot.querySelector('.tbody');

                this.tableColumns = this.querySelectorAll('lit-table-column');

                this.colCount = this.tableColumns.length;

                this.st.addEventListener('slotchange', (event) => {

                    this.theadElement.innerHTML = '';

                    setTimeout(() => {

                        this.columns = this.st.assignedElements();



                        let rowElement = document.createElement('div');

                        rowElement.classList.add('th');

                        if (this.selectable) {

                            let box = document.createElement('div');

                            box.style.display = 'flex';

                            box.style.justifyContent = 'center';

                            box.style.alignItems = 'center';

                            box.style.gridArea = "_checkbox_";

                            box.classList.add('td');

                            box.style.backgroundColor = "#ffffff66";

                            let checkbox = document.createElement('lit-checkbox');

                            checkbox.classList.add('row-checkbox-all');

                            // checkbox.style.boxShadow = '0 0 1px #fff';

                            // console.log(checkbox.shadowRoot.querySelector('input'));

                            checkbox.onchange = e => {

                                this.shadowRoot.querySelectorAll('.row-checkbox').forEach(a => a.checked = e.detail.checked);

                                if (e.detail.checked) {

                                    this.shadowRoot.querySelectorAll('.tr').forEach(a => a.setAttribute('checked', ''));

                                } else {

                                    this.shadowRoot.querySelectorAll('.tr').forEach(a => a.removeAttribute('checked'));

                                }

                            }



                            box.appendChild(checkbox);

                            rowElement.appendChild(box);

                        }



                        // let getGridDesc = (columns)=>{

                        //     columns.forEach(a=>{

                        //         // console.log(a);

                        //         if(a.tagName==='LIT-TABLE-GROUP'){

                        //             let children = [...a.querySelectorAll('lit-table-column')];

                        //             // console.log(children);

                        //             getGridDesc(children)

                        //         }else{

                        //             // console.log([...a.querySelectorAll('lit-table-column')]);

                        //         }

                        //     })

                        // }

                        // getGridDesc(this.columns);

                        let area = [], gridTemplateColumns = [];

                        let resolvingArea = (columns, x, y) => {

                            columns.forEach((a, i) => {

                                // console.log(a.getAttribute('key'),i);

                                if (!area[y]) area[y] = []

                                let key = a.getAttribute('key') || a.getAttribute('title')

                                if (a.tagName === 'LIT-TABLE-GROUP') {

                                    let len = a.querySelectorAll('lit-table-column').length;

                                    let children = [...a.children].filter(a => a.tagName !== 'TEMPLATE');

                                    if (children.length > 0) {

                                        resolvingArea(children, x, y + 1);

                                    }

                                    for (let j = 0; j < len; j++) {

                                        area[y][x] = { x, y, t: key };

                                        x++;

                                    }

                                    let h = document.createElement('div');

                                    h.classList.add('td');

                                    h.style.justifyContent = a.getAttribute('align')

                                    h.style.borderBottom = '1px solid #f0f0f0'

                                    h.style.gridArea = key;

                                    h.innerText = a.title;

                                    if (a.hasAttribute('fixed')) {

                                        this.fixed(h, a.getAttribute('fixed'), "#42b983")

                                    }

                                    rowElement.append(h);

                                } else if (a.tagName === 'LIT-TABLE-COLUMN') {

                                    area[y][x] = { x, y, t: key };

                                    x++;

                                    let h = document.createElement('div');

                                    h.classList.add('td');

                                    if (a.hasAttribute('order')) {

                                        h.sortType = 0;

                                        h.classList.add('td-order');

                                        h.style.position = "relative"

                                        let NS = "http://www.w3.org/2000/svg";

                                        let upSvg = document.createElementNS(NS, "svg");

                                        let upPath = document.createElementNS(NS, "path");

                                        upSvg.setAttribute('fill', '#efefef');

                                        upSvg.setAttribute('viewBox', '0 0 1024 1024');

                                        upSvg.setAttribute('stroke', '#000000');

                                        upSvg.classList.add('up-svg');

                                        // upPath.setAttribute("d", "M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3c-3.8 5.3-0.1 12.7 6.5 12.7h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z");

                                        upPath.setAttribute("d", "M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z");

                                        // upPath.setAttribute("fill", "#ffffff");

                                        // upPath.setAttribute("stroke-width", "2px");

                                        // upPath.setAttribute("stroke", "rgba(207, 219, 230, 1)");

                                        // upPath.setAttribute("marker-end", "url(#markerArrow)");

                                        upSvg.appendChild(upPath);

                                        let downSvg = document.createElementNS(NS, "svg");

                                        let downPath = document.createElementNS(NS, "path");

                                        downSvg.setAttribute('fill', '#efefef');

                                        downSvg.setAttribute('viewBox', '0 0 1024 1024');

                                        downSvg.setAttribute('stroke', '#efefef');

                                        downSvg.classList.add('down-svg');

                                        // downPath.setAttribute("d", "M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3 0.1-12.7-6.4-12.7z");

                                        downPath.setAttribute("d", "M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z");

                                        // downPath.setAttribute("fill", "#ffffff");

                                        // downPath.setAttribute("stroke-width", "2px");

                                        // downPath.setAttribute("stroke", "rgba(207, 219, 230, 1)");

                                        // downPath.setAttribute("marker-end", "url(#markerArrow)");

                                        downSvg.appendChild(downPath)

                                        if (i == 0) {

                                            h.sortType = 2; // 默认以第一列 降序排序 作为默认排序

                                            upSvg.setAttribute('fill', '#efefef');

                                            downSvg.setAttribute('fill', '#333');

                                        }

                                        h.appendChild(upSvg);

                                        h.appendChild(downSvg);

                                        h.onclick = ev => {

                                            this.shadowRoot.querySelectorAll('.td-order svg').forEach(it => {

                                                it.setAttribute('fill', '#efefef');

                                                it.setAttribute('fill', '#efefef');

                                                it.sortType = 0;

                                            })

                                            if (h.sortType == undefined || h.sortType == null) {

                                                h.sortType = 0;

                                            } else if (h.sortType === 2) {

                                                h.sortType = 0;

                                            } else {

                                                h.sortType += 1;

                                            }

                                            // if(h.sortType == 2){

                                            //     h.sortType = 1

                                            // }else{

                                            //     h.sortType = 2

                                            // }

                                            switch (h.sortType) {

                                                case 1:

                                                    upSvg.setAttribute('fill', '#333');

                                                    downSvg.setAttribute('fill', '#efefef');

                                                    break;

                                                case 2:

                                                    upSvg.setAttribute('fill', '#efefef');

                                                    downSvg.setAttribute('fill', '#333');

                                                    break;

                                                default:

                                                    upSvg.setAttribute('fill', "#efefef");

                                                    downSvg.setAttribute('fill', "#efefef");

                                                    break;

                                            }

                                            this.dispatchEvent(new CustomEvent("ColumnClick", {

                                                detail: {

                                                    sort: h.sortType, key: key

                                                }, composed: true

                                            }))

                                        }

                                    }

                                    h.style.justifyContent = a.getAttribute('align')

                                    gridTemplateColumns.push(a.getAttribute('width') || '1fr');

                                    h.style.gridArea = key;

                                    let titleLabel = document.createElement("label");

                                    titleLabel.textContent = a.title;

                                    // h.innerText = a.title;

                                    h.appendChild(titleLabel);

                                    if (a.hasAttribute('fixed')) {

                                        this.fixed(h, a.getAttribute('fixed'), "#42b983")

                                    }

                                    rowElement.append(h);

                                }



                                // console.log(str)

                                // console.log(a.title,i,a.querySelectorAll('lit-table-column').length);

                            })

                        }

                        resolvingArea(this.columns, 0, 0);

                        area.forEach((rows, j, array) => {

                            for (let i = 0; i < this.colCount; i++) {

                                if (!rows[i]) rows[i] = array[j - 1][i];

                            }

                        })



                        // console.log(a.map(aa=>aa.t).join(' '));

                        // console.log(gridTemplateColumns.join(' '));

                        this.gridTemplateColumns = gridTemplateColumns.join(' ');

                        if (this.selectable) {

                            let s = area.map(a => '"_checkbox_ ' + (a.map(aa => aa.t).join(' ')) + '"').join(' ');

                            rowElement.style.gridTemplateColumns = "60px " + gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)`

                            rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)`

                            rowElement.style.gridTemplateAreas = s

                        } else {

                            let s = area.map(a => '"' + (a.map(aa => aa.t).join(' ')) + '"').join(' ');

                            rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)`

                            rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)`

                            rowElement.style.gridTemplateAreas = s

                        }

                        this.theadElement.append(rowElement);

                        if (this.hasAttribute('tree')) {

                            this.renderTreeTable();

                        } else {

                            this.renderTable();

                        }

                    });



                });



                // this.shadowRoot.addEventListener("load", function (event) {

                //     console.log("DOM fully loaded and parsed");

                // });

            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {



            }



            fixed(td, placement, bgColor, zIndex) {

                td.style.position = 'sticky';

                if (placement === "left") {

                    td.style.left = '0px';

                    // td.style.borderRight = '1px solid #f0f0f0';

                    td.style.boxShadow = '3px 0px 5px #33333333'

                    // td.style.backgroundColor=bgColor

                } else if (placement === "right") {

                    td.style.right = '0px';

                    td.style.boxShadow = '-3px 0px 5px #33333333'

                    // td.style.borderLeft = '1px solid #f0f0f0';

                    // td.style.backgroundColor=bgColor

                }

            }



            /*渲染成表格*/

            renderTable() {

                let that = this;

                if (!this.columns) return;

                if (!this.ds) return; // 如果没有设置数据源,直接返回

                this.tbodyElement.innerHTML = '';//清空表格内容

                // this.style.gridTemplateRows = `repeat(${this.ds.length}*2 ,1fr)`;

                this.ds.forEach(rowData => {

                    let rowElement = document.createElement('div');

                    rowElement.classList.add('tr');

                    rowElement.data = rowData;

                    let gridTemplateColumns = []

                    //如果table配置了selectable(选择行模式) 单独在行头部添加一个 checkbox

                    if (this.selectable) {

                        let box = document.createElement('div');

                        box.style.display = 'flex';

                        box.style.justifyContent = 'center';

                        box.style.alignItems = 'center';

                        box.classList.add('td');

                        let checkbox = document.createElement('lit-checkbox');

                        checkbox.classList.add('row-checkbox');

                        checkbox.onchange = (e) => {//checkbox 的是否选中 会影响  行对应的 div上是否有 checked属性,用于标记

                            if (e.detail.checked) {

                                rowElement.setAttribute('checked', "");

                            } else {

                                rowElement.removeAttribute('checked');

                            }

                        }

                        box.appendChild(checkbox);

                        rowElement.appendChild(box);

                    }

                    this.tableColumns.forEach(cl => {

                        let dataIndex = cl.getAttribute('data-index');

                        gridTemplateColumns.push(cl.getAttribute('width') || '1fr')

                        if (cl.template) {//如果自定义渲染,从模版中渲染得到节点

                            let cloneNode = cl.template.render(rowData).content.cloneNode(true);

                            // cloneNode.classList.add('td');

                            let d = document.createElement('div');

                            d.classList.add('td');

                            d.style.justifyContent = cl.getAttribute('align')

                            if (cl.hasAttribute('fixed')) {

                                this.fixed(d, cl.getAttribute('fixed'), "#ffffff")

                            }

                            d.append(cloneNode);

                            rowElement.append(d);

                        } else {

                            let td = document.createElement('div');

                            td.classList.add('td');

                            td.style.justifyContent = cl.getAttribute('align')

                            if (cl.hasAttribute('fixed')) {

                                this.fixed(td, cl.getAttribute('fixed'), "#ffffff")

                            }

                            // td.style.position='sticky';

                            // td.innerHTML = rowData[dataIndex];

                            td.innerHTML = `<code style="padding:0;margin:0">${rowData[dataIndex].toString().replace('\n', "")}</code>`;

                            // console.log(cl,cl.template);

                            rowElement.append(td);

                        }



                    })

                    if (this.selectable) { //如果 带选择的table 前面添加一个 60px的列

                        rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)`

                    } else {

                        rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)`

                    }

                    rowElement.onclick = e => {

                        this.dispatchEvent(new CustomEvent('onRowClick', { detail: rowData, composed: true }));

                    }

                    this.tbodyElement.append(rowElement);

                })

            }



            /*渲染树表结构*/

            renderTreeTable() {

                if (!this.columns) return;

                if (!this.ds) return;

                this.tbodyElement.innerHTML = '';

                /*通过list 构建 tree 结构*/

                let ids = JSON.parse(this.getAttribute('tree') || `["id","pid"]`);

                let toTreeData = (data, id, pid) => {

                    let cloneData = JSON.parse(JSON.stringify(data));

                    return cloneData.filter(father => {

                        let branchArr = cloneData.filter(child => father[id] == child[pid]);

                        branchArr.length > 0 ? father['children'] = branchArr : '';

                        return !father[pid];

                    });

                }

                let treeData = toTreeData(this.ds, ids[0], ids[1]);//

                // console.log(treeData);

                let offset = 30;

                let offsetVal = offset;

                const drawRow = (arr, parentNode) => {

                    arr.forEach(rowData => {

                        let rowElement = document.createElement('div');

                        rowElement.classList.add('tr');

                        rowElement.data = rowData;

                        let gridTemplateColumns = [];

                        if (this.selectable) {

                            let box = document.createElement('div');

                            box.style.display = 'flex';

                            box.style.justifyContent = 'center';

                            box.style.alignItems = 'center';

                            box.classList.add('td');

                            let checkbox = document.createElement('lit-checkbox');

                            checkbox.classList.add('row-checkbox');

                            checkbox.onchange = (e) => {

                                if (e.detail.checked) {

                                    rowElement.setAttribute('checked', "");

                                } else {

                                    rowElement.removeAttribute('checked');

                                }

                                const changeChildNode = (rowElement, checked) => {

                                    let id = rowElement.getAttribute('id');

                                    let pid = rowElement.getAttribute('pid');

                                    this.shadowRoot.querySelectorAll(`div[pid=${id}]`).forEach(a => {

                                        a.querySelector('.row-checkbox').checked = checked;

                                        if (checked) {

                                            a.setAttribute('checked', '');

                                        } else {

                                            a.removeAttribute('checked');

                                        }

                                        changeChildNode(a, checked);

                                    });

                                };

                                changeChildNode(rowElement, e.detail.checked);

                            }

                            box.appendChild(checkbox);

                            rowElement.appendChild(box);

                        }

                        this.tableColumns.forEach((cl, index) => {

                            let dataIndex = cl.getAttribute('data-index');

                            gridTemplateColumns.push(cl.getAttribute('width') || '1fr')

                            let td;

                            if (cl.template) {

                                let cloneNode = cl.template.render(rowData).content.cloneNode(true);

                                // cloneNode.classList.add('td');

                                td = document.createElement('div');

                                td.classList.add('td');

                                td.style.justifyContent = cl.getAttribute('align')

                                if (cl.hasAttribute('fixed')) {

                                    this.fixed(td, cl.getAttribute('fixed'), "#ffffff")

                                }

                                td.append(cloneNode);

                            } else {

                                td = document.createElement('div');

                                td.classList.add('td');

                                td.style.justifyContent = cl.getAttribute('align')

                                if (cl.hasAttribute('fixed')) {

                                    this.fixed(td, cl.getAttribute('fixed'), "#ffffff")

                                }

                                // td.style.position='sticky';

                                td.innerHTML = rowData[dataIndex];

                                // console.log(cl,cl.template);

                            }

                            if (index === 0) {

                                if (rowData.children && rowData.children.length > 0) {

                                    let btn = document.createElement('lit-icon');

                                    btn.classList.add('tree-icon');

                                    btn.name = 'minus-square';

                                    td.insertBefore(btn, td.firstChild);

                                    td.style.paddingLeft = (offsetVal - 30) + 'px';

                                    btn.onclick = (e) => {

                                        const foldNode = (rowElement) => {

                                            let id = rowElement.getAttribute('id');

                                            let pid = rowElement.getAttribute('pid');

                                            this.shadowRoot.querySelectorAll(`div[pid=${id}]`).forEach(a => {

                                                let id = a.getAttribute('id');

                                                let pid = a.getAttribute('pid');

                                                a.style.display = 'none';

                                                foldNode(a);

                                            });

                                            if (rowElement.querySelector('.tree-icon')) {

                                                rowElement.querySelector('.tree-icon').name = 'plus-square';

                                            }

                                            rowElement.removeAttribute('expand');

                                        };

                                        const expendNode = (rowElement) => {

                                            let id = rowElement.getAttribute('id');

                                            let pid = rowElement.getAttribute('pid');

                                            this.shadowRoot.querySelectorAll(`div[pid=${id}]`).forEach(a => {

                                                let id = a.getAttribute('id');

                                                let pid = a.getAttribute('pid');

                                                a.style.display = '';

                                                // expendNode(a);

                                            });

                                            if (rowElement.querySelector('.tree-icon')) {

                                                rowElement.querySelector('.tree-icon').name = 'minus-square';

                                            }

                                            rowElement.setAttribute('expand', '');

                                        }

                                        if (rowElement.hasAttribute('expand')) {

                                            foldNode(rowElement);

                                        } else {

                                            expendNode(rowElement);

                                        }

                                    };

                                } else {

                                    td.style.paddingLeft = offsetVal + 'px';

                                }

                            }

                            rowElement.append(td);



                        })

                        if (this.selectable) {

                            rowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)`

                        } else {

                            rowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');//`repeat(${this.colCount},1fr)`

                        }

                        rowElement.onclick = e => {

                            // console.log(rowElement.style.gridTemplateColumns);

                            // LitMessage.info(JSON.stringify(rowData));

                        }

                        parentNode.append(rowElement);

                        rowElement.setAttribute('id', rowData[ids[0]]);

                        rowElement.setAttribute('pid', rowData[ids[1]]);

                        rowElement.setAttribute('expand', '');

                        if (rowData.children && rowData.children.length > 0) {

                            //有子节点的 前面加上 + 图标 表示可以展开节点



                            offsetVal = offsetVal + offset;

                            drawRow(rowData.children, parentNode);

                            offsetVal = offsetVal - offset;

                        }

                    });

                };

                drawRow(treeData, this.tbodyElement);

            }



            //获取选中的行数据

            getCheckRows() {

                return [...this.shadowRoot.querySelectorAll('div[class=tr][checked]')].map(a => a.data).map(a => {

                    delete a['children'];

                    return a;

                });

            }



            deleteRowsCondition(fn) {

                this.shadowRoot.querySelectorAll("div[class=tr]").forEach(tr => {

                    if (fn(tr.data)) {

                        tr.remove();

                    }

                })

            }

        }

        if (!customElements.get('lit-table')) {

            customElements.define('lit-table', LitTable);

        }



        class LitTableColumn extends HTMLElement {

            static get observedAttributes() {

                return ['name', 'order']

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

<style>

:host{ }

</style>

<slot id="slot"></slot>

        `

            }

            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {

                this.template = null;

                this.st = this.shadowRoot.querySelector('#slot')

                this.st.addEventListener('slotchange', () => {

                    const elements = this.st.assignedElements({ flatten: false });

                    if (elements.length > 0) {

                        this.template = elements[0];

                    }

                })

            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {



            }

        }

        if (!customElements.get('lit-table-column')) {

            customElements.define('lit-table-column', LitTableColumn);

        }



        class LitTableGroup extends HTMLElement {

            static get observedAttributes() {

                return ['title']

            }



            get title() {

                return this.getAttribute('title');

            }



            set title(value) {

                this.setAttribute('title', value);

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{ }

        </style>

        <slot id="sl"></slot>

        `

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {



            }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {



            }

        }

        if (!customElements.get('lit-table-group')) {

            customElements.define('lit-table-group', LitTableGroup);

        }



        class LitTabpane extends HTMLElement {

            static get observedAttributes() { return ['tab', 'key', 'disabled', 'icon', 'closeable', 'hide']; }

            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

<style>

:host(){

    scroll-behavior: smooth;

    -webkit-overflow-scrolling: touch;

    overflow: auto;

    width: 100%;

}

</style>

<slot></slot>

`

            }



            get tab() {

                return this.getAttribute('tab');

            }



            set tab(value) {

                this.setAttribute("tab", value);

            }



            get icon() {

                return this.getAttribute("icon");

            }



            get disabled() {

                return this.getAttribute('disabled') !== null;

            }



            set disabled(value) {

                if (value === null || !value) {

                    this.removeAttribute("disabled");

                } else {

                    this.setAttribute("disabled", value);

                }

            }

            get closeable() {

                return this.getAttribute('closeable') !== null;

            }

            set closeable(value) {

                if (value === null || !value) {

                    this.removeAttribute("closeable");

                } else {

                    this.setAttribute("closeable", value);

                }

            }



            get key() {

                return this.getAttribute("key");

            }

            set key(value) {

                this.setAttribute("key", value);

            }



            get hide() {

                return this.getAttribute('hide') !== null;

            }

            set hide(value) {

                if (value === null || !value) {

                    this.removeAttribute("hide");

                } else {

                    this.setAttribute("hide", value);

                }

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() { }



            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() { }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() { }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {

                if (oldValue !== newValue && newValue !== undefined) {

                    if (name === 'tab' && this.parentNode) {

                        this.parentNode.updateLabel && this.parentNode.updateLabel(this.key, newValue);

                    }

                    if (name === 'disabled' && this.parentNode) {

                        this.parentNode.updateDisabled && this.parentNode.updateDisabled(this.key, newValue);

                    }

                    if (name === 'closeable' && this.parentNode) {

                        this.parentNode.updateCloseable && this.parentNode.updateCloseable(this.key, newValue);

                    }

                    if (name === 'hide' && this.parentNode) {

                        this.parentNode.updateCloseable && this.parentNode.updateHide(this.key, newValue);

                    }

                }

            }

        }

        if (!customElements.get('lit-tabpane')) {

            customElements.define('lit-tabpane', LitTabpane);

        }



        class LitTabs extends HTMLElement {

            static get observedAttributes() {

                //mode = flat(default) | card

                //position = top | top-left | top-center | top-right | left | left-top | left-center | left-bottom | right | bottom

                return ['activekey', 'mode', 'position']

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{

            display: block;

            text-align: unset;

            color: #252525;

            background-color: #fff;

            box-shadow: #00000033 0 0 10px ;

            /*padding: 10px;*/

            /*margin-right: 10px;*/

        }

        ::slotted(lit-tabpane){

            box-sizing:border-box;

            width:100%;

            height:100%;

            /*padding:10px;*/

            flex-shrink:0;

            overflow:auto;

        }

        .nav-item{

            display: inline-flex;

            justify-content: center;

            align-items: center;

            padding: 6px 0px 6px 12px;

            font-size: .9rem;

            font-weight: normal;

            cursor: pointer;

            transition: all 0.3s;

            flex-shrink: 0;

        }

        .nav-item lit-icon{

            margin-right: 2px;

            font-size: inherit;

        }

        .nav-item:hover{

            color: #42b983;

        }

        .nav-item[data-disabled]{

            pointer-events: all;

            cursor: not-allowed;

            color: #bfbfbf;

        }

        .nav-item[data-selected]{

            color: #42b983;;

        }

        .tab-content{

            display: block;

            background-color: #fff;

            flex:1;

        }



        /*

         *   top  top-left top-center top-right

         */

        :host(:not([position])) .nav-root,

        :host([position^='top']) .nav-root{

            display: flex;

            position: relative;

            justify-content: center;

            align-items: center;

        }

        :host(:not([mode]):not([position])) .tab-line,/*移动的线条*/

        :host([mode='flat'][position^='top']) .tab-line{

            position:absolute;

            bottom: 2px;

            background-color: #42b983;

            height: 2px;

            transform: translateY(100%);

            transition: all 0.3s;

        }



        :host(:not([position])) .tab-nav-container,

        :host([position^='top']) .tab-nav-container{

            display: flex;

            position: relative;

            flex-direction: column;

            overflow-y: hidden;

            overflow-x: auto;

            overflow: -moz-scrollbars-none;

            -ms-overflow-style: none;

            transition: all 0.3s;

            flex: 1;

            /*background: linear-gradient(90deg,white 30%, transparent),radial-gradient(at 0 50%, rgba(0,0,0,.2),transparent 70%);*/

            /*background-repeat: no-repeat;*/

            /*background-size: 50px 100%, 15px 100%;*/

            /*background-attachment: local,scroll,local,scroll;*/

            /*border-bottom: #f0f0f0 1px solid;*/

        }

        :host([position='top']) .tab-nav,

        :host([position='top-left']) .tab-nav{

            display: flex;

            position: relative;

            justify-content: flex-start;

        }

        :host([position='top-center']) .tab-nav{

            display: flex;

            justify-content: center;

        }

        :host([position='top-right']) .tab-nav{

            display: flex;

            justify-content: flex-end;

        }



        :host([position^='top'][mode='card']) .nav-item{

            border-top: 1px solid #f0f0f0;

            border-left: 1px solid #f0f0f0;

            border-right: 1px solid #f0f0f0;

            border-bottom: 1px solid #f0f0f0;

            bottom: 0px;

            margin-right: 2px;

            position: relative;

        }

        :host([position^='top']) .tab-nav-bg-line{

            position: absolute;bottom: 0;height: 1px;background-color: #f0f0f0;width: 100%

        }

        :host([position^='top'][mode='card']) .nav-item:not([data-selected]){

            background-color: #f6f6f6;

            border-bottom: 1px solid #f0f0f0;

        }

        :host([position^='top'][mode='card']) .nav-item[data-selected]{

            background-color: #ffffff;

            border-bottom: 1px solid #fff;

            bottom: 0px;

        }

        /*

            bottom bottom-left bottom-center bottom-right

        */

        :host([position^='bottom']) .tab{

            display: flex;

            flex-direction: column-reverse;

        }

        :host([mode='flat'][position^='bottom']) .tab-line{

            position:absolute;

            top: -3px;

            background-color: #42b983;

            height: 2px;

            transform: translateY(-100%);

            transition: all 0.3s;

        }

        :host([position^='bottom']) .tab-nav-container{

            display: flex;

            position: relative;

            flex-direction: column;

            overflow-x: auto;

            overflow-y: visible;

            overflow: -moz-scrollbars-none;

            -ms-overflow-style: none;

            transition: all 0.3s;

            flex: 1;

            /*background: linear-gradient(90deg,white 30%, transparent),radial-gradient(at 0 50%, rgba(0,0,0,.2),transparent 70%);*/

            /*background-repeat: no-repeat;*/

            /*background-size: 50px 100%, 15px 100%;*/

            /*background-attachment: local,scroll,local,scroll;*/

            border-top: #f0f0f0 1px solid;

        }

        :host([position^='bottom']) .nav-root{

            display: flex;

            justify-content: center;

            align-items: center;

        }

        :host([position='bottom']) .tab-nav,

        :host([position='bottom-left']) .tab-nav{

            display: flex;

            position: relative;

            justify-content: flex-start;

        }

        :host([position='bottom-center']) .tab-nav{

            display: flex;

            justify-content: center;

        }

        :host([position='bottom-right']) .tab-nav{

            display: flex;

            justify-content: flex-end;

        }

        :host([position^='bottom'][mode='card']) .nav-item{

            border-top: 1px solid #ffffff;

            border-left: 1px solid #f0f0f0;

            border-right: 1px solid #f0f0f0;

            border-bottom: 1px solid #f0f0f0;

            top: -1px;

            margin-right: 2px;

            position: relative;

        }

        :host([position^='bottom']) .tab-nav-bg-line{

            position: absolute;top: 0;height: 1px;background-color: #f0f0f0;width: 100%

        }

        :host([position^='bottom'][mode='card']) .nav-item:not([data-selected]){

            background-color: #f5f5f5;

            border-top: 1px solid #f0f0f0;

        }

        :host([position^='bottom'][mode='card']) .nav-item[data-selected]{

            background-color: #ffffff;

            border-top: 1px solid #fff;

            top: -1px;

        }

        /*

        left left-top left-center left-bottom

        */

        :host([position^='left']) .tab{

            display: flex;

            flex-direction: row;

        }

        :host([mode='flat'][position^='left']) .tab-line{

            position:absolute;

            right: 1px;

            background-color: #42b983;

            width: 3px;

            transform: translateX(100%);

            transition: all 0.3s;

        }

        :host([position^='left']) .tab-nav-container{

            display: flex;

            position: relative;

            flex-direction: row;

            overflow-x: auto;

            overflow-y: visible;

            overflow: -moz-scrollbars-none;

            -ms-overflow-style: none;

            transition: all 0.3s;

            flex: 1;

            /*background: linear-gradient(90deg,white 30%, transparent),radial-gradient(at 0 50%, rgba(0,0,0,.2),transparent 70%);*/

            /*background-repeat: no-repeat;*/

            /*background-size: 50px 100%, 15px 100%;*/

            /*background-attachment: local,scroll,local,scroll;*/

            border-right: #f0f0f0 1px solid;

        }

        :host([position^='left']) .nav-root{

            display: flex;

            flex-direction: column;

            justify-content: center;

            align-items: center;

        }

        :host([position='left']) .tab-nav,

        :host([position='left-top']) .tab-nav{

            display: flex;

            position: relative;

            flex-direction: column;

            justify-content: flex-start;

        }

        :host([position='left-center']) .tab-nav{

            display: flex;

            position: relative;

            flex-direction: column;

            justify-content: center;

        }

        :host([position='left-bottom']) .tab-nav{

            display: flex;

            position: relative;

            flex-direction: column;

            justify-content: flex-end;

        }

        :host([position^='left'][mode='card']) .nav-item{

            border-top: 1px solid #f0f0f0;

            border-left: 1px solid #f0f0f0;

            border-right: 1px solid #ffffff;

            border-bottom: 1px solid #f0f0f0;

            right: -1px;

            margin-bottom: 2px;

            position: relative;

        }

        :host([position^='left']) .tab-nav-bg-line{

            position: absolute;right: 0;width: 1px;background-color: #f0f0f0;width: 100%

        }

        :host([position^='left'][mode='card']) .nav-item:not([data-selected]){

            background-color: #f5f5f5;

            border-right: 1px solid #f0f0f0;

        }

        :host([position^='left'][mode='card']) .nav-item[data-selected]{

            background-color: #ffffff;

            border-bottom: 1px solid #fff;

            right: -1px;

        }

        /*

        right right-top right-center right-bottom

        */

        :host([position^='right']) .tab{

            display: flex;

            flex-direction: row-reverse;

        }

        :host([mode='flat'][position^='right']) .tab-line{

            position:absolute;

            left: 1px;

            background-color: #42b983;

            width: 3px;

            transform: translateX(-100%);

            transition: all 0.3s;

        }

        :host([position^='right']) .tab-nav-container{

            display: flex;

            position: relative;

            flex-direction: row-reverse;

            overflow-x: auto;

            overflow-y: visible;

            overflow: -moz-scrollbars-none;

            -ms-overflow-style: none;

            transition: all 0.3s;

            flex: 1;

            /*background: linear-gradient(90deg,white 30%, transparent),radial-gradient(at 0 50%, rgba(0,0,0,.2),transparent 70%);*/

            /*background-repeat: no-repeat;*/

            /*background-size: 50px 100%, 15px 100%;*/

            /*background-attachment: local,scroll,local,scroll;*/

            border-left: #f0f0f0 1px solid;

        }

        :host([position^='right']) .nav-root{

            display: flex;

            flex-direction: column;

            justify-content: center;

            align-items: center;

        }

        :host([position='right']) .tab-nav,

        :host([position='right-top']) .tab-nav{

            display: flex;

            position: relative;

            flex-direction: column;

            justify-content: flex-start;

        }

        :host([position='right-center']) .tab-nav{

            display: flex;

            position: relative;

            flex-direction: column;

            justify-content: center;

        }

        :host([position='right-bottom']) .tab-nav{

            display: flex;

            position: relative;

            flex-direction: column;

            justify-content: flex-end;

        }

        :host([position^='right'][mode='card']) .nav-item{

            border-top: 1px solid #f0f0f0;

            border-left: 1px solid #ffffff;

            border-right: 1px solid #f0f0f0;

            border-bottom: 1px solid #f0f0f0;

            left: -1px;

            margin-top: 2px;

            position: relative;

        }

        :host([position^='right']) .tab-nav-bg-line{

            position: absolute;left: 0;width: 1px;background-color: #f0f0f0;width: 100%

        }

        :host([position^='right'][mode='card']) .nav-item:not([data-selected]){

            background-color: #f5f5f5;

            border-left: 1px solid #f0f0f0;

        }

        :host([position^='right'][mode='card']) .nav-item[data-selected]{

            background-color: #ffffff;

            left: -1px;

        }





        .tab-nav-container::-webkit-scrollbar {

            display: none;

        }





        /*关闭的图标*/

        .close-icon:hover{

            color: #000;

        }

        .nav-item[data-closeable] .close-icon{

            display: block;

            padding: 5px 5px 5px 5px;

            color: #999;

        }

        .nav-item[data-closeable] .no-close-icon{

            display: none;

        }

        .nav-item:not([data-closeable]) .no-close-icon{

            display: block;

        }

        .nav-item:not([data-closeable]) .close-icon{

            display: none;

        }

        .nav-item:not([data-hide]){

            display: block;

        }

        .nav-item[data-hide]{

            display: none;

        }



        </style>

        <style id="filter"></style>

        <div class="tab">

            <div class="nav-root">

                <slot name="left" style="flex:1"></slot>

                <div class="tab-nav-container" >

                    <div class="tab-nav-bg-line"></div>

                    <div class="tab-nav" id="nav"></div>

                    <div class="tab-line" id="tab-line"></div>

                </div>

                <slot name="right" style="flex:1"></slot>

            </div>

            <div class="tab-content">

                <slot id="slot">NEED CONTENT</slot>

            </div>

        </div>

        `

            }



            get position() {

                return this.getAttribute('position') || 'top';

            }



            set position(value) {

                this.setAttribute('position', value);

            }



            get mode() {

                return this.getAttribute('mode') || 'flat';

            }



            set mode(value) {

                this.setAttribute('mode', value);

            }



            get activekey() {

                return this.getAttribute("activekey");

            }



            set activekey(value) {

                this.setAttribute('activekey', value);

            }



            updateLabel(key, value) {

                // console.log(key, value);

                if (this.nav) {

                    let item = this.nav.querySelector(`.nav-item[data-key='${key}']`);

                    if (item) {

                        item.querySelector("span").innerHTML = value;

                        this.initTabPos()

                    }

                }

            }



            updateDisabled(key, value) {

                // console.log(key, value);

                if (this.nav) {

                    let item = this.nav.querySelector(`.nav-item[data-key='${key}']`);

                    if (item) {

                        if (value) {

                            item.setAttribute('data-disabled', '')

                        } else {

                            item.removeAttribute('data-disabled');

                        }

                        this.initTabPos()

                    }

                }

            }

            updateCloseable(key, value) {

                if (this.nav) {

                    let item = this.nav.querySelector(`.nav-item[data-key='${key}']`);

                    if (item) {

                        if (value) {

                            item.setAttribute('data-closeable', '')

                        } else {

                            item.removeAttribute('data-closeable');

                        }

                        this.initTabPos()

                    }

                }

            }

            updateHide(key, value) {

                if (this.nav) {

                    let item = this.nav.querySelector(`.nav-item[data-key='${key}']`);

                    if (item) {

                        if (value) {

                            item.setAttribute('data-hide', '')

                        } else {

                            item.removeAttribute('data-hide');

                        }

                        this.initTabPos()

                    }

                }

            }



            initTabPos() {

                const items = this.nav.querySelectorAll(".nav-item");

                Array.from(items).forEach((a, index) => {

                    this.tabPos[a.dataset.key] = {

                        index: index,

                        width: a.offsetWidth,

                        height: a.offsetHeight,

                        left: a.offsetLeft,

                        top: a.offsetTop,

                        label: a.textContent

                    }

                })

                if (this.activekey) {

                    if (this.position.startsWith('left')) {

                        this.line.style = `height:${this.tabPos[this.activekey].height}px;transform:translate(100%,${this.tabPos[this.activekey].top}px)`;

                    } else if (this.position.startsWith('top')) {

                        if (this.tabPos[this.activekey]) {

                            this.line.style = `width:${this.tabPos[this.activekey].width}px;transform:translate(${this.tabPos[this.activekey].left}px,100%)`;

                        }

                    } else if (this.position.startsWith('right')) {

                        this.line.style = `height:${this.tabPos[this.activekey].height}px;transform:translate(-100%,${this.tabPos[this.activekey].top}px)`;

                    } else if (this.position.startsWith('bottom')) {

                        this.line.style = `width:${this.tabPos[this.activekey].width}px;transform:translate(${this.tabPos[this.activekey].left}px,100%)`;

                    }

                }

            }



            //当 custom element首次被插入文档DOM时,被调用。

            connectedCallback() {

                let that = this;

                this.tabPos = {}

                this.nav = this.shadowRoot.querySelector('#nav')

                this.line = this.shadowRoot.querySelector('#tab-line')

                this.slots = this.shadowRoot.querySelector('#slot');

                this.slots.addEventListener('slotchange', () => {

                    const elements = this.slots.assignedElements();

                    let panes = this.querySelectorAll('lit-tabpane');

                    if (this.activekey) {

                        panes.forEach(a => {

                            if (a.key === this.activekey) {

                                a.style.display = 'block'

                            } else {

                                a.style.display = 'none';

                            }

                        })

                    } else {

                        panes.forEach((a, index) => {

                            if (index === 0) {

                                a.style.display = 'block'

                                this.activekey = a.key

                            } else {

                                a.style.display = 'none';

                            }

                        })

                    }



                    let navHtml = "";

                    elements.forEach(a => {

                        if (a.disabled) {

                            navHtml += `<div class="nav-item" data-key="${a.key}" data-disabled ${a.closeable ? 'data-closeable' : ''} ${a.hide ? 'data-hide' : ''}>

                    ${a.icon ? `<lit-icon name='${a.icon}'></lit-icon>` : ``}

                    <span>${a.tab}</span>

                    <lit-icon class="close-icon" name='close' size="12"></lit-icon><div class="no-close-icon" style="margin-right: 12px"></div>

                    </div>`;

                        } else {

                            if (a.key === this.activekey) {

                                navHtml += `<div class="nav-item" data-key="${a.key}" data-selected ${a.closeable ? 'data-closeable' : ''} ${a.hide ? 'data-hide' : ''}>

                        ${a.icon ? `<lit-icon name='${a.icon}'></lit-icon>` : ``}

                        <span>${a.tab}</span>

                        <lit-icon class="close-icon" name='close' size="12"></lit-icon><div class="no-close-icon" style="margin-right: 12px"></div>

                        </div>`;

                            } else {

                                navHtml += `<div class="nav-item" data-key="${a.key}" ${a.closeable ? 'data-closeable' : ''} ${a.hide ? 'data-hide' : ''}>

                            ${a.icon ? `<lit-icon name='${a.icon}'></lit-icon>` : ``}

                            <span>${a.tab}</span>

                            <lit-icon class="close-icon" name='close' size="12"></lit-icon><div class="no-close-icon" style="margin-right: 12px"></div>

                            </div>`;

                            }



                        }

                    })

                    this.nav.innerHTML = navHtml;

                    this.initTabPos()

                    this.nav.querySelectorAll('.close-icon').forEach(a => {

                        a.onclick = (e) => {

                            e.stopPropagation();

                            const closeKey = e.target.parentElement.dataset.key;

                            console.log(closeKey);

                            console.log(e.target.parentElement.parentElement);

                            this.nav.removeChild(e.target.parentElement)

                            let elements = this.slots.assignedElements();

                            let closeElement = elements.filter(a => a.key === closeKey)[0];

                            closeElement.parentElement.removeChild(closeElement)

                            if (closeElement.style.display !== 'none') {

                                elements = this.slots.assignedElements();

                                let elArr = elements.filter(a => !a.hasAttribute('disabled'));

                                if (elArr.length > 0) {

                                    elArr[0].style.display = 'block';

                                    this.activekey = elArr[0].key

                                }

                            }

                        }

                    });

                })

                this.nav.onclick = (e) => {

                    if (e.target.closest('div').hasAttribute('data-disabled')) return;

                    let key = e.target.closest('div').dataset.key;

                    this.activeByKey(key)

                    let label = e.target.closest('div').querySelector('span').textContent;

                    this.dispatchEvent(new CustomEvent('onTabClick', { detail: { key: key, tab: label } }))

                };

            }

            set onTabClick(fn) {

                this.addEventListener('onTabClick', fn);

            }

            activeByKey(key) {

                if (key === null || key === undefined) return; //如果没有key 不做相应

                this.nav.querySelectorAll('.nav-item').forEach(a => {

                    if (a.getAttribute('data-key') === key) {

                        a.setAttribute('data-selected', 'true');

                    } else {

                        a.removeAttribute('data-selected');

                    }

                })

                let tbp = this.querySelector(`lit-tabpane[key='${key}']`);

                let panes = this.querySelectorAll('lit-tabpane');

                panes.forEach(a => {

                    if (a.key === key) {

                        a.style.display = 'block';

                        this.activekey = a.key;

                        this.initTabPos()

                    } else {

                        a.style.display = 'none';

                    }

                })

            }

            /*激活选中 key 对应的 pane  成功返回true,没有找到key对应的pane 返回false*/

            activePane(key) {

                if (key === null || key === undefined) return false;

                let tbp = this.querySelector(`lit-tabpane[key='${key}']`);

                if (tbp) {

                    this.activeByKey(key)

                    return true;

                } else {

                    return false;

                }

            }

            //当 custom element从文档DOM中删除时,被调用。

            disconnectedCallback() {



            }



            //当 custom element被移动到新的文档时,被调用。

            adoptedCallback() {

                console.log('Custom square element moved to new page.');

            }



            //当 custom element增加、删除、修改自身属性时,被调用。

            attributeChangedCallback(name, oldValue, newValue) {

                if (name === 'activekey' && this.nav && oldValue !== newValue) {

                    this.activeByKey(newValue)

                }

            }

        }

        if (!customElements.get('lit-tabs')) {

            customElements.define('lit-tabs', LitTabs);

        }



        class AppDiffFlame extends HTMLElement {

            draw;

            drawC;

            rowHeight = 17;



            static get observedAttributes() {

                return []

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{

            font-size:inherit;

            display:inline-flex;

            align-items: center;

            justify-content:center;

            height: 100%;

            width: 100%;

            margin-bottom: 40px;

        }

        canvas { border: 1px solid #e9e9e9; }

        #title{

            font-weight: bold;

            height: auto;

        }

        #title span{

            color: gray;

        }

        #funcNameSpan{

            display: inline-block;

            border: 1px solid #e9e9e9;

            box-sizing: border-box;

            border-radius: 2px;

            padding: 2px 8px;

            background: #fff;

             color: gray;

            flex: 3;

            margin-left: 10px;

        }

        #percentSpan{

            display: inline-block;

            border: 1px solid #e9e9e9;

            margin-left: 10px;

            box-sizing: border-box;

            border-radius: 2px;

            padding: 2px 8px;

            background: #fff;

            min-width: 160px;

            max-width: 160px;

            margin-left: 10px;

            width: 100px;

            height: 30px;

            color: gray;

        }

        #diffSpan{

            display: inline-block;

            border: 1px solid #e9e9e9;

            margin-left: 10px;

            box-sizing: border-box;

            border-radius: 2px;

            padding: 2px 8px;

            background: #fff;

            min-width: 160px;

            max-width: 160px;

            margin-left: 10px;

            width: 100px;

            height: 30px;

            color: gray;

        }

        #history{

            display: none;

            border: 1px solid #42b983;

            box-sizing: border-box;

            border-radius: 2px;

            padding: 2px 8px;

            background: #fff;

            width: 100px;

            margin-left: 10px;

            height: 30px;

            cursor: pointer;

            user-select: none;

        }

        #history:hover{

            background: #42b983;

            color: #fff;

        }

        #searchInput{

            height: 30px;

            margin-left: 10px;

            margin-right: 10px;

            flex: 1;

        }

        </style>

        <div style="position: relative;width: 100%">

            <div id="title">Process <span id="pid"></span> <span id="processName"></span> Thread <span id="tid"></span> <span id="threadName"></span><span id="sample"></span></div>

            <canvas id="panel" title=""></canvas>

            <div id="controller" style="position: absolute;top: 32px;display: flex;width: 100%">

                <span id="history">Zoom Out</span>

                <span id="funcNameSpan"></span>

                <span id="diffSpan"></span>

                <span id="percentSpan"></span>

                <lit-input id="searchInput" placeholder="search"  allow-clear>Search</lit-input>

            </div>

        </div>

        <slot></slot>

        `

            }



            connectedCallback() {

                this.history = [];

                this.historyRefer = [];

                this.panel = this.shadowRoot.getElementById('panel');

                this.controller = this.shadowRoot.getElementById('controller');

                this.funcNameSpan = this.shadowRoot.getElementById('funcNameSpan');

                this.percentSpan = this.shadowRoot.getElementById('percentSpan');

                this.diffSpan = this.shadowRoot.getElementById('diffSpan');

                this.historySpan = this.shadowRoot.getElementById('history');

                this.searchInput = this.shadowRoot.getElementById('searchInput');

                this.pid = this.shadowRoot.getElementById('pid');

                this.tid = this.shadowRoot.getElementById('tid');

                this.processName = this.shadowRoot.getElementById('processName');

                this.threadName = this.shadowRoot.getElementById('threadName');

                this.sample = this.shadowRoot.getElementById('sample');

                this.titleDiv = this.shadowRoot.getElementById('title');

                this.context = this.panel.getContext('2d');

                this.panel.width = this.shadowRoot.host.clientWidth;

                this.panel.height = this.shadowRoot.host.clientHeight;

                this.historySpan.onclick = e => {

                    if (this.history.length > 2) {

                        this.history.pop();

                        this.historyRefer.pop();

                        this.zoomOutRefer(this.historyRefer[this.historyRefer.length - 1])

                        this.zoomOut(this.history[this.history.length - 1])

                    } else if (this.history.length == 2) {

                        this.history.pop();

                        this.historyRefer.pop();

                        this.zoomOutRefer(this.historyRefer[this.historyRefer.length - 1])

                        this.zoomOut(this.history[this.history.length - 1])

                        this.historySpan.style.display = 'none';

                    } else {

                        this.historySpan.style.display = 'none';

                    }

                }

                this.searchInput.addEventListener("onPressEnter", (e) => {

                    this.keyword = e.currentTarget.value;

                    requestAnimationFrame(this.draw);

                })

                this.searchInput.addEventListener('onClear', e => {

                    this.keyword = null;

                    requestAnimationFrame(this.draw);

                })

                this.panel.onmouseover = (e) => {

                    this.mouseState = 'mouseOver';

                }

                this.panel.onmouseleave = e => {

                    this.mouseState = 'mouseLeave';

                    this.mouseX = 0;

                    this.mouseY = 0;

                    requestAnimationFrame(this.draw)

                }

                this.panel.onmousemove = e => {

                    const pos = e.currentTarget.getBoundingClientRect();

                    this.mouseX = e.clientX - pos.left;

                    this.mouseY = e.clientY - pos.top;

                    this.mouseState = 'mouseMove';

                    requestAnimationFrame(this.draw)

                }

                this.panel.onmousedown = e => {

                    this.mouseState = 'mouseDown';

                    // const pos = e.currentTarget.getBoundingClientRect();

                    // this.mouseX = e.clientX - pos.left;

                    // this.mouseY = e.clientY - pos.top;

                    // requestAnimationFrame(this.draw)

                }

                this.panel.onmouseup = e => {

                    this.mouseState = 'mouseUp';

                    const pos = e.currentTarget.getBoundingClientRect();

                    this.mouseX = e.clientX - pos.left;

                    this.mouseY = e.clientY - pos.top;

                    requestAnimationFrame(this.draw)

                }

                // this.panel.onclick = (e)=>{

                //     this.mouseState = 'mouseClick';

                // }

            }



            set data(value) {

                this._data = value;

                this._dataRefer = value.jsonRefer;

                /**

                 * type 值默认为1

                 * 1 Show percentage of event count relative to the current thread

                 * 2 Show percentage of event count relative to the current process

                 * 3 Show percentage of event count relative to all process

                 * 4 show event count

                 * 5 show event count in milliseconds

                 * 其他值

                 * pid, processName, tid, threadName, eventCount, sampleCount, CallOrder(g节点)

                 */

                this.type = value.type;

                // reverse 表示火焰图需要是否需要倒序绘制,value中没有传reverse,默认表示false 既正序绘制

                this.reverse = value.reverse || false;

                // CallOrder.symbol 如果为-1 表示为根节点

                if (value.CallOrder.symbol === -1) {

                    this._c = value.CallOrder.callStack;

                    this._cRef = this.threadRefer.CallOrder.callStack;

                } else {

                    this._c = [value.CallOrder];

                    this._cRef = [this.threadRefer.CallOrder];

                }

                // console.log(this.data.json, this.dataRefer)

                // console.log(this.c, this.cRef)

                this.history.push(this._c)

                this.historyRefer.push(this.cRef)

                // 获取选项的 eventCount值 例如:hw-cpu-cycles 和 processes 同层级节点  表示所有进程的eventCount值求和

                this.eventCountAllProcess = this._data.json.recordSampleInfo[window.eventIndex].eventCount

                console.log("diff eventCountAllProcess = " + this.eventCountAllProcess)

                if (value.pid) {

                    // 当前进程的 eventCount值,没有直接送json中去取是因为,第一次传的json 和 windows.data 一样,后续点击了 自节点传入的是子集,可能取的不准确

                    this.eventCountCurrentProcess = this._data.json.recordSampleInfo[window.eventIndex].processes.filter(it => it.pid === value.pid)[0].eventCount

                    console.log("diff eventCountCurrentProcess = " + this.eventCountCurrentProcess)

                    // 将进程号显示在界面上

                    this.pid.textContent = value.pid;

                } else {

                    // this.titleDiv.style.display = 'none';

                }

                if (value.tid) {

                    // 取当前线程的 eventCount 值

                    this.eventCountCurrentThread = this._data.json.recordSampleInfo[window.eventIndex].processes.filter(it => it.pid === value.pid)[0].threads.filter(it => it.tid === value.tid)[0].eventCount;

                    this.eventCountCurrentThreadRefer = this._data.jsonRefer.recordSampleInfo[window.eventIndex].processes.filter(it => it.pid === value.pid)[0].threads.filter(it => it.tid === value.tid)[0].eventCount;

                    console.log("diff eventCountCurrentThread = " + this.eventCountCurrentThread)

                    // 显示线程号

                    this.tid.textContent = value.tid;

                }

                if (value.sampleCount) {

                    //显示sampleCount值 ,这个值在 thread节点里,只有线程有

                    this.sample.textContent = ' (Samples: ' + value.sampleCount + ")";

                }

                if (value.processName) {

                    //显示进程名 null显示空字符串

                    this.processName.textContent = value.processName ? `(${value.processName})` : '';

                }

                if (value.threadName) {

                    //显示线程名 null显示空字符串

                    this.threadName.textContent = value.threadName ? `(${value.threadName})` : '';

                }

                if (value.funcName) {

                    //如果是单独绘制Funtion Tab界面下的火焰图,只有 函数名称, 上面的 的进程线程信息不显示

                    this.titleDiv.innerHTML = `${value.funcName}`

                    this.controller.style.top = `${this.titleDiv.clientHeight + 10}px`

                }

                //获取最大层级,用于做火焰图高度计算,点击子节点后 maxDepth 也对应变化

                this.maxDepth = this.getMaxDepth(this.data.CallOrder.callStack) + 5; //设置最大层级

                this.maxDepthRefer = this.getMaxDepth(this.threadRefer.CallOrder.callStack) + 5; //设置最大层级

                console.log("diff maxDepth = " + this.maxDepth + " maxDepthRefer = " + this.maxDepthRefer)

                this.sumCount = this.data.CallOrder.subEvents; //设置根节点的 sumCount

                this.sumCountRefer = this.threadRefer.CallOrder.subEvents; //设置根节点的 sumCountRefer 用来做对比

                console.log("diff sumCount = " + this.sumCount + " sumCountRefer = " + this.sumCountRefer)

                // console.log(this.threadRefer)//对比的线程数据

                //计算canvas的宽度和高度

                this.panel.height = this.maxDepth * this.rowHeight

                this.panel.width = this.shadowRoot.host.clientWidth

                //设置canvas 的大小

                this.makeHighRes(this.panel);

                //开始调用draw方法绘制一帧

                requestAnimationFrame(this.draw);

            }



            get data() {

                return this._data;

            }



            //需要对比的原始数据

            get dataRefer() {

                return this._dataRefer;

            }



            set dataRefer(val) {

                this._dataRefer = val;

            }



            /*

              获取要对比的 thread数据

             */

            get threadRefer() {

                return this._threadRefer;

            }



            /**

             * 设置要对比的数据 这里传入的是 thread 节点;包含 {tid,eventCount,sampleCount,libs:[],CallOrder:[],CalledOrder:[]}

             * @param val

             */

            set threadRefer(val) {

                this._threadRefer = val;

            }



            /**

             * 点击图形中子节点时 传入 当前节点当作根节点绘制

             * @param value

             */

            set c(value) {

                //显示回退button

                this.historySpan.style.display = 'block';

                //设置相对根节点

                this._c = value;

                //添加历史记录,用于回退到上一图形状态

                this.history.push(this._c)

                // 下面代码实现 canvas 随内容高度变化

                // this.maxDepth = this._getMaxDepth(value) + 5; //设置最大层级

                // this.panel.height = this.maxDepth * this.rowHeight

                // this.panel.width = this.shadowRoot.host.clientWidth;

                // this.makeHighRes(this.panel);

                //开始绘制

                requestAnimationFrame(this.draw);

            }



            get c() {

                return this._c;

            }



            get cRef() {

                return this._cRef

            }



            set cRef(val) {

                this._cRef = val;

                this.historyRefer.push(this._cRef)

            }



            zoomOutRefer(value) {

                this._cRef = value;

            }

            zoomOut(value) {

                this._c = value;

                // 下面代码实现 canvas 随内容高度变化

                // this.maxDepth = this._getMaxDepth(value) + 5; //设置最大层级

                // // this.sumCount = value.reduce((acc, cur) => acc + cur.s, 0); //设置根节点的 sumCount

                // this.panel.height = this.maxDepth * this.rowHeight

                // this.panel.width = this.shadowRoot.host.clientWidth;

                // this.makeHighRes(this.panel);

                requestAnimationFrame(this.draw);

            }



            makeHighRes(canvas) {

                let ctx = canvas.getContext('2d');

                let dpr = window.devicePixelRatio || window.webkitDevicePixelRatio || window.mozDevicePixelRatio || 1;

                let oldWidth = canvas.width;

                let oldHeight = canvas.height;

                canvas.width = Math.round(oldWidth * dpr);

                canvas.height = Math.round(oldHeight * dpr);

                canvas.style.width = oldWidth + 'px';

                canvas.style.height = oldHeight + 'px';

                ctx.scale(dpr, dpr);

                this.context = ctx;

                return ctx;

            }



            //绘制火焰图

            draw = () => {

                // requestAnimationFrame(this.draw);

                let ctx = this.context;

                // ctx.clearRect(0, 0, this.panel.width, this.panel.height);

                //绘制背景渐变色

                let grad = ctx.createLinearGradient(0, 0, 0, this.panel.height / 2); //创建一个渐变色线性对象

                grad.addColorStop(0, "#eeeeee");                  //定义渐变色颜色

                grad.addColorStop(1, "#efefb1");

                ctx.fillStyle = grad;                         //设置fillStyle为当前的渐变对象

                ctx.fillRect(0, 0, this.panel.width, this.panel.height);

                // console.log(this.c,this.cRef);

                if (this.data) {

                    //如果需要倒序绘制调用drawCReverse方法绘制

                    if (this.reverse) {

                        this.drawCReverse(

                            this.c,

                            1,

                            {

                                x: 0,

                                y: this.rowHeight * 4,

                                w: this.panel.clientWidth,

                                h: this.rowHeight

                            });

                    } else {

                        //绘制正序图,需要3个参数  节点数据,当前绘制的层级,当前这行的Rect数据

                        this.drawC(

                            this.c,//根节点

                            this.cRef,

                            1,

                            {

                                x: 0,

                                y: this.panel.clientHeight - this.rowHeight,

                                w: this.panel.clientWidth,

                                h: this.rowHeight

                            });

                    }

                }

            }



            //根据type类型计算 统计数据

            getStatistics(c) {

                let statistics;//鼠标hover展示的百分比

                switch (this.type) {

                    case 1: //current thread

                        statistics = c.subEvents * 100 / this.eventCountCurrentThread;

                        statistics = statistics.toFixed(2)

                        statistics = `${statistics}%`

                        break;

                    case 2: // current process

                        statistics = c.subEvents * 100 / this.eventCountCurrentProcess;

                        statistics = statistics.toFixed(2)

                        statistics = `${statistics}%`

                        break;

                    case 3: // all process

                        statistics = c.subEvents * 100 / this.eventCountAllProcess;

                        statistics = statistics.toFixed(2)

                        statistics = `${statistics}%`

                        break;

                    case 4: //event count

                        statistics = c.subEvents;

                        statistics = `${statistics}`

                        break;

                    case 5: //event count in milliseconds

                        statistics = c.subEvents / 1000000;

                        statistics = statistics.toFixed(3)

                        statistics = `${statistics} ms`

                        break;

                    default: //current thread

                        statistics = c.subEvents * 100 / this.eventCountCurrentThread;

                        statistics = statistics.toFixed(2)

                        statistics = `${statistics}%`

                        break;

                }

                return statistics;

            }



            //HTML反转义

            htmlDecode(text) {

                let temp = document.createElement("div");

                temp.innerHTML = text;

                let output = temp.innerText || temp.textContent;

                temp = null;

                return output;

            }



            //获取方法名

            getFunctionName(f) {

                let funName = "";

                if (this._data.json.SymbolMap[f]) {

                    funName = this._data.json.SymbolMap[f].symbol;

                } else {

                    let f = c[i].symbol;

                    console.log(`processId:${this.pid.textContent} processName:${this.processName.textContent} threadId:${this.tid.textContent} threadName:${this.threadName.textContent}`, c[i], "SymbolMap中没有对应的值")

                }

                return this.htmlDecode(funName);

            }



            //根据比对对象的funId 在比对数组中找到对应的函数名

            getFunctionNameRefer(f) {

                let funName = "";

                if (this.dataRefer.SymbolMap[f]) {

                    funName = this.dataRefer.SymbolMap[f].symbol;

                } else {

                    // let f = c[i].symbol;

                    // console.log(`processId:${this.pid.textContent} processName:${this.processName.textContent} threadId:${this.tid.textContent} threadName:${this.threadName.textContent}`, c[i], "SymbolMap中没有对应的值")

                }

                return this.htmlDecode(funName);

            }



            //根据百分比获取显示的背景色,如果 搜索框中的关键字与当前funcName 匹配则单独显示色值

            getColor(percent2, funName) {

                let heatColor;

                if (this.keyword && this.keyword.length > 0 && funName.indexOf(this.keyword) != -1) {

                    heatColor = { r: 0x66, g: 0xad, b: 0xff };

                } else {

                    heatColor = this.getHeatColor(percent2);

                }

                return heatColor;

            }



            //倒序绘制

            drawCReverse = (c, dept, rect) => {

                let ctx = this.context;

                let offset = 0

                for (let i = 0; i < c.length; i++) {

                    let funName = this.getFunctionName(c[i].symbol);

                    let funcId = c[i].symbol;

                    let percent = c[i].subEvents * 100 / (c.reduce((acc, cur) => acc + cur.subEvents, 0));

                    let percent2 = c[i].subEvents * 100 / this.sumCount;

                    if (percent2 < 0.1) continue //过滤掉 百分比为0.1一下的节点

                    let heatColor = this.getColor(percent2, funName);

                    let w = rect.w * (percent / 100.0);

                    if (w < 1) {

                        w = 1

                    }

                    let _x = rect.x + offset;

                    //绘制填充矩形

                    ctx.fillStyle = `rgba(${heatColor.r}, ${heatColor.g}, ${heatColor.b}, 1)`;

                    ctx.fillRect(_x, rect.y + 2, w, rect.h - 2);

                    // 绘制文本

                    ctx.fillStyle = "rgba(0,0,0,1)";

                    let txtWidth = ctx.measureText(funName).width;//文本长度

                    let chartWidth = txtWidth / funName.length;//每个字符长度

                    let number = (w - 6) / chartWidth;//可以显示多少字符

                    if (number >= 4 && number < funName.length - 3) {

                        ctx.fillText(funName.slice(0, number - 3) + '...', _x + 3, rect.y + 13, w - 6)

                    } else if (number >= 4) {

                        ctx.fillText(funName, _x + 3, rect.y + 13, w - 6)

                    }

                    let _rect = {

                        x: _x, y: rect.y, w: w, h: rect.h

                    }

                    c[i].rect = _rect;



                    if (this.mouseX > _x && this.mouseX < _x + w && this.mouseY > rect.h * 3 + (dept) * rect.h && this.mouseY < rect.h * 3 + (dept + 1) * rect.h) {

                        if (this.mouseState === 'mouseMove') {

                            //绘制边框矩形

                            // ctx.font = '12px serif';

                            ctx.lineWidth = 2;

                            ctx.strokeStyle = `#000000`;

                            ctx.strokeRect(_x, rect.y + 1, w - 1, rect.h);

                            this.funcNameSpan.textContent = funName

                            this.panel.title = funName

                            this.percentSpan.textContent = this.getStatistics(c[i]);

                        } else {

                            if (this.mouseState === 'mouseUp') {

                                this.mouseState = null;

                                if (!this.compareNodes(this.c, [c[i]])) {

                                    this.c = [c[i]];

                                }

                            }

                        }

                    } else {

                        ctx.lineWidth = 1;

                        // ctx.font = '11px serif';

                    }

                    offset += w;

                    // console.log(_rect,dept,percent,funName);

                    //递归绘制子节点

                    if (c[i].callStack && c[i].callStack.length > 0) {

                        _rect.y = _rect.y + _rect.h

                        this.drawCReverse(c[i].callStack, dept + 1, _rect);

                    }

                }

            }



            //正序绘制

            drawC = (c, cRef, dept, rect) => {

                let ctx = this.context;

                let offset = 0//用来保存x坐标的偏移量,保证在rect的矩形范围内从左往右绘制 c集合中的节点

                for (let i = 0; i < c.length; i++) {

                    let funName = this.getFunctionName(c[i].symbol);

                    // console.log(dept,this.data.SymbolMap[c[i].symbol].symbol);

                    let funcId = c[i].symbol;//获取funcId

                    //计算这个节点的subEvents值 在当前传入集合的subEvents总和中占的百分比,因为rect默认是最大宽宽的,递归后最越来越小,根据这个百分比和 rect矩形的宽度计算节点绘制的宽度

                    let percent = c[i].subEvents * 100 / (c.reduce((acc, cur) => acc + cur.subEvents, 0));//sumCount;

                    //计算这个节点的subEvents 在总的sumCount(对应的是最大宽度)中占比,这个百分比用来计算颜色,占比越少颜色越浅

                    let percent2 = c[i].subEvents * 100 / this.sumCount;

                    if (percent2 < 0.1) continue //过滤掉 百分比为0.1一下的节点

                    let heatColor = this.getColor(percent2, funName);

                    let w = rect.w * (percent / 100.0);

                    if (w < 1) {

                        w = 1

                    }

                    let _x = rect.x + offset;

                    //绘制填充矩形

                    ctx.fillStyle = `rgba(${heatColor.r}, ${heatColor.g}, ${heatColor.b}, 1)`;

                    let __rect = { x: _x, y: rect.y + 2, w: w, h: rect.h - 2 }

                    ctx.fillRect(__rect.x, __rect.y, __rect.w, __rect.h);



                    //覆盖要比较的数据 (显示的方法名,显示的矩形对象,宽度的百分比,需要比对节点集合[需要根据funName从中取得要比较的节点])

                    let nodeRefer = this.drawReferData(ctx, funName, __rect, percent, cRef);



                    // 绘制文本

                    ctx.fillStyle = "rgba(0,0,0,1)";

                    let txtWidth = ctx.measureText(funName).width;//文本长度

                    let chartWidth = txtWidth / funName.length;//每个字符长度

                    let number = (w - 6) / chartWidth;//可以显示多少字符

                    if (number >= 4 && number < funName.length - 3) {

                        ctx.fillText(funName.slice(0, number - 3) + '...', _x + 3, rect.y + 13, w - 6)

                    } else if (number >= 4) {

                        ctx.fillText(funName, _x + 3, rect.y + 13, w - 6)

                    }

                    let _rect = {

                        x: _x, y: rect.y, w: w, h: rect.h

                    }

                    c[i].rect = _rect;



                    if (this.mouseX > _x && this.mouseX < _x + w && this.mouseY > (this.maxDepth - dept) * rect.h && this.mouseY < (this.maxDepth - dept + 1) * rect.h) {

                        if (this.mouseState === 'mouseMove') {

                            //绘制边框矩形

                            // ctx.font = '12px serif';

                            ctx.lineWidth = 2;

                            ctx.strokeStyle = `#000000`;

                            ctx.strokeRect(_x, rect.y + 1, w - 1, rect.h);

                            this.funcNameSpan.textContent = funName

                            this.panel.title = funName

                            this.percentSpan.textContent = this.getStatistics(c[i]);

                            let node = this.fetchSameFuncNameData(funName, cRef);

                            var diff = 0.0;

                            if (node) {

                                let percentRefer = node.subEvents * 100 / (cRef.reduce((acc, cur) => acc + cur.subEvents, 0))

                                diff = (percent - percentRefer).toFixed(2)

                            }

                            this.diffSpan.textContent = `diff: ${diff}%`;

                        } else {

                            if (this.mouseState === 'mouseUp') {

                                this.mouseState = null;

                                if (!this.compareNodes(this.c, [c[i]])) {

                                    this.c = [c[i]];

                                    this.cRef = [nodeRefer];

                                }

                            }

                        }

                    } else {

                        ctx.lineWidth = 1;

                        // ctx.font = '11px serif';

                    }

                    offset += w;

                    // console.log(_rect,dept,percent,funName);

                    //递归绘制子节点

                    if (c[i].callStack && c[i].callStack.length > 0) {

                        _rect.y = _rect.y - _rect.h

                        this.drawC(c[i].callStack, nodeRefer ? nodeRefer.callStack : [], dept + 1, _rect);

                    }

                }

            }



            //在对比数组中找到 方法名与 funName相同的节点

            fetchSameFuncNameData(funName, cRef) {

                let node = cRef.filter(it => {

                    let funNameRefer = this.getFunctionNameRefer(it.symbol);

                    return funName === funNameRefer

                })

                // console.log("cRef:",funName,cRef,node)

                if (node && node.length > 0) {

                    return node[0];

                } else {

                    return null;

                }

            }



            //对比数据,如果要比对的数据宽度大于绘制节点宽度 显示红色,否则显示蓝色,颜色深度取决于大多少或者小多少

            drawReferData(ctx, funName, rect, percent, cRef) {

                //根据funName 在cRef集合中找到同函数名的节点

                let node = this.fetchSameFuncNameData(funName, cRef);

                if (node) {

                    let percentRefer = node.subEvents * 100 / (cRef.reduce((acc, cur) => acc + cur.subEvents, 0));//sumCount;

                    // console.log("找到相同节点", funName, rect.w, percent, percentRefer, node)

                    //如果绘制的百分比小于要比较的百分比

                    if (percent < percentRefer) {

                        let offset = Math.abs(percent - percentRefer);

                        if (offset > 0 && offset <= 10) {

                            ctx.fillStyle = `#66B3FF`;

                        } else if (offset > 10 && offset <= 20) {

                            ctx.fillStyle = `#2894FF`;

                        } else if (offset > 20 && offset <= 30) {

                            ctx.fillStyle = `#0072E3`;

                        } else if (offset > 30 && offset <= 50) {

                            ctx.fillStyle = `#0066CC`;

                        } else {

                            ctx.fillStyle = `#005AB5`;

                        }

                        ctx.fillRect(rect.x, rect.y, rect.w, rect.h);

                    } else if (percent > percentRefer) {

                        let offset = Math.abs(percent - percentRefer);

                        if (offset > 0 && offset <= 10) {

                            ctx.fillStyle = `#FF7575`;

                        } else if (offset > 10 && offset <= 20) {

                            ctx.fillStyle = `#FF2D2D`;

                        } else if (offset > 20 && offset <= 30) {

                            ctx.fillStyle = `#EA0000`;

                        } else if (offset > 30 && offset <= 50) {

                            ctx.fillStyle = `#CE0000`;

                        } else {

                            ctx.fillStyle = `#AE0000`;

                        }

                        ctx.fillRect(rect.x, rect.y, rect.w, rect.h);

                    }

                }

                return node;

            }





            compareNode(na, nb) {

                let res = false;

                if (na.selfEvents === nb.selfEvents && na.subEvents === nb.subEvents && na.symbol === nb.symbol) {

                    res = this.compareNodes(na.callStack || [], nb.callStack || []);

                }

                return res;

            }



            compareNodes(a, b) {

                let res = false;

                if (a.length === b.length) {

                    if (a.length === 0) {

                        return true;

                    }

                    for (let i = 0; i < a.length; i++) {

                        res = this.compareNode(a[i], b[i])

                    }

                }

                return res;

            }



            getMaxDepth(nodes) {

                let isArray = Array.isArray(nodes);

                let sumCount;

                if (isArray) {

                    sumCount = nodes.reduce((acc, cur) => acc + cur.subEvents, 0);

                } else {

                    sumCount = nodes.subEvents;

                }

                let width = sumCount * 100.0 / this.sumCount;

                if (width < 0.1) {

                    return 0;

                }

                let children = isArray ? this.splitChildrenForNodes(nodes) : nodes.callStack;

                let childDepth = 0;

                if (children) {

                    for (let child of children) {

                        childDepth = Math.max(childDepth, this.getMaxDepth(child));

                    }

                }

                return childDepth + 1;

            }



            splitChildrenForNodes(nodes) {

                let map = new Map();

                for (let node of nodes) {

                    for (let child of node.callStack) {

                        let subNodes = map.get(child.symbol);

                        if (subNodes) {

                            subNodes.push(child);

                        } else {

                            map.set(child.symbol, [child]);

                        }

                    }

                }

                let res = [];

                for (let subNodes of map.values()) {

                    res.push(subNodes.length == 1 ? subNodes[0] : subNodes);

                }

                return res;

            }



            //根据百分比获取节点的背景色

            getHeatColor(widthPercentage) {

                return {

                    r: Math.floor(245 + 10 * (1 - widthPercentage * 0.01)),

                    g: Math.floor(110 + 105 * (1 - widthPercentage * 0.01)),

                    b: 100,

                };

            }



            attributeChangedCallback(name, oldValue, newValue) {

            }

        }

        if (!customElements.get('app-diff-flame')) {

            customElements.define('app-diff-flame', AppDiffFlame);

        }



        class AppNormalFlame extends HTMLElement {

            draw;

            drawC;

            rowHeight = 17;



            static get observedAttributes() {

                return []

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{

            font-size:inherit;

            display:inline-flex;

            align-items: center;

            justify-content:center;

            height: 100%;

            width: 100%;

            margin-bottom: 40px;

        }

        canvas { border: 1px solid #e9e9e9; }

        #title{

            font-weight: bold;

            height: auto;

        }

        #title span{

            color: gray;

        }

        #funcNameSpan{

            display: inline-block;

            border: 1px solid #e9e9e9;

            box-sizing: border-box;

            border-radius: 2px;

            padding: 2px 8px;

            background: #fff;

             color: gray;

            flex: 3;

            margin-left: 10px;

        }

        #percentSpan{

            display: inline-block;

            border: 1px solid #e9e9e9;

            margin-left: 10px;

            box-sizing: border-box;

            border-radius: 2px;

            padding: 2px 8px;

            background: #fff;

            min-width: 160px;

            max-width: 160px;

            margin-left: 10px;

            width: 100px;

            height: 30px;

            color: gray;

        }

        #history{

            display: none;

            border: 1px solid #42b983;

            box-sizing: border-box;

            border-radius: 2px;

            padding: 2px 8px;

            background: #fff;

            width: 100px;

            margin-left: 10px;

            height: 30px;

            cursor: pointer;

            user-select: none;

        }

        #history:hover{

            background: #42b983;

            color: #fff;

        }

        #searchInput{

            height: 30px;

            margin-left: 10px;

            margin-right: 10px;

            flex: 1;

        }

        </style>

        <div style="position: relative;width: 100%">

            <div id="title">Process <span id="pid"></span> <span id="processName"></span> Thread <span id="tid"></span> <span id="threadName"></span><span id="sample"></span></div>

            <canvas id="panel" title=""></canvas>

            <div id="controller" style="position: absolute;top: 32px;display: flex;width: 100%">

                <span id="history">Zoom Out</span>

                <span id="funcNameSpan"></span>

                <span id="percentSpan"></span>

                <lit-input id="searchInput" placeholder="search"  allow-clear>Search</lit-input>

            </div>

        </div>

        <slot></slot>

        `

            }



            connectedCallback() {

                this.history = [];

                this.panel = this.shadowRoot.getElementById('panel');

                this.controller = this.shadowRoot.getElementById('controller');

                this.funcNameSpan = this.shadowRoot.getElementById('funcNameSpan');

                this.percentSpan = this.shadowRoot.getElementById('percentSpan');

                this.historySpan = this.shadowRoot.getElementById('history');

                this.searchInput = this.shadowRoot.getElementById('searchInput');

                this.pid = this.shadowRoot.getElementById('pid');

                this.tid = this.shadowRoot.getElementById('tid');

                this.processName = this.shadowRoot.getElementById('processName');

                this.threadName = this.shadowRoot.getElementById('threadName');

                this.sample = this.shadowRoot.getElementById('sample');

                this.titleDiv = this.shadowRoot.getElementById('title');

                this.context = this.panel.getContext('2d');

                this.panel.width = this.shadowRoot.host.clientWidth;

                this.panel.height = this.shadowRoot.host.clientHeight;

                this.historySpan.onclick = e => {

                    if (this.history.length > 2) {

                        this.history.pop();

                        this.zoomOut(this.history[this.history.length - 1])

                    } else if (this.history.length == 2) {

                        this.history.pop();

                        this.zoomOut(this.history[this.history.length - 1])

                        this.historySpan.style.display = 'none';

                    } else {

                        this.historySpan.style.display = 'none';

                    }

                }

                this.searchInput.addEventListener("onPressEnter", (e) => {

                    this.keyword = e.currentTarget.value;

                    requestAnimationFrame(this.draw);

                })

                this.searchInput.addEventListener('onClear', e => {

                    this.keyword = null;

                    requestAnimationFrame(this.draw);

                })

                this.panel.onmouseover = (e) => {

                    this.mouseState = 'mouseOver';

                }

                this.panel.onmouseleave = e => {

                    this.mouseState = 'mouseLeave';

                    this.mouseX = 0;

                    this.mouseY = 0;

                    requestAnimationFrame(this.draw)

                }

                this.panel.onmousemove = e => {

                    const pos = e.currentTarget.getBoundingClientRect();

                    this.mouseX = e.clientX - pos.left;

                    this.mouseY = e.clientY - pos.top;

                    this.mouseState = 'mouseMove';

                    requestAnimationFrame(this.draw)

                }

                this.panel.onmousedown = e => {

                    this.mouseState = 'mouseDown';

                    // const pos = e.currentTarget.getBoundingClientRect();

                    // this.mouseX = e.clientX - pos.left;

                    // this.mouseY = e.clientY - pos.top;

                    // requestAnimationFrame(this.draw)

                }

                this.panel.onmouseup = e => {

                    this.mouseState = 'mouseUp';

                    const pos = e.currentTarget.getBoundingClientRect();

                    this.mouseX = e.clientX - pos.left;

                    this.mouseY = e.clientY - pos.top;

                    requestAnimationFrame(this.draw)

                }

                // this.panel.onclick = (e)=>{

                //     this.mouseState = 'mouseClick';

                // }

            }



            set data(value) {

                this._data = value;

                this.type = value.type;

                this.reverse = value.reverse || false;

                if (value.CallOrder.symbol === -1) {

                    this._c = value.CallOrder.callStack;

                } else {

                    this._c = [value.CallOrder];

                }

                this.history.push(this._c)

                this.eventCountAllProcess = value.json.recordSampleInfo[window.eventIndex].eventCount

                if (value.pid) {

                    this.eventCountCurrentProcess = value.json.recordSampleInfo[window.eventIndex].processes.filter(it => it.pid === value.pid)[0].eventCount

                    this.pid.textContent = value.pid;

                } else {

                    // this.titleDiv.style.display = 'none';

                }

                if (value.tid) {

                    this.eventCountCurrentThread = value.json.recordSampleInfo[window.eventIndex].processes.filter(it => it.pid === value.pid)[0].threads.filter(it => it.tid === value.tid)[0].eventCount;

                    this.tid.textContent = value.tid;

                }

                if (value.sampleCount) {

                    this.sample.textContent = ' (Samples: ' + value.sampleCount + ")";

                }

                if (value.processName) {

                    this.processName.textContent = value.processName ? `(${value.processName})` : '';

                }

                if (value.threadName) {

                    this.threadName.textContent = value.threadName ? `(${value.threadName})` : '';

                }

                if (value.funcName) {

                    this.titleDiv.innerHTML = `${value.funcName}`

                    this.controller.style.top = `${this.titleDiv.clientHeight + 10}px`

                }

                this.maxDepth = this.getMaxDepth(this.data.CallOrder.callStack) + 5; //设置最大层级

                this.sumCount = this.data.CallOrder.subEvents; //设置根节点的 sumCount

                this.panel.height = this.maxDepth * this.rowHeight

                this.panel.width = this.shadowRoot.host.clientWidth

                this.makeHighRes(this.panel);

                requestAnimationFrame(this.draw);

            }



            get data() {

                return this._data;

            }



            set c(value) {

                this.historySpan.style.display = 'block';

                this._c = value;

                this.history.push(this._c)

                // 下面代码实现 canvas 随内容高度变化

                // this.maxDepth = this._getMaxDepth(value) + 5; //设置最大层级

                // this.panel.height = this.maxDepth * this.rowHeight

                // this.panel.width = this.shadowRoot.host.clientWidth;

                // this.makeHighRes(this.panel);

                requestAnimationFrame(this.draw);

            }



            get c() {

                return this._c;

            }



            zoomOut(value) {

                this._c = value;

                // 下面代码实现 canvas 随内容高度变化

                // this.maxDepth = this._getMaxDepth(value) + 5; //设置最大层级

                // // this.sumCount = value.reduce((acc, cur) => acc + cur.s, 0); //设置根节点的 sumCount

                // this.panel.height = this.maxDepth * this.rowHeight

                // this.panel.width = this.shadowRoot.host.clientWidth;

                // this.makeHighRes(this.panel);

                requestAnimationFrame(this.draw);

            }



            makeHighRes(canvas) {

                let ctx = canvas.getContext('2d');

                let dpr = window.devicePixelRatio || window.webkitDevicePixelRatio || window.mozDevicePixelRatio || 1;

                let oldWidth = canvas.width;

                let oldHeight = canvas.height;

                canvas.width = Math.round(oldWidth * dpr);

                canvas.height = Math.round(oldHeight * dpr);

                canvas.style.width = oldWidth + 'px';

                canvas.style.height = oldHeight + 'px';

                ctx.scale(dpr, dpr);

                this.context = ctx;

                return ctx;

            }



            draw = () => {

                // requestAnimationFrame(this.draw);

                let ctx = this.context;

                // ctx.clearRect(0, 0, this.panel.width, this.panel.height);

                let grad = ctx.createLinearGradient(0, 0, 0, this.panel.height / 2); //创建一个渐变色线性对象

                grad.addColorStop(0, "#eeeeee");                  //定义渐变色颜色

                grad.addColorStop(1, "#efefb1");

                ctx.fillStyle = grad;                         //设置fillStyle为当前的渐变对象

                ctx.fillRect(0, 0, this.panel.width, this.panel.height);

                if (this.data) {

                    if (this.reverse) {

                        this.drawCReverse(

                            this.c,

                            1,

                            {

                                x: 0,

                                y: this.rowHeight * 4,

                                w: this.panel.clientWidth,

                                h: this.rowHeight

                            });

                    } else {

                        this.drawC(

                            this.c,

                            1,

                            {

                                x: 0,

                                y: this.panel.clientHeight - this.rowHeight,

                                w: this.panel.clientWidth,

                                h: this.rowHeight

                            });

                    }

                }

            }



            getStatistics(c) {

                let statistics;//鼠标hover展示的百分比

                switch (this.type) {

                    case 1: //current thread

                        statistics = c.subEvents * 100 / this.eventCountCurrentThread;

                        statistics = statistics.toFixed(2)

                        statistics = `${statistics}%`

                        break;

                    case 2: // current process

                        statistics = c.subEvents * 100 / this.eventCountCurrentProcess;

                        statistics = statistics.toFixed(2)

                        statistics = `${statistics}%`

                        break;

                    case 3: // all process

                        statistics = c.subEvents * 100 / this.eventCountAllProcess;

                        statistics = statistics.toFixed(2)

                        statistics = `${statistics}%`

                        break;

                    case 4: //event count

                        statistics = c.subEvents;

                        statistics = `${statistics}`

                        break;

                    case 5: //event count in milliseconds

                        statistics = c.subEvents / 1000000;

                        statistics = statistics.toFixed(3)

                        statistics = `${statistics} ms`

                        break;

                    default: //current thread

                        statistics = c.subEvents * 100 / this.eventCountCurrentThread;

                        statistics = statistics.toFixed(2)

                        statistics = `${statistics}%`

                        break;

                }

                return statistics;

            }



            //HTML反转义

            htmlDecode(text) {

                let temp = document.createElement("div");

                temp.innerHTML = text;

                let output = temp.innerText || temp.textContent;

                temp = null;

                return output;

            }



            getFunctionName(f) {

                let funName = "";

                if (this.data.json.SymbolMap[f]) {

                    funName = this.data.json.SymbolMap[f].symbol;

                } else {

                    let f = c[i].symbol;

                    console.log(`processId:${this.pid.textContent} processName:${this.processName.textContent} threadId:${this.tid.textContent} threadName:${this.threadName.textContent}`, c[i], "SymbolMap中没有对应的值")

                }

                return this.htmlDecode(funName);

            }



            getColor(percent2, funName) {

                let heatColor;

                if (this.keyword && this.keyword.length > 0 && funName.indexOf(this.keyword) != -1) {

                    heatColor = { r: 0x66, g: 0xad, b: 0xff };

                } else {

                    heatColor = this.getHeatColor(percent2);

                }

                return heatColor;

            }



            drawCReverse = (c, dept, rect) => {

                let ctx = this.context;

                let offset = 0

                for (let i = 0; i < c.length; i++) {

                    let funName = this.getFunctionName(c[i].symbol);

                    let funcId = c[i].symbol;

                    let percent = c[i].subEvents * 100 / (c.reduce((acc, cur) => acc + cur.subEvents, 0));

                    let percent2 = c[i].subEvents * 100 / this.sumCount;

                    if (percent2 < 0.1) continue //过滤掉 百分比为0.1一下的节点

                    let heatColor = this.getColor(percent2, funName);

                    let w = rect.w * (percent / 100.0);

                    if (w < 1) {

                        w = 1

                    }

                    let _x = rect.x + offset;

                    //绘制填充矩形

                    ctx.fillStyle = `rgba(${heatColor.r}, ${heatColor.g}, ${heatColor.b}, 1)`;

                    ctx.fillRect(_x, rect.y + 2, w, rect.h - 2);

                    // 绘制文本

                    ctx.fillStyle = "rgba(0,0,0,1)";

                    let txtWidth = ctx.measureText(funName).width;//文本长度

                    let chartWidth = txtWidth / funName.length;//每个字符长度

                    let number = (w - 6) / chartWidth;//可以显示多少字符

                    if (number >= 4 && number < funName.length - 3) {

                        ctx.fillText(funName.slice(0, number - 3) + '...', _x + 3, rect.y + 13, w - 6)

                    } else if (number >= 4) {

                        ctx.fillText(funName, _x + 3, rect.y + 13, w - 6)

                    }

                    let _rect = {

                        x: _x, y: rect.y, w: w, h: rect.h

                    }

                    c[i].rect = _rect;



                    if (this.mouseX > _x && this.mouseX < _x + w && this.mouseY > rect.h * 3 + (dept) * rect.h && this.mouseY < rect.h * 3 + (dept + 1) * rect.h) {

                        if (this.mouseState === 'mouseMove') {

                            //绘制边框矩形

                            // ctx.font = '12px serif';

                            ctx.lineWidth = 2;

                            ctx.strokeStyle = `#000000`;

                            ctx.strokeRect(_x, rect.y + 1, w - 1, rect.h);

                            this.funcNameSpan.textContent = funName

                            this.panel.title = funName

                            this.percentSpan.textContent = this.getStatistics(c[i]);

                        } else {

                            if (this.mouseState === 'mouseUp') {

                                this.mouseState = null;

                                if (!this.compareNodes(this.c, [c[i]])) {

                                    this.c = [c[i]];

                                }

                            }

                        }

                    } else {

                        ctx.lineWidth = 1;

                        // ctx.font = '11px serif';

                    }

                    offset += w;

                    // console.log(_rect,dept,percent,funName);

                    //递归绘制子节点

                    if (c[i].callStack && c[i].callStack.length > 0) {

                        _rect.y = _rect.y + _rect.h

                        this.drawCReverse(c[i].callStack, dept + 1, _rect);

                    }

                }

            }

            drawC = (c, dept, rect) => {

                let ctx = this.context;

                let offset = 0

                for (let i = 0; i < c.length; i++) {

                    let funName = this.getFunctionName(c[i].symbol);

                    // console.log(dept,this.data.SymbolMap[c[i].symbol].symbol);

                    let funcId = c[i].symbol;

                    let percent = c[i].subEvents * 100 / (c.reduce((acc, cur) => acc + cur.subEvents, 0));//sumCount;

                    let percent2 = c[i].subEvents * 100 / this.sumCount;

                    if (percent2 < 0.1) continue //过滤掉 百分比为0.1一下的节点

                    let heatColor = this.getColor(percent2, funName);

                    let w = rect.w * (percent / 100.0);

                    if (w < 1) {

                        w = 1

                    }

                    let _x = rect.x + offset;

                    //绘制填充矩形

                    ctx.fillStyle = `rgba(${heatColor.r}, ${heatColor.g}, ${heatColor.b}, 1)`;

                    ctx.fillRect(_x, rect.y + 2, w, rect.h - 2);

                    // 绘制文本

                    ctx.fillStyle = "rgba(0,0,0,1)";

                    let txtWidth = ctx.measureText(funName).width;//文本长度

                    let chartWidth = txtWidth / funName.length;//每个字符长度

                    let number = (w - 6) / chartWidth;//可以显示多少字符

                    if (number >= 4 && number < funName.length - 3) {

                        ctx.fillText(funName.slice(0, number - 3) + '...', _x + 3, rect.y + 13, w - 6)

                    } else if (number >= 4) {

                        ctx.fillText(funName, _x + 3, rect.y + 13, w - 6)

                    }

                    let _rect = {

                        x: _x, y: rect.y, w: w, h: rect.h

                    }

                    c[i].rect = _rect;



                    if (this.mouseX > _x && this.mouseX < _x + w && this.mouseY > (this.maxDepth - dept) * rect.h && this.mouseY < (this.maxDepth - dept + 1) * rect.h) {

                        if (this.mouseState === 'mouseMove') {

                            //绘制边框矩形

                            // ctx.font = '12px serif';

                            ctx.lineWidth = 2;

                            ctx.strokeStyle = `#000000`;

                            ctx.strokeRect(_x, rect.y + 1, w - 1, rect.h);

                            this.funcNameSpan.textContent = funName

                            this.panel.title = funName

                            this.percentSpan.textContent = this.getStatistics(c[i]);

                        } else {

                            if (this.mouseState === 'mouseUp') {

                                this.mouseState = null;

                                if (!this.compareNodes(this.c, [c[i]])) {

                                    this.c = [c[i]];

                                }

                            }

                        }

                    } else {

                        ctx.lineWidth = 1;

                        // ctx.font = '11px serif';

                    }

                    offset += w;

                    // console.log(_rect,dept,percent,funName);

                    //递归绘制子节点

                    if (c[i].callStack && c[i].callStack.length > 0) {

                        _rect.y = _rect.y - _rect.h

                        this.drawC(c[i].callStack, dept + 1, _rect);

                    }

                }

            }



            compareNode(na, nb) {

                let res = false;

                if (na.selfEvents === nb.selfEvents && na.subEvents === nb.subEvents && na.symbol === nb.symbol) {

                    res = this.compareNodes(na.callStack || [], nb.callStack || []);

                }

                return res;

            }



            compareNodes(a, b) {

                let res = false;

                if (a.length === b.length) {

                    if (a.length === 0) {

                        return true;

                    }

                    for (let i = 0; i < a.length; i++) {

                        res = this.compareNode(a[i], b[i])

                    }

                }

                return res;

            }



            getMaxDepth(nodes) {

                let isArray = Array.isArray(nodes);

                let sumCount;

                if (isArray) {

                    sumCount = nodes.reduce((acc, cur) => acc + cur.subEvents, 0);

                } else {

                    sumCount = nodes.subEvents;

                }

                let width = sumCount * 100.0 / this.sumCount;

                if (width < 0.1) {

                    return 0;

                }

                let children = isArray ? this.splitChildrenForNodes(nodes) : nodes.callStack;

                let childDepth = 0;

                if (children) {

                    for (let child of children) {

                        childDepth = Math.max(childDepth, this.getMaxDepth(child));

                    }

                }

                return childDepth + 1;

            }



            splitChildrenForNodes(nodes) {

                let map = new Map();

                for (let node of nodes) {

                    for (let child of node.callStack) {

                        let subNodes = map.get(child.symbol);

                        if (subNodes) {

                            subNodes.push(child);

                        } else {

                            map.set(child.symbol, [child]);

                        }

                    }

                }

                let res = [];

                for (let subNodes of map.values()) {

                    res.push(subNodes.length == 1 ? subNodes[0] : subNodes);

                }

                return res;

            }



            getHeatColor(widthPercentage) {

                return {

                    r: Math.floor(245 + 10 * (1 - widthPercentage * 0.01)),

                    g: Math.floor(110 + 105 * (1 - widthPercentage * 0.01)),

                    b: 100,

                };

            }



            attributeChangedCallback(name, oldValue, newValue) {

            }

        }

        if (!customElements.get('app-normal-flame')) {

            customElements.define('app-normal-flame', AppNormalFlame);

        }



        class AppFlameGraph extends HTMLElement {

            static get observedAttributes() {

                return ['color', 'size']

            }



            constructor() {

                super();

                const shadowRoot = this.attachShadow({ mode: 'open' });

                shadowRoot.innerHTML = `

        <style>

        :host{

            font-size:inherit;

            display:inline-flex;

            align-items: center;

            justify-content:center;

            width: 100%;

        }

        </style>

        <div style="width: 100%;display: flex;flex-direction: column">

            <lit-select id="typeSelect" default-value="1" mode="single" style="width:40vw;margin-bottom: 10px;align-self: flex-end">

                    <lit-select-option value="1">Show percentage of event count relative to the current thread</lit-select-option>

                    <lit-select-option value="2">Show percentage of event count relative to the current process</lit-select-option>

                    <lit-select-option value="3">Show percentage of event count relative to all process</lit-select-option>

                    <lit-select-option value="4">show event count</lit-select-option>

                    <lit-select-option value="5">show event count in milliseconds</lit-select-option>

            </lit-select>

            <div id="panel" style="width: 100%"></div>

        </div>

        <slot></slot>

        `

            }



            get dataRefer() {

                return this._dataRefer;

            }



            //设置比对的数据,【这里是json文件中加载的数据 需要从 recordSampleInfo[index] 取进程集合 线程集合】

            set dataRefer(val) {

                this._dataRefer = val;

            }



            get data() {

                return this._json || null;

            }



            set data(json) {

                //如果已经给过值,不重新刷新

                if (this.isFinished) {

                    return;

                }

                this._json = json;

                this.panel = this.shadowRoot.getElementById('panel');

                this.panel.innerHTML = '';

                let processes = json.recordSampleInfo[window.eventIndex].processes;

                let processesRefer;

                if (this.dataRefer) {

                    processesRefer = this.dataRefer.recordSampleInfo[window.eventIndex].processes;

                }

                processes.slice(0).forEach(it => {

                    let itRefer

                    if (processesRefer) {

                        itRefer = processesRefer.find(element => element.pid == it.pid);//找到要比较的进程

                    }

                    //slice(0,1) 控制只绘制一个线程数据,用作测试

                    it.threads.slice(0).forEach(th => {

                        let pid = it.pid;

                        let processName = json.processNameMap[it.pid];

                        let tid = th.tid;

                        let threadName = json.threadNameMap[th.tid];

                        let eventCount = th.eventCount;

                        let sampleCount = th.sampleCount;

                        let g = th.CallOrder;

                        if (this.dataRefer) {

                            console.log("create diff")

                            let thRefer;

                            if (itRefer) {

                                thRefer = itRefer.threads.find(e => e.tid == th.tid);//找到要比较的线程

                            }

                            let chart = document.createElement('app-diff-flame');

                            chart.style.width = '100%'

                            chart.style.height = 'auto';

                            chart.style.display = 'flex'

                            this.panel.appendChild(chart);

                            chart.threadRefer = thRefer;//注意 app-flame-graph中的dataRefer中保存的是加载的json完整数据集,app-chart-flame中的dataRefer缓存的是对比的线程数据

                            chart.data = {

                                json: json,//显示的json数据集【直接从json文件读取的完整json结构】

                                jsonRefer: this.dataRefer,//需要把完整的对比数据也传入过去,因为只传入thread对比数据需要 完整数据中的eventCount去计算百分比,计算宽度,然后对比原始宽度多还是少

                                type: this.type || 1,

                                pid, processName, tid, threadName, eventCount, sampleCount, CallOrder: g

                            }

                        } else {

                            console.log("create normal")

                            let chart = document.createElement('app-normal-flame');

                            chart.style.width = '100%'

                            chart.style.height = 'auto';

                            chart.style.display = 'flex'

                            this.panel.appendChild(chart);

                            chart.data = {

                                json: json,

                                type: this.type || 1,

                                pid, processName, tid, threadName, eventCount, sampleCount, CallOrder: g

                            }

                        }

                        // console.log(pid,processName,tid,threadName,sampleCount,g);

                    })

                })

                this.isFinished = true;

            }



            connectedCallback() {

                this.isFinished = false;

                this.panel = this.shadowRoot.getElementById('panel');

                this.typeSelect = this.shadowRoot.getElementById('typeSelect');

                this.typeSelect.onchange = ev => {

                    this.type = parseInt(ev.detail.value);

                    this.isFinished = false;

                    this.data = this.data; //切换分类后刷新

                }

            }



            attributeChangedCallback(name, oldValue, newValue) {

                if (name == 'color' && this.loading) {

                    this.loading.style.color = newValue;

                }

                if (name == 'size' && this.loading) {

                    this.loading.style.fontSize = newValue + 'px';

                }

            }

        }

        if (!customElements.get('app-flame-graph')) {

            customElements.define('app-flame-graph', AppFlameGraph);

        }



        (function (values) {



            function createPromise(callback) {

                if (callback) {

                    return new Promise((resolve, _) => callback(resolve));

                }

                return new Promise((resolve, _) => resolve());

            }



            function initGlobalObjects1() {

                let recordData = document.querySelector('#record_data_diff_1').textContent;

                if (recordData.trim().length > 0) {

                    return new Promise((resolve, reject) => {

                        resolve(JSON.parse(recordData));

                    })

                } else {

                    return fetch('data-diff-1.json').then(response => response.json())

                }

            }

            function initGlobalObjects2() {

                let recordData = document.querySelector('#record_data_diff_2').textContent;

                if (recordData.trim().length > 0) {

                    return new Promise((resolve, reject) => {

                        resolve(JSON.parse(recordData));

                    })

                } else {

                    return fetch('data-diff-2.json').then(response => response.json())

                }

            }



            function waitDocumentReady() {

                return createPromise((resolve) => document.addEventListener("DOMContentLoaded", resolve));

            }



            createPromise()

                .then(waitDocumentReady)

                .then(() => Promise.all([initGlobalObjects1(), initGlobalObjects2()]))

                .then((array) => {

                    let j1 = array[0]

                    let j2 = array[1]

                    // window.data = j1; // 没有用到function 模块 不用保存

                    let eventSelector1 = document.querySelector('#events1')

                    let changeBaseBt = document.querySelector('#changeBaseBt')

                    if (j1.recordSampleInfo && j1.recordSampleInfo.length > 0) {

                        let events = [];

                        j1.recordSampleInfo.forEach((e, index) => {

                            events.push({ key: index + '', val: e.eventConfigName })

                        })

                        eventSelector1.dataSource = events;

                        window.eventIndex = 0;

                    }

                    let loading = document.querySelector('#loading');

                    let tabs = document.querySelector('#tabs')

                    let diffFlame = document.querySelector('#diff-flame');

                    let flame1 = document.querySelector('#flame-1');

                    let flame2 = document.querySelector('#flame-2');

                    let legend1 = document.querySelector('#legend-1');

                    let legend2 = document.querySelector('#legend-2');

                    tabs.onTabClick = (e) => {

                        if (e.detail.key == 1) {

                            diffFlame.isFinished = false;

                            diffFlame.dataRefer = window.isReserved ? j1 : j2; //对换显示数据和对比数据

                            diffFlame.data = window.isReserved ? j2 : j1;//将 对比的数据当作显示数据

                        } else if (e.detail.key == 2) {

                            flame1.isFinished = false;

                            flame1.data = j1;

                        } else {

                            flame2.isFinished = false;

                            flame2.data = j2;

                        }

                    }

                    //火焰图

                    window.isReserved = false; //定义变量。表示是否反转基本画图数据,默认为false ,表示以 data-diff-1.json 数据图形数据,data-diff-2.json 为比较数据

                    diffFlame.isFinished = false;

                    diffFlame.dataRefer = j2; //设置需要对比的数据集,flame.data赋值会引起绘制,所以这行要先设置对比数据

                    diffFlame.data = j1;//要绘制火焰图需要显示的数据

                    eventSelector1.addEventListener('change', (e) => {

                        loading.style.display = 'flex'

                        window.eventIndex = parseInt(e.detail.value);//改变界面最上面的select 缓存的index刷新 绘制的数据需要这个index去总数据中取

                        diffFlame.isFinished = false;

                        diffFlame.dataRefer = j2;

                        diffFlame.data = j1;//这里触发了界面更新

                        flame1.isFinished = false;

                        flame1.data = j1;

                        flame2.isFinished = false;

                        flame2.data = j2;

                        loading.style.display = 'none'

                    })

                    changeBaseBt.addEventListener('click', (e) => {

                        window.isReserved = !window.isReserved

                        changeBaseBt.setAttribute('enable', 'false');

                        loading.style.display = 'flex'

                        legend1.textContent = window.isReserved ? "diff-data-2" : "diff-data-1";

                        legend2.textContent = window.isReserved ? "diff-data-1" : "diff-data-2";

                        diffFlame.isFinished = false;

                        diffFlame.dataRefer = window.isReserved ? j1 : j2; //对换显示数据和对比数据

                        diffFlame.data = window.isReserved ? j2 : j1;//将 对比的数据当作显示数据

                        loading.style.display = 'none'

                        changeBaseBt.setAttribute('enable', 'true');

                    })

                })

        }())

    </script>

    <div style="width: 100%;height: 100%">

        <div style="width: 100%;display: flex;flex-direction: column;align-items: center">

            <lit-loading id="loading" size="32" style="display: none"></lit-loading>

        </div>

        <div style="display: flex;flex-direction: row;align-items: center;padding: 15px;justify-content: space-between">

            <div>

                <span style="font-weight: bold;margin-right: 10px">Event Type :</span>

                <lit-select id="events1" default-value="0" style="width: 400px"></lit-select>

            </div>

        </div>

        <lit-tabs id='tabs' position="top-left" activekey="1" mode="flat">

            <lit-tabpane id="pane1" tab="diff-flame" key="1">

                <div style="display: flex;flex-direction: row;align-items: center;justify-content: space-between">

                    <div style="display: flex;flex-direction: row;align-items: center">

                        <div style="display: flex;flex-direction: row;align-items: center">

                            <span>图形数据: </span>

                            <span id="legend-1">data-diff-1</span>

                        </div>

                        <div style="display: flex;flex-direction: row;margin-left: 20px;align-items: center">

                            <span>比较数据: </span>

                            <span id="legend-2">data-diff-2</span>

                        </div>

                        <div id="changeBaseBt" style="background-color: coral;color: white;margin-left: 40px;

                padding: 7px 15px 7px 15px;border-radius: 5px;cursor: pointer">change</div>

                    </div>

                    <div style="display: flex;flex-direction: row;align-items: center">

                        <div style="display: flex;flex-direction: row;align-items: center">

                            <span style="width: 10px;height: 10px;background-color:#2894FF;margin-right: 10px"></span>

                            <span>函数执行时间相比小于(颜色越深则差值越大)</span>

                        </div>

                        <div style="display: flex;flex-direction: row;align-items: center;margin-left: 30px">

                            <span style="width: 10px;height: 10px;background-color:#FF2D2D;margin-right: 10px"></span>

                            <span>函数执行时间相比大于(颜色越深则差值越大)</span>

                        </div>

                    </div>

                </div>

                <div style="padding: 20px">

                    <app-flame-graph id="diff-flame"></app-flame-graph>

                </div>

            </lit-tabpane>

            <lit-tabpane id="pane2" tab="data-1-flame" key="2">

                <app-flame-graph id="flame-1"></app-flame-graph>

            </lit-tabpane>

            <lit-tabpane id="pane3" tab="data-2-flame" key="3">

                <app-flame-graph id="flame-2"></app-flame-graph>

            </lit-tabpane>

        </lit-tabs>

    </div>