Merge branch 'dev' of http://47.109.205.240:3000/Web/daimp-front into dev
							
								
								
									
										18532
									
								
								sub-operation-service/src/assets/530926geo.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/closing.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/down_1@2x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/bell.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/fall.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/goDown.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/goUp.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/location.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.5 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/rainy.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/rise.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.2 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/sunny.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.2 KiB | 
| After Width: | Height: | Size: 3.6 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/testPic1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 100 KiB | 
| After Width: | Height: | Size: 13 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/windy.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 3.9 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/产能预测.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 602 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/传感器.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/光照传感器.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/土壤温度.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.0 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/土壤湿度.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/排风.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 2.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/监控.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.4 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/空气.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/smartFarm/蒸腾.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 1.6 KiB | 
| @ -1,5 +1,5 @@ | |||||||
| <!-- | <!-- | ||||||
|  * @Description:  |  * @Description: | ||||||
|  * @Author: zenghua.wang |  * @Author: zenghua.wang | ||||||
|  * @Date: 2023-06-20 14:29:45 |  * @Date: 2023-06-20 14:29:45 | ||||||
|  * @LastEditors: zenghua.wang |  * @LastEditors: zenghua.wang | ||||||
|  | |||||||
| @ -0,0 +1,72 @@ | |||||||
|  | <template> | ||||||
|  |   <div ref="chartRef" style="width: 600px; height: 150px"></div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script setup> | ||||||
|  | import { ref, onMounted } from 'vue'; | ||||||
|  | import * as echarts from 'echarts'; | ||||||
|  | 
 | ||||||
|  | const chartRef = ref(null); | ||||||
|  | 
 | ||||||
|  | onMounted(() => { | ||||||
|  |   const myChart = echarts.init(chartRef.value); | ||||||
|  | 
 | ||||||
|  |   const option = { | ||||||
|  |     tooltip: { | ||||||
|  |       trigger: 'item', | ||||||
|  |     }, | ||||||
|  |     xAxis: { | ||||||
|  |       type: 'category', | ||||||
|  |       data: ['1月', '2月', '3月', '4月', '5月', '6月'], | ||||||
|  |       axisLine: { | ||||||
|  |         show: false, // 隐藏X轴线 | ||||||
|  |       }, | ||||||
|  |       axisTick: { | ||||||
|  |         show: false, // 隐藏X轴刻度 | ||||||
|  |       }, | ||||||
|  |       axisLabel: { | ||||||
|  |         color: '#666', // 月份标签颜色 | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     yAxis: { | ||||||
|  |       type: 'value', | ||||||
|  |       show: false, // 完全隐藏Y轴 | ||||||
|  |     }, | ||||||
|  |     series: [ | ||||||
|  |       { | ||||||
|  |         data: [120, 200, 150, 80, 70, 110], // 这里替换为你的实际数据 | ||||||
|  |         type: 'bar', | ||||||
|  |         barWidth: '20%', | ||||||
|  |         itemStyle: { | ||||||
|  |           color: '#4CAF50', // 绿色柱状条 | ||||||
|  |           borderRadius: [6, 6, 6, 6], // 圆角设置(左上、右上、右下、左下) | ||||||
|  |         }, | ||||||
|  |         showBackground: true, | ||||||
|  |         backgroundStyle: { | ||||||
|  |           color: 'rgba(180, 180, 180, 0.2)', // 背景色 | ||||||
|  |           borderRadius: [6, 6, 6, 6], // 背景圆角(与柱子相同) | ||||||
|  |         }, | ||||||
|  |         label: { | ||||||
|  |           show: false, | ||||||
|  |           position: 'top', | ||||||
|  |           formatter: '', // 你可以根据需要调整或移除 | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |     grid: { | ||||||
|  |       left: '-40px', | ||||||
|  |       right: '3%', | ||||||
|  |       bottom: '3%', | ||||||
|  |       top: '15%', | ||||||
|  |       containLabel: true, | ||||||
|  |     }, | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   myChart.setOption(option); | ||||||
|  | 
 | ||||||
|  |   // 响应式调整 | ||||||
|  |   window.addEventListener('resize', function () { | ||||||
|  |     myChart.resize(); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | </script> | ||||||
| @ -1,10 +1,10 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="ecommerce-common-warp"> |   <div class="smartFarm-common-warp"> | ||||||
|     <div class="ecommerce-common-content"> |     <div class="smartFarm-common-content"> | ||||||
|       <div class="left-menu"> |       <div class="left-menu"> | ||||||
|         <slot v-if="$slots.left" name="left"></slot> |         <slot v-if="$slots.left" name="left"></slot> | ||||||
|         <template v-else> |         <template v-else> | ||||||
|           <leftMenu :current-name="currentName"></leftMenu> |           <left-menu :menus="menus"></left-menu> | ||||||
|         </template> |         </template> | ||||||
|       </div> |       </div> | ||||||
|       <div class="common-content"> |       <div class="common-content"> | ||||||
| @ -21,13 +21,48 @@ import leftMenu from './leftMenu.vue'; | |||||||
| const props = defineProps({ | const props = defineProps({ | ||||||
|   currentName: { type: String, default: 'agricultural' }, |   currentName: { type: String, default: 'agricultural' }, | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  | const menus = reactive([ | ||||||
|  |   { | ||||||
|  |     name: 'supplier', | ||||||
|  |     title: '农业环境监测', | ||||||
|  |     icon: 'menu1.png', | ||||||
|  |     path: '/sub-operation-service/smartFarm/main', | ||||||
|  |     isOpen: true, | ||||||
|  |     children: [ | ||||||
|  |       { | ||||||
|  |         name: 'supplier', | ||||||
|  |         title: '田间监测', | ||||||
|  |         path: '/sub-operation-service/smartFarm/fieldInspection', | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         name: 'supplier', | ||||||
|  |         title: '水质监测', | ||||||
|  |         path: '/sub-operation-service/ecommerce-supplier', | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         name: 'supplier', | ||||||
|  |         title: '病虫害监测', | ||||||
|  |         path: '/sub-operation-service/ecommerce-supplier', | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: 'purchaser', | ||||||
|  |     title: '生产管理控制', | ||||||
|  |     icon: 'menu3.png', | ||||||
|  |     path: '/sub-operation-service/ecommerce-purchaser', | ||||||
|  |     isOpen: false, | ||||||
|  |     children: [], | ||||||
|  |   }, | ||||||
|  | ]); | ||||||
| </script> | </script> | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
| .ecommerce-common-warp { | .smartFarm-common-warp { | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   height: calc(100vh - 230px); |   height: calc(100vh - 230px); | ||||||
|   text-align: center; |   text-align: center; | ||||||
|   .ecommerce-common-content { |   .smartFarm-common-content { | ||||||
|     width: $width-main; |     width: $width-main; | ||||||
|     margin: auto; |     margin: auto; | ||||||
|     height: 100%; |     height: 100%; | ||||||
|  | |||||||
| @ -0,0 +1,85 @@ | |||||||
|  | <script setup> | ||||||
|  | import { ref, reactive, onMounted, watch } from 'vue'; | ||||||
|  | import { isEmpty, getAssetsFile } from '@/utils'; | ||||||
|  | import { useRoute, useRouter } from 'vue-router'; | ||||||
|  | const route = useRoute(); | ||||||
|  | const router = useRouter(); | ||||||
|  | 
 | ||||||
|  | const props = defineProps({ | ||||||
|  |   devices: { | ||||||
|  |     type: Array, | ||||||
|  |     required: true, | ||||||
|  |     default: () => [], | ||||||
|  |     validator: (items) => { | ||||||
|  |       return items.every((item) => { | ||||||
|  |         return ( | ||||||
|  |           typeof item === 'object' && | ||||||
|  |           item !== null && | ||||||
|  |           typeof item.id === 'number' && | ||||||
|  |           typeof item.name === 'string' && | ||||||
|  |           typeof item.detail === 'string' && | ||||||
|  |           typeof item.icon === 'string' && | ||||||
|  |           (!item.status || typeof item.status === 'number') | ||||||
|  |         ); | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   title: { | ||||||
|  |     type: String, | ||||||
|  |     required: true, | ||||||
|  |     default: () => '', | ||||||
|  |     validator: (items) => { | ||||||
|  |       return items; | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <el-card style="border-radius: 16px"> | ||||||
|  |       <div style="font-size: 16px; font-weight: bold; text-align: left; color: #000">{{ title }}</div> | ||||||
|  |       <div style="display: flex; justify-content: flex-start; flex-wrap: wrap"> | ||||||
|  |         <div v-for="(item, index) in devices" :key="index" class="device"> | ||||||
|  |           <div v-if="item.status == 0" class="status" style="background-color: #25bf82">正常</div> | ||||||
|  |           <div v-else-if="item.status == -1" class="status" style="background-color: #fe4066">异常</div> | ||||||
|  |           <div style="display: flex; flex-direction: column; justify-content: space-between; height: 100%"> | ||||||
|  |             <img v-if="item.icon === 'camera'" :src="getAssetsFile('images/smartFarm/监控.png')" alt="" /> | ||||||
|  |             <img v-else-if="item.icon === 'sensor'" :src="getAssetsFile('images/smartFarm/传感器.png')" alt="" /> | ||||||
|  |             <div style="text-align: left; font-weight: bold; font-size: 18px">{{ item.name }}</div> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </el-card> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <style scoped lang="scss"> | ||||||
|  | .device { | ||||||
|  |   height: 100px; | ||||||
|  |   width: 18%; | ||||||
|  |   background-color: #f5f5f5; | ||||||
|  |   margin: 20px 1%; | ||||||
|  |   border-radius: 16px; | ||||||
|  |   position: relative; | ||||||
|  |   cursor: pointer; | ||||||
|  |   padding: 10px 20px; | ||||||
|  |   img { | ||||||
|  |     height: 35px; | ||||||
|  |     width: 35px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .status { | ||||||
|  |   border-radius: 0 16px 0 16px; | ||||||
|  |   height: 30px; | ||||||
|  |   width: 30px; | ||||||
|  |   position: absolute; | ||||||
|  |   right: 0; | ||||||
|  |   top: 0; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: center; | ||||||
|  |   color: #ffffff; | ||||||
|  |   font-size: 10px; | ||||||
|  | } | ||||||
|  | </style> | ||||||
							
								
								
									
										183
									
								
								sub-operation-service/src/views/smartFarm/components/mapComp.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,183 @@ | |||||||
|  | <template> | ||||||
|  |   <div ref="mapContainer" style="width: 100%; height: 300px; background: #ffffff; border: 0"></div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script setup> | ||||||
|  | import { ref, onMounted } from 'vue'; | ||||||
|  | import * as echarts from 'echarts'; | ||||||
|  | import json from '@/assets/530926geo.json'; | ||||||
|  | import { getAssetsFile } from '@/utils'; | ||||||
|  | 
 | ||||||
|  | // 您提供的耿马县GeoJSON数据 | ||||||
|  | const gengmaGeoJSON = json; | ||||||
|  | 
 | ||||||
|  | // 模拟乡镇数据(根据图片中的地名) | ||||||
|  | const towns = ref([ | ||||||
|  |   { name: '孟定镇', coord: [99.01, 23.64], weather: '晴', temp: '28℃', icon: 'sunny' }, | ||||||
|  |   { name: '勐简乡', coord: [99.24, 23.79], weather: '多云', temp: '26℃', icon: 'cloudy' }, | ||||||
|  |   { name: '四排山乡', coord: [99.5, 23.38], weather: '小雨', temp: '24℃', icon: 'rainy' }, | ||||||
|  |   { name: '大兴乡', coord: [99.8, 23.76], weather: '多云', temp: '25℃', icon: 'cloudy' }, | ||||||
|  |   { name: '耿马镇', coord: [99.42, 23.66], weather: '多云', temp: '26℃', icon: 'cloudy' }, | ||||||
|  |   { name: '贺派乡', coord: [99.21, 23.4], weather: '晴', temp: '27℃', icon: 'sunny' }, | ||||||
|  |   { name: '芒洪乡', coord: [99.73, 23.59], weather: '阴', temp: '23℃', icon: 'overcast' }, | ||||||
|  |   { name: '勐永镇', coord: [99.53, 23.99], weather: '小雨', temp: '22℃', icon: 'rainy' }, | ||||||
|  |   { name: '勐撒镇', coord: [99.47, 23.85], weather: '晴', temp: '28℃', icon: 'sunny' }, | ||||||
|  | ]); | ||||||
|  | 
 | ||||||
|  | const mapContainer = ref(null); | ||||||
|  | 
 | ||||||
|  | // 获取天气图标路径 | ||||||
|  | // function getWeatherIconPath(iconType) { | ||||||
|  | //   return `/images/${iconType}.png`; // 使用绝对路径 | ||||||
|  | // } | ||||||
|  | function getWeatherIconPath(iconType) { | ||||||
|  |   const iconMap = { | ||||||
|  |     sunny: 'images/smartFarm/sunny.png', | ||||||
|  |     cloudy: 'images/smartFarm/sunnyToCloudy.png', | ||||||
|  |     rainy: 'images/smartFarm/rainy.png', | ||||||
|  |     overcast: 'images/smartFarm/windy.png', | ||||||
|  |   }; | ||||||
|  |   let path = iconMap[iconType] ? iconMap[iconType] : 'images/smartFarm/sunny.png'; | ||||||
|  |   return getAssetsFile(path); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | onMounted(() => { | ||||||
|  |   // 添加防御性检查 | ||||||
|  |   if (!towns.value || towns.value.some((t) => !t.weather)) { | ||||||
|  |     console.error('天气数据不完整'); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  |   const chart = echarts.init(mapContainer.value, 'dark'); | ||||||
|  | 
 | ||||||
|  |   // 添加点击事件监听 | ||||||
|  |   chart.on('click', (params) => { | ||||||
|  |     if (params.componentType === 'series') { | ||||||
|  |       // 点击乡镇标记点 | ||||||
|  |       console.log('点击乡镇:', params.name); | ||||||
|  |       showWeatherDetail(params.data); | ||||||
|  |     } else if (params.componentType === 'geo') { | ||||||
|  |       // 点击地图区域 | ||||||
|  |       console.log('点击地图区域:', params.name); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   // 显示天气详情弹窗 | ||||||
|  |   const showWeatherDetail = (data) => { | ||||||
|  |     console.log(data); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // 注册地图 | ||||||
|  |   echarts.registerMap('耿马县', gengmaGeoJSON); | ||||||
|  | 
 | ||||||
|  |   // 配置项 | ||||||
|  |   const option = { | ||||||
|  |     backgroundColor: '#fff', // 白色背景 | ||||||
|  |     title: { | ||||||
|  |       text: '气象数据', | ||||||
|  |       left: 20, | ||||||
|  |       top: 10, | ||||||
|  |       textStyle: { | ||||||
|  |         color: '#000', // 黑色文字 | ||||||
|  |         fontSize: 18, | ||||||
|  |         fontWeight: 'bold', | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     geo: { | ||||||
|  |       map: '耿马县', | ||||||
|  |       roam: false, | ||||||
|  |       zoom: 1.1, | ||||||
|  |       itemStyle: { | ||||||
|  |         areaColor: '#a8d8ea', // 浅蓝色填充 | ||||||
|  |         borderColor: '#4682B4', // 钢蓝色边界 | ||||||
|  |         borderWidth: 1.2, | ||||||
|  |         shadowColor: 'rgba(0, 100, 150, 0.3)', | ||||||
|  |         shadowBlur: 8, | ||||||
|  |       }, | ||||||
|  |       emphasis: { | ||||||
|  |         itemStyle: { | ||||||
|  |           areaColor: '#7ac5e0', // 稍深的蓝绿色 | ||||||
|  |           borderWidth: 1.5, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     series: [ | ||||||
|  |       { | ||||||
|  |         type: 'scatter', | ||||||
|  |         coordinateSystem: 'geo', | ||||||
|  |         symbolSize: 30, | ||||||
|  |         data: towns.value.map((town) => ({ | ||||||
|  |           name: town.name, | ||||||
|  |           value: [...town.coord, town.temp], | ||||||
|  |           weather: town.weather, | ||||||
|  |           symbol: `image://${getWeatherIconPath(town.icon)}`, | ||||||
|  |           symbolOffset: [10, -10], // 符号向上移 | ||||||
|  |           // 标签下移10px(抵消symbol偏移) | ||||||
|  |           label: { offset: [10, 20] }, | ||||||
|  |         })), | ||||||
|  |         label: { | ||||||
|  |           show: true, | ||||||
|  |           formatter: (params) => { | ||||||
|  |             // 使用rich实现图文复合布局 | ||||||
|  |             return `{name|${params.name}}`; | ||||||
|  |           }, | ||||||
|  |           rich: { | ||||||
|  |             name: { | ||||||
|  |               color: '#333', | ||||||
|  |               fontSize: 12, | ||||||
|  |               align: 'center', | ||||||
|  |               lineHeight: 20, | ||||||
|  |               padding: [2, 0], | ||||||
|  |             }, | ||||||
|  |           }, | ||||||
|  |           position: function (point) { | ||||||
|  |             // 根据坐标动态调整位置(示例逻辑,需根据实际坐标微调) | ||||||
|  |             return point[1] > 23.6 ? 'top' : 'bottom'; | ||||||
|  |           }, | ||||||
|  |           distance: 8, | ||||||
|  |           offset: [0, 0], | ||||||
|  |           padding: [2, 5], | ||||||
|  |           backgroundColor: 'rgba(255,255,255,0.7)', | ||||||
|  |           borderColor: '#4682B4', | ||||||
|  |           borderWidth: 0.5, | ||||||
|  |           borderRadius: 3, | ||||||
|  |         }, | ||||||
|  |         tooltip: { | ||||||
|  |           formatter: (params) => ` | ||||||
|  |           <div style="font-size:14px;color:#333;font-weight:bold;margin-bottom:5px;"> | ||||||
|  |             ${params.name} | ||||||
|  |           </div> | ||||||
|  |           <div style="margin:5px 0;"> | ||||||
|  |             <span style="display:inline-block;width:70px;">天气:</span> | ||||||
|  |             <span style="color:#1E90FF;">${params.data.weather}</span> | ||||||
|  |           </div> | ||||||
|  |           <div> | ||||||
|  |             <span style="display:inline-block;width:70px;">温度:</span> | ||||||
|  |             <span style="color:#1E90FF;">${params.value[2]}</span> | ||||||
|  |           </div> | ||||||
|  |         `, | ||||||
|  |           backgroundColor: 'rgba(255, 255, 255, 0.9)', | ||||||
|  |           borderColor: '#4682B4', | ||||||
|  |           borderWidth: 1, | ||||||
|  |           padding: 10, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |     graphic: { | ||||||
|  |       type: 'text', | ||||||
|  |       left: 20, | ||||||
|  |       bottom: 5, | ||||||
|  |       style: { | ||||||
|  |         text: '数据更新于: 2025.01.01 08:00:00', | ||||||
|  |         fill: '#666', | ||||||
|  |         fontSize: 12, | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   chart.setOption(option); | ||||||
|  | 
 | ||||||
|  |   window.addEventListener('resize', function () { | ||||||
|  |     chart.resize(); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | </script> | ||||||
| @ -0,0 +1,130 @@ | |||||||
|  | <template> | ||||||
|  |   <div ref="mapContainer" style="width: 100%; height: 300px; background: #ffffff"></div> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script setup> | ||||||
|  | import { ref, onMounted } from 'vue'; | ||||||
|  | import * as echarts from 'echarts'; | ||||||
|  | import json from '@/assets/530926geo.json'; | ||||||
|  | import { getAssetsFile } from '@/utils'; | ||||||
|  | 
 | ||||||
|  | // 您提供的耿马县GeoJSON数据 | ||||||
|  | const gengmaGeoJSON = json; | ||||||
|  | 
 | ||||||
|  | // 模拟乡镇数据(根据图片中的地名) | ||||||
|  | const towns = ref([ | ||||||
|  |   { name: '孟定镇', coord: [99.01, 23.64] }, | ||||||
|  |   { name: '勐简乡', coord: [99.24, 23.79] }, | ||||||
|  |   { name: '四排山乡', coord: [99.5, 23.38] }, | ||||||
|  |   { name: '大兴乡', coord: [99.8, 23.76] }, | ||||||
|  |   { name: '耿马镇', coord: [99.42, 23.66] }, | ||||||
|  |   { name: '贺派乡', coord: [99.21, 23.4] }, | ||||||
|  |   { name: '芒洪乡', coord: [99.73, 23.59] }, | ||||||
|  |   { name: '勐永镇', coord: [99.53, 23.99] }, | ||||||
|  |   { name: '勐撒镇', coord: [99.47, 23.85] }, | ||||||
|  | ]); | ||||||
|  | 
 | ||||||
|  | const mapContainer = ref(null); | ||||||
|  | 
 | ||||||
|  | // 获取天气图标路径 | ||||||
|  | // function getWeatherIconPath(iconType) { | ||||||
|  | //   return `/images/${iconType}.png`; // 使用绝对路径 | ||||||
|  | // } | ||||||
|  | function getWeatherIconPath(iconType) { | ||||||
|  |   const iconMap = { | ||||||
|  |     sunny: 'images/smartFarm/sunny.png', | ||||||
|  |     cloudy: 'images/smartFarm/sunnyToCloudy.png', | ||||||
|  |     rainy: 'images/smartFarm/rainy.png', | ||||||
|  |     overcast: 'images/smartFarm/windy.png', | ||||||
|  |   }; | ||||||
|  |   let path = iconMap[iconType] ? iconMap[iconType] : 'images/smartFarm/sunny.png'; | ||||||
|  |   return getAssetsFile(path); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | onMounted(() => { | ||||||
|  |   const chart = echarts.init(mapContainer.value, 'dark'); | ||||||
|  | 
 | ||||||
|  |   // 添加点击事件监听 | ||||||
|  |   chart.on('click', (params) => { | ||||||
|  |     if (params.componentType === 'series') { | ||||||
|  |       // 点击乡镇标记点 | ||||||
|  |       console.log('点击乡镇:', params.name); | ||||||
|  |       showWeatherDetail(params.data); | ||||||
|  |     } else if (params.componentType === 'geo') { | ||||||
|  |       // 点击地图区域 | ||||||
|  |       console.log('点击地图区域:', params.name); | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   // 显示天气详情弹窗 | ||||||
|  |   const showWeatherDetail = (data) => { | ||||||
|  |     console.log(data); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // 注册地图 | ||||||
|  |   echarts.registerMap('耿马县', gengmaGeoJSON); | ||||||
|  | 
 | ||||||
|  |   // 配置项 | ||||||
|  |   const option = { | ||||||
|  |     backgroundColor: '#fff', // 白色背景 | ||||||
|  |     title: { | ||||||
|  |       text: '', | ||||||
|  |       left: 20, | ||||||
|  |       top: 10, | ||||||
|  |       textStyle: { | ||||||
|  |         color: '#000', // 黑色文字 | ||||||
|  |         fontSize: 18, | ||||||
|  |         fontWeight: 'bold', | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     geo: { | ||||||
|  |       map: '耿马县', | ||||||
|  |       roam: false, | ||||||
|  |       zoom: 1.1, | ||||||
|  |       label: { | ||||||
|  |         show: true, // 开启地名显示 | ||||||
|  |         color: '#333', | ||||||
|  |         fontSize: 12, | ||||||
|  |         formatter: (params) => params.name, // 直接显示地名 | ||||||
|  |       }, | ||||||
|  |       itemStyle: { | ||||||
|  |         areaColor: '#a8d8ea', // 浅蓝色填充 | ||||||
|  |         borderColor: '#4682B4', // 钢蓝色边界 | ||||||
|  |         borderWidth: 1.2, | ||||||
|  |         shadowColor: 'rgba(0, 100, 150, 0.3)', | ||||||
|  |         shadowBlur: 8, | ||||||
|  |       }, | ||||||
|  |       emphasis: { | ||||||
|  |         label: { | ||||||
|  |           show: true, | ||||||
|  |           color: '#1890FF', | ||||||
|  |         }, | ||||||
|  |         itemStyle: { | ||||||
|  |           areaColor: '#BAE7FF', | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |     series: [ | ||||||
|  |       { | ||||||
|  |         type: 'scatter', | ||||||
|  |         coordinateSystem: 'geo', | ||||||
|  |         symbolSize: 0, | ||||||
|  |         data: towns.value, | ||||||
|  |         label: { | ||||||
|  |           show: true, | ||||||
|  |           position: 'inside', // 地名显示在区域内 | ||||||
|  |           formatter: '{b}', | ||||||
|  |           color: '#000', | ||||||
|  |           fontSize: 10, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   chart.setOption(option); | ||||||
|  | 
 | ||||||
|  |   window.addEventListener('resize', function () { | ||||||
|  |     chart.resize(); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | </script> | ||||||
							
								
								
									
										115
									
								
								sub-operation-service/src/views/smartFarm/components/stream.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,115 @@ | |||||||
|  | <script setup> | ||||||
|  | import { ref, reactive, onMounted, onUnmounted } from 'vue'; | ||||||
|  | import { isEmpty, getAssetsFile } from '@/utils'; | ||||||
|  | import { useRoute, useRouter } from 'vue-router'; | ||||||
|  | import Hls from 'hls.js'; | ||||||
|  | const route = useRoute(); | ||||||
|  | const router = useRouter(); | ||||||
|  | 
 | ||||||
|  | const currentDevice = ref(0); | ||||||
|  | const currentPicture = ref(0); | ||||||
|  | const videoPlayer = ref(null); | ||||||
|  | const hls = ref(null); | ||||||
|  | 
 | ||||||
|  | const loading = ref(false); | ||||||
|  | const error = ref(false); | ||||||
|  | 
 | ||||||
|  | const props = defineProps({ | ||||||
|  |   title: { | ||||||
|  |     type: String, | ||||||
|  |     required: true, | ||||||
|  |     default: () => '', | ||||||
|  |     validator: (items) => { | ||||||
|  |       return items; | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   devices: { | ||||||
|  |     type: Array, | ||||||
|  |     required: true, | ||||||
|  |     default: () => [], | ||||||
|  |     validator: (items) => { | ||||||
|  |       return items.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') | ||||||
|  |         ); | ||||||
|  |       }); | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | onUnmounted(() => { | ||||||
|  |   if (hls.value) { | ||||||
|  |     hls.value.destroy(); | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | onMounted(async () => { | ||||||
|  |   if (Hls.isSupported()) { | ||||||
|  |     hls.value = new Hls(); | ||||||
|  |     hls.value.loadSource('https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8'); | ||||||
|  |     hls.value.attachMedia(videoPlayer.value); | ||||||
|  |     hls.value.on(Hls.Events.MANIFEST_PARSED, () => { | ||||||
|  |       videoPlayer.value.play(); | ||||||
|  |     }); | ||||||
|  |   } else if (videoPlayer.value.canPlayType('application/vnd.apple.mpegurl')) { | ||||||
|  |     // Safari原生支持HLS | ||||||
|  |     videoPlayer.value.src = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8'; | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <el-card style="border-radius: 16px"> | ||||||
|  |     <div style="display: flex; justify-content: space-between"> | ||||||
|  |       <div style="font-size: 16px; font-weight: bold; text-align: left">{{ title }}</div> | ||||||
|  |       <div style="color: #999999; line-height: 25px"> | ||||||
|  |         当前设备 | ||||||
|  |         <el-select v-model="currentDevice" placeholder="Select" size="small" style="width: 160px; margin-left: 10px"> | ||||||
|  |           <el-option v-for="item in devices" :key="item.value" :label="item.detail" :value="item.id" /> | ||||||
|  |         </el-select> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |     <div style="display: flex; justify-content: space-between; align-items: center"> | ||||||
|  |       <div class="video-wrapper"> | ||||||
|  |         <video ref="videoPlayer" controls autoplay muted></video> | ||||||
|  |         <div v-if="loading" class="status-message">正在加载直播流...</div> | ||||||
|  |         <div v-if="error" class="status-message error">{{ error }}</div> | ||||||
|  |       </div> | ||||||
|  |       <div class="pictures-wrapper"> | ||||||
|  |         <img :src="getAssetsFile('images/smartFarm/goUp.png')" alt="" style="width: 100px" /> | ||||||
|  |         <img :src="getAssetsFile('images/smartFarm/testPic1.png')" style="width: 80%; margin: 5px 0" :alt="devices[currentDevice].detail" /> | ||||||
|  |         <img :src="getAssetsFile('images/smartFarm/testPic1.png')" style="width: 80%; margin: 5px 0" :alt="devices[currentDevice].detail" /> | ||||||
|  |         <img :src="getAssetsFile('images/smartFarm/goDown.png')" alt="" style="width: 100px" /> | ||||||
|  |       </div> | ||||||
|  |     </div> | ||||||
|  |   </el-card> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <style scoped lang="scss"> | ||||||
|  | .video-wrapper { | ||||||
|  |   height: 100%; | ||||||
|  |   margin-top: 30px; | ||||||
|  |   width: 58%; | ||||||
|  |   video { | ||||||
|  |     width: 100%; | ||||||
|  |     border-radius: 16px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .pictures-wrapper { | ||||||
|  |   width: 38%; | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   margin-top: 20px; | ||||||
|  |   img { | ||||||
|  |     cursor: pointer; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @ -2,25 +2,359 @@ | |||||||
|   <section> |   <section> | ||||||
|     <common> |     <common> | ||||||
|       <template #main> |       <template #main> | ||||||
|         <div>农田监测</div> |         <div> | ||||||
|  |           <devices :title="'田间监测设备'" :devices="devices"></devices> | ||||||
|  |         </div> | ||||||
|  |         <div style="display: flex; justify-content: space-between; margin-top: 10px"> | ||||||
|  |           <stream :title="'田间监测实时监控'" :devices="devices" style="width: 60%"></stream> | ||||||
|  |           <el-card style="width: calc(40% - 20px); border-radius: 16px; padding: 10px"> | ||||||
|  |             <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: 150px"></div> | ||||||
|  |           </el-card> | ||||||
|  |         </div> | ||||||
|       </template> |       </template> | ||||||
|     </common> |     </common> | ||||||
|   </section> |   </section> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> | <script setup> | ||||||
| import { ref } from 'vue'; | import { ref, onMounted, onBeforeUnmount } from 'vue'; | ||||||
| import Common from '../components/common.vue'; | import Common from '../components/common.vue'; | ||||||
| 
 | import Devices from '@/views/smartFarm/components/devices.vue'; | ||||||
|  | import Stream from '@/views/smartFarm/components/stream.vue'; | ||||||
|  | import * as echarts from 'echarts'; | ||||||
| /* --------------- data --------------- */ | /* --------------- data --------------- */ | ||||||
| // #region | // #region | ||||||
| 
 | // 图表 DOM 引用 | ||||||
|  | const chartRef = ref(null); | ||||||
|  | // ECharts 实例 | ||||||
|  | let chartInstance = null; | ||||||
|  | // 颜色列表 | ||||||
|  | const colorList = ['#9E87FF', '#73DDFF']; | ||||||
|  | // x轴数据 | ||||||
|  | const xData = ['1月', '2月', '3月', '4月', '5月', '6月']; | ||||||
|  | const devices = ref([ | ||||||
|  |   { | ||||||
|  |     name: 'A-001', | ||||||
|  |     icon: 'camera', | ||||||
|  |     detail: 'A区-监控设备9', | ||||||
|  |     status: '0', | ||||||
|  |     id: 0, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: 'A-002', | ||||||
|  |     icon: 'camera', | ||||||
|  |     detail: 'A区-监控设备66', | ||||||
|  |     status: '0', | ||||||
|  |     id: 1, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: 'A-003', | ||||||
|  |     icon: 'sensor', | ||||||
|  |     detail: 'A区-监控设备7', | ||||||
|  |     status: '0', | ||||||
|  |     id: 2, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: 'A-004', | ||||||
|  |     icon: 'sensor', | ||||||
|  |     detail: 'A区-监控设备1', | ||||||
|  |     status: '-1', | ||||||
|  |     id: 3, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: 'A-005', | ||||||
|  |     icon: 'sensor', | ||||||
|  |     detail: 'A区-监控设备5', | ||||||
|  |     status: '-1', | ||||||
|  |     id: 4, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: 'A-006', | ||||||
|  |     icon: 'camera', | ||||||
|  |     status: '0', | ||||||
|  |     detail: 'A区-监控设备21', | ||||||
|  |     id: 5, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: 'A-007', | ||||||
|  |     icon: 'camera', | ||||||
|  |     status: '0', | ||||||
|  |     detail: 'A区-监控设备4', | ||||||
|  |     id: 6, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     name: 'A-008', | ||||||
|  |     detail: 'A区-监控设备3', | ||||||
|  |     icon: 'camera', | ||||||
|  |     status: '0', | ||||||
|  |     id: 7, | ||||||
|  |   }, | ||||||
|  | ]); | ||||||
| // #endregion | // #endregion | ||||||
| 
 |  | ||||||
| /* --------------- methods --------------- */ | /* --------------- methods --------------- */ | ||||||
| // #region | // #region | ||||||
|  | // 初始化图表 | ||||||
|  | const initChart = () => { | ||||||
|  |   // 图表配置 | ||||||
|  |   const option = { | ||||||
|  |     backgroundColor: '#fff', | ||||||
|  |     title: { | ||||||
|  |       text: '简单折线图', | ||||||
|  |       textStyle: { | ||||||
|  |         fontSize: 12, | ||||||
|  |         fontWeight: 400, | ||||||
|  |       }, | ||||||
|  |       left: 'center', | ||||||
|  |       top: '5%', | ||||||
|  |     }, | ||||||
|  |     legend: { | ||||||
|  |       icon: 'circle', | ||||||
|  |       top: '5%', | ||||||
|  |       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: '15%', | ||||||
|  |     }, | ||||||
|  |     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', | ||||||
|  |         axisTick: { | ||||||
|  |           show: false, | ||||||
|  |         }, | ||||||
|  |         axisLine: { | ||||||
|  |           show: true, | ||||||
|  |           lineStyle: { | ||||||
|  |             color: 'rgba(107,107,107,0.37)', | ||||||
|  |           }, | ||||||
|  |         }, | ||||||
|  |         axisLabel: { | ||||||
|  |           textStyle: { | ||||||
|  |             color: '#999', | ||||||
|  |           }, | ||||||
|  |         }, | ||||||
|  |         splitLine: { | ||||||
|  |           show: false, | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |     series: [ | ||||||
|  |       { | ||||||
|  |         name: 'Adidas', | ||||||
|  |         type: 'line', | ||||||
|  |         data: [10, 10, 30, 12, 15, 3, 7], | ||||||
|  |         symbolSize: 1, | ||||||
|  |         symbol: 'circle', | ||||||
|  |         smooth: true, | ||||||
|  |         yAxisIndex: 0, | ||||||
|  |         showSymbol: false, | ||||||
|  |         lineStyle: { | ||||||
|  |           width: 5, | ||||||
|  |           color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [ | ||||||
|  |             { | ||||||
|  |               offset: 0, | ||||||
|  |               color: '#9effff', | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |               offset: 1, | ||||||
|  |               color: '#9E87FF', | ||||||
|  |             }, | ||||||
|  |           ]), | ||||||
|  |           shadowColor: 'rgba(158,135,255, 0.3)', | ||||||
|  |           shadowBlur: 10, | ||||||
|  |           shadowOffsetY: 20, | ||||||
|  |         }, | ||||||
|  |         itemStyle: { | ||||||
|  |           color: colorList[0], | ||||||
|  |           borderColor: colorList[0], | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         name: 'Nike', | ||||||
|  |         type: 'line', | ||||||
|  |         data: [5, 12, 11, 14, 25, 16, 10], | ||||||
|  |         symbolSize: 1, | ||||||
|  |         symbol: 'circle', | ||||||
|  |         smooth: true, | ||||||
|  |         yAxisIndex: 0, | ||||||
|  |         showSymbol: false, | ||||||
|  |         lineStyle: { | ||||||
|  |           width: 5, | ||||||
|  |           color: new echarts.graphic.LinearGradient(1, 1, 0, 0, [ | ||||||
|  |             { | ||||||
|  |               offset: 0, | ||||||
|  |               color: '#73DD39', | ||||||
|  |             }, | ||||||
|  |             { | ||||||
|  |               offset: 1, | ||||||
|  |               color: '#73DDFF', | ||||||
|  |             }, | ||||||
|  |           ]), | ||||||
|  |           shadowColor: 'rgba(115,221,255, 0.3)', | ||||||
|  |           shadowBlur: 10, | ||||||
|  |           shadowOffsetY: 20, | ||||||
|  |         }, | ||||||
|  |         itemStyle: { | ||||||
|  |           color: colorList[1], | ||||||
|  |           borderColor: colorList[1], | ||||||
|  |         }, | ||||||
|  |       }, | ||||||
|  |     ], | ||||||
|  |   }; | ||||||
|  |   if (chartRef.value) { | ||||||
|  |     // 基于准备好的dom,初始化echarts实例 | ||||||
|  |     chartInstance = echarts.init(chartRef.value); | ||||||
|  |     // 绘制图表 | ||||||
|  |     chartInstance.setOption(option); | ||||||
| 
 | 
 | ||||||
|  |     // 响应式调整 | ||||||
|  |     window.addEventListener('resize', resizeChart); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | // 组件挂载时初始化图表 | ||||||
|  | onMounted(() => { | ||||||
|  |   initChart(); | ||||||
|  | }); | ||||||
|  | // 组件卸载前销毁图表 | ||||||
|  | onBeforeUnmount(() => { | ||||||
|  |   if (chartInstance) { | ||||||
|  |     window.removeEventListener('resize', resizeChart); | ||||||
|  |     chartInstance.dispose(); | ||||||
|  |     chartInstance = null; | ||||||
|  |   } | ||||||
|  | }); | ||||||
|  | // 调整图表大小 | ||||||
|  | const resizeChart = () => { | ||||||
|  |   if (chartInstance) { | ||||||
|  |     chartInstance.resize(); | ||||||
|  |   } | ||||||
|  | }; | ||||||
| // #endregion | // #endregion | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped> | ||||||
|  | .plantStatus { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   font-size: 14px; | ||||||
|  |   margin: 7px 0; | ||||||
|  |   .leftKey { | ||||||
|  |     color: #000000; | ||||||
|  |   } | ||||||
|  |   .rightValue { | ||||||
|  |     color: #25bf82; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | |||||||
| @ -3,7 +3,289 @@ | |||||||
|     <common> |     <common> | ||||||
|       <template #main> |       <template #main> | ||||||
|         <div> |         <div> | ||||||
|           <el-card shadow="hover"> </el-card> |           <el-card shadow="hover"> | ||||||
|  |             <el-row> | ||||||
|  |               <el-col :span="10"> | ||||||
|  |                 <map-comp style="height: 300px; width: 100%; border: 0"></map-comp> | ||||||
|  |               </el-col> | ||||||
|  |               <el-col :span="1"> </el-col> | ||||||
|  |               <el-col :span="13"> | ||||||
|  |                 <div class="location"> | ||||||
|  |                   耿马县·孟定镇<img :src="getAssetsFile('images/smartFarm/location.png')" height="20" style="margin-left: 8px" alt="" /> | ||||||
|  |                 </div> | ||||||
|  |                 <div style="display: flex; justify-content: space-around"> | ||||||
|  |                   <el-card v-for="(item, index) in weatherData" :key="index" :body-style="{ padding: 0 }" shadow="always" class="weatherCards"> | ||||||
|  |                     <div>{{ item.time }}</div> | ||||||
|  |                     <div><img :src="getAssetsFile('images/smartFarm/' + item.weather + '.png')" alt="" height="50" /></div> | ||||||
|  |                     <div>{{ item.temp }}℃</div> | ||||||
|  |                   </el-card> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="details"> | ||||||
|  |                   <div class="details-block"> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">温度</div> | ||||||
|  |                       <div class="rightValue"> | ||||||
|  |                         {{ currentData.temp }} | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">PM2.5</div> | ||||||
|  |                       <div class="rightValue">{{ currentData.PM2 }}μg/m³</div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">作物虫害</div> | ||||||
|  |                       <div class="rightValue"> | ||||||
|  |                         {{ currentData.bugs === 0 ? '无' : '有' }} | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">土壤温度</div> | ||||||
|  |                       <div class="rightValue">{{ currentData.dustTemp }}℃</div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="details-block"> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">湿度</div> | ||||||
|  |                       <div class="rightValue">{{ currentData.wet }}%</div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">PM10</div> | ||||||
|  |                       <div class="rightValue">{{ currentData.temp }}μg/m³</div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">作物病害</div> | ||||||
|  |                       <div class="rightValue"> | ||||||
|  |                         {{ currentData.sick === 0 ? '无' : '有' }} | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">土壤湿度</div> | ||||||
|  |                       <div class="rightValue">{{ currentData.dustWet }}%</div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="details-block"> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">风向</div> | ||||||
|  |                       <div class="rightValue"> | ||||||
|  |                         {{ currentData.wind }} | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">光照度</div> | ||||||
|  |                       <div class="rightValue">{{ currentData.light }}Lux</div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">风速</div> | ||||||
|  |                       <div class="rightValue">{{ currentData.temp }}m/s</div> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="detail"> | ||||||
|  |                       <div class="leftTitle">土壤酸碱度</div> | ||||||
|  |                       <div class="rightValue"> | ||||||
|  |                         {{ currentData.PH }} | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </el-col> | ||||||
|  |             </el-row> | ||||||
|  |           </el-card> | ||||||
|  |           <el-card shadow="hover" style="margin-top: 10px"> | ||||||
|  |             <div style="display: flex; padding: 20px"> | ||||||
|  |               <div style="width: 30%"> | ||||||
|  |                 <div style="font-size: 18px; font-weight: bold; text-align: left">土壤数据</div> | ||||||
|  |                 <div style="display: flex"> | ||||||
|  |                   <div class="dustData"> | ||||||
|  |                     <div> | ||||||
|  |                       <img :src="getAssetsFile('images/smartFarm/光照传感器.png')" alt="" /> | ||||||
|  |                       光照 | ||||||
|  |                     </div> | ||||||
|  |                     <div class="values">2000Lux</div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="dustData"> | ||||||
|  |                     <div> | ||||||
|  |                       <img :src="getAssetsFile('images/smartFarm/排风.png')" alt="" /> | ||||||
|  |                       排风 | ||||||
|  |                     </div> | ||||||
|  |                     <div class="values">15m³/h</div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="dustData"> | ||||||
|  |                     <div> | ||||||
|  |                       <img :src="getAssetsFile('images/smartFarm/蒸腾.png')" alt="" /> | ||||||
|  |                       蒸腾 | ||||||
|  |                     </div> | ||||||
|  |                     <div class="values">2000Lux</div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div style="display: flex"> | ||||||
|  |                   <div class="dustData"> | ||||||
|  |                     <div> | ||||||
|  |                       <img :src="getAssetsFile('images/smartFarm/土壤湿度.png')" alt="" /> | ||||||
|  |                       湿度 | ||||||
|  |                     </div> | ||||||
|  |                     <div class="values">26%</div> | ||||||
|  |                     <div class="values">34%</div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="dustData"> | ||||||
|  |                     <div> | ||||||
|  |                       <img :src="getAssetsFile('images/smartFarm/土壤温度.png')" alt="" /> | ||||||
|  |                       温度 | ||||||
|  |                     </div> | ||||||
|  |                     <div class="values">32℃</div> | ||||||
|  |                     <div class="values">28℃</div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="dustData"> | ||||||
|  |                     <div> | ||||||
|  |                       <img :src="getAssetsFile('images/smartFarm/空气.png')" alt="" /> | ||||||
|  |                       空气 | ||||||
|  |                     </div> | ||||||
|  |                     <div class="values">300ppm</div> | ||||||
|  |                     <div class="values">34%</div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="report"> | ||||||
|  |                   <div><img :src="getAssetsFile('images/smartFarm/bell.png')" alt="" /></div> | ||||||
|  |                   <div class="warning"> | ||||||
|  |                     <div>温度</div> | ||||||
|  |                     <div>36℃</div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="warning"> | ||||||
|  |                     <div>超高</div> | ||||||
|  |                     <div>4℃</div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |               <div style="width: 35%"> | ||||||
|  |                 <map-simple style="height: 320px; width: 100%"></map-simple> | ||||||
|  |               </div> | ||||||
|  |               <div style="width: 35%"> | ||||||
|  |                 <div style="margin-top: 70px; display: flex; text-align: left"> | ||||||
|  |                   <el-col :span="12"> | ||||||
|  |                     <el-row class="dataTitle">泵压管控mpa</el-row> | ||||||
|  |                     <el-row> | ||||||
|  |                       <el-col :span="12"> | ||||||
|  |                         <span style="font-size: 15px">输入</span> | ||||||
|  |                         <span class="values">11</span> | ||||||
|  |                       </el-col> | ||||||
|  |                       <el-col :span="12"> | ||||||
|  |                         <span style="font-size: 15px">末端</span> | ||||||
|  |                         <span class="values">2</span> | ||||||
|  |                       </el-col> | ||||||
|  |                     </el-row> | ||||||
|  |                   </el-col> | ||||||
|  |                   <el-col :span="12"> | ||||||
|  |                     <el-row class="dataTitle">灌溉流量m²/h</el-row> | ||||||
|  |                     <el-row> | ||||||
|  |                       <el-col :span="12"> | ||||||
|  |                         <span style="font-size: 15px">灌溉</span> | ||||||
|  |                         <span class="values">18℃</span> | ||||||
|  |                       </el-col> | ||||||
|  |                       <el-col :span="12"> | ||||||
|  |                         <span style="font-size: 15px">回液</span> | ||||||
|  |                         <span class="values">18℃</span> | ||||||
|  |                       </el-col> | ||||||
|  |                     </el-row> | ||||||
|  |                   </el-col> | ||||||
|  |                 </div> | ||||||
|  |                 <div style="display: flex; text-align: left"> | ||||||
|  |                   <el-col :span="12"> | ||||||
|  |                     <el-row class="dataTitle">水肥监测</el-row> | ||||||
|  |                     <el-row> | ||||||
|  |                       <el-col :span="12"> | ||||||
|  |                         <span style="font-size: 15px">PH</span> | ||||||
|  |                         <span class="values">8</span> | ||||||
|  |                       </el-col> | ||||||
|  |                       <el-col :span="12"> | ||||||
|  |                         <span style="font-size: 15px">输入</span> | ||||||
|  |                         <span class="values">18℃</span> | ||||||
|  |                       </el-col> | ||||||
|  |                     </el-row> | ||||||
|  |                   </el-col> | ||||||
|  |                   <el-col :span="12"> </el-col> | ||||||
|  |                 </div> | ||||||
|  |                 <el-row class="dataTitle">灌溉流量m²/h</el-row> | ||||||
|  |                 <charts-flow style="height: 150px; width: 100%"></charts-flow> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </el-card> | ||||||
|  |           <el-card shadow="hover" style="margin-top: 10px"> | ||||||
|  |             <div style="display: flex; padding: 20px"> | ||||||
|  |               <div style="width: 50%"> | ||||||
|  |                 <div style="font-size: 18px; font-weight: bold; text-align: left">产能预测</div> | ||||||
|  |                 <div style="display: flex; justify-content: flex-start; margin: 20px 0"> | ||||||
|  |                   <div class="plansBlock" style="background-color: #25bf82"> | ||||||
|  |                     <div style="">预计生产</div> | ||||||
|  |                     <div style="font-weight: 900">300吨</div> | ||||||
|  |                   </div> | ||||||
|  |                   <div class="plansBlock" style="background-color: #ffbe4d; margin-left: 5%"> | ||||||
|  |                     <div>预计产值</div> | ||||||
|  |                     <div style="font-weight: 900">1500万元</div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="coins"> | ||||||
|  |                   <div style="width: 28%"> | ||||||
|  |                     <div style="text-align: left; font-size: 14px; color: #999999">水质综合评分</div> | ||||||
|  |                     <div style="display: flex; justify-content: space-between; margin-top: 5px"> | ||||||
|  |                       <div style="display: flex; align-items: center; font-size: 20px"> | ||||||
|  |                         <div class="shu" style="background-color: #3685fe"></div> | ||||||
|  |                         <div style="margin-left: 5px">87</div> | ||||||
|  |                       </div> | ||||||
|  |                       <div style="line-height: 30px"> | ||||||
|  |                         <img :src="getAssetsFile('images/smartFarm/fall.png')" alt="" style="width: 25px; height: 25px" /> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                   <div style="width: 28%"> | ||||||
|  |                     <div style="text-align: left; font-size: 14px; color: #999999">病虫害管控评分</div> | ||||||
|  |                     <div style="display: flex; justify-content: space-between; margin-top: 5px"> | ||||||
|  |                       <div style="display: flex; align-items: center; font-size: 20px"> | ||||||
|  |                         <div class="shu" style="background-color: #25bf82"></div> | ||||||
|  |                         <div style="margin-left: 5px">87</div> | ||||||
|  |                       </div> | ||||||
|  |                       <div style="line-height: 30px"> | ||||||
|  |                         <img :src="getAssetsFile('images/smartFarm/rise.png')" alt="" style="width: 25px; height: 25px" /> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                   <div style="width: 28%"> | ||||||
|  |                     <div style="text-align: left; font-size: 14px; color: #999999">环境综合评分</div> | ||||||
|  |                     <div style="display: flex; justify-content: space-between; margin-top: 5px"> | ||||||
|  |                       <div style="display: flex; align-items: center; font-size: 20px"> | ||||||
|  |                         <div class="shu" style="background-color: #ffd500"></div> | ||||||
|  |                         <div style="margin-left: 5px">87</div> | ||||||
|  |                       </div> | ||||||
|  |                       <div style="line-height: 30px"> | ||||||
|  |                         <img :src="getAssetsFile('images/smartFarm/rise.png')" alt="" style="width: 25px; height: 25px" /> | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  | 
 | ||||||
|  |                 <div class="vars"> | ||||||
|  |                   <div style="display: flex; justify-content: space-between; width: 45%"> | ||||||
|  |                     <div style="color: #999999">种植面积</div> | ||||||
|  |                     <div style="color: #25bf82; font-weight: 900">500亩</div> | ||||||
|  |                   </div> | ||||||
|  |                   <div style="display: flex; justify-content: space-between; width: 45%"> | ||||||
|  |                     <div style="color: #999999">水质监测</div> | ||||||
|  |                     <div style="color: #25bf82; font-weight: 900">1266次</div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |                 <div class="vars"> | ||||||
|  |                   <div style="display: flex; justify-content: space-between; width: 45%"> | ||||||
|  |                     <div style="color: #999999">病虫害监测</div> | ||||||
|  |                     <div style="color: #25bf82; font-weight: 900">367次</div> | ||||||
|  |                   </div> | ||||||
|  |                   <div style="display: flex; justify-content: space-between; width: 45%"> | ||||||
|  |                     <div style="color: #999999">环境监测</div> | ||||||
|  |                     <div style="color: #25bf82; font-weight: 900">1547次</div> | ||||||
|  |                   </div> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |               <div style="width: 50%"> | ||||||
|  |                 <img style="width: 100%" :src="getAssetsFile('images/smartFarm/产能预测.png')" alt="" /> | ||||||
|  |               </div> | ||||||
|  |             </div> | ||||||
|  |           </el-card> | ||||||
|         </div> |         </div> | ||||||
|       </template> |       </template> | ||||||
|     </common> |     </common> | ||||||
| @ -11,12 +293,63 @@ | |||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script setup> | <script setup> | ||||||
| import { ref } from 'vue'; | import { ref, onMounted } from 'vue'; | ||||||
| import Common from './components/common.vue'; | import Common from './components/common.vue'; | ||||||
|  | import * as echarts from 'echarts'; | ||||||
|  | import MapComp from '@/views/smartFarm/components/mapComp.vue'; | ||||||
|  | import { getAssetsFile } from '@/utils/index.js'; | ||||||
|  | import MapSimple from '@/views/smartFarm/components/mapSimple.vue'; | ||||||
|  | import ChartsFlow from '@/views/smartFarm/components/charts-flow.vue'; | ||||||
| 
 | 
 | ||||||
| /* --------------- data --------------- */ | /* --------------- data --------------- */ | ||||||
| // #region | // #region | ||||||
|  | const weatherData = ref([ | ||||||
|  |   { | ||||||
|  |     weather: 'sunny', | ||||||
|  |     time: '15:00', | ||||||
|  |     temp: '18', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     weather: 'sunnyToCloudy', | ||||||
|  |     time: '16:00', | ||||||
|  |     temp: '19', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     weather: 'thunderRain', | ||||||
|  |     time: '17:00', | ||||||
|  |     temp: '19', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     weather: 'rainy', | ||||||
|  |     time: '18:00', | ||||||
|  |     temp: '18', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     weather: 'rainy', | ||||||
|  |     time: '19:00', | ||||||
|  |     temp: '15', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     weather: 'windy', | ||||||
|  |     time: '20:00', | ||||||
|  |     temp: '13', | ||||||
|  |   }, | ||||||
|  | ]); | ||||||
| 
 | 
 | ||||||
|  | const currentData = ref({ | ||||||
|  |   temp: 18, // 当前温度 | ||||||
|  |   PM2: 80, // 空气质量 μg/m³ | ||||||
|  |   bugs: 0, // 虫害 | ||||||
|  |   dustTemp: 15, // 土壤温度 ℃ | ||||||
|  |   wet: 56, // 湿度 % | ||||||
|  |   PM10: 120, // 空气质量 μg/m³ | ||||||
|  |   sick: 0, // 病害 | ||||||
|  |   dustWet: 64, // 土壤湿度% | ||||||
|  |   wind: '东南风', // 风向 | ||||||
|  |   light: 500, // 光照Lux | ||||||
|  |   windSpeed: 1.5, // 风速 m/s | ||||||
|  |   PH: 6.5, // 土壤酸碱度 | ||||||
|  | }); | ||||||
| // #endregion | // #endregion | ||||||
| 
 | 
 | ||||||
| /* --------------- methods --------------- */ | /* --------------- methods --------------- */ | ||||||
| @ -25,4 +358,121 @@ import Common from './components/common.vue'; | |||||||
| // #endregion | // #endregion | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style lang="scss" scoped></style> | <style lang="scss" scoped> | ||||||
|  | .vars { | ||||||
|  |   width: 95%; | ||||||
|  |   margin: 15px 0; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   font-size: 14px; | ||||||
|  | } | ||||||
|  | .shu { | ||||||
|  |   width: 4px; | ||||||
|  |   height: 30px; | ||||||
|  |   border-radius: 2px; | ||||||
|  | } | ||||||
|  | .coins { | ||||||
|  |   display: flex; | ||||||
|  |   width: 95%; | ||||||
|  |   height: 60px; | ||||||
|  |   justify-content: space-between; | ||||||
|  | } | ||||||
|  | .plansBlock { | ||||||
|  |   height: 90px; | ||||||
|  |   width: 45%; | ||||||
|  |   border-radius: 16px; | ||||||
|  |   box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   justify-content: space-around; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   padding: 10px 20px; | ||||||
|  |   color: #ffffff; | ||||||
|  |   font-size: 16px; | ||||||
|  | } | ||||||
|  | .values { | ||||||
|  |   color: #25bf82; | ||||||
|  |   font-size: 15px; | ||||||
|  |   margin-left: 5px; | ||||||
|  | } | ||||||
|  | .dataTitle { | ||||||
|  |   margin: 4px 0; | ||||||
|  |   color: #999999; | ||||||
|  | } | ||||||
|  | .warning { | ||||||
|  |   div { | ||||||
|  |     margin: 4px 0; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .report { | ||||||
|  |   height: 70px; | ||||||
|  |   width: 100%; | ||||||
|  |   border-radius: 10px; | ||||||
|  |   display: flex; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: space-around; | ||||||
|  |   background: linear-gradient(to left, #ffc9d4 0%, #ffffff 100% /* 底部稍深青色 */); | ||||||
|  |   img { | ||||||
|  |     height: 40px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .dustData { | ||||||
|  |   width: 33%; | ||||||
|  |   height: 70px; | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   flex-direction: column; | ||||||
|  |   font-size: 15px; | ||||||
|  |   margin: 20px 0; | ||||||
|  |   .values { | ||||||
|  |     color: #25bf82; | ||||||
|  |   } | ||||||
|  |   img { | ||||||
|  |     height: 20px; | ||||||
|  |     margin-right: 5px; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .details { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-around; | ||||||
|  |   .details-block { | ||||||
|  |     width: 29%; | ||||||
|  |     display: flex; | ||||||
|  |     flex-direction: column; | ||||||
|  |     justify-content: space-around; | ||||||
|  |   } | ||||||
|  |   .detail { | ||||||
|  |     display: flex; | ||||||
|  |     justify-content: space-between; | ||||||
|  |     padding: 8px 0; | ||||||
|  |     .leftTitle { | ||||||
|  |       font-size: 15px; | ||||||
|  |       color: #999999; | ||||||
|  |     } | ||||||
|  |     .rightValue { | ||||||
|  |       font-size: 15px; | ||||||
|  |       color: #25bf82; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | .location { | ||||||
|  |   padding: 20px 0; | ||||||
|  |   text-align: right; | ||||||
|  |   font-size: 15px; | ||||||
|  |   color: #000000; | ||||||
|  | } | ||||||
|  | .weatherCards { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: column; | ||||||
|  |   justify-content: space-around; | ||||||
|  |   font-size: 15px; | ||||||
|  |   color: #999999; | ||||||
|  |   text-align: center; | ||||||
|  |   height: 120px; | ||||||
|  |   width: 70px; | ||||||
|  |   background: linear-gradient(to left bottom, #cfffec 0%, /* 顶部浅青色 */ #fbfefd 70%, /* 中间渐变色 */ #ffffff 100% /* 底部稍深青色 */); | ||||||
|  |   border-radius: 12px; | ||||||
|  |   border: none; | ||||||
|  |   box-shadow: 0 4px 12px rgba(0, 150, 136, 0.15); | ||||||
|  | } | ||||||
|  | </style> | ||||||
|  | |||||||
 2090205686@qq.com
						2090205686@qq.com