1fb726d48Sopenharmony_ci/*
2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd.
3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb726d48Sopenharmony_ci * You may obtain a copy of the License at
6fb726d48Sopenharmony_ci *
7fb726d48Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fb726d48Sopenharmony_ci *
9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF unknown KIND, either express or implied.
12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and
13fb726d48Sopenharmony_ci * limitations under the License.
14fb726d48Sopenharmony_ci */
15fb726d48Sopenharmony_ci
16fb726d48Sopenharmony_ciimport { BaseElement, element } from '../../base-ui/BaseElement';
17fb726d48Sopenharmony_ciimport { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
18fb726d48Sopenharmony_ciimport { threadPool } from '../database/SqlLite';
19fb726d48Sopenharmony_ciimport { SpAiAnalysisPageHtml } from './SpAiAnalysisPage.html'
20fb726d48Sopenharmony_ciimport { getTimeString } from './trace/sheet/TabPaneCurrentSelection';
21fb726d48Sopenharmony_ciimport { WebSocketManager } from '../../webSocket/WebSocketManager';
22fb726d48Sopenharmony_ciimport { TypeConstants } from '../../webSocket/Constants';
23fb726d48Sopenharmony_ciimport { TraceRow } from './trace/base/TraceRow';
24fb726d48Sopenharmony_ciimport { SpSystemTrace } from './SpSystemTrace';
25fb726d48Sopenharmony_ci
26fb726d48Sopenharmony_ci@element('sp-ai-analysis')
27fb726d48Sopenharmony_ciexport class SpAiAnalysisPage extends BaseElement {
28fb726d48Sopenharmony_ci    private askQuestion: Element | null | undefined;
29fb726d48Sopenharmony_ci    private aiAnswerBox: HTMLDivElement | null | undefined;
30fb726d48Sopenharmony_ci    private newChatEl: HTMLImageElement | null | undefined;
31fb726d48Sopenharmony_ci    private chatWindow: HTMLDivElement | null | undefined;
32fb726d48Sopenharmony_ci    private inputEl: HTMLTextAreaElement | null | undefined;
33fb726d48Sopenharmony_ci    private chatImg: HTMLImageElement | null | undefined;
34fb726d48Sopenharmony_ci    private reportBar: HTMLImageElement | null | undefined;
35fb726d48Sopenharmony_ci    private reportImg: HTMLImageElement | null | undefined;
36fb726d48Sopenharmony_ci    private sendImg: HTMLImageElement | null | undefined;
37fb726d48Sopenharmony_ci    private draftBtn: HTMLDivElement | null | undefined;
38fb726d48Sopenharmony_ci    private downloadBtn: HTMLDivElement | null | undefined;
39fb726d48Sopenharmony_ci    private draftList: HTMLDivElement | null | undefined;
40fb726d48Sopenharmony_ci    private noDataEl: HTMLDivElement | null | undefined;
41fb726d48Sopenharmony_ci    private loginTipEl: HTMLDivElement | null | undefined;
42fb726d48Sopenharmony_ci    private loadingItem: HTMLDivElement | null | undefined;
43fb726d48Sopenharmony_ci    private startTimeEl: HTMLSpanElement | null | undefined;
44fb726d48Sopenharmony_ci    private endTimeEl: HTMLSpanElement | null | undefined;
45fb726d48Sopenharmony_ci    private question: string = '';
46fb726d48Sopenharmony_ci    private token: string = '';
47fb726d48Sopenharmony_ci    // 是否点击了新建聊天
48fb726d48Sopenharmony_ci    private isNewChat: boolean = false;
49fb726d48Sopenharmony_ci    isCtrlDown: boolean = false;
50fb726d48Sopenharmony_ci    static isRepeatedly: boolean = false;
51fb726d48Sopenharmony_ci    // 拼接下载内容
52fb726d48Sopenharmony_ci    private reportContent: string = '';
53fb726d48Sopenharmony_ci    private md: unknown;
54fb726d48Sopenharmony_ci    // 监听选中时间范围变化
55fb726d48Sopenharmony_ci    static selectChangeListener(startTime: number, endTime: number) {
56fb726d48Sopenharmony_ci        let startEl = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatBox > div > div.report_details > div.selectionBox > div.startBox > span");
57fb726d48Sopenharmony_ci        startEl!.innerHTML = getTimeString(startTime).toString();
58fb726d48Sopenharmony_ci        let endEl = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatBox > div > div.report_details > div.selectionBox > div.endBox > span");
59fb726d48Sopenharmony_ci        endEl!.innerHTML = getTimeString(endTime).toString();
60fb726d48Sopenharmony_ci    }
61fb726d48Sopenharmony_ci    initElements(): void {
62fb726d48Sopenharmony_ci        this.md = require('markdown-it')({
63fb726d48Sopenharmony_ci            html: true,
64fb726d48Sopenharmony_ci            typographer: true
65fb726d48Sopenharmony_ci        });
66fb726d48Sopenharmony_ci        let chatBar = this.shadowRoot?.querySelector('.chatBar');
67fb726d48Sopenharmony_ci        this.askQuestion = this.shadowRoot?.querySelector('.ask_question');
68fb726d48Sopenharmony_ci        this.reportBar = this.shadowRoot?.querySelector('.report');
69fb726d48Sopenharmony_ci        let reportDetails = this.shadowRoot?.querySelector('.report_details');
70fb726d48Sopenharmony_ci        let chatInputBox = this.shadowRoot?.querySelector('.chatInputBox');
71fb726d48Sopenharmony_ci        this.chatWindow = this.shadowRoot?.querySelector('.ask_question');
72fb726d48Sopenharmony_ci        this.inputEl = this.shadowRoot?.querySelector('.inputText');
73fb726d48Sopenharmony_ci        this.chatImg = this.shadowRoot?.querySelector('.chatBar')?.getElementsByTagName('img')[0];
74fb726d48Sopenharmony_ci        this.reportImg = this.shadowRoot?.querySelector('.report')?.getElementsByTagName('img')[0];
75fb726d48Sopenharmony_ci        this.sendImg = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatInputBox > div.chatInput > img");
76fb726d48Sopenharmony_ci        this.newChatEl = document.querySelector("body > sp-application")!.shadowRoot!.querySelector("#sp-ai-analysis")!.shadowRoot?.querySelector("div.chatBox > div > div.chatInputBox > div.chatConfig > div > div.newChat > img");
77fb726d48Sopenharmony_ci        // 诊断按钮
78fb726d48Sopenharmony_ci        this.draftBtn = this.shadowRoot?.querySelector('.analysisBtn');
79fb726d48Sopenharmony_ci        // 下载报告按钮
80fb726d48Sopenharmony_ci        this.downloadBtn = this.shadowRoot?.querySelector('.downloadBtn');
81fb726d48Sopenharmony_ci        // 报告列表
82fb726d48Sopenharmony_ci        this.draftList = this.shadowRoot?.querySelector('.data-record');
83fb726d48Sopenharmony_ci        // 空数据页面
84fb726d48Sopenharmony_ci        this.noDataEl = this.shadowRoot?.querySelector('.no-data');
85fb726d48Sopenharmony_ci        // 未连接提示弹窗
86fb726d48Sopenharmony_ci        this.loginTipEl = this.shadowRoot?.querySelector('.loginTip');
87fb726d48Sopenharmony_ci        // 时间展示区域
88fb726d48Sopenharmony_ci        this.startTimeEl = this.shadowRoot?.querySelector('.startTime');
89fb726d48Sopenharmony_ci        this.startTimeEl!.innerHTML = getTimeString(TraceRow.range?.startNS!);
90fb726d48Sopenharmony_ci        this.endTimeEl = this.shadowRoot?.querySelector('.endTime');
91fb726d48Sopenharmony_ci        this.endTimeEl!.innerHTML = getTimeString(TraceRow.range?.endNS!);
92fb726d48Sopenharmony_ci
93fb726d48Sopenharmony_ci        // 发送消息图标点击事件
94fb726d48Sopenharmony_ci        this.sendImg?.addEventListener('click', () => {
95fb726d48Sopenharmony_ci            this.sendMessage();
96fb726d48Sopenharmony_ci        })
97fb726d48Sopenharmony_ci
98fb726d48Sopenharmony_ci        // 新建对话按钮点击事件
99fb726d48Sopenharmony_ci        this.newChatEl?.addEventListener('click', () => {
100fb726d48Sopenharmony_ci            this.isNewChat = true;
101fb726d48Sopenharmony_ci            this.token = '';
102fb726d48Sopenharmony_ci            this.askQuestion!.innerHTML = '';
103fb726d48Sopenharmony_ci            this.createAiChatBox('有什么可以帮助您的吗?');
104fb726d48Sopenharmony_ci        })
105fb726d48Sopenharmony_ci
106fb726d48Sopenharmony_ci        // 输入框发送消息
107fb726d48Sopenharmony_ci        this.inputEl?.addEventListener('keydown', (e) => {
108fb726d48Sopenharmony_ci            if (e.key.toLocaleLowerCase() === 'control' || e.keyCode === 17) {
109fb726d48Sopenharmony_ci                this.isCtrlDown = true;
110fb726d48Sopenharmony_ci            }
111fb726d48Sopenharmony_ci            if (this.isCtrlDown) {
112fb726d48Sopenharmony_ci                if (e.key.toLocaleLowerCase() === 'enter') {
113fb726d48Sopenharmony_ci                    this.inputEl!.value += '\n';
114fb726d48Sopenharmony_ci                }
115fb726d48Sopenharmony_ci            } else {
116fb726d48Sopenharmony_ci                if (e.key.toLocaleLowerCase() === 'enter') {
117fb726d48Sopenharmony_ci                    this.sendMessage();
118fb726d48Sopenharmony_ci                    // 禁止默认的回车换行
119fb726d48Sopenharmony_ci                    e.preventDefault();
120fb726d48Sopenharmony_ci                };
121fb726d48Sopenharmony_ci            };
122fb726d48Sopenharmony_ci        });
123fb726d48Sopenharmony_ci
124fb726d48Sopenharmony_ci        // 输入框聚焦/失焦--防止触发页面快捷键
125fb726d48Sopenharmony_ci        this.inputEl?.addEventListener('focus', () => {
126fb726d48Sopenharmony_ci            SpSystemTrace.isAiAsk = true;
127fb726d48Sopenharmony_ci        });
128fb726d48Sopenharmony_ci
129fb726d48Sopenharmony_ci        this.inputEl?.addEventListener('blur', () => {
130fb726d48Sopenharmony_ci            SpSystemTrace.isAiAsk = false;
131fb726d48Sopenharmony_ci        })
132fb726d48Sopenharmony_ci
133fb726d48Sopenharmony_ci        // 监听浏览器刷新,清除db数据
134fb726d48Sopenharmony_ci        window.onbeforeunload = function () {
135fb726d48Sopenharmony_ci            caches.delete(`${window.localStorage.getItem('fileName')}.db`);
136fb726d48Sopenharmony_ci            sessionStorage.removeItem('fileName');
137fb726d48Sopenharmony_ci        }
138fb726d48Sopenharmony_ci
139fb726d48Sopenharmony_ci        // 监听ctrl抬起
140fb726d48Sopenharmony_ci        this.inputEl?.addEventListener('keyup', (e) => {
141fb726d48Sopenharmony_ci            if (e.key.toLocaleLowerCase() === 'control' || e.keyCode === 17) {
142fb726d48Sopenharmony_ci                this.isCtrlDown = false;
143fb726d48Sopenharmony_ci            };
144fb726d48Sopenharmony_ci        });
145fb726d48Sopenharmony_ci
146fb726d48Sopenharmony_ci        // 下载诊断报告按钮监听
147fb726d48Sopenharmony_ci        this.downloadBtn?.addEventListener('click', (e) => {
148fb726d48Sopenharmony_ci            let a = document.createElement('a');
149fb726d48Sopenharmony_ci            a.href = URL.createObjectURL(new Blob([this.reportContent]));
150fb726d48Sopenharmony_ci            a.download = window.sessionStorage.getItem('fileName')! + '诊断报告';
151fb726d48Sopenharmony_ci            a.click();
152fb726d48Sopenharmony_ci        })
153fb726d48Sopenharmony_ci
154fb726d48Sopenharmony_ci        // 诊断按钮
155fb726d48Sopenharmony_ci        this.draftBtn?.addEventListener('click', async (e) => {
156fb726d48Sopenharmony_ci            // 取消已经存在的诊断
157fb726d48Sopenharmony_ci            this.draftList!.innerHTML = '';
158fb726d48Sopenharmony_ci            // 没有登陆,弹窗提示,退出逻辑
159fb726d48Sopenharmony_ci            if (!WebSocketManager.getInstance()?.isReady()) {
160fb726d48Sopenharmony_ci                this.loginTipEl!.style.visibility = 'visible';
161fb726d48Sopenharmony_ci                setTimeout(() => {
162fb726d48Sopenharmony_ci                    this.loginTipEl!.style.visibility = 'hidden';
163fb726d48Sopenharmony_ci                }, 1000);
164fb726d48Sopenharmony_ci                return;
165fb726d48Sopenharmony_ci            }
166fb726d48Sopenharmony_ci            // 同一个trace非第一次诊断,无需再发db文件过去
167fb726d48Sopenharmony_ci            if (SpAiAnalysisPage.isRepeatedly) {
168fb726d48Sopenharmony_ci                this.initiateDiagnosis();
169fb726d48Sopenharmony_ci            } else {
170fb726d48Sopenharmony_ci                // 首次诊断
171fb726d48Sopenharmony_ci                WebSocketManager.getInstance()!.registerMessageListener(TypeConstants.DIAGNOSIS_TYPE, this.webSocketCallBack);
172fb726d48Sopenharmony_ci                // 看缓存中有没有db,没有的话拿一个进行诊断并存缓存
173fb726d48Sopenharmony_ci                let fileName = sessionStorage.getItem('fileName');
174fb726d48Sopenharmony_ci                caches.match(`${fileName}.db`).then(async (res) => {
175fb726d48Sopenharmony_ci                    if (!res) {
176fb726d48Sopenharmony_ci                        this.cacheDb(fileName);
177fb726d48Sopenharmony_ci                    }
178fb726d48Sopenharmony_ci                    WebSocketManager.getInstance()!.sendMessage(TypeConstants.DIAGNOSIS_TYPE, TypeConstants.SENDDB_CMD, new TextEncoder().encode(await res!.text()));
179fb726d48Sopenharmony_ci                });
180fb726d48Sopenharmony_ci            };
181fb726d48Sopenharmony_ci            // 隐藏nodata
182fb726d48Sopenharmony_ci            this.noDataEl!.style.display = 'none';
183fb726d48Sopenharmony_ci            // 加载中的loading模块
184fb726d48Sopenharmony_ci            let loadingDiv = document.createElement('div');
185fb726d48Sopenharmony_ci            loadingDiv.className = 'loadingBox';
186fb726d48Sopenharmony_ci            loadingDiv.innerHTML = '<lit-loading style="position:absolute;top:45%;left:45%;z-index:999"></lit-loading>';
187fb726d48Sopenharmony_ci            let loadingItem = document.createElement('div');
188fb726d48Sopenharmony_ci            loadingItem.className = 'loadingItem';
189fb726d48Sopenharmony_ci            this.loadingItem = loadingItem;
190fb726d48Sopenharmony_ci            loadingItem!.appendChild(loadingDiv);
191fb726d48Sopenharmony_ci            this.draftList?.appendChild(loadingItem);
192fb726d48Sopenharmony_ci        })
193fb726d48Sopenharmony_ci
194fb726d48Sopenharmony_ci        // 侧边栏诊断点击事件 *************优化,考虑多个按钮
195fb726d48Sopenharmony_ci        this.reportBar!.addEventListener('click', () => {
196fb726d48Sopenharmony_ci            this.reportImg!.src = 'img/report_active.png';
197fb726d48Sopenharmony_ci            this.chatImg!.src = 'img/talk.png';
198fb726d48Sopenharmony_ci            this.reportBar!.classList.add('active');
199fb726d48Sopenharmony_ci            chatBar!.classList.remove('active');
200fb726d48Sopenharmony_ci            //@ts-ignore
201fb726d48Sopenharmony_ci            this.askQuestion!.style.display = 'none';
202fb726d48Sopenharmony_ci            //@ts-ignore
203fb726d48Sopenharmony_ci            chatInputBox!.style.display = 'none';
204fb726d48Sopenharmony_ci            //@ts-ignore
205fb726d48Sopenharmony_ci            reportDetails!.style.display = 'block';
206fb726d48Sopenharmony_ci        });
207fb726d48Sopenharmony_ci
208fb726d48Sopenharmony_ci        // 侧边栏聊天点击事件
209fb726d48Sopenharmony_ci        chatBar!.addEventListener('click', () => {
210fb726d48Sopenharmony_ci            this.reportImg!.src = 'img/report.png';
211fb726d48Sopenharmony_ci            this.chatImg!.src = 'img/talk_active.png';
212fb726d48Sopenharmony_ci            this.reportBar!.classList.remove('active');
213fb726d48Sopenharmony_ci            chatBar!.classList.add('active');
214fb726d48Sopenharmony_ci            //@ts-ignore
215fb726d48Sopenharmony_ci            this.askQuestion!.style.display = 'block';
216fb726d48Sopenharmony_ci            //@ts-ignore
217fb726d48Sopenharmony_ci            chatInputBox!.style.display = 'block';
218fb726d48Sopenharmony_ci            //@ts-ignore
219fb726d48Sopenharmony_ci            reportDetails!.style.display = 'none';
220fb726d48Sopenharmony_ci        });
221fb726d48Sopenharmony_ci
222fb726d48Sopenharmony_ci
223fb726d48Sopenharmony_ci    }
224fb726d48Sopenharmony_ci
225fb726d48Sopenharmony_ci    // 点击诊断之后,重置
226fb726d48Sopenharmony_ci    reset() {
227fb726d48Sopenharmony_ci        this.reportContent = '';
228fb726d48Sopenharmony_ci        this.downloadBtn!.style.display = 'none';
229fb726d48Sopenharmony_ci    }
230fb726d48Sopenharmony_ci
231fb726d48Sopenharmony_ci    // 发送消息
232fb726d48Sopenharmony_ci    async sendMessage() {
233fb726d48Sopenharmony_ci        if (this.inputEl!.value != '') {
234fb726d48Sopenharmony_ci            if (this.isNewChat) {
235fb726d48Sopenharmony_ci                this.isNewChat = false;
236fb726d48Sopenharmony_ci            }
237fb726d48Sopenharmony_ci            this.question = JSON.parse(JSON.stringify(this.inputEl!.value));
238fb726d48Sopenharmony_ci            this.createChatBox();
239fb726d48Sopenharmony_ci            this.createAiChatBox('AI智能分析中...');
240fb726d48Sopenharmony_ci            this.chatWindow!.scrollTop = this.chatWindow!.scrollHeight;
241fb726d48Sopenharmony_ci            // 没有token
242fb726d48Sopenharmony_ci            if (this.token === '') {
243fb726d48Sopenharmony_ci                this.token = await SpStatisticsHttpUtil.getAItoken();
244fb726d48Sopenharmony_ci                if (this.token === '') {
245fb726d48Sopenharmony_ci                    this.aiAnswerBox!.firstElementChild!.innerHTML = '获取token失败';
246fb726d48Sopenharmony_ci                    return;
247fb726d48Sopenharmony_ci                }
248fb726d48Sopenharmony_ci            }
249fb726d48Sopenharmony_ci            this.answer();
250fb726d48Sopenharmony_ci        }
251fb726d48Sopenharmony_ci    }
252fb726d48Sopenharmony_ci
253fb726d48Sopenharmony_ci    // ai对话
254fb726d48Sopenharmony_ci    async answer() {
255fb726d48Sopenharmony_ci        let requestBody = {
256fb726d48Sopenharmony_ci            token: this.token,
257fb726d48Sopenharmony_ci            question: this.question,
258fb726d48Sopenharmony_ci            collection: 'smart_perf_test',
259fb726d48Sopenharmony_ci            scope: 'smartperf'
260fb726d48Sopenharmony_ci        };
261fb726d48Sopenharmony_ci        let answer = await SpStatisticsHttpUtil.askAi(requestBody);
262fb726d48Sopenharmony_ci        if (answer !== '') {
263fb726d48Sopenharmony_ci            if (!this.isNewChat) {
264fb726d48Sopenharmony_ci                // @ts-ignore
265fb726d48Sopenharmony_ci                this.aiAnswerBox!.firstElementChild!.innerHTML = this.md!.render(answer);
266fb726d48Sopenharmony_ci                // 滚动条滚到底部
267fb726d48Sopenharmony_ci                this.chatWindow!.scrollTop = this.chatWindow!.scrollHeight;
268fb726d48Sopenharmony_ci            }
269fb726d48Sopenharmony_ci        } else {
270fb726d48Sopenharmony_ci            this.aiAnswerBox!.firstElementChild!.innerHTML = '服务器异常';
271fb726d48Sopenharmony_ci            this.chatWindow!.scrollTop = this.chatWindow!.scrollHeight;
272fb726d48Sopenharmony_ci        }
273fb726d48Sopenharmony_ci    }
274fb726d48Sopenharmony_ci
275fb726d48Sopenharmony_ci    // 创建用户聊天对话气泡
276fb726d48Sopenharmony_ci    createChatBox() {
277fb726d48Sopenharmony_ci        // 生成头像
278fb726d48Sopenharmony_ci        let headerDiv = document.createElement('div');
279fb726d48Sopenharmony_ci        headerDiv.className = 'userHeader headerDiv';
280fb726d48Sopenharmony_ci        // 生成聊天内容框
281fb726d48Sopenharmony_ci        let newQuestion = document.createElement('div');
282fb726d48Sopenharmony_ci        newQuestion.className = "usersay";
283fb726d48Sopenharmony_ci        // @ts-ignore
284fb726d48Sopenharmony_ci        newQuestion!.innerHTML = this.inputEl!.value;
285fb726d48Sopenharmony_ci        // 生成聊天气泡三角
286fb726d48Sopenharmony_ci        let triangleDiv = document.createElement('div');
287fb726d48Sopenharmony_ci        newQuestion.appendChild(triangleDiv);
288fb726d48Sopenharmony_ci        triangleDiv.className = 'userTriangle';
289fb726d48Sopenharmony_ci        // 单条消息模块,最大的div,包含头像、消息、清除浮动元素
290fb726d48Sopenharmony_ci        let newMessage = document.createElement('div');
291fb726d48Sopenharmony_ci        newMessage.className = 'usermessage message';
292fb726d48Sopenharmony_ci        // @ts-ignore
293fb726d48Sopenharmony_ci        this.inputEl!.value = '';
294fb726d48Sopenharmony_ci        newMessage.appendChild(headerDiv);
295fb726d48Sopenharmony_ci        newMessage.appendChild(newQuestion);
296fb726d48Sopenharmony_ci        let claerDiv = document.createElement('div');
297fb726d48Sopenharmony_ci        claerDiv.className = 'clear';
298fb726d48Sopenharmony_ci        newMessage.appendChild(claerDiv);
299fb726d48Sopenharmony_ci        this.askQuestion?.appendChild(newMessage);
300fb726d48Sopenharmony_ci    }
301fb726d48Sopenharmony_ci
302fb726d48Sopenharmony_ci    // 创建ai助手聊天对话气泡
303fb726d48Sopenharmony_ci    createAiChatBox(aiText: string) {
304fb726d48Sopenharmony_ci        // 生成ai头像
305fb726d48Sopenharmony_ci        let headerDiv = document.createElement('div');
306fb726d48Sopenharmony_ci        headerDiv.className = 'aiHeader headerDiv';
307fb726d48Sopenharmony_ci        headerDiv.innerHTML = `<img class='headerImg' src = "img/logo.png" title=""></img>`
308fb726d48Sopenharmony_ci        let newQuestion = document.createElement('div');
309fb726d48Sopenharmony_ci        newQuestion.className = "systemSay";
310fb726d48Sopenharmony_ci        // @ts-ignore
311fb726d48Sopenharmony_ci        newQuestion!.innerHTML = `<div>${aiText}</div>`;
312fb726d48Sopenharmony_ci        let triangleDiv = document.createElement('div');
313fb726d48Sopenharmony_ci        newQuestion.appendChild(triangleDiv);
314fb726d48Sopenharmony_ci        triangleDiv.className = 'aiTriangle';
315fb726d48Sopenharmony_ci        let newMessage = document.createElement('div');
316fb726d48Sopenharmony_ci        newMessage.className = 'aiMessage message';
317fb726d48Sopenharmony_ci        newMessage.appendChild(headerDiv);
318fb726d48Sopenharmony_ci        newMessage.appendChild(newQuestion);
319fb726d48Sopenharmony_ci        let claerDiv = document.createElement('div');
320fb726d48Sopenharmony_ci        claerDiv.className = 'clear';
321fb726d48Sopenharmony_ci        this.aiAnswerBox = newQuestion;
322fb726d48Sopenharmony_ci        newMessage.appendChild(claerDiv);
323fb726d48Sopenharmony_ci        this.askQuestion?.appendChild(newMessage);
324fb726d48Sopenharmony_ci    }
325fb726d48Sopenharmony_ci
326fb726d48Sopenharmony_ci    // 页面渲染诊断结果
327fb726d48Sopenharmony_ci    async renderData(dataList: any) {
328fb726d48Sopenharmony_ci        for (let i = 0; i < dataList.length; i++) {
329fb726d48Sopenharmony_ci            let itemDiv = document.createElement('div');
330fb726d48Sopenharmony_ci            itemDiv!.style.visibility = 'hidden';
331fb726d48Sopenharmony_ci            itemDiv.className = 'analysisItem';
332fb726d48Sopenharmony_ci            // 生成标题
333fb726d48Sopenharmony_ci            let titleDiv = document.createElement('div');
334fb726d48Sopenharmony_ci            titleDiv.className = 'title item-name';
335fb726d48Sopenharmony_ci            titleDiv!.innerText = `问题${i + 1}:${dataList[i].type}`;
336fb726d48Sopenharmony_ci            // 生成时间
337fb726d48Sopenharmony_ci            let timeDiv = document.createElement('div');
338fb726d48Sopenharmony_ci            timeDiv.className = 'item two';
339fb726d48Sopenharmony_ci            // 获取每一个诊断项的时间
340fb726d48Sopenharmony_ci            let timeList = new Array();
341fb726d48Sopenharmony_ci            dataList[i].trace_info.forEach((v: any) => {
342fb726d48Sopenharmony_ci                timeList.push(getTimeString(v.ts / 1000000));
343fb726d48Sopenharmony_ci            });
344fb726d48Sopenharmony_ci            timeDiv!.innerHTML = `<span class="item-name">发生时间:</span>${timeList.join(',')}`
345fb726d48Sopenharmony_ci            // 生成问题原因
346fb726d48Sopenharmony_ci            let reasonDiv = document.createElement('div');
347fb726d48Sopenharmony_ci            reasonDiv.className = 'item';
348fb726d48Sopenharmony_ci            reasonDiv!.innerHTML = `<span class="item-name">问题原因:</span>${dataList[i].description}`;
349fb726d48Sopenharmony_ci            itemDiv.appendChild(titleDiv);
350fb726d48Sopenharmony_ci            itemDiv.appendChild(timeDiv);
351fb726d48Sopenharmony_ci            itemDiv.appendChild(reasonDiv);
352fb726d48Sopenharmony_ci            // 生成优化建议
353fb726d48Sopenharmony_ci            let suggestonDiv = document.createElement('div');
354fb726d48Sopenharmony_ci            suggestonDiv.className = 'item two';
355fb726d48Sopenharmony_ci            let suggestionText = '';
356fb726d48Sopenharmony_ci            this.token = await SpStatisticsHttpUtil.getAItoken();
357fb726d48Sopenharmony_ci            suggestionText = await this.getSuggestion(dataList[i].description, itemDiv, suggestonDiv);
358fb726d48Sopenharmony_ci            this.reportContent += `问题${i + 1}:${dataList[i].type}\n\n时间:${timeList.join(',')}\n\n问题原因:${dataList[i].description}\n\n优化建议:${suggestionText}\n\n\n`;
359fb726d48Sopenharmony_ci        }
360fb726d48Sopenharmony_ci        this.loadingItem!.style.display = 'none';
361fb726d48Sopenharmony_ci        this.downloadBtn!.style.display = 'inline-block';
362fb726d48Sopenharmony_ci    }
363fb726d48Sopenharmony_ci
364fb726d48Sopenharmony_ci    // 发送请求获取优化建议并渲染页面
365fb726d48Sopenharmony_ci    async getSuggestion(description: string, itemDiv: HTMLDivElement | null | undefined, suggestonDiv: HTMLDivElement | null | undefined) {
366fb726d48Sopenharmony_ci        let suggestion = await SpStatisticsHttpUtil.askAi({
367fb726d48Sopenharmony_ci            token: this.token,
368fb726d48Sopenharmony_ci            question: description + ',请问该怎么优化?',
369fb726d48Sopenharmony_ci            collection: ''
370fb726d48Sopenharmony_ci        });
371fb726d48Sopenharmony_ci        suggestonDiv!.innerHTML = `<span class="item-name">优化建议:</span>${suggestion}`;
372fb726d48Sopenharmony_ci        itemDiv!.appendChild(suggestonDiv!);
373fb726d48Sopenharmony_ci        // 吧loading放到最后面
374fb726d48Sopenharmony_ci        this.draftList!.insertBefore(itemDiv!, this.loadingItem!);
375fb726d48Sopenharmony_ci        itemDiv!.style.visibility = 'visible';
376fb726d48Sopenharmony_ci        itemDiv!.style.animation = 'opcityliner 3s';
377fb726d48Sopenharmony_ci        return suggestion;
378fb726d48Sopenharmony_ci    }
379fb726d48Sopenharmony_ci
380fb726d48Sopenharmony_ci    cacheDb(fileName: string | null) {
381fb726d48Sopenharmony_ci        threadPool.submit(
382fb726d48Sopenharmony_ci            'download-db',
383fb726d48Sopenharmony_ci            '',
384fb726d48Sopenharmony_ci            {},
385fb726d48Sopenharmony_ci            (reqBufferDB: Uint8Array) => {
386fb726d48Sopenharmony_ci                // 存入缓存
387fb726d48Sopenharmony_ci                caches.open(`${fileName}.db`).then((cache) => {
388fb726d48Sopenharmony_ci                    let headers = new Headers();
389fb726d48Sopenharmony_ci                    headers.append('Content-Type', 'application/octet-stream');
390fb726d48Sopenharmony_ci                    headers.append('Content-Transfer-Encoding', 'binary')
391fb726d48Sopenharmony_ci                    return cache
392fb726d48Sopenharmony_ci                        .put(
393fb726d48Sopenharmony_ci                            `${fileName}.db`,
394fb726d48Sopenharmony_ci                            new Response(reqBufferDB, {
395fb726d48Sopenharmony_ci                                status: 200,
396fb726d48Sopenharmony_ci                            })
397fb726d48Sopenharmony_ci                        );
398fb726d48Sopenharmony_ci                });
399fb726d48Sopenharmony_ci            },
400fb726d48Sopenharmony_ci            'download-db'
401fb726d48Sopenharmony_ci        );
402fb726d48Sopenharmony_ci    }
403fb726d48Sopenharmony_ci
404fb726d48Sopenharmony_ci    // websocket通信回调注册
405fb726d48Sopenharmony_ci    webSocketCallBack = (cmd: number, result: Uint8Array) => {
406fb726d48Sopenharmony_ci        const decoder = new TextDecoder();
407fb726d48Sopenharmony_ci        const jsonString = decoder.decode(result);
408fb726d48Sopenharmony_ci        let jsonRes = JSON.parse(jsonString);
409fb726d48Sopenharmony_ci        // db文件写入成功
410fb726d48Sopenharmony_ci        if (cmd === 2) {
411fb726d48Sopenharmony_ci            SpAiAnalysisPage.isRepeatedly = true;
412fb726d48Sopenharmony_ci            this.initiateDiagnosis();
413fb726d48Sopenharmony_ci        }
414fb726d48Sopenharmony_ci        // 诊断结果,resultCode===0:失败;resultCode===1:成功
415fb726d48Sopenharmony_ci        if (cmd === 4) {
416fb726d48Sopenharmony_ci            //     需要处理
417fb726d48Sopenharmony_ci            if (jsonRes.resultCode !== 0) {
418fb726d48Sopenharmony_ci                console.log('错误');
419fb726d48Sopenharmony_ci            }
420fb726d48Sopenharmony_ci            let dataList = JSON.parse(jsonRes.resultMessage);
421fb726d48Sopenharmony_ci            // 整理数据,渲染数据
422fb726d48Sopenharmony_ci            this.renderData(dataList);
423fb726d48Sopenharmony_ci        }
424fb726d48Sopenharmony_ci    }
425fb726d48Sopenharmony_ci
426fb726d48Sopenharmony_ci    // 发起诊断
427fb726d48Sopenharmony_ci    initiateDiagnosis() {
428fb726d48Sopenharmony_ci        let requestBodyObj = {
429fb726d48Sopenharmony_ci            type: 0
430fb726d48Sopenharmony_ci        }
431fb726d48Sopenharmony_ci        let requestBodyString = JSON.stringify(requestBodyObj);
432fb726d48Sopenharmony_ci        let requestBody = new TextEncoder().encode(requestBodyString);
433fb726d48Sopenharmony_ci        WebSocketManager.getInstance()!.sendMessage(TypeConstants.DIAGNOSIS_TYPE, TypeConstants.DIAGNOSIS_CMD, requestBody);
434fb726d48Sopenharmony_ci    }
435fb726d48Sopenharmony_ci
436fb726d48Sopenharmony_ci    initHtml(): string {
437fb726d48Sopenharmony_ci        return SpAiAnalysisPageHtml;
438fb726d48Sopenharmony_ci    }
439fb726d48Sopenharmony_ci}