guonan
2025-04-17 e15245c624a20a3b46e428d646f5f2dd863cd1bc
完善
已修改8个文件
418 ■■■■ 文件已修改
src/api/trApi.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monifangzhen/schemeCard.vue 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/simulation.js 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Screen.vue 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/CitySim.vue 113 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/Left.vue 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/left/Simulation.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/trApi.js
@@ -3,10 +3,47 @@
// 获取雨量数据
export async function getData() {
    try {
      const response = await axios.get("/api/region/selectPage", {
    const response = await axios.get("/region/selectPage", {
      });
      console.log("Response:", response);
    // console.log("Response:", response);
    } catch (error) {
      console.error("Error fetching data:", error);
    }
  }
// 获取方案列表
export async function getSimData() {
  try {
    const res = await axios.get("/simu/selectPage");
    return res.data; // 返回实际数据(通常 res.data 才是接口返回的内容)
  } catch (error) {
    console.error("Error fetching data:", error);
    throw error; // 抛出错误,让调用方可以捕获
  }
}
// 新建仿真方案
export async function createSimData(simData) {
  try {
    const res = await axios.post("/simu/insert", simData, {
      headers: {
        "Content-Type": "application/json",
      },
    });
    return res;
  } catch (error) {
    console.error("Error creating simulation data:", error);
    throw error; // 抛出错误,让调用方可以捕获
  }
}
// 删除仿真方案
export async function deleteSimData(ids) {
  try {
    const res = await axios.delete(`/simu/deleteByIds?ids=${ids}`);
    return res.data;
  } catch (error) {
    console.error('Error deleting simulation data:', error);
    throw error;
  }
}
src/components/monifangzhen/schemeCard.vue
@@ -1,19 +1,33 @@
<template>
  <div class="listCard">
    <!-- <div>方案数量: {{ simStore.schemCard.length }}</div> -->
    <el-card v-for="(item, key) in simStore.schemCard" :key="key" :class="{ selected: selectedId === item.id }"
    @click="selectScheme(item.id)">
    <!-- 接口版本删除该代码块 -->
    <el-card
      v-for="(item, key) in simStore.schemCard"
      :key="key"
      :class="{ selected: selectedId === item.id }"
      @click="selectScheme(item.id)"
    >
      <!-- <el-card
      v-for="(item, key) in schemeList"
      :key="key"
      @click="selectScheme(item.id)"
    > -->
      <div>
        <p>方案名称 : {{ item.name }}</p>
        <p>创建时间 : {{ formatTime(item.createTime) }}</p>
        <p>
          方案状态 :
          <span style="color: aquamarine">{{ statusText[item.taskStatus] || "未知" }}</span>
          <span style="color: aquamarine">{{
            statusText[item.taskStatus] || "未知"
          }}</span>
        </p>
      </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>
@@ -29,11 +43,12 @@
</template>
<script setup>
import { ref } from "vue";
import { onMounted, ref, watch } from "vue";
import dayjs from "dayjs";
import { initeWaterPrimitiveView } from "@/utils/water";
import Message from "@/components/tools/Message.vue";
import { useSimStore } from "@/store/simulation.js";
import { ElMessage, ElMessageBox } from "element-plus";
const simStore = useSimStore();
// 选中的方案 ID
@@ -310,14 +325,70 @@
  initeWaterPrimitiveView();
  emit("start");
}
const emit = defineEmits(["start", "end"]);
const emit = defineEmits(["start", "end", "reset"]);
function endPlay() {
  emit("end");
}
// 暴露选中的 ID 给父组件
//////////////////////////////////// 暴露选中的 ID 给父组件(接口版本删除)////////////////////////////////////
defineExpose({
  getSelectedId: () => selectedId.value,
});
/////////////////////// 调用接口(使用时打开) ///////////////////////
// import { getData, getSimData, deleteSimData } from "@/api/trApi.js";
// onMounted(() => {
//   getScheme();
// });
// const props = defineProps({
//   deleteSim: Boolean, // 接收父组件传递的函数
// });
// watch(
//   () => props.deleteSim,
//   (newVal) => {
//     if (newVal) {
//       console.log(newVal);
//       deleteSim();
//       emit("reset");
//     }
//   }
// );
// const schemeList = ref([]);
// async function getScheme() {
//   try {
//     const res = await getSimData();
//     schemeList.value = res.data;
//   } catch (error) {
//     console.error("Error fetching data:", error);
//   }
// }
// const deleteSim = () => {
//   ElMessageBox.confirm("确定要删除该方案吗?", "删除方案", {
//     confirmButtonText: "OK",
//     cancelButtonText: "Cancel",
//   })
//     .then(() => {
//       deleteSimData(selectedId.value).then((res) => {
//         getScheme();
//       });
//       ElMessage({
//         type: "success",
//         message: "删除成功",
//       });
//     })
//     .catch(() => {
//       ElMessage({
//         type: "info",
//         message: "已取消删除",
//       });
//     });
// };
/////////////////////// 调用接口结束 ///////////////////////
</script>
<style lang="less" scoped>
src/store/simulation.js
@@ -1,6 +1,7 @@
// stores/ui.js
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { createSimData } from '@/api/trApi';
export const useSimStore = defineStore('ui', () => {
    // 所有UI状态
@@ -24,6 +25,7 @@
    const showLayerTree = ref(true)
    const showDangerAssess = ref(false)
    const schemCard = ref([])
    const selectTab = ref("行政区划仿真")
    // 初始化方法
    const init = () => {
@@ -43,7 +45,44 @@
        showResultAssess.value = false
        showDangerAssess.value = false
        schemCard.value = []
        selectTab.value = "行政区划仿真"
    }
    const handleClickTab = (data) => {
        selectTab.value = data
    }
    // 新建方案
    const createSimulation = async (forms) => {
        const getAreaType = (tabName) => {
            switch (tabName) {
                case '行政区划仿真':
                    return 1
                case '重点区域仿真':
                    return 2
                case '重点沟仿真':
                    return 3
                default:
                    return 0 // 自定义
            }
        }
        const params = {
            areaType: getAreaType(selectTab),
            createTime: Date.now(),
            name: forms.name,
            // 1为预测模拟,2为实时模拟,3为历史模拟
            type: 1,
            // 0为创建仿真,1为预处理,2为分析中,10为完成,20为出错
            status: 0,
        }
        try {
            await createSimData(params)
        } catch (error) {
            console.error('创建仿真失败:', error)
        }
    }
    // 方案相关
    const setSchemCard = (data) => {
        schemCard.value = data
@@ -128,16 +167,19 @@
        showResultAssess,
        showLayerTree,
        showDangerAssess,
        schemCard,
        selectTab,
        handleNavClick,
        init,
        startYHGL,
        startZHJC,
        startMNFZ,
        startMNPG,
        schemCard,
        setSchemCard,
        addSchemCard,
        removeSchemCardItem,
        updateSchemCardItem,
        handleClickTab,
        createSimulation,
    }
})
src/views/Screen.vue
@@ -18,7 +18,10 @@
                <div class="screen-widget-text">
                    {{ weather.now.text }} {{ weather.now.temperature + "℃" }}
                </div>
                <div class="screen-widget-time screen-widget-text" style="margin-left: 20px">
        <div
          class="screen-widget-time screen-widget-text"
          style="margin-left: 20px"
        >
                    {{ $dayjs().format("YYYY/MM/DD HH:mm") }}
                </div>
            </div>
@@ -35,18 +38,18 @@
</template>
<script setup>
    import { ref, onMounted, computed, defineEmits } from "vue"
    import { useRouter } from "vue-router"
    const router = useRouter()
    const bgVisible = ref(true)
    const defaultCity = ref(cityData.name)
    const emits = defineEmits("showWeatherDetail")
import { ref, onMounted, computed, defineEmits } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
const bgVisible = ref(true);
const defaultCity = ref(cityData.name);
const emits = defineEmits("showWeatherDetail");
    function init(visible) {
        bgVisible.value = visible
  bgVisible.value = visible;
    }
    const weatherIcon = computed(() => {
        return `https://cdn.sencdn.com/widget2/assets/img/chameleon/weather/${weather.value.now.code}.svg `
    })
  return `https://cdn.sencdn.com/widget2/assets/img/chameleon/weather/${weather.value.now.code}.svg `;
});
    const weather = ref({
        location: {
            id: "WKNM0GVFCUJJ",
@@ -72,12 +75,12 @@
            dew_point: "",
        },
        last_update: "2023-04-21T11:02:40+08:00",
    })
});
    const air = ref({
        city: {
            quality: "优",
        },
    })
});
    const getWeatherData = () => {
        fetch(
            "https://api.seniverse.com/v3/weather/now.json?key=Sn4df5dIxeplgBv3X&location=beijing&language=zh-Hans&unit=c",
@@ -90,14 +93,14 @@
                },
            }
        )
            .then(response => response.json())
            .then(data => {
                weather.value = data.results[0]
    .then((response) => response.json())
    .then((data) => {
      weather.value = data.results[0];
                // console.log(weather.value)
            })
    }
    });
};
    function initScene() {
        flyToHomeView()
  flyToHomeView();
        let desc = {
            func_name: "FlyTo",
            vectorType: "WGS84",
@@ -109,15 +112,22 @@
            distance: "4918164.228809",
            PlayRate: "5",
            Name: "甘肃顶视图",
        }
        ps.emitMessage(desc)
  };
  ps.emitMessage(desc);
    }
    function openWeather() {
        emits("showWeatherDetail")
  emits("showWeatherDetail");
    }
import { useSimStore } from "@/store/simulation";
import { storeToRefs } from "pinia";
const simStore = useSimStore();
const { showDangerAssess, rightRiverShow } = storeToRefs(simStore);
    function flyToHomeView() {
        router.push("/")
  rightRiverShow.value = false;
  showDangerAssess.value = false;
  router.push("/");
        const view = {
            destination: {
                x: -2355432.569004413,
@@ -129,12 +139,12 @@
                roll: 0.00031421159527500464,
                heading: 6.140424766644804,
            },
        }
        viewer.scene.camera.flyTo(view)
  };
  viewer.scene.camera.flyTo(view);
    }
    onMounted(() => {
        // getWeatherData()
    })
});
</script>
<style lang="less" scoped>
    @import url("../assets/css/screen.css");
src/views/left/CitySim.vue
@@ -2,16 +2,24 @@
  <div style="width: 100%; height: 100%">
    <div
      class="left-top"
      v-if="disForm == '行政区划仿真'"
      v-if="simStore.selectTab == '行政区划仿真'"
      style="margin-top: 0px"
    >
      行政区划仿真(30m精度)
    </div>
    <div class="left-top" v-if="disForm == '重点区域仿真'">
    <div class="left-top" v-if="simStore.selectTab == '重点区域仿真'">
      重点区域仿真(10m精度)
    </div>
    <div class="forms">
      <el-form :model="forms" label-width="auto" style="max-width: 600px">
        <el-form-item label="方案名称:">
          <el-input
            v-model="forms.name"
            style="max-width: 600px"
            placeholder="Please input"
          >
          </el-input>
        </el-form-item>
        <el-form-item label="上传参数">
          <el-upload
            v-model:file-list="forms.fileList"
@@ -28,7 +36,10 @@
            <template #append>mm/h</template>
          </el-upload>
        </el-form-item>
        <el-form-item label="行政区域:" v-if="disForm == '行政区划仿真'">
        <el-form-item
          label="行政区域:"
          v-if="simStore.selectTab == '行政区划仿真'"
        >
          <el-select
            v-model="forms.eare"
            placeholder="Select"
@@ -42,7 +53,10 @@
            />
          </el-select>
        </el-form-item>
        <el-form-item label="重点区域:" v-if="disForm == '重点区域仿真'">
        <el-form-item
          label="重点区域:"
          v-if="simStore.selectTab == '重点区域仿真'"
        >
          <el-select
            v-model="forms.eares"
            placeholder="Select"
@@ -93,7 +107,7 @@
        <el-button type="primary" @click="openSaveDialog">保存方案</el-button>
        <el-button type="success" @click="startPlay">开始模拟</el-button>
      </div>
      <!-- 保存方案对话框 -->
      <!---------------------------- 保存方案对话框(接口版本需删除) -------------------------------->
      <el-dialog
        v-model="saveDialogVisible"
        :title="dialogTitle"
@@ -129,14 +143,20 @@
import { reactive, ref, watch, inject, computed } from "vue";
import * as XLSX from "xlsx";
import Papa from "papaparse";
import { ElMessage } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { initeWaterPrimitiveView } from "@/utils/water";
import { createSimData } from "@/api/trApi";
import { useSimStore } from "@/store/simulation";
const simStore = useSimStore();
// 注入父组件提供的方法
const { startSimulate, endSimulate } = inject("simulateActions");
const saveDialogVisible = ref(false); // 控制保存方案对话框的显示状态
const saveDialogVisible = ref(false); // 控制保存方案对话框的显示状态(接口版本删除)
// 表单数据
const forms = reactive({
  name: "",
  eare: "北京市",
  eares: "孙胡沟",
  rainfall: "",
@@ -175,7 +195,9 @@
// 计算属性:获取对话框标题
const dialogTitle = computed(() => {
  return disForm.value === "行政区划仿真" ? "行政区划仿真" : "重点区域仿真";
  return simStore.selectTab === "行政区划仿真"
    ? "行政区划仿真"
    : "重点区域仿真";
});
// 计算属性:获取上传文件的名称列表
@@ -183,22 +205,21 @@
  return forms.fileList.map((file) => file.name).join(", ") || "无";
});
////////////////////////////////////// 接口版本需删除//////////////////////////////////////
// 打开保存方案对话框
const openSaveDialog = () => {
  if (
    !forms.rainfall ||
    !forms.duration ||
    !forms.intensity ||
    (disForm.value === "行政区划仿真" && !forms.eare) ||
    (disForm.value === "重点区域仿真" && !forms.eares)
    (simStore.selectTab === "行政区划仿真" && !forms.eare) ||
    (simStore.selectTab === "重点区域仿真" && !forms.eares)
  ) {
    ElMessage.warning("请先填写所有必填项");
    return;
  }
  saveDialogVisible.value = true;
};
// 关闭保存方案对话框
}
const handleClose = () => {
  saveDialogVisible.value = false;
};
@@ -207,8 +228,8 @@
const confirmSave = () => {
  console.log("保存方案成功", {
    模拟类型: dialogTitle.value,
    行政区域: disForm.value === "行政区划仿真" ? forms.eare : null,
    重点区域: disForm.value === "重点区域仿真" ? forms.eares : null,
    行政区域: simStore.selectTab === "行政区划仿真" ? forms.eare : null,
    重点区域: simStore.selectTab === "重点区域仿真" ? forms.eares : null,
    降雨量: `${forms.rainfall} mm`,
    降雨时长: `${forms.duration} h`,
    降雨强度: `${forms.intensity} mm/h`,
@@ -218,6 +239,53 @@
  saveDialogVisible.value = false;
  resetForm();
};
////////////////////////////////////// 结束删除//////////////////////////////////////
//////////////////////////////////接口版本启用//////////////////////////////////
// const isLoading = ref(false);
// // 保存方案
// const openSaveDialog = () => {
//   if (
//     !forms.rainfall ||
//     !forms.duration ||
//     !forms.intensity ||
//     (simStore.selectTab === "行政区划仿真" && !forms.eare) ||
//     (simStore.selectTab === "重点区域仿真" && !forms.eares)
//   ) {
//     ElMessage.warning("请先填写所有必填项");
//     return;
//   }
//   ElMessageBox.confirm("确定要保存当前方案吗?", dialogTitle.value, {
//     confirmButtonText: "确定",
//     cancelButtonText: "取消",
//     type: "warning",
//   })
//     .then(confirmSave)
//     .catch(() => {
//       ElMessage({
//         type: "info",
//         message: "已取消保存",
//       });
//     });
// };
// const confirmSave = async () => {
//   if (isLoading.value) {
//     ElMessage.warning("正在保存,请稍候...");
//     return; // 防止重复提交
//   }
//   isLoading.value = true; // 开始加载状态
//   try {
//     await simStore.createSimulation(forms); // 调用 Store 中的保存方法
//     ElMessage.success("保存成功");
//     saveDialogVisible.value = true; // 显示保存对话框(如果需要)
//   } catch (error) {
//     console.error("保存失败:", error);
//     ElMessage.error("保存失败,请稍后重试");
//   } finally {
//     isLoading.value = false; // 结束加载状态
//   }
// };
//////////////////////////////////接口版本启用//////////////////////////////////
// 重置表单
const resetForm = () => {
@@ -345,21 +413,6 @@
  return true;
};
const disForm = ref("");
// 定义 Props
const props = defineProps({
  clickValue: String,
});
// 监听 Props 变化
watch(
  () => props.clickValue,
  (newValue) => {
    disForm.value = newValue || "行政区划仿真";
  },
  { immediate: true, deep: true }
);
// 开始模拟
function startPlay() {
src/views/left/Left.vue
@@ -15,24 +15,20 @@
        <el-button @click="deleteSelectedScheme">删除仿真方案</el-button>
        <!-- <el-button>删除仿真方案</el-button> -->
      </div>
      <!-- <div class="mock">
        <div
          class="mock-item"
          :class="item.name == currentMock ? 'active' : ''"
          v-for="item in mockList"
          :key="item.id"
          @click="handleClick(item)"
        >
          <div class="mock-item-text">{{ item.name }}</div>
        </div>
      </div> -->
      <!-- <RiverLevel v-show="currentMock === '删除仿真方案'" />
      <listInfo
        v-show="currentMock === '新建仿真方案'"
      <!-- 接口版本删除该代码块 -->
      <schemeCard
        ref="schemeCardRef"
        @start="start"
        @end="end"
        @reset="reset"
      />
      <!-- <schemeCard
        ref="schemeCardRef"
        @start="start"
        @end="end"
        @reset="reset"
        :deleteSim="deleteSim"
      /> -->
      <schemeCard ref="schemeCardRef" @start="start" @end="end" />
    </div>
  </div>
  <div class="left" v-show="showAddIns">
@@ -52,15 +48,7 @@
// import { deviceDictList, getDictName } from "@/constant/dict.js";
import { getDeviceData } from "@/api/index";
const emits = defineEmits(["start", "end"]);
// const currentMock = ref("新建仿真方案");
// const mockList = ref([
//   {
//     name: "删除仿真方案",
//   },
//   {
//     name: "新建仿真方案",
//   },
// ]);
const list = [
  {
    alias: "孙胡沟主沟断面1",
@@ -410,9 +398,12 @@
  // entities.push(entity)
}
const schemeCardRef = ref(null);
function deleteSelectedScheme() {
  const selectedId = schemeCardRef.value.getSelectedId();
  const selectedScheme = simStore.schemCard.find(item => item.id === selectedId);
  const selectedScheme = simStore.schemCard.find(
    (item) => item.id === selectedId
  );
  if (!selectedId) {
    ElMessage.warning("请先选择一个方案!");
    return;
@@ -430,9 +421,9 @@
      simStore.removeSchemCardItem(selectedId);
      ElMessage.success(`方案 "${selectedScheme.name}" 删除成功!`);
    })
    .catch(() => {
    });
    .catch(() => {});
}
function start(form) {
  emits("start", form);
}
@@ -451,6 +442,17 @@
  });
  divPointList = [];
});
///////////////////////////删除仿真方案///////////////////////////
// const deleteSim = ref(false);
// function reset() {
//   deleteSim.value = false; // 重置标志位
// }
// function deleteSelectedScheme() {
//   deleteSim.value = true;
// }
///////////////////////////删除仿真方案///////////////////////////
</script>
<style lang="less" scoped>
.mock {
src/views/left/Simulation.vue
@@ -1,24 +1,24 @@
<template>
  <div style="height: 100%">
    <div class="left-top" style="margin-bottom: 20px;">
    <div class="left-top" style="margin-bottom: 20px">
      <span>新建仿真方案</span>
      <span class="clickable-text" @click="goBack">返回列表</span>
    </div>
    <el-tabs
      style="height: calc(100% - 40px);"
      style="height: calc(100% - 40px)"
      v-model="activeName"
      type="card"
      class="demo-tabs"
      @tab-click="handleClick"
    >
      <el-tab-pane label="行政区划仿真" name="first">
        <city-sim :clickValue="clickValue" />
        <city-sim />
      </el-tab-pane>
      <el-tab-pane label="重点区域仿真" name="second">
        <city-sim :clickValue="clickValue" />
        <city-sim />
      </el-tab-pane>
      <el-tab-pane label="重点沟仿真" name="third">
        <kg-sim :clickValue="clickValue" />
        <kg-sim />
      </el-tab-pane>
    </el-tabs>
  </div>
@@ -28,6 +28,10 @@
import { ref, defineEmits } from "vue";
import citySim from "./CitySim.vue";
import kgSim from "./KGSim.vue";
import { useSimStore } from "@/store/simulation";
const simStore = useSimStore();
// 定义返回事件
const emits = defineEmits(["back"]);
@@ -40,8 +44,7 @@
// 标签点击事件
const handleClick = (tab) => {
  clickValue.value = tab.props.label;
  console.log(clickValue.value);
  simStore.handleClickTab(tab.props.label);
};
// 返回上一级
vue.config.js
@@ -21,7 +21,7 @@
    hot: true, 
    proxy: {
      '/api': {
        target: 'http://192.168.1.106:8079',
        target: 'http://192.168.56.107:8078',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''