模拟数据变动

This commit is contained in:
姚俊旭 2025-05-21 14:31:53 +08:00
parent 2da225162e
commit a60301fba5
3 changed files with 248 additions and 53 deletions

View File

@ -11,17 +11,26 @@ import { getAssetsFile } from '@/utils';
// GeoJSON // GeoJSON
const gengmaGeoJSON = json; const gengmaGeoJSON = json;
const today = new Date();
const formattedDate = today
.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
})
.replace(/\//g, '/'); // /
// //
const towns = ref([ const towns = ref([
{ name: '孟定镇', coord: [99.01, 23.64], weather: '晴', temp: '28℃', icon: 'sunny' }, { id: 0, name: '孟定镇', coord: [99.01, 23.64], weather: '晴', temp: '28℃', icon: 'sunny' },
{ name: '勐简乡', coord: [99.24, 23.79], weather: '多云', temp: '26℃', icon: 'cloudy' }, { id: 1, name: '勐简乡', coord: [99.24, 23.79], weather: '多云', temp: '26℃', icon: 'cloudy' },
{ name: '四排山乡', coord: [99.5, 23.38], weather: '小雨', temp: '24℃', icon: 'rainy' }, { id: 2, name: '四排山乡', coord: [99.5, 23.38], weather: '小雨', temp: '24℃', icon: 'rainy' },
{ name: '大兴乡', coord: [99.8, 23.76], weather: '多云', temp: '25℃', icon: 'cloudy' }, { id: 3, name: '大兴乡', coord: [99.8, 23.76], weather: '多云', temp: '25℃', icon: 'cloudy' },
{ name: '耿马镇', coord: [99.42, 23.66], weather: '多云', temp: '26℃', icon: 'cloudy' }, { id: 4, name: '耿马镇', coord: [99.42, 23.66], weather: '多云', temp: '26℃', icon: 'cloudy' },
{ name: '贺派乡', coord: [99.21, 23.4], weather: '晴', temp: '27℃', icon: 'sunny' }, { id: 5, name: '贺派乡', coord: [99.21, 23.4], weather: '晴', temp: '27℃', icon: 'sunny' },
{ name: '芒洪乡', coord: [99.73, 23.59], weather: '阴', temp: '23℃', icon: 'overcast' }, { id: 6, name: '芒洪乡', coord: [99.73, 23.59], weather: '阴', temp: '23℃', icon: 'overcast' },
{ name: '勐永镇', coord: [99.53, 23.99], weather: '小雨', temp: '22℃', icon: 'rainy' }, { id: 7, name: '勐永镇', coord: [99.53, 23.99], weather: '小雨', temp: '22℃', icon: 'rainy' },
{ name: '勐撒镇', coord: [99.47, 23.85], weather: '晴', temp: '28℃', icon: 'sunny' }, { id: 8, name: '勐撒镇', coord: [99.47, 23.85], weather: '晴', temp: '28℃', icon: 'sunny' },
]); ]);
const mapContainer = ref(null); const mapContainer = ref(null);
@ -40,6 +49,11 @@ function getWeatherIconPath(iconType) {
let path = iconMap[iconType] ? iconMap[iconType] : 'images/smartFarm/sunny.png'; let path = iconMap[iconType] ? iconMap[iconType] : 'images/smartFarm/sunny.png';
return getAssetsFile(path); return getAssetsFile(path);
} }
const emit = defineEmits(['changeMap']);
//
const showWeatherDetail = (data) => {
emit('changeMap', { message: data });
};
onMounted(() => { onMounted(() => {
// //
@ -53,19 +67,13 @@ onMounted(() => {
chart.on('click', (params) => { chart.on('click', (params) => {
if (params.componentType === 'series') { if (params.componentType === 'series') {
// //
console.log('点击乡镇:', params.name); showWeatherDetail(params.name);
showWeatherDetail(params.data);
} else if (params.componentType === 'geo') { } else if (params.componentType === 'geo') {
// //
console.log('点击地图区域:', params.name); showWeatherDetail(params.name);
} }
}); });
//
const showWeatherDetail = (data) => {
console.log(data);
};
// //
echarts.registerMap('耿马县', gengmaGeoJSON); echarts.registerMap('耿马县', gengmaGeoJSON);
@ -106,6 +114,7 @@ onMounted(() => {
coordinateSystem: 'geo', coordinateSystem: 'geo',
symbolSize: 30, symbolSize: 30,
data: towns.value.map((town) => ({ data: towns.value.map((town) => ({
id: town.id,
name: town.name, name: town.name,
value: [...town.coord, town.temp], value: [...town.coord, town.temp],
weather: town.weather, weather: town.weather,
@ -165,9 +174,9 @@ onMounted(() => {
graphic: { graphic: {
type: 'text', type: 'text',
left: 20, left: 20,
bottom: 5, bottom: 0,
style: { style: {
text: '数据更新于: 2025.01.01 08:00:00', text: '数据更新于: ' + formattedDate,
fill: '#666', fill: '#666',
fontSize: 12, fontSize: 12,
}, },

View File

@ -26,10 +26,12 @@ const towns = ref([
const mapContainer = ref(null); const mapContainer = ref(null);
// const emit = defineEmits(['changeMap2']);
// function getWeatherIconPath(iconType) { //
// return `/images/${iconType}.png`; // 使 const showDustDetail = (data) => {
// } emit('changeMap2', { message: data });
};
function getWeatherIconPath(iconType) { function getWeatherIconPath(iconType) {
const iconMap = { const iconMap = {
sunny: 'images/smartFarm/sunny.png', sunny: 'images/smartFarm/sunny.png',
@ -47,20 +49,12 @@ onMounted(() => {
// //
chart.on('click', (params) => { chart.on('click', (params) => {
if (params.componentType === 'series') { if (params.componentType === 'series') {
// showDustDetail(params.name);
console.log('点击乡镇:', params.name);
showWeatherDetail(params.data);
} else if (params.componentType === 'geo') { } else if (params.componentType === 'geo') {
// showDustDetail(params.name);
console.log('点击地图区域:', params.name);
} }
}); });
//
const showWeatherDetail = (data) => {
console.log(data);
};
// //
echarts.registerMap('耿马县', gengmaGeoJSON); echarts.registerMap('耿马县', gengmaGeoJSON);

View File

@ -6,12 +6,13 @@
<el-card shadow="hover" style="border-radius: 16px"> <el-card shadow="hover" style="border-radius: 16px">
<el-row> <el-row>
<el-col :span="10"> <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>
<el-col :span="1">&nbsp;</el-col> <el-col :span="1">&nbsp;</el-col>
<el-col :span="13"> <el-col :span="13">
<div class="location"> <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>
<div style="display: flex; justify-content: space-around"> <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"> <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="" /> <img :src="getAssetsFile('images/smartFarm/光照传感器.png')" alt="" />
光照 光照
</div> </div>
<div class="values">2000Lux</div> <div class="values">{{ dustData.light }}</div>
</div> </div>
<div class="dustData"> <div class="dustData">
<div> <div>
<img :src="getAssetsFile('images/smartFarm/排风.png')" alt="" /> <img :src="getAssetsFile('images/smartFarm/排风.png')" alt="" />
排风 排风
</div> </div>
<div class="values">15/h</div> <div class="values">{{ dustData.wind }}</div>
</div> </div>
<div class="dustData"> <div class="dustData">
<div> <div>
<img :src="getAssetsFile('images/smartFarm/蒸腾.png')" alt="" /> <img :src="getAssetsFile('images/smartFarm/蒸腾.png')" alt="" />
蒸腾 蒸腾
</div> </div>
<div class="values">2000Lux</div> <div class="values">{{ dustData.evapotranspiration }}</div>
</div> </div>
</div> </div>
<div style="display: flex"> <div style="display: flex">
@ -122,24 +123,24 @@
<img :src="getAssetsFile('images/smartFarm/土壤湿度.png')" alt="" /> <img :src="getAssetsFile('images/smartFarm/土壤湿度.png')" alt="" />
湿度 湿度
</div> </div>
<div class="values">26%</div> <div class="values">{{ dustData.wet.min }}</div>
<div class="values">34%</div> <div class="values">{{ dustData.wet.max }}</div>
</div> </div>
<div class="dustData"> <div class="dustData">
<div> <div>
<img :src="getAssetsFile('images/smartFarm/土壤温度.png')" alt="" /> <img :src="getAssetsFile('images/smartFarm/土壤温度.png')" alt="" />
温度 温度
</div> </div>
<div class="values">32</div> <div class="values">{{ dustData.temp.min }}</div>
<div class="values">28</div> <div class="values">{{ dustData.temp.max }}</div>
</div> </div>
<div class="dustData"> <div class="dustData">
<div> <div>
<img :src="getAssetsFile('images/smartFarm/空气.png')" alt="" /> <img :src="getAssetsFile('images/smartFarm/空气.png')" alt="" />
空气 空气
</div> </div>
<div class="values">300ppm</div> <div class="values">{{ dustData.air.dirt }}</div>
<div class="values">34%</div> <div class="values">{{ dustData.air.wet }}</div>
</div> </div>
</div> </div>
<div class="report"> <div class="report">
@ -155,7 +156,7 @@
</div> </div>
</div> </div>
<div style="width: 35%"> <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>
<div style="width: 35%"> <div style="width: 35%">
<div style="margin-top: 70px; display: flex; text-align: left"> <div style="margin-top: 70px; display: flex; text-align: left">
@ -164,11 +165,11 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<span style="font-size: 15px">输入</span> <span style="font-size: 15px">输入</span>
<span class="values">11</span> <span class="values">{{ dustData.pressure.input }}</span>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<span style="font-size: 15px">末端</span> <span style="font-size: 15px">末端</span>
<span class="values">2</span> <span class="values">{{ dustData.pressure.end }}</span>
</el-col> </el-col>
</el-row> </el-row>
</el-col> </el-col>
@ -177,11 +178,11 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<span style="font-size: 15px">灌溉</span> <span style="font-size: 15px">灌溉</span>
<span class="values">18</span> <span class="values">{{ dustData.flow.output }}</span>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<span style="font-size: 15px">回液</span> <span style="font-size: 15px">回液</span>
<span class="values">18</span> <span class="values">{{ dustData.flow.input }}</span>
</el-col> </el-col>
</el-row> </el-row>
</el-col> </el-col>
@ -192,11 +193,11 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<span style="font-size: 15px">PH</span> <span style="font-size: 15px">PH</span>
<span class="values">8</span> <span class="values">{{ dustData.fertilization.ph }}</span>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<span style="font-size: 15px">输入</span> <span style="font-size: 15px">输入</span>
<span class="values">18</span> <span class="values">{{ dustData.fertilization.output }}</span>
</el-col> </el-col>
</el-row> </el-row>
</el-col> </el-col>
@ -293,13 +294,13 @@
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref } from 'vue';
import Common from './components/common.vue'; import Common from './components/common.vue';
import * as echarts from 'echarts';
import MapComp from '@/views/smartFarm/components/mapComp.vue'; import MapComp from '@/views/smartFarm/components/mapComp.vue';
import { getAssetsFile } from '@/utils/index.js'; import { getAssetsFile } from '@/utils/index.js';
import MapSimple from '@/views/smartFarm/components/mapSimple.vue'; import MapSimple from '@/views/smartFarm/components/mapSimple.vue';
import ChartsFlow from '@/views/smartFarm/components/charts-flow.vue'; import ChartsFlow from '@/views/smartFarm/components/charts-flow.vue';
import Mock from 'mockjs';
/* --------------- data --------------- */ /* --------------- data --------------- */
// #region // #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({ const currentData = ref({
temp: 18, // temp: 18, //
PM2: 80, // μg/m³ PM2: 80, // μg/m³
@ -350,11 +412,141 @@ const currentData = ref({
windSpeed: 1.5, // m/s windSpeed: 1.5, // m/s
PH: 6.5, // PH: 6.5, //
}); });
//
// #endregion // #endregion
/* --------------- methods --------------- */ /* --------------- methods --------------- */
// #region // #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%, maxmin5-15%)
wet: {
min: '@natural(20, 40)' + '%',
max: function () {
return parseInt(this.min) + Mock.mock('@natural(5, 15)') + '%';
},
},
// (min:15-25, maxmin5-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 // #endregion
</script> </script>