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