refactor(ems/report-charts): 优化折线图配置和样式,提升响应式表现

- 统一各报表折线图的grid布局,添加containLabel确保标签显示完整
- 增强tooltip轴指示器,全部改为cross类型,提升交互体验
- 添加多种类型dataZoom,支持滑块与内置缩放,增强图表缩放控制
- 优化x轴标签显示,超长时间字符串自动截取,长图时旋转标签避免重叠
- y轴添加虚线辅助分割线,完善刻度格式化规则,提升数值可读性
- 降低折线符号尺寸,保持图表整洁,保障不同设备的展示效果
- 使用flex布局替代inline-block,完善图表容器响应式宽高适配
- 添加媒体查询,动态调节图表高度与宽度,适配不同屏幕尺寸
- 重构振动曲线图配置,抽象公共配置对象复用,减少冗余代码
master
zangch@mesnac.com 2 weeks ago
parent bc92f566a9
commit 97d4e685e3

@ -187,28 +187,55 @@ async function getChart() {
right: 0 right: 0
}, },
grid: { grid: {
top: '40', top: 60,
bottom: '15%', bottom: 80,
left: '3%', left: 60,
right: '3%' right: 40,
containLabel: true
}, },
tooltip: { tooltip: {
trigger: 'axis' trigger: 'axis'
}, },
dataZoom: [{ type: 'slider' }], dataZoom: [
{ type: 'slider', height: 20, bottom: 10, start: 0, end: 100 },
{ type: 'inside', zoomOnMouseWheel: true, moveOnMouseMove: true }
],
xAxis: { xAxis: {
type: 'category',
data: data.dataList.map((e: any) => e.collectTime), data: data.dataList.map((e: any) => e.collectTime),
axisLine: { show: true, lineStyle: { color: '#000' } }, axisLine: { show: true, lineStyle: { color: '#000' } },
axisLabel: { show: true, textStyle: { color: '#000' } } axisTick: { alignWithLabel: true },
axisLabel: {
show: true,
color: '#000',
rotate: data.dataList.length > 20 ? 45 : 0,
interval: 'auto',
formatter: (value: string) => {
if (value && value.length > 16) {
return value.substring(11, 19);
}
return value;
}
}
}, },
yAxis: [{ yAxis: [{
type: 'value', type: 'value',
name: '数值', name: '数值',
nameTextStyle: { color: '#000' }, nameTextStyle: { color: '#000' },
splitLine: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed', color: '#e0e0e0' } },
axisTick: { show: true }, axisTick: { show: true },
axisLine: { show: true, lineStyle: { color: '#000' } }, axisLine: { show: true, lineStyle: { color: '#000' } },
axisLabel: { show: true, textStyle: { color: '#000' } } axisLabel: {
show: true,
color: '#000',
formatter: (value: number) => {
if (Math.abs(value) >= 10000) return (value / 1000).toFixed(1) + 'k';
if (Math.abs(value) >= 1) return value.toFixed(1);
return value.toFixed(2);
}
},
scale: true,
splitNumber: 5
}], }],
series: [ series: [
{ {
@ -292,11 +319,25 @@ onMounted(() => {
<style scoped> <style scoped>
.chart1 { .chart1 {
width: 100%; width: 100%;
height: 75vh; height: calc(100vh - 200px);
min-height: 400px;
max-height: 800px;
} }
.chart2 { .chart2 {
width: 100%; width: 100%;
height: 40vh; height: calc(50vh - 100px);
min-height: 300px;
}
@media screen and (max-width: 768px) {
.chart1 {
height: 60vh;
min-height: 300px;
}
.chart2 {
height: 40vh;
min-height: 250px;
}
} }
</style> </style>

@ -234,28 +234,32 @@ export default {
initBaseChartOptions() { initBaseChartOptions() {
this.baseChartOptions = { this.baseChartOptions = {
grid: { grid: {
top: '40', top: 50,
bottom: '20%', bottom: 70,
left: '10%', left: 20,
right: '3%' right: 20,
containLabel: true
}, },
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { axisPointer: {
type: 'shadow', type: 'cross',
label: { label: {
show: true show: true
} }
} }
}, },
dataZoom: [{ dataZoom: [
type: 'slider' { type: 'slider', height: 18, bottom: 8, start: 0, end: 100 },
}], { type: 'inside', zoomOnMouseWheel: true, moveOnMouseMove: true }
],
legend: { legend: {
right: 0, right: 0,
top: 5,
data: ['数据', '停电'] data: ['数据', '停电']
}, },
xAxis: { xAxis: {
type: 'category',
axisLine: { axisLine: {
show: true, show: true,
lineStyle: { lineStyle: {
@ -263,19 +267,30 @@ export default {
} }
}, },
axisTick: { axisTick: {
show: true show: true,
alignWithLabel: true
}, },
axisLabel: { axisLabel: {
show: true, show: true,
textStyle: { color: '#000000',
color: '#000000' rotate: 45,
interval: 'auto',
formatter: function(value) {
if (value && value.length > 16) {
return value.substring(11, 19);
}
return value;
} }
} }
}, },
yAxis: { yAxis: {
type: 'value', type: 'value',
splitLine: { splitLine: {
show: false show: true,
lineStyle: {
type: 'dashed',
color: '#e0e0e0'
}
}, },
axisTick: { axisTick: {
show: true show: true
@ -288,10 +303,10 @@ export default {
}, },
axisLabel: { axisLabel: {
show: true, show: true,
textStyle: { color: '#000000'
color: '#000000' },
} scale: true,
} splitNumber: 5
} }
} }
}, },
@ -880,22 +895,40 @@ export default {
margin-top: 10px; margin-top: 10px;
} }
.chart1 { .charts-container {
width: 50%; display: flex;
height: 40vh; flex-wrap: wrap;
display: inline-block; gap: 10px;
}
.chart2 {
width: 50%;
height: 40vh;
display: inline-block;
} }
.chart1,
.chart2,
.chart3 { .chart3 {
width: 50%; flex: 1 1 calc(50% - 10px);
height: 40vh; min-width: 400px;
display: inline-block; height: calc(45vh - 60px);
min-height: 280px;
max-height: 380px;
}
@media screen and (max-width: 1200px) {
.chart1,
.chart2,
.chart3 {
flex: 1 1 100%;
min-width: 100%;
height: calc(40vh - 50px);
min-height: 260px;
}
}
@media screen and (max-width: 768px) {
.chart1,
.chart2,
.chart3 {
height: 35vh;
min-height: 240px;
}
} }
.power-outage-summary { .power-outage-summary {

@ -267,377 +267,117 @@ export default {
} }
let query = JSON.parse(JSON.stringify(this.queryParams)) let query = JSON.parse(JSON.stringify(this.queryParams))
const {data} = await vibrationInstantList(query) const {data} = await vibrationInstantList(query)
const timeData = data.map(e => e.collectTime);
const chartGridConfig = {
top: 50,
bottom: 70,
left: 20,
right: 20,
containLabel: true
};
const chartDataZoom = [
{ type: 'slider', height: 18, bottom: 8, start: 0, end: 100 },
{ type: 'inside', zoomOnMouseWheel: true, moveOnMouseMove: true }
];
const xAxisConfig = {
type: 'category',
data: timeData,
axisLine: { show: true, lineStyle: { color: '#000000' } },
axisTick: { show: true, alignWithLabel: true },
axisLabel: {
show: true,
color: '#000000',
rotate: timeData.length > 20 ? 45 : 0,
interval: 'auto',
formatter: function(value) {
if (value && value.length > 16) return value.substring(11, 19);
return value;
}
}
};
const createYAxisConfig = (name) => ({
type: 'value',
name: name,
nameTextStyle: { color: '#000000' },
splitLine: { show: true, lineStyle: { type: 'dashed', color: '#e0e0e0' } },
axisTick: { show: true },
axisLine: { show: true, lineStyle: { color: '#000000' } },
axisLabel: { show: true, color: '#000000' },
scale: true,
splitNumber: 5
});
let option1 = { let option1 = {
title: { title: { text: this.selectMonitorName + ' 速度曲线', x: 'center' },
text: this.selectMonitorName + ' 速度曲线', grid: chartGridConfig,
x: 'center' tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { show: true } } },
}, dataZoom: chartDataZoom,
grid: { legend: { right: 0, top: 5 },
top: '40', xAxis: xAxisConfig,
bottom: '10%', yAxis: [createYAxisConfig('速度(mm/s)')],
left: '10%', series: [{
right: '3%' name: '速度(mm/s)',
}, type: 'line',
tooltip: { smooth: true,
trigger: 'axis', showAllSymbol: true,
axisPointer: { symbol: 'circle',
type: 'shadow', symbolSize: 6,
label: { data: data.map(e => e.speed)
show: true }]
}
}
},
dataZoom: [{
type: 'slider'
}],
legend: {
right: 0
},
xAxis: {
data: data.map(e => e.collectTime),
axisLine: {
show: true, //X线
lineStyle: {
color: '#000000'
}
},
axisTick: {
show: true //X
},
axisLabel: {
show: true,
textStyle: {
color: '#000000' //X
}
}
},
yAxis: [
{
type: 'value',
name: '速度(mm/s)',
nameTextStyle: {
color: '#000000'
},
splitLine: {
show: false
},
axisTick: {
show: true
},
axisLine: {
show: true,
lineStyle: {
color: '#000000'
}
},
axisLabel: {
show: true,
textStyle: {
color: '#000000'
}
}
}
],
series: [
{
name: '速度(mm/s)',
type: 'line',
smooth: true, //线
showAllSymbol: true, //
symbol: 'circle', //
symbolSize: 10, //
// itemStyle: {
// //线
// color: "#058cff",
// },
// lineStyle: {
// color: "#058cff",
// },
// areaStyle: {
// color: "rgba(5,140,255, 0.2)",
// },
data: data.map(e => e.speed)
},
]
} }
let option2 = { let option2 = {
title: { title: { text: this.selectMonitorName + ' 温度曲线', x: 'center' },
text: this.selectMonitorName + ' 温度曲线', grid: chartGridConfig,
x: 'center' dataZoom: chartDataZoom,
}, tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { show: true } } },
grid: { legend: { right: 0, top: 5 },
top: '40', xAxis: xAxisConfig,
bottom: '10%', yAxis: [createYAxisConfig('温度(℃)')],
left: '10%', series: [{
right: '3%' name: '温度(℃)',
}, type: 'line',
smooth: true,
dataZoom: [{ showAllSymbol: true,
type: 'slider' symbol: 'circle',
}], symbolSize: 6,
tooltip: { data: data.map(e => e.temperature)
trigger: 'axis', }]
axisPointer: {
type: 'shadow',
label: {
show: true
}
}
},
legend: {
right: 0
},
xAxis: {
data: data.map(e => e.collectTime),
axisLine: {
show: true, //X线
lineStyle: {
color: '#000000'
}
},
axisTick: {
show: true //X
},
axisLabel: {
show: true,
textStyle: {
color: '#000000' //X
}
}
},
yAxis: [
{
type: 'value',
name: '温度(℃)',
nameTextStyle: {
color: '#000000'
},
splitLine: {
show: false
},
axisTick: {
show: true
},
axisLine: {
show: true,
lineStyle: {
color: '#000000'
}
},
axisLabel: {
show: true,
textStyle: {
color: '#000000'
}
}
}
],
series: [
{
name: '温度(℃)',
type: 'line',
smooth: true, //线
showAllSymbol: true, //
symbol: 'circle', //
symbolSize: 10, //
// itemStyle: {
// //线
// color: "#058cff",
// },
// lineStyle: {
// color: "#058cff",
// },
// areaStyle: {
// color: "rgba(5,140,255, 0.2)",
// },
data: data.map(e => e.temperature)
},
]
} }
let option3 = { let option3 = {
title: { title: { text: this.selectMonitorName + ' 位移曲线', x: 'center' },
text: this.selectMonitorName + ' 位移曲线', grid: chartGridConfig,
x: 'center' tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { show: true } } },
}, dataZoom: chartDataZoom,
grid: { legend: { right: 0, top: 5 },
top: '40', xAxis: xAxisConfig,
bottom: '10%', yAxis: [createYAxisConfig('位移(um)')],
left: '10%', series: [{
right: '3%' name: '位移(um)',
}, type: 'line',
tooltip: { smooth: true,
trigger: 'axis', showAllSymbol: true,
axisPointer: { symbol: 'circle',
type: 'shadow', symbolSize: 6,
label: { data: data.map(e => e.displacement)
show: true }]
}
}
},
dataZoom: [{
type: 'slider'
}],
legend: {
right: 0
},
xAxis: {
data: data.map(e => e.collectTime),
axisLine: {
show: true, //X线
lineStyle: {
color: '#000000'
}
},
axisTick: {
show: true //X
},
axisLabel: {
show: true,
textStyle: {
color: '#000000' //X
}
}
},
yAxis: [
{
type: 'value',
name: '位移(um)',
nameTextStyle: {
color: '#000000'
},
splitLine: {
show: false
},
axisTick: {
show: true
},
axisLine: {
show: true,
lineStyle: {
color: '#000000'
}
},
axisLabel: {
show: true,
textStyle: {
color: '#000000'
}
}
}
],
series: [
{
name: '位移(um)',
type: 'line',
smooth: true, //线
showAllSymbol: true, //
symbol: 'circle', //
symbolSize: 10, //
// itemStyle: {
// //线
// color: "#058cff",
// },
// lineStyle: {
// color: "#058cff",
// },
// areaStyle: {
// color: "rgba(5,140,255, 0.2)",
// },
data: data.map(e => e.displacement)
},
]
} }
let option4 = { let option4 = {
title: { title: { text: this.selectMonitorName + ' 加速度曲线', x: 'center' },
text: this.selectMonitorName + ' 加速度曲线', grid: chartGridConfig,
x: 'center' tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { show: true } } },
}, dataZoom: chartDataZoom,
grid: { legend: { right: 0, top: 5 },
top: '40', xAxis: xAxisConfig,
bottom: '10%', yAxis: [createYAxisConfig('加速度(g)')],
left: '10%', series: [{
right: '3%' name: '加速度(g)',
}, type: 'line',
tooltip: { smooth: true,
trigger: 'axis', showAllSymbol: true,
axisPointer: { symbol: 'circle',
type: 'shadow', symbolSize: 6,
label: { data: data.map(e => e.acceleration)
show: true }]
}
}
},
dataZoom: [{
type: 'slider'
}],
legend: {
right: 0
},
xAxis: {
data: data.map(e => e.collectTime),
axisLine: {
show: true, //X线
lineStyle: {
color: '#000000'
}
},
axisTick: {
show: true //X
},
axisLabel: {
show: true,
textStyle: {
color: '#000000' //X
}
}
},
yAxis: [
{
type: 'value',
name: '加速度(g)',
nameTextStyle: {
color: '#000000'
},
splitLine: {
show: false
},
axisTick: {
show: true
},
axisLine: {
show: true,
lineStyle: {
color: '#000000'
}
},
axisLabel: {
show: true,
textStyle: {
color: '#000000'
}
}
}
],
series: [
{
name: '加速度(g)',
type: 'line',
smooth: true, //线
showAllSymbol: true, //
symbol: 'circle', //
symbolSize: 10, //
// itemStyle: {
// color: "#058cff",
// },
// lineStyle: {
// color: "#058cff",
// },
// areaStyle: {
// color: "rgba(5,140,255, 0.2)",
// },
data: data.map(e => e.acceleration)
},
]
} }
this.$refs.Chart1.setData(option1) this.$refs.Chart1.setData(option1)
this.$refs.Chart2.setData(option2) this.$refs.Chart2.setData(option2)
@ -693,24 +433,36 @@ export default {
} }
</script> </script>
<style scoped> <style scoped>
.chart1 { .chart1,
width: 50%; .chart2,
height: 40vh; .chart3,
display: inline-block;
}
.chart2 {
width: 50%;
height: 40vh;
display: inline-block;
}
.chart3 {
width: 50%;
height: 40vh;
display: inline-block;
}
.chart4 { .chart4 {
width: 50%;
display: inline-block; display: inline-block;
height: 40vh; width: calc(50% - 5px);
height: calc(45vh - 60px);
min-height: 280px;
max-height: 380px;
vertical-align: top;
}
@media screen and (max-width: 1200px) {
.chart1,
.chart2,
.chart3,
.chart4 {
width: 100%;
height: calc(40vh - 50px);
min-height: 260px;
}
}
@media screen and (max-width: 768px) {
.chart1,
.chart2,
.chart3,
.chart4 {
height: 35vh;
min-height: 240px;
}
} }
</style> </style>

@ -167,65 +167,91 @@ async function getChart() {
const currentOption: EChartsOption = { const currentOption: EChartsOption = {
title: { text: `${selectMonitorName.value} 电流曲线`, left: 'center' }, title: { text: `${selectMonitorName.value} 电流曲线`, left: 'center' },
grid: { top: '15%', bottom: '10%', left: '3%', right: '3%' }, grid: { top: 50, bottom: 70, left: 60, right: 40, containLabel: true },
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { type: 'shadow', label: { show: true } } axisPointer: { type: 'cross', label: { show: true } }
}, },
dataZoom: [{ type: 'slider', start: 0, end: 100 }], dataZoom: [
legend: { right: 0 }, { type: 'slider', height: 20, bottom: 8, start: 0, end: 100 },
{ type: 'inside', zoomOnMouseWheel: true, moveOnMouseMove: true }
],
legend: { right: 0, top: 5 },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: collectTimes, data: collectTimes,
axisLine: { lineStyle: { color: '#000' } }, axisLine: { lineStyle: { color: '#000' } },
axisTick: { show: true }, axisTick: { show: true, alignWithLabel: true },
axisLabel: { color: '#000' } axisLabel: {
color: '#000',
rotate: collectTimes.length > 20 ? 45 : 0,
interval: 'auto',
formatter: (value: string) => value && value.length > 16 ? value.substring(11, 19) : value
}
}, },
yAxis: [{ yAxis: [{
type: 'value', type: 'value',
name: '电流A', name: '电流A',
nameTextStyle: { color: '#000' }, nameTextStyle: { color: '#000' },
splitLine: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed', color: '#e0e0e0' } },
axisTick: { show: true }, axisTick: { show: true },
axisLine: { lineStyle: { color: '#000' } }, axisLine: { lineStyle: { color: '#000' } },
axisLabel: { color: '#000' } axisLabel: {
color: '#000',
formatter: (value: number) => Math.abs(value) >= 1000 ? (value / 1000).toFixed(1) + 'k' : value.toFixed(1)
},
scale: true,
splitNumber: 5
}], }],
series: [ series: [
{ name: 'A相电流', type: 'line', smooth: true, symbol: 'circle', symbolSize: 10, data: data.map((item: any) => item.ia) }, { name: 'A相电流', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6, data: data.map((item: any) => item.ia) },
{ name: 'B相电流', type: 'line', smooth: true, symbol: 'circle', symbolSize: 10, data: data.map((item: any) => item.ib) }, { name: 'B相电流', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6, data: data.map((item: any) => item.ib) },
{ name: 'C相电流', type: 'line', smooth: true, symbol: 'circle', symbolSize: 10, data: data.map((item: any) => item.ic) } { name: 'C相电流', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6, data: data.map((item: any) => item.ic) }
] ]
}; };
const voltageOption: EChartsOption = { const voltageOption: EChartsOption = {
title: { text: `${selectMonitorName.value} 电压曲线`, left: 'center' }, title: { text: `${selectMonitorName.value} 电压曲线`, left: 'center' },
grid: { top: '15%', bottom: '10%', left: '3%', right: '3%' }, grid: { top: 50, bottom: 70, left: 60, right: 40, containLabel: true },
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { type: 'shadow', label: { show: true } } axisPointer: { type: 'cross', label: { show: true } }
}, },
dataZoom: [{ type: 'slider', start: 0, end: 100 }], dataZoom: [
legend: { right: 0 }, { type: 'slider', height: 20, bottom: 8, start: 0, end: 100 },
{ type: 'inside', zoomOnMouseWheel: true, moveOnMouseMove: true }
],
legend: { right: 0, top: 5 },
xAxis: { xAxis: {
type: 'category', type: 'category',
data: collectTimes, data: collectTimes,
axisLine: { lineStyle: { color: '#000' } }, axisLine: { lineStyle: { color: '#000' } },
axisTick: { show: true }, axisTick: { show: true, alignWithLabel: true },
axisLabel: { color: '#000' } axisLabel: {
color: '#000',
rotate: collectTimes.length > 20 ? 45 : 0,
interval: 'auto',
formatter: (value: string) => value && value.length > 16 ? value.substring(11, 19) : value
}
}, },
yAxis: [{ yAxis: [{
type: 'value', type: 'value',
name: '电压V', name: '电压V',
nameTextStyle: { color: '#000' }, nameTextStyle: { color: '#000' },
splitLine: { show: false }, splitLine: { show: true, lineStyle: { type: 'dashed', color: '#e0e0e0' } },
axisTick: { show: true }, axisTick: { show: true },
axisLine: { lineStyle: { color: '#000' } }, axisLine: { lineStyle: { color: '#000' } },
axisLabel: { color: '#000' } axisLabel: {
color: '#000',
formatter: (value: number) => Math.abs(value) >= 1000 ? (value / 1000).toFixed(1) + 'k' : value.toFixed(1)
},
scale: true,
splitNumber: 5
}], }],
series: [ series: [
{ name: 'A相电压', type: 'line', smooth: true, symbol: 'circle', symbolSize: 10, data: data.map((item: any) => item.va) }, { name: 'A相电压', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6, data: data.map((item: any) => item.va) },
{ name: 'B相电压', type: 'line', smooth: true, symbol: 'circle', symbolSize: 10, data: data.map((item: any) => item.vb) }, { name: 'B相电压', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6, data: data.map((item: any) => item.vb) },
{ name: 'C相电压', type: 'line', smooth: true, symbol: 'circle', symbolSize: 10, data: data.map((item: any) => item.vc) } { name: 'C相电压', type: 'line', smooth: true, symbol: 'circle', symbolSize: 6, data: data.map((item: any) => item.vc) }
] ]
}; };
@ -270,14 +296,28 @@ onMounted(() => {
getList(); getList();
}); });
</script> </script>
<style> <style scoped>
.chart1 { .chart1,
width: 100%;
height: 40vh;
}
.chart2 { .chart2 {
width: 100%; width: 100%;
height: 40vh; height: calc(50vh - 80px);
min-height: 280px;
max-height: 400px;
}
@media screen and (max-width: 1200px) {
.chart1,
.chart2 {
height: calc(45vh - 60px);
min-height: 250px;
}
}
@media screen and (max-width: 768px) {
.chart1,
.chart2 {
height: 40vh;
min-height: 220px;
}
} }
</style> </style>

Loading…
Cancel
Save