<template>
|
<div class="real-time-simulation">
|
<div class="left-top">
|
<span>实时模拟</span>
|
<span class="clickable-text" @click="toggleDetails">{{
|
isCollapsed ? "展开" : "收起"
|
}}</span>
|
</div>
|
|
<el-form
|
:model="formData"
|
label-width="auto"
|
style="max-width: 600px; padding-right: 10px; box-sizing: border-box"
|
>
|
<el-collapse-transition style="margin-top: 10px">
|
<div v-show="!isCollapsed">
|
<el-form-item label="方案名称:">
|
<el-input
|
v-model="formData.name"
|
type="text"
|
placeholder="请输入"
|
></el-input>
|
</el-form-item>
|
<el-form-item label="雨量数据:">
|
<el-select
|
v-model="formData.selectedRainfall"
|
placeholder="请选择"
|
popper-class="mySelectStyle"
|
>
|
<el-option
|
v-for="item in rainfallData"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item>
|
<div class="table-container">
|
<div
|
class="table-row"
|
v-for="(item, index) in filteredTableData"
|
:key="index"
|
>
|
<input type="checkbox" v-model="item.selected" />
|
<span>{{ item.name }}</span>
|
</div>
|
</div>
|
</el-form-item>
|
</div>
|
</el-collapse-transition>
|
</el-form>
|
|
<!-- <div style="margin-top: 10px;">
|
<label>仿真参数:</label>
|
<div style="width: 100%; height: 60px; background-color: #fff;"></div>
|
</div> -->
|
<div class="buttons">
|
<el-button type="primary" @click="openSaveDialog">保存方案</el-button>
|
<el-button type="success" @click="startPlay">开始模拟</el-button>
|
<el-button type="success" @click="futurePredictions">未来预测</el-button>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, watch, defineProps, computed, inject, reactive } from "vue";
|
import { ElMessage } from "element-plus";
|
import { initeWaterPrimitiveView } from "@/utils/water";
|
import { SimAPIStore } from "@/store/simAPI";
|
import { EventBus } from "@/eventBus"; // 引入事件总线
|
|
// 获取 Store 实例
|
const simStore = SimAPIStore();
|
|
// 表单数据
|
const formData = reactive({
|
name: "方案名称",
|
selectedRainfall: "",
|
type: 2,
|
gauges: [
|
{
|
id: "xxxxxxxxxxxxxx",
|
name: "雨量计1",
|
x: 119.0,
|
y: 28.0,
|
r: 10000,
|
},
|
{
|
id: "xxxxxxxxxxxxxx",
|
name: "雨量计2",
|
x: 119.0,
|
y: 28.0,
|
r: 10000,
|
},
|
],
|
});
|
|
// 工具函数:深拷贝并设置默认选中状态
|
function deepCloneAndSetSelected(data) {
|
const newData = {};
|
for (const key in data) {
|
newData[key] = data[key].map((item) => ({ ...item, selected: true }));
|
}
|
return newData;
|
}
|
|
// 接收父组件传递的 props
|
const props = defineProps({
|
selectedArea: {
|
type: Object,
|
required: true,
|
},
|
});
|
const rainfallData = ref([]);
|
const tableData = ref({}); // 表格数据(按雨量数据分组)
|
const isCollapsed = ref(false); // 控制展开/收起状态
|
|
// 模拟不同区域的数据
|
const areaDataMap = {
|
孙胡沟: {
|
rainfallData: [
|
{ id: "1", name: "气象实时数据 - 孙胡沟" },
|
{ id: "2", name: "雨量计实时数据 - 孙胡沟" },
|
],
|
tableData: {
|
1: [
|
{ id: "001", name: "孙胡沟气象站001" },
|
{ id: "002", name: "孙胡沟气象站002" },
|
],
|
2: [
|
{ id: "003", name: "孙胡沟雨量计003" },
|
{ id: "004", name: "孙胡沟雨量计004" },
|
],
|
},
|
},
|
鱼水洞后沟: {
|
rainfallData: [
|
{ id: "1", name: "气象实时数据 - 鱼水洞后沟" },
|
{ id: "2", name: "雨量计实时数据 - 鱼水洞后沟" },
|
],
|
tableData: {
|
1: [
|
{ id: "005", name: "鱼水洞后沟气象站005" },
|
{ id: "006", name: "鱼水洞后沟气象站006" },
|
],
|
2: [
|
{ id: "007", name: "鱼水洞后沟雨量计007" },
|
{ id: "008", name: "鱼水洞后沟雨量计008" },
|
],
|
},
|
},
|
于家西沟: {
|
rainfallData: [
|
{ id: "1", name: "气象实时数据 - 于家西沟" },
|
{ id: "2", name: "雨量计实时数据 - 于家西沟" },
|
],
|
tableData: {
|
1: [
|
{ id: "009", name: "于家西沟气象站009" },
|
{ id: "010", name: "于家西沟气象站010" },
|
],
|
2: [
|
{ id: "011", name: "于家西沟雨量计011" },
|
{ id: "012", name: "于家西沟雨量计012" },
|
],
|
},
|
},
|
};
|
|
// 根据 selectedArea 更新数据
|
watch(
|
() => props.selectedArea,
|
(newArea) => {
|
console.log(newArea.label, "new");
|
if (areaDataMap[newArea.label]) {
|
rainfallData.value = areaDataMap[newArea.label].rainfallData;
|
// 使用深拷贝设置默认选中状态
|
tableData.value = deepCloneAndSetSelected(
|
areaDataMap[newArea.label].tableData
|
);
|
formData.selectedRainfall = ""; // 清空选中的雨量数据
|
} else {
|
rainfallData.value = [];
|
tableData.value = {};
|
formData.selectedRainfall = "";
|
}
|
}
|
// { immediate: true } // 立即执行一次,确保初始数据正确
|
);
|
|
// 动态计算表格数据
|
const filteredTableData = computed(() => {
|
return formData.selectedRainfall && tableData.value[formData.selectedRainfall]
|
? tableData.value[formData.selectedRainfall]
|
: [];
|
});
|
|
// 获取当前选中的雨量数据名称
|
const selectedRainfallName = computed(() => {
|
const selected = rainfallData.value.find(
|
(item) => item.id === formData.selectedRainfall
|
);
|
return selected ? selected.name : "";
|
});
|
|
// 获取当前选中的设备信息
|
const selectedDevices = computed(() => {
|
return filteredTableData.value.filter((item) => item.selected);
|
});
|
|
const resetForm = () => {
|
formData.name = "";
|
formData.selectedRainfall = "";
|
};
|
|
// 打开保存方案对话框
|
const openSaveDialog = async () => {
|
try {
|
formData.geom = props.selectedArea;
|
await simStore.addSimCheme(formData);
|
resetForm();
|
EventBus.emit("close-selectArea");
|
} catch (err) {}
|
};
|
|
// 注入模拟操作方法
|
const { startSimulate, endSimulate } = inject("simulateActions");
|
|
async function startPlay() {
|
const selectedItems = filteredTableData.value.filter((item) => item.selected);
|
if (selectedItems.length > 0) {
|
console.log(
|
"选中的项:",
|
selectedItems.map((item) => item.name)
|
);
|
} else {
|
console.log("未选中任何项");
|
}
|
console.log("当前选中的区域:", props.selectedArea);
|
// 开始模拟前需要先保存方案
|
formData.geom = props.selectedArea;
|
await simStore.addSimCheme(formData);
|
EventBus.emit("close-selectArea");
|
initeWaterPrimitiveView();
|
startSimulate();
|
}
|
|
const toggleDetails = () => {
|
isCollapsed.value = !isCollapsed.value;
|
};
|
|
const futurePredictions = () => {
|
console.log("未来预测按钮被点击");
|
};
|
</script>
|
|
<style scoped>
|
.custom-dialog {
|
z-index: 3000 !important;
|
}
|
.real-time-simulation {
|
margin-bottom: 20px;
|
}
|
|
.clickable-text {
|
margin-left: 160px;
|
cursor: pointer;
|
font-size: 14px;
|
color: #61f7d4;
|
}
|
|
.details {
|
margin-top: 10px;
|
transition: height 0.3s ease, opacity 0.3s ease;
|
overflow: hidden;
|
}
|
|
.hidden {
|
height: 0;
|
opacity: 0;
|
}
|
|
.input-group {
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
padding-right: 10px;
|
box-sizing: border-box;
|
}
|
|
.input-item {
|
display: flex;
|
align-items: center;
|
}
|
|
label {
|
text-align: left;
|
white-space: nowrap;
|
margin-right: 10px;
|
}
|
|
.el-select {
|
flex: 4;
|
text-align: left;
|
margin-bottom: 10px;
|
}
|
|
.table-container {
|
font-size: 12px;
|
height: 120px;
|
width: 90%;
|
overflow-y: auto;
|
border: 1px solid #ddd;
|
border-radius: 4px;
|
padding: 5px;
|
}
|
|
.table-row {
|
display: flex;
|
justify-content: space-between;
|
padding: 5px 0;
|
border-bottom: 1px solid #ddd;
|
}
|
|
.table-row:last-child {
|
border-bottom: none;
|
}
|
|
.table-row span {
|
flex: 1;
|
text-align: left;
|
}
|
|
.table-row input[type="checkbox"] {
|
margin-right: 10px;
|
}
|
|
.buttons {
|
margin-top: 20px;
|
display: flex;
|
justify-content: flex-end;
|
gap: 10px;
|
padding-right: 10px;
|
box-sizing: border-box;
|
}
|
|
.el-button {
|
flex: 1;
|
}
|
</style>
|