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