模拟数据变动
This commit is contained in:
parent
2da225162e
commit
a60301fba5
@ -11,17 +11,26 @@ import { getAssetsFile } from '@/utils';
|
||||
// 您提供的耿马县GeoJSON数据
|
||||
const gengmaGeoJSON = json;
|
||||
|
||||
const today = new Date();
|
||||
const formattedDate = today
|
||||
.toLocaleDateString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: 'numeric',
|
||||
day: 'numeric',
|
||||
})
|
||||
.replace(/\//g, '/'); // 确保分隔符是 /
|
||||
|
||||
// 模拟乡镇数据(根据图片中的地名)
|
||||
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' },
|
||||
{ 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' },
|
||||
]);
|
||||
|
||||
const mapContainer = ref(null);
|
||||
@ -40,6 +49,11 @@ function getWeatherIconPath(iconType) {
|
||||
let path = iconMap[iconType] ? iconMap[iconType] : 'images/smartFarm/sunny.png';
|
||||
return getAssetsFile(path);
|
||||
}
|
||||
const emit = defineEmits(['changeMap']);
|
||||
// 显示天气详情弹窗
|
||||
const showWeatherDetail = (data) => {
|
||||
emit('changeMap', { message: data });
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 添加防御性检查
|
||||
@ -53,19 +67,13 @@ onMounted(() => {
|
||||
chart.on('click', (params) => {
|
||||
if (params.componentType === 'series') {
|
||||
// 点击乡镇标记点
|
||||
console.log('点击乡镇:', params.name);
|
||||
showWeatherDetail(params.data);
|
||||
showWeatherDetail(params.name);
|
||||
} else if (params.componentType === 'geo') {
|
||||
// 点击地图区域
|
||||
console.log('点击地图区域:', params.name);
|
||||
showWeatherDetail(params.name);
|
||||
}
|
||||
});
|
||||
|
||||
// 显示天气详情弹窗
|
||||
const showWeatherDetail = (data) => {
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
// 注册地图
|
||||
echarts.registerMap('耿马县', gengmaGeoJSON);
|
||||
|
||||
@ -106,6 +114,7 @@ onMounted(() => {
|
||||
coordinateSystem: 'geo',
|
||||
symbolSize: 30,
|
||||
data: towns.value.map((town) => ({
|
||||
id: town.id,
|
||||
name: town.name,
|
||||
value: [...town.coord, town.temp],
|
||||
weather: town.weather,
|
||||
@ -165,9 +174,9 @@ onMounted(() => {
|
||||
graphic: {
|
||||
type: 'text',
|
||||
left: 20,
|
||||
bottom: 5,
|
||||
bottom: 0,
|
||||
style: {
|
||||
text: '数据更新于: 2025.01.01 08:00:00',
|
||||
text: '数据更新于: ' + formattedDate,
|
||||
fill: '#666',
|
||||
fontSize: 12,
|
||||
},
|
||||
|
@ -26,10 +26,12 @@ const towns = ref([
|
||||
|
||||
const mapContainer = ref(null);
|
||||
|
||||
// 获取天气图标路径
|
||||
// function getWeatherIconPath(iconType) {
|
||||
// return `/images/${iconType}.png`; // 使用绝对路径
|
||||
// }
|
||||
const emit = defineEmits(['changeMap2']);
|
||||
// 显示天气详情弹窗
|
||||
const showDustDetail = (data) => {
|
||||
emit('changeMap2', { message: data });
|
||||
};
|
||||
|
||||
function getWeatherIconPath(iconType) {
|
||||
const iconMap = {
|
||||
sunny: 'images/smartFarm/sunny.png',
|
||||
@ -47,20 +49,12 @@ onMounted(() => {
|
||||
// 添加点击事件监听
|
||||
chart.on('click', (params) => {
|
||||
if (params.componentType === 'series') {
|
||||
// 点击乡镇标记点
|
||||
console.log('点击乡镇:', params.name);
|
||||
showWeatherDetail(params.data);
|
||||
showDustDetail(params.name);
|
||||
} else if (params.componentType === 'geo') {
|
||||
// 点击地图区域
|
||||
console.log('点击地图区域:', params.name);
|
||||
showDustDetail(params.name);
|
||||
}
|
||||
});
|
||||
|
||||
// 显示天气详情弹窗
|
||||
const showWeatherDetail = (data) => {
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
// 注册地图
|
||||
echarts.registerMap('耿马县', gengmaGeoJSON);
|
||||
|
||||
|
@ -6,12 +6,13 @@
|
||||
<el-card shadow="hover" style="border-radius: 16px">
|
||||
<el-row>
|
||||
<el-col :span="10">
|
||||
<map-comp style="height: 300px; width: 100%; border: 0"></map-comp>
|
||||
<map-comp style="height: 300px; width: 100%; border: 0" @change-map="changeMap"></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="" />
|
||||
耿马县·{{ currentPosition
|
||||
}}<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">
|
||||
@ -99,21 +100,21 @@
|
||||
<img :src="getAssetsFile('images/smartFarm/光照传感器.png')" alt="" />
|
||||
光照
|
||||
</div>
|
||||
<div class="values">2000Lux</div>
|
||||
<div class="values">{{ dustData.light }}</div>
|
||||
</div>
|
||||
<div class="dustData">
|
||||
<div>
|
||||
<img :src="getAssetsFile('images/smartFarm/排风.png')" alt="" />
|
||||
排风
|
||||
</div>
|
||||
<div class="values">15m³/h</div>
|
||||
<div class="values">{{ dustData.wind }}</div>
|
||||
</div>
|
||||
<div class="dustData">
|
||||
<div>
|
||||
<img :src="getAssetsFile('images/smartFarm/蒸腾.png')" alt="" />
|
||||
蒸腾
|
||||
</div>
|
||||
<div class="values">2000Lux</div>
|
||||
<div class="values">{{ dustData.evapotranspiration }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex">
|
||||
@ -122,24 +123,24 @@
|
||||
<img :src="getAssetsFile('images/smartFarm/土壤湿度.png')" alt="" />
|
||||
湿度
|
||||
</div>
|
||||
<div class="values">26%</div>
|
||||
<div class="values">34%</div>
|
||||
<div class="values">{{ dustData.wet.min }}</div>
|
||||
<div class="values">{{ dustData.wet.max }}</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 class="values">{{ dustData.temp.min }}</div>
|
||||
<div class="values">{{ dustData.temp.max }}</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 class="values">{{ dustData.air.dirt }}</div>
|
||||
<div class="values">{{ dustData.air.wet }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="report">
|
||||
@ -155,7 +156,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 35%">
|
||||
<map-simple style="height: 320px; width: 100%"></map-simple>
|
||||
<map-simple style="height: 320px; width: 100%" @change-map2="changeMap2"></map-simple>
|
||||
</div>
|
||||
<div style="width: 35%">
|
||||
<div style="margin-top: 70px; display: flex; text-align: left">
|
||||
@ -164,11 +165,11 @@
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<span style="font-size: 15px">输入</span>
|
||||
<span class="values">11</span>
|
||||
<span class="values">{{ dustData.pressure.input }}</span>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<span style="font-size: 15px">末端</span>
|
||||
<span class="values">2</span>
|
||||
<span class="values">{{ dustData.pressure.end }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
@ -177,11 +178,11 @@
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<span style="font-size: 15px">灌溉</span>
|
||||
<span class="values">18℃</span>
|
||||
<span class="values">{{ dustData.flow.output }}</span>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<span style="font-size: 15px">回液</span>
|
||||
<span class="values">18℃</span>
|
||||
<span class="values">{{ dustData.flow.input }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
@ -192,11 +193,11 @@
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<span style="font-size: 15px">PH</span>
|
||||
<span class="values">8</span>
|
||||
<span class="values">{{ dustData.fertilization.ph }}</span>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<span style="font-size: 15px">输入</span>
|
||||
<span class="values">18℃</span>
|
||||
<span class="values">{{ dustData.fertilization.output }}</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
@ -293,13 +294,13 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref } 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';
|
||||
import Mock from 'mockjs';
|
||||
|
||||
/* --------------- data --------------- */
|
||||
// #region
|
||||
@ -336,6 +337,67 @@ const weatherData = ref([
|
||||
},
|
||||
]);
|
||||
|
||||
const dustData = ref({
|
||||
light: '2000Lux', // 光照强度
|
||||
wind: '15m³/h', // 排风量
|
||||
evapotranspiration: '2000Lux', // 蒸腾
|
||||
wet: {
|
||||
min: '26%',
|
||||
max: '34%',
|
||||
},
|
||||
temp: {
|
||||
min: '32℃',
|
||||
max: '28℃',
|
||||
},
|
||||
air: {
|
||||
dirt: '300ppm',
|
||||
wet: '34%',
|
||||
},
|
||||
pressure: {
|
||||
input: '11',
|
||||
end: 2,
|
||||
},
|
||||
flow: {
|
||||
temp: '53',
|
||||
input: '125',
|
||||
},
|
||||
fertilization: {
|
||||
ph: 8,
|
||||
output: '18',
|
||||
},
|
||||
});
|
||||
|
||||
// 定义合法的天气状态流转规则
|
||||
const weatherStates = [
|
||||
{
|
||||
type: 'sunny',
|
||||
next: ['sunny', 'sunnyToCloudy'], // 晴天只能转晴天或晴转多云
|
||||
tempEffect: +0, // 温度影响
|
||||
},
|
||||
{
|
||||
type: 'sunnyToCloudy',
|
||||
next: ['thunderRain', 'rainy'], // 晴转多云后可能转雷雨或直接下雨
|
||||
tempEffect: +1,
|
||||
},
|
||||
{
|
||||
type: 'thunderRain',
|
||||
next: ['rainy', 'windy'], // 雷雨后继续下雨或转大风
|
||||
tempEffect: -2,
|
||||
},
|
||||
{
|
||||
type: 'rainy',
|
||||
next: ['rainy', 'windy'], // 雨天可能持续或转大风
|
||||
tempEffect: -3,
|
||||
},
|
||||
{
|
||||
type: 'windy',
|
||||
next: ['sunny'], // 大风后转晴天
|
||||
tempEffect: -4,
|
||||
},
|
||||
];
|
||||
|
||||
const currentPosition = ref('孟定镇');
|
||||
|
||||
const currentData = ref({
|
||||
temp: 18, // 当前温度
|
||||
PM2: 80, // 空气质量 μg/m³
|
||||
@ -350,11 +412,141 @@ const currentData = ref({
|
||||
windSpeed: 1.5, // 风速 m/s
|
||||
PH: 6.5, // 土壤酸碱度
|
||||
});
|
||||
// 基础环境数据模板
|
||||
|
||||
// #endregion
|
||||
|
||||
/* --------------- methods --------------- */
|
||||
// #region
|
||||
const changeMap = (params) => {
|
||||
currentPosition.value = params.message;
|
||||
const newWeatherData = generateSmartWeather(15, 6, 18);
|
||||
weatherData.value = newWeatherData;
|
||||
currentData.value = generateFarmData(18);
|
||||
};
|
||||
|
||||
const changeMap2 = (params) => {
|
||||
console.log(params.message);
|
||||
dustData.value = Mock.mock({
|
||||
// 光照强度 (500-3000 Lux)
|
||||
light: '@natural(500, 3000)' + 'Lux',
|
||||
|
||||
// 排风量 (5-30 m³/h)
|
||||
wind: '@natural(5, 30)' + 'm³/h',
|
||||
|
||||
// 蒸腾量 (1-10 mm/day)
|
||||
evapotranspiration: '@natural(1, 10)' + 'mm/day',
|
||||
|
||||
// 湿度范围 (min:20-40%, max比min高5-15%)
|
||||
wet: {
|
||||
min: '@natural(20, 40)' + '%',
|
||||
max: function () {
|
||||
return parseInt(this.min) + Mock.mock('@natural(5, 15)') + '%';
|
||||
},
|
||||
},
|
||||
|
||||
// 温度范围 (min:15-25℃, max比min高5-15℃)
|
||||
temp: {
|
||||
min: '@natural(15, 25)' + '℃',
|
||||
max: function () {
|
||||
return parseInt(this.min) + Mock.mock('@natural(5, 15)') + '℃';
|
||||
},
|
||||
},
|
||||
|
||||
// 空气质量
|
||||
air: {
|
||||
// 颗粒物浓度 (100-800 ppm)
|
||||
dirt: '@natural(100, 800)' + 'ppm',
|
||||
wet: '@natural(30, 60)%', // 先独立生成
|
||||
},
|
||||
|
||||
// 压力参数
|
||||
pressure: {
|
||||
// 输入压力 (5-15 MPa)
|
||||
input: '@natural(5, 15)',
|
||||
// 末端压力衰减 (1-5)
|
||||
end: '@natural(1, 5)',
|
||||
},
|
||||
|
||||
// 流量参数
|
||||
flow: {
|
||||
// 流体温度 (30-60 m²/h)
|
||||
temp: '@natural(30, 60)',
|
||||
// 输入流量 (50-200 m²/h)
|
||||
input: '@natural(50, 200)',
|
||||
},
|
||||
|
||||
// 施肥参数
|
||||
fertilization: {
|
||||
// pH值 (5.0-8.5)
|
||||
ph: '@float(5, 8.5, 1, 1)',
|
||||
// 输出流量 (10-50 m²/h)
|
||||
output: '@natural(10, 50)',
|
||||
},
|
||||
});
|
||||
};
|
||||
// 生成智能天气数据
|
||||
function generateSmartWeather(startTime, hours, baseTemp = 18) {
|
||||
let currentWeather = 'sunny';
|
||||
const result = [];
|
||||
|
||||
for (let i = 0; i < hours; i++) {
|
||||
// 1. 获取当前天气状态对象
|
||||
const state = weatherStates.find((s) => s.type === currentWeather);
|
||||
|
||||
// 2. 计算时间 (15:00 格式)
|
||||
const time = `${startTime + i}:00`.padStart(5, '0');
|
||||
|
||||
// 3. 计算温度(基于基础温度+天气影响+随机波动)
|
||||
const temp = baseTemp + state.tempEffect + Math.floor(Math.random() * 2);
|
||||
|
||||
// 4. 记录数据
|
||||
result.push({
|
||||
weather: currentWeather,
|
||||
time,
|
||||
temp: Math.max(temp, -5), // 确保不低于-5度
|
||||
});
|
||||
|
||||
// 5. 智能切换下一个天气状态
|
||||
currentWeather = state.next[Math.floor(Math.random() * state.next.length)];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const generateFarmData = (baseTemp = 18) => {
|
||||
// 1. 先生成核心天气数据(基于之前方案)
|
||||
const weather = Mock.mock({
|
||||
weather: '@pick(["sunny", "sunnyToCloudy", "thunderRain", "rainy", "windy"])',
|
||||
wind: '@pick(["东南风", "西南风", "东北风", "西北风"])',
|
||||
windSpeed: '@float(0.5, 5, 1, 1)',
|
||||
});
|
||||
|
||||
// 2. 根据天气计算衍生数据
|
||||
const weatherImpact = {
|
||||
sunny: { temp: +0, light: +200, wet: -10 },
|
||||
sunnyToCloudy: { temp: +1, light: -100, wet: +5 },
|
||||
thunderRain: { temp: -2, light: -300, wet: +20 },
|
||||
rainy: { temp: -3, light: -400, wet: +25 },
|
||||
windy: { temp: -4, light: +50, wet: -15 },
|
||||
}[weather.weather];
|
||||
|
||||
// 3. 生成完整数据集(带科学关联)
|
||||
return {
|
||||
temp: Mock.Random.float(baseTemp + weatherImpact.temp - 1, baseTemp + weatherImpact.temp + 1, 1, 1),
|
||||
PM2: Mock.Random.integer(weather.weather === 'windy' ? 30 : 60, weather.weather === 'rainy' ? 90 : 120),
|
||||
PM10: Mock.Random.integer(80, 150),
|
||||
bugs: Mock.Random.integer(0, weather.wet > 70 ? 5 : 2), // 高湿度虫害增加
|
||||
dustTemp: Mock.Random.float(baseTemp - 3, baseTemp + 1, 1, 1),
|
||||
wet: Mock.Random.integer(50 + weatherImpact.wet, 70 + weatherImpact.wet),
|
||||
sick: Mock.Random.integer(0, weather.weather === 'thunderRain' ? 3 : 1), // 雷雨易引发病害
|
||||
dustWet: Mock.Random.integer(60, weather.weather === 'rainy' ? 85 : 75),
|
||||
wind: weather.wind,
|
||||
light: Mock.Random.integer(Math.max(200, 500 + weatherImpact.light), Math.min(1200, 800 + weatherImpact.light)),
|
||||
windSpeed: weather.windSpeed,
|
||||
PH: Mock.Random.float(6.0, 7.5, 1, 1),
|
||||
};
|
||||
};
|
||||
// #endregion
|
||||
</script>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user