@@ -0,0 +1 @@ | |||
@@ -0,0 +1 @@ | |||
<div #chart style="width: 100%; height: 100%;"></div> |
@@ -0,0 +1,120 @@ | |||
import { Component, OnInit, AfterViewInit, OnDestroy, OnChanges, SimpleChanges, Input, ViewChild, ElementRef } from '@angular/core'; | |||
import * as echarts from 'echarts'; | |||
@Component({ | |||
selector: 'app-chart-component', | |||
standalone: true, | |||
templateUrl: './chart-component.component.html', | |||
styleUrls: ['./chart-component.component.css'] | |||
}) | |||
export class ChartComponentComponent implements OnInit, OnDestroy, OnChanges { | |||
@ViewChild('chart', { static: true }) | |||
chartContainer!: ElementRef; | |||
private chartInstance: echarts.ECharts | null = null; | |||
// 接收外部传入的配置项(例如:柱状图、折线图等配置) | |||
@Input() options: echarts.EChartsOption = {}; | |||
/** 默认样式 */ | |||
defaultTooltipOptions = { | |||
title: { | |||
textStyle: { | |||
color: "#ffffff" | |||
}, | |||
}, | |||
backgroundColor: "#100c2A", | |||
legend: { | |||
textStyle: { | |||
color: '#ffffff' | |||
}, | |||
}, | |||
tooltip: { | |||
trigger: 'item', | |||
borderColor: '#00eff8', | |||
backgroundColor: '#12192C', | |||
padding: [6, 14, 6, 14], | |||
textStyle: { | |||
fontSize: 14, | |||
color: '#74FAFB', | |||
}, | |||
position: 'top', | |||
axisPointer: { | |||
type: 'shadow' | |||
} | |||
}, | |||
grid: { | |||
left: '3%', | |||
right: '3%', | |||
bottom: '3%', | |||
containLabel: true | |||
}, | |||
toolbox: { | |||
show: false, | |||
feature: { | |||
dataView: { show: true, readOnly: false }, | |||
magicType: { show: true, type: ['line', 'bar'] }, | |||
restore: { show: true }, | |||
saveAsImage: { show: true } | |||
} | |||
}, | |||
calculable: true, | |||
xAxis: [ | |||
{ | |||
type: 'category', | |||
// prettier-ignore | |||
data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] | |||
} | |||
], | |||
yAxis: [ | |||
{ | |||
type: 'value' | |||
} | |||
], | |||
} | |||
constructor() { } | |||
ngOnInit(): void { | |||
console.log('ChartComponentComponent ngOnInit'); | |||
this.initEcharts(); | |||
} | |||
ngOnChanges(changes: SimpleChanges): void { | |||
if (changes['options'] && !changes['options'].isFirstChange()) { | |||
console.log('ChartComponentComponent ngOnChanges'); | |||
this.updateChartOptions(); | |||
} | |||
} | |||
ngOnDestroy(): void { | |||
if (this.chartInstance) { | |||
console.log('ChartComponentComponent ngOnInit'); | |||
this.chartInstance.dispose(); | |||
} | |||
} | |||
initEcharts(): void { | |||
const chartDom = this.chartContainer.nativeElement; | |||
this.chartInstance = echarts.init(chartDom); | |||
// 设置默认的tooltip配置,如果外部传入了tooltip则会覆盖这里的设置 | |||
// 合并默认和外部传入的配置项 | |||
const mergedOptions = { | |||
...this.defaultTooltipOptions, | |||
...this.options | |||
}; | |||
this.chartInstance.setOption(mergedOptions); | |||
} | |||
updateChartOptions(): void { | |||
if (this.chartInstance) { | |||
this.chartInstance.setOption(this.options); | |||
} | |||
} | |||
} |
@@ -75,9 +75,13 @@ | |||
<div nz-col nzSpan="8"> | |||
<data-v-card title="化验结果" [showSetting]="true"> | |||
<div class="centered-element"> | |||
<app-chart-component [options]="chart_options1" style="width: 26rem; height: 11rem;" /> | |||
</div> | |||
<div class="centered-element"> | |||
<div id="d1" style="width: 26rem; height: 11rem;"> | |||
</div> | |||
</div> | |||
<div class="centered-element"> | |||
<div id="d2" style="width: 26rem; height: 11rem; margin-top: 0.4rem;"> | |||
@@ -1,3 +1,4 @@ | |||
/* stylelint-disable comment-empty-line-before */ | |||
.dashboard-container { | |||
width: 20rem; | |||
height: 10rem; | |||
@@ -12,18 +12,21 @@ import { NzProgressModule } from 'ng-zorro-antd/progress'; | |||
import { NzBadgeModule } from 'ng-zorro-antd/badge'; | |||
import { Subscription } from 'rxjs'; | |||
import { IMqttMessage, MqttService } from 'ngx-mqtt'; | |||
import { ChartComponentComponent } from './chart-component/chart-component.component'; | |||
@Component({ | |||
selector: 'app-data-v-s1', | |||
standalone: true, | |||
imports: [NzBadgeModule, NzProgressModule, AgGridAngular, DataVCardComponent, DataVTitleComponent, ...SHARED_IMPORTS], | |||
templateUrl: './s1.component.html', | |||
styleUrls: ['./s1.component.less'] | |||
styleUrls: ['./s1.component.less'], | |||
imports: [NzBadgeModule, NzProgressModule, AgGridAngular, DataVCardComponent, DataVTitleComponent, ...SHARED_IMPORTS, ChartComponentComponent] | |||
}) | |||
export class DataVS1Component implements OnInit { | |||
private readonly http = inject(_HttpClient); | |||
private readonly modal = inject(ModalHelper); | |||
private c1OptionC = { | |||
chart_options1 = {} | |||
c1OptionC: echarts.EChartsOption = { | |||
series: [ | |||
{ | |||
type: 'gauge', | |||
@@ -234,7 +237,7 @@ export class DataVS1Component implements OnInit { | |||
const messagePayload = JSON.parse(message.payload.toString()); | |||
console.log('Received message as object: ', messagePayload.msg); | |||
this.c1OptionC.series[0].data[0].value = messagePayload.c1_value; | |||
this.c1Chart.setOption(this.c1OptionC); | |||
}); | |||
} | |||
@@ -472,6 +475,122 @@ export class DataVS1Component implements OnInit { | |||
] | |||
}; | |||
this.chart_options1 = { | |||
title: { | |||
textStyle: { | |||
color: "#ffffff" | |||
}, | |||
text: '全水', | |||
subtext: '(kg/kg)', | |||
}, | |||
legend: { | |||
data: ['测量值', '上限值', '下限值',] | |||
}, | |||
calculable: true, | |||
xAxis: [ | |||
{ | |||
axisLine: { | |||
lineStyle: { | |||
color: [ | |||
[0.25, '#74FAFB'], | |||
[0.5, '#74FAFB'], | |||
[0.75, '#74FAFB'], | |||
[1, '#74FAFB'] | |||
] | |||
} | |||
}, | |||
position: 'bottom', | |||
type: 'category', | |||
data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] | |||
} | |||
], | |||
yAxis: [ | |||
{ | |||
type: 'value' | |||
} | |||
], | |||
series: [ | |||
{ | |||
name: '测量值', | |||
type: 'line', | |||
data: [100, 155, 139, 199, 220, 160, 120, 182.2, 150, 155, 160, 180], | |||
markPoint: { | |||
data: [ | |||
{ name: '最大值', value: 220, xAxis: 4, yAxis: 220 }, | |||
{ name: '最小值', value: 100, xAxis: 0, yAxis: 100 } | |||
] | |||
}, | |||
markLine: { | |||
data: [{ type: 'average', name: '平均值' }] | |||
} | |||
}, | |||
{ | |||
type: 'custom', | |||
name: 'error', | |||
itemStyle: { | |||
borderWidth: 1.5 | |||
}, | |||
renderItem: function (_params: any, api: any) { | |||
var xValue = api.value(0); | |||
var highPoint = api.coord([xValue, api.value(1)]); | |||
var lowPoint = api.coord([xValue, api.value(2)]); | |||
var halfWidth = api.size([1, 0])[0] * 0.1; | |||
var style = api.style({ | |||
stroke: api.visual('color'), | |||
fill: undefined | |||
}); | |||
return { | |||
type: 'group', | |||
children: [ | |||
{ | |||
type: 'line', | |||
transition: ['shape'], | |||
shape: { | |||
x1: highPoint[0] - halfWidth, | |||
y1: highPoint[1], | |||
x2: highPoint[0] + halfWidth, | |||
y2: highPoint[1] | |||
}, | |||
style: style | |||
}, | |||
{ | |||
type: 'line', | |||
transition: ['shape'], | |||
shape: { | |||
x1: highPoint[0], | |||
y1: highPoint[1], | |||
x2: lowPoint[0], | |||
y2: lowPoint[1] | |||
}, | |||
style: style | |||
}, | |||
{ | |||
type: 'line', | |||
transition: ['shape'], | |||
shape: { | |||
x1: lowPoint[0] - halfWidth, | |||
y1: lowPoint[1], | |||
x2: lowPoint[0] + halfWidth, | |||
y2: lowPoint[1] | |||
}, | |||
style: style | |||
} | |||
] | |||
}; | |||
}, | |||
encode: { | |||
x: 0, | |||
y: [1, 2] | |||
}, | |||
data: errorData, | |||
z: 100 | |||
} | |||
] | |||
}; | |||
var optionD2; | |||
optionD2 = { | |||
title: { | |||