随机数据生成 田间监测
This commit is contained in:
		
							parent
							
								
									af11fa876b
								
							
						
					
					
						commit
						78255cea06
					
				| @ -1,6 +1,206 @@ | |||||||
| <script setup> | <script setup> | ||||||
| import { ref, reactive, onMounted, watch } from 'vue'; | import { ref, reactive, onMounted, watch, onBeforeUnmount } from 'vue'; | ||||||
| import { isEmpty, getAssetsFile } from '@/utils'; | 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({ | const props = defineProps({ | ||||||
|   data: { |   data: { | ||||||
| @ -8,6 +208,11 @@ const props = defineProps({ | |||||||
|     required: true, |     required: true, | ||||||
|     default: () => [], |     default: () => [], | ||||||
|   }, |   }, | ||||||
|  |   chartsData: { | ||||||
|  |     type: Array, | ||||||
|  |     required: false, | ||||||
|  |     default: () => [], | ||||||
|  |   }, | ||||||
|   title: { |   title: { | ||||||
|     type: String, |     type: String, | ||||||
|     required: true, |     required: true, | ||||||
| @ -20,11 +225,79 @@ const props = defineProps({ | |||||||
|     type: Boolean, |     type: Boolean, | ||||||
|     default: false, |     default: false, | ||||||
|   }, |   }, | ||||||
|  |   showCharts: { | ||||||
|  |     type: Boolean, | ||||||
|  |     default: false, | ||||||
|  |   }, | ||||||
|   imageList: { |   imageList: { | ||||||
|     type: Array, |     type: Array, | ||||||
|     default: () => [], |     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> | </script> | ||||||
| 
 | 
 | ||||||
| <template> | <template> | ||||||
| @ -49,6 +322,9 @@ const props = defineProps({ | |||||||
|           fit="cover" |           fit="cover" | ||||||
|         /> |         /> | ||||||
|       </div> |       </div> | ||||||
|  |       <div v-if="showCharts"> | ||||||
|  |         <div ref="chartRef" style="width: 100%; height: 200px"></div> | ||||||
|  |       </div> | ||||||
|     </el-card> |     </el-card> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| <script setup> | <script setup> | ||||||
| import { ref, reactive, onMounted, onUnmounted } from 'vue'; | import { ref, watch, onMounted, onUnmounted, computed } from 'vue'; | ||||||
| import { isEmpty, getAssetsFile } from '@/utils'; | import { isEmpty, getAssetsFile } from '@/utils'; | ||||||
| import { useRoute, useRouter } from 'vue-router'; | import { useRoute, useRouter } from 'vue-router'; | ||||||
| import Hls from 'hls.js'; | import Hls from 'hls.js'; | ||||||
| @ -27,9 +27,35 @@ const props = defineProps({ | |||||||
|     type: Array, |     type: Array, | ||||||
|     required: true, |     required: true, | ||||||
|     default: () => [], |     default: () => [], | ||||||
|  |     validator: (items) => { | ||||||
|  |       const validItems = items.filter((item) => item.icon === 'camera'); | ||||||
|  |       return validItems.every((item) => { | ||||||
|  |         return ( | ||||||
|  |           typeof item === 'object' && | ||||||
|  |           item !== null && | ||||||
|  |           typeof item.id === 'number' && | ||||||
|  |           typeof item.name === 'string' && | ||||||
|  |           typeof item.icon === 'string' && | ||||||
|  |           typeof item.detail === 'string' && | ||||||
|  |           (!item.status || typeof item.status === 'number') | ||||||
|  |         ); | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | const emit = defineEmits(['changeDevice']); | ||||||
|  | // 显示天气详情弹窗 | ||||||
|  | const showWeatherDetail = (data) => { | ||||||
|  |   emit('changeDevice', { message: data }); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // 监听 currentDevice 的变化 | ||||||
|  | watch(currentDevice, (newValue, oldValue) => { | ||||||
|  |   showWeatherDetail(newValue); | ||||||
|  |   // console.log(`count 从 ${oldValue} 变为 ${newValue}`); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| onUnmounted(() => { | onUnmounted(() => { | ||||||
|   if (hls.value) { |   if (hls.value) { | ||||||
|     hls.value.destroy(); |     hls.value.destroy(); | ||||||
|  | |||||||
| @ -6,43 +6,8 @@ | |||||||
|           <devices :title="'田间监测设备'" :devices="devices"></devices> |           <devices :title="'田间监测设备'" :devices="devices"></devices> | ||||||
|         </div> |         </div> | ||||||
|         <div style="display: flex; justify-content: space-between; margin-top: 10px"> |         <div style="display: flex; justify-content: space-between; margin-top: 10px"> | ||||||
|           <stream :title="'田间监测实时监控'" :devices="devices" style="width: 60%; height: fit-content"></stream> |           <stream :title="'田间监测实时监控'" :devices="devices" style="width: 60%; height: fit-content" @change-device="changeDevice"></stream> | ||||||
|           <el-card style="width: calc(40% - 20px); border-radius: 16px; padding: 10px"> |           <data-display style="width: calc(40% - 20px)" title="作物生长状态" show-charts :data="textData"></data-display> | ||||||
|             <div style="font-size: 16px; font-weight: bold; text-align: left">作物生长状态</div> |  | ||||||
|             <div class="plantStatus"> |  | ||||||
|               <div class="leftKey">作物名称:</div> |  | ||||||
|               <div class="rightValue">橙子</div> |  | ||||||
|             </div> |  | ||||||
|             <div class="plantStatus"> |  | ||||||
|               <div class="leftKey">生长状态:</div> |  | ||||||
|               <div class="rightValue">成熟期</div> |  | ||||||
|             </div> |  | ||||||
|             <div class="plantStatus"> |  | ||||||
|               <div class="leftKey">植株形态:</div> |  | ||||||
|               <div class="rightValue">果木型</div> |  | ||||||
|             </div> |  | ||||||
|             <div class="plantStatus"> |  | ||||||
|               <div class="leftKey">叶片形态:</div> |  | ||||||
|               <div class="rightValue">阔叶型</div> |  | ||||||
|             </div> |  | ||||||
|             <div class="plantStatus"> |  | ||||||
|               <div class="leftKey">生长态势:</div> |  | ||||||
|               <div class="rightValue">良好</div> |  | ||||||
|             </div> |  | ||||||
|             <div class="plantStatus"> |  | ||||||
|               <div class="leftKey">田间有机质含量:</div> |  | ||||||
|               <div class="rightValue">橙子</div> |  | ||||||
|             </div> |  | ||||||
|             <div class="plantStatus"> |  | ||||||
|               <div class="leftKey">田间有机质含量:</div> |  | ||||||
|               <div class="rightValue">16%</div> |  | ||||||
|             </div> |  | ||||||
|             <div class="plantStatus"> |  | ||||||
|               <div class="leftKey">生长趋势图</div> |  | ||||||
|               <div class="rightValue"> </div> |  | ||||||
|             </div> |  | ||||||
|             <div ref="chartRef1" style="width: 100%; height: 200px"></div> |  | ||||||
|           </el-card> |  | ||||||
|         </div> |         </div> | ||||||
|       </template> |       </template> | ||||||
|     </common> |     </common> | ||||||
| @ -55,29 +20,62 @@ import Common from '../components/common.vue'; | |||||||
| import Devices from '@/views/smartFarm/components/devices.vue'; | import Devices from '@/views/smartFarm/components/devices.vue'; | ||||||
| import Stream from '@/views/smartFarm/components/stream.vue'; | import Stream from '@/views/smartFarm/components/stream.vue'; | ||||||
| import * as echarts from 'echarts'; | import * as echarts from 'echarts'; | ||||||
|  | import Mock from 'mockjs'; | ||||||
|  | import DataDisplay from '@/views/smartFarm/components/dataDisplay.vue'; | ||||||
| /* --------------- data --------------- */ | /* --------------- data --------------- */ | ||||||
| // #region | // #region | ||||||
| // 图表 DOM 引用 | 
 | ||||||
| const chartRef1 = ref(null); | const textData = ref([ | ||||||
| // ECharts 实例 |   { | ||||||
| let chartInstance = null; |     title: '作物名称', //左侧文本 | ||||||
| // 颜色列表 |     status: '1', //  0:不正常 1:正常 | ||||||
| const colorList = ['#3685FE', '#FFD500', '#25BF82']; |     statusText: '橙子', //左侧文本 | ||||||
| // x轴数据 |   }, | ||||||
| const xData = ['1月', '2月', '3月', '4月', '5月', '6月']; |   { | ||||||
|  |     title: '生长状态', | ||||||
|  |     status: '1', | ||||||
|  |     statusText: '成熟期', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '植株形态', | ||||||
|  |     status: '1', | ||||||
|  |     statusText: '果木型', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '叶片形态', | ||||||
|  |     status: '1', | ||||||
|  |     statusText: '阔叶型', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '生长态势', | ||||||
|  |     status: '1', | ||||||
|  |     statusText: '良好', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '田间有机质含量', | ||||||
|  |     status: '1', | ||||||
|  |     statusText: '16%', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     title: '生长趋势图', | ||||||
|  |     status: '1', | ||||||
|  |     statusText: '', | ||||||
|  |   }, | ||||||
|  | ]); | ||||||
|  | 
 | ||||||
| const devices = ref([ | const devices = ref([ | ||||||
|   { |   { | ||||||
|     name: 'A-001', |     name: 'A-001', | ||||||
|     icon: 'camera', |     icon: 'camera', | ||||||
|     detail: 'A区-监控设备9', |     detail: 'A区-监控设备9', | ||||||
|     status: '0', |     status: '1', | ||||||
|     id: 0, |     id: 0, | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     name: 'A-002', |     name: 'A-002', | ||||||
|     icon: 'camera', |     icon: 'camera', | ||||||
|     detail: 'A区-监控设备66', |     detail: 'A区-监控设备66', | ||||||
|     status: '0', |     status: '1', | ||||||
|     id: 1, |     id: 1, | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
| @ -123,258 +121,118 @@ const devices = ref([ | |||||||
|     id: 7, |     id: 7, | ||||||
|   }, |   }, | ||||||
| ]); | ]); | ||||||
| // 图表配置 | 
 | ||||||
| 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], |  | ||||||
|       }, |  | ||||||
|     }, |  | ||||||
|   ], |  | ||||||
| }; |  | ||||||
| // #endregion | // #endregion | ||||||
| /* --------------- methods --------------- */ | /* --------------- methods --------------- */ | ||||||
| // #region | // #region | ||||||
| // 初始化图表 | const changeDevice = (params) => { | ||||||
| const initChart = () => { |   console.log(params); | ||||||
|   if (chartRef1.value) { |   textData.value = generateCropReport(); | ||||||
|     // 基于准备好的dom,初始化echarts实例 |  | ||||||
|     chartInstance = echarts.init(chartRef1.value); |  | ||||||
|     // 绘制图表 |  | ||||||
|     chartInstance.setOption(option); |  | ||||||
|     // 自动显示最大值点的tooltip |  | ||||||
|     // showMaxValueTooltip(); |  | ||||||
|     // 响应式调整 |  | ||||||
|     window.addEventListener('resize', resizeChart); |  | ||||||
|   } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const showMaxValueTooltip = () => { | // 生成模拟数据 | ||||||
|   if (!chartInstance) return; | // 农业知识库 | ||||||
| 
 | const AGRICULTURE_KNOWLEDGE = { | ||||||
|   // 找出所有系列中的最大值点 |   crops: ['橙子', '蓝莓', '水稻', '番茄', '小麦', '苹果', '葡萄'], | ||||||
|   let maxValue = -Infinity; |   plantTypes: { | ||||||
|   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; |   leafTypes: { | ||||||
|       } |     橙子: '革质叶', | ||||||
|     }); |     蓝莓: '卵形叶', | ||||||
|   }); |     水稻: '线形叶', | ||||||
| 
 |     番茄: '羽状叶', | ||||||
|   // 延迟执行确保图表渲染完成 |     小麦: '披针叶', | ||||||
|   setTimeout(() => { |     苹果: '椭圆形叶', | ||||||
|     chartInstance.dispatchAction({ |     葡萄: '掌状叶', | ||||||
|       type: 'showTip', |   }, | ||||||
|       seriesIndex: maxSeriesIndex, |   growthStages: { | ||||||
|       dataIndex: maxDataIndex, |     橙子: ['幼苗期', '生长期', '开花期', '结果期'], | ||||||
|     }); |     蓝莓: ['萌芽期', '开花期', '果实膨大期', '成熟期'], | ||||||
|   }, 300); |     水稻: ['分蘖期', '拔节期', '抽穗期', '灌浆期'], | ||||||
|  |     番茄: ['育苗期', '定植期', '开花坐果期', '采收期'], | ||||||
|  |     小麦: ['出苗期', '越冬期', '返青期', '成熟期'], | ||||||
|  |     苹果: ['花芽期', '展叶期', '果实发育期', '成熟期'], | ||||||
|  |     葡萄: ['萌芽期', '新梢生长期', '果实生长期', '成熟期'], | ||||||
|  |   }, | ||||||
|  |   organicMatterRange: { | ||||||
|  |     橙子: [12, 20], | ||||||
|  |     蓝莓: [8, 15], | ||||||
|  |     水稻: [15, 25], | ||||||
|  |     番茄: [10, 18], | ||||||
|  |     小麦: [18, 30], | ||||||
|  |     苹果: [10, 22], | ||||||
|  |     葡萄: [12, 18], | ||||||
|  |   }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // 组件挂载时初始化图表 | // 生成单组作物数据 | ||||||
| onMounted(() => { | function generateCropReport() { | ||||||
|   initChart(); |   const crop = Mock.Random.pick(AGRICULTURE_KNOWLEDGE.crops); | ||||||
|  |   const isHealthy = Mock.Random.integer(0, 10) > 1; // 80%概率健康 | ||||||
|  |   const growthStage = Mock.Random.pick(AGRICULTURE_KNOWLEDGE.growthStages[crop]); | ||||||
|  | 
 | ||||||
|  |   // 异常数据生成 | ||||||
|  |   const abnormalTexts = { | ||||||
|  |     growth: ['发育迟缓', '生长停滞', '提前成熟'], | ||||||
|  |     leaf: ['枯黄', '卷曲', '病斑'], | ||||||
|  |     status: ['欠佳', '受阻', '严重滞后'], | ||||||
|  |     organic: ['过低', '严重不足', '失衡'], | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   return [ | ||||||
|  |     { | ||||||
|  |       title: '作物名称', | ||||||
|  |       status: isHealthy ? 1 : 0, | ||||||
|  |       statusText: crop, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '生长状态', | ||||||
|  |       status: isHealthy ? 1 : 0, | ||||||
|  |       statusText: isHealthy ? growthStage : `${Mock.Random.pick(abnormalTexts.growth)}${growthStage}`, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '植株形态', | ||||||
|  |       status: isHealthy ? 1 : 0, | ||||||
|  |       statusText: AGRICULTURE_KNOWLEDGE.plantTypes[crop], | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '叶片形态', | ||||||
|  |       status: isHealthy ? 1 : 0, | ||||||
|  |       statusText: isHealthy | ||||||
|  |         ? AGRICULTURE_KNOWLEDGE.leafTypes[crop] | ||||||
|  |         : `${Mock.Random.pick(abnormalTexts.leaf)}${AGRICULTURE_KNOWLEDGE.leafTypes[crop]}`, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '生长态势', | ||||||
|  |       status: isHealthy ? 1 : 0, | ||||||
|  |       statusText: isHealthy ? '良好' : Mock.Random.pick(abnormalTexts.status), | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '田间有机质含量', | ||||||
|  |       status: isHealthy ? 1 : 0, | ||||||
|  |       statusText: isHealthy | ||||||
|  |         ? `${Mock.Random.integer(...AGRICULTURE_KNOWLEDGE.organicMatterRange[crop])}%` | ||||||
|  |         : `${Mock.Random.integer(3, 8)}% (${Mock.Random.pick(abnormalTexts.organic)})`, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '生长趋势图', | ||||||
|  |       status: isHealthy ? 1 : 0, | ||||||
|  |       statusText: '', | ||||||
|  |     }, | ||||||
|  |   ]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // 生成7组不同作物数据 | ||||||
|  | const cropMonitoringData = Mock.mock({ | ||||||
|  |   'data|7': [generateCropReport], | ||||||
| }); | }); | ||||||
| // 组件卸载前销毁图表 |  | ||||||
| onBeforeUnmount(() => { |  | ||||||
|   if (chartInstance) { |  | ||||||
|     window.removeEventListener('resize', resizeChart); |  | ||||||
|     chartInstance.dispose(); |  | ||||||
|     chartInstance = null; |  | ||||||
|   } |  | ||||||
| }); |  | ||||||
| // 调整图表大小 |  | ||||||
| const resizeChart = () => { |  | ||||||
|   if (chartInstance) { |  | ||||||
|     chartInstance.resize(); |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| // #endregion | // #endregion | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user