guonan
2025-05-13 75134e86655dedcb2ad574146dadaad1a24f6f01
修改很多很多很多
已添加1个文件
已修改11个文件
1069 ■■■■■ 文件已修改
src/api/hpApi.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monifangzhen/schemeCard.vue 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tools/LayerTree.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/simAPI.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/simulation.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/CitySim.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/KGSimOption/HistorySimulation.vue 311 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/KGSimOption/PredictiveSimulation.vue 70 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/KGSimOption/RealTimeSimulation copy.vue 341 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/KGSimOption/RealTimeSimulation.vue 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mnfz.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/hpApi.js
@@ -4,7 +4,7 @@
export async function fetchToken() {
  try {
    const response = await axios.post("/hp/auth/getToken", {
      username: "yxxx",
      username: "yunweiyonghu",
      password: "c2d6bba7f0a67701a97550684e39fa5f",
      systemName: "RS_SYSTEM",
    });
src/components/monifangzhen/schemeCard.vue
@@ -1,8 +1,13 @@
<template>
  <div class="listCard">
    <!-- <div>方案数量: {{ simStore.schemCard.length }}</div> -->
    <el-card v-if="!schemeInfoShow" v-for="(item, key) in schemeList" :key="key"
      :class="{ selected: selectedId === item.id }" @click="selectScheme(item.id)">
    <el-card
      v-if="!schemeInfoShow"
      v-for="(item, key) in schemeList"
      :key="key"
      :class="{ selected: selectedId === item.id }"
      @click="selectScheme(item.id)"
    >
      <div>
        <p>方案名称 : {{ item.name }}</p>
        <p>创建时间 : {{ formatTime(item.createTime) }}</p>
@@ -15,15 +20,26 @@
      </div>
      <div class="cardMenu">
        <div style="float: right; margin-top: 3px">
          <el-button size="small" @click="setSchemClick(item)">方案详情</el-button>
          <el-button size="small" @click="setSchemClick(item)"
            >方案详情</el-button
          >
          <el-button size="small" @click="startPlay(item)">进入模拟</el-button>
          <!--  :disabled="item.taskStatus !== 2" -->
        </div>
      </div>
    </el-card>
    <schemeInfo v-if="schemeInfoShow" :selectedScheme="currentScheme" @back="handleBack" />
    <schemeInfo
      v-if="schemeInfoShow"
      :selectedScheme="currentScheme"
      @back="handleBack"
    />
  </div>
  <Message @close="close" class="mess" v-show="messageShow" :mesData="mesData" />
  <Message
    @close="close"
    class="mess"
    v-show="messageShow"
    :mesData="mesData"
  />
</template>
<script setup>
@@ -73,7 +89,7 @@
  //   alert("当前方案尚未完成,无法进入模拟!");
  //   return;
  // }
  simStore.setSelectedScheme(item)
  simStore.setSelectedScheme(item);
  currentScheme.value = item;
  schemeInfoShow.value = true;
@@ -96,7 +112,6 @@
// æ³¨å†Œäº‹ä»¶ç›‘听器
EventBus.on("hide-schemeInfo", handleHideSchemeInfo);
/////////////////////// è°ƒç”¨æŽ¥å£ï¼ˆä½¿ç”¨æ—¶æ‰“开) ///////////////////////
import { getRegionData, getSimData, deleteSimData } from "@/api/trApi.js";
@@ -150,17 +165,15 @@
    });
    return;
  }
  const selectedScheme = schemeList.value.find((item) => item.id === selectedId.value);
  const selectedScheme = schemeList.value.find(
    (item) => item.id === selectedId.value
  );
  const schemeName = selectedScheme ? selectedScheme.name : "未知方案";
  ElMessageBox.confirm(
    `确定要删除方案 "${schemeName}" å—?`,
    "删除方案",
    {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
    }
  )
  ElMessageBox.confirm(`确定要删除方案 "${schemeName}" å—?`, "删除方案", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(() => {
      deleteSimData(selectedId.value).then((res) => {
        getScheme();
@@ -170,8 +183,7 @@
        message: `方案 "${schemeName}" åˆ é™¤æˆåŠŸ`,
      });
    })
    .catch(() => {
    });
    .catch(() => {});
};
/////////////////////// è°ƒç”¨æŽ¥å£ç»“束 ///////////////////////
onUnmounted(() => {
src/components/tools/LayerTree.vue
@@ -384,6 +384,7 @@
</script>
<style lang="less" scoped>
@import url("../../assets/css/infobox.css");
.layer-tree {
  background: url("@/assets/img/tools/plotting_new.png");
  width: 200px;
src/store/simAPI.js
@@ -94,6 +94,7 @@
    // ä¿å­˜æ–¹æ¡ˆå¼¹çª—
    const addSimCheme = async (forms) => {
        // è¡¨å•验证
        if (!validateForm(forms)) {
            throw new Error('表单验证未通过'); // æŠ›å‡ºé”™è¯¯ï¼Œé˜»æ­¢ç»§ç»­æ‰§è¡Œ
        }
@@ -117,6 +118,7 @@
    }
    return {
        selectTab,
        isLoading,
src/store/simulation.js
@@ -27,8 +27,11 @@
    const schemCard = ref([])
    const backToHome = ref(false)
    const selectedScheme = ref(null)
    const rainFalls = ref()
    const setSelectedScheme = (scheme) => {
        selectedScheme.value = scheme
        rainFalls.value = JSON.parse(scheme.data).rainfalls
        console.log(rainFalls.value, 'shceme')
    }
    const clearSelectedScheme = () => {
        selectedScheme.value = null
@@ -141,6 +144,7 @@
        showDangerAssess,
        schemCard,
        backToHome,
        rainFalls,
        // æ–¹æ¡ˆç›¸å…³æ–¹æ³•
        setSchemCard,
src/views/left/CitySim.vue
@@ -11,7 +11,12 @@
      é‡ç‚¹åŒºåŸŸä»¿çœŸï¼ˆ10m精度)
    </div>
    <div class="forms">
      <el-form :model="forms" label-width="auto" style="max-width: 600px">
      <el-form
        :rules="rules"
        :model="forms"
        label-width="auto"
        style="max-width: 600px"
      >
        <el-form-item label="方案名称:">
          <el-input
            v-model="forms.name"
@@ -466,7 +471,10 @@
};
// å¼€å§‹æ¨¡æ‹Ÿ
function startPlay() {
async function startPlay() {
  // å¼€å§‹æ¨¡æ‹Ÿå‰éœ€è¦å…ˆä¿å­˜æ–¹æ¡ˆ
  await simStore.addSimCheme(forms);
  EventBus.emit("close-selectArea");
  initeWaterPrimitiveView();
  startSimulate();
}
src/views/left/KGSimOption/HistorySimulation.vue
@@ -1,17 +1,22 @@
<template>
  <div class="history-simulation">
    <div class="left-top">
      <span>历史模拟</span>
      <span class="clickable-text" @click="toggleDetails">{{
        isCollapsed ? "展开" : "收起"
      }}</span>
    </div>
    <div class="details" :class="{ hidden: isCollapsed }">
      <div class="input-group">
        <div class="input-item">
          <label>历史雨情:</label>
  <div class="left-top">
    <span>历史模拟</span>
    <span class="clickable-text" @click="toggleDetails">{{
      isCollapsed ? "展开" : "收起"
    }}</span>
  </div>
  <el-form
    ref="historySimForm"
    class="history-simulation"
    :model="formData"
    label-width="auto"
    style="max-width: 600px"
  >
    <el-collapse-transition style="margin-top: 10px">
      <div v-show="!isCollapsed">
        <el-form-item label="历史雨情:" prop="history">
          <el-select
            v-model="rainfallHistory"
            v-model="formData.history"
            placeholder="请选择"
            popper-class="mySelectStyle"
          >
@@ -20,118 +25,77 @@
              :key="item.id"
              :label="item.name"
              :value="item.name"
            ></el-option>
            />
          </el-select>
        </div>
      </div>
      <div class="input-group">
        <div class="input-item">
          <label>方案名称:</label>
        </el-form-item>
        <el-form-item label="方案名称:" prop="name">
          <el-input v-model="formData.name" type="text" placeholder="请输入" />
        </el-form-item>
        <el-form-item label="降雨总量:" prop="rainfall">
          <el-input
            v-model="schemeName"
            type="text"
            placeholder="请输入"
          ></el-input>
        </div>
        <div class="input-item">
          <label>降雨总量:</label>
          <el-input
            v-model="totalRainfall"
            v-model="formData.rainfall"
            type="number"
            placeholder="请输入"
          ></el-input>
          <span>mm</span>
        </div>
        <div class="input-item">
          <label>降雨强度:</label>
          >
            <template #append>mm</template>
          </el-input>
        </el-form-item>
        <el-form-item label="降雨强度:" prop="intensity">
          <el-input
            v-model="rainfallIntensity"
            v-model="formData.intensity"
            type="number"
            placeholder="请输入"
          ></el-input>
          <span>mm/h</span>
        </div>
        <div class="input-item">
          <label>选择时间:</label>
          >
            <template #append>mm/h</template>
          </el-input>
        </el-form-item>
        <el-form-item label="选择时间:" prop="hours">
          <el-date-picker
            v-model="hours"
            v-model="formData.hours"
            type="datetimerange"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            format="YYYY-MM-DD HH:mm:ss"
            date-format="YYYY/MM/DD ddd"
            time-format="A hh:mm:ss"
            @change="change"
            @change="handleTimeChange"
          />
          <span>h</span>
        </div>
        <div class="input-item">
          <label>降雨时长:</label>
          <el-input
            disabled
            v-model="rainfallDuration"
            type="number"
            placeholder="请输入"
          ></el-input>
          <span>h</span>
        </div>
      </div>
      <!-- <div>
        <label>仿真参数:</label>
        <div style="width: 100%; height: 60px; background-color: #fff"></div>
      </div> -->
    </div>
    <div class="buttons">
      <el-button type="primary" @click="openSaveDialog">保存方案</el-button>
      <el-button type="success" @click="startPlay">开始模拟</el-button>
    </div>
        </el-form-item>
    <!-- ä¿å­˜æ–¹æ¡ˆå¯¹è¯æ¡† -->
    <!-- <el-dialog
      v-model="saveDialogVisible"
      title="保存方案"
      width="50%"
      :before-close="handleClose"
      custom-class="custom-dialog"
    >
      <div class="dialog-content">
        <p><strong>方案名称:</strong>{{ schemeName }}</p>
        <p><strong>所选重点沟:</strong>{{ props.selectedArea }}</p>
        <p><strong>模拟类型:</strong>历史模拟</p>
        <p><strong>历史雨情:</strong>{{ selectedRainfallName }}</p>
        <p><strong>降雨总量:</strong>{{ totalRainfall }} mm</p>
        <p><strong>降雨强度:</strong>{{ rainfallIntensity }} mm/h</p>
        <p><strong>降雨时长:</strong>{{ rainfallDuration }} h</p>
        <el-form-item label="降雨时长:" prop="duration">
          <el-input
            v-model="formData.duration"
            type="number"
            placeholder="自动计算"
            disabled
          >
            <template #append>h</template>
          </el-input>
        </el-form-item>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="saveDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmSave">确定保存</el-button>
        </span>
      </template>
    </el-dialog> -->
    </el-collapse-transition>
  </el-form>
  <div class="buttons">
    <el-button type="primary" @click="openSaveDialog">保存方案</el-button>
    <el-button type="success" @click="startPlay">开始模拟</el-button>
  </div>
</template>
<script setup>
import { ref, computed, inject } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { ref, computed, reactive, inject } from "vue";
import { ElMessage } from "element-plus";
import { initeWaterPrimitiveView } from "@/utils/water";
import { useSimStore } from "@/store/simulation.js"; // å¼•å…¥ Store
import { useSimStore } from "@/store/simulation.js";
import { getRainfallData } from "@/api/hpApi.js";
import { SimAPIStore } from "@/store/simAPI";
import { EventBus } from "@/eventBus"; // å¼•入事件总线
import { EventBus } from "@/eventBus";
// èŽ·å– Store å®žä¾‹
const simStore = SimAPIStore();
// æµ‹è¯•获取雨量数据
// const getRainData = () => {
//   getRainfallData()
//     .then((a) => {
//       console.log(a, '宏图获取雨量数据');
//     })
// };
// æ³¨å…¥æ¨¡æ‹Ÿæ“ä½œæ–¹æ³•
const { startSimulate, endSimulate } = inject("simulateActions");
@@ -144,15 +108,19 @@
  },
});
// æ•°æ®ç»‘定
const rainfallHistory = ref("XXå¹´50mm降雨"); // é»˜è®¤é€‰ä¸­ç¬¬äºŒé¡¹
const totalRainfall = ref(50); // é™é›¨æ€»é‡
const schemeName = ref("方案名称"); // æ–¹æ¡ˆåç§°
const rainfallIntensity = ref(70); // é™é›¨å¼ºåº¦
const hours = ref(null);
const rainfallDuration = ref(null); // é™é›¨æ—¶é•¿
const isCollapsed = ref(false); // æŽ§åˆ¶è¯¦æƒ…的展开/收起状态
const saveDialogVisible = ref(false); // æŽ§åˆ¶ä¿å­˜æ–¹æ¡ˆå¯¹è¯æ¡†çš„æ˜¾ç¤ºçŠ¶æ€
// è¡¨å•数据
const formData = reactive({
  history: "XXå¹´50mm降雨",
  name: "方案名称",
  rainfall: 50,
  intensity: 70,
  hours: null,
  duration: null,
  type: 3,
});
// æŽ§åˆ¶è¯¦æƒ…的展开/收起状态
const isCollapsed = ref(false);
// åŽ†å²é›¨æƒ…æ•°æ®
const HistoricalRainData = [
@@ -166,7 +134,7 @@
// èŽ·å–å½“å‰é€‰ä¸­çš„åŽ†å²é›¨æƒ…åç§°
const selectedRainfallName = computed(() => {
  const selected = HistoricalRainData.find(
    (item) => item.name === rainfallHistory.value
    (item) => item.name === formData.history
  );
  return selected ? selected.name : "";
});
@@ -178,92 +146,58 @@
const { calculateHoursDifference } = inject("calculateHours");
const change = (val) => {
  rainfallDuration.value = calculateHoursDifference(val);
const handleTimeChange = (val) => {
  formData.duration = calculateHoursDifference(val);
};
const resetForm = () => {
  formData.name = "方案名称";
  formData.rainfall = 50;
  formData.intensity = 70;
  formData.hours = null;
  formData.duration = null;
};
// æ‰“开保存方案对话框
const openSaveDialog = async () => {
  const forms = {
    name: schemeName.value,
    geom: props.selectedArea,
    type: 3,
    rainfall: totalRainfall.value,
    intensity: rainfallIntensity.value,
    duration: rainfallDuration.value,
    history: rainfallHistory.value,
  };
  await simStore.addSimCheme(forms);
  EventBus.emit("close-selectArea");
};
// å…³é—­ä¿å­˜æ–¹æ¡ˆå¯¹è¯æ¡†
const handleClose = () => {
  saveDialogVisible.value = false;
};
async function openSaveDialog() {
  try {
    formData.geom = props.selectedArea;
    await simStore.addSimCheme(formData);
    resetForm();
    EventBus.emit("close-selectArea");
    ElMessage.success("方案保存成功");
  } catch (error) {
    // ElMessage.error("方案保存失败");
    console.log(error);
  }
}
// å¼€å§‹æ¨¡æ‹Ÿ
function startPlay() {
  console.log("开始模拟按钮被点击");
  console.log("当前选中的区域:", props.selectedArea);
  initeWaterPrimitiveView();
  startSimulate();
async function startPlay() {
  try {
    formData.geom = props.selectedArea;
    await simStore.addSimCheme(formData);
    EventBus.emit("close-selectArea");
    initeWaterPrimitiveView();
    startSimulate();
    ElMessage.success("模拟开始");
  } catch (error) {
    ElMessage.error("模拟启动失败");
  }
}
</script>
<style scoped>
.history-simulation {
  margin-bottom: 20px;
}
.details {
  margin-top: 10px;
  transition: height 0.3s ease, opacity 0.3s ease;
  overflow: hidden;
}
.hidden {
  height: 0;
  opacity: 0;
  padding: 10px 10px 0px 0px;
  box-sizing: border-box;
}
.buttons {
  margin-top: 20px;
  display: flex;
  gap: 10px;
  justify-content: space-evenly;
}
.input-group {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.input-item {
  display: flex;
  align-items: center;
}
label {
  text-align: left;
  white-space: nowrap;
  margin-right: 10px;
}
.el-input {
  flex: 4;
}
span {
  flex: 1;
  text-align: left;
}
.el-select {
  flex: 4;
  text-align: left;
  margin-bottom: 10px;
  justify-content: flex-end;
}
.clickable-text {
@@ -273,9 +207,24 @@
  color: #61f7d4;
}
/* è‡ªå®šä¹‰ Dialog çš„ z-index */
.custom-dialog {
  z-index: 5000 !important;
  /* ç¡®ä¿å¯¹è¯æ¡†è¦†ç›–其他元素 */
:deep(.el-form-item__content) {
  display: flex;
  align-items: center;
}
:deep(.el-input) {
  flex: 1;
}
:deep(.el-select) {
  width: 100%;
}
:deep(.el-input-group__append),
:deep(.el-input-group__prepend) {
  background-color: #084b42;
  color: #fff;
}
:deep(.el-form-item__label) {
  color: #61f7d4 !important;
}
</style>
src/views/left/KGSimOption/PredictiveSimulation.vue
@@ -43,7 +43,7 @@
      </el-form-item>
      <el-form-item label="方案名称:">
        <el-input
          v-model="forms.schemeName"
          v-model="forms.name"
          type="text"
          placeholder="请输入"
        ></el-input>
@@ -54,11 +54,7 @@
        >
      </el-form-item>
      <el-form-item label="降雨强度:">
        <el-input
          v-model="forms.rainfallIntensity"
          type="number"
          placeholder="请输入"
        >
        <el-input v-model="forms.intensity" type="number" placeholder="请输入">
          <template #append>mm/h</template></el-input
        >
      </el-form-item>
@@ -114,23 +110,12 @@
import { getRainfallData } from "@/api/hpApi";
import { EventBus } from "@/eventBus"; // å¼•入事件总线
onMounted(() => {
  getRain();
});
// èŽ·å– Store å®žä¾‹
const simStore = SimAPIStore();
// æ³¨å…¥æ¨¡æ‹Ÿæ“ä½œæ–¹æ³•
const { startSimulate, endSimulate } = inject("simulateActions");
function startPlay() {
  console.log("开始模拟按钮被点击");
  console.log("当前选中的区域:", props.selectedArea);
  initeWaterPrimitiveView();
  startSimulate();
}
// å®šä¹‰ Props
const props = defineProps({
@@ -162,13 +147,15 @@
const forms = reactive({
  rainfall: 50,
  schemeName: "",
  rainfallIntensity: 70,
  name: "",
  intensity: 70,
  duration: null,
  prediction: "降雨场次",
  mode: "正态分布",
  showRainFall: "",
  hours: null,
  type: 1,
  geom: null, // å…ˆè®¾ç½®ä¸º null æˆ–者其他默认值,
});
// é™é›¨åœºæ¬¡é€‰æ‹©
@@ -192,23 +179,42 @@
  forms.duration = calculateHoursDifference(val);
};
const resetForm = () => {
  forms.rainfall = 50;
  forms.name = "";
  forms.intensity = 70;
  forms.duration = null;
  forms.prediction = "降雨场次";
  forms.mode = "正态分布";
  forms.showRainFall = "";
  forms.hours = null;
  forms.type = 1;
  forms.geom = null; // å…ˆè®¾ç½®ä¸º null æˆ–者其他默认值,
};
// æ‰“开保存方案对话框
const openSaveDialog = async () => {
  const params = {
    name: forms.schemeName,
    geom: props.selectedArea,
    type: 1,
    rainfall: forms.rainfall,
    duration: forms.duration,
    intensity: forms.rainfallIntensity,
    mode: forms.mode,
    prediction: forms.prediction,
  };
  await simStore.addSimCheme(params);
  EventBus.emit("close-selectArea");
  // åœ¨ setup å†…部更新 geom çš„值
  try {
    forms.geom = props.selectedArea;
    await simStore.addSimCheme(forms);
    resetForm();
    EventBus.emit("close-selectArea");
  } catch (err) {}
};
// æ³¨å…¥æ¨¡æ‹Ÿæ“ä½œæ–¹æ³•
const { startSimulate, endSimulate } = inject("simulateActions");
// å¼€å§‹æ¨¡æ‹Ÿ
async function startPlay() {
  forms.geom = props.selectedArea;
  await simStore.addSimCheme(forms);
  EventBus.emit("close-selectArea");
  initeWaterPrimitiveView();
  startSimulate();
}
// æ‰“开方案
const openPlan = () => {
  // getRain();
src/views/left/KGSimOption/RealTimeSimulation copy.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,341 @@
<template>
  <div class="real-time-simulation">
    <div class="left-top">
      <span>实时模拟</span>
      <span class="clickable-text" @click="toggleDetails">{{
        isCollapsed ? "展开" : "收起"
      }}</span>
    </div>
    <div class="details" :class="{ hidden: isCollapsed }">
      <div class="input-group">
        <div class="input-item">
          <label>方案名称:</label>
          <el-input
            v-model="schemeName"
            type="text"
            placeholder="请输入"
          ></el-input>
        </div>
        <div class="input-item">
          <label>雨量数据:</label>
          <el-select
            v-model="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>
        </div>
      </div>
      <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>
      <!-- <div style="margin-top: 10px;">
        <label>仿真参数:</label>
        <div style="width: 100%; height: 60px; background-color: #fff;"></div>
      </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 } 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();
// èŽ·å– Store å®žä¾‹
const schemeName = ref("方案名称"); // æ–¹æ¡ˆåç§°
// å·¥å…·å‡½æ•°ï¼šæ·±æ‹·è´å¹¶è®¾ç½®é»˜è®¤é€‰ä¸­çŠ¶æ€
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 selectedRainfall = ref(""); // å½“前选中的雨量数据
const isCollapsed = ref(false); // æŽ§åˆ¶å±•å¼€/收起状态
const saveDialogVisible = 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) => {
    if (areaDataMap[newArea]) {
      rainfallData.value = areaDataMap[newArea].rainfallData;
      // ä½¿ç”¨æ·±æ‹·è´è®¾ç½®é»˜è®¤é€‰ä¸­çŠ¶æ€
      tableData.value = deepCloneAndSetSelected(areaDataMap[newArea].tableData);
      selectedRainfall.value = ""; // æ¸…空选中的雨量数据
    } else {
      rainfallData.value = [];
      tableData.value = {};
      selectedRainfall.value = "";
    }
  },
  { immediate: true } // ç«‹å³æ‰§è¡Œä¸€æ¬¡ï¼Œç¡®ä¿åˆå§‹æ•°æ®æ­£ç¡®
);
// åŠ¨æ€è®¡ç®—è¡¨æ ¼æ•°æ®
const filteredTableData = computed(() => {
  return selectedRainfall.value && tableData.value[selectedRainfall.value]
    ? tableData.value[selectedRainfall.value]
    : [];
});
// èŽ·å–å½“å‰é€‰ä¸­çš„é›¨é‡æ•°æ®åç§°
const selectedRainfallName = computed(() => {
  const selected = rainfallData.value.find(
    (item) => item.id === selectedRainfall.value
  );
  return selected ? selected.name : "";
});
// èŽ·å–å½“å‰é€‰ä¸­çš„è®¾å¤‡ä¿¡æ¯
const selectedDevices = computed(() => {
  return filteredTableData.value.filter((item) => item.selected);
});
// å°è£…构造表单的方法
const buildSchemeForm = () => {
  return {
    name: schemeName.value,
    geom: props.selectedArea,
    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,
      },
    ],
  };
};
// æ‰“开保存方案对话框
const openSaveDialog = async () => {
  await simStore.addSimCheme(buildSchemeForm());
  EventBus.emit("close-selectArea");
};
// å…³é—­ä¿å­˜æ–¹æ¡ˆå¯¹è¯æ¡†
const handleClose = () => {
  saveDialogVisible.value = false;
};
// æ³¨å…¥æ¨¡æ‹Ÿæ“ä½œæ–¹æ³•
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);
  console.log("当前选中的雨量数据:", selectedRainfall.value);
  // å¼€å§‹æ¨¡æ‹Ÿå‰éœ€è¦å…ˆä¿å­˜æ–¹æ¡ˆ
  await simStore.addSimCheme(buildSchemeForm());
  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;
  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;
  gap: 10px;
}
.el-button {
  flex: 1;
}
</style>
src/views/left/KGSimOption/RealTimeSimulation.vue
@@ -6,82 +6,65 @@
        isCollapsed ? "展开" : "收起"
      }}</span>
    </div>
    <div class="details" :class="{ hidden: isCollapsed }">
      <div class="input-group">
        <div class="input-item">
          <label>方案名称:</label>
          <el-input
            v-model="schemeName"
            type="text"
            placeholder="请输入"
          ></el-input>
    <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>
        <div class="input-item">
          <label>雨量数据:</label>
          <el-select
            v-model="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>
        </div>
      </div>
      <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>
      <!-- <div style="margin-top: 10px;">
      </el-collapse-transition>
    </el-form>
    <!-- <div style="margin-top: 10px;">
        <label>仿真参数:</label>
        <div style="width: 100%; height: 60px; background-color: #fff;"></div>
      </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>
    <!-- ä¿å­˜æ–¹æ¡ˆå¯¹è¯æ¡†
    <el-dialog
      v-model="saveDialogVisible"
      title="保存方案"
      width="50%"
      :before-close="handleClose"
       custom-class="custom-dialog"
    >
      <div class="dialog-content">
        <p><strong>所选重点沟:</strong>{{ props.selectedArea }}</p>
        <p><strong>模拟类型:</strong>实时模拟</p>
        <p><strong>雨量数据类型:</strong>{{ selectedRainfallName }}</p>
        <p><strong>设备信息:</strong></p>
        <ul>
          <li v-for="item in selectedDevices" :key="item.id">{{ item.name }}</li>
        </ul>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="saveDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmSave">确定保存</el-button>
        </span>
      </template>
    </el-dialog> -->
  </div>
</template>
<script setup>
import { ref, watch, defineProps, computed, inject } from "vue";
import { ref, watch, defineProps, computed, inject, reactive } from "vue";
import { ElMessage } from "element-plus";
import { initeWaterPrimitiveView } from "@/utils/water";
import { SimAPIStore } from "@/store/simAPI";
@@ -90,27 +73,28 @@
// èŽ·å– Store å®žä¾‹
const simStore = SimAPIStore();
// èŽ·å– Store å®žä¾‹
const schemeName = ref("方案名称"); // æ–¹æ¡ˆåç§°
// æ³¨å…¥æ¨¡æ‹Ÿæ“ä½œæ–¹æ³•
const { startSimulate, endSimulate } = inject("simulateActions");
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);
  console.log("当前选中的雨量数据:", selectedRainfall.value);
  initeWaterPrimitiveView();
  startSimulate();
}
// è¡¨å•数据
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) {
@@ -128,13 +112,9 @@
    required: true,
  },
});
// å­ç»„件内部状态
const rainfallData = ref([]); // é›¨é‡æ•°æ®
const rainfallData = ref([]);
const tableData = ref({}); // è¡¨æ ¼æ•°æ®ï¼ˆæŒ‰é›¨é‡æ•°æ®åˆ†ç»„)
const selectedRainfall = ref(""); // å½“前选中的雨量数据
const isCollapsed = ref(false); // æŽ§åˆ¶å±•å¼€/收起状态
const saveDialogVisible = ref(false); // æŽ§åˆ¶ä¿å­˜æ–¹æ¡ˆå¯¹è¯æ¡†æ˜¾ç¤ºçŠ¶æ€
// æ¨¡æ‹Ÿä¸åŒåŒºåŸŸçš„æ•°æ®
const areaDataMap = {
@@ -192,31 +172,34 @@
watch(
  () => props.selectedArea,
  (newArea) => {
    if (areaDataMap[newArea]) {
      rainfallData.value = areaDataMap[newArea].rainfallData;
    console.log(newArea.label, "new");
    if (areaDataMap[newArea.label]) {
      rainfallData.value = areaDataMap[newArea.label].rainfallData;
      // ä½¿ç”¨æ·±æ‹·è´è®¾ç½®é»˜è®¤é€‰ä¸­çŠ¶æ€
      tableData.value = deepCloneAndSetSelected(areaDataMap[newArea].tableData);
      selectedRainfall.value = ""; // æ¸…空选中的雨量数据
      tableData.value = deepCloneAndSetSelected(
        areaDataMap[newArea.label].tableData
      );
      formData.selectedRainfall = ""; // æ¸…空选中的雨量数据
    } else {
      rainfallData.value = [];
      tableData.value = {};
      selectedRainfall.value = "";
      formData.selectedRainfall = "";
    }
  },
  { immediate: true } // ç«‹å³æ‰§è¡Œä¸€æ¬¡ï¼Œç¡®ä¿åˆå§‹æ•°æ®æ­£ç¡®
  }
  // { immediate: true } // ç«‹å³æ‰§è¡Œä¸€æ¬¡ï¼Œç¡®ä¿åˆå§‹æ•°æ®æ­£ç¡®
);
// åŠ¨æ€è®¡ç®—è¡¨æ ¼æ•°æ®
const filteredTableData = computed(() => {
  return selectedRainfall.value && tableData.value[selectedRainfall.value]
    ? tableData.value[selectedRainfall.value]
  return formData.selectedRainfall && tableData.value[formData.selectedRainfall]
    ? tableData.value[formData.selectedRainfall]
    : [];
});
// èŽ·å–å½“å‰é€‰ä¸­çš„é›¨é‡æ•°æ®åç§°
const selectedRainfallName = computed(() => {
  const selected = rainfallData.value.find(
    (item) => item.id === selectedRainfall.value
    (item) => item.id === formData.selectedRainfall
  );
  return selected ? selected.name : "";
});
@@ -226,61 +209,42 @@
  return filteredTableData.value.filter((item) => item.selected);
});
const resetForm = () => {
  formData.name = "";
  formData.selectedRainfall = "";
};
// æ‰“开保存方案对话框
const openSaveDialog = async () => {
  const forms = {
    name: schemeName.value,
    geom: props.selectedArea,
    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,
      },
    ],
  };
  await simStore.addSimCheme(forms);
  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");
};
// å…³é—­ä¿å­˜æ–¹æ¡ˆå¯¹è¯æ¡†
const handleClose = () => {
  saveDialogVisible.value = false;
};
// // ç¡®è®¤ä¿å­˜
// const confirmSave = () => {
//   // æž„造新的方案对象
//   const newScheme = {
//     name: schemeName.value,//方案名称
//     id: Date.now().toString(), // å”¯ä¸€ ID
//     area: props.selectedArea, // åŒºåŸŸ
//     name: selectedRainfallName.value, // æ–¹æ¡ˆåç§°ï¼ˆé›¨é‡æ•°æ®ç±»åž‹ï¼‰
//     createTime: new Date().toISOString(), // åˆ›å»ºæ—¶é—´
//     taskStatus:1, // åˆå§‹çŠ¶æ€ä¸ºæœªå¼€å§‹
//     rainfallType: selectedRainfallName.value, // é›¨é‡æ•°æ®ç±»åž‹
//     devices: selectedDevices.value.map((item) => item.name), // è®¾å¤‡ä¿¡æ¯
//   };
//   // è°ƒç”¨ Store çš„æ–¹æ³•添加方案
//   simStore.addSchemCard(newScheme);
//   console.log("保存方案成功", newScheme);
//   ElMessage.success("方案已保存");
//   // å…³é—­å¯¹è¯æ¡†
//   saveDialogVisible.value = false;
// };
  initeWaterPrimitiveView();
  startSimulate();
}
const toggleDetails = () => {
  isCollapsed.value = !isCollapsed.value;
@@ -321,6 +285,8 @@
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding-right: 10px;
  box-sizing: border-box;
}
.input-item {
@@ -343,6 +309,7 @@
.table-container {
  font-size: 12px;
  height: 120px;
  width: 90%;
  overflow-y: auto;
  border: 1px solid #ddd;
  border-radius: 4px;
@@ -372,7 +339,10 @@
.buttons {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  padding-right: 10px;
  box-sizing: border-box;
}
.el-button {
src/views/mnfz.vue
@@ -295,7 +295,7 @@
    url: "/json/line.json",
    color: "#00FF00",
    width: 12.0,
    pointColor: "#73FFA7",
    pointColor: "#FFFF73",
    speed: 2,
    far: 50000,
  });
vue.config.js
@@ -30,7 +30,7 @@
        secure: false
      },
      '/hp': {
        target: 'http://192.168.56.106:9511',
        target: 'http://192.168.56.106:9522',
        changeOrigin: true,
        pathRewrite: {
          '^/hp': ''