• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { LitTableColumn } from './lit-table-column';
17import { LitProgressBar } from './../progress-bar/LitProgressBar';
18import { element } from '../BaseElement';
19import '../utils/Template';
20import { TableRowObject } from './TableRowObject';
21import { ExcelFormater } from '../utils/ExcelFormater';
22import { LitIcon } from '../icon/LitIcon';
23import { NodeType } from '../../js-heap/model/DatabaseStruct';
24import { ConstructorType } from '../../js-heap/model/UiStruct';
25import { JsCpuProfilerStatisticsStruct } from '../../trace/bean/JsStruct';
26import {
27  iconPadding,
28  iconWidth,
29  createDownUpSvg,
30  litTableHtml,
31  exportData,
32  formatExportData,
33  recursionExportTableData,
34  addCopyEventListener,
35  addSelectAllBox,
36  fixed,
37  formatName,
38} from './LitTableHtml';
39
40@element('lit-table')
41export class LitTable extends HTMLElement {
42  meauseRowElement: HTMLDivElement | undefined;
43  currentRecycleList: HTMLDivElement[] = [];
44  currentTreeDivList: HTMLDivElement[] = [];
45  public rememberScrollTop = false;
46  public getItemTextColor?: (data: unknown) => string;
47  public itemTextHandleMap: Map<string, (value: unknown) => string> = new Map<string, (value: unknown) => string>();
48  public exportTextHandleMap: Map<string, (value: unknown) => string> = new Map<string, (value: unknown) => string>();
49  public ds: Array<unknown> = [];
50  public recycleDs: Array<unknown> = [];
51  public gridTemplateColumns: Array<string> = [];
52  public tableColumns: NodeListOf<LitTableColumn> | undefined;
53  public treeElement: HTMLDivElement | undefined | null;
54  public columns: Array<Element> | null | undefined;
55  public exportLoading: boolean = false;
56  public exportProgress: LitProgressBar | null | undefined;
57  public tableElement: HTMLDivElement | null | undefined;
58  private normalDs: Array<unknown> = [];
59  /*Grid css layout descriptions are obtained according to the clustern[] nested structure*/
60  private st: HTMLSlotElement | null | undefined;
61  private theadElement: HTMLDivElement | null | undefined;
62  private tbodyElement: HTMLDivElement | undefined | null;
63  private colCount: number = 0;
64  private isRecycleList: boolean = true;
65  private isScrollXOutSide: boolean = false;
66  private value: Array<unknown> = [];
67  private _mode = TableMode.Expand;
68  private columnResizeEnable: boolean = true;
69  private _isSearch: boolean = false;
70  private maxLength: number = 0;
71
72  constructor() {
73    super();
74    const shadowRoot = this.attachShadow({ mode: 'open' });
75    shadowRoot.innerHTML = litTableHtml;
76  }
77
78  static get observedAttributes(): string[] {
79    return [
80      'scroll-y',
81      'selectable',
82      'no-head',
83      'grid-line',
84      'defaultOrderColumn',
85      'hideDownload',
86      'noRecycle',
87      'loading',
88      'expand',
89    ];
90  }
91
92  get slotArr(): Array<Element> {
93    return this.st!.assignedElements();
94  }
95
96  set mode(mode: TableMode) {
97    this._mode = mode;
98  }
99
100  set loading(value: boolean) {
101    this.exportProgress && (this.exportProgress.loading = value);
102  }
103
104  get hideDownload(): boolean {
105    return this.hasAttribute('hideDownload');
106  }
107
108  set hideDownload(value) {
109    if (value) {
110      this.setAttribute('hideDownload', '');
111    } else {
112      this.removeAttribute('hideDownload');
113    }
114  }
115
116  get selectable(): boolean {
117    return this.hasAttribute('selectable');
118  }
119
120  set selectable(value) {
121    if (value) {
122      this.setAttribute('selectable', '');
123    } else {
124      this.removeAttribute('selectable');
125    }
126  }
127
128  get scrollY(): string {
129    return this.getAttribute('scroll-y') || 'auto';
130  }
131
132  set scrollY(value) {
133    this.setAttribute('scroll-y', value);
134  }
135
136  get dataSource(): unknown[] {
137    return this.ds || [];
138  }
139
140  set dataSource(value) {
141    if (this.hasAttribute('noRecycle')) {
142      this.ds = value;
143      this.isRecycleList = false;
144      this.renderTable();
145    } else {
146      this.columnResizeEnable = false;
147      this.recycleDataSource = value;
148    }
149  }
150
151  set noRecycle(value) {
152    if (value) {
153      this.setAttribute('noRecycle', '');
154    } else {
155      this.removeAttribute('noRecycle');
156    }
157  }
158
159  get noRecycle(): boolean {
160    return this.hasAttribute('noRecycle');
161  }
162
163  get recycleDataSource(): unknown[] {
164    return this.ds || [];
165  }
166
167  set isSearch(value: boolean) {
168    this._isSearch = value;
169  }
170
171  set recycleDataSource(value) {
172    // 处理数据按小数点位置对齐
173    if (value && value.length) {
174      // 找出数字部分的最大长度
175      value.forEach((item: unknown) => {
176        // 提取数字部分(包括小数点)
177        // @ts-ignore
178        if (item.durFormat) {
179          // @ts-ignore
180          const match = item.durFormat.match(/^(\d+(\.\d+)?)/);
181          if (match && match[1]) {
182            // 计算长度(包括小数点)
183            const length = match[1].length;
184            this.maxLength = Math.max(this.maxLength, length);
185          }
186        }
187        // @ts-ignore
188        if (item.percent) {
189          // @ts-ignore
190          const match = String(item.percent).match(/^(\d+(\.\d+)?)/);
191          if (match && match[1]) {
192            const length = match[1].length;
193            this.maxLength = Math.max(this.maxLength, length);
194          }
195        }
196      });
197    }
198    if (this.tableElement) {
199      this.isScrollXOutSide = this.tableElement!.scrollWidth > this.tableElement!.clientWidth;
200      this.isRecycleList = true;
201      this.ds = value;
202      if (this.rememberScrollTop) {
203        this.tableElement!.scrollTop = 0;
204        this.tableElement!.scrollLeft = 0;
205      } else {
206        this.tableElement!.scrollTop = 0;
207      }
208      if (this.hasAttribute('tree') && this.querySelector('lit-table-column')?.hasAttribute('retract')) {
209        if ((value.length === 0 || this.value.length !== 0) && value !== this.value && !this._isSearch) {
210          if (this.shadowRoot!.querySelector<LitIcon>('.top')) {
211            this.shadowRoot!.querySelector<LitIcon>('.top')!.name = 'up';
212          }
213          if (this.shadowRoot!.querySelector<LitIcon>('.bottom')) {
214            this.shadowRoot!.querySelector<LitIcon>('.bottom')!.name = 'down';
215          }
216        }
217        this.value = value;
218        this._isSearch = false;
219        this.recycleDs = this.meauseTreeRowElement(value, RedrawTreeForm.Retract);
220      } else {
221        this.recycleDs = this.meauseAllRowHeight(value);
222      }
223    }
224  }
225
226  get snapshotDataSource(): unknown[] {
227    return this.ds || [];
228  }
229
230  set snapshotDataSource(value) {
231    this.ds = value;
232    if (this.hasAttribute('tree')) {
233      this.recycleDs = this.meauseTreeRowElement(value, RedrawTreeForm.Default);
234    } else {
235      this.recycleDs = this.meauseAllRowHeight(value);
236    }
237  }
238
239  move1px(): void {
240    this.tableElement!.scrollTop = this.tableElement!.scrollTop + 1;
241  }
242
243  dataExportInit(): void {
244    let exportDiv = this.shadowRoot!.querySelector<HTMLDivElement>('.export');
245    exportDiv &&
246      (exportDiv.onclick = (): void => {
247        this.exportData();
248      });
249  }
250
251  exportData(): void {
252    exportData(this);
253  }
254
255  exportExcelData(): void {
256    let now = Date.now();
257    ExcelFormater.testExport(
258      [
259        {
260          columns: this.columns as unknown[],
261          tables: this.ds,
262          sheetName: `${now}`,
263        },
264      ],
265      `${now}`
266    );
267  }
268
269  formatExportData(dataSource: unknown[]): unknown[] {
270    return formatExportData(dataSource, this);
271  }
272
273  formatExportCsvData(dataSource: unknown[]): string {
274    if (dataSource === undefined || dataSource.length === 0) {
275      return '';
276    }
277    if (this.columns === undefined) {
278      return '';
279    }
280    let str = '';
281    str += this.columns!.map((column) => {
282      let dataIndex = column.getAttribute('data-index');
283      let columnName = column.getAttribute('title');
284      if (columnName === '') {
285        columnName = dataIndex;
286      }
287      return columnName;
288    }).join(',');
289    str += recursionExportTableData(this.columns || [], dataSource);
290    return str;
291  }
292
293  injectColumns(): void {
294    this.columns = this.st!.assignedElements();
295    this.columns.forEach((column) => {
296      if (column.tagName === 'LIT-TABLE-COLUMN') {
297        this.gridTemplateColumns.push(column.getAttribute('width') || '1fr');
298      }
299    });
300  }
301  /**
302   * 设置表格每条数据的展开/收起状态
303   * @param list 表格数据
304   * @param status 展开/收起状态
305   * @param depth 展开深度,用来实现和图标的联动
306   * @param profundity 展开深度,用来实现逐级展开
307   */
308  public setStatus(list: unknown, status: boolean, depth: number = 0, profundity?: number): void {
309    this.tableElement!.scrollTop = 0;
310    // 添加depth参数,让切换图标的代码在递归中只走一遍
311    if (depth === 0) {
312      if (status) {
313        this.shadowRoot!.querySelector<LitIcon>('.top')!.name = 'down';
314        this.shadowRoot!.querySelector<LitIcon>('.bottom')!.name = 'up';
315      } else {
316        this.shadowRoot!.querySelector<LitIcon>('.top')!.name = 'up';
317        this.shadowRoot!.querySelector<LitIcon>('.bottom')!.name = 'down';
318      }
319    } // @ts-ignore
320    for (let item of list) {
321      if (profundity) {
322        if (depth < profundity) {
323          item.status = true;
324          status = true;
325        } else {
326          item.status = false;
327          status = false;
328        }
329      } else {
330        item.status = status;
331      }
332      if (item.children !== undefined && item.children.length > 0) {
333        this.setStatus(item.children, status, depth + 1, profundity);
334      }
335    }
336  }
337
338  //当 custom element首次被插入文档DOM时,被调用。
339  connectedCallback(): void {
340    this.st = this.shadowRoot?.querySelector('#slot');
341    this.tableElement = this.shadowRoot?.querySelector('.table');
342    this.exportProgress = this.shadowRoot?.querySelector('#export_progress_bar');
343    this.theadElement = this.shadowRoot?.querySelector('.thead');
344    this.treeElement = this.shadowRoot?.querySelector('.tree');
345    this.tbodyElement = this.shadowRoot?.querySelector('.body');
346    this.tableColumns = this.querySelectorAll<LitTableColumn>('lit-table-column');
347    this.colCount = this.tableColumns!.length;
348    this.dataExportInit();
349    addCopyEventListener(this);
350    this.st?.addEventListener('slotchange', () => {
351      this.theadElement!.innerHTML = '';
352      setTimeout(() => {
353        this.columns = this.st!.assignedElements();
354        let rowElement = document.createElement('div');
355        rowElement.classList.add('th');
356        addSelectAllBox(rowElement, this);
357        let area: Array<unknown> = [];
358        this.gridTemplateColumns = [];
359        this.resolvingArea(this.columns, 0, 0, area, rowElement);
360        area.forEach((rows, j, array) => {
361          for (let i = 0; i < this.colCount; i++) {
362            // @ts-ignore
363            if (!rows[i]) {
364              // @ts-ignore
365              rows[i] = array[j - 1][i];
366            }
367          }
368        });
369        if (this.selectable) {
370          // @ts-ignore
371          let s = area.map((a) => '"_checkbox_ ' + a.map((aa: unknown) => aa.t).join(' ') + '"').join(' ');
372          rowElement.style.gridTemplateColumns = '60px ' + this.gridTemplateColumns.join(' ');
373          rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)`;
374          rowElement.style.gridTemplateAreas = s;
375        } else {
376          // @ts-ignore
377          let s = area.map((a) => '"' + a.map((aa: unknown) => aa.t).join(' ') + '"').join(' ');
378          rowElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' ');
379          rowElement.style.gridTemplateRows = `repeat(${area.length},1fr)`;
380          rowElement.style.gridTemplateAreas = s;
381        }
382        this.theadElement!.innerHTML = '';
383        this.theadElement!.append(rowElement);
384      });
385    });
386    this.shadowRoot!.addEventListener('load', function (event) { });
387    this.tableElement!.addEventListener('mouseout', (ev) => this.mouseOut());
388    this.treeElement && (this.treeElement!.style.transform = 'translateY(0px)');
389    this.tbodyElement && (this.tbodyElement!.style.transform = 'translateY(0px)');
390  }
391
392  resolvingArea(columns: unknown, x: unknown, y: unknown, area: Array<unknown>, rowElement: HTMLDivElement): void {
393    // @ts-ignore
394    columns.forEach((a: unknown, i: unknown) => {
395      // @ts-ignore
396      if (!area[y]) {
397        // @ts-ignore
398        area[y] = [];
399      } // @ts-ignore
400      let key = a.getAttribute('key') || a.getAttribute('title'); // @ts-ignore
401      if (a.tagName === 'LIT-TABLE-GROUP') {
402        // @ts-ignore
403        let len = a.querySelectorAll('lit-table-column').length; // @ts-ignore
404        let children = [...a.children].filter((a) => a.tagName !== 'TEMPLATE');
405        if (children.length > 0) {
406          // @ts-ignore
407          this.resolvingArea(children, x, y + 1, area, rowElement);
408        }
409        for (let j = 0; j < len; j++) {
410          // @ts-ignore
411          area[y][x] = { x, y, t: key }; // @ts-ignore
412          x++;
413        }
414        let h = document.createElement('div');
415        h.classList.add('td'); // @ts-ignore
416        h.style.justifyContent = a.getAttribute('align');
417        h.style.borderBottom = '1px solid #f0f0f0';
418        h.style.gridArea = key; // @ts-ignore
419        h.innerText = a.title; // @ts-ignore
420        if (a.hasAttribute('fixed')) {
421          // @ts-ignore
422          fixed(h, a.getAttribute('fixed'), '#42b983');
423        }
424        rowElement.append(h); // @ts-ignore
425      } else if (a.tagName === 'LIT-TABLE-COLUMN') {
426        // @ts-ignore
427        area[y][x] = { x, y, t: key }; // @ts-ignore
428        x++; // @ts-ignore
429        let head = this.resolvingAreaColumn(rowElement, a, i, key); // @ts-ignore
430        this.gridTemplateColumns.push(a.getAttribute('width') || '1fr'); // @ts-ignore
431        let labelArr = a.title.split('/');
432        for (let i = 0; i < labelArr.length; i++) {
433          let titleLabel = document.createElement('label');
434          titleLabel.style.cursor = 'pointer';
435          i === 0 ? (titleLabel.textContent = labelArr[i]) : (titleLabel.textContent = '/' + labelArr[i]);
436          head.appendChild(titleLabel);
437        } // @ts-ignore
438        if (a.hasAttribute('fixed')) {
439          // @ts-ignore
440          fixed(head, a.getAttribute('fixed'), '#42b983');
441        }
442        rowElement.append(head);
443      }
444    });
445  }
446
447  resolvingAreaColumn(rowElement: HTMLDivElement, column: unknown, index: number, key: string): HTMLDivElement {
448    let head: unknown = document.createElement('div'); // @ts-ignore
449    head.classList.add('td');
450    if ((this.hasAttribute('tree') && index > 1) || (!this.hasAttribute('tree') && index > 0)) {
451      let resizeDiv: HTMLDivElement = document.createElement('div');
452      resizeDiv.classList.add('resize'); // @ts-ignore
453      head.appendChild(resizeDiv);
454      this.resizeEventHandler(rowElement, resizeDiv, index);
455    } // @ts-ignore
456    this.resolvingAreaColumnRetract(column, head);
457    this.resolvingAreaColumnOrder(column, index, key, head); // @ts-ignore
458    this.resolvingAreaColumnButton(column, key, head); // @ts-ignore
459    head.style.justifyContent = column.getAttribute('align'); // @ts-ignore
460    head.style.gridArea = key; // @ts-ignore
461    return head;
462  }
463
464  resolvingAreaColumnRetract(column: unknown, columnHead: HTMLDivElement): void {
465    // @ts-ignore
466    if (column.hasAttribute('retract')) {
467      let expand = document.createElement('div');
468      expand.classList.add('expand');
469      expand.style.display = 'grid';
470      columnHead.append(expand);
471      let top = document.createElement('lit-icon') as LitIcon;
472      top.classList.add('top');
473      top.name = 'up';
474      expand.append(top);
475      let bottom = document.createElement('lit-icon') as LitIcon;
476      bottom.classList.add('bottom');
477      bottom.name = 'down';
478      expand.append(bottom);
479      expand.addEventListener('click', (e) => {
480        if (top.name === 'up' && bottom.name === 'down') {
481          top.name = 'down';
482          bottom.name = 'up';
483          // 一键展开
484          this.setStatus(this.value, true);
485          this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Expand);
486        } else {
487          top.name = 'up';
488          bottom.name = 'down';
489          // 一键收起
490          this.setStatus(this.value, false);
491          this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Retract);
492        }
493        e.stopPropagation();
494      });
495    }
496  }
497
498  resolvingAreaColumnButton(column: unknown, key: string, head: HTMLDivElement): void {
499    // @ts-ignore
500    if (column.hasAttribute('button')) {
501      let buttonIcon = document.createElement('button');
502      buttonIcon.innerHTML = 'GetBusyTime(ms)';
503      buttonIcon.classList.add('button-icon');
504      head.appendChild(buttonIcon);
505      buttonIcon.addEventListener('click', (event) => {
506        this.dispatchEvent(
507          new CustomEvent('button-click', {
508            detail: {
509              key: key,
510            },
511            composed: true,
512          })
513        );
514        event.stopPropagation();
515      });
516    }
517  }
518
519  resolvingAreaColumnOrder(column: unknown, index: number, key: string, columnHead: unknown): void {
520    // @ts-ignore
521    if (column.hasAttribute('order')) {
522      // @ts-ignore
523      (columnHead as unknown).sortType = 0; // @ts-ignore
524      columnHead.classList.add('td-order'); // @ts-ignore
525      columnHead.style.position = 'relative'; // @ts-ignore
526      let { upSvg, downSvg } = createDownUpSvg(index, columnHead); // @ts-ignore
527      columnHead.onclick = (): void => {
528        if (this.isResize || this.resizeColumnIndex !== -1) {
529          return;
530        }
531        this?.shadowRoot?.querySelectorAll('.td-order svg').forEach((it: unknown) => {
532          // @ts-ignore
533          it.setAttribute('fill', 'let(--dark-color1,#212121)'); // @ts-ignore
534          it.sortType = 0; // @ts-ignore
535          it.style.display = 'none';
536        }); // @ts-ignore
537        if (columnHead.sortType === undefined || columnHead.sortType === null) {
538          // @ts-ignore
539          columnHead.sortType = 0; // @ts-ignore
540        } else if (columnHead.sortType === 2) {
541          // @ts-ignore
542          columnHead.sortType = 0;
543        } else {
544          // @ts-ignore
545          columnHead.sortType += 1;
546        }
547        upSvg.setAttribute('fill', 'let(--dark-color1,#212121)');
548        downSvg.setAttribute('fill', 'let(--dark-color1,#212121)'); // @ts-ignore
549        upSvg.style.display = columnHead.sortType === 1 ? 'block' : 'none'; // @ts-ignore
550        downSvg.style.display = columnHead.sortType === 2 ? 'block' : 'none'; // @ts-ignore
551        switch (columnHead.sortType) {
552          case 1:
553            this.theadElement!.setAttribute('sort', '');
554            break;
555          case 2:
556            break;
557          default:
558            this.theadElement!.removeAttribute('sort');
559            break;
560        }
561        this.dispatchEvent(
562          new CustomEvent('column-click', {
563            detail: {
564              // @ts-ignore
565              sort: columnHead.sortType,
566              key: key,
567            },
568            composed: true,
569          })
570        );
571      };
572    }
573  }
574
575  private isResize: boolean = false;
576  private resizeColumnIndex: number = -1;
577  private resizeDownX: number = 0;
578  private columnMinWidth: number = 50;
579  private beforeResizeWidth: number = 0;
580
581  resizeEventHandler(header: HTMLDivElement, element: HTMLDivElement, index: number): void {
582    this.resizeMouseMoveEventHandler(header);
583    header.addEventListener('mouseup', (event) => {
584      if (!this.columnResizeEnable) {
585        return;
586      }
587      this.isResize = false;
588      this.resizeDownX = 0;
589      header.style.cursor = 'pointer';
590      setTimeout(() => {
591        this.resizeColumnIndex = -1;
592      }, 100);
593      event.stopPropagation();
594      event.preventDefault();
595    });
596    header.addEventListener('mouseleave', (event) => {
597      if (!this.columnResizeEnable) {
598        return;
599      }
600      event.stopPropagation();
601      event.preventDefault();
602      this.isResize = false;
603      this.resizeDownX = 0;
604      this.resizeColumnIndex = -1;
605      header.style.cursor = 'pointer';
606    });
607    element.addEventListener('mousedown', (event) => {
608      if (event.button === 0) {
609        if (!this.columnResizeEnable) {
610          return;
611        }
612        this.isResize = true;
613        this.resizeColumnIndex = index;
614        this.resizeDownX = event.clientX;
615        let pre = header.childNodes.item(this.resizeColumnIndex - 1) as HTMLDivElement;
616        this.beforeResizeWidth = pre.clientWidth;
617        event.stopPropagation();
618      }
619    });
620    element.addEventListener('click', (event) => {
621      event.stopPropagation();
622    });
623  }
624
625  resizeMouseMoveEventHandler(header: HTMLDivElement): void {
626    header.addEventListener('mousemove', (event) => {
627      if (!this.columnResizeEnable) {
628        return;
629      }
630      if (this.isResize) {
631        let width = event.clientX - this.resizeDownX;
632        header.style.cursor = 'col-resize';
633        let preWidth = Math.max(this.beforeResizeWidth + width, this.columnMinWidth);
634        this.gridTemplateColumns[header.childNodes.length - 1] = '1fr';
635        for (let i = 0; i < header.childNodes.length; i++) {
636          let node = header.childNodes.item(i) as HTMLDivElement;
637          this.gridTemplateColumns[i] = `${node.clientWidth}px`;
638        }
639        this.gridTemplateColumns[this.resizeColumnIndex - 1] = `${preWidth}px`;
640        let lastNode = header.childNodes.item(header.childNodes.length - 1) as HTMLDivElement;
641        let totalWidth = 0;
642        this.gridTemplateColumns.forEach((it) => {
643          totalWidth += parseInt(it);
644        });
645        totalWidth = Math.max(totalWidth, this.shadowRoot!.querySelector<HTMLDivElement>('.table')!.scrollWidth);
646        this.gridTemplateColumns[this.gridTemplateColumns.length - 1] = `${totalWidth - lastNode.offsetLeft}px`;
647        header.style.gridTemplateColumns = this.gridTemplateColumns.join(' ');
648        let preNode = header.childNodes.item(this.resizeColumnIndex - 1) as HTMLDivElement;
649        preNode.style.width = `${preWidth}px`;
650        this.shadowRoot!.querySelectorAll<HTMLDivElement>('.tr').forEach((tr) => {
651          if (this.hasAttribute('tree')) {
652            tr.style.gridTemplateColumns = this.gridTemplateColumns.slice(1).join(' ');
653          } else {
654            tr.style.gridTemplateColumns = this.gridTemplateColumns.join(' ');
655          }
656        });
657        event.preventDefault();
658        event.stopPropagation();
659      } else {
660        header.style.cursor = 'pointer';
661      }
662    });
663  }
664
665  adoptedCallback(): void { }
666
667  getCheckRows(): unknown[] {
668    // @ts-ignore
669    return [...this.shadowRoot!.querySelectorAll('div[class=tr][checked]')] // @ts-ignore
670      .map((a) => (a as unknown).data)
671      .map((a) => {
672        if ('children' in a) {
673          Reflect.deleteProperty(a, 'chlidren');
674        }
675        return a;
676      });
677  }
678
679  deleteRowsCondition(fn: unknown): void {
680    this.shadowRoot!.querySelectorAll('div[class=tr]').forEach((tr) => {
681      // @ts-ignore
682      if (fn(tr.data)) {
683        tr.remove();
684      }
685    });
686  }
687
688  meauseElementHeight(rowData: unknown): number {
689    return 27;
690  }
691
692  meauseTreeElementHeight(rowData: unknown, depth: number): number {
693    return 27;
694  }
695
696  getVisibleObjects(list: unknown[]): { visibleObjects: TableRowObject[]; totalHeight: number } {
697    let headHeight = 0;
698    let totalHeight = headHeight;
699    let visibleObjects: TableRowObject[] = [];
700    let itemHandler = (rowData: unknown, index: number): void => {
701      let height = this.meauseElementHeight(rowData);
702      let tableRowObject = new TableRowObject();
703      tableRowObject.height = height;
704      tableRowObject.top = totalHeight;
705      tableRowObject.data = rowData;
706      tableRowObject.rowIndex = index;
707      if (
708        Math.max(totalHeight, this.tableElement!.scrollTop + headHeight) <=
709        Math.min(totalHeight + height, this.tableElement!.scrollTop + this.tableElement!.clientHeight + headHeight)
710      ) {
711        let newTableElement = this.addTableElement(tableRowObject, false, false, true, totalHeight);
712        let td = newTableElement?.querySelectorAll('.td'); //@ts-ignore
713        if (tableRowObject.data.rowName === 'cpu-profiler') {
714          td[0].innerHTML = '';
715          this.createTextColor(tableRowObject, td[0]);
716        }
717      }
718      totalHeight += height;
719      visibleObjects.push(tableRowObject);
720    };
721    let realIndex = 0;
722    list.forEach((item, index) => {
723      if (Array.isArray(item)) {
724        item.forEach((rowData, childIndex) => {
725          itemHandler(rowData, realIndex);
726          realIndex++;
727        });
728      } else {
729        itemHandler(item, index);
730      }
731    });
732    return { visibleObjects, totalHeight };
733  }
734
735  meauseAllRowHeight(list: unknown[]): TableRowObject[] {
736    this.tbodyElement!.innerHTML = '';
737    this.meauseRowElement = undefined;
738    let head = this.shadowRoot!.querySelector('.th');
739    this.tbodyElement && (this.tbodyElement.style.width = head?.clientWidth + 'px');
740    this.currentRecycleList = [];
741    let { visibleObjects, totalHeight } = this.getVisibleObjects(list);
742    this.tbodyElement && (this.tbodyElement.style.height = totalHeight + (this.isScrollXOutSide ? 0 : 0) + 'px');
743    this.tableElement &&
744      (this.tableElement.onscroll = (event): void => {
745        let tblScrollTop = this.tableElement!.scrollTop;
746        let skip = 0;
747        for (let i = 0; i < visibleObjects.length; i++) {
748          if (
749            visibleObjects[i].top <= tblScrollTop &&
750            visibleObjects[i].top + visibleObjects[i].height >= tblScrollTop
751          ) {
752            skip = i;
753            break;
754          }
755        }
756        let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0);
757        if (reduce === 0) {
758          return;
759        }
760        while (reduce <= this.tableElement!.clientHeight) {
761          let newTableElement = this.addTableElement(visibleObjects[skip], false, false, false);
762          reduce += newTableElement.clientHeight;
763        }
764        for (let i = 0; i < this.currentRecycleList.length; i++) {
765          this.freshLineHandler(i, skip, visibleObjects);
766        }
767      });
768    return visibleObjects;
769  }
770
771  freshLineHandler(index: number, skip: number, visibleObjects: TableRowObject[]): void {
772    this.freshCurrentLine(this.currentRecycleList[index], visibleObjects[index + skip]);
773    if (visibleObjects[index + skip]) {
774      //@ts-ignore
775      if (visibleObjects[index + skip].data.rowName === 'cpu-profiler') {
776        this.createTextColor(visibleObjects[index + skip], this.currentRecycleList[index].childNodes[0]);
777      }
778    }
779  }
780
781  newTableRowObject(item: unknown, totalHeight: number, depth: number, parentNode?: TableRowObject): TableRowObject {
782    let tableRowObject = new TableRowObject();
783    tableRowObject.depth = depth;
784    tableRowObject.data = item;
785    tableRowObject.top = totalHeight;
786    tableRowObject.height = this.meauseTreeElementHeight(tableRowObject, depth);
787    if (parentNode) {
788      parentNode!.children.push(tableRowObject);
789    }
790    return tableRowObject;
791  }
792
793  resetAllHeight(
794    list: unknown[],
795    depth: number,
796    totalHeight: number,
797    visibleObjects: TableRowObject[],
798    parentNode?: TableRowObject,
799    form?: RedrawTreeForm
800  ): number {
801    let th = totalHeight;
802    let headHeight = this.theadElement?.clientHeight || 0;
803    list.forEach((item) => {
804      let tableRowObject = this.newTableRowObject(item, th, depth, parentNode); // @ts-ignore
805      if (this._mode === TableMode.Expand && form === RedrawTreeForm.Retract && !item.status) {
806        tableRowObject.expanded = false;
807      } else if (this._mode === TableMode.Expand && form === RedrawTreeForm.Default) {
808        tableRowObject.expanded = true;
809      }
810      if (
811        // @ts-ignore
812        (this._mode === TableMode.Retract && !item.status) || // @ts-ignore
813        (this._mode === TableMode.Expand && !item.status && form !== RedrawTreeForm.Expand)
814      ) {
815        tableRowObject.expanded = false; // @ts-ignore
816        if (item.children !== undefined && item.children.length > 0) {
817          this.newTableRowObject(item, th, depth, tableRowObject);
818        }
819      }
820      if (
821        Math.max(th, this.tableElement!.scrollTop) <=
822        Math.min(
823          th + tableRowObject.height,
824          this.tableElement!.scrollTop + this.tableElement!.clientHeight - headHeight
825        )
826      ) {
827        this.addTableElement(tableRowObject, true, false, true, th);
828      }
829      th += tableRowObject.height;
830      visibleObjects.push(tableRowObject);
831      th = this.resetAllHeightChildrenHandler(item, depth, th, visibleObjects, tableRowObject, form);
832    });
833    return th;
834  }
835
836  resetAllHeightChildrenHandler(
837    item: unknown,
838    depth: number,
839    totalHeight: number,
840    visibleObjects: TableRowObject[],
841    tableRowObject?: TableRowObject,
842    form?: RedrawTreeForm
843  ): number {
844    let th = totalHeight; // @ts-ignore
845    if (item.hasNext) {
846      // js memory的表格
847      // @ts-ignore
848      if (item.parents !== undefined && item.parents.length > 0 && item.status) {
849        // @ts-ignore
850        th = this.resetAllHeight(item.parents, depth + 1, totalHeight, visibleObjects, tableRowObject); // @ts-ignore
851      } else if (item.children !== undefined && item.children.length > 0 && item.status) {
852        // @ts-ignore
853        th = this.resetAllHeight(item.children, depth + 1, totalHeight, visibleObjects, tableRowObject);
854      }
855    } else {
856      // 其他数据
857      if (
858        // @ts-ignore
859        item.children !== undefined && // @ts-ignore
860        item.children.length > 0 &&
861        form === RedrawTreeForm.Expand &&
862        this._mode === TableMode.Expand
863      ) {
864        // @ts-ignore
865        item.status = true; // @ts-ignore
866        th = this.resetAllHeight(item.children, depth + 1, totalHeight, visibleObjects, tableRowObject); // @ts-ignore
867      } else if (item.children !== undefined && item.children.length > 0 && item.status) {
868        // @ts-ignore
869        th = this.resetAllHeight(item.children, depth + 1, totalHeight, visibleObjects, tableRowObject);
870      }
871    }
872    return th;
873  }
874
875  measureReset(): void {
876    this.meauseRowElement = undefined;
877    this.tbodyElement!.innerHTML = '';
878    this.treeElement!.innerHTML = '';
879    this.currentRecycleList = [];
880    this.currentTreeDivList = [];
881  }
882
883  meauseTreeRowElement(list: unknown[], form?: RedrawTreeForm): TableRowObject[] {
884    this.measureReset();
885    let visibleObjects: TableRowObject[] = [];
886    let totalHeight = 0;
887    totalHeight = this.resetAllHeight(list, 0, totalHeight, visibleObjects);
888    this.tbodyElement && (this.tbodyElement.style.height = totalHeight + 'px');
889    this.treeElement!.style.height = this.tableElement!.clientHeight - this.theadElement!.clientHeight + 'px';
890    this.tableElement &&
891      (this.tableElement.onscroll = (event): void => {
892        let visibleObjects = this.recycleDs.filter((item) => {
893          // @ts-ignore
894          return !item.rowHidden;
895        });
896        let top = this.tableElement!.scrollTop;
897        this.treeElement && (this.treeElement!.style.transform = `translateY(${top}px)`);
898        let skip = 0;
899        for (let index = 0; index < visibleObjects.length; index++) {
900          // @ts-ignore
901          if (visibleObjects[index].top <= top && visibleObjects[index].top + visibleObjects[index].height >= top) {
902            skip = index;
903            break;
904          }
905        }
906        // 如果滚动高度大于数据全部收起的高度,并且this.currentRecycleList数组长度为0要给this.currentRecycleList赋值,不然tab页没有数据
907        if (
908          visibleObjects[0] && // @ts-ignore
909          this.tableElement!.scrollTop >= this.value.length * visibleObjects[0].height &&
910          this.currentRecycleList.length === 0
911        ) {
912          // @ts-ignore
913          this.addTableElement(visibleObjects[skip], true, false, false);
914        }
915        let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0);
916        if (reduce === 0) {
917          return;
918        }
919        while (reduce <= this.tableElement!.clientHeight) {
920          // @ts-ignore
921          let newTableElement = this.addTableElement(visibleObjects[skip], true, false, false);
922          reduce += newTableElement.clientHeight;
923        }
924        for (let i = 0; i < this.currentRecycleList.length; i++) {
925          this.freshCurrentLine(
926            this.currentRecycleList[i], // @ts-ignore
927            visibleObjects[i + skip],
928            this.treeElement?.children[i] as HTMLElement
929          );
930        }
931      });
932    return visibleObjects;
933  }
934
935  private addTableElement(
936    rowData: TableRowObject,
937    isTree: boolean,
938    last: boolean,
939    translate: boolean,
940    totalHeight?: number
941  ): HTMLDivElement {
942    let newTableElement;
943    if (isTree) {
944      newTableElement = this.createNewTreeTableElement(rowData);
945    } else {
946      newTableElement = this.createNewTableElement(rowData);
947    }
948    if (translate) {
949      newTableElement.style.transform = `translateY(${totalHeight}px)`;
950    }
951    this.tbodyElement?.append(newTableElement);
952    if (last) {
953      if (this.hasAttribute('tree')) {
954        if (this.treeElement?.lastChild) {
955          (this.treeElement?.lastChild as HTMLElement).style.height = rowData.height + 'px';
956        }
957      }
958    }
959    this.currentRecycleList.push(newTableElement);
960    return newTableElement;
961  }
962
963  createNewTreeTableElement(rowData: TableRowObject): HTMLDivElement {
964    let rowTreeElement = document.createElement('div');
965    rowTreeElement.classList.add('tr');
966    let treeTop = 0;
967    if (this.treeElement!.children?.length > 0) {
968      let transX = Number((this.treeElement?.lastChild as HTMLElement).style.transform.replace(/[^0-9]/gi, ''));
969      treeTop += transX + rowData.height;
970    }
971    this?.columns?.forEach((column: unknown, index) => {
972      // @ts-ignore
973      let dataIndex = column.getAttribute('data-index') || '1';
974      let td: unknown;
975      if (index === 0) {
976        td = this.firstElementTdHandler(rowTreeElement, dataIndex, rowData, column);
977      } else {
978        td = this.otherElementHandler(dataIndex, rowData, column); // @ts-ignore
979        this.dispatchTdClickEvent(td, column, rowData);// @ts-ignore
980        rowTreeElement.append(td);
981      }
982    });
983    let lastChild = this.treeElement?.lastChild as HTMLElement;
984    if (lastChild) {
985      lastChild.style.transform = `translateY(${treeTop}px)`;
986    } // @ts-ignore
987    (rowTreeElement as unknown).data = rowData.data;
988    rowTreeElement.style.gridTemplateColumns = this.gridTemplateColumns.slice(1).join(' ');
989    rowTreeElement.style.position = 'absolute';
990    rowTreeElement.style.top = '0px';
991    rowTreeElement.style.left = '0px';
992    rowTreeElement.style.cursor = 'pointer'; //@ts-ignore
993    this.setHighLight(rowData.data.isSearch, rowTreeElement);
994    this.addRowElementEvent(rowTreeElement, rowData);
995    return rowTreeElement;
996  }
997
998  addRowElementEvent(rowTreeElement: HTMLDivElement, rowData: unknown): void {
999    rowTreeElement.onmouseenter = (): void => {
1000      // @ts-ignore
1001      if ((rowTreeElement as unknown).data.isSelected) {
1002        return;
1003      }
1004      let indexOf = this.currentRecycleList.indexOf(rowTreeElement);
1005      this.currentTreeDivList.forEach((row) => {
1006        row.classList.remove('mouse-in');
1007      });
1008      if (indexOf >= 0 && indexOf < this.currentTreeDivList.length) {
1009        this.setMouseIn(true, [this.currentTreeDivList[indexOf]]);
1010      }
1011    };
1012    rowTreeElement.onmouseleave = (): void => {
1013      // @ts-ignore
1014      if ((rowTreeElement as unknown).data.isSelected) {
1015        return;
1016      }
1017      let indexOf = this.currentRecycleList.indexOf(rowTreeElement);
1018      if (indexOf >= 0 && indexOf < this.treeElement!.children.length) {
1019        this.setMouseIn(false, [this.treeElement?.children[indexOf] as HTMLElement]);
1020      }
1021    };
1022    rowTreeElement.onmouseup = (e: MouseEvent): void => {
1023      let indexOf = this.currentRecycleList.indexOf(rowTreeElement);
1024      this.dispatchRowClickEvent(rowData, [this.treeElement?.children[indexOf] as HTMLElement, rowTreeElement], e);
1025      e.stopPropagation();
1026    };
1027  }
1028
1029  firstElementTdHandler(tr: HTMLDivElement, dataIndex: string, row: unknown, column: unknown): HTMLElement {
1030    let td: unknown; // @ts-ignore
1031    let text = formatName(dataIndex, row.data[dataIndex], this); // @ts-ignore
1032    if (column.template) {
1033      // @ts-ignore
1034      td = column.template.render(row.data).content.cloneNode(true); // @ts-ignore
1035      td.template = column.template; // @ts-ignore
1036      td.title = row.data[dataIndex];
1037    } else {
1038      td = document.createElement('div'); // @ts-ignore
1039      if (row.data.rowName === 'js-memory' || row.data.rowName === 'cpu-profiler') {
1040        // @ts-ignore
1041        td.innerHTML = '';
1042      } else {
1043        // @ts-ignore
1044        td.innerHTML = text;
1045      } // @ts-ignore
1046      td.dataIndex = dataIndex; //@ts-ignore
1047      if (text.indexOf('&lt;') === -1) {
1048        // @ts-ignore
1049        td.title = text;
1050      }
1051    } // @ts-ignore
1052    if (row.data.children && row.data.children.length > 0 && !row.data.hasNext) {
1053      let btn = this.createExpandBtn(row); // @ts-ignore
1054      td.insertBefore(btn, td.firstChild);
1055    } // @ts-ignore
1056    if (row.data.hasNext) {
1057      // @ts-ignore
1058      td.title = row.data.objectName;
1059      let btn = this.createBtn(row); // @ts-ignore
1060      td.insertBefore(btn, td.firstChild);
1061    } // @ts-ignore
1062    td.style.paddingLeft = row.depth * iconWidth + 'px'; // @ts-ignore
1063    if (!row.data.children || row.data.children.length === 0) {
1064      // @ts-ignore
1065      td.style.paddingLeft = iconWidth * row.depth + iconWidth + iconPadding * 2 + 'px';
1066    }
1067    this.jsMemoryHandler(row, td); // @ts-ignore
1068    if (row.data.rowName === 'cpu-profiler') {
1069      this.createTextColor(row, td);
1070    } // @ts-ignore
1071    (td as unknown).data = row.data; // @ts-ignore
1072    td.classList.add('tree-first-body'); // @ts-ignore
1073    td.style.position = 'absolute'; // @ts-ignore
1074    td.style.top = '0px'; // @ts-ignore
1075    td.style.left = '0px'; // @ts-ignore
1076    td.style.height = `${row.height}px`; // @ts-ignore
1077    this.addFirstElementEvent(td, tr, row); // @ts-ignore
1078    this.setHighLight(row.data.isSearch, td); // @ts-ignore
1079    this.treeElement!.style.width = column.getAttribute('width'); // @ts-ignore
1080    this.treeElement?.append(td); // @ts-ignore
1081    this.currentTreeDivList.push(td); // @ts-ignore
1082    return td;
1083  }
1084
1085  addFirstElementEvent(td: HTMLDivElement, tr: HTMLDivElement, rowData: unknown): void {
1086    td.onmouseenter = (): void => {
1087      let indexOf = this.currentTreeDivList.indexOf(td);
1088      this.currentRecycleList.forEach((row) => {
1089        row.classList.remove('mouse-in');
1090      });
1091      if (indexOf >= 0 && indexOf < this.currentRecycleList.length && td.innerHTML !== '') {
1092        this.setMouseIn(true, [tr]);
1093      }
1094    };
1095    td.onmouseleave = (): void => {
1096      let indexOf = this.currentTreeDivList.indexOf(td);
1097      if (indexOf >= 0 && indexOf < this.currentRecycleList.length) {
1098        this.setMouseIn(false, [tr]);
1099      }
1100    };
1101    td.onmouseup = (e: MouseEvent): void => {
1102      let indexOf = this.currentTreeDivList.indexOf(td);
1103      this.dispatchRowClickEvent(rowData, [td, tr], e);
1104      e.stopPropagation();
1105    };
1106  }
1107
1108  otherElementHandler(dataIndex: string, rowData: unknown, column: unknown): HTMLDivElement {
1109    // @ts-ignore
1110    let tdDiv: unknown = document.createElement('div'); // @ts-ignore
1111    tdDiv.classList.add('td'); // @ts-ignore
1112    tdDiv.style.overflow = 'hidden'; // @ts-ignore
1113    tdDiv.style.textOverflow = 'ellipsis'; // @ts-ignore
1114    tdDiv.style.whiteSpace = 'nowrap'; // @ts-ignore
1115    let text = formatName(dataIndex, rowData.data[dataIndex], this); //@ts-ignore
1116    if (text.indexOf('&lt;') === -1) {
1117      // @ts-ignore
1118      if (dataIndex === 'selfTimeStr' && rowData.data.chartFrameChildren) {
1119        // @ts-ignore
1120        tdDiv.title = rowData.data.selfTime + 'ns'; // @ts-ignore
1121      } else if (dataIndex === 'totalTimeStr' && rowData.data.chartFrameChildren) {
1122        // @ts-ignore
1123        tdDiv.title = rowData.data.totalTime + 'ns';
1124      } else {
1125        // @ts-ignore
1126        tdDiv.title = text;
1127      }
1128    } // @ts-ignore
1129    tdDiv.dataIndex = dataIndex; // @ts-ignore
1130    tdDiv.style.justifyContent = column.getAttribute('align') || 'flex-start'; // @ts-ignore
1131    if (column.template) {
1132      // @ts-ignore
1133      tdDiv.appendChild(column.template.render(rowData.data).content.cloneNode(true)); // @ts-ignore
1134      tdDiv.template = column.template;
1135    } else {
1136      // @ts-ignore
1137      tdDiv.innerHTML = text;
1138    } // @ts-ignore
1139    return tdDiv;
1140  }
1141
1142  createNewTableElement(rowData: unknown): HTMLDivElement {
1143    let newTableElement = document.createElement('div');
1144    newTableElement.classList.add('tr');
1145    this?.columns?.forEach((column: unknown) => {
1146      // @ts-ignore
1147      let dataIndex = column.getAttribute('data-index') || '1';
1148      let td = this.createColumnTd(dataIndex, column, rowData);
1149      //@ts-ignore
1150      this.dispatchTdClickEvent(td, column, rowData);
1151      newTableElement.append(td);
1152    });
1153    newTableElement.onmouseup = (e: MouseEvent): void => {
1154      this.dispatchRowClickEvent(rowData, [newTableElement], e);
1155      e.stopPropagation();
1156    };
1157    newTableElement.onmouseenter = (): void => {
1158      this.dispatchRowHoverEvent(rowData, [newTableElement]);
1159    }; // @ts-ignore
1160    if (rowData.data.isSelected !== undefined) {
1161      // @ts-ignore
1162      this.setSelectedRow(rowData.data.isSelected, [newTableElement]);
1163    } // @ts-ignore
1164    (newTableElement as unknown).data = rowData.data;
1165    newTableElement.style.cursor = 'pointer';
1166    newTableElement.style.gridTemplateColumns = this.gridTemplateColumns.join(' ');
1167    newTableElement.style.position = 'absolute';
1168    newTableElement.style.top = '0px';
1169    newTableElement.style.left = '0px';
1170    if (this.getItemTextColor) {
1171      // @ts-ignore
1172      newTableElement.style.color = this.getItemTextColor(rowData.data);
1173    }
1174    return newTableElement;
1175  }
1176
1177  createColumnTd(dataIndex: string, column: unknown, rowData: unknown): HTMLDivElement {
1178    let td: unknown;
1179    td = document.createElement('div'); // @ts-ignore
1180    td.classList.add('td'); // @ts-ignore
1181    td.style.overflow = 'hidden'; // @ts-ignore
1182    td.style.textOverflow = 'ellipsis'; // @ts-ignore
1183    td.style.whiteSpace = 'nowrap'; // @ts-ignore
1184    td.dataIndex = dataIndex; // @ts-ignore
1185    td.style.justifyContent = column.getAttribute('align') || 'flex-start'; // @ts-ignore
1186    let text = formatName(dataIndex, rowData.data[dataIndex], this); //@ts-ignore
1187    if (text.indexOf('&lt;') === -1) {
1188      // @ts-ignore
1189      if (dataIndex === 'totalTimeStr' && rowData.data.chartFrameChildren) {
1190        // @ts-ignore
1191        td.title = rowData.data.totalTime + 'ns';
1192      } else {
1193        // @ts-ignore
1194        td.title = text;
1195      }
1196    }
1197    //   如果表格中有模板的情况,将模板中的数据放进td中,没有模板,直接将文本放进td
1198    //  但是对于Current Selection tab页来说,表格前两列是时间,第三列是input标签,第四列是button标签
1199    //  而第一行的数据只有第四列一个button,和模板中的数据并不一样,所以要特别处理一下
1200    // @ts-ignore
1201    if (column.template) {
1202      if (
1203        // @ts-ignore
1204        (dataIndex === 'color' && rowData.data.color === undefined) || // @ts-ignore
1205        (dataIndex === 'text' && rowData.data.text === undefined)
1206      ) {
1207        // @ts-ignore
1208        td.innerHTML = ''; // @ts-ignore
1209        td.template = ''; // @ts-ignore
1210      } else if (dataIndex === 'operate' && rowData.data.operate && rowData.data.operate.innerHTML === 'RemoveAll') {
1211        let removeAll = document.createElement('button');
1212        removeAll.className = 'removeAll';
1213        removeAll.innerHTML = 'RemoveAll';
1214        removeAll.style.background = 'var(--dark-border1,#262f3c)';
1215        removeAll.style.color = 'white';
1216        removeAll.style.borderRadius = '10px';
1217        removeAll.style.fontSize = '10px';
1218        removeAll.style.height = '18px';
1219        removeAll.style.lineHeight = '18px';
1220        removeAll.style.minWidth = '7em';
1221        removeAll.style.border = 'none';
1222        removeAll.style.cursor = 'pointer';
1223        removeAll.style.outline = 'inherit'; // @ts-ignore
1224        td.appendChild(removeAll);
1225      } else {
1226        // @ts-ignore
1227        td.appendChild(column.template.render(rowData.data).content.cloneNode(true)); // @ts-ignore
1228        td.template = column.template;
1229      }
1230    } else {
1231      // @ts-ignore
1232      td.innerHTML = text;
1233    } // @ts-ignore
1234    return td;
1235  }
1236
1237  createBtn(rowData: unknown): unknown {
1238    let btn: unknown = document.createElement('lit-icon'); // @ts-ignore
1239    btn.classList.add('tree-icon'); // @ts-ignore
1240    if (rowData.data.expanded) {
1241      // @ts-ignore
1242      btn.name = 'plus-square';
1243    } else {
1244      // @ts-ignore
1245      btn.name = 'minus-square';
1246    } // @ts-ignore
1247    btn.addEventListener('mouseup', (e: MouseEvent): void => {
1248      if (e.button === 0) {
1249        // @ts-ignore
1250        rowData.data.status = false;
1251        const resetNodeHidden = (hidden: boolean, rowData: unknown): void => {
1252          if (hidden) {
1253            // @ts-ignore
1254            rowData.children.forEach((child: unknown) => {
1255              // @ts-ignore
1256              child.rowHidden = false;
1257            });
1258          } else {
1259            // @ts-ignore
1260            rowData.children.forEach((child: unknown) => {
1261              // @ts-ignore
1262              child.rowHidden = true;
1263              resetNodeHidden(hidden, child);
1264            });
1265          }
1266        };
1267        // @ts-ignore
1268        if (rowData.data.expanded) {
1269          // @ts-ignore
1270          rowData.data.status = true;
1271          this.dispatchRowClickEventIcon(rowData, [btn]); // @ts-ignore
1272          rowData.data.expanded = false;
1273          resetNodeHidden(true, rowData);
1274        } else {
1275          // @ts-ignore
1276          rowData.data.expanded = true; // @ts-ignore
1277          rowData.data.status = false;
1278          resetNodeHidden(false, rowData);
1279        }
1280        this.reMeauseHeight();
1281      }
1282      e.stopPropagation();
1283    });
1284    return btn;
1285  }
1286
1287  resetExpandNodeHidden = (hidden: boolean, rowData: unknown): void => {
1288    // @ts-ignore
1289    if (rowData.children.length > 0) {
1290      if (hidden) {
1291        // @ts-ignore
1292        rowData.children.forEach((child: unknown) => {
1293          // @ts-ignore
1294          child.rowHidden = true;
1295          this.resetExpandNodeHidden(hidden, child);
1296        });
1297      } else {
1298        // @ts-ignore
1299        rowData.children.forEach((child: unknown) => {
1300          // @ts-ignore
1301          child.rowHidden = !rowData.expanded; // @ts-ignore
1302          if (rowData.expanded) {
1303            this.resetExpandNodeHidden(hidden, child);
1304          }
1305        });
1306      }
1307    }
1308  };
1309
1310  setChildrenStatus(rowData: unknown, data: unknown): void {
1311    // @ts-ignore
1312    for (let d of data) {
1313      // @ts-ignore
1314      if (rowData.data === d) {
1315        d.status = false;
1316      }
1317      if (d.children !== undefined && d.children.length > 0) {
1318        this.setChildrenStatus(rowData, d.children);
1319      }
1320    }
1321  }
1322  createExpandBtn(rowData: unknown): LitIcon {
1323    // @ts-ignore
1324    let btn: unknown = document.createElement('lit-icon'); // @ts-ignore
1325    btn.classList.add('tree-icon');
1326    // @ts-ignore
1327    if (rowData.expanded) {
1328      // @ts-ignore
1329      btn.name = 'minus-square';
1330    } else {
1331      // @ts-ignore
1332      btn.name = 'plus-square';
1333    } // @ts-ignore
1334    btn.onmouseup = (e: MouseEvent): void => {
1335      if (e.button === 0) {
1336        // @ts-ignore
1337        if (rowData.expanded && this._mode === TableMode.Retract) {
1338          // @ts-ignore
1339          rowData.data.status = false; // @ts-ignore
1340          rowData.expanded = false;
1341          this.resetExpandNodeHidden(true, rowData); // @ts-ignore
1342        } else if (!rowData.expanded && this._mode === TableMode.Retract) {
1343          // @ts-ignore
1344          rowData.expanded = true; // @ts-ignore
1345          rowData.data.status = true;
1346          this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Retract);
1347          this.resetExpandNodeHidden(false, rowData);
1348        } // @ts-ignore
1349        if (this._mode === TableMode.Expand && rowData.expanded) {
1350          // 点击收起的时候将点击的那条数据的status改为false
1351          this.setChildrenStatus(rowData, this.value); // @ts-ignore
1352          rowData.expanded = false;
1353          this.resetExpandNodeHidden(true, rowData); // @ts-ignore
1354        } else if (this._mode === TableMode.Expand && !rowData.expanded) {
1355          // @ts-ignore
1356          if (rowData.data.children) {
1357            // @ts-ignore
1358            rowData.data.status = true;
1359          }
1360          this.recycleDs = this.meauseTreeRowElement(this.value, RedrawTreeForm.Default); // @ts-ignore
1361          rowData.expanded = true;
1362          this.resetExpandNodeHidden(false, rowData);
1363        }
1364        this.reMeauseHeight();
1365      }
1366      e.stopPropagation();
1367    }; // @ts-ignore
1368    return btn;
1369  }
1370
1371  reMeauseHeight(): void {
1372    if (this.currentRecycleList.length === 0 && this.ds.length !== 0) {
1373      this.recycleDataSource = this.ds;
1374      return;
1375    }
1376    let totalHeight = 0;
1377    this.recycleDs.forEach((it) => {
1378      // @ts-ignore
1379      if (!it.rowHidden) {
1380        // @ts-ignore
1381        it.top = totalHeight; // @ts-ignore
1382        totalHeight += it.height;
1383      }
1384    });
1385    this.tbodyElement && (this.tbodyElement.style.height = totalHeight + (this.isScrollXOutSide ? 0 : 0) + 'px');
1386    this.treeElement &&
1387      (this.treeElement.style.height = this.tableElement!.clientHeight - this.theadElement!.clientHeight + 'px');
1388    let visibleObjects = this.recycleDs.filter((item) => {
1389      // @ts-ignore
1390      return !item.rowHidden;
1391    });
1392    if (this.tableElement) {
1393      let top = this.tableElement!.scrollTop;
1394      let skip = 0;
1395      for (let i = 0; i < visibleObjects.length; i++) {
1396        // @ts-ignore
1397        if (visibleObjects[i].top <= top && visibleObjects[i].top + visibleObjects[i].height >= top) {
1398          skip = i;
1399          break;
1400        }
1401      }
1402      let reduce = this.currentRecycleList.map((item) => item.clientHeight).reduce((a, b) => a + b, 0);
1403      if (reduce === 0) {
1404        return;
1405      }
1406      while (reduce <= this.tableElement!.clientHeight + 1) {
1407        let isTree = this.hasAttribute('tree'); // @ts-ignore
1408        let newTableElement = this.addTableElement(visibleObjects[skip], isTree, isTree, false);
1409        reduce += newTableElement.clientHeight;
1410      }
1411      for (let i = 0; i < this.currentRecycleList.length; i++) {
1412        if (this.hasAttribute('tree')) {
1413          this.freshCurrentLine(
1414            this.currentRecycleList[i], // @ts-ignore
1415            visibleObjects[i + skip],
1416            this.treeElement?.children[i] as HTMLElement
1417          );
1418        } else {
1419          // @ts-ignore
1420          this.freshLineHandler(i, skip, visibleObjects);
1421        }
1422      }
1423    }
1424  }
1425
1426  getWheelStatus(element: unknown): void {
1427    // @ts-ignore
1428    element.addEventListener('wheel', (event: WheelEvent) => {
1429      // @ts-ignore
1430      if (element.scrollWidth !== element.offsetWidth) {
1431        event.preventDefault();
1432      } // @ts-ignore
1433      element.scrollLeft += event.deltaY;
1434    });
1435  }
1436
1437  renderTable(): void {
1438    if (!this.columns) {
1439      return;
1440    }
1441    if (!this.ds) {
1442      return;
1443    } // If no data source is set, it is returned directly
1444    this.normalDs = [];
1445    this.tbodyElement!.innerHTML = ''; // Clear the table contents
1446    this.ds.forEach((rowData: unknown) => {
1447      let tblRowElement = document.createElement('div');
1448      tblRowElement.classList.add('tr');
1449      // @ts-ignore
1450      tblRowElement.data = rowData;
1451      let gridTemplateColumns: Array<unknown> = [];
1452      // If the table is configured with selectable (select row mode) add a checkbox at the head of the line alone
1453      this.renderTableRowSelect(tblRowElement);
1454      this.tableColumns!.forEach((tblColumn) => {
1455        tblColumn.addEventListener('contextmenu', (e) => {
1456          e.preventDefault();
1457        });
1458        let dataIndex = tblColumn.getAttribute('data-index') || '1';
1459        gridTemplateColumns.push(tblColumn.getAttribute('width') || '1fr');
1460        this.renderTableRowColumnElement(tblColumn, tblRowElement, dataIndex, rowData);
1461      });
1462      if (this.selectable) {
1463        // If the table with selection is preceded by a 60px column
1464        tblRowElement.style.gridTemplateColumns = '60px ' + gridTemplateColumns.join(' ');
1465      } else {
1466        tblRowElement.style.gridTemplateColumns = gridTemplateColumns.join(' ');
1467      }
1468      this.renderTableRowElementEvent(tblRowElement, rowData);
1469      this.normalDs.push(tblRowElement);
1470      this.tbodyElement!.append(tblRowElement);
1471    });
1472  }
1473
1474  renderTableRowSelect(tblRowElement: HTMLDivElement): void {
1475    if (this.selectable) {
1476      let tblBox = document.createElement('div');
1477      tblBox.style.display = 'flex';
1478      tblBox.style.justifyContent = 'center';
1479      tblBox.style.alignItems = 'center';
1480      tblBox.classList.add('td');
1481      let checkbox = document.createElement('lit-checkbox');
1482      checkbox.classList.add('row-checkbox');
1483      checkbox.onchange = (e: unknown): void => {
1484        // Checkbox checking affects whether the div corresponding to the row has a checked attribute for marking
1485        // @ts-ignore
1486        if (e.detail.checked) {
1487          tblRowElement.setAttribute('checked', '');
1488        } else {
1489          tblRowElement.removeAttribute('checked');
1490        }
1491      };
1492      this.getWheelStatus(tblBox);
1493      tblBox.appendChild(checkbox);
1494      tblRowElement.appendChild(tblBox);
1495    }
1496  }
1497
1498  renderTableRowColumnElement(
1499    tblColumn: LitTableColumn,
1500    tblRowElement: HTMLDivElement,
1501    dataIndex: string,
1502    rowData: unknown
1503  ): void {
1504    if (tblColumn.template) {
1505      // If you customize the rendering, you get the nodes from the template
1506      // @ts-ignore
1507      let cloneNode = tblColumn.template.render(rowData).content.cloneNode(true);
1508      let tblCustomDiv = document.createElement('div');
1509      tblCustomDiv.classList.add('td');
1510      tblCustomDiv.style.wordBreak = 'break-all';
1511      tblCustomDiv.style.whiteSpace = 'pre-wrap';
1512      tblCustomDiv.style.justifyContent = tblColumn.getAttribute('align') || '';
1513      if (tblColumn.hasAttribute('fixed')) {
1514        fixed(tblCustomDiv, tblColumn.getAttribute('fixed') || '', '#ffffff');
1515      }
1516      this.getWheelStatus(tblCustomDiv);
1517      tblCustomDiv.append(cloneNode);
1518      tblRowElement.append(tblCustomDiv);
1519    } else {
1520      let tblDiv = document.createElement('div');
1521      tblDiv.classList.add('td');
1522      tblDiv.style.wordBreak = 'break-all';
1523      tblDiv.style.whiteSpace = 'pre-wrap'; // @ts-ignore
1524      tblDiv.title = rowData[dataIndex];
1525      tblDiv.style.justifyContent = tblColumn.getAttribute('align') || '';
1526      if (tblColumn.hasAttribute('fixed')) {
1527        fixed(tblDiv, tblColumn.getAttribute('fixed') || '', '#ffffff');
1528      }
1529      this.getWheelStatus(tblDiv); // @ts-ignore
1530      tblDiv.innerHTML = formatName(dataIndex, rowData[dataIndex], this);
1531      tblRowElement.append(tblDiv);
1532    }
1533  }
1534
1535  renderTableRowElementEvent(tblRowElement: HTMLDivElement, rowData: unknown): void {
1536    tblRowElement.onmouseup = (e: MouseEvent): void => {
1537      e.stopPropagation();
1538      this.dispatchEvent(
1539        new CustomEvent('row-click', {
1540          detail: {
1541            rowData,
1542            data: rowData,
1543            callBack: (isSelected: boolean): void => {
1544              //是否爲单选
1545              if (isSelected) {
1546                this.clearAllSelection(rowData);
1547              } // @ts-ignore
1548              this.setSelectedRow(rowData.isSelected, [tblRowElement]);
1549            },
1550          },
1551          composed: true,
1552        })
1553      );
1554      e.stopPropagation();
1555    };
1556  }
1557
1558  //自定义td点击事件
1559  dispatchTdClickEvent(td: unknown, column: unknown, rowData: unknown): void {
1560    // @ts-ignore
1561    if (column.hasAttribute('tdJump')) {
1562      //@ts-ignore
1563      td.style.color = '#208aed';
1564      //@ts-ignore
1565      td.style.textDecoration = 'underline';
1566      //@ts-ignore
1567      td.onclick = (event: unknown): void => {
1568        this.dispatchEvent(
1569          new CustomEvent('td-click', {
1570            detail: {
1571              //@ts-ignore
1572              ...rowData.data,
1573            },
1574            composed: true,
1575          })
1576        );
1577        // @ts-ignore
1578        event.stopPropagation();
1579      };
1580    }
1581  }
1582
1583  freshCurrentLine(element: HTMLElement, rowObject: TableRowObject, firstElement?: HTMLElement): void {
1584    if (!rowObject) {
1585      if (firstElement) {
1586        firstElement.style.display = 'none';
1587      }
1588      element.style.display = 'none';
1589      return;
1590    }
1591    let childIndex = -1; //@ts-ignore
1592    this.setHighLight(rowObject.data.isSearch, element);
1593    element.childNodes.forEach((child) => {
1594      if (child.nodeType !== 1) {
1595        return;
1596      }
1597      childIndex++;
1598      let idx = firstElement !== undefined ? childIndex + 1 : childIndex;
1599      this.freshLineFirstElementHandler(firstElement, rowObject, childIndex);
1600      if (idx < this.columns!.length) {
1601        //@ts-ignore
1602        let dataIndex = this.columns![idx].getAttribute('data-index') || '1'; //@ts-ignore
1603        let text = formatName(dataIndex, rowObject.data[dataIndex], this); // @ts-ignore
1604        if ((this.columns![idx] as unknown).template) {
1605          (child as HTMLElement).innerHTML = '';
1606          (child as HTMLElement).appendChild(
1607            // @ts-ignore
1608            (this.columns![idx] as unknown).template.render(rowObject.data).content.cloneNode(true)
1609          );
1610          // @ts-ignore
1611          (child as HTMLElement).title = text;
1612        } else {
1613          //@ts-ignore
1614          if (rowObject.data.rowName === 'cpu-profiler' && dataIndex === 'symbolName') {
1615            (child as HTMLElement).innerHTML = '';
1616          } else {
1617            //@ts-ignore
1618            if (rowObject.data.durFormat) { //ebpf泳道下的analysis页
1619              // 提取数字部分(包括小数点)
1620              if (dataIndex === 'durFormat') {
1621                // @ts-ignore
1622                const match = text.match(/^(\d+(\.\d+)?)(.*)$/);
1623                if (match && match[1] && match[3]) {
1624                  // 计算需要添加的空格数
1625                  const padding = '\xa0\xa0'.repeat(this.maxLength - match[1].length);
1626                  // 构造新的durFormat字符串
1627                  text = padding + match[1] + match[3];
1628                }
1629              }
1630              if (dataIndex === 'percent') {
1631                // @ts-ignore
1632                const match = text.match(/^(\d+(\.\d+)?)(.*)$/);
1633                if (match && match[1]) {
1634                  const padding = '\xa0\xa0'.repeat(this.maxLength - match[1].length);
1635                  text = padding + match[1];
1636                }
1637              }
1638            }
1639            //@ts-ignore
1640            (child as HTMLElement).innerHTML = text;
1641          } //@ts-ignore
1642          if (dataIndex === 'selfTimeStr' && rowObject.data.chartFrameChildren) {
1643            //@ts-ignore
1644            (child as HTMLElement).title = rowObject.data.selfTime + 'ns'; //@ts-ignore
1645          } else if (dataIndex === 'totalTimeStr' && rowObject.data.chartFrameChildren) {
1646            //@ts-ignore
1647            (child as HTMLElement).title = rowObject.data.totalTime + 'ns';
1648          } else if (dataIndex === 'timeStr' && rowObject.data instanceof JsCpuProfilerStatisticsStruct) {
1649            (child as HTMLElement).title = rowObject.data.time + 'ns';
1650          } else {
1651            //@ts-ignore
1652            (child as HTMLElement).title = text;
1653          }
1654        }
1655      }
1656    });
1657    this.freshLineStyleAndEvents(element, rowObject, firstElement);
1658  }
1659
1660  freshLineStyleAndEvents(element: HTMLElement, rowObject: TableRowObject, firstElement?: HTMLElement): void {
1661    if (element.style.display === 'none') {
1662      element.style.display = 'grid';
1663    }
1664    element.style.transform = `translateY(${rowObject.top}px)`;
1665    if (firstElement && firstElement.style.display === 'none') {
1666      firstElement.style.display = 'flex';
1667    }
1668    element.onmouseup = (e: MouseEvent): void => {
1669      if (firstElement !== undefined) {
1670        this.dispatchRowClickEvent(rowObject, [firstElement, element], e);
1671      } else {
1672        this.dispatchRowClickEvent(rowObject, [element], e);
1673      }
1674      e.stopPropagation();
1675    };
1676    element.onmouseenter = (): void => {
1677      this.dispatchRowHoverEvent(rowObject, [element]); // @ts-ignore
1678      if ((element as unknown).data.isSelected) {
1679        return;
1680      }
1681      let indexOf = this.currentRecycleList.indexOf(element as HTMLDivElement);
1682      this.currentTreeDivList.forEach((row) => {
1683        row.classList.remove('mouse-in');
1684      });
1685      if (indexOf >= 0 && indexOf < this.currentTreeDivList.length) {
1686        this.setMouseIn(true, [this.currentTreeDivList[indexOf]]);
1687      }
1688    };
1689    this.querySelectorAll('lit-table-column').forEach((item, i) => {
1690      if (this.hasAttribute('tree')) {
1691        this.dispatchTdClickEvent(element.childNodes[i - 1], item, rowObject);
1692      } else {
1693        this.dispatchTdClickEvent(element.childNodes[i], item, rowObject);
1694      }
1695    });
1696    // @ts-ignore
1697    (element as unknown).data = rowObject.data; //@ts-ignore
1698    if (rowObject.data.isSelected !== undefined) {
1699      //@ts-ignore
1700      this.setSelectedRow(rowObject.data.isSelected, [element]);
1701    } else {
1702      this.setSelectedRow(false, [element]);
1703    } //@ts-ignore
1704    if (rowObject.data.isHover !== undefined) {
1705      //@ts-ignore
1706      this.setMouseIn(rowObject.data.isHover, [element]);
1707    } else {
1708      this.setMouseIn(false, [element]);
1709    }
1710    if (this.getItemTextColor) {
1711      // @ts-ignore
1712      element.style.color = this.getItemTextColor((element as unknown).data);
1713    }
1714  }
1715
1716  freshLineFirstElementHandler(firstElement: unknown, rowObject: TableRowObject, childIndex: number): void {
1717    if (firstElement !== undefined && childIndex === 0) {
1718      //@ts-ignore
1719      this.setHighLight(rowObject.data.isSearch, firstElement); // @ts-ignore
1720      (firstElement as unknown).data = rowObject.data; // @ts-ignore
1721      if ((this.columns![0] as unknown).template) {
1722        // @ts-ignore
1723        firstElement.innerHTML = (this.columns![0] as unknown).template
1724          .render(rowObject.data)
1725          .content.cloneNode(true).innerHTML;
1726      } else {
1727        let dataIndex = this.columns![0].getAttribute('data-index') || '1'; //@ts-ignore
1728        let text = formatName(dataIndex, rowObject.data[dataIndex], this); //@ts-ignore
1729        if (rowObject.data.rowName === 'js-memory' || rowObject.data.rowName === 'cpu-profiler') {
1730          // @ts-ignore
1731          firstElement.innerHTML = '';
1732        } else {
1733          // @ts-ignore
1734          firstElement.innerHTML = text;
1735        } // @ts-ignore
1736        firstElement.title = text;
1737      } //@ts-ignore
1738      if (rowObject.children && rowObject.children.length > 0 && !rowObject.data.hasNext) {
1739        let btn = this.createExpandBtn(rowObject); // @ts-ignore
1740        firstElement.insertBefore(btn, firstElement.firstChild);
1741      } // @ts-ignore
1742      firstElement.style.paddingLeft = iconWidth * rowObject.depth + 'px';
1743      if (!rowObject.children || rowObject.children.length === 0) {
1744        // @ts-ignore
1745        firstElement.style.paddingLeft = iconWidth * rowObject.depth + iconWidth + iconPadding * 2 + 'px';
1746      } //@ts-ignore
1747      if (rowObject.data.hasNext) {
1748        let btn = this.createBtn(rowObject); // @ts-ignore
1749        firstElement.title = rowObject.data.objectName; // @ts-ignore
1750        firstElement.insertBefore(btn, firstElement.firstChild); // @ts-ignore
1751        firstElement.style.paddingLeft = iconWidth * rowObject.depth + 'px';
1752      }
1753      this.jsMemoryHandler(rowObject, firstElement); //@ts-ignore
1754      if (rowObject.data.rowName === 'cpu-profiler') {
1755        this.createTextColor(rowObject, firstElement);
1756      } // @ts-ignore
1757      firstElement.onmouseup = (e: MouseEvent): void => {
1758        this.dispatchRowClickEvent(rowObject, [firstElement, element], e);
1759        e.stopPropagation();
1760      }; // @ts-ignore
1761      firstElement.style.transform = `translateY(${rowObject.top - this.tableElement!.scrollTop}px)`; //@ts-ignore
1762      if (rowObject.data.isSelected !== undefined) {
1763        //@ts-ignore
1764        this.setSelectedRow(rowObject.data.isSelected, [firstElement]);
1765      } else {
1766        this.setSelectedRow(false, [firstElement]);
1767      }
1768    }
1769  }
1770
1771  setSelectedRow(isSelected: boolean, rows: unknown[]): void {
1772    if (isSelected) {
1773      rows.forEach((row) => {
1774        // @ts-ignore
1775        if (row.classList) {
1776          // @ts-ignore
1777          if (row.classList.contains('mouse-in')) {
1778            // @ts-ignore
1779            row.classList.remove('mouse-in');
1780          } // @ts-ignore
1781          row.classList.add('mouse-select');
1782        }
1783      });
1784    } else {
1785      rows.forEach((row) => {
1786        // @ts-ignore
1787        row.classList && row.classList.remove('mouse-select');
1788      });
1789    }
1790  }
1791
1792  setMouseIn(isMouseIn: boolean, rows: unknown[]): void {
1793    if (isMouseIn) {
1794      rows.forEach((row) => {
1795        // @ts-ignore
1796        row.classList.add('mouse-in');
1797      });
1798    } else {
1799      rows.forEach((row) => {
1800        // @ts-ignore
1801        row.classList.remove('mouse-in');
1802      });
1803    }
1804  }
1805
1806  scrollToData(data: unknown): void {
1807    if (this.isRecycleList) {
1808      if (this.recycleDs.length > 0) {
1809        let filter = this.recycleDs.filter((item) => {
1810          // @ts-ignore
1811          return item.data === data;
1812        });
1813        if (filter.length > 0) {
1814          // @ts-ignore
1815          this.tableElement!.scrollTop = filter[0].top;
1816        }
1817        this.setCurrentSelection(data);
1818      }
1819    } else {
1820      if (this.normalDs.length > 0) {
1821        let filter = this.normalDs.filter((item) => {
1822          // @ts-ignore
1823          return item.data === data;
1824        });
1825        if (filter.length > 0) {
1826          // @ts-ignore
1827          this.tableElement!.scrollTop = filter[0].top;
1828        }
1829      }
1830    }
1831  }
1832
1833  expandList(datasource: unknown[]): void {
1834    let filter = this.recycleDs.filter((item) => {
1835      // @ts-ignore
1836      return datasource.indexOf(item.data) !== -1;
1837    });
1838    if (filter.length > 0) {
1839      filter.forEach((item) => {
1840        // @ts-ignore
1841        item.expanded = true; // @ts-ignore
1842        item.rowHidden = false;
1843      });
1844    }
1845    this.reMeauseHeight();
1846  }
1847
1848  clearAllSelection(rowObjectData: unknown): void {
1849    if (this.isRecycleList) {
1850      this.recycleDs.forEach((item) => {
1851        // @ts-ignore
1852        if (item.data !== rowObjectData && item.data.isSelected) {
1853          // @ts-ignore
1854          item.data.isSelected = false;
1855        }
1856      });
1857      this.setSelectedRow(false, this.currentTreeDivList);
1858      this.setSelectedRow(false, this.currentRecycleList);
1859    } else {
1860      this.dataSource.forEach((item) => {
1861        // @ts-ignore
1862        if (item !== rowObjectData && item.isSelected) {
1863          // @ts-ignore
1864          item.isSelected = false;
1865        }
1866      });
1867      this.setSelectedRow(false, this.normalDs);
1868    }
1869  }
1870
1871  clearAllHover(rowObjectData: unknown): void {
1872    if (this.isRecycleList) {
1873      this.recycleDs.forEach((item) => {
1874        // @ts-ignore
1875        if (item.data !== rowObjectData && item.data.isHover) {
1876          // @ts-ignore
1877          item.data.isHover = false;
1878        }
1879      });
1880      this.setMouseIn(false, this.currentTreeDivList);
1881      this.setMouseIn(false, this.currentRecycleList);
1882    } else {
1883      this.dataSource.forEach((item) => {
1884        // @ts-ignore
1885        if (item !== rowObjectData && item.isHover) {
1886          // @ts-ignore
1887          item.isHover = false;
1888        }
1889      });
1890      this.setMouseIn(false, this.normalDs);
1891    }
1892  }
1893
1894  mouseOut(): void {
1895    if (this.isRecycleList) {
1896      // @ts-ignore
1897      this.recycleDs.forEach((item) => (item.data.isHover = false));
1898      this.setMouseIn(false, this.currentTreeDivList);
1899      this.setMouseIn(false, this.currentRecycleList);
1900    } else {
1901      // @ts-ignore
1902      this.dataSource.forEach((item) => (item.isHover = false));
1903      this.setMouseIn(false, this.normalDs);
1904    }
1905    this.dispatchEvent(
1906      new CustomEvent('row-hover', {
1907        detail: {
1908          data: undefined,
1909        },
1910        composed: true,
1911      })
1912    );
1913  }
1914
1915  setCurrentSelection(selectionData: unknown): void {
1916    if (this.isRecycleList) {
1917      // @ts-ignore
1918      if (selectionData.isSelected !== undefined) {
1919        this.currentTreeDivList.forEach((itemEl) => {
1920          // @ts-ignore
1921          if ((itemEl as unknown).data === selectionData) {
1922            // @ts-ignore
1923            this.setSelectedRow(selectionData.isSelected, [itemEl]);
1924          }
1925        });
1926        this.currentRecycleList.forEach((recycleItem) => {
1927          // @ts-ignore
1928          if ((recycleItem as unknown).data === selectionData) {
1929            // @ts-ignore
1930            this.setSelectedRow(selectionData.isSelected, [recycleItem]);
1931          }
1932        });
1933      }
1934    } else {
1935      // @ts-ignore
1936      if (selectionData.isSelected !== undefined) {
1937        this.normalDs.forEach((item) => {
1938          // @ts-ignore
1939          if ((item as unknown).data === selectionData) {
1940            // @ts-ignore
1941            this.setSelectedRow(selectionData.isSelected, [item]);
1942          }
1943        });
1944      }
1945    }
1946  }
1947
1948  setCurrentHover(data: unknown): void {
1949    if (this.isRecycleList) {
1950      this.setMouseIn(false, this.currentTreeDivList);
1951      this.setMouseIn(false, this.currentRecycleList); // @ts-ignore
1952      if (data.isHover !== undefined) {
1953        this.currentTreeDivList.forEach((hoverItem) => {
1954          // @ts-ignore
1955          if ((hoverItem as unknown).data === data) {
1956            // @ts-ignore
1957            this.setMouseIn(data.isHover, [hoverItem]);
1958          }
1959        });
1960        this.currentRecycleList.forEach((hoverItem) => {
1961          // @ts-ignore
1962          if ((hoverItem as unknown).data === data) {
1963            // @ts-ignore
1964            this.setMouseIn(data.isHover, [hoverItem]);
1965          }
1966        });
1967      }
1968    } else {
1969      this.setMouseIn(false, this.normalDs); // @ts-ignore
1970      if (data.isHover !== undefined) {
1971        this.normalDs.forEach((item): void => {
1972          // @ts-ignore
1973          if ((item as unknown).data === data) {
1974            // @ts-ignore
1975            this.setMouseIn(data.isHover, [item]);
1976          }
1977        });
1978      }
1979    }
1980  }
1981
1982  dispatchRowClickEventIcon(rowData: unknown, elements: unknown[]): void {
1983    this.dispatchEvent(
1984      new CustomEvent('icon-click', {
1985        detail: {
1986          // @ts-ignore
1987          ...rowData.data,
1988          // @ts-ignore
1989          data: rowData.data,
1990          callBack: (isSelected: boolean): void => {
1991            //是否爲单选
1992            if (isSelected) {
1993              // @ts-ignore
1994              this.clearAllSelection(rowData.data);
1995            } // @ts-ignore
1996            this.setSelectedRow(rowData.data.isSelected, elements);
1997          },
1998        },
1999        composed: true,
2000      })
2001    );
2002  }
2003
2004  dispatchRowClickEvent(rowObject: unknown, elements: unknown[], event: MouseEvent): void {
2005    this.dispatchEvent(
2006      new CustomEvent('row-click', {
2007        detail: {
2008          button: event.button, // @ts-ignore
2009          ...rowObject.data, // @ts-ignore
2010          data: rowObject.data,
2011          callBack: (isSelected: boolean): void => {
2012            //是否爲单选
2013            if (isSelected) {
2014              // @ts-ignore
2015              this.clearAllSelection(rowObject.data);
2016            } // @ts-ignore
2017            this.setSelectedRow(rowObject.data.isSelected, elements);
2018          },
2019        },
2020        composed: true,
2021      })
2022    );
2023    event.stopPropagation();
2024  }
2025
2026  dispatchRowHoverEvent(rowObject: unknown, elements: unknown[]): void {
2027    this.dispatchEvent(
2028      new CustomEvent('row-hover', {
2029        detail: {
2030          // @ts-ignore
2031          data: rowObject.data,
2032          callBack: (): void => {
2033            // @ts-ignore
2034            this.clearAllHover(rowObject.data); // @ts-ignore
2035            this.setMouseIn(rowObject.data.isHover, elements);
2036          },
2037        },
2038        composed: true,
2039      })
2040    );
2041  }
2042
2043  setHighLight(isSearch: boolean, element: unknown): void {
2044    if (isSearch) {
2045      // @ts-ignore
2046      element.setAttribute('high-light', '');
2047    } else {
2048      // @ts-ignore
2049      element.removeAttribute('high-light');
2050    }
2051  }
2052
2053  createTextColor(rowData: unknown, divElement: unknown): void {
2054    let nodeText = document.createElement('text');
2055    nodeText.classList.add('functionName'); // @ts-ignore
2056    nodeText.textContent = rowData.data.name; // @ts-ignore
2057    divElement.append(nodeText); // @ts-ignore
2058    if (rowData.data.scriptName !== 'unknown') {
2059      let scriptText = document.createElement('text');
2060      scriptText.classList.add('scriptName'); // @ts-ignore
2061      scriptText.textContent = rowData.data.scriptName; // @ts-ignore
2062      divElement.append(scriptText);
2063      scriptText.style.color = '#a1a1a1';
2064    } // @ts-ignore
2065    divElement.title = rowData.data.symbolName;
2066  }
2067
2068  jsMemoryHandler(rowData: unknown, td: unknown): void {
2069    // @ts-ignore
2070    if (rowData.data.rowName === 'js-memory') {
2071      let nodeText = document.createElement('text');
2072      nodeText.classList.add('nodeName'); // @ts-ignore
2073      nodeText.textContent = rowData.data.nodeName; // @ts-ignore
2074      td.append(nodeText);
2075      let countText = document.createElement('text');
2076      countText.classList.add('countName'); // @ts-ignore
2077      countText.textContent = rowData.data.count; // @ts-ignore
2078      td.append(countText);
2079      let nodeIdText = document.createElement('text');
2080      nodeIdText.classList.add('nodeIdText'); // @ts-ignore
2081      nodeIdText.textContent = rowData.data.nodeId; // @ts-ignore
2082      td.append(nodeIdText); // @ts-ignore
2083      if (rowData.data.edgeName !== '') {
2084        let edgeNameText = document.createElement('text');
2085        edgeNameText.classList.add('edgeNameText'); // @ts-ignore
2086        edgeNameText.textContent = rowData.data.edgeName; // @ts-ignore
2087        td.insertBefore(edgeNameText, nodeText);
2088        let span = document.createElement('span');
2089        span.classList.add('span'); // @ts-ignore
2090        if (rowData.data.type === ConstructorType.RetainersType) {
2091          // @ts-ignore
2092          span.textContent = '\xa0' + 'in' + '\xa0'; // @ts-ignore
2093          nodeIdText.textContent = ` @${rowData.data.id}`;
2094        } else {
2095          span.textContent = '\xa0' + '::' + '\xa0';
2096        }
2097        edgeNameText.append(span);
2098      }
2099      if (
2100        // @ts-ignore
2101        (rowData.data.nodeType === NodeType.STRING || // @ts-ignore
2102          rowData.data.nodeType === NodeType.CONCATENATED_STRING || // @ts-ignore
2103          rowData.data.nodeType === NodeType.SLICED_STRING) && // @ts-ignore
2104        rowData.data.type !== ConstructorType.ClassType
2105      ) {
2106        nodeText.style.color = '#d53d3d'; // @ts-ignore
2107        nodeText.textContent = '"' + rowData.data.nodeName + '"';
2108      } // @ts-ignore
2109      td.title = rowData.data.objectName;
2110    }
2111  }
2112}
2113
2114// 表格默认是展开还是收起的
2115export enum TableMode {
2116  Expand, // 默认展开
2117  Retract, // 默认收起
2118}
2119
2120// 重绘的表格是要全部展开,全部收起,还是一层一层手动打开
2121export enum RedrawTreeForm {
2122  Expand, // 一键展开
2123  Retract, // 一键收起
2124  Default, //点击加号,逐层展开
2125}
2126