guonan
2025-06-25 2f387619c1cf834c058ac77a3fd4cabc42e5d4de
提交初版实时模拟
已修改5个文件
138 ■■■■■ 文件已修改
src/api/trApi.js 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/menu/TimeLine.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monifangzhen/schemeCard.vue 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tools/LayerTree.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/simulation.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/trApi.js
@@ -38,7 +38,7 @@
export async function getSimDataById(id) {
  try {
    const res = await instance.get(`/simu/selectPage?id=${id}`);
    return res.data;
    return res.data;
  } catch (error) {
    console.error("Error fetching data:", error);
    throw error; // 抛出错误,让调用方可以捕获
@@ -117,22 +117,44 @@
  }
}
// 通过接口去请求json,将请求的json解析获取泥石流参数
export async function fetchWaterSimulationData(serviceInfo) {
// // 通过接口去请求json,将请求的json解析获取泥石流参数
// export async function fetchWaterSimulationData(serviceInfo) {
//   try {
//     const response = await fetch(`/simu/${serviceInfo}/layer.json`); // 发起请求
//     // const response = await fetch(`/simu/c2h1dc/layer.json`); // 发起请求
//     if (!response.ok) {
//       throw new Error(`HTTP error! status: ${response.status}`);
//     }
//     const jsonData = await response.json(); // 解析 JSON 数据
//     // console.log(jsonData, "jsonjsonjsonjson");
//     return parseWaterSimulationData(jsonData); // 调用解析函数
//   } catch (error) {
//     console.error("请求或解析数据时出错:", error);
//     return null;
//   }
// }
export async function fetchWaterSimulationData(serviceInfo, timestamp = null) {
  try {
    const response = await fetch(`/simu/${serviceInfo}/layer.json`); // 发起请求
    // const response = await fetch(`/simu/c2h1dc/layer.json`); // 发起请求
    // 根据是否提供时间戳来决定文件名
    let fileName = timestamp ? timestamp : 'layer.json';
    const url = `/simu/${serviceInfo}/${fileName}`;
    const response = await fetch(url); // 发起请求
    console.log(url,'aaaaaaaaa')
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const jsonData = await response.json(); // 解析 JSON 数据
    // console.log(jsonData, "jsonjsonjsonjson");
    return parseWaterSimulationData(jsonData); // 调用解析函数
    return parseWaterSimulationData(jsonData); // 调用解析函数处理数据
  } catch (error) {
    console.error("请求或解析数据时出错:", error);
    return null;
  }
}
// 获取水位水深
export async function getFlowRate(data) {
  // console.log(data,'发送的数据!');
src/components/menu/TimeLine.vue
@@ -152,7 +152,7 @@
import { useSimStore } from "@/store/simulation";
import { storeToRefs } from "pinia";
const simStore = useSimStore();
const { selectedScheme, frameNum } = storeToRefs(simStore);
const { selectedScheme, frameNum, layerDate } = storeToRefs(simStore);
const emit = defineEmits([
  "timeUpdate",
@@ -191,7 +191,7 @@
const isWaterPrimitiveCreated = ref(false);
let playInterval = null;
let timeStepInfo = null;
let rainTotalInfo = ([]);
let rainTotalInfo = [];
const isRainEnabled = ref(false);
const rainParams = reactive({
  rainSize: 0.5,
@@ -349,10 +349,10 @@
  const rainfallList = data.rainfalls;
  console.log("最终的 rainfallList:", rainfallList);
  rainTotalInfo.value = rainfallList
  calculateTimeStep(rainTotalInfo.value)
  rainTotalInfo.value = rainfallList;
  calculateTimeStep(rainTotalInfo.value);
  // 使用示例
 timeStepInfo = calculateTimeStep(rainTotalInfo.value);
  timeStepInfo = calculateTimeStep(rainTotalInfo.value);
  // 提取 intensity 值
  rainFallValues.value = rainfallList.map((r) => r.intensity);
@@ -431,13 +431,13 @@
function calculateTimeStep(dataArray) {
  if (!dataArray || dataArray.length < 2) {
    console.warn('数据不足,无法计算时间步长');
    console.warn("数据不足,无法计算时间步长");
    return null;
  }
  // 解析时间字符串为 Date 对象
  function parseTime(timeStr) {
    return new Date(timeStr.replace(' ', 'T')); // 兼容 ISO 格式
    return new Date(timeStr.replace(" ", "T")); // 兼容 ISO 格式
  }
  const firstTime = parseTime(dataArray[0].time);
@@ -455,7 +455,9 @@
    const next = parseTime(dataArray[i + 1].time);
    const step = Math.abs(next - current) / (1000 * 60 * 60); // 毫秒 -> 小时
    if (Math.abs(step - timeStepHours) > 0.01) {
      console.warn(`在索引 ${i} 处发现了不同的时间步长: ${step.toFixed(2)} 小时`);
      console.warn(
        `在索引 ${i} 处发现了不同的时间步长: ${step.toFixed(2)} 小时`
      );
    }
  }
@@ -481,7 +483,9 @@
  const currentTimestamp = timeToTimestamp(currentData.time);
  // 已过去的时间(小时)
  const elapsedTimeInHours = parseFloat((currentTimestamp - initialTimestamp) / (1000 * 60 * 60));
  const elapsedTimeInHours = parseFloat(
    (currentTimestamp - initialTimestamp) / (1000 * 60 * 60)
  );
  console.log(`持续了 ${elapsedTimeInHours} 小时`);
@@ -516,13 +520,13 @@
  // 输出关键信息
  console.table({
    '当前时间': currentData.time,
    '累计时长 D(t) (h)': D.toFixed(2),
    '雨强阈值 IR(t) (mm/h)': IR.toFixed(2),
    '当前降雨强度 I(t) (mm/h)': intensity.toFixed(2),
    '当前阶段编号': stage,
    '最大阶段编号': maxStage,
    '是否触发泥石流': stage >= 5 ? '是' : '否'
    当前时间: currentData.time,
    "累计时长 D(t) (h)": D.toFixed(2),
    "雨强阈值 IR(t) (mm/h)": IR.toFixed(2),
    "当前降雨强度 I(t) (mm/h)": intensity.toFixed(2),
    当前阶段编号: stage,
    最大阶段编号: maxStage,
    是否触发泥石流: stage >= 5 ? "是" : "否",
  });
  // 根据最大阶段设置颜色
@@ -757,12 +761,16 @@
  try {
    // 当前方案的所有信息
    const schemeInfo = selectedScheme.value;
    const jsonFetch = ref(null);
    serviceInfo = schemeInfo.serviceName;
    if (selectedScheme.value.type == 2) {
      speedShow.value = false;
      jsonFetch.value = layerDate.value;
      // serviceInfo = layerDate.value;
    } else {
      getRainfallData();
      speedShow.value = true;
      jsonFetch.value = null;
    }
    // console.log('获取到的 serviceName:', serviceInfo);
@@ -772,7 +780,7 @@
      waterTimestamps: timestamps,
      watersMaxHeight,
      watersMinHeight,
    } = await fetchWaterSimulationData(serviceInfo);
    } = await fetchWaterSimulationData(serviceInfo, jsonFetch.value);
    console.log(
      "当前方案下的最大水位深度和最小水位深度",
      watersMaxHeight,
src/components/monifangzhen/schemeCard.vue
@@ -74,7 +74,6 @@
  selectedId.value = id;
}
function formatTime(time) {
  return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
}
@@ -93,6 +92,9 @@
function close() {
  messageShow.value = false;
}
// 实时模拟五分钟请求一次的定时器
const realTimeSimInterval = ref(null);
async function startPlay(item) {
  if (item.status === 2) {
@@ -127,7 +129,7 @@
    return;
  }
  // 调用求解器(不在实时模拟的情况下)
  // 新建方案,没有 status 和 serviceName 且 type != 2
  if (!item.status && !item.serviceName && item.type !== 2) {
    try {
      await getSimStart(item.id);
@@ -143,23 +145,21 @@
    return;
  }
  // 实时模拟
  // 处理 type == 2 的情况(实时模拟)
  if (item.type === 2) {
    try {
      // 实时模拟调用求解器会直接在接口中返回结果
      const ress = await getSimStart(item.id);
      const res = await getSimDataById(item.id);
      item.serviceName = res.data[0]?.serviceName || null;
      simStore.setSelectedScheme(item);
      getScheme();
      if (ress.code === 200) {
        initeWaterPrimitiveView();
        emit("start");
      }
    } catch (e) {
      console.error("实时模拟获取模拟数据失败:", e);
    // 清除已有定时器,防止重复启动
    if (realTimeSimInterval.value) {
      clearInterval(realTimeSimInterval.value);
    }
    // 即刻执行一次
    await executeRealTimeSimulation(item);
    // 每隔 5 分钟执行一次
    realTimeSimInterval.value = setInterval(() => {
      executeRealTimeSimulation(item);
    }, 5 * 60 * 1000); // 5分钟
    return;
  }
@@ -167,7 +167,28 @@
  simStore.setSelectedScheme(item);
}
// 封装实时模拟的异步操作
async function executeRealTimeSimulation(item) {
  try {
    const ress = await getSimStart(item.id);
    console.log(ress, "resssssssss");
    const res = await getSimDataById(item.id);
    item.serviceName = res.data[0]?.serviceName || null;
    simStore.setSelectedScheme(item);
    getScheme();
    if (ress.code === 200) {
      simStore.layerDate = ress.data;
      console.log(simStore.layerDate,'aaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbb')
      initeWaterPrimitiveView();
      emit("start");
    }
  } catch (e) {
    console.error("实时模拟获取模拟数据失败:", e);
  }
}
function handleBack(value) {
  if (value === false) {
src/components/tools/LayerTree.vue
@@ -76,7 +76,7 @@
  try {
    TerrainLayer = await earthCtrl.factory.createTerrainLayer({
      sourceType: "ctb",
      url: "http://106.120.22.26:9103/gisserver/ctsserver/sunhugoudem",
      url: "http://106.120.22.26:9103/gisserver/ctsserver/sunhugoudem84",
      requestVertexNormals: true,
    });
    treeMap.set("地形数据", TerrainLayer);
src/store/simulation.js
@@ -2,6 +2,7 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useSimStore = defineStore('simulation', () => {
    const layerDate = ref("")
    // 帧数
    const frameNum = ref(0)
    // 目录树选中
@@ -46,7 +47,6 @@
        selectedScheme.value = scheme
        rainFalls.value = JSON.parse(scheme.data).rainfalls
        intensityUnit.value = JSON.parse(scheme.data).intensityUnit
        console.log(intensityUnit.value, 'shceme')
    }
    const clearSelectedScheme = () => {
        selectedScheme.value = null
@@ -196,6 +196,7 @@
        userSelectedLayers,
        devices,
        frameNum,
        layerDate,
        // 方案相关方法
        setSchemCard,