Merge branch 'dev' of http://47.109.205.240:3000/Web/daimp-front into dev
| @ -8,6 +8,7 @@ | ||||
| <script setup> | ||||
| import { ref, reactive, onMounted, computed } from 'vue'; | ||||
| import { useRoute } from 'vue-router'; | ||||
| import * as echarts from 'echarts'; | ||||
| import geoJsonData from './china.json'; // 根据实际情况调整路径; | ||||
| const route = useRoute(); | ||||
| const props = defineProps({ | ||||
| @ -26,6 +27,33 @@ const chinaGeoCoordMap = ref({ | ||||
|   香港: [114.133834, 22.381374], | ||||
|   四川: [104.063707, 30.658753], | ||||
|   河北: [114.511072, 38.054693], | ||||
|   北京: [116.46, 39.92], | ||||
|   浙江: [120.19, 30.26], | ||||
|   山东: [117, 36.65], | ||||
|   福建: [119.3, 26.08], | ||||
|   上海: [121.48, 31.22], | ||||
|   重庆: [106.54, 29.59], | ||||
|   江西: [115.89, 28.68], | ||||
|   山西: [112.53, 37.87], | ||||
|   黑龙江: [126.63, 45.75], | ||||
|   陕西: [108.95, 34.27], | ||||
|   辽宁: [123.38, 41.8], | ||||
|   海南: [110.35, 20.02], | ||||
|   湖南: [113, 28.21], | ||||
|   宁夏: [106.27, 38.47], | ||||
|   湖北: [114.31, 30.52], | ||||
|   内蒙古: [111.65, 40.82], | ||||
|   天津: [117.2, 39.13], | ||||
|   贵州: [106.71, 26.57], | ||||
|   甘肃: [103.73, 36.03], | ||||
|   江苏: [118.78, 32.04], | ||||
|   吉林: [125.35, 43.88], | ||||
|   河南: [113.65, 34.76], | ||||
|   青海: [101.74, 36.56], | ||||
|   安徽: [117.27, 31.86], | ||||
|   广西: [108.33, 22.84], | ||||
|   西藏: [91.11, 29.97], | ||||
|   新疆: [87.68, 43.77], | ||||
| }); | ||||
| const chinaDatas = ref([ | ||||
|   [{ name: '云南', value: 382 }], | ||||
| @ -33,7 +61,35 @@ const chinaDatas = ref([ | ||||
|   [{ name: '香港', value: 9256 }], | ||||
|   [{ name: '四川', value: 1256 }], | ||||
|   [{ name: '河北', value: 382 }], | ||||
|   [{ name: '北京', value: 88 }], | ||||
|   [{ name: '浙江', value: 87 }], | ||||
|   [{ name: '山东', value: 87 }], | ||||
|   [{ name: '福建', value: 87 }], | ||||
|   [{ name: '上海', value: 87 }], | ||||
|   [{ name: '重庆', value: 87 }], | ||||
|   [{ name: '江西', value: 86 }], | ||||
|   [{ name: '山西', value: 84 }], | ||||
|   [{ name: '黑龙江', value: 83 }], | ||||
|   [{ name: '陕西', value: 83 }], | ||||
|   [{ name: '辽宁', value: 82 }], | ||||
|   [{ name: '海南', value: 82 }], | ||||
|   [{ name: '湖南', value: 82 }], | ||||
|   [{ name: '宁夏', value: 82 }], | ||||
|   [{ name: '湖北', value: 81 }], | ||||
|   [{ name: '内蒙古', value: 81 }], | ||||
|   [{ name: '天津', value: 80 }], | ||||
|   [{ name: '贵州', value: 80 }], | ||||
|   [{ name: '甘肃', value: 80 }], | ||||
|   [{ name: '江苏', value: 80 }], | ||||
|   [{ name: '吉林', value: 80 }], | ||||
|   [{ name: '河南', value: 79 }], | ||||
|   [{ name: '青海', value: 79 }], | ||||
|   [{ name: '广西', value: 78 }], | ||||
|   [{ name: '安徽', value: 77 }], | ||||
|   [{ name: '新疆', value: 76 }], | ||||
|   [{ name: '西藏', value: 76 }], | ||||
| ]); | ||||
| // 设置扩散中心 | ||||
| const convertData = (data) => { | ||||
|   var res = []; | ||||
|   for (var i = 0; i < data.length; i++) { | ||||
| @ -73,6 +129,10 @@ const getSeries = () => { | ||||
|             width: 1, //尾迹线条宽度 | ||||
|             opacity: 1, //尾迹线条透明度 | ||||
|             curveness: 0.3, //尾迹线条曲直度 | ||||
|             color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ | ||||
|               { offset: 0, color: '#0096FF' }, | ||||
|               { offset: 1, color: '#00FF00' }, | ||||
|             ]), | ||||
|           }, | ||||
|         }, | ||||
|         data: convertData(item[1]), | ||||
| @ -180,7 +240,8 @@ const chartsData = reactive({ | ||||
|     }, | ||||
|     tooltip: { | ||||
|       trigger: 'item', | ||||
|       backgroundColor: 'rgba(18, 55, 85, 0.8);', | ||||
|       className: 'custom-tooltip-container', // 自定义父容器类名 | ||||
|       backgroundColor: 'rgba(0,0,0,0.5)', | ||||
|       borderColor: '#35d0c0', | ||||
|       showDelay: 0, | ||||
|       hideDelay: 0, | ||||
| @ -189,6 +250,7 @@ const chartsData = reactive({ | ||||
|       extraCssText: 'z-index:100', | ||||
|       formatter: function (params, ticket, callback) { | ||||
|         let val = 0; | ||||
|         let str = `<div class="custom-echarts-tips"></div>`; | ||||
|         if (typeof params.value == 'number') { | ||||
|           val = params.value; | ||||
|         } else { | ||||
| @ -197,7 +259,7 @@ const chartsData = reactive({ | ||||
|         //根据业务自己拓展要显示的内容 | ||||
|         var res = ''; | ||||
|         var name = params.name; | ||||
|         res = "<span style='color:#fff;'>" + name + '</span><br/>数据:' + val; | ||||
|         res = `<span style='color:#fff;'> ${name}<br/>数据:${val}</span>`; | ||||
|         return res; | ||||
|       }, | ||||
|     }, | ||||
| @ -211,15 +273,27 @@ const chartsData = reactive({ | ||||
|           show: false, | ||||
|         }, | ||||
|       }, | ||||
|       roam: true, //是否允许缩放 | ||||
|       roam: false, //是否允许缩放 | ||||
|       itemStyle: { | ||||
|         normal: { | ||||
|           color: 'rgba(75,255,180,0.3)', //地图背景色 | ||||
|           color: 'rgba(75,255,180,0.5)', //地图背景色 | ||||
|           borderColor: '#4bffb4', //省市边界线00fcff 516a89 | ||||
|           borderWidth: 1, | ||||
|           areaColor: { | ||||
|             type: 'radial', // 径向渐变 | ||||
|             x: 0.5, | ||||
|             y: 0.5, | ||||
|             r: 0.8, | ||||
|             colorStops: [ | ||||
|               { offset: 0, color: 'rgba(17,217,245,0.2)' }, | ||||
|               { offset: 1, color: 'rgba(10,209,231,0.6)' }, | ||||
|             ], | ||||
|           }, | ||||
|           shadowColor: '#182f68', | ||||
|           shadowOffsetY: 2, | ||||
|         }, | ||||
|         emphasis: { | ||||
|           color: 'rgba(75,255,180,0.5)', //悬浮背景 | ||||
|           color: 'rgba(10,209,231,0.6)', //悬浮背景 | ||||
|           borderWidth: 2, | ||||
|         }, | ||||
|       }, | ||||
|  | ||||
							
								
								
									
										1
									
								
								sub-operation-service/.yarnrc.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1 @@ | ||||
| nodeLinker: node-modules | ||||
							
								
								
									
										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 | ||||
|  * @Date: 2023-06-20 14:29:45 | ||||
|  * @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> | ||||
|   <div class="ecommerce-common-warp"> | ||||
|     <div class="ecommerce-common-content"> | ||||
|   <div class="smartFarm-common-warp"> | ||||
|     <div class="smartFarm-common-content"> | ||||
|       <div class="left-menu"> | ||||
|         <slot v-if="$slots.left" name="left"></slot> | ||||
|         <template v-else> | ||||
|           <leftMenu :current-name="currentName"></leftMenu> | ||||
|           <left-menu :menus="menus"></left-menu> | ||||
|         </template> | ||||
|       </div> | ||||
|       <div class="common-content"> | ||||
| @ -21,13 +21,48 @@ import leftMenu from './leftMenu.vue'; | ||||
| const props = defineProps({ | ||||
|   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> | ||||
| <style lang="scss" scoped> | ||||
| .ecommerce-common-warp { | ||||
| .smartFarm-common-warp { | ||||
|   width: 100%; | ||||
|   height: calc(100vh - 230px); | ||||
|   text-align: center; | ||||
|   .ecommerce-common-content { | ||||
|   .smartFarm-common-content { | ||||
|     width: $width-main; | ||||
|     margin: auto; | ||||
|     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> | ||||
|     <common> | ||||
|       <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> | ||||
|     </common> | ||||
|   </section> | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref } from 'vue'; | ||||
| import { ref, onMounted, onBeforeUnmount } from '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 --------------- */ | ||||
| // #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 | ||||
| 
 | ||||
| /* --------------- methods --------------- */ | ||||
| // #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 | ||||
| </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> | ||||
|       <template #main> | ||||
|         <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> | ||||
|       </template> | ||||
|     </common> | ||||
| @ -11,12 +293,63 @@ | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref } from 'vue'; | ||||
| import { ref, onMounted } from '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 --------------- */ | ||||
| // #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 | ||||
| 
 | ||||
| /* --------------- methods --------------- */ | ||||
| @ -25,4 +358,121 @@ import Common from './components/common.vue'; | ||||
| // #endregion | ||||
| </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> | ||||
|  | ||||