348 lines
7.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { ref, reactive, onMounted, watch, onBeforeUnmount } from 'vue';
import { isEmpty, getAssetsFile } from '@/utils';
import * as echarts from 'echarts';
// 图表 DOM 引用
const chartRef = ref(null);
// ECharts 实例
let chartInstance = null;
// 颜色列表
const colorList = ['#3685FE', '#FFD500', '#25BF82'];
// x轴数据
const xData = ['1月', '2月', '3月', '4月', '5月', '6月'];
// 图表配置
const option = {
backgroundColor: '#fff',
title: {
text: '',
textStyle: {
fontSize: 12,
fontWeight: 400,
},
left: 'center',
top: '5%',
},
legend: {
icon: 'circle',
top: '0',
right: '5%',
itemWidth: 6,
itemGap: 20,
textStyle: {
color: '#556677',
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
label: {
show: true,
backgroundColor: '#fff',
color: '#556677',
borderColor: 'rgba(0,0,0,0)',
shadowColor: 'rgba(0,0,0,0)',
shadowOffsetY: 0,
},
lineStyle: {
width: 0,
},
},
backgroundColor: '#fff',
textStyle: {
color: '#5c6c7c',
},
padding: [10, 10],
extraCssText: 'box-shadow: 1px 0 2px 0 rgba(163,163,163,0.5)',
},
grid: {
top: '20%',
},
xAxis: [
{
type: 'category',
data: xData,
axisLine: {
lineStyle: {
color: 'rgba(107,107,107,0.37)',
},
},
axisTick: {
show: false,
},
axisLabel: {
interval: 0,
textStyle: {
color: '#999',
},
margin: 15,
},
axisPointer: {
label: {
padding: [11, 5, 7],
backgroundColor: {
type: 'linear',
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{
offset: 0,
color: '#fff',
},
{
offset: 0.9,
color: '#fff',
},
{
offset: 0.9,
color: '#33c0cd',
},
{
offset: 1,
color: '#33c0cd',
},
],
global: false,
},
},
},
boundaryGap: false,
},
],
yAxis: [
{
type: 'value',
show: false,
axisTick: {
show: false,
},
axisLine: {
show: true,
lineStyle: {
color: 'rgba(107,107,107,0.37)',
},
},
axisLabel: {
textStyle: {
color: '#999',
},
},
splitLine: {
show: false,
},
},
],
series: [
{
name: '茎秆高度',
type: 'line',
data: [10, 10, 30, 12, 15, 3],
symbolSize: 1,
symbol: 'circle',
smooth: true,
yAxisIndex: 0,
showSymbol: false,
lineStyle: {
width: 5,
color: '#3685FE',
shadowColor: 'rgba(158,135,255, 0.3)',
shadowBlur: 10,
shadowOffsetY: 20,
},
itemStyle: {
color: colorList[0],
borderColor: colorList[0],
},
},
{
name: '叶片温度',
type: 'line',
data: [5, 12, 11, 14, 25, 16],
symbolSize: 1,
symbol: 'circle',
smooth: true,
yAxisIndex: 0,
showSymbol: false,
lineStyle: {
width: 5,
color: '#FFD500',
shadowColor: 'rgba(115,221,255, 0.3)',
shadowBlur: 10,
shadowOffsetY: 20,
},
itemStyle: {
color: colorList[1],
borderColor: colorList[1],
},
},
{
name: '果实大小',
type: 'line',
data: [6, 14, 17, 25, 21, 10],
symbolSize: 1,
symbol: 'circle',
smooth: true,
yAxisIndex: 0,
showSymbol: false,
lineStyle: {
width: 5,
color: '#25BF82',
shadowColor: 'rgba(115,221,255, 0.3)',
shadowBlur: 10,
shadowOffsetY: 20,
},
itemStyle: {
color: colorList[2],
borderColor: colorList[2],
},
},
],
};
const props = defineProps({
data: {
type: Array,
required: true,
default: () => [],
},
chartsData: {
type: Array,
required: false,
default: () => [],
},
title: {
type: String,
required: true,
default: () => '',
validator: (items) => {
return items;
},
},
showImage: {
type: Boolean,
default: false,
},
showCharts: {
type: Boolean,
default: false,
},
imageList: {
type: Array,
default: () => [],
},
});
/* --------------- methods --------------- */
// #region
// 初始化图表
const initChart = () => {
if (chartRef.value) {
// 基于准备好的dom初始化echarts实例
chartInstance = echarts.init(chartRef.value);
// 绘制图表
chartInstance.setOption(option);
// 自动显示最大值点的tooltip
// showMaxValueTooltip();
// 响应式调整
window.addEventListener('resize', resizeChart);
}
};
const showMaxValueTooltip = () => {
if (!chartInstance) return;
// 找出所有系列中的最大值点
let maxValue = -Infinity;
let maxSeriesIndex = 0;
let maxDataIndex = 0;
option.series.forEach((series, seriesIndex) => {
series.data.forEach((value, dataIndex) => {
if (value > maxValue) {
maxValue = value;
maxSeriesIndex = seriesIndex;
maxDataIndex = dataIndex;
}
});
});
// 延迟执行确保图表渲染完成
setTimeout(() => {
chartInstance.dispatchAction({
type: 'showTip',
seriesIndex: maxSeriesIndex,
dataIndex: maxDataIndex,
});
}, 300);
};
// 组件挂载时初始化图表
onMounted(() => {
initChart();
});
// 组件卸载前销毁图表
onBeforeUnmount(() => {
if (chartInstance) {
window.removeEventListener('resize', resizeChart);
chartInstance.dispose();
chartInstance = null;
}
});
// 调整图表大小
const resizeChart = () => {
if (chartInstance) {
chartInstance.resize();
}
};
// #endregion
</script>
<template>
<div>
<el-card style="border-radius: 16px; min-height: 316px">
<div class="my-card-title" style="">{{ title }}</div>
<div v-for="(item, index) in data" :key="index" class="show-data-box">
<div class="left-title">{{ item.title }}:</div>
<div :style="{ color: item.status == '0' ? '#FE4066' : '#25BF82' }">{{ item.statusText }}</div>
</div>
<div v-if="showImage">
<p style="font-size: 14px; text-align: left; color: #000000; margin-bottom: 10px">灌溉记录:</p>
<el-image
style="width: 100%"
:src="imageList[0]"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
:preview-src-list="imageList"
show-progress
:initial-index="4"
fit="cover"
/>
</div>
<div v-if="showCharts">
<div ref="chartRef" style="width: 100%; height: 200px"></div>
</div>
</el-card>
</div>
</template>
<style scoped lang="scss">
.my-card-title {
font-size: 16px;
font-weight: bold;
text-align: left;
color: #000;
margin-bottom: 16px;
}
.show-data-box {
display: flex;
justify-content: space-between;
font-size: 14px;
margin: 7px 0;
color: #000000;
}
</style>