• 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 { BoxJumpParam, SelectionParam, SliceBoxJumpParam } from '../../../bean/BoxSelection';
20import { type TabPaneCurrentSelection } from '../sheet/TabPaneCurrentSelection';
21import { type TabPaneFlag } from '../timer-shaft/TabPaneFlag';
22import { type Flag } from '../timer-shaft/Flag';
23import { type WakeupBean } from '../../../bean/WakeupBean';
24import { type LitIcon } from '../../../../base-ui/icon/LitIcon';
25import { tabConfig } from './TraceSheetConfig';
26import { type TabPaneBoxChild } from '../sheet/cpu/TabPaneBoxChild';
27import { type CpuStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCPU';
28import { CpuFreqStruct } from '../../../database/ui-worker/ProcedureWorkerFreq';
29import { CpuFreqLimitsStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits';
30import { type ThreadStruct } from '../../../database/ui-worker/ProcedureWorkerThread';
31import { type FuncStruct } from '../../../database/ui-worker/ProcedureWorkerFunc';
32import { ProcessMemStruct } from '../../../database/ui-worker/ProcedureWorkerMem';
33import { CpuStateStruct } from '../../../database/ui-worker/cpu/ProcedureWorkerCpuState';
34import { type HangStruct } from '../../../database/ui-worker/ProcedureWorkerHang';
35import { type ClockStruct } from '../../../database/ui-worker/ProcedureWorkerClock';
36import { type DmaFenceStruct } from '../../../database/ui-worker/ProcedureWorkerDmaFence';
37import { type IrqStruct } from '../../../database/ui-worker/ProcedureWorkerIrq';
38import { type JankStruct } from '../../../database/ui-worker/ProcedureWorkerJank';
39import { type HeapStruct } from '../../../database/ui-worker/ProcedureWorkerHeap';
40import { type LitTable } from '../../../../base-ui/table/lit-table';
41import { threadPool } from '../../../database/SqlLite';
42import { type HeapSnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerHeapSnapshot';
43import { type TabPaneNMStatisticAnalysis } from '../sheet/native-memory/TabPaneNMStatisticAnalysis';
44import { type TabPaneCurrent } from '../sheet/TabPaneCurrent';
45import { type SlicesTime } from '../timer-shaft/SportRuler';
46import { type AppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAppStartup';
47import { type AllAppStartupStruct } from '../../../database/ui-worker/ProcedureWorkerAllAppStartup';
48import { type SoStruct } from '../../../database/ui-worker/ProcedureWorkerSoInit';
49import { type FrameAnimationStruct } from '../../../database/ui-worker/ProcedureWorkerFrameAnimation';
50import { type TraceRow } from './TraceRow';
51import { type FrameDynamicStruct } from '../../../database/ui-worker/ProcedureWorkerFrameDynamic';
52import { type TabPaneFrameDynamic } from '../sheet/frame/TabPaneFrameDynamic';
53import { type FrameSpacingStruct } from '../../../database/ui-worker/ProcedureWorkerFrameSpacing';
54import { type TabFrameSpacing } from '../sheet/frame/TabFrameSpacing';
55import { type JsCpuProfilerChartFrame } from '../../../bean/JsStruct';
56import { type TabPaneComparison } from '../sheet/ark-ts/TabPaneComparison';
57import { type TabPaneSummary } from '../sheet/ark-ts/TabPaneSummary';
58import { type TabPaneGpuClickSelect } from '../sheet/gpu/TabPaneGpuClickSelect';
59import { type TabPanePurgTotalSelection } from '../sheet/ability/TabPanePurgTotalSelection';
60import { type TabPanePurgPinSelection } from '../sheet/ability/TabPanePurgPinSelection';
61import { type TabPaneVmTrackerShmSelection } from '../sheet/vmtracker/TabPaneVmTrackerShmSelection';
62import { type TabPaneSmapsStatistics } from '../sheet/smaps/TabPaneSmapsStatistics';
63import { type TabPaneSmapsComparison } from '../sheet/smaps/TabPaneSmapsComparison';
64import { type SnapshotStruct } from '../../../database/ui-worker/ProcedureWorkerSnapshot';
65import { type TabPaneDmaSelectAbility } from '../sheet/ability/TabPaneDmaSelectAbility';
66import { type TabPaneGpuMemorySelectAbility } from '../sheet/ability/TabPaneGpuMemorySelectAbility';
67import { type TabPaneDmaSelectVmTracker } from '../sheet/vmtracker/TabPaneDmaSelectVmTracker';
68import { type TabPanePurgTotalComparisonAbility } from '../sheet/ability/TabPanePurgTotalComparisonAbility';
69import { type TabPanePurgPinComparisonAbility } from '../sheet/ability/TabPanePurgPinComparisonAbility';
70import { type TabPanePurgTotalComparisonVM } from '../sheet/vmtracker/TabPanePurgTotalComparisonVM';
71import { type TabPanePurgPinComparisonVM } from '../sheet/vmtracker/TabPanePurgPinComparisonVM';
72import { type TabPaneDmaAbilityComparison } from '../sheet/ability/TabPaneDmaAbilityComparison';
73import { type TabPaneGpuMemoryComparison } from '../sheet/ability/TabPaneGpuMemoryComparison';
74import { type TabPaneDmaVmTrackerComparison } from '../sheet/vmtracker/TabPaneDmaVmTrackerComparison';
75import { type TabPaneGpuMemorySelectVmTracker } from '../sheet/vmtracker/TabPaneGpuMemorySelectVmTracker';
76import { type TabPaneGpuMemoryVmTrackerComparison } from '../sheet/vmtracker/TabPaneGpuMemoryVmTrackerComparison';
77import { type TabPaneVmTrackerShmComparison } from '../sheet/vmtracker/TabPaneVmTrackerShmComparison';
78import { type TabPaneJsCpuStatistics } from '../sheet/ark-ts/TabPaneJsCpuStatistics';
79import { type TabPaneGpuClickSelectComparison } from '../sheet/gpu/TabPaneGpuClickSelectComparison';
80import { Utils } from './Utils';
81import { TabPaneHiLogs } from '../sheet/hilog/TabPaneHiLogs';
82import { TabPaneGpuResourceVmTracker } from '../sheet/vmtracker/TabPaneGpuResourceVmTracker';
83import { type LitPageTable } from '../../../../base-ui/table/LitPageTable';
84import '../../../../base-ui/popover/LitPopoverV';
85import { LitPopover } from '../../../../base-ui/popover/LitPopoverV';
86import { LitTree, TreeItemData } from '../../../../base-ui/tree/LitTree';
87import { SampleStruct } from '../../../database/ui-worker/ProcedureWorkerBpftrace';
88import { TabPaneUserPlugin } from '../sheet/userPlugin/TabPaneUserPlugin';
89import { TabPaneSampleInstruction } from '../sheet/bpftrace/TabPaneSampleInstruction';
90import { TabPaneFreqStatesDataCut } from '../sheet/states/TabPaneFreqStatesDataCut';
91import { TabPaneDataCut } from '../sheet/TabPaneDataCut';
92import { SpSystemTrace } from '../../SpSystemTrace';
93import { PerfToolStruct } from '../../../database/ui-worker/ProcedureWorkerPerfTool';
94import { GpuCounterStruct } from '../../../database/ui-worker/ProcedureWorkerGpuCounter';
95import { TabPaneGpuCounter } from '../sheet/gpu-counter/TabPaneGpuCounter';
96import { TabPaneSliceChild } from '../sheet/process/TabPaneSliceChild';
97
98@element('trace-sheet')
99export class TraceSheet extends BaseElement {
100  systemLogFlag: Flag | undefined | null;
101  private litTabs: LitTabs | undefined | null;
102  private switchDiv: LitPopover | undefined | null;
103  private processTree: LitTree | undefined | null;
104  private importDiv: HTMLDivElement | undefined | null;
105  private exportBt: LitIcon | undefined | null;
106  private nav: HTMLDivElement | undefined | null;
107  private tabs: HTMLDivElement | undefined | null;
108  private navRoot: HTMLDivElement | null | undefined;
109  private search: HTMLDivElement | undefined | null;
110  private timerShaft: HTMLDivElement | undefined | null;
111  private spacer: HTMLDivElement | undefined | null;
112  private rowsPaneEL: HTMLDivElement | undefined | null;
113  private selection: SelectionParam | undefined | null;
114  private currentPaneID: string = 'current-selection';
115  private fragment: DocumentFragment | undefined;
116  private lastSelectIPid: number = -1;
117  private lastProcessSet: Set<number> = new Set<number>();
118  private optionsDiv: LitPopover | undefined | null;
119  private optionsSettingTree: LitTree | undefined | null;
120  private tabPaneHeight: string = '';
121
122  static get observedAttributes(): string[] {
123    return ['mode'];
124  }
125
126  buildTabs(litTabs: LitTabs | undefined | null): void {
127    this.fragment = document.createDocumentFragment(); // @ts-ignore
128    Reflect.ownKeys(tabConfig).forEach((key, index): void => {
129      let pane = new LitTabpane();
130      pane.id = key.toString();
131      pane.className = 'tabHeight'; // @ts-ignore
132      pane.tab = tabConfig[key].title;
133      pane.hidden = true; // @ts-ignore
134      pane.key = `${tabConfig[key].key || index}`; // @ts-ignore
135      let cls = tabConfig[key].type;
136      // @ts-ignore
137      let node = new cls();
138      pane.append(node);
139      this.fragment?.appendChild(pane);
140    });
141    litTabs!.appendChild(this.fragment);
142  }
143
144  displayTab<T>(...names: string[]): T {
145    this.setMode('max');
146    if (names.includes('box-flag') || names.includes('tabpane-current')) {
147      this.showUploadSoBt(this.selection);
148      this.showSwitchProcessBt(this.selection);
149    } else {
150      this.showOptionsBt(null);
151      this.showUploadSoBt(null);
152      this.showSwitchProcessBt(null);
153    }
154    this.shadowRoot
155      ?.querySelectorAll<LitTabpane>('#tabs lit-tabpane')
156      .forEach((it) => (it.hidden = !names.some((k) => k === it.id)));
157    let litTabpane = this.shadowRoot?.querySelector<LitTabpane>(`#tabs lit-tabpane[id='${names[0]}']`);
158    if (names[0] === 'current-selection') {
159      this.exportBt!.style.display = 'none';
160    } else {
161      this.exportBt!.style.display = 'flex';
162    }
163    this.shadowRoot?.querySelector<LitTabs>('#tabs')?.activePane(litTabpane!.key);
164    return litTabpane!.children.item(0) as unknown as T;
165  }
166
167  getComponentByID<T>(id: string): T {
168    return this.getPaneByID(id)?.children.item(0) as unknown as T;
169  }
170
171  getPaneByID(id: string): LitTabpane {
172    return this.shadowRoot!.querySelector(`#${id}`)!;
173  }
174
175  initElements(): void {
176    this.litTabs = this.shadowRoot?.querySelector('#tabs');
177    this.litTabs!.addEventListener('contextmenu', (e): void => {
178      e.preventDefault();
179    });
180    this.importDiv = this.shadowRoot?.querySelector('#import_div');
181    this.switchDiv = this.shadowRoot?.querySelector('#select-process');
182    this.processTree = this.shadowRoot?.querySelector('#processTree');
183    this.optionsDiv = this.shadowRoot?.querySelector('#options');
184    this.optionsSettingTree = this.shadowRoot?.querySelector('#optionsSettingTree');
185    this.optionsSettingTree!.onChange = (e: unknown): void => {
186      const select = this.optionsSettingTree!.getCheckdKeys();
187      document.dispatchEvent(
188        new CustomEvent('sample-popver-change', {
189          detail: {
190            select: select[0],
191          },
192        })
193      );
194    };
195    this.processTree!.onChange = (e: unknown): void => {
196      const select = this.processTree!.getCheckdKeys();
197      const selectIPid = Number(select[0]);
198      this.switchDiv!.visible = 'false';
199      this.updateRangeSelect(selectIPid);
200      this.lastSelectIPid = selectIPid;
201    };
202    this.buildTabs(this.litTabs); // @ts-ignore
203    this.litTabs!.onTabClick = (e: unknown): void => this.loadTabPaneData(e.detail.key);
204    this.tableCloseHandler();
205    this.rowClickEvent();
206    this.tdClickEvent();
207  }
208  private rowClickEvent(): void {
209    // @ts-ignore
210    this.getComponentByID<unknown>('box-perf-analysis')?.addEventListener('row-click', (evt: MouseEvent) => {
211      this.perfAnalysisListener(evt);
212    });
213    // @ts-ignore
214    this.getComponentByID<unknown>('box-native-statistic-analysis')?.addEventListener('row-click', (e: MouseEvent) => {
215      this.nativeAnalysisListener(e);
216    });
217    // @ts-ignore
218    this.getComponentByID<unknown>('box-io-tier-statistics-analysis')?.addEventListener('row-click', (evt: MouseEvent) => {
219      // @ts-ignore
220      if (evt.detail.button === 2 && evt.detail.tableName) {
221        let pane = this.getPaneByID('box-io-calltree');
222        this.litTabs!.activeByKey(pane.key);
223      }
224    });
225    // @ts-ignore
226    this.getComponentByID<unknown>('box-virtual-memory-statistics-analysis')?.addEventListener(
227      'row-click',
228      (evt: MouseEvent) => {
229        // @ts-ignore
230        if (evt.detail.button === 2 && evt.detail.tableName) {
231          let pane = this.getPaneByID('box-vm-calltree');
232          this.litTabs!.activeByKey(pane.key);
233        }
234      }
235    );
236    // @ts-ignore
237    this.getComponentByID<unknown>('box-file-system-statistics-analysis')?.addEventListener(
238      'row-click',
239      (evt: MouseEvent) => {
240        // @ts-ignore
241        if (evt.detail.button === 2 && evt.detail.tableName) {
242          let pane = this.getPaneByID('box-file-system-calltree');
243          this.litTabs!.activeByKey(pane.key);
244        }
245      }
246    );
247    // @ts-ignore
248    this.getComponentByID<unknown>('box-native-statstics')?.addEventListener('row-click', (e: unknown) => {
249      this.nativeStatsticsListener(e);
250    });
251    // @ts-ignore
252    this.getComponentByID<unknown>('box-virtual-memory-statistics')?.addEventListener('row-click', (e: unknown) => {
253      this.virtualMemoryListener(e);
254    });
255    // @ts-ignore
256    this.getComponentByID<unknown>('box-io-tier-statistics')?.addEventListener('row-click', (e: unknown) => {
257      this.ioTierListener(e);
258    });
259    // @ts-ignore
260    this.getComponentByID<unknown>('box-file-system-statistics')?.addEventListener('row-click', (e: unknown) => {
261      this.fileSystemListener(e);
262    });
263  }
264
265  private tdClickEvent(): void {
266    // @ts-ignore
267    this.getComponentByID<unknown>('box-spt')?.addEventListener('td-click', (evt: unknown) => {
268      this.tdClickHandler(evt);
269    });
270    // @ts-ignore
271    this.getComponentByID<unknown>('box-pts')?.addEventListener('td-click', (evt: unknown) => {
272      this.tdClickHandler(evt);
273    });
274    // @ts-ignore
275    this.getComponentByID<unknown>('box-thread-states')?.addEventListener('td-click', (evt: unknown) => {
276      this.tdClickHandler(evt);
277    });
278    // @ts-ignore
279    this.getComponentByID<unknown>('box-slices')?.addEventListener('td-click', (evt: unknown) => {
280      this.tdSliceClickHandler(evt);
281    });
282  }
283
284  private perfAnalysisListener(evt: MouseEvent): void {
285    // @ts-ignore
286    if (evt.detail.button === 2 && evt.detail.pid) {
287      let pane = this.getPaneByID('box-perf-profile');
288      this.litTabs!.activeByKey(pane.key);
289    }
290  }
291
292  private nativeAnalysisListener(e: MouseEvent): void {
293    //@ts-ignore
294    if (e.detail.button === 2 && e.detail.tableName) {
295      let pane = this.getPaneByID('box-native-calltree');
296      pane.hidden = false;
297      this.litTabs!.activeByKey(pane.key);
298    }
299  }
300
301  private nativeStatsticsListener(e: unknown): void {
302    // @ts-ignore
303    if (e.detail.button === 0) {
304      // @ts-ignore
305      this.selection!.statisticsSelectData = e.detail;
306      let pane = this.getPaneByID('box-native-memory');
307      this.litTabs?.activeByKey(pane.key);
308      // @ts-ignore
309      (pane.children.item(0) as unknown)!.fromStastics(this.selection);
310    }
311  }
312
313  private virtualMemoryListener(e: unknown): void {
314    // @ts-ignore
315    if (e.detail.button === 0) {
316      // @ts-ignore
317      this.selection!.fileSystemVMData = { path: e.detail.path };
318      let pane = this.getPaneByID('box-vm-events');
319      this.litTabs?.activeByKey(pane.key);
320      // @ts-ignore
321      if (e.detail.path) {
322        // @ts-ignore
323        (pane.children.item(0) as unknown)!.fromStastics(this.selection);
324      }
325    }
326  }
327
328  private ioTierListener(e: unknown): void {
329    // @ts-ignore
330    if (e.detail.button === 0) {
331      // @ts-ignore
332      this.selection!.fileSystemIoData = { path: e.detail.path };
333      let pane = this.getPaneByID('box-io-events');
334      this.litTabs?.activeByKey(pane.key);
335      // @ts-ignore
336      if (e.detail.path) {
337        // @ts-ignore
338        (pane.children.item(0) as unknown)!.fromStastics(this.selection);
339      }
340    }
341  }
342
343  private fileSystemListener(e: unknown): void {
344    // @ts-ignore
345    if (e.detail.button === 0) {
346      // @ts-ignore
347      this.selection!.fileSystemFsData = e.detail.data;
348      let pane = this.getPaneByID('box-file-system-event');
349      this.litTabs?.activeByKey(pane.key);
350      // @ts-ignore
351      if (e.detail.data) {
352        // @ts-ignore
353        (pane.children.item(0) as unknown)!.fromStastics(this.selection);
354      }
355    }
356  }
357
358  private tableCloseHandler(): void {
359    this.litTabs!.addEventListener('close-handler', () => {
360      // @ts-ignore
361      Reflect.ownKeys(tabConfig)
362        .reverse()
363        .forEach((id) => {
364          // @ts-ignore
365          let element = tabConfig[id];
366          let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`);
367          if (element.require) {
368            pane!.hidden = !element.require(this.selection!);
369          } else {
370            pane!.hidden = true;
371          }
372        });
373      this.litTabs?.activeByKey(`${this.getPaneByID(this.currentPaneID).key}`);
374    });
375  }
376
377  connectedCallback(): void {
378    this.nav = this.shadowRoot?.querySelector('#tabs')?.shadowRoot?.querySelector('.tab-nav-vessel');
379    this.tabs = this.shadowRoot?.querySelector('#tabs');
380    this.navRoot = this.shadowRoot?.querySelector('#tabs')?.shadowRoot?.querySelector('.nav-root');
381    this.search = document.querySelector('body > sp-application')?.shadowRoot?.querySelector('div > div.search-vessel');
382    this.timerShaft = this.parentElement?.querySelector('.timer-shaft');
383    this.spacer = this.parentElement?.querySelector('.spacer');
384    this.rowsPaneEL = this.parentElement?.querySelector('.rows-pane');
385    let tabsOpenUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#max-btn');
386    let tabsPackUp: LitIcon | undefined | null = this.shadowRoot?.querySelector<LitIcon>('#min-btn');
387    let borderTop: number = 1;
388    let initialHeight = { tabs: 'calc(30vh + 39px)', node: '30vh' };
389    this.initNavElements(tabsPackUp!, borderTop, initialHeight);
390    this.exportBt = this.shadowRoot?.querySelector<LitIcon>('#export-btn');
391    tabsOpenUp!.onclick = (): void => {
392      this.tabs!.style.height = `${window.innerHeight - this.search!.offsetHeight - this.timerShaft!.offsetHeight - borderTop
393        }px`;
394      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
395        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
396      litTabpane!.forEach((node: HTMLDivElement): void => {
397        node!.style.height = `${window.innerHeight -
398          this.search!.offsetHeight -
399          this.timerShaft!.offsetHeight -
400          this.navRoot!.offsetHeight -
401          borderTop
402          }px`;
403        initialHeight.node = node!.style.height;
404      });
405      initialHeight.tabs = this.tabs!.style.height;
406      tabsPackUp!.name = 'down';
407    };
408    tabsPackUp!.onclick = (): void => {
409      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
410        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
411      if (tabsPackUp!.name === 'down') {
412        let beforeHeight = this.clientHeight;
413        this.tabs!.style.height = `${this.navRoot!.offsetHeight}px`;
414        window.publish(window.SmartEvent.UI.ShowBottomTab, { show: 2, delta: beforeHeight - this.clientHeight });
415        litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = '0px'));
416        tabsPackUp!.name = 'up';
417        tabsPackUp!.title = 'Reset Tab'; // @ts-ignore
418        (window as unknown).isPackUpTable = true;
419      } else {
420        tabsPackUp!.name = 'down';
421        tabsPackUp!.title = 'Minimize Tab';
422        this.tabs!.style.height = initialHeight.tabs;
423        litTabpane!.forEach((node: HTMLDivElement) => (node!.style.height = initialHeight.node));
424      }
425    };
426    this.importClickEvent();
427    this.exportClickEvent();
428  }
429
430  private initNavElements(tabsPackUp: LitIcon, borderTop: number, initialHeight: { node: string; tabs: string }): void {
431    let that = this;
432    // 节点挂载时给Tab面板绑定鼠标按下事件
433    this.nav!.onmousedown = (event): void => {
434      if (SpSystemTrace.isKeyUp === false) {
435        return;
436      }
437      // @ts-ignore
438      (window as unknown).isSheetMove = true;
439      // 获取所有标签页的节点数组
440      let litTabpane: NodeListOf<HTMLDivElement> | undefined | null =
441        this.shadowRoot?.querySelectorAll('#tabs > lit-tabpane');
442      // 获取当前选中面板的key值,后续用来确定当前面板是哪一个。 对于用户来说,直观看到的只有当前面板,其他面板可以在拖动完成后一次性设置好新的高度
443      // @ts-ignore
444      let litTabNavKey: string = this.nav!.querySelector('.nav-item[data-selected=true]').dataset.key;
445      let currentPane: HTMLDivElement = this.shadowRoot?.querySelector(`#tabs > lit-tabpane[key="${litTabNavKey}"]`)!;
446      // 原函数 绑定鼠标移动事件,动态获取鼠标位置信息
447      this.navMouseMove(event, currentPane!, that, tabsPackUp, borderTop);
448      document.onmouseup = function (): void {
449        setTimeout(() => {
450          // @ts-ignore
451          (window as unknown).isSheetMove = false;
452        }, 100);
453        litTabpane!.forEach((node: HTMLDivElement): void => {
454          node!.style.height = that.tabPaneHeight;
455        });
456        if (that.tabPaneHeight !== '0px' && that.tabs!.style.height !== '') {
457          // 每次都会重新记录上次拖动完成后的面板高度,下次重新显示tab页时,会以上次拖动后的高度显示
458          initialHeight.node = that.tabPaneHeight;
459          initialHeight.tabs = that.tabs!.style.height;
460        }
461        // 将绑定的事件置空,需要时重新绑定
462        this.onmousemove = null;
463        this.onmouseup = null;
464      };
465    };
466  }
467
468  private navMouseMove(
469    event: MouseEvent,
470    litTabpane: HTMLDivElement,
471    that: this,
472    tabsPackUp: LitIcon,
473    borderTop: number
474  ): void {
475    // 鼠标移动前记录此时的鼠标位置信息,后续根据新值与前次值作比对
476    let preY = event.pageY;
477    // 获取此时tab组件的偏移高度 需要包含水平滚动条的高度等
478    let preHeight = this.tabs!.offsetHeight;
479    // 获取此时整个滚动区域高度
480    let scrollH = that.rowsPaneEL!.scrollHeight;
481    // 获取此时滚动区域上方被隐藏的高度
482    let scrollT = that.rowsPaneEL!.scrollTop;
483    // 获取当前内容区高度加上上下内边距高度,即面板组件高度
484    let ch = that.clientHeight;
485    // 鼠标移动事件
486    document.onmousemove = function (event): void {
487      // 移动前的面板高度 - 移动前后鼠标的坐标差值 = 新的面板高度
488      let newHeight: number = preHeight - (event.pageY - preY);
489      // that指向的是tracesheet节点 spacer为垫片  rowsPaneEl为泳道   tabs为tab页组件
490      // litTabpane为当前面板 navRoot为面板头部区的父级容器  search为顶部搜索区整个区域
491      // 这四个判断条件中,第一个尚未找到触发条件 后续和润和确认是否会触发
492      if (that.spacer!.offsetHeight > that.rowsPaneEL!.offsetHeight) {
493        that.tabs!.style.height = `${newHeight}px`;
494        litTabpane!.style.height = `${newHeight - that.navRoot!.offsetHeight}px`;
495        // 设置右上角面板大小化的箭头样式,面板在移动到最底部时,箭头向上,其余情况箭头向下
496        tabsPackUp!.name = 'down';
497      } else if (
498        // 只要没有移动到边界区域都会进入该条件
499        that.navRoot!.offsetHeight <= newHeight &&
500        that.search!.offsetHeight + that.timerShaft!.offsetHeight + borderTop + that.spacer!.offsetHeight <=
501        window.innerHeight - newHeight
502      ) {
503        that.tabs!.style.height = `${newHeight}px`;
504        litTabpane!.style.height = `${newHeight - that.navRoot!.offsetHeight}px`;
505        tabsPackUp!.name = 'down';
506      } else if (that.navRoot!.offsetHeight >= newHeight) {
507        // 该条件在面板置底时触发
508        that.tabs!.style.height = `${that.navRoot!.offsetHeight}px`;
509        litTabpane!.style.height = '0px';
510        tabsPackUp!.name = 'up';
511      } else if (
512        that.search!.offsetHeight + that.timerShaft!.offsetHeight + borderTop + that.spacer!.offsetHeight >=
513        window.innerHeight - newHeight
514      ) {
515        // 该条件在面板高度置顶时触发
516        that.tabs!.style.height = `${window.innerHeight -
517          that.search!.offsetHeight -
518          that.timerShaft!.offsetHeight -
519          borderTop -
520          that.spacer!.offsetHeight
521          }px`;
522        litTabpane!.style.height = `${window.innerHeight -
523          that.search!.offsetHeight -
524          that.timerShaft!.offsetHeight -
525          that.navRoot!.offsetHeight -
526          borderTop -
527          that.spacer!.offsetHeight
528          }px`;
529        tabsPackUp!.name = 'down';
530      }
531      that.tabPaneHeight = litTabpane!.style.height;
532      let currentSH = that.rowsPaneEL!.scrollHeight;
533      // 第一个判断条件尚未确定如何触发,currentSH与scrollH始终相等
534      if (currentSH > scrollH && currentSH > that.rowsPaneEL!.scrollTop + that.clientHeight) {
535        that.rowsPaneEL!.scrollTop = scrollT - (ch - that.clientHeight);
536      }
537    };
538  }
539
540  private importClickEvent(): void {
541    let importFileBt: HTMLInputElement | undefined | null =
542      this.shadowRoot?.querySelector<HTMLInputElement>('#import-file');
543    importFileBt!.addEventListener('change', (event): void => {
544      let files = importFileBt?.files;
545      if (files) {
546        let fileList: Array<File> = [];
547        for (let file of files) {
548          if (file.name.endsWith('.so')) {
549            fileList.push(file);
550          }
551        }
552        if (fileList.length > 0) {
553          importFileBt!.disabled = true;
554          window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Import So File' });
555          threadPool.submit(
556            'upload-so',
557            '',
558            fileList,
559            (res: unknown) => {
560              importFileBt!.disabled = false; // @ts-ignore
561              if (res.result === 'ok') {
562                window.publish(window.SmartEvent.UI.UploadSOFile, {});
563              } else {
564                // @ts-ignore
565                const failedList = res.failedArray.join(',');
566                window.publish(window.SmartEvent.UI.Error, `parse so file ${failedList} failed!`);
567              }
568            },
569            'upload-so'
570          );
571        }
572        fileList.length = 0;
573      }
574      importFileBt!.files = null;
575      importFileBt!.value = '';
576    });
577  }
578
579  private exportClickEvent(): void {
580    this.exportBt!.onclick = (): void => {
581      let currentTab = this.getTabpaneByKey(this.litTabs?.activekey!);
582      if (currentTab) {
583        let table1 = Array.from(
584          (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitPageTable>('lit-page-table') || []
585        );
586        let table2 = Array.from(
587          (currentTab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || []
588        );
589        let tables = [...table1, ...table2];
590
591        for (let table of tables) {
592          if (!table.hasAttribute('hideDownload')) {
593            table.exportData();
594          }
595        }
596      }
597    };
598  }
599
600  getTabpaneByKey(key: string): LitTabpane | undefined {
601    let tabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []);
602    return tabs.find((it) => it.key === key);
603  }
604
605  initHtml(): string {
606    return `
607            <style>
608                :host([mode='hidden']){
609                    display: none;
610                }
611                :host{
612                    display: block;
613                    background-color: rebeccapurple;
614                }
615                .tabHeight{
616                    height: 30vh;
617                    background-color: var(--dark-background,#FFFFFF);
618                }
619                #check-popover[visible="true"] #check-des{
620                    color: #0A59F7;
621                }
622                .popover{
623                  color: var(--dark-color1,#4b5766);
624                  justify-content: center;
625                  align-items: center;
626                  margin-right: 10px;
627                  z-index: 2;
628                }
629                .option {
630                  display: flex;
631                  margin-right: 10px;
632                  cursor: pointer;
633                }
634            </style>
635            <div id="vessel" style="border-top: 1px solid var(--dark-border1,#D5D5D5);">
636                <lit-tabs id="tabs" position="top-left" activekey="1" mode="card" >
637                    <div class="option" slot="options">
638                      <lit-popover placement="bottom" class="popover" haveRadio="true" trigger="click" id="options">
639                        <div slot="content">
640                          <lit-tree id="optionsSettingTree" checkable="true"></lit-tree>
641                        </div>
642                        <lit-icon name="setting" size="21" id="setting"></lit-icon>
643                      </lit-popover>
644                    </div>
645                    <div slot="right" style="margin: 0 10px; color: var(--dark-icon,#606060);display: flex;align-items: center;">
646                        <lit-popover placement="bottomRight" class="popover" haveRadio="true" trigger="click" id="select-process">
647                              <div slot="content">
648                                <lit-tree id="processTree" checkable="true"></lit-tree>
649                              </div>
650                              <lit-icon name="setting" size="20" id="setting"></lit-icon>
651                        </lit-popover>
652                        <div title="Import SO" id="import_div" style="width: 20px;height: 20px;display: flex;flex-direction: row;margin-right: 10px">
653                            <input id="import-file" style="display: none;pointer-events: none" type="file" webkitdirectory>
654                            <label style="width: 20px;height: 20px;cursor: pointer;" for="import-file">
655                                <lit-icon id="import-btn" name="copy-csv" style="pointer-events: none" size="20">
656                                </lit-icon>
657                            </label>
658                        </div>
659                        <lit-icon title="Download Table" id="export-btn" name="import-so" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20">
660                        </lit-icon>
661                        <lit-icon title="Maximize Tab" id="max-btn" name="vertical-align-top" style="font-weight: bold;cursor: pointer;margin-right: 10px" size="20">
662                        </lit-icon>
663                        <lit-icon title="Minimize Tab" id="min-btn" name="down" style="font-weight: bold;cursor: pointer;" size="20">
664                        </lit-icon>
665                    </div>
666                </lit-tabs>
667            </div>`;
668  }
669  displayCurrent = (data: SlicesTime): void =>
670    this.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(data);
671  displayThreadData = (
672    data: ThreadStruct,
673    scrollCallback: ((e: ThreadStruct) => void) | undefined,
674    scrollWakeUp: (d: unknown) => void | undefined,
675    scrollPrio: (d: unknown) => void | undefined,
676    callback?: (data: Array<unknown>, str: string) => void
677  ): Promise<void> =>
678    this.displayTab<TabPaneCurrentSelection>('current-selection').setThreadData(
679      data,
680      // @ts-ignore
681      scrollCallback,
682      scrollWakeUp,
683      scrollPrio,
684      callback
685    );
686  displayMemData = (data: ProcessMemStruct): void =>
687    this.displayTab<TabPaneCurrentSelection>('current-selection').setMemData(data);
688  displayHangData = (data: HangStruct, sp: SpSystemTrace): Promise<void> =>
689    this.displayTab<TabPaneCurrentSelection>('current-selection').setHangData(data, sp);
690  displayClockData = (data: ClockStruct): Promise<void> =>
691    this.displayTab<TabPaneCurrentSelection>('current-selection').setClockData(data);
692  displayDmaFenceData = (data: DmaFenceStruct, rowData: unknown): void =>//展示tab页内容
693    // @ts-ignore
694    this.displayTab<TabPaneCurrentSelection>('current-selection').setDmaFenceData(data, rowData);
695  displayPerfToolsData = (data: PerfToolStruct): void =>
696    this.displayTab<TabPaneCurrentSelection>('current-selection').setPerfToolsData(data);
697  displayIrqData = (data: IrqStruct): void =>
698    this.displayTab<TabPaneCurrentSelection>('current-selection').setIrqData(data);
699  displayStartupData = (data: AppStartupStruct, scrollCallback: Function, rowData: unknown): void =>
700    this.displayTab<TabPaneCurrentSelection>('current-selection').setStartupData(data, scrollCallback, rowData);
701  displayAllStartupData = (data: AllAppStartupStruct, scrollCallback: Function): void =>
702    this.displayTab<TabPaneCurrentSelection>('current-selection').setAllStartupData(data, scrollCallback);
703  displayStaticInitData = (data: SoStruct, scrollCallback: Function): void =>
704    this.displayTab<TabPaneCurrentSelection>('current-selection').setStaticInitData(data, scrollCallback);
705
706  displayNativeHookData = (data: HeapStruct, rowType: string, ipid: number): void => {
707    let val = new SelectionParam();
708    val.nativeMemoryStatistic.push(rowType);
709    val.nativeMemoryCurrentIPid = ipid;
710    val.nativeMemory = [];
711    val.leftNs = data.startTime! + data.dur!;
712    val.rightNs = data.startTime! + data.dur! + 1;
713    this.selection = val;
714    this.displayTab<TabPaneNMStatisticAnalysis>('box-native-statistic-analysis', 'box-native-calltree').data = val;
715    this.showUploadSoBt(val);
716    this.showSwitchProcessBt(val);
717  };
718
719  displayGpuSelectedData = (type: string, startTs: number, dataList: Array<SnapshotStruct>): void => {
720    this.displayTab<TabPaneGpuClickSelectComparison>('gpu-click-select-comparison').getGpuClickDataByDB(
721      type,
722      startTs,
723      dataList
724    );
725    let dataObject = { type: type, startTs: startTs };
726    this.displayTab<TabPaneGpuClickSelect>('gpu-click-select', 'gpu-click-select-comparison').gpuClickData(dataObject);
727  };
728
729  displayFuncData = (
730    names: string[],
731    threadName: string,
732    data: FuncStruct,
733    scrollCallback: Function,
734    callback?: (data: Array<unknown>, str: string, binderTid: number) => void,
735    distributedCallback?: (dataList: FuncStruct[]) => void,
736  ): Promise<void> =>
737    this.displayTab<TabPaneCurrentSelection>(...names).setFunctionData(data, threadName, scrollCallback, callback, distributedCallback);
738  displayCpuData = (
739    data: CpuStruct,
740    callback: ((data: WakeupBean | null) => void) | undefined = undefined,
741    scrollCallback?: (data: CpuStruct) => void
742  ): Promise<void> =>
743    this.displayTab<TabPaneCurrentSelection>('current-selection').setCpuData(data, callback, scrollCallback);
744  displayJankData = (
745    data: JankStruct,
746    callback: ((data: Array<unknown>) => void) | undefined = undefined,
747    scrollCallback: ((e: JankStruct) => void) | undefined
748    // @ts-ignore
749  ): void => this.displayTab<TabPaneCurrentSelection>('current-selection').setJankData(data, callback, scrollCallback);
750  displayShmData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => {
751    this.displayTab<TabPaneVmTrackerShmComparison>('box-vmtracker-shm-comparison').setShmData(data, dataList);
752    this.displayTab<TabPaneVmTrackerShmSelection>(
753      'box-vmtracker-shm-selection',
754      'box-vmtracker-shm-comparison'
755    ).setShmData(data, dataList);
756  };
757  displaySmapsData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => {
758    let val = new SelectionParam();
759    val.smapsType = [];
760    val.leftNs = data.startNs;
761    this.selection = val;
762    val.smapsType = [];
763    this.displayTab<TabPaneSmapsComparison>('box-smaps-comparison').setData(val, dataList);
764    this.displayTab<TabPaneSmapsStatistics>(
765      'box-smaps-statistics',
766      'box-smaps-sample',
767      'box-smaps-comparison',
768      'box-smaps-record'
769    ).data = val;
770  };
771  displaySnapshotData = (
772    data: HeapSnapshotStruct,
773    dataListCache: Array<HeapSnapshotStruct>,
774    scrollCallback?: (data: HeapSnapshotStruct, dataListCache: Array<HeapSnapshotStruct>) => void
775  ): void => {
776    if (dataListCache.length > 1) {
777      this.displayTab<TabPaneSummary>('box-heap-summary', 'box-heap-comparison').setSnapshotData(
778        data,
779        dataListCache,
780        scrollCallback
781      );
782      let nav = this.shadowRoot!.querySelector('#tabs')!.shadowRoot!.querySelector(
783        '#nav > #nav-comparison'
784      ) as HTMLDivElement;
785      let tabPaneComparison = this.shadowRoot!.querySelector(
786        '#box-heap-comparison > tabpane-comparison'
787      ) as TabPaneComparison;
788      nav!.onclick = (): void => {
789        tabPaneComparison.initComparison(data, dataListCache);
790      };
791    } else {
792      this.displayTab<TabPaneSummary>('box-heap-summary').setSnapshotData(data, dataListCache, scrollCallback);
793    }
794  };
795  displayFlagData = (flagObj: Flag): void => this.displayTab<TabPaneFlag>('box-flag').setCurrentFlag(flagObj);
796  displayFreqData = (): CpuFreqStruct | undefined =>
797    (this.displayTab<TabPaneCurrentSelection>('box-freq').data = CpuFreqStruct.selectCpuFreqStruct);
798  displayCpuStateData = (): CpuStateStruct | undefined =>
799    (this.displayTab<TabPaneCurrentSelection>('cpu-state-click').data = CpuStateStruct.selectStateStruct);
800  displayFreqLimitData = (): CpuFreqLimitsStruct | undefined =>
801    (this.displayTab<TabPaneCurrentSelection>('box-freq-limit').data = CpuFreqLimitsStruct.selectCpuFreqLimitsStruct);
802
803  displayFrameAnimationData = (data: FrameAnimationStruct, scrollCallback: Function): Promise<void> =>
804    this.displayTab<TabPaneCurrentSelection>('current-selection').setFrameAnimationData(data, scrollCallback);
805  displayFrameDynamicData = (row: TraceRow<FrameDynamicStruct>, data: FrameDynamicStruct): void =>
806    this.displayTab<TabPaneFrameDynamic>('box-frame-dynamic').buildDynamicTable([data], true);
807  displayFrameSpacingData = (data: FrameSpacingStruct): void =>
808    this.displayTab<TabFrameSpacing>('box-frames-spacing').setFrameSpacingData(data);
809  displayJsProfilerData = (data: Array<JsCpuProfilerChartFrame>): void => {
810    let val = new SelectionParam();
811    val.jsCpuProfilerData = data;
812    this.selection = val;
813    this.displayTab<TabPaneJsCpuStatistics>(
814      'box-js-Profiler-statistics',
815      'box-js-Profiler-bottom-up',
816      'box-js-Profiler-top-down'
817    ).data = data;
818  };
819  displayPurgTotalAbilityData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => {
820    data.type = 'ability';
821    this.displayTab<TabPanePurgTotalComparisonAbility>('box-purgeable-total-comparison-ability').totalData(
822      data,
823      dataList
824    );
825    this.displayTab<TabPanePurgTotalSelection>(
826      'box-purgeable-total-selection',
827      'box-purgeable-total-comparison-ability'
828    ).data = data;
829  };
830  displayPurgPinAbilityData = (data: SnapshotStruct, dataList: Array<SnapshotStruct>): void => {
831    data.type = 'ability';
832    this.displayTab<TabPanePurgPinComparisonAbility>('box-purgeable-pin-comparison-ability').totalData(data, dataList);
833    this.displayTab<TabPanePurgPinSelection>(
834      'box-purgeable-pin-selection',
835      'box-purgeable-pin-comparison-ability'
836    ).data = data;
837  };
838  displayPurgTotalVMData = (data: SnapshotStruct, dataListCache: Array<SnapshotStruct>): void => {
839    data.type = 'VM';
840    this.displayTab<TabPanePurgTotalComparisonVM>('box-purgeable-total-comparison-vm').totalData(data, dataListCache);
841    this.displayTab<TabPanePurgTotalSelection>(
842      'box-purgeable-total-selection',
843      'box-purgeable-total-comparison-vm'
844    ).data = data;
845  };
846  displayPurgPinVMData = (data: SnapshotStruct, dataListCache: Array<SnapshotStruct>): void => {
847    data.type = 'VM';
848    this.displayTab<TabPanePurgPinComparisonVM>('box-purgeable-pin-comparison-vm').totalData(data, dataListCache);
849    this.displayTab<TabPanePurgPinSelection>('box-purgeable-pin-selection', 'box-purgeable-pin-comparison-vm').data =
850      data;
851  };
852  displayDmaAbility = (data: number, dataList: Array<SnapshotStruct>): void => {
853    if (dataList.length > 0) {
854      this.displayTab<TabPaneDmaAbilityComparison>('box-dma-ability-comparison').comparisonDataByDB(data, dataList);
855      this.displayTab<TabPaneDmaSelectAbility>(
856        'box-dma-selection-ability',
857        'box-dma-ability-comparison'
858      ).queryDmaClickDataByDB(data);
859    } else {
860      this.displayTab<TabPaneDmaSelectAbility>('box-dma-selection-ability').queryDmaClickDataByDB(data);
861    }
862  };
863  displayDmaVmTracker = (data: number, dataListCache: Array<SnapshotStruct>): void => {
864    if (dataListCache.length > 0) {
865      this.displayTab<TabPaneDmaVmTrackerComparison>('box-vmTracker-comparison').comparisonDataByDB(
866        data,
867        dataListCache
868      );
869      this.displayTab<TabPaneDmaSelectVmTracker>(
870        'box-dma-selection-vmTracker',
871        'box-vmTracker-comparison'
872      ).queryDmaVmTrackerClickDataByDB(data);
873    } else {
874      this.displayTab<TabPaneDmaSelectVmTracker>('box-dma-selection-vmTracker').queryDmaVmTrackerClickDataByDB(data);
875    }
876  };
877  displayGpuMemoryAbility = (data: number, dataList: Array<SnapshotStruct>): void => {
878    if (dataList.length > 0) {
879      this.displayTab<TabPaneGpuMemoryComparison>('box-gpu-memory-comparison').comparisonDataByDB(data, dataList);
880      this.displayTab<TabPaneGpuMemorySelectAbility>(
881        'box-gpu-memory-selection-ability',
882        'box-gpu-memory-comparison'
883      ).queryGpuMemoryClickDataByDB(data);
884    } else {
885      this.displayTab<TabPaneGpuMemorySelectAbility>('box-gpu-memory-selection-ability').data = data;
886    }
887  };
888  displayGpuMemoryVmTracker = (data: number, dataListCache: Array<SnapshotStruct>): void => {
889    if (dataListCache.length > 0) {
890      this.displayTab<TabPaneGpuMemoryVmTrackerComparison>('box-gpu-memory-vmTracker-comparison').comparisonDataByDB(
891        data,
892        dataListCache
893      );
894      this.displayTab<TabPaneGpuMemorySelectVmTracker>(
895        'box-gpu-memory-selection-vmTracker',
896        'box-gpu-memory-vmTracker-comparison'
897      ).queryGpuMemoryVmTrackerClickDataByDB(data);
898    } else {
899      this.displayTab<TabPaneGpuMemorySelectVmTracker>(
900        'box-gpu-memory-selection-vmTracker'
901      ).queryGpuMemoryVmTrackerClickDataByDB(data);
902    }
903  };
904  displayGpuResourceVmTracker = (data: number): void => {
905    this.displayTab<TabPaneGpuResourceVmTracker>('box-smaps-gpu-resource').data = data;
906  };
907
908  displaySystemLogsData = (): void => {
909    let tblHiLogPanel = this.shadowRoot?.querySelector<LitTabpane>("lit-tabpane[id='box-hilogs']");
910    if (tblHiLogPanel) {
911      let tblHiLog = tblHiLogPanel.querySelector<TabPaneHiLogs>('tab-hi-log');
912      if (tblHiLog) {
913        tblHiLog.initTabSheetEl(this);
914      }
915    }
916  };
917
918  displayHangsData = (): void => {
919    let tblHangPanel = this.shadowRoot?.querySelector<LitTabpane>("lit-tabpane[id='box-hang']");
920    if (tblHangPanel) {
921      let tblHang = tblHangPanel.querySelector<TabPaneHiLogs>('tab-hang');
922      if (tblHang) {
923        tblHang.initTabSheetEl(this);
924      }
925    }
926  };
927
928  displaySampleData = (data: SampleStruct, reqProperty: unknown): void => {
929    this.displayTab<TabPaneSampleInstruction>('box-sample-instruction').setSampleInstructionData(data, reqProperty);
930    this.optionsDiv!.style.display = 'flex';
931    const select =
932      this.optionsSettingTree!.getCheckdKeys().length === 0 ? ['0'] : this.optionsSettingTree!.getCheckdKeys();
933    this.optionsSettingTree!.treeData = [
934      { key: '0', title: 'instruction', checked: select[0] === '0' },
935      { key: '1', title: 'cycles', checked: select[0] === '1' },
936    ];
937  };
938  displayUserPlugin = (selectData: unknown): void => {
939    this.displayTab<TabPaneUserPlugin>("tab-pane-userplugin").data = selectData;
940  };
941
942
943  displayGpuCounterData = (data: GpuCounterStruct): void => {
944    this.displayTab<TabPaneGpuCounter>('box-gpu-counter').data = data;
945  };
946
947  displaySystemStatesData = (): void => {
948    let dataCutPane = this.shadowRoot?.querySelector<TabPaneDataCut>('tabpane-datacut');
949    if (dataCutPane) {
950      dataCutPane.initTabSheetEl(this);
951    }
952    let tblStatesPanel = this.shadowRoot?.querySelector<TabPaneFreqStatesDataCut>('tabpane-states-datacut');
953    if (tblStatesPanel) {
954      tblStatesPanel.initTabSheetEl(this);
955    }
956  };
957  rangeSelect(selection: SelectionParam, restore = false): boolean {
958    this.selection = selection;
959    this.exportBt!.style.display = 'flex';
960    this.showUploadSoBt(selection);
961    this.showSwitchProcessBt(selection);
962    this.showOptionsBt(selection); // @ts-ignore
963    Reflect.ownKeys(tabConfig)
964      .reverse()
965      .forEach((id) => {
966        // @ts-ignore
967        let element = tabConfig[id];
968        let pane = this.shadowRoot!.querySelector<LitTabpane>(`#${id as string}`);
969        if (pane) {
970          pane.hidden = !(element.require && element.require(selection));
971        }
972      });
973    if (restore) {
974      if (this.litTabs?.activekey) {
975        this.loadTabPaneData(this.litTabs?.activekey);
976        this.setMode('max');
977        return true;
978      } else {
979        this.setMode('hidden');
980        return false;
981      }
982    } else {
983      let firstPane = this.shadowRoot!.querySelector<LitTabpane>("lit-tabpane[hidden='false']");
984      if (firstPane) {
985        this.litTabs?.activeByKey(firstPane.key);
986        this.loadTabPaneData(firstPane.key);
987        this.setMode('max');
988        return true;
989      } else {
990        this.setMode('hidden');
991        return false;
992      }
993    }
994  }
995
996  showOptionsBt(selection: SelectionParam | null | undefined): void {
997    if (selection && selection.sampleData.length > 0) {
998      this.optionsDiv!.style.display = 'flex';
999      const select =
1000        this.optionsSettingTree!.getCheckdKeys().length === 0 ? ['0'] : this.optionsSettingTree!.getCheckdKeys();
1001      this.optionsSettingTree!.treeData = [
1002        { key: '0', title: 'instruction', checked: select[0] === '0' },
1003        { key: '1', title: 'cycles', checked: select[0] === '1' },
1004      ];
1005    } else {
1006      this.optionsDiv!.style.display = 'none';
1007    }
1008  }
1009
1010  updateRangeSelect(ipid?: number): boolean {
1011    if (
1012      this.selection &&
1013      (this.selection.nativeMemory.length > 0 ||
1014        this.selection.nativeMemoryStatistic.length > 0 ||
1015        this.selection.perfSampleIds.length > 0 ||
1016        this.selection.fileSystemType.length > 0 ||
1017        this.selection.fsCount > 0 ||
1018        this.selection.fileSysVirtualMemory ||
1019        this.selection.vmCount > 0 ||
1020        this.selection.diskIOLatency ||
1021        this.selection.diskIOipids.length > 0)
1022    ) {
1023      let param: SelectionParam = new SelectionParam();
1024      Object.assign(param, this.selection);
1025      if (param.nativeMemory.length > 0 || param.nativeMemoryStatistic.length > 0) {
1026        Utils.getInstance().initResponseTypeList(param);
1027        if (ipid) {
1028          Utils.getInstance().setCurrentSelectIPid(ipid);
1029          param.nativeMemoryCurrentIPid = ipid;
1030        }
1031      }
1032      this.rangeSelect(param, true);
1033      return true;
1034    } else {
1035      return false;
1036    }
1037  }
1038
1039  showUploadSoBt(selection: SelectionParam | null | undefined): void {
1040    if (
1041      selection &&
1042      (selection.nativeMemory.length > 0 ||
1043        selection.nativeMemoryStatistic.length > 0 ||
1044        selection.perfSampleIds.length > 0 ||
1045        selection.fileSystemType.length > 0 ||
1046        selection.fsCount > 0 ||
1047        selection.fileSysVirtualMemory ||
1048        selection.vmCount > 0 ||
1049        selection.diskIOLatency ||
1050        selection.diskIOipids.length > 0 ||
1051        selection.threadIds.length > 0)
1052    ) {
1053      this.importDiv!.style.display = 'flex';
1054    } else {
1055      this.importDiv!.style.display = 'none';
1056    }
1057  }
1058  isProcessEqual(treeData: Array<{ pid: number; ipid: number }>): boolean {
1059    if (treeData.length !== this.lastProcessSet.size) {
1060      return false;
1061    }
1062    for (let process of treeData) {
1063      if (!this.lastProcessSet.has(process.pid)) {
1064        return false;
1065      }
1066    }
1067    return true;
1068  }
1069
1070  showSwitchProcessBt(selection: SelectionParam | null | undefined): void {
1071    // 2个及以上进程再显示
1072    if (selection && selection.nativeMemoryAllProcess.length > 1) {
1073      this.switchDiv!.style.display = 'flex';
1074      if (this.isProcessEqual(selection.nativeMemoryAllProcess)) {
1075        if (this.processTree) {
1076          for (const data of this.processTree.treeData) {
1077            if (data.key === `${selection.nativeMemoryCurrentIPid}`) {
1078              data.checked = true;
1079            } else {
1080              data.checked = false;
1081            }
1082          }
1083          //调用set重新更新界面
1084          this.processTree.treeData = this.processTree.treeData;
1085        }
1086        return;
1087      }
1088      this.lastProcessSet = new Set<number>();
1089      const processArray: Array<TreeItemData> = [];
1090      let isFirst: boolean = true;
1091      for (let process of selection.nativeMemoryAllProcess) {
1092        const treeData: TreeItemData = {
1093          key: `${process.ipid}`,
1094          title: `Process ${process.pid}`,
1095          checked: isFirst,
1096        };
1097        if (isFirst) {
1098          this.lastSelectIPid = process.ipid;
1099          isFirst = false;
1100        }
1101        processArray.push(treeData);
1102        this.lastProcessSet.add(process.pid);
1103      }
1104      this.processTree!.treeData = processArray;
1105    } else {
1106      this.switchDiv!.style.display = 'none';
1107    }
1108  }
1109
1110  loadTabPaneData(key: string): void {
1111    let component: unknown = this.shadowRoot
1112      ?.querySelector<LitTabpane>(`#tabs lit-tabpane[key='${key}']`)
1113      ?.children.item(0);
1114    if (component) {
1115      // @ts-ignore
1116      component.data = this.selection;
1117      if (this.selection) {
1118        this.selection.isRowClick = false;
1119      }
1120    }
1121  }
1122
1123  setMode(mode: string): void {
1124    let delta = this.clientHeight;
1125    let show = mode === 'max' ? 1 : -1;
1126    this.setAttribute('mode', mode);
1127    if (mode === 'hidden') {
1128      this.selection = undefined;
1129    }
1130    window.publish(window.SmartEvent.UI.ShowBottomTab, { show: show, delta: delta });
1131  }
1132
1133  tdClickHandler(e: unknown): void {
1134    // @ts-ignore
1135    this.currentPaneID = e.target.parentElement.id;
1136    //隐藏除了当前Tab页的其他Tab页
1137    this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach((it): boolean =>
1138      it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false)
1139    );//todo:看能不能优化
1140    let pane = this.getPaneByID('box-cpu-child');//通过Id找到需要展示的Tab页
1141    pane.closeable = true;//关闭的ican显示
1142    pane.hidden = false;
1143    this.litTabs!.activeByKey(pane.key); //显示key值对应的Tab页
1144    // @ts-ignore
1145    pane.tab = e.detail.tabTitle ? e.detail.tabTitle : Utils.transferPTSTitle(e.detail.title);//设置Tab页标题,有的标题可直接用,有的标题需在此转换成需要展示的字符串
1146    let param = new BoxJumpParam();
1147    param.traceId = this.selection!.traceId;
1148    param.leftNs = this.selection!.leftNs;
1149    param.rightNs = this.selection!.rightNs;
1150    param.cpus = this.selection!.cpus;
1151    // @ts-ignore
1152    param.state = e.detail.summary ? '' : e.detail.state;
1153    // @ts-ignore
1154    param.processId = e.detail.summary ? this.selection.processIds : e.detail.pid;
1155    // @ts-ignore
1156    param.threadId = e.detail.summary ? this.selection.threadIds : e.detail.tid;
1157    param.isJumpPage = true;// @ts-ignore
1158    param.currentId = e.target.parentElement.id;//根据父Tab页的标题,确认子Tab页的dur是否需要处理
1159    (pane.children.item(0) as TabPaneBoxChild).data = param;
1160  }
1161
1162  //Slice Tab点击Occurrences列下的td进行跳转
1163  tdSliceClickHandler(e: unknown): void {
1164    // @ts-ignore
1165    this.currentPaneID = e.target.parentElement.id;
1166    //隐藏除了当前Tab页的其他Tab页
1167    this.shadowRoot!.querySelectorAll<LitTabpane>('lit-tabpane').forEach((it): boolean =>
1168      it.id !== this.currentPaneID ? (it.hidden = true) : (it.hidden = false)
1169    );
1170    let pane = this.getPaneByID('box-slice-child');//通过Id找到需要展示的Tab页
1171    pane.closeable = true;
1172    pane.hidden = false;
1173    this.litTabs!.activeByKey(pane.key); //显示key值(sheetconfig里面对应的index是一个数字)对应的Tab页
1174    // @ts-ignore
1175    pane.tab = e.detail.tabTitle;//设置Tab页标题
1176    let param = new SliceBoxJumpParam();
1177    param.traceId = this.selection!.traceId;
1178    param.leftNs = this.selection!.leftNs;
1179    param.rightNs = this.selection!.rightNs;
1180    param.processId = this.selection!.processIds;
1181    param.threadId = this.selection!.funTids;//@ts-ignore2
1182    param.name = e.detail.allName ? e.detail.allName : [e.detail.name];//@ts-ignore2
1183    param.asyncNames = e.detail.asyncNames;//@ts-ignore2
1184    param.asyncCatNames = e.detail.asyncCatNames;
1185    param.isJumpPage = true;
1186    (pane.children.item(0) as TabPaneSliceChild).data = param;
1187  }
1188
1189  clearMemory(): void {
1190    let allTabs = Array.from(this.shadowRoot?.querySelectorAll<LitTabpane>('#tabs lit-tabpane').values() || []);
1191    allTabs.forEach((tab) => {
1192      if (tab) {
1193        let tables = Array.from(
1194          (tab.firstChild as BaseElement).shadowRoot?.querySelectorAll<LitTable>('lit-table') || []
1195        );
1196        for (let table of tables) {
1197          table.recycleDataSource = [];
1198        }
1199      }
1200    });
1201  }
1202}
1203