• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../../../../base-ui/BaseElement';
17import { type LitTabs } from '../../../../base-ui/tabs/lit-tabs';
18import { LitTabpane } from '../../../../base-ui/tabs/lit-tabpane';
19import {
20  BoxJumpParam,
21  SelectionParam,
22  SysCallBoxJumpParam,
23  SliceBoxJumpParam,
24  PerfSampleBoxJumpParam
25} from '../../../bean/BoxSelection';
26import { type TabPaneCurrentSelection } from '../sheet/TabPaneCurrentSelection';
27import { type TabPaneFlag } from '../timer-shaft/TabPaneFlag';
28import { type Flag } from '../timer-shaft/Flag';
29import { type WakeupBean } from '../../../bean/WakeupBean';
30import { type LitIcon } from '../../../../base-ui/icon/LitIcon';
31import { tabConfig } from './TraceSheetConfig';
32import { type TabPaneBoxChild } from '../sheet/cpu/TabPaneBoxChild';
33import { type CpuStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCPU';
34import { CpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerFreq';
35import { CpuFreqLimitsStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits';
36import { type ThreadStruct } from '../../../database/ui-worker/ProcedureWorkerThread';
37import { type ThreadSysCallStruct } from '../../../database/ui-worker/ProcedureWorkerThreadSysCall';
38import { type FuncStruct } from '../../../database/ui-worker/ProcedureWorkerFunc';
39import { ProcessMemStruct } from '../../../database/ui-worker/ProcedureWorkerMem';
40import { CpuStateStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuState';
41import { type HangStruct } from '../../../database/ui-worker/ProcedureWorkerHang';
42import { type ClockStruct } from '../../../database/ui-worker/ProcedureWorkerClock';
43import { type DmaFenceStruct } from '../../../database/ui-worker/ProcedureWorkerDmaFence';
44import { type XpowerStruct } from '../../../database/ui-worker/ProcedureWorkerXpower';
45import { type IrqStruct } from '../../../database/ui-worker/ProcedureWorkerIrq';
46import { type JankStruct } from '../../../database/ui-worker/ProcedureWorkerJank';
47import { type HeapStruct } from '../../../database/ui-worker/ProcedureWorkerHeap';
48import { type LitTable } from '../../../../base-ui/table/lit-table';
49import { threadPool } from '../../../database/SqlLite';
50import { type HeapSnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerHeapSnapshot';
51import { type TabPaneNMStatisticAnalysis } from '../sheet/native-memory/TabPaneNMStatisticAnalysis';
52import { type TabPaneCurrent } from '../sheet/TabPaneCurrent';
53import { type SlicesTime } from '../timer-shaft/SportRuler';
54import { type AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup';
55import { type AllAppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAllAppStartup';
56import { type SoStruct } from '../../../database/ui-worker/ProcedureWorkerSoInit';
57import { type FrameAnimationStruct } from '../../../database/ui-worker/ProcedureWorkerFrameAnimation';
58import { type TraceRow } from './TraceRow';
59import { type FrameDynamicStruct } from '../../../database/ui-worker/ProcedureWorkerFrameDynamic';
60import { type TabPaneFrameDynamic } from '../sheet/frame/TabPaneFrameDynamic';
61import { type FrameSpacingStruct } from '../../../database/ui-worker/ProcedureWorkerFrameSpacing';
62import { type TabFrameSpacing } from '../sheet/frame/TabFrameSpacing';
63import { type JsCpuProfilerChartFrame } from '../../../bean/JsStruct';
64import { type TabPaneComparison } from '../sheet/ark-ts/TabPaneComparison';
65import { type TabPaneSummary } from '../sheet/ark-ts/TabPaneSummary';
66import { type TabPaneGpuClickSelect } from '../sheet/gpu/TabPaneGpuClickSelect';
67import { type TabPanePurgTotalSelection } from '../sheet/ability/TabPanePurgTotalSelection';
68import { type TabPanePurgPinSelection } from '../sheet/ability/TabPanePurgPinSelection';
69import { type TabPaneVmTrackerShmSelection } from '../sheet/vmtracker/TabPaneVmTrackerShmSelection';
70import { type TabPaneSmapsStatistics } from '../sheet/smaps/TabPaneSmapsStatistics';
71import { type TabPaneSmapsComparison } from '../sheet/smaps/TabPaneSmapsComparison';
72import { type SnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerSnapshot';
73import { type TabPaneDmaSelectAbility } from '../sheet/ability/TabPaneDmaSelectAbility';
74import { type TabPaneGpuMemorySelectAbility } from '../sheet/ability/TabPaneGpuMemorySelectAbility';
75import { type TabPaneDmaSelectVmTracker } from '../sheet/vmtracker/TabPaneDmaSelectVmTracker';
76import { type TabPanePurgTotalComparisonAbility } from '../sheet/ability/TabPanePurgTotalComparisonAbility';
77import { type TabPanePurgPinComparisonAbility } from '../sheet/ability/TabPanePurgPinComparisonAbility';
78import { type TabPanePurgTotalComparisonVM } from '../sheet/vmtracker/TabPanePurgTotalComparisonVM';
79import { type TabPanePurgPinComparisonVM } from '../sheet/vmtracker/TabPanePurgPinComparisonVM';
80import { type TabPaneDmaAbilityComparison } from '../sheet/ability/TabPaneDmaAbilityComparison';
81import { type TabPaneGpuMemoryComparison } from '../sheet/ability/TabPaneGpuMemoryComparison';
82import { type TabPaneDmaVmTrackerComparison } from '../sheet/vmtracker/TabPaneDmaVmTrackerComparison';
83import { type TabPaneGpuMemorySelectVmTracker } from '../sheet/vmtracker/TabPaneGpuMemorySelectVmTracker';
84import { type TabPaneGpuMemoryVmTrackerComparison } from '../sheet/vmtracker/TabPaneGpuMemoryVmTrackerComparison';
85import { type TabPaneVmTrackerShmComparison } from '../sheet/vmtracker/TabPaneVmTrackerShmComparison';
86import { type TabPaneJsCpuStatistics } from '../sheet/ark-ts/TabPaneJsCpuStatistics';
87import { type TabPaneGpuClickSelectComparison } from '../sheet/gpu/TabPaneGpuClickSelectComparison';
88import { Utils } from './Utils';
89import { TabPaneHiLogs } from '../sheet/hilog/TabPaneHiLogs';
90import { TabPaneGpuResourceVmTracker } from '../sheet/vmtracker/TabPaneGpuResourceVmTracker';
91import { type LitPageTable } from '../../../../base-ui/table/LitPageTable';
92import '../../../../base-ui/popover/LitPopoverV';
93import { LitPopover } from '../../../../base-ui/popover/LitPopoverV';
94import { LitTree, TreeItemData } from '../../../../base-ui/tree/LitTree';
95import { SampleStruct } from '../../../database/ui-worker/ProcedureWorkerBpftrace';
96import { TabPaneUserPlugin } from '../sheet/userPlugin/TabPaneUserPlugin';
97import { TabPaneSampleInstruction } from '../sheet/bpftrace/TabPaneSampleInstruction';
98import { TabPaneFreqStatesDataCut } from '../sheet/states/TabPaneFreqStatesDataCut';
99import { TabPaneDataCut } from '../sheet/TabPaneDataCut';
100import { SpSystemTrace } from '../../SpSystemTrace';
101import { PerfToolStruct } from '../../../database/ui-worker/ProcedureWorkerPerfTool';
102import { GpuCounterStruct } from '../../../database/ui-worker/ProcedureWorkerGpuCounter';
103import { TabPaneGpuCounter } from '../sheet/gpu-counter/TabPaneGpuCounter';
104import { TabPaneSliceChild } from '../sheet/process/TabPaneSliceChild';
105import { TabPerfFuncAsm } from '../sheet/hiperf/TabPerfFuncAsm';
106import { XpowerStatisticStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerStatistic';
107import { XpowerAppDetailStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerAppDetail';
108import { XpowerWifiStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerWifi';
109import { TabPaneXpowerStatisticCurrentData } from '../sheet/xpower/TabPaneXpowerStatisticCurrentData';
110import { XpowerThreadInfoStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerThreadInfo';
111import { TabPaneXpowerThreadInfoSelection } from '../sheet/xpower/TabPaneXpowerThreadInfoSelection';
112import { TabPaneXpowerGpuFreqSelection } from '../sheet/xpower/TabPaneXpowerGpuFreqSelection';
113import { XpowerGpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerGpuFreq';
114import { WebSocketManager } from '../../../../webSocket/WebSocketManager';
115import { Constants, TypeConstants } from '../../../../webSocket/Constants';
116import { PerfFunctionAsmParam } from '../../../bean/PerfAnalysis';
117import { info, error } from '../../../../log/Log';
118import { XpowerThreadCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerThreadCount';
119import { XpowerGpuFreqCountStruct } from '../../../database/ui-worker/ProcedureWorkerXpowerGpuFreqCount';
120import { TabPaneSysCallChild } from '../sheet/process/TabPaneSysCallChild';
121import { TabPanePerfSampleChild } from '../sheet/hiperf/TabPerfSampleChild';
122
123
124@element('trace-sheet')
125export class TraceSheet extends BaseElement {
126  systemLogFlag: Flag | undefined | null;
127  private litTabs: LitTabs | undefined | null;
128  private switchDiv: LitPopover | undefined | null;
129  private processTree: LitTree | undefined | null;
130  private importDiv: HTMLDivElement | undefined | null;
131  private symbolDiv: HTMLDivElement | undefined | null;
132  private exportBt: LitIcon | undefined | null;
133  private nav: HTMLDivElement | undefined | null;
134  private tabs: HTMLDivElement | undefined | null;
135  private navRoot: HTMLDivElement | null | undefined;
136  private search: HTMLDivElement | undefined | null;
137  private timerShaft: HTMLDivElement | undefined | null;
138  private spacer: HTMLDivElement | undefined | null;
139  private rowsPaneEL: HTMLDivElement | undefined | null;
140  private selection: SelectionParam | undefined | null;
141  private currentPaneID: string = 'current-selection';
142  private fragment: DocumentFragment | undefined;
143  private lastSelectIPid: number = -1;
144  private lastProcessSet: Set<number> = new Set<number>();
145  private optionsDiv: LitPopover | undefined | null;
146  private optionsSettingTree: LitTree | undefined | null;
147  private tabPaneHeight: string = '';
148  private spsystemTrace: SpSystemTrace | undefined;
149  private isDragging = true;
150  private REQ_BUF_SIZE = 1024 * 1024;
151  private loadSoComplete = false;
152
153  static get observedAttributes(): string[] {
154    return ['mode'];
155  }
156
157  buildTabs(litTabs: LitTabs | undefined | null): void {
158    this.fragment = document.createDocumentFragment(); // @ts-ignore
159    Reflect.ownKeys(tabConfig).forEach((key, index): void => {
160      let pane = new LitTabpane();
161      pane.id = key.toString();
162      pane.className = 'tabHeight'; // @ts-ignore
163      pane.tab = tabConfig[key].title;
164      pane.hidden = true; // @ts-ignore
165      pane.key = `${tabConfig[key].key || index}`; // @ts-ignore
166      let cls = tabConfig[key].type;
167      // @ts-ignore
168      let node = new cls();
169      pane.append(node);
170      this.fragment?.appendChild(pane);
171    });
172    litTabs!.appendChild(this.fragment);
173  }
174
175  displayTab<T>(...names: string[]): T {
176    this.setMode('max');
177    this.showOptionsBt(this.selection);
178    this.showUploadSoBt(this.selection);
179    this.showSwitchProcessBt(this.selection);
180    this.shadowRoot
181      ?.querySelectorAll<LitTabpane>('#tabs lit-tabpane')
182      .forEach((it) => (it.hidden = !names.some((k) => k === it.id)));
183    let litTabpane = this.shadowRoot?.querySelector<LitTabpane>(`#tabs lit-tabpane[id='${names[0]}']`);
184    if (names[0] === 'current-selection') {
185      this.exportBt!.style.display = 'none';
186    } else {
187      this.exportBt!.style.display = 'flex';
188    }
189    this.shadowRoot?.querySelector<LitTabs>('#tabs')?.activePane(litTabpane!.key);
190    return litTabpane!.children.item(0) as unknown as T;
191  }
192
193  getComponentByID<T>(id: string): T {
194    return this.getPaneByID(id)?.children.item(0) as unknown as T;
195  }
196
197  getPaneByID(id: string): LitTabpane {
198    return this.shadowRoot!.querySelector(`#${id}`)!;
199  }
200
201  initElements(): void {
202    this.spsystemTrace = document.querySelector("body > sp-application")?.shadowRoot?.querySelector("#sp-system-trace") as SpSystemTrace;
203    this.litTabs = this.shadowRoot?.querySelector('#tabs');
204    this.litTabs!.addEventListener('contextmenu', (e): void => {
205      e.preventDefault();
206    });
207    this.importDiv = this.shadowRoot?.querySelector('#import_div');
208    this.symbolDiv = this.shadowRoot?.querySelector('#symbol_div');
209    this.switchDiv = this.shadowRoot?.querySelector('#select-process');
210    this.processTree = this.shadowRoot?.querySelector('#processTree');
211    this.optionsDiv = this.shadowRoot?.querySelector('#options');
212    this.optionsSettingTree = this.shadowRoot?.querySelector('#optionsSettingTree');
213    this.optionsSettingTree!.onChange = (e: unknown): void => {
214      const select = this.optionsSettingTree!.getCheckdKeys();
215      document.dispatchEvent(
216        new CustomEvent('sample-popver-change', {
217          detail: {
218            select: select[0],
219          },
220        })
221      );
222    };
223    this.processTree!.onChange = (e: unknown): void => {
224      const select = this.processTree!.getCheckdKeys();
225      const selectIPid = Number(select[0]);
226      this.switchDiv!.visible = 'false';
227      this.updateRangeSelect(selectIPid);
228      this.lastSelectIPid = selectIPid;
229    };
230    this.buildTabs(this.litTabs); // @ts-ignore
231    this.litTabs!.onTabClick = (e: unknown): void => this.loadTabPaneData(e.detail.key);
232    this.tableCloseHandler();
233    this.rowClickEvent();
234    this.tdClickEvent();
235  }
236  private rowClickEvent(): void {
237    // @ts-ignore
238    this.getComponentByID<unknown>('box-perf-analysis')?.addEventListener('row-click', (evt: MouseEvent) => {
239      this.perfAnalysisListener(evt);
240    });
241    // @ts-ignore
242    this.getComponentByID<unknown>('box-perf-analysis')?.addFunctionRowClickEventListener(this.functionAnalysisListener.bind(this));
243    // @ts-ignore
244    this.getComponentByID<unknown>('box-native-statistic-analysis')?.addEventListener('row-click', (e: MouseEvent) => {
245      this.nativeAnalysisListener(e);
246    });
247    // @ts-ignore
248    this.getComponentByID<unknown>('box-io-tier-statistics-analysis')?.addEventListener(
249      'row-click',
250      (evt: MouseEvent) => {
251        // @ts-ignore
252        if (evt.detail.button === 2 && evt.detail.tableName) {
253          let pane = this.getPaneByID('box-io-calltree');
254          this.litTabs!.activeByKey(pane.key);
255        }
256      }
257    );
258    // @ts-ignore
259    this.getComponentByID<unknown>('box-virtual-memory-statistics-analysis')?.addEventListener(
260      'row-click',
261      (evt: MouseEvent) => {
262        // @ts-ignore
263        if (evt.detail.button === 2 && evt.detail.tableName) {
264          let pane = this.getPaneByID('box-vm-calltree');
265          this.litTabs!.activeByKey(pane.key);
266        }
267      }
268    );
269    // @ts-ignore
270    this.getComponentByID<unknown>('box-file-system-statistics-analysis')?.addEventListener(
271      'row-click',
272      (evt: MouseEvent) => {
273        // @ts-ignore
274        if (evt.detail.button === 2 && evt.detail.tableName) {
275          let pane = this.getPaneByID('box-file-system-calltree');
276          this.litTabs!.activeByKey(pane.key);
277        }
278      }
279    );
280    // @ts-ignore
281    this.getComponentByID<unknown>('box-native-statstics')?.addEventListener('row-click', (e: unknown) => {
282      this.nativeStatsticsListener(e);
283    });
284    // @ts-ignore
285    this.getComponentByID<unknown>('box-virtual-memory-statistics')?.addEventListener('row-click', (e: unknown) => {
286      this.virtualMemoryListener(e);
287    });
288    // @ts-ignore
289    this.getComponentByID<unknown>('box-io-tier-statistics')?.addEventListener('row-click', (e: unknown) => {
290      this.ioTierListener(e);
291    });
292    // @ts-ignore
293    this.getComponentByID<unknown>('box-file-system-statistics')?.addEventListener('row-click', (e: unknown) => {
294      this.fileSystemListener(e);
295    });
296  }
297
298  private tdClickEvent(): void {
299    // @ts-ignore
300    this.getComponentByID<unknown>('box-spt')?.addEventListener('td-click', (evt: unknown) => {
301      this.tdClickHandler(evt, true);
302    });
303    // @ts-ignore
304    this.getComponentByID<unknown>('box-pts')?.addEventListener('td-click', (evt: unknown) => {
305      this.tdClickHandler(evt, true);
306    });
307    // @ts-ignore
308    this.getComponentByID<unknown>('box-thread-states')?.addEventListener('td-click', (evt: unknown) => {
309      this.tdClickHandler(evt);
310    });
311    // @ts-ignore
312    this.getComponentByID<unknown>('box-slices')?.addEventListener('td-click', (evt: unknown) => {
313      this.tdSliceClickHandler(evt);
314    });
315    // @ts-ignore
316    this.getComponentByID<unknown>('box-thread-syscall')?.addEventListener('td-click', (evt: unknown) => {
317      this.tdSysCallClickHandler(evt);
318    });
319    // @ts-ignore
320    this.getComponentByID<unknown>('box-perf-profile')?.addEventListener('td-click', (evt: unknown) => {
321      this.tdPerfSampleClickHandler(evt);
322    });
323  }
324
325  private perfAnalysisListener(evt: MouseEvent): void {
326    // @ts-ignore
327    if (evt.detail.button === 2 && evt.detail.pid) {
328      let pane = this.getPaneByID('box-perf-profile');
329      this.litTabs!.activeByKey(pane.key);
330    }
331  }
332
333  private functionAnalysisListener(evt: unknown, vaddrList: Array<unknown>): void {
334    // @ts-ignore
335    this.currentPaneID = 'box-perf-analysis';
336    //隐藏除了当前Tab页的其他Tab页
337    this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach(
338      (it)=>{
339        if(it.id === this.currentPaneID) {
340          it.hidden = false;
341        }
342      }
343    );
344    let asmPane = this.getPaneByID('tab-perf-func-asm'); //通过Id找到需要展示的Tab页
345    asmPane.closeable = true;
346    asmPane.hidden = false;
347    // @ts-ignore
348    asmPane.tab = evt.tableName; //设置Tab页标题
349    let param = new PerfFunctionAsmParam();
350    param.vaddrList = vaddrList;
351    // @ts-ignore
352    param.functionName = evt.tableName;
353    // @ts-ignore
354    param.totalCount = evt.count;
355    (asmPane.children.item(0) as TabPerfFuncAsm)!.data = param;
356    this.litTabs!.activeByKey(asmPane.key); //显示key值(sheetconfig里面对应的index是一个数字)对应的Tab页
357  }
358
359  private nativeAnalysisListener(e: MouseEvent): void {
360    //@ts-ignore
361    if (e.detail.button === 2 && e.detail.tableName) {
362      let pane = this.getPaneByID('box-native-calltree');
363      pane.hidden = false;
364      this.litTabs!.activeByKey(pane.key);
365    }
366  }
367
368  private nativeStatsticsListener(e: unknown): void {
369    // @ts-ignore
370    if (e.detail.button === 0) {
371      // @ts-ignore
372      this.selection!.statisticsSelectData = e.detail;
373      let pane = this.getPaneByID('box-native-memory');
374      this.litTabs?.activeByKey(pane.key);
375      // @ts-ignore
376      (pane.children.item(0) as unknown)!.fromStastics(this.selection);
377    }
378  }
379
380  private virtualMemoryListener(e: unknown): void {
381    // @ts-ignore
382    if (e.detail.button === 0) {
383      // @ts-ignore
384      this.selection!.fileSystemVMData = { path: e.detail.path };
385      let pane = this.getPaneByID('box-vm-events');
386      this.litTabs?.activeByKey(pane.key);
387      // @ts-ignore
388      if (e.detail.path) {
389        // @ts-ignore
390        (pane.children.item(0) as unknown)!.fromStastics(this.selection);
391      }
392    }
393  }
394
395  private ioTierListener(e: unknown): void {
396    // @ts-ignore
397    if (e.detail.button === 0) {
398      // @ts-ignore
399      this.selection!.fileSystemIoData = { path: e.detail.path };
400      let pane = this.getPaneByID('box-io-events');
401      this.litTabs?.activeByKey(pane.key);
402      // @ts-ignore
403      if (e.detail.path) {
404        // @ts-ignore
405        (pane.children.item(0) as unknown)!.fromStastics(this.selection);
406      }
407    }
408  }
409
410  private fileSystemListener(e: unknown): void {
411    // @ts-ignore
412    if (e.detail.button === 0) {
413      // @ts-ignore
414      this.selection!.fileSystemFsData = e.detail.data;
415      let pane = this.getPaneByID('box-file-system-event');
416      this.litTabs?.activeByKey(pane.key);
417      // @ts-ignore
418      if (e.detail.data) {
419        // @ts-ignore
420        (pane.children.item(0) as unknown)!.fromStastics(this.selection);
421      }
422    }
423  }
424
425  private tableCloseHandler(): void {
426    this.litTabs!.addEventListener('close-handler', () => {
427      // @ts-ignore
428      Reflect.ownKeys(tabConfig)
429        .reverse()
430        .forEach((id) => {
431          // @ts-ignore
432          let element = tabConfig[id];
433          let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`);
434          if (element.require) {
435            pane!.hidden = !element.require(this.selection!);
436          } else {
437            pane!.hidden = true;
438          }
439        });
440      this.litTabs?.activeByKey(`${this.getPaneByID(this.currentPaneID).key}`);
441    });
442  }
443
444  connectedCallback(): void {
445    this.nav = this.shadowRoot?.querySelector('#tabs')?.shadowRoot?.querySelector('.tab-nav-vessel');
446    this.tabs = this.shadowRoot?.querySelector('#tabs');
447    this.navRoot = this.shadowRoot?.querySelector('#tabs')?.shadowRoot?.querySelector('.nav-root');
448    this.search = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('div > div.search-vessel');
449    this.timerShaft = this.parentElement?.querySelector('.timer-shaft');
450    this.spacer = this.parentElement?.querySelector('.spacer');
451    this.rowsPaneEL = this.parentElement?.querySelector('.rows-pane');
452    let tabsOpenUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#max-btn');
453    let tabsPackUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#min-btn');
454    let borderTop: number = 1;
455    let initialHeight = { tabs: 'calc(30vh + 39px)', node: '30vh' };
456    this.initNavElements(tabsPackUp!, borderTop, initialHeight);
457    this.exportBt = this.shadowRoot?.querySelector<LitIcon>('#export-btn');
458    tabsOpenUp!.onclick = (): void => {
459      this.tabs!.style.height = `${window.innerHeight - this.search!.offsetHeight - this.timerShaft!.offsetHeight - borderTop
460        }px`;
461      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
462        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
463      litTabpane!.forEach((node: HTMLDivElement): void => {
464        node!.style.height = `${window.innerHeight -
465          this.search!.offsetHeight -
466          this.timerShaft!.offsetHeight -
467          this.navRoot!.offsetHeight -
468          borderTop
469          }px`;
470        initialHeight.node = node!.style.height;
471      });
472      initialHeight.tabs = this.tabs!.style.height;
473      tabsPackUp!.name = 'down';
474    };
475    tabsPackUp!.onclick = (): void => {
476      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
477        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
478      if (tabsPackUp!.name === 'down') {
479        let beforeHeight = this.clientHeight;
480        this.tabs!.style.height = `${this.navRoot!.offsetHeight}px`;
481        window.publish(window.SmartEvent.UI.ShowBottomTab, { show: 2, delta: beforeHeight - this.clientHeight });
482        litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = '0px'));
483        tabsPackUp!.name = 'up';
484        tabsPackUp!.title = 'Reset Tab'; // @ts-ignore
485        (window as unknown).isPackUpTable = true;
486      } else {
487        tabsPackUp!.name = 'down';
488        tabsPackUp!.title = 'Minimize Tab';
489        this.tabs!.style.height = initialHeight.tabs;
490        litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = initialHeight.node));
491      }
492    };
493    this.importClickEvent();
494    this.exportClickEvent();
495  }
496
497  private initNavElements(tabsPackUp: LitIcon, borderTop: number, initialHeight: { node: string; tabs: string }): void {
498    let that = this;
499    // 节点挂载时给Tab面板绑定鼠标按下事件
500    this.nav!.onmousedown = (event): void => {
501      this.isDragging = true;
502      // @ts-ignore
503      (window as unknown).isSheetMove = true;
504      // 获取所有标签页的节点数组
505      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
506        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
507      // 获取当前选中面板的key值,后续用来确定当前面板是哪一个。 对于用户来说,直观看到的只有当前面板,其他面板可以在拖动完成后一次性设置好新的高度
508      // @ts-ignore
509      let litTabNavKey: string = this.nav!.querySelector('.nav-item[data-selected=true]').dataset.key;
510      let currentPane: HTMLDivElement = this.shadowRoot?.querySelector(`#tabs > lit-tabpane[key="${litTabNavKey}"]`)!;
511      // 原函数 绑定鼠标移动事件,动态获取鼠标位置信息
512      this.navMouseMove(event, currentPane!, that, tabsPackUp, borderTop);
513      document.onmouseup = function (): void {
514        that.isDragging = true;
515        setTimeout(() => {
516          // @ts-ignore
517          (window as unknown).isSheetMove = false;
518        }, 100);
519        litTabpane!.forEach((node: HTMLDivElement): void => {
520          node!.style.height = that.tabPaneHeight;
521        });
522        if (that.tabPaneHeight !== '0px' && that.tabs!.style.height !== '') {
523          // 每次都会重新记录上次拖动完成后的面板高度,下次重新显示tab页时,会以上次拖动后的高度显示
524          initialHeight.node = that.tabPaneHeight;
525          initialHeight.tabs = that.tabs!.style.height;
526        }
527        // 将绑定的事件置空,需要时重新绑定
528        this.onmousemove = null;
529        this.onmouseup = null;
530      };
531    };
532    this.spsystemTrace?.addEventListener('abnormal-mouseup', () => {
533      this.isDragging = false;
534      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
535        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
536      setTimeout(() => {
537        // @ts-ignore
538        (window as unknown).isSheetMove = false;
539      }, 100);
540      litTabpane!.forEach((node: HTMLDivElement): void => {
541        node!.style.height = that.tabPaneHeight;
542      });
543      if (that.tabPaneHeight !== '0px' && that.tabs!.style.height !== '') {
544        initialHeight.node = that.tabPaneHeight;
545        initialHeight.tabs = that.tabs!.style.height;
546      }
547      this.onmousemove = null;
548      this.onmouseup = null;
549    })
550  }
551
552  private navMouseMove(
553    event: MouseEvent,
554    litTabpane: HTMLDivElement,
555    that: this,
556    tabsPackUp: LitIcon,
557    borderTop: number
558  ): void {
559    // 鼠标移动前记录此时的鼠标位置信息,后续根据新值与前次值作比对
560    let preY = event.pageY;
561    // 获取此时tab组件的偏移高度 需要包含水平滚动条的高度等
562    let preHeight = this.tabs!.offsetHeight;
563    // 获取此时整个滚动区域高度
564    let scrollH = that.rowsPaneEL!.scrollHeight;
565    // 获取此时滚动区域上方被隐藏的高度
566    let scrollT = that.rowsPaneEL!.scrollTop;
567    // 获取当前内容区高度加上上下内边距高度,即面板组件高度
568    let ch = that.clientHeight;
569    // 鼠标移动事件
570    document.onmousemove = function (event): void {
571      if (!that.isDragging) {
572        return;
573      }
574      // 移动前的面板高度 - 移动前后鼠标的坐标差值 = 新的面板高度
575      let newHeight: number = preHeight - (event.pageY - preY);
576      // that指向的是tracesheet节点 spacer为垫片  rowsPaneEl为泳道   tabs为tab页组件
577      // litTabpane为当前面板 navRoot为面板头部区的父级容器  search为顶部搜索区整个区域
578      // 这四个判断条件中,第一个尚未找到触发条件 后续和润和确认是否会触发
579      if (that.spacer!.offsetHeight > that.rowsPaneEL!.offsetHeight) {
580        that.tabs!.style.height = `${newHeight}px`;
581        litTabpane!.style.height = `${newHeight - that.navRoot!.offsetHeight}px`;
582        // 设置右上角面板大小化的箭头样式,面板在移动到最底部时,箭头向上,其余情况箭头向下
583        tabsPackUp!.name = 'down';
584      } else if (
585        // 只要没有移动到边界区域都会进入该条件
586        that.navRoot!.offsetHeight <= newHeight &&
587        that.search!.offsetHeight + that.timerShaft!.offsetHeight + borderTop + that.spacer!.offsetHeight <=
588        window.innerHeight - newHeight
589      ) {
590        that.tabs!.style.height = `${newHeight}px`;
591        litTabpane!.style.height = `${newHeight - that.navRoot!.offsetHeight}px`;
592        tabsPackUp!.name = 'down';
593      } else if (that.navRoot!.offsetHeight >= newHeight) {
594        // 该条件在面板置底时触发
595        that.tabs!.style.height = `${that.navRoot!.offsetHeight}px`;
596        litTabpane!.style.height = '0px';
597        tabsPackUp!.name = 'up';
598      } else if (
599        that.search!.offsetHeight + that.timerShaft!.offsetHeight + borderTop + that.spacer!.offsetHeight >=
600        window.innerHeight - newHeight
601      ) {
602        // 该条件在面板高度置顶时触发
603        that.tabs!.style.height = `${window.innerHeight -
604          that.search!.offsetHeight -
605          that.timerShaft!.offsetHeight -
606          borderTop -
607          that.spacer!.offsetHeight
608          }px`;
609        litTabpane!.style.height = `${window.innerHeight -
610          that.search!.offsetHeight -
611          that.timerShaft!.offsetHeight -
612          that.navRoot!.offsetHeight -
613          borderTop -
614          that.spacer!.offsetHeight
615          }px`;
616        tabsPackUp!.name = 'down';
617      }
618      that.tabPaneHeight = litTabpane!.style.height;
619      let currentSH = that.rowsPaneEL!.scrollHeight;
620      // 第一个判断条件尚未确定如何触发,currentSH与scrollH始终相等
621      if (currentSH > scrollH && currentSH > that.rowsPaneEL!.scrollTop + that.clientHeight) {
622        that.rowsPaneEL!.scrollTop = scrollT - (ch - that.clientHeight);
623      }
624    };
625  }
626
627  private importClickEvent(): void {
628    let importFileBt: HTMLInputElement | undefined | null =
629      this.shadowRoot?.querySelector<HTMLInputElement>('#import-file');
630    importFileBt!.addEventListener('change', (event): void => {
631      WebSocketManager.instance = null;
632      WebSocketManager.getInstance();
633      let timerOut = window.setTimeout(() => {
634        window.clearTimeout(timerOut);
635        let errorTipHtml = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('#sp-system-trace')
636        ?.shadowRoot?.querySelector('div > trace-sheet')?.shadowRoot?.querySelector('#box-perf-analysis > tabpane-perf-analysis')?.shadowRoot?.querySelector('#SO-err-tips');
637        let connected = document.querySelector('body > sp-application')
638        ?.shadowRoot?.querySelector('#main-menu')?.shadowRoot?.querySelector('div.bottom > div.extend_connect') as HTMLDivElement;
639        if (connected && connected.style.backgroundColor !== 'green') {
640          errorTipHtml!.innerHTML = 'Please check if the extension service is enabled and try again!';
641          importFileBt!.files = null;
642          importFileBt!.value = '';
643          return;
644        }
645        let files = importFileBt?.files;
646        if (files) {
647          let fileList: Array<File> = [];
648          for (let file of files) {
649            fileList.push(file);
650          }
651          if (fileList.length > 0) {
652            importFileBt!.disabled = true;
653            this.loadSoComplete = false;
654            window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Import So File' });
655            this.uploadSoOrAN(fileList).then(r => {
656            errorTipHtml!.innerHTML = '';
657            let soFileList = fileList.filter(item => !item.name.includes('.an'));
658            if (soFileList.length === 0) {
659              window.publish(window.SmartEvent.UI.UploadSOFile, {});
660              importFileBt!.disabled = false;
661              return;
662            }
663            threadPool.submit(
664              'upload-so',
665              '',
666              soFileList,
667              (res: unknown) => {
668                importFileBt!.disabled = false; // @ts-ignore
669                if (res.result === 'ok') {
670                  window.publish(window.SmartEvent.UI.UploadSOFile, {});
671                  this.loadSoComplete = true;
672                } else {
673                  // @ts-ignore
674                  const failedList = res.failedArray.join(',');
675                  window.publish(window.SmartEvent.UI.Error, `parse so file ${failedList} failed!`);
676                }
677              },
678              'upload-so'
679            )
680          }
681          ).finally(() => {
682            fileList.length = 0;
683          })
684        }
685      }
686      importFileBt!.files = null;
687      importFileBt!.value = '';
688      }, 500)
689    });
690    this.addClickEventToSoSymbolImport();
691  }
692
693  private addClickEventToSoSymbolImport(): void{
694    let symbolBt: HTMLInputElement | undefined | null =
695      this.shadowRoot?.querySelector<HTMLInputElement>('#so-symbolization');
696      symbolBt!.addEventListener('change', (event): void => {
697      let files = symbolBt?.files;
698      if (files) {
699        let fileList: Array<File> = [];
700        for (let file of files) {
701          fileList.push(file);
702        }
703        if (fileList.length > 0) {
704          symbolBt!.disabled = true;
705          window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Import So File' });
706          // @ts-ignore
707          document.querySelector('body > sp-application').shadowRoot.querySelector('#sp-system-trace').shadowRoot.querySelector('div > trace-sheet').shadowRoot.querySelector('#box-perf-analysis > tabpane-perf-analysis').shadowRoot.querySelector('#SO-err-tips')?.innerHTML = '';
708          let soFileList = fileList.filter(item => item.name.includes('.so'));
709          if (soFileList.length === 0) {
710            window.publish(window.SmartEvent.UI.UploadSOFile, {});
711            symbolBt!.disabled = false;
712            return;
713          }
714          threadPool.submit(
715            'upload-so',
716            '',
717            soFileList,
718            (res: unknown) => {
719              symbolBt!.disabled = false;
720              setTimeout(() => {
721                // @ts-ignore
722              if (res.result === 'ok') {
723                window.publish(window.SmartEvent.UI.UploadSOFile, {});
724              } else {
725                // @ts-ignore
726                const failedList = res.failedArray.join(',');
727                window.publish(window.SmartEvent.UI.Error, `parse so file ${failedList} failed!`);
728              }
729              }, 500);
730            },
731            'upload-so'
732          );
733        }
734        fileList.length = 0;
735      }
736      symbolBt!.files = null;
737      symbolBt!.value = '';
738    })
739  }
740
741  private async uploadSoOrAN(fileList: Array<File>): Promise<void> {
742    if (fileList) {
743      fileList.sort((a, b) => {
744        return b.size - a.size;
745      });
746      await this.uploadAllFiles(fileList);
747    }
748  }
749
750
751  // 上传文件
752  private async uploadAllFiles(fileList: Array<File>): Promise<void> {
753    // 创建一个副本,避免修改原始的 fileList
754    const filesToUpload = [...fileList];
755
756    for (let i = 0; i < filesToUpload.length; i++) {
757      const file = filesToUpload[i];
758      try {
759        await this.uploadSingleFile(file);
760        info(`File ${file.name} uploaded successfully.`);
761      } catch (err) {
762        error(`Failed to upload file: ${file.name}, error: `, err);
763      }
764    }
765    info(`All files have been uploaded.`);
766  }
767
768
769  private uploadSingleFile = async (file: File | null): Promise<void> => {
770    if (file) {
771      let writeSize = 0;
772      let wsInstance = WebSocketManager.getInstance();
773      const fileName = file.name;
774      let bufferIndex = 0;
775
776      // 定义一个 ACK 回调函数的等待机制
777      const waitForAck = (): Promise<void> => {
778        return new Promise<void>((resolve, reject) => {
779          wsInstance!.registerMessageListener(TypeConstants.DISASSEMBLY_TYPE, onAckReceived, () => { }, true);
780          // 定义超时定时器
781          const timeout = setTimeout(() => {
782            // 超时后注销回调并拒绝 Promise
783            wsInstance!.unregisterCallback(TypeConstants.DISASSEMBLY_TYPE, onAckReceived);
784            reject(new Error('等待 ACK 超时:文件 ${fileName},索引 ${bufferIndex})'));
785          }, 10000);
786          function onAckReceived(cmd: number, result: Uint8Array): void {
787            const decoder = new TextDecoder();
788            const jsonString = decoder.decode(result);
789            let jsonRes = JSON.parse(jsonString);
790            if (cmd === Constants.DISASSEMBLY_SAVE_BACK_CMD) {
791              if (jsonRes.fileName === fileName && jsonRes.bufferIndex === bufferIndex) {
792                wsInstance!.unregisterCallback(TypeConstants.DISASSEMBLY_TYPE, onAckReceived);
793                clearTimeout(timeout);
794                if (jsonRes.resultCode === 0) {
795                  bufferIndex++;
796                  // 当收到对应分片的 ACK 时,resolve Promise,继续上传下一个分片
797                  resolve();
798                } else {
799                  // 上传失败,拒绝 Promise 并返回
800                  reject(new Error(`Upload failed for file: ${fileName}, index: ${jsonRes.bufferIndex})`));
801                }
802              }
803            }
804          }
805        });
806      };
807
808      while (writeSize < file.size) {
809        let sliceLen = Math.min(file.size - writeSize, this.REQ_BUF_SIZE);
810        let blob: Blob | null = file.slice(writeSize, writeSize + sliceLen);
811        let buffer: ArrayBuffer | null = await blob.arrayBuffer();
812        let data: Uint8Array | null = new Uint8Array(buffer);
813		const dataObject = {
814          file_name: fileName,
815          buffer_index: bufferIndex,
816          buffer_size: sliceLen,
817          total_size: file.size,
818          is_last: writeSize + sliceLen >= file.size
819        };
820        const dataString = JSON.stringify(dataObject);
821		const jsonStr = `${dataString.length}|${dataString}`;
822        const textEncoder = new TextEncoder();
823        const jsonData = textEncoder.encode(jsonStr);
824        let mergeData: Uint8Array = new Uint8Array(jsonData.length + data.length);
825        mergeData.set(jsonData);
826        mergeData.set(data, jsonData.length);
827        wsInstance!.sendMessage(TypeConstants.DISASSEMBLY_TYPE, Constants.DISASSEMBLY_SAVE_CMD, mergeData);
828        writeSize += sliceLen;
829        // 等待服务器端确认当前分片的 ACK
830        await waitForAck();
831        data = null;
832        buffer = null;
833        blob = null;
834      }
835    }
836  };
837
838  private exportClickEvent(): void {
839    this.exportBt!.onclick = (): void => {
840      let currentTab = this.getTabpaneByKey(this.litTabs?.activekey!);
841      if (currentTab) {
842        let table1 = Array.from(
843          (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitPageTable>('lit-page-table') || []
844        );
845        let table2 = Array.from(
846          (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || []
847        );
848        let componentTopTable = undefined;
849        if (
850          (currentTab.firstChild as BaseElement).shadowRoot?.querySelector('#tb-counter') &&
851          ((currentTab.firstChild as BaseElement).shadowRoot?.querySelector('#tb-counter')?.firstChild as BaseElement)
852        ) {
853          componentTopTable = ((currentTab.firstChild as BaseElement).shadowRoot?.querySelector('#tb-counter')
854            ?.firstChild as BaseElement)!.shadowRoot?.querySelectorAll<LitTable>('lit-table');
855        }
856
857        let table3 = Array.from(componentTopTable || []);
858        let tables = [...table1, ...table2, ...table3];
859
860        for (let table of tables) {
861          if (!table.hasAttribute('hideDownload')) {
862            table.exportData();
863          }
864        }
865      }
866    };
867  }
868
869  getTabpaneByKey(key: string): LitTabpane | undefined {
870    let tabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []);
871    return tabs.find((it) => it.key === key);
872  }
873
874  initHtml(): string {
875    return `
876            <style>
877                :host([mode='hidden']){
878                    display: none;
879                }
880                :host{
881                    display: block;
882                    background-color: rebeccapurple;
883                }
884                .tabHeight{
885                    height: 30vh;
886                    background-color: var(--dark-background,#FFFFFF);
887                }
888                #check-popover[visible="true"] #check-des{
889                    color: #0A59F7;
890                }
891                .popover{
892                  color: var(--dark-color1,#4b5766);
893                  justify-content: center;
894                  align-items: center;
895                  margin-right: 10px;
896                  z-index: 2;
897                }
898                .option {
899                  display: flex;
900                  margin-right: 10px;
901                  cursor: pointer;
902                }
903            </style>
904            <div id="vessel" style="border-top: 1px solid var(--dark-border1,#D5D5D5);">
905                <lit-tabs id="tabs" position="top-left" activekey="1" mode="card" >
906                    <div class="option" slot="options">
907                      <lit-popover placement="bottom" class="popover" haveRadio="true" trigger="click" id="options">
908                        <div slot="content">
909                          <lit-tree id="optionsSettingTree" checkable="true"></lit-tree>
910                        </div>
911                        <lit-icon name="setting" size="21" id="setting"></lit-icon>
912                      </lit-popover>
913                    </div>
914                    <div slot="right" style="margin: 0 10px; color: var(--dark-icon,#606060);display: flex;align-items: center;">
915                        <lit-popover placement="bottomRight" class="popover" haveRadio="true" trigger="click" id="select-process">
916                              <div slot="content">
917                                <lit-tree id="processTree" checkable="true"></lit-tree>
918                              </div>
919                              <lit-icon name="setting" size="20" id="setting"></lit-icon>
920                        </lit-popover>
921                        <div title="So Symbolization" id="import_div" style="width: 20px;height: 20px;display: flex;flex-direction: row;margin-right: 10px">
922                            <input id="import-file" style="display: none;pointer-events: none" type="file" webkitdirectory>
923                            <label style="width: 20px;height: 20px;cursor: pointer;" for="import-file">
924                                <lit-icon id="import-btn" name="so-symbol" style="pointer-events: none" size="20">
925                                </lit-icon>
926                            </label>
927                        </div>
928                        <div title="Import SO" id="symbol_div" style="width: 20px;height: 20px;display: flex;flex-direction: row;margin-right: 10px">
929                            <input id="so-symbolization" style="display: none;pointer-events: none" type="file" webkitdirectory>
930                            <label style="width: 20px;height: 20px;cursor: pointer;" for="so-symbolization">
931                                <lit-icon id="import-btn" name="copy-csv" style="pointer-events: none" size="20">
932                                </lit-icon>
933                            </label>
934                        </div>
935                        <lit-icon title="Download Table" id="export-btn" name="import-so" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20">
936                        </lit-icon>
937                        <lit-icon title="Maximize Tab" id="max-btn" name="vertical-align-top" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20">
938                        </lit-icon>
939                        <lit-icon title="Minimize Tab" id="min-btn" name="down" style="font-weight: bold;cursor: pointer;" size="20">
940                        </lit-icon>
941                    </div>
942                </lit-tabs>
943            </div>`;
944  }
945  displayCurrent = (data: SlicesTime): void =>
946    this.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(data);
947  displayThreadData = (
948    data: ThreadStruct,
949    scrollCallback: ((e: ThreadStruct) => void) | undefined,
950    scrollWakeUp: (d: unknown) => void | undefined,
951    scrollPrio: (d: unknown) => void | undefined,
952    callback?: (data: Array<unknown>, str: string) => void
953  ): Promise<void> =>
954    this.displayTab<TabPaneCurrentSelection>('current-selection').setThreadData(
955      data,
956      // @ts-ignore
957      scrollCallback,
958      scrollWakeUp,
959      scrollPrio,
960      callback
961    );
962
963  displaySysCallData = (data: ThreadSysCallStruct) =>
964    this.displayTab<TabPaneCurrentSelection>('current-selection').setSysCallData(data);
965  displayMemData = (data: ProcessMemStruct): void =>
966    this.displayTab<TabPaneCurrentSelection>('current-selection').setMemData(data);
967  displayHangData = (data: HangStruct, sp: SpSystemTrace, scrollCallback: Function): Promise<void> =>
968    this.displayTab<TabPaneCurrentSelection>('current-selection').setHangData(data, sp, scrollCallback);
969  displayClockData = (data: ClockStruct): Promise<void> =>
970    this.displayTab<TabPaneCurrentSelection>('current-selection').setClockData(data);
971  displayDmaFenceData = (
972    data: DmaFenceStruct,
973    rowData: unknown
974  ): void => //展示tab页内容
975    // @ts-ignore
976    this.displayTab<TabPaneCurrentSelection>('current-selection').setDmaFenceData(data, rowData);
977  displayXpowerData = (data: XpowerStruct): Promise<void> =>
978    this.displayTab<TabPaneCurrentSelection>('current-selection').setXpowerData(data);
979  displayXpowerDisplayData = (data: XpowerAppDetailStruct): Promise<void> =>
980    this.displayTab<TabPaneCurrentSelection>('current-selection').setXpowerDisplayData(data);
981  displayXpowerWifiPacketsData = (data: XpowerWifiStruct): Promise<void> =>
982    this.displayTab<TabPaneCurrentSelection>('current-selection').setXpowerWifiPacketsData(data);
983  displayXpowerBytesWifiData = (data: XpowerWifiStruct): Promise<void> =>
984    this.displayTab<TabPaneCurrentSelection>('current-selection').setXpowerWifiBytesData(data);
985  displayXpowerStatisticData = (data: XpowerStatisticStruct): void =>
986    this.displayTab<TabPaneXpowerStatisticCurrentData>(
987      'box-xpower-statistic-current-data'
988    ).setXpowerStatisticCurrentData(data);
989  displayXpowerThreadInfoData = (dataList: Array<XpowerThreadInfoStruct>): void => {
990    this.displayTab<TabPaneXpowerThreadInfoSelection>('box-xpower-thread-info-selection').setThreadInfoData(dataList);
991  };
992  displayXpowerGpuFreqData = (dataList: Array<XpowerGpuFreqStruct>): void => {
993    this.displayTab<TabPaneXpowerGpuFreqSelection>('box-xpower-gpu-freq-selection').setGpuFreqData(dataList);
994  };
995  displayXpowerTreadCountData = (data: XpowerThreadCountStruct): Promise<void> =>
996    this.displayTab<TabPaneCurrentSelection>('current-selection').setXpowerTreadCountData(data);
997  displayXpowerGpuFreqCountData = (data: XpowerGpuFreqCountStruct): Promise<void> =>
998    this.displayTab<TabPaneCurrentSelection>('current-selection').setXpowerGpuFreqCountData(data);
999  displayPerfToolsData = (data: PerfToolStruct): void =>
1000    this.displayTab<TabPaneCurrentSelection>('current-selection').setPerfToolsData(data);
1001  displayIrqData = (data: IrqStruct): void =>
1002    this.displayTab<TabPaneCurrentSelection>('current-selection').setIrqData(data);
1003  displayStartupData = (data: AppStartupStruct, scrollCallback: Function, rowData: unknown): void =>
1004    this.displayTab<TabPaneCurrentSelection>('current-selection').setStartupData(data, scrollCallback, rowData);
1005  displayAllStartupData = (data: AllAppStartupStruct, scrollCallback: Function): void =>
1006    this.displayTab<TabPaneCurrentSelection>('current-selection').setAllStartupData(data, scrollCallback);
1007  displayStaticInitData = (data: SoStruct, scrollCallback: Function): void =>
1008    this.displayTab<TabPaneCurrentSelection>('current-selection').setStaticInitData(data, scrollCallback);
1009
1010  displayNativeHookData = (data: HeapStruct, rowType: string, ipid: number): void => {
1011    let val = new SelectionParam();
1012    val.nativeMemoryStatistic.push(rowType);
1013    val.nativeMemoryCurrentIPid = ipid;
1014    val.nativeMemory = [];
1015    val.leftNs = data.startTime! + data.dur!;
1016    val.rightNs = data.startTime! + data.dur! + 1;
1017    this.selection = val;
1018    this.displayTab<TabPaneNMStatisticAnalysis>('box-native-statistic-analysis', 'box-native-calltree').data = val;
1019    this.showUploadSoBt(val);
1020    this.showSwitchProcessBt(val);
1021  };
1022
1023  displayGpuSelectedData = (type: string, startTs: number, dataList: Array<SnapshotStruct>): void => {
1024    this.displayTab<TabPaneGpuClickSelectComparison>('gpu-click-select-comparison').getGpuClickDataByDB(
1025      type,
1026      startTs,
1027      dataList
1028    );
1029    let dataObject = { type: type, startTs: startTs };
1030    this.displayTab<TabPaneGpuClickSelect>('gpu-click-select', 'gpu-click-select-comparison').gpuClickData(dataObject);
1031  };
1032
1033  displayFuncData = (
1034    names: string[],
1035    threadName: string,
1036    data: FuncStruct,
1037    scrollCallback: Function,
1038    callback?: (data: Array<unknown>, str: string, binderTid: number) => void,
1039    distributedCallback?: (dataList: FuncStruct[]) => void
1040  ): Promise<void> =>
1041    this.displayTab<TabPaneCurrentSelection>(...names).setFunctionData(
1042      data,
1043      threadName,
1044      scrollCallback,
1045      callback,
1046      distributedCallback
1047    );
1048  displayCpuData = (
1049    data: CpuStruct,
1050    callback: ((data: WakeupBean | null) => void) | undefined = undefined,
1051    scrollCallback?: (data: CpuStruct) => void
1052  ): Promise<void> =>
1053    this.displayTab<TabPaneCurrentSelection>('current-selection').setCpuData(data, callback, scrollCallback);
1054  displayJankData = (
1055    data: JankStruct,
1056    callback: ((data: Array<unknown>) => void) | undefined = undefined,
1057    scrollCallback: ((e: JankStruct) => void) | undefined
1058    // @ts-ignore
1059  ): void => this.displayTab<TabPaneCurrentSelection>('current-selection').setJankData(data, callback, scrollCallback);
1060  displayShmData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => {
1061    this.displayTab<TabPaneVmTrackerShmComparison>('box-vmtracker-shm-comparison').setShmData(data, dataList);
1062    this.displayTab<TabPaneVmTrackerShmSelection>(
1063      'box-vmtracker-shm-selection',
1064      'box-vmtracker-shm-comparison'
1065    ).setShmData(data, dataList);
1066  };
1067  displaySmapsData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => {
1068    let val = new SelectionParam();
1069    val.smapsType = [];
1070    val.leftNs = data.startNs;
1071    this.selection = val;
1072    val.smapsType = [];
1073    this.displayTab<TabPaneSmapsComparison>('box-smaps-comparison').setData(val, dataList);
1074    this.displayTab<TabPaneSmapsStatistics>(
1075      'box-smaps-statistics',
1076      'box-smaps-sample',
1077      'box-smaps-comparison',
1078      'box-smaps-record'
1079    ).data = val;
1080  };
1081  displaySnapshotData = (
1082    data: HeapSnapshotStruct,
1083    dataListCache: Array<HeapSnapshotStruct>,
1084    scrollCallback?: (data: HeapSnapshotStruct, dataListCache: Array<HeapSnapshotStruct>) => void
1085  ): void => {
1086    if (dataListCache.length > 1) {
1087      this.displayTab<TabPaneSummary>('box-heap-summary', 'box-heap-comparison').setSnapshotData(
1088        data,
1089        dataListCache,
1090        scrollCallback
1091      );
1092      let nav = this.shadowRoot!.querySelector('#tabs')!.shadowRoot!.querySelector(
1093        '#nav > #nav-comparison'
1094      ) as HTMLDivElement;
1095      let tabPaneComparison = this.shadowRoot!.querySelector(
1096        '#box-heap-comparison > tabpane-comparison'
1097      ) as TabPaneComparison;
1098      nav!.onclick = (): void => {
1099        tabPaneComparison.initComparison(data, dataListCache);
1100      };
1101    } else {
1102      this.displayTab<TabPaneSummary>('box-heap-summary').setSnapshotData(data, dataListCache, scrollCallback);
1103    }
1104  };
1105  displayFlagData = (flagObj: Flag): void => this.displayTab<TabPaneFlag>('box-flag').setCurrentFlag(flagObj);
1106  displayFreqData = (): CpuFreqStruct | undefined =>
1107    (this.displayTab<TabPaneCurrentSelection>('box-freq').data = CpuFreqStruct.selectCpuFreqStruct);
1108  displayCpuStateData = (): CpuStateStruct | undefined =>
1109    (this.displayTab<TabPaneCurrentSelection>('cpu-state-click').data = CpuStateStruct.selectStateStruct);
1110  displayFreqLimitData = (): CpuFreqLimitsStruct | undefined =>
1111    (this.displayTab<TabPaneCurrentSelection>('box-freq-limit').data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct);
1112
1113  displayFrameAnimationData = (data: FrameAnimationStruct, scrollCallback: Function): Promise<void> =>
1114    this.displayTab<TabPaneCurrentSelection>('current-selection').setFrameAnimationData(data, scrollCallback);
1115  displayFrameDynamicData = (row: TraceRow<FrameDynamicStruct>, data: FrameDynamicStruct): void =>
1116    this.displayTab<TabPaneFrameDynamic>('box-frame-dynamic').buildDynamicTable([data], true);
1117  displayFrameSpacingData = (data: FrameSpacingStruct): void =>
1118    this.displayTab<TabFrameSpacing>('box-frames-spacing').setFrameSpacingData(data);
1119  displayJsProfilerData = (data: Array<JsCpuProfilerChartFrame>): void => {
1120    let val = new SelectionParam();
1121    val.jsCpuProfilerData = data;
1122    this.selection = val;
1123    this.displayTab<TabPaneJsCpuStatistics>(
1124      'box-js-Profiler-statistics',
1125      'box-js-Profiler-bottom-up',
1126      'box-js-Profiler-top-down'
1127    ).data = data;
1128  };
1129  displayPurgTotalAbilityData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => {
1130    data.type = 'ability';
1131    this.displayTab<TabPanePurgTotalComparisonAbility>('box-purgeable-total-comparison-ability').totalData(
1132      data,
1133      dataList
1134    );
1135    this.displayTab<TabPanePurgTotalSelection>(
1136      'box-purgeable-total-selection',
1137      'box-purgeable-total-comparison-ability'
1138    ).data = data;
1139  };
1140  displayPurgPinAbilityData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => {
1141    data.type = 'ability';
1142    this.displayTab<TabPanePurgPinComparisonAbility>('box-purgeable-pin-comparison-ability').totalData(data, dataList);
1143    this.displayTab<TabPanePurgPinSelection>(
1144      'box-purgeable-pin-selection',
1145      'box-purgeable-pin-comparison-ability'
1146    ).data = data;
1147  };
1148  displayPurgTotalVMData = (data: SnapshotStruct, dataListCache: Array<SnapshotStruct>): void => {
1149    data.type = 'VM';
1150    this.displayTab<TabPanePurgTotalComparisonVM>('box-purgeable-total-comparison-vm').totalData(data, dataListCache);
1151    this.displayTab<TabPanePurgTotalSelection>(
1152      'box-purgeable-total-selection',
1153      'box-purgeable-total-comparison-vm'
1154    ).data = data;
1155  };
1156  displayPurgPinVMData = (data: SnapshotStruct, dataListCache: Array<SnapshotStruct>): void => {
1157    data.type = 'VM';
1158    this.displayTab<TabPanePurgPinComparisonVM>('box-purgeable-pin-comparison-vm').totalData(data, dataListCache);
1159    this.displayTab<TabPanePurgPinSelection>('box-purgeable-pin-selection', 'box-purgeable-pin-comparison-vm').data =
1160      data;
1161  };
1162  displayDmaAbility = (data: number, dataList: Array<SnapshotStruct>): void => {
1163    if (dataList.length > 0) {
1164      this.displayTab<TabPaneDmaAbilityComparison>('box-dma-ability-comparison').comparisonDataByDB(data, dataList);
1165      this.displayTab<TabPaneDmaSelectAbility>(
1166        'box-dma-selection-ability',
1167        'box-dma-ability-comparison'
1168      ).queryDmaClickDataByDB(data);
1169    } else {
1170      this.displayTab<TabPaneDmaSelectAbility>('box-dma-selection-ability').queryDmaClickDataByDB(data);
1171    }
1172  };
1173  displayDmaVmTracker = (data: number, dataListCache: Array<SnapshotStruct>): void => {
1174    if (dataListCache.length > 0) {
1175      this.displayTab<TabPaneDmaVmTrackerComparison>('box-vmTracker-comparison').comparisonDataByDB(
1176        data,
1177        dataListCache
1178      );
1179      this.displayTab<TabPaneDmaSelectVmTracker>(
1180        'box-dma-selection-vmTracker',
1181        'box-vmTracker-comparison'
1182      ).queryDmaVmTrackerClickDataByDB(data);
1183    } else {
1184      this.displayTab<TabPaneDmaSelectVmTracker>('box-dma-selection-vmTracker').queryDmaVmTrackerClickDataByDB(data);
1185    }
1186  };
1187  displayGpuMemoryAbility = (data: number, dataList: Array<SnapshotStruct>): void => {
1188    if (dataList.length > 0) {
1189      this.displayTab<TabPaneGpuMemoryComparison>('box-gpu-memory-comparison').comparisonDataByDB(data, dataList);
1190      this.displayTab<TabPaneGpuMemorySelectAbility>(
1191        'box-gpu-memory-selection-ability',
1192        'box-gpu-memory-comparison'
1193      ).queryGpuMemoryClickDataByDB(data);
1194    } else {
1195      this.displayTab<TabPaneGpuMemorySelectAbility>('box-gpu-memory-selection-ability').data = data;
1196    }
1197  };
1198  displayGpuMemoryVmTracker = (data: number, dataListCache: Array<SnapshotStruct>): void => {
1199    if (dataListCache.length > 0) {
1200      this.displayTab<TabPaneGpuMemoryVmTrackerComparison>('box-gpu-memory-vmTracker-comparison').comparisonDataByDB(
1201        data,
1202        dataListCache
1203      );
1204      this.displayTab<TabPaneGpuMemorySelectVmTracker>(
1205        'box-gpu-memory-selection-vmTracker',
1206        'box-gpu-memory-vmTracker-comparison'
1207      ).queryGpuMemoryVmTrackerClickDataByDB(data);
1208    } else {
1209      this.displayTab<TabPaneGpuMemorySelectVmTracker>(
1210        'box-gpu-memory-selection-vmTracker'
1211      ).queryGpuMemoryVmTrackerClickDataByDB(data);
1212    }
1213  };
1214  displayGpuResourceVmTracker = (data: number): void => {
1215    this.displayTab<TabPaneGpuResourceVmTracker>('box-smaps-gpu-resource').data = data;
1216  };
1217
1218  displaySystemLogsData = (): void => {
1219    let tblHiLogPanel = this.shadowRoot?.querySelector<LitTabpane>("lit-tabpane[id='box-hilogs']");
1220    if (tblHiLogPanel) {
1221      let tblHiLog = tblHiLogPanel.querySelector<TabPaneHiLogs>('tab-hi-log');
1222      if (tblHiLog) {
1223        tblHiLog.initTabSheetEl(this);
1224      }
1225    }
1226  };
1227
1228  displayHangsData = (): void => {
1229    let tblHangPanel = this.shadowRoot?.querySelector<LitTabpane>("lit-tabpane[id='box-hang']");
1230    if (tblHangPanel) {
1231      let tblHang = tblHangPanel.querySelector<TabPaneHiLogs>('tab-hang');
1232      if (tblHang) {
1233        tblHang.initTabSheetEl(this);
1234      }
1235    }
1236  };
1237
1238  displaySampleData = (data: SampleStruct, reqProperty: unknown): void => {
1239    this.displayTab<TabPaneSampleInstruction>('box-sample-instruction').setSampleInstructionData(data, reqProperty);
1240    this.optionsDiv!.style.display = 'flex';
1241    const select =
1242      this.optionsSettingTree!.getCheckdKeys().length === 0 ? ['0'] : this.optionsSettingTree!.getCheckdKeys();
1243    this.optionsSettingTree!.treeData = [
1244      { key: '0', title: 'instruction', checked: select[0] === '0' },
1245      { key: '1', title: 'cycles', checked: select[0] === '1' },
1246    ];
1247  };
1248  displayUserPlugin = (selectData: unknown): void => {
1249    this.displayTab<TabPaneUserPlugin>('tab-pane-userplugin').data = selectData;
1250  };
1251
1252  displayGpuCounterData = (data: GpuCounterStruct): void => {
1253    this.displayTab<TabPaneGpuCounter>('box-gpu-counter').data = data;
1254  };
1255
1256  displaySystemStatesData = (): void => {
1257    let dataCutPane = this.shadowRoot?.querySelector<TabPaneDataCut>('tabpane-datacut');
1258    if (dataCutPane) {
1259      dataCutPane.initTabSheetEl(this);
1260    }
1261    let tblStatesPanel = this.shadowRoot?.querySelector<TabPaneFreqStatesDataCut>('tabpane-states-datacut');
1262    if (tblStatesPanel) {
1263      tblStatesPanel.initTabSheetEl(this);
1264    }
1265  };
1266  rangeSelect(selection: SelectionParam, restore = false): boolean {
1267    this.selection = selection;
1268    this.exportBt!.style.display = 'flex';
1269    this.showUploadSoBt(selection);
1270    this.showSwitchProcessBt(selection);
1271    this.showOptionsBt(selection); // @ts-ignore
1272    Reflect.ownKeys(tabConfig)
1273      .reverse()
1274      .forEach((id) => {
1275        // @ts-ignore
1276        let element = tabConfig[id];
1277        let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`);
1278        if (pane) {
1279          pane.hidden = !(element.require && element.require(selection));
1280        }
1281      });
1282    if (restore) {
1283      if (this.litTabs?.activekey) {
1284        if (this.loadSoComplete) {
1285          let analysisTabpane = this.shadowRoot!.querySelector('#box-perf-analysis') as LitTabpane;
1286          if (analysisTabpane && this.litTabs) {
1287            this.litTabs.activekey = analysisTabpane.key;
1288          }
1289        }
1290        this.loadTabPaneData(this.litTabs?.activekey);
1291        this.setMode('max');
1292        return true;
1293      } else {
1294        this.setMode('hidden');
1295        return false;
1296      }
1297    } else {
1298      let firstPane = this.shadowRoot!.querySelector<LitTabpane>("lit-tabpane[hidden='false']");
1299      if (firstPane) {
1300        this.litTabs?.activeByKey(firstPane.key);
1301        this.loadTabPaneData(firstPane.key);
1302        this.setMode('max');
1303        return true;
1304      } else {
1305        this.setMode('hidden');
1306        return false;
1307      }
1308    }
1309  }
1310
1311  showOptionsBt(selection: SelectionParam | null | undefined): void {
1312    if (selection && selection.sampleData.length > 0) {
1313      this.optionsDiv!.style.display = 'flex';
1314      const select =
1315        this.optionsSettingTree!.getCheckdKeys().length === 0 ? ['0'] : this.optionsSettingTree!.getCheckdKeys();
1316      this.optionsSettingTree!.treeData = [
1317        { key: '0', title: 'instruction', checked: select[0] === '0' },
1318        { key: '1', title: 'cycles', checked: select[0] === '1' },
1319      ];
1320    } else {
1321      this.optionsDiv!.style.display = 'none';
1322    }
1323  }
1324
1325  updateRangeSelect(ipid?: number): boolean {
1326    if (
1327      this.selection &&
1328      (this.selection.nativeMemory.length > 0 ||
1329        this.selection.nativeMemoryStatistic.length > 0 ||
1330        this.selection.perfSampleIds.length > 0 ||
1331        this.selection.fileSystemType.length > 0 ||
1332        this.selection.fsCount > 0 ||
1333        this.selection.fileSysVirtualMemory ||
1334        this.selection.vmCount > 0 ||
1335        this.selection.diskIOLatency ||
1336        this.selection.diskIOipids.length > 0)
1337    ) {
1338      let param: SelectionParam = new SelectionParam();
1339      Object.assign(param, this.selection);
1340      if (param.nativeMemory.length > 0 || param.nativeMemoryStatistic.length > 0) {
1341        Utils.getInstance().initResponseTypeList(param);
1342        if (ipid) {
1343          Utils.getInstance().setCurrentSelectIPid(ipid);
1344          param.nativeMemoryCurrentIPid = ipid;
1345        }
1346      }
1347      param.isImportSo = true;
1348      this.rangeSelect(param, true);
1349      return true;
1350    } else {
1351      return false;
1352    }
1353  }
1354
1355  showUploadSoBt(selection: SelectionParam | null | undefined): void {
1356    if (
1357      selection &&
1358      (selection.nativeMemory.length > 0 ||
1359        selection.nativeMemoryStatistic.length > 0 ||
1360        selection.perfSampleIds.length > 0 ||
1361        selection.fileSystemType.length > 0 ||
1362        selection.fsCount > 0 ||
1363        selection.fileSysVirtualMemory ||
1364        selection.vmCount > 0 ||
1365        selection.diskIOLatency ||
1366        selection.diskIOipids.length > 0 ||
1367        selection.threadIds.length > 0)
1368    ) {
1369      this.importDiv!.style.display = 'flex';
1370      this.symbolDiv!.style.display = 'flex';
1371    } else {
1372      this.importDiv!.style.display = 'none';
1373      this.symbolDiv!.style.display = 'none';
1374    }
1375  }
1376  isProcessEqual(treeData: Array<{ pid: number; ipid: number }>): boolean {
1377    if (treeData.length !== this.lastProcessSet.size) {
1378      return false;
1379    }
1380    for (let process of treeData) {
1381      if (!this.lastProcessSet.has(process.pid)) {
1382        return false;
1383      }
1384    }
1385    return true;
1386  }
1387
1388  showSwitchProcessBt(selection: SelectionParam | null | undefined): void {
1389    // 2个及以上进程再显示
1390    if (selection && selection.nativeMemoryAllProcess.length > 1) {
1391      this.switchDiv!.style.display = 'flex';
1392      if (this.isProcessEqual(selection.nativeMemoryAllProcess)) {
1393        if (this.processTree) {
1394          for (const data of this.processTree.treeData) {
1395            if (data.key === `${selection.nativeMemoryCurrentIPid}`) {
1396              data.checked = true;
1397            } else {
1398              data.checked = false;
1399            }
1400          }
1401          //调用set重新更新界面
1402          this.processTree.treeData = this.processTree.treeData;
1403        }
1404        return;
1405      }
1406      this.lastProcessSet = new Set<number>();
1407      const processArray: Array<TreeItemData> = [];
1408      let isFirst: boolean = true;
1409      for (let process of selection.nativeMemoryAllProcess) {
1410        const treeData: TreeItemData = {
1411          key: `${process.ipid}`,
1412          title: `Process ${process.pid}`,
1413          checked: isFirst,
1414        };
1415        if (isFirst) {
1416          this.lastSelectIPid = process.ipid;
1417          isFirst = false;
1418        }
1419        processArray.push(treeData);
1420        this.lastProcessSet.add(process.pid);
1421      }
1422      this.processTree!.treeData = processArray;
1423    } else {
1424      this.switchDiv!.style.display = 'none';
1425    }
1426  }
1427
1428  loadTabPaneData(key: string): void {
1429    let component: unknown = this.shadowRoot
1430      ?.querySelector<LitTabpane>(`#tabs lit-tabpane[key='${key}']`)
1431      ?.children.item(0);
1432    if (component) {
1433      // @ts-ignore
1434      component.data = this.selection;
1435      if (this.selection) {
1436        this.selection.isRowClick = false;
1437      }
1438    }
1439  }
1440
1441  setMode(mode: string): void {
1442    let delta = this.clientHeight;
1443    let show = mode === 'max' ? 1 : -1;
1444    this.setAttribute('mode', mode);
1445    if (mode === 'hidden') {
1446      this.selection = undefined;
1447    }
1448    window.publish(window.SmartEvent.UI.ShowBottomTab, { show: show, delta: delta });
1449  }
1450
1451  tdClickHandler(e: unknown, isDependCpu?: boolean): void {
1452    // @ts-ignore
1453    this.currentPaneID = e.target.parentElement.id;
1454    //隐藏除了当前Tab页的其他Tab页
1455    this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach((it): boolean =>
1456      it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false)
1457    ); //todo:看能不能优化
1458    let pane = this.getPaneByID('box-cpu-child'); //通过Id找到需要展示的Tab页
1459    pane.closeable = true; //关闭的ican显示
1460    pane.hidden = false;
1461    this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页
1462    // @ts-ignore
1463    pane.tab = e.detail.tabTitle ? e.detail.tabTitle : Utils.transferPTSTitle(e.detail.title); //设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串
1464    let param = new BoxJumpParam();
1465    param.traceId = this.selection!.traceId;
1466    param.leftNs = this.selection!.leftNs;
1467    param.rightNs = this.selection!.rightNs;
1468    param.cpus = isDependCpu ? this.selection!.cpus : [];
1469    // @ts-ignore
1470    param.state = e.detail.summary ? '' : e.detail.state;
1471    // @ts-ignore
1472    param.processId = e.detail.summary ? this.selection.processIds : e.detail.pid;
1473    // @ts-ignore
1474    param.threadId = e.detail.summary ? this.selection.threadIds : e.detail.tid;
1475    param.isJumpPage = true; // @ts-ignore
1476    param.currentId = e.target.parentElement.id; //根据父Tab页的标题,确认子Tab页的dur是否需要处理
1477    (pane.children.item(0) as TabPaneBoxChild).data = param;
1478  }
1479
1480  tdSysCallClickHandler(e: unknown): void {
1481    // @ts-ignore
1482    this.currentPaneID = e.target.parentElement.id;
1483    //隐藏除了当前Tab页的其他Tab页
1484    this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach((it): boolean =>
1485      it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false)
1486    ); //todo:看能不能优化
1487    let pane = this.getPaneByID('box-thread-syscall-child'); //通过Id找到需要展示的Tab页
1488    pane.closeable = true; //关闭的ican显示
1489    pane.hidden = false;
1490    this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页
1491    // @ts-ignore
1492    pane.tab = e.detail.name; //设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串
1493    let param = new SysCallBoxJumpParam();
1494    param.traceId = this.selection!.traceId;
1495    param.leftNs = this.selection!.leftNs;
1496    param.rightNs = this.selection!.rightNs;
1497    // @ts-ignore
1498    const level = e.detail.level;
1499    if (level === 'Process') {
1500      // @ts-ignore
1501      param.processId = [e.detail.id];
1502    } else if (level === 'Thread'){
1503      // @ts-ignore
1504      param.processId = [e.detail.parentId];
1505      // @ts-ignore
1506      param.threadId = [e.detail.id];
1507    } else {
1508      // @ts-ignore
1509      param.threadId = [e.detail.parentId];
1510      // @ts-ignore
1511      param.sysCallId = e.detail.id;
1512    }
1513    param.isJumpPage = true; // @ts-ignore
1514    (pane.children.item(0) as TabPaneSysCallChild).data = param;
1515  }
1516
1517  tdPerfSampleClickHandler(e: unknown): void {
1518    // @ts-ignore
1519    this.currentPaneID = e.target.parentElement.id;
1520    //隐藏除了当前Tab页的其他Tab页
1521    this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach((it): boolean =>
1522      it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false)
1523    ); //todo:看能不能优化
1524    let pane = this.getPaneByID('box-perf-sample-child'); //通过Id找到需要展示的Tab页
1525    pane.closeable = true; //关闭的ican显示
1526    pane.hidden = false;
1527    this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页
1528    // @ts-ignore
1529    pane.tab = e.detail.symbol; //设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串
1530    let param = new PerfSampleBoxJumpParam();
1531    param.traceId = this.selection!.traceId;
1532    param.leftNs = this.selection!.leftNs;
1533    param.rightNs = this.selection!.rightNs;
1534    //@ts-ignore
1535    param.pid = e.detail.pid;
1536    //@ts-ignore
1537    param.tid = e.detail.tid;
1538    //@ts-ignore
1539    param.count = e.detail.dur || 0;
1540    //@ts-ignore
1541    param.tsArr = e.detail.tsArray || [];
1542    param.isJumpPage = true;
1543    (pane.children.item(0) as TabPanePerfSampleChild).data = param;
1544  }
1545
1546  //Slice Tab点击Occurrences列下的td进行跳转
1547  tdSliceClickHandler(e: unknown): void {
1548    // @ts-ignore
1549    this.currentPaneID = e.target.parentElement.id;
1550    //隐藏除了当前Tab页的其他Tab页
1551    this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach((it): boolean =>
1552      it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false)
1553    );
1554    let pane = this.getPaneByID('box-slice-child'); //通过Id找到需要展示的Tab页
1555    pane.closeable = true;
1556    pane.hidden = false;
1557    this.litTabs!.activeByKey(pane.key); //显示key值(sheetconfig里面对应的index是一个数字)对应的Tab页
1558    // @ts-ignore
1559    pane.tab = e.detail.tabTitle; //设置Tab页标题
1560    let param = new SliceBoxJumpParam();
1561    param.traceId = this.selection!.traceId;
1562    param.leftNs = this.selection!.leftNs;
1563    param.rightNs = this.selection!.rightNs;
1564    param.processId = this.selection!.processIds;
1565    param.threadId = this.selection!.funTids; //@ts-ignore2
1566    param.name = e.detail.allName ? e.detail.allName : [e.detail.name]; //@ts-ignore2
1567    param.isJumpPage = true; // @ts-ignore
1568    param.isSummary = e.detail.allName ? true : false;
1569    (pane.children.item(0) as TabPaneSliceChild).data = { param: param, selection: this.selection };
1570  }
1571
1572  clearMemory(): void {
1573    let allTabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []);
1574    allTabs.forEach((tab) => {
1575      if (tab) {
1576        let tables = Array.from(
1577          (tab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || []
1578        );
1579        for (let table of tables) {
1580          table.recycleDataSource = [];
1581        }
1582      }
1583    });
1584  }
1585}
1586