import { HttpClient } from '@angular/common/http'; import { Component, OnInit, ViewContainerRef, ElementRef } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import * as echarts from 'echarts'; import { NzModalService } from 'ng-zorro-antd/modal'; import { GetOutOfLineDetailsComponent } from '../today-warning/get-out-of-line-details/get-out-of-line-details.component'; import * as moment from 'moment'; import { fromEvent } from 'rxjs'; import { debounceTime } from 'rxjs/operators'; import { Router } from '@angular/router'; import { DispositionComponent } from '../disposition/disposition.component'; import { NzMessageService } from 'ng-zorro-antd/message'; import { DisposeequipmentComponent } from '../warning-statistics-list/disposeequipment/disposeequipment.component'; @Component({ selector: 'app-criminal-records', templateUrl: './criminal-records.component.html', styleUrls: ['./criminal-records.component.scss'] }) export class CriminalRecordsComponent implements OnInit { validateForm!: FormGroup; constructor(private http: HttpClient, private fb: FormBuilder, private router: Router, private modal: NzModalService, private viewContainerRef: ViewContainerRef, private element: ElementRef, private message: NzMessageService) { } myChart: any //左侧饼图 option = { color: ['#FF4B65', '#23D9FF', '#608AFF', '#B2FF6D', '#FFFF99', '#C4E2FC', '#FF7F00', '#0090FF', '#FFD634', '#105597', '#FF4B65', '#23D9FF', '#71FFF5', '#B2FF6D'], tooltip: { trigger: 'item'//触发类型 }, series: [ { // name: 'Access From', type: 'pie', radius: ['58%', '75%'],//内半径外,外半径 left: '0', top: '9%', avoidLabelOverlap: false,//防止标签重叠策略 label: {//每一个标签外网延伸的引导说明 show: false, position: 'outside' }, labelLine: {//引导线 show: true, showAbove: true }, emphasis: {//中间高亮区域 label: { show: false, fontSize: '40', fontWeight: 'bold' } }, data: [ ], tooltip: {//鼠标移入提示 position: 'right', padding: [14, 19], backgroundColor: 'rgba(28, 129, 218, 0.4)', textStyle: { color: '#fff', fontSize: 12 }, formatter: "{b} : {c} ({d}%)" } } ] }; mybarChart: any //柱状图 baroption = { xAxis: { type: 'category', data: [], axisLine: { show: false, lineStyle: { color: '#91CCFF' } }, axisTick: {//刻度线 show: false }, inverse: true }, yAxis: { type: 'value', nameTextStyle: { color: '#C4E2FC' }, splitLine: {//分割线 lineStyle: { color: ['#0f4374'], width: 2 } }, axisTick: {//刻度线 show: false }, axisLine: {//轴线 show: false, lineStyle: { color: '#C4E2FC' } } }, tooltip: { // trigger: 'axis' }, series: [ { data: [], type: 'bar', itemStyle: { color: { type: 'linear', x: 0, y: 0, x2: 0, y2: 1, colorStops: [{ offset: 0, color: '#23F0FF' // 0% 处的颜色 }, { offset: 1, color: 'rgba(35, 153, 255, 0.1)' // 100% 处的颜色 }], global: false // 缺省为 false } }, barWidth: '25%' }, { data: [], type: 'line', symbol: 'circle', symbolSize: 8, label: { show: true }, itemStyle: { color: '#fff', shadowColor: '#fff', shadowBlur: 10 }, lineStyle: { color: '#FFCC8A', width: 1 } } ], grid: { left: '42px', right: '30px', bottom: '38px', top: '80px' } }; baroption2 = { xAxis: { type: 'value', show: false }, tooltip: { // trigger: 'axis' }, yAxis: { type: 'category', data: [], axisLine: { show: false, lineStyle: { color: '#91CCFF', } }, axisTick: {//刻度线 show: false }, axisLabel: { formatter: function (value, index) { let newParamsName = ''; const paramsNameNumber = value.length; const provideNumber = 10; const rowNumber = Math.ceil(paramsNameNumber / provideNumber); if (paramsNameNumber > provideNumber) { for (let p = 0; p < rowNumber; p++) { let tempStr = ''; const start = p * provideNumber; const end = start + provideNumber; if (p == rowNumber - 1) { tempStr = value.substring(start, paramsNameNumber); } else { tempStr = value.substring(start, end) + '\n'; } newParamsName += tempStr; } } else { newParamsName = value; } // 格式化成月/日,只在第一个刻度显示年份 return '{s|·}' + `{a|${newParamsName}}`; }, rich: { a: { color: '#C4E2FC', padding: [0, 0, 0, 8], }, s: { color: '#fff', borderWidth: 1, borderColor: '#23D9FF', backgroundColor: '#fff', width: 4, height: 4, shadowBlur: 3, shadowColor: "#fff" } } }, inverse: true }, series: { label: { // 柱图头部显示值 show: true, position: "right", color: "#fff", fontSize: 12, formatter: '{c}', offset: [6, 0] }, data: [], type: 'bar', itemStyle: { color: { type: 'linear', x: 0, y: 0, x2: 1, y2: 0, colorStops: [{ offset: 0, color: '#063d72' // 0% 处的颜色 }, { offset: 1, color: '#FF9963' // 100% 处的颜色 }], global: false // 缺省为 false } }, barWidth: '36%', } , grid: { left: '150px', right: '80px', bottom: '3px', top: '36px' } } getThirtyDays() { //获取当前日期 let myDate = new Date(); var nowY = myDate.getFullYear(); var nowM = myDate.getMonth() + 1; var nowD = myDate.getDate(); var enddateStr = nowY + "-" + (nowM < 10 ? "0" + nowM : nowM) + "-" + (nowD < 10 ? "0" + nowD : nowD);//当前日期 var enddate = new Date(enddateStr); //获取三十天前日期 var lw = new Date(new Date().getTime() - 1000 * 60 * 60 * 24 * 30);//最后一个数字30可改,30天的意思 var lastY = lw.getFullYear(); var lastM = lw.getMonth() + 1; var lastD = lw.getDate(); var startdateStr = lastY + "-" + (lastM < 10 ? "0" + lastM : lastM) + "-" + (lastD < 10 ? "0" + lastD : lastD);//三十天之前日期 var startDate = new Date(startdateStr); const dateList = [] while (true) { startDate.setDate(startDate.getDate() + 1) if (startDate.getTime() <= enddate.getTime()) { if (startDate.getDate() < 10) { // startDate.getFullYear() 获取年,此处没加上年份 dateList.push((startDate.getMonth() + 1) + '.0' + startDate.getDate()) } else { dateList.push((startDate.getMonth() + 1) + '.' + startDate.getDate()) } } else { break } } return dateList; } isEcharts: boolean = true isEchartsShow() { this.isEcharts = !this.isEcharts } startdate enddate isMisinformation: boolean = false//误报按钮的显隐 ngOnInit(): void { let loginUserInfo if (sessionStorage.getItem('isGasStation') == 'true') { loginUserInfo = JSON.parse(sessionStorage.getItem('userdataOfgasstation')) } else { loginUserInfo = JSON.parse(sessionStorage.getItem('userdata')) } if (loginUserInfo.roles.find((item) => { return item.name == 'ViolationPositiveCensorer' })) { this.isMisinformation = true } else { this.isMisinformation = false } //当前日期 let myDate: any = new Date(); let nowY = myDate.getFullYear(); let nowM = myDate.getMonth() + 1; let nowD = myDate.getDate(); this.enddate = nowY + "-" + (nowM < 10 ? "0" + nowM : nowM) + "-" + (nowD < 10 ? "0" + nowD : nowD);//当前日期 //获取三十天前日期 let lw = new Date(myDate - 1000 * 60 * 60 * 24 * 30);//最后一个数字30可改,30天的意思 let lastY = lw.getFullYear(); let lastM = lw.getMonth() + 1; let lastD = lw.getDate(); this.startdate = lastY + "-" + (lastM < 10 ? "0" + lastM : lastM) + "-" + (lastD < 10 ? "0" + lastD : lastD);//三十天之前日期 this.validateForm = this.fb.group({ level: [null], type: [null], event: [null], disposalState: [null], site: [null], datePicker: [[this.startdate, this.enddate]], misinformation: ['true'], }); // 饼图 this.myChart = echarts.init(document.getElementById('piechart')); this.myChart.setOption(this.option); //柱状折线图 this.mybarChart = echarts.init(document.getElementById('barchart')); this.mybarChart.setOption(this.baroption); this.warningType() this.getViolateRecordList() this.getAggregations() } //刷新饼图图表数据 num echartsData: any refreshPieData(data) { //饼图 let option = this.myChart.getOption(); var num = 0 data.pieTop.forEach(element => { num += element.count element.name = element.key element.value = element.count }); this.num = num option.series[0].data = data.pieTop; this.myChart.setOption(option); } //刷新柱状折线图表数据 refreshBarLineData(data, type) { console.log('统计图表数据', data) //柱状图 let option = this.mybarChart.getOption(); console.log('柱图option', option) if (type == 'month') {//近一个月柱状折线图 option = this.baroption let monthArr = [] let valuedata = [] data.timeTop.forEach(element => { monthArr.push(moment(element.key).format('MM.DD')) valuedata.push(element.count) }); option.xAxis.data = monthArr option.series[0].data = valuedata option.series[1].data = valuedata } else if (type == 'eventTop') { option = this.baroption2 let ydata = [] let valuedata = [] data.eventTop.forEach(element => { ydata.push(element.key) valuedata.push(element.count) }); option.yAxis.data = ydata option.series.data = valuedata } else if (type == 'siteTop') { option = this.baroption2 let ydata = [] let valuedata = [] data.siteTop.forEach(element => { ydata.push(element.key) valuedata.push(element.count) }); option.yAxis.data = ydata option.series.data = valuedata } this.mybarChart.setOption(option); } //获取统计信息 chartsSpin: boolean = false getAggregations() { this.chartsSpin = true let ViolationIds = [] if (this.validateForm.value.type) { this.warningTypesDetails.forEach(item => { item.id ? ViolationIds.push(item.id) : null }); } let body: any = { organizationUnitId: JSON.parse(sessionStorage.getItem('userdataOfgasstation')).organization.id, isContainsChildren: true, ViolateTime: this.validateForm.value.datePicker ? [moment(this.validateForm.value.datePicker[0]).format('yyyy-MM-DD'), moment(this.validateForm.value.datePicker[1]).format('yyyy-MM-DD')] : null } this.validateForm.value.level ? body.level = this.validateForm.value.level : null this.validateForm.value.site ? body.violateArea = this.validateForm.value.site : null ViolationIds.length != 0 ? body.violationType = ViolationIds : null this.http.post('/api/services/app/ViolateRecord/Aggregations', body).subscribe((data: any) => { this.echartsData = data.result this.chartsSpin = false this.refreshPieData(data.result) this.refreshBarLineData(this.echartsData, 'month') }) } //获得违规记录列表 SkipCount: string = '0' MaxResultCount: string = '50' list: any = [] totalCount: string tableSpin: boolean = false getViolateRecordList() { let ViolationIds = [] if (this.validateForm.value.event) { ViolationIds = this.validateForm.value.event } if (this.validateForm.value.type && !this.validateForm.value.event) { this.warningTypesDetails.forEach(item => { item.id ? ViolationIds.push(item.id) : null }); } let disposalState if (this.validateForm.value.disposalState == '0') { disposalState = true } else if (this.validateForm.value.disposalState == '1') { disposalState = false } else { disposalState = null } let params = { Level: this.validateForm.value.level, ViolationIds: ViolationIds, ViolateAreas: this.validateForm.value.site, OrganizationUnitId: JSON.parse(sessionStorage.getItem('userdataOfgasstation')).organization.id, IsContainsChildren: 'true', ViolateTime: this.validateForm.value.datePicker ? [moment(this.validateForm.value.datePicker[0]).format('yyyy-MM-DD'), moment(this.validateForm.value.datePicker[1]).format('yyyy-MM-DD')] : null, IsHandled: disposalState, SkipCount: this.SkipCount, MaxResultCount: this.MaxResultCount, Positive: this.validateForm.value.misinformation } this.tableSpin = true this.http.get('/api/services/app/ViolateRecord/GetAll', { params: params }).subscribe((data: any) => { this.list = this.list.concat(data.result.items); this.list = [...this.list] // this.list = data.result.items this.totalCount = data.result.totalCount console.log('违规记录列表', data) this.tableSpin = false }) } ngAfterViewInit(): void { fromEvent(this.element.nativeElement.querySelector(`#tbody`) as HTMLCanvasElement, 'scroll').pipe(debounceTime(100)).subscribe((event: any) => { //监听 DOM 滚动事件 if (event.target.scrollHeight - (event.target.scrollTop + event.target.clientHeight) <= 10) { if (this.totalCount > this.list.length) { console.log('需要加载数据了', event) this.SkipCount = String(Number(this.SkipCount) + 50) this.getViolateRecordList() } } }); } submitForm(): void { for (const i in this.validateForm.controls) { this.validateForm.controls[i].markAsDirty(); this.validateForm.controls[i].updateValueAndValidity(); } this.list = [] this.SkipCount = '0' this.getViolateRecordList() } resetForm(e: MouseEvent): void { e.preventDefault(); this.validateForm.reset(); for (const key in this.validateForm.controls) { this.validateForm.controls[key].markAsPristine(); this.validateForm.controls[key].updateValueAndValidity(); } this.validateForm.patchValue({ datePicker: [this.startdate, this.enddate], misinformation: 'true' }); this.list = [] this.SkipCount = '0' this.getViolateRecordList() } //预警类型接口 warningTypesDetails: any warningTypesDetailsCopy: any warningTypes: any //预警接口数据 warningTypesCopy: any warningLevels: any warningLevelsCopy: any warningType() { this.http.get('/api/services/app/Violation/GetAllList').subscribe((data: any) => { this.warningTypesDetails = JSON.parse(JSON.stringify(data.result)) this.warningTypesDetailsCopy = JSON.parse(JSON.stringify(data.result)) //原始数据备份 this.warningTypes = (data.result as any).groupBy((t) => { return t.violationType }); this.warningTypesCopy = (data.result as any).groupBy((t) => { return t.violationType }) this.warningLevels = (data.result as any).groupBy((t) => { return t.level }); this.warningLevelsCopy = (data.result as any).groupBy((t) => { return t.level }) this.warningLevels.sort(function (a, b) { if (a.key < b.key) { return -1; } else if (a.key == b.key) { return 0; } else { return 1; } }); this.warningLevelsCopy.sort(function (a, b) { if (a.key < b.key) { return -1; } else if (a.key == b.key) { return 0; } else { return 1; } }); // console.log(111, this.warningTypesDetails) // console.log(222, this.warningTypesCopy) // console.log(333, this.warningLevels) }) } typeChange(e) { if (!e) { this.warningTypesDetails = this.warningTypesDetailsCopy this.warningLevels = this.warningLevelsCopy return } this.warningTypes.forEach(element => { if (element.key == e) { this.warningTypesDetails = element this.warningLevels = (element as any).groupBy((t) => { return t.level }); } }); this.validateForm.patchValue({ event: null, }); } levelChange(e) { if (!e) { this.warningTypesDetails = this.warningTypesDetailsCopy this.warningTypes = this.warningTypesCopy this.validateForm.patchValue({ type: null, }); return } this.warningLevels.forEach(element => { if (element.key == e) { this.warningTypesDetails = element this.warningTypes = (element as any).groupBy((t) => { return t.violationType }); } }); this.validateForm.patchValue({ event: null, }); } selectedType = '分布' selectedRankingType = '站点排名' echartClick(type) { this.selectedType = type this.mybarChart.dispose() this.mybarChart = echarts.init(document.getElementById('barchart')); if (type == '排名') { console.log(this.selectedRankingType) this.refreshBarLineData(this.echartsData, 'eventTop') } else { this.refreshBarLineData(this.echartsData, 'month') } } look(item) { if (item.violation.eventSystemName == '灭火器维护') { item.violatedItemSnapshotObj = JSON.parse(item.violatedItemSnapshot) const modal = this.modal.create({ nzContent: DisposeequipmentComponent, nzViewContainerRef: this.viewContainerRef, nzWidth: 380, nzBodyStyle: { 'border': '1px solid #91CCFF', 'border-radius': '0px', 'padding': '7px', 'box-shadow': '0 0 8px 0 #fff', 'background-image': 'linear-gradient(#003665, #000f25)' }, nzComponentParams: { data: item }, nzFooter: null, nzClosable: false, nzOnOk: async () => { if (instance.isScrap) { await new Promise(resolve => { let body = { id: item.violatedItemSnapshotObj.id, name: instance.copydata2.violatedItemSnapshotObj.name, storageLocation: instance.copydata2.violatedItemSnapshotObj.storageLocation, productionDate: moment(instance.copydata2.violatedItemSnapshotObj.productionDate).format('yyyy-MM-DD'), maintenanceDate: moment(instance.copydata2.violatedItemSnapshotObj.maintenanceDate).format('yyyy-MM-DD'), validityEndTime: moment(instance.copydata2.violatedItemSnapshotObj.validityEndTime).format('yyyy-MM-DD'), isScrapped: true, organizationUnitId: item.violatedItemSnapshotObj.organizationUnitId } this.http.put('/api/services/app/FireEquipment/Update', body).subscribe((data: any) => { let body = { id: item.id, handleRecord: '报废成功!' } this.http.post('/api/services/app/ViolateRecord/HandleViolateRecord', body).subscribe(data => { resolve(data) this.message.create('success', '报废成功!'); item.handleTime = new Date() return true }) }) }) } else { if (instance.validateForm.valid) { await new Promise(resolve => { let body = { id: item.violatedItemSnapshotObj.id, name: instance.validateForm.value.name, storageLocation: instance.validateForm.value.storageLocation, productionDate: moment(instance.validateForm.value.productionDate).format('yyyy-MM-DD'), maintenanceDate: moment(instance.validateForm.value.maintenanceDate).format('yyyy-MM-DD'), validityEndTime: moment(instance.validateForm.value.validityEndTime).format('yyyy-MM-DD'), organizationUnitId: item.violatedItemSnapshotObj.organizationUnitId } this.http.put('/api/services/app/FireEquipment/Update', body).subscribe((data: any) => { // item.violatedItemSnapshotObj = data.result let body = { id: item.id, handleRecord: '维保成功!' } this.http.post('/api/services/app/ViolateRecord/HandleViolateRecord', body).subscribe(data => { resolve(data) this.message.create('success', '维保成功!'); item.handleTime = new Date() return true }) }) }) } else { this.message.create('warning', '请填写完整!'); return false } } } }); const instance = modal.getContentComponent(); } else { const modal = this.modal.create({ nzContent: GetOutOfLineDetailsComponent, nzWrapClassName: "vertical-center-modal", nzViewContainerRef: this.viewContainerRef, nzWidth: (document.documentElement.clientHeight < 650 || document.documentElement.clientWidth < 1400) ? 1000 : 1200, nzBodyStyle: { 'border': '1px solid #6d9cc7', 'border-radius': '0px', 'padding': '0px', 'box-shadow': '0 0 8px 0 #fff', 'background': '#000D21', }, nzComponentParams: { data: item }, nzFooter: null, nzOnOk: async () => { } }); const instance = modal.getContentComponent(); } } goOilList() { this.router.navigate(['/records/petrolStation/oliunloadinglist']) } goWarningList() { this.router.navigate(['/records/petrolStation/warningstatisticslist']) } goMisinformationList() { this.router.navigate(['records/petrolStation/misinformationList']) } dispose(item) { console.log(item) const modal = this.modal.create({ nzContent: DispositionComponent, nzWrapClassName: "vertical-center-modal", nzViewContainerRef: this.viewContainerRef, nzWidth: 380, nzBodyStyle: { 'border': '1px solid #91CCFF', 'border-radius': '0px', 'padding': '7px', 'box-shadow': '0 0 8px 0 #fff', 'background-image': 'linear-gradient(#003665, #000f25)' }, nzComponentParams: {}, nzFooter: null, nzClosable: false, nzOnOk: async () => { if (instance.validateForm.valid) { await new Promise(resolve => { let body = { id: item.id, handleRecord: instance.validateForm.value.content } this.http.post('/api/services/app/ViolateRecord/HandleViolateRecord', body).subscribe(data => { resolve(data) this.message.create('success', '处置成功!'); item.handleTime = new Date() return true }) }) } else { this.message.create('warning', '请填写完整!'); return false } }, }); const instance = modal.getContentComponent(); } }