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 { SystemDetailsEnergy } from '../../../../bean/EnergyStruct'; 17import { BaseElement, element } from '../../../../../base-ui/BaseElement'; 18import { LitTable } from '../../../../../base-ui/table/lit-table'; 19import { SelectionParam } from '../../../../bean/BoxSelection'; 20import { SpHiSysEnergyChart } from '../../../chart/SpHiSysEnergyChart'; 21import { resizeObserver } from '../SheetUtils'; 22import { type LitSlicerTrack } from '../../../../../base-ui/slicer/lit-slicer'; 23import { 24 querySysLocationDetailsData, 25 querySysLockDetailsData, 26 querySystemWorkData 27} from "../../../../database/sql/SqlLite.sql"; 28 29@element('tabpane-system-details') 30export class TabPaneSystemDetails extends BaseElement { 31 private tblSystemDetails: LitTable | null | undefined; 32 private detailsTbl: LitTable | null | undefined; 33 private eventSource: Array<any> = []; 34 private detailsSource: Array<any> = []; 35 private boxDetails: HTMLDivElement | null | undefined; 36 private slicerTrack: LitSlicerTrack | null | undefined; 37 38 set data(valSystemDetails: SelectionParam | any) { 39 this.slicerTrack!.style.visibility = 'hidden'; 40 this.queryDataByDB(valSystemDetails); 41 } 42 43 connectedCallback() { 44 super.connectedCallback(); 45 resizeObserver(this.parentElement!, this.tblSystemDetails!); 46 } 47 48 initElements(): void { 49 this.boxDetails = this.shadowRoot?.querySelector<HTMLDivElement>('.box-details'); 50 this.tblSystemDetails = this.shadowRoot?.querySelector<LitTable>('#tb-system-data'); 51 this.detailsTbl = this.shadowRoot?.querySelector<LitTable>('#tb-system-details-data'); 52 this.slicerTrack = this.shadowRoot?.querySelector<LitSlicerTrack>('lit-slicer-track'); 53 this.tblSystemDetails!.addEventListener('row-click', (e) => { 54 this.detailsSource = []; 55 // @ts-ignore 56 let data = e.detail.data as SystemDetailsEnergy; 57 this.convertData(data); 58 }); 59 } 60 61 convertData(data: SystemDetailsEnergy) { 62 if (data.eventName === 'Event Name') { 63 this.slicerTrack!.style.visibility = 'hidden'; 64 this.detailsTbl!.dataSource = []; 65 this.boxDetails!.style.width = '100%'; 66 } else { 67 this.slicerTrack!.style.visibility = 'visible'; 68 this.detailsSource.push({ 69 key: 'EVENT_NAME : ', 70 value: data.eventName, 71 }); 72 this.detailsSource.push({ key: 'PID : ', value: data.pid }); 73 this.detailsSource.push({ key: 'UID : ', value: data.uid }); 74 if (data.eventName === 'GNSS_STATE') { 75 this.detailsSource.push({ key: 'STATE : ', value: data.state }); 76 } else if (data.eventName === 'POWER_RUNNINGLOCK') { 77 this.detailsSource.push({ key: 'TYPE : ', value: data.type }); 78 this.detailsSource.push({ key: 'STATE : ', value: data.state }); 79 this.detailsSource.push({ 80 key: 'LOG_LEVEL : ', 81 value: data.log_level, 82 }); 83 this.detailsSource.push({ key: 'NAME : ', value: data.name }); 84 this.detailsSource.push({ 85 key: 'MESSAGE : ', 86 value: data.message, 87 }); 88 this.detailsSource.push({ key: 'TAG : ', value: data.tag }); 89 } else { 90 this.detailsSource.push({ key: 'TYPE : ', value: data.type }); 91 this.detailsSource.push({ 92 key: 'WORK_ID : ', 93 value: data.workId, 94 }); 95 this.detailsSource.push({ key: 'NAME : ', value: data.name }); 96 this.detailsSource.push({ 97 key: 'INTERVAL : ', 98 value: data.interval, 99 }); 100 } 101 this.detailsTbl!.dataSource = this.detailsSource; 102 this.boxDetails!.style.width = '65%'; 103 } 104 this.detailsTblStyle(); 105 } 106 107 detailsTblStyle(){ 108 this.detailsTbl!.shadowRoot?.querySelectorAll<HTMLDivElement>('.tr').forEach((tr) => { 109 tr.style.gridTemplateColumns = '120px 1fr'; 110 }); 111 this.detailsTbl!.shadowRoot?.querySelectorAll<HTMLDivElement>('.td').forEach((td) => { 112 let item = td.getAttribute('title'); 113 td.style.fontSize = '14px'; 114 td.style.fontWeight = '400'; 115 if (item != null && item.indexOf(':') > -1) { 116 td.style.opacity = '0.9'; 117 td.style.lineHeight = '16px'; 118 } else { 119 td.style.opacity = '0.6'; 120 td.style.lineHeight = '20px'; 121 } 122 }); 123 } 124 125 queryDataByDB(val: SelectionParam | any) { 126 Promise.all([ 127 querySystemWorkData(val.rightNs), 128 querySysLockDetailsData(val.rightNs, 'POWER_RUNNINGLOCK'), 129 querySysLocationDetailsData(val.rightNs, 'GNSS_STATE'), 130 ]).then((result) => { 131 let itemList: Array<any> = []; 132 let systemWorkData = this.getSystemWorkData(result[0], val.leftNs, val.rightNs); 133 if (systemWorkData.length > 0) { 134 systemWorkData.forEach((item) => { 135 itemList.push(item); 136 }); 137 } 138 let systemLockData = this.getSystemLockData(result[1], val.leftNs); 139 if (systemLockData.length > 0) { 140 systemLockData.forEach((item) => { 141 itemList.push(item); 142 }); 143 } 144 let systemLocationData = this.getSystemLocationData(result[2], val.leftNs); 145 if (systemLocationData.length > 0) { 146 systemLocationData.forEach((item) => { 147 itemList.push(item); 148 }); 149 } 150 itemList.sort((leftData: any, rightData: any) => { 151 return leftData.ts - rightData.ts; 152 }); 153 this.eventSource = []; 154 this.eventSource.push({ 155 ts: 'Time', 156 interval: 0, 157 level: 0, 158 name: '', 159 state: 0, 160 tag: '', 161 type: '', 162 uid: 0, 163 pid: 0, 164 workId: '', 165 message: '', 166 log_level: '', 167 eventName: 'Event Name', 168 }); 169 this.tblSystemDetails!.recycleDataSource = this.eventSource.concat(itemList); 170 this.detailsTbl!.dataSource = []; 171 this.boxDetails!.style.width = '100%'; 172 this.tblSystemDetailsStyle(); 173 }); 174 } 175 176 tblSystemDetailsStyle(){ 177 this.tblSystemDetails?.shadowRoot?.querySelectorAll<HTMLDivElement>('.td').forEach((td) => { 178 td.style.fontSize = '14px'; 179 if (td.getAttribute('title') === 'Event Name' || td.getAttribute('title') === 'Time') { 180 td.style.fontWeight = '700'; 181 } else { 182 td.style.fontWeight = '400'; 183 td.style.opacity = '0.9'; 184 td.style.lineHeight = '16px'; 185 } 186 }); 187 } 188 189 private getSystemWorkData(data: Array<any>, leftNs: number, rightNs: number) { 190 let values = this.getConvertData(data); 191 let lifeCycleData: Array<any> = []; 192 let watchIndex: Array<string> = []; 193 for (let index = 0; index < values.length; index++) { 194 let filterData: any = values[index]; 195 if (filterData.name == SpHiSysEnergyChart.app_name) { 196 if (filterData.eventName.indexOf('WORK_ADD') > -1) { 197 watchIndex.push(filterData.workId); 198 let number = watchIndex.indexOf(filterData.workId); 199 lifeCycleData[number] = { 200 startData: {}, 201 endData: {}, 202 rangeData: [], 203 }; 204 lifeCycleData[number].startData = filterData; 205 let virtualEndData = JSON.parse(JSON.stringify(filterData)); 206 virtualEndData.ts = rightNs; 207 virtualEndData.eventName = 'WORK_REMOVE'; 208 lifeCycleData[number].endData = virtualEndData; 209 } else if (filterData.eventName.indexOf('WORK_REMOVE') > -1) { 210 let number = watchIndex.indexOf(filterData.workId); 211 if (number > -1) { 212 lifeCycleData[number].endData = filterData; 213 watchIndex[number] = number + filterData.ts; 214 } 215 } else { 216 lifeCycleData = this.getSysDataExtend(rightNs, watchIndex, filterData, lifeCycleData) 217 } 218 } 219 } 220 let resultData: Array<any> = []; 221 lifeCycleData.forEach((life: any) => { 222 if (life.endData.ts >= leftNs) { 223 let midData = life.rangeData; 224 midData.forEach((rang: any, index: number) => { 225 if (rang.eventName.indexOf('WORK_STOP') > -1 && rang.ts >= leftNs) { 226 resultData.push(life.startData); 227 if (index - 1 >= 0 && midData[index - 1].eventName.indexOf('WORK_START') > -1) { 228 resultData.push(midData[index - 1]); 229 } 230 resultData.push(rang); 231 } 232 }); 233 } 234 }); 235 return resultData; 236 } 237 238 getSysDataExtend( 239 rightNs: number, 240 watchIndex: Array<string>, 241 filterData: any, 242 lifeCycleData: any[] 243 ): any[]{ 244 let number = watchIndex.indexOf(filterData.workId); 245 if (number > -1) { 246 lifeCycleData[number].rangeData.push(filterData); 247 let virtualEndData = JSON.parse(JSON.stringify(filterData)); 248 virtualEndData.ts = rightNs; 249 virtualEndData.eventName = 'WORK_REMOVE'; 250 lifeCycleData[number].endData = virtualEndData; 251 } else { 252 if (filterData.eventName.indexOf('WORK_START') > -1) { 253 lifeCycleData.push({ 254 startData: {}, 255 endData: {}, 256 rangeData: [], 257 }); 258 watchIndex.push(filterData.workId); 259 number = watchIndex.indexOf(filterData.workId); 260 let virtualData = JSON.parse(JSON.stringify(filterData)); 261 if (filterData.ts > 0) { 262 virtualData.ts = 0; 263 } else { 264 virtualData.ts = filterData.ts - 1; 265 } 266 virtualData.eventName = 'WORK_ADD'; 267 lifeCycleData[number].startData = virtualData; 268 lifeCycleData[number].rangeData.push(filterData); 269 let virtualEndData = JSON.parse(JSON.stringify(filterData)); 270 virtualEndData.ts = rightNs; 271 virtualEndData.eventName = 'WORK_REMOVE'; 272 lifeCycleData[number].endData = virtualEndData; 273 } 274 } 275 return lifeCycleData; 276 } 277 278 private getSystemLocationData(data: Array<any>, leftNs: number) { 279 let values = this.getConvertData(data); 280 let fillMap: Map<any, any> = new Map<any, any>(); 281 let leftMap: Map<any, any> = new Map<any, any>(); 282 let watchIndex: Array<string> = []; 283 for (let index = 0; index < values.length; index++) { 284 let filterData: any = values[index]; 285 if (filterData.state.indexOf('start') > -1) { 286 leftMap.set(filterData.pid, filterData); 287 watchIndex.push(filterData.pid); 288 } else { 289 let i = watchIndex.indexOf(filterData.pid); 290 if (i > -1) { 291 fillMap.set(leftMap.get(filterData.pid), filterData); 292 delete watchIndex[i]; 293 leftMap.delete(filterData.pid); 294 } 295 } 296 } 297 298 let locationData: Array<any> = []; 299 fillMap.forEach((value, key) => { 300 if (value.ts >= leftNs) { 301 locationData.push(key); 302 locationData.push(value); 303 } 304 }); 305 leftMap.forEach((value, key) => { 306 locationData.push(value); 307 }); 308 return locationData; 309 } 310 311 private getSystemLockData(data: Array<any>, leftNs: number) { 312 let values = this.getConvertData(data); 313 let watchIndex: Array<string> = []; 314 let fillMap: Map<any, any> = new Map<any, any>(); 315 let leftMap: Map<any, any> = new Map<any, any>(); 316 for (let index = 0; index < values.length; index++) { 317 let filterData: any = values[index]; 318 if (filterData.tag.indexOf('ADD') > -1) { 319 leftMap.set(filterData.message, filterData); 320 watchIndex.push(filterData.message); 321 } else { 322 let i = watchIndex.indexOf(filterData.message); 323 if (i > -1) { 324 fillMap.set(leftMap.get(filterData.message), filterData); 325 delete watchIndex[i]; 326 leftMap.delete(filterData.message); 327 } 328 } 329 } 330 let lockData: Array<any> = []; 331 fillMap.forEach((value, key) => { 332 if (value.ts >= leftNs) { 333 lockData.push(key); 334 lockData.push(value); 335 } 336 }); 337 leftMap.forEach((value, key) => { 338 lockData.push(value); 339 }); 340 return lockData; 341 } 342 343 private getConvertData(data: Array<any>) { 344 let convertItem: any = {}; 345 data.forEach((item: any) => { 346 if (convertItem[item.ts + item.eventName] == undefined) { 347 convertItem[item.ts + item.eventName] = {}; 348 convertItem[item.ts + item.eventName]['ts'] = item.ts; 349 convertItem[item.ts + item.eventName]['eventName'] = item.eventName; 350 convertItem[item.ts + item.eventName][item.appKey.toLocaleLowerCase()] = item.appValue; 351 } else { 352 convertItem[item.ts + item.eventName][item.appKey.toLocaleLowerCase()] = item.appValue; 353 } 354 }); 355 // @ts-ignore 356 return Object.values(convertItem); 357 } 358 359 initHtml(): string { 360 return ` 361 <style> 362 :host{ 363 display: flex; 364 flex-direction: column; 365 padding: 10px 10px 0 10px; 366 } 367 .sys-detail-progress{ 368 bottom: 33px; 369 position: absolute; 370 height: 1px; 371 left: 0; 372 right: 0; 373 } 374 </style> 375 <div class="sys-detail-content" style="display: flex;flex-direction: column"> 376 <div style="display: flex;flex-direction: row"> 377 <lit-slicer style="width:100%"> 378 <div class="box-details" style="width: 100%"> 379 <lit-table id="tb-system-data" style="height: auto"> 380 <lit-table-column class="sys-detail-column" width="300px" title="" data-index="eventName" key="eventName" align="flex-start" order> 381 </lit-table-column> 382 <lit-table-column class="sys-detail-column" width="300px" title="" data-index="ts" key="ts" align="flex-start" order> 383 </lit-table-column> 384 </lit-table> 385 </div> 386 <lit-slicer-track ></lit-slicer-track> 387 <lit-table id="tb-system-details-data" no-head hideDownload style="height: auto;border-left: 1px solid var(--dark-border1,#e2e2e2)"> 388 <lit-table-column class="sys-detail-column" width="100px" title="" data-index="key" key="key" align="flex-start" > 389 </lit-table-column> 390 <lit-table-column class="sys-detail-column" width="1fr" title="" data-index="value" key="value" align="flex-start"> 391 </lit-table-column> 392 </lit-table> 393 </lit-slicer> 394 </div> 395 <lit-progress-bar class="progress sys-detail-progress"></lit-progress-bar> 396 </div> 397 `; 398 } 399} 400