2025-05-19 13:38:34 +08:00
|
|
|
|
<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;
|
|
|
|
|
|
2025-05-21 14:31:53 +08:00
|
|
|
|
const today = new Date();
|
|
|
|
|
const formattedDate = today
|
|
|
|
|
.toLocaleDateString('zh-CN', {
|
|
|
|
|
year: 'numeric',
|
|
|
|
|
month: 'numeric',
|
|
|
|
|
day: 'numeric',
|
|
|
|
|
})
|
|
|
|
|
.replace(/\//g, '/'); // 确保分隔符是 /
|
|
|
|
|
|
2025-05-19 13:38:34 +08:00
|
|
|
|
// 模拟乡镇数据(根据图片中的地名)
|
|
|
|
|
const towns = ref([
|
2025-05-21 14:31:53 +08:00
|
|
|
|
{ id: 0, name: '孟定镇', coord: [99.01, 23.64], weather: '晴', temp: '28℃', icon: 'sunny' },
|
|
|
|
|
{ id: 1, name: '勐简乡', coord: [99.24, 23.79], weather: '多云', temp: '26℃', icon: 'cloudy' },
|
|
|
|
|
{ id: 2, name: '四排山乡', coord: [99.5, 23.38], weather: '小雨', temp: '24℃', icon: 'rainy' },
|
|
|
|
|
{ id: 3, name: '大兴乡', coord: [99.8, 23.76], weather: '多云', temp: '25℃', icon: 'cloudy' },
|
|
|
|
|
{ id: 4, name: '耿马镇', coord: [99.42, 23.66], weather: '多云', temp: '26℃', icon: 'cloudy' },
|
|
|
|
|
{ id: 5, name: '贺派乡', coord: [99.21, 23.4], weather: '晴', temp: '27℃', icon: 'sunny' },
|
|
|
|
|
{ id: 6, name: '芒洪乡', coord: [99.73, 23.59], weather: '阴', temp: '23℃', icon: 'overcast' },
|
|
|
|
|
{ id: 7, name: '勐永镇', coord: [99.53, 23.99], weather: '小雨', temp: '22℃', icon: 'rainy' },
|
|
|
|
|
{ id: 8, name: '勐撒镇', coord: [99.47, 23.85], weather: '晴', temp: '28℃', icon: 'sunny' },
|
2025-05-19 13:38:34 +08:00
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2025-05-21 14:31:53 +08:00
|
|
|
|
const emit = defineEmits(['changeMap']);
|
|
|
|
|
// 显示天气详情弹窗
|
|
|
|
|
const showWeatherDetail = (data) => {
|
|
|
|
|
emit('changeMap', { message: data });
|
|
|
|
|
};
|
2025-05-19 13:38:34 +08:00
|
|
|
|
|
|
|
|
|
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') {
|
|
|
|
|
// 点击乡镇标记点
|
2025-05-21 14:31:53 +08:00
|
|
|
|
showWeatherDetail(params.name);
|
2025-05-19 13:38:34 +08:00
|
|
|
|
} else if (params.componentType === 'geo') {
|
|
|
|
|
// 点击地图区域
|
2025-05-21 14:31:53 +08:00
|
|
|
|
showWeatherDetail(params.name);
|
2025-05-19 13:38:34 +08:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 注册地图
|
|
|
|
|
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) => ({
|
2025-05-21 14:31:53 +08:00
|
|
|
|
id: town.id,
|
2025-05-19 13:38:34 +08:00
|
|
|
|
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,
|
2025-05-21 14:31:53 +08:00
|
|
|
|
bottom: 0,
|
2025-05-19 13:38:34 +08:00
|
|
|
|
style: {
|
2025-05-21 14:31:53 +08:00
|
|
|
|
text: '数据更新于: ' + formattedDate,
|
2025-05-19 13:38:34 +08:00
|
|
|
|
fill: '#666',
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
chart.setOption(option);
|
|
|
|
|
|
|
|
|
|
window.addEventListener('resize', function () {
|
|
|
|
|
chart.resize();
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
</script>
|