From ca74058a77d7c9000a485502a2b53fbef5807ef5 Mon Sep 17 00:00:00 2001
From: guonan <guonan201020@163.com>
Date: 星期四, 03 七月 2025 14:08:02 +0800
Subject: [PATCH] 历史回放

---
 src/store/simulation.js                           |   23 ++
 src/api/trApi.js                                  |   22 ++
 src/components/menu/TimeLine.vue                  |  238 ++++++++++++++++++++------
 src/views/left/CitySim.vue                        |    7 
 src/components/monifangzhen/schemeCard.vue        |   86 ++++----
 src/views/left/KGSimOption/RealTimeSimulation.vue |  134 +++++++++++---
 6 files changed, 369 insertions(+), 141 deletions(-)

diff --git a/src/api/trApi.js b/src/api/trApi.js
index 4b64eb5..f826b82 100644
--- a/src/api/trApi.js
+++ b/src/api/trApi.js
@@ -81,6 +81,28 @@
     throw error;
   }
 }
+
+// 瀹炴椂妯℃嫙鐨勭粨鏋�
+export async function getSimresult(ids) {
+  try {
+    const res = await instance.get(`/simu/results?id=${ids}`);
+    return res.data;
+  } catch (error) {
+    console.error("Error deleting simulation data:", error);
+    throw error;
+  }
+}
+
+// 缁撴潫瀹炴椂妯℃嫙
+export async function stopSim(ids) {
+  try {
+    const res = await instance.get(`/simu/stop?id=${ids}`);
+    return res.data;
+  } catch (error) {
+    console.error("Error deleting simulation data:", error);
+    throw error;
+  }
+}
 // **************************************************************************************************************
 // 瑙f瀽json鑾峰彇娉ョ煶娴佸弬鏁�
 export function parseWaterSimulationData(jsonData) {
diff --git a/src/components/menu/TimeLine.vue b/src/components/menu/TimeLine.vue
index 5f1eaf0..1483981 100644
--- a/src/components/menu/TimeLine.vue
+++ b/src/components/menu/TimeLine.vue
@@ -2,20 +2,30 @@
   <div class="timeline-container">
     <div class="controls">
       <div class="control-btn" @click="skipBackward">
-        <img src="@/assets/img/timeline/left.png" class="fas fa-step-backward" />
+        <img
+          src="@/assets/img/timeline/left.png"
+          class="fas fa-step-backward"
+        />
       </div>
       <div class="control-btn play-btn" @click="togglePlay">
         <img v-show="isPlaying" src="@/assets/img/timeline/stop.png" />
         <img v-show="!isPlaying" src="@/assets/img/timeline/start.png" />
       </div>
       <div class="control-btn" @click="skipForward">
-        <img src="@/assets/img/timeline/right.png" class="fas fa-step-forward" />
+        <img
+          src="@/assets/img/timeline/right.png"
+          class="fas fa-step-forward"
+        />
       </div>
       <div class="speed-control" v-show="speedShow">
         <div @click="toggleSpeedMenu">{{ playbackRate }}X</div>
         <div class="speed-menu" v-show="showSpeedMenu">
-          <div v-for="rate in playbackRates" :key="rate" @click.capture="setPlaybackRate(rate)"
-            :class="{ active: playbackRate === rate }">
+          <div
+            v-for="rate in playbackRates"
+            :key="rate"
+            @click.capture="setPlaybackRate(rate)"
+            :class="{ active: playbackRate === rate }"
+          >
             {{ rate }}X
           </div>
         </div>
@@ -25,19 +35,33 @@
     <div class="timeline">
       <div class="dates">
         <div class="current-date">褰撳墠鎾斁鏃堕棿锛歿{ currentPlayingTime }}</div>
-        <div v-for="(date, index) in visibleDates" :key="index" class="date-label">
+        <div
+          v-for="(date, index) in visibleDates"
+          :key="index"
+          class="date-label"
+        >
           <!-- {{ formatDate(date) }} -->
         </div>
         <div>
           涓撻娓叉煋:
-          <el-switch v-model="isColorRenderEnabled" @change="handleColorRenderChange" style="margin-top: -3px"
-            :disabled="!isPlaying || !isWaterPrimitiveCreated" />
+          <el-switch
+            v-model="isColorRenderEnabled"
+            @change="handleColorRenderChange"
+            style="margin-top: -3px"
+            :disabled="!isPlaying || !isWaterPrimitiveCreated"
+          />
           <!-- active-text="寮�" inactive-text="鍏�" -->
         </div>
       </div>
       <div class="timeline-track" ref="timelineTrack" @click="seekToPosition">
-        <div class="timeline-progress" :style="{ width: progressPercentage + '%' }"></div>
-        <div class="timeline-cursor" :style="{ left: progressPercentage + '%' }"></div>
+        <div
+          class="timeline-progress"
+          :style="{ width: progressPercentage + '%' }"
+        ></div>
+        <div
+          class="timeline-cursor"
+          :style="{ left: progressPercentage + '%' }"
+        ></div>
         <div class="scale-markers">
           <div class="scale-marker" style="left: 0%"></div>
           <div class="scale-marker" style="left: 25%"></div>
@@ -46,8 +70,12 @@
           <div class="scale-marker" style="left: 100%"></div>
         </div>
         <div class="time-markers">
-          <div v-for="(time, index) in timeMarkers" :key="index" class="time-marker"
-            :style="{ left: `${index * 25}%`, transform: 'translateX(-50%)' }">
+          <div
+            v-for="(time, index) in timeMarkers"
+            :key="index"
+            class="time-marker"
+            :style="{ left: `${index * 25}%`, transform: 'translateX(-50%)' }"
+          >
             <div class="date-part">{{ time.split(" ")[0] }}</div>
             <div class="time-part">{{ time.split(" ")[1] }}</div>
           </div>
@@ -56,27 +84,38 @@
     </div>
     <div>
       <div style="display: flex">
-        <ratelevel ref="ratelevelRef" :playing-time="sendCurrentPlayingTime"
-          @finish-calculation="handleFinishCalculation" style="
+        <ratelevel
+          ref="ratelevelRef"
+          :playing-time="sendCurrentPlayingTime"
+          @finish-calculation="handleFinishCalculation"
+          style="
             margin-top: 12px;
             margin-left: 28px;
             margin-right: 10px;
             justify-content: flex-end;
-          " />
-        <crossanalysis ref="crossRef" style="
+          "
+        />
+        <crossanalysis
+          ref="crossRef"
+          style="
             margin-top: 12px;
             margin-left: 16px;
             margin-right: 20px;
             justify-content: flex-end;
-          " />
+          "
+        />
       </div>
-      <el-button @click="handleBack" style="
+      <el-button
+        @click="handleBack"
+        style="
           margin-top: 3px;
           margin-left: 28px;
           margin-right: 10px;
           width: 75%;
           height: 30%;
-        ">缁撴潫妯℃嫙</el-button>
+        "
+        >缁撴潫妯℃嫙</el-button
+      >
     </div>
   </div>
 </template>
@@ -107,9 +146,9 @@
   updateWaterColor,
 } from "@/utils/water";
 import mapUtils from "@/utils/tools.js";
-import { fetchWaterSimulationData } from "@/api/trApi.js";
+import { fetchWaterSimulationData, stopSim } from "@/api/trApi.js";
 import { EventBus } from "@/eventBus";
-import { ElMessage } from "element-plus";
+import { ElMessage, ElMessageBox } from "element-plus";
 // 鐘舵�佺鐞嗗櫒
 import { useSimStore } from "@/store/simulation";
 import { storeToRefs } from "pinia";
@@ -278,7 +317,8 @@
 const startPlayback = () => {
   clearInterval(playInterval);
 
-  if (selectedScheme.value.type === 2) {
+  // 鏂板缓鏂规涓殑瀹炴椂妯℃嫙涓嶈兘鍊嶉��
+  if (selectedScheme.value.type === 2 && simStore.rePlayList.length == 0) {
     // 绫诲瀷涓� 2锛氭瘡 5 绉掕烦鍔ㄤ竴娆�
     playInterval = setInterval(() => {
       const fiveSeconds = 5;
@@ -541,9 +581,9 @@
 // 鍏ㄥ眬鐘舵�佽褰�
 const colorState = {
   currentColor: "#F5F0E6", // 褰撳墠棰滆壊
-  currentAlpha: -0.3,      // 褰撳墠閫忔槑搴�
-  colorStages: null,       // 棰勮绠楃殑棰滆壊闃舵鏃堕棿鐐�
-  maxColorTime: null       // 璁板綍杈惧埌鏈�娣遍鑹叉椂鐨勬椂闂寸偣
+  currentAlpha: -0.3, // 褰撳墠閫忔槑搴�
+  colorStages: null, // 棰勮绠楃殑棰滆壊闃舵鏃堕棿鐐�
+  maxColorTime: null, // 璁板綍杈惧埌鏈�娣遍鑹叉椂鐨勬椂闂寸偣
 };
 
 // 棰勮绠楅鑹查樁娈垫椂闂寸偣
@@ -556,17 +596,17 @@
     { hex: "#D4B483", luminance: 184.0 }, // stage 2
     { hex: "#B78B6A", luminance: 148.4 }, // stage 3
     { hex: "#8B5A3A", luminance: 101.0 }, // stage 4
-    { hex: "#744C33", luminance: 84.5 },  // stage 5
-    { hex: "#5D3D2C", luminance: 68.1 }   // stage 6
+    { hex: "#744C33", luminance: 84.5 }, // stage 5
+    { hex: "#5D3D2C", luminance: 68.1 }, // stage 6
   ];
   const alphaStops = [
-    -0.2,   // stage 0
-    -0.3,   // stage 1
-    -0.4,   // stage 2
-    -0.5,   // stage 3
-    -0.6,   // stage 4
-    -0.7,   // stage 5
-    -0.8    // stage 6
+    -0.2, // stage 0
+    -0.3, // stage 1
+    -0.4, // stage 2
+    -0.5, // stage 3
+    -0.6, // stage 4
+    -0.7, // stage 5
+    -0.8, // stage 6
   ];
   // 绱闄嶉洦閲忛槇鍊硷紙mm锛�
   const R_THRESHOLDS = [0, 200, 240, 280, 310, 350]; // 鍏�6涓樁娈靛搴�6涓槇鍊�
@@ -579,7 +619,7 @@
     const total = rainTotalInfo.value[i].total; // 浣跨敤 total 鏇夸唬 intensity
     timeTotals.push({
       time,
-      total
+      total,
     });
   }
 
@@ -594,7 +634,7 @@
           startTime: time,
           color: COLOR_STOPS[stage].hex,
           alpha: alphaStops[stage],
-          threshold
+          threshold,
         };
         break;
       }
@@ -606,7 +646,7 @@
     startTime: 0,
     color: COLOR_STOPS[0].hex,
     alpha: alphaStops[0],
-    threshold: 0
+    threshold: 0,
   };
 
   colorState.colorStages = stages;
@@ -623,7 +663,10 @@
   // 鏌ユ壘褰撳墠鏃堕棿鐐规墍灞炵殑闃舵
   let currentStage = 0;
   for (let i = colorState.colorStages.length - 1; i >= 0; i--) {
-    if (colorState.colorStages[i] && currentTime.value >= colorState.colorStages[i].startTime) {
+    if (
+      colorState.colorStages[i] &&
+      currentTime.value >= colorState.colorStages[i].startTime
+    ) {
       currentStage = i;
       break;
     }
@@ -631,15 +674,21 @@
 
   // 璁板綍杈惧埌鏈�娣遍鑹茬殑鏃堕棿鐐�
   if (currentStage >= colorState.colorStages.length - 1) {
-    if (colorState.maxColorTime === null || currentTime.value > colorState.maxColorTime) {
+    if (
+      colorState.maxColorTime === null ||
+      currentTime.value > colorState.maxColorTime
+    ) {
       colorState.maxColorTime = currentTime.value;
     }
   }
 
   // 鍒ゆ柇鏄惁闇�瑕佸己鍒舵洿鏂伴鑹�
   const isTimeGoingBackward = currentTime.value < colorState.lastTime;
-  const isBeforeMaxColorTime = colorState.maxColorTime !== null && currentTime.value <= colorState.maxColorTime;
-  const shouldForceUpdate = isForceUpdate && (isTimeGoingBackward || isBeforeMaxColorTime);
+  const isBeforeMaxColorTime =
+    colorState.maxColorTime !== null &&
+    currentTime.value <= colorState.maxColorTime;
+  const shouldForceUpdate =
+    isForceUpdate && (isTimeGoingBackward || isBeforeMaxColorTime);
 
   // 鏇存柊棰滆壊閫昏緫
   if (shouldForceUpdate || isTimeGoingBackward) {
@@ -652,7 +701,9 @@
     const newAlpha = colorState.colorStages[currentStage].alpha;
 
     // 鍙簲鐢ㄦ洿鏆楃殑棰滆壊鍜屾洿浣庣殑閫忔槑搴�
-    if (calculateLuminance(newColor) < calculateLuminance(colorState.currentColor)) {
+    if (
+      calculateLuminance(newColor) < calculateLuminance(colorState.currentColor)
+    ) {
       colorState.currentColor = newColor;
     }
     if (newAlpha < colorState.currentAlpha) {
@@ -717,7 +768,8 @@
 
   // 鍒ゆ柇鏄惁闇�瑕佸己鍒舵洿鏂伴鑹�
   const isGoingBackward = newTime < currentTime.value;
-  const isBeforeMaxColor = colorState.maxColorTime !== null && newTime <= colorState.maxColorTime;
+  const isBeforeMaxColor =
+    colorState.maxColorTime !== null && newTime <= colorState.maxColorTime;
   const shouldForceUpdate = isGoingBackward || isBeforeMaxColor;
 
   currentTime.value = newTime;
@@ -910,16 +962,25 @@
 );
 
 const jsonFetch = ref(null);
-
+const currentReplayIndex = ref(0); // 褰撳墠鎾斁鐨剅ePlayList绱㈠紩
 // 鎻愬彇涓虹嫭绔嬪嚱鏁�
-async function initializeSimulationData(force = false) {
+async function initializeSimulationData(replayItem = null) {
   try {
     const schemeInfo = selectedScheme.value;
     serviceInfo = schemeInfo.serviceName;
 
     if (schemeInfo.type == 2) {
-      speedShow.value = false;
-      jsonFetch.value = layerDate.value;
+      if (
+        replayItem ||
+        (simStore.rePlayList && simStore.rePlayList.length != 0)
+      ) {
+        jsonFetch.value =
+          replayItem || simStore.rePlayList[currentReplayIndex.value];
+        speedShow.value = true;
+      } else {
+        jsonFetch.value = layerDate.value;
+        speedShow.value = false;
+      }
     } else {
       getRainfallData();
       speedShow.value = true;
@@ -962,11 +1023,36 @@
   }
 }
 
-// 鎸傝浇鏃惰皟鐢�
-onMounted(async () => {
-  // 鍥犱负杩欎釜鍑芥暟瀹炴椂妯℃嫙鐩戝惉涔熼渶瑕佷娇鐢紝鎵�浠ュ皝瑁呬簡涓�涓嚱鏁�
-  await initializeSimulationData();
-});
+// 鎾斁瀹屾垚鍚庣殑鍥炶皟
+function handlePlayFinished() {
+  if (selectedScheme.value.type !== 2) return;
+  finishPlay.value = false;
+  currentReplayIndex.value++;
+
+  if (currentReplayIndex.value < simStore.rePlayList.length) {
+    console.log(currentReplayIndex.value);
+
+    // 鑷姩鎾斁涓嬩竴涓�
+    initializeSimulationData(simStore.rePlayList[currentReplayIndex.value]);
+    togglePlay();
+    shouldAutoPlay.value = false;
+  } else {
+    // 鎵�鏈夐」鐩挱鏀惧畬鎴�
+    currentReplayIndex.value = 0; // 閲嶇疆绱㈠紩
+    isPlaying.value = false; // 鍋滄鎾斁
+  }
+}
+
+// 鐩戝惉鎾斁瀹屾垚浜嬩欢
+watch(
+  () => finishPlay.value,
+  (newVal) => {
+    if (newVal && selectedScheme.value.type === 2) {
+      handlePlayFinished();
+    }
+  }
+);
+
 const shouldAutoPlay = ref(false);
 // 鐩戝惉 layerDate 鍙樺寲鍚庢爣璁板噯澶囨挱鏀�
 watch(
@@ -986,6 +1072,13 @@
     shouldAutoPlay.value = false;
   }
 });
+
+// 鎸傝浇鏃惰皟鐢�
+onMounted(async () => {
+  // 鍥犱负杩欎釜鍑芥暟瀹炴椂妯℃嫙鐩戝惉涔熼渶瑕佷娇鐢紝鎵�浠ュ皝瑁呬簡涓�涓嚱鏁�
+  await initializeSimulationData();
+});
+
 // 鏍规嵁杩斿洖鏁版嵁鐨勪釜鏁板幓娓叉煋鏃堕棿杞�
 function updateTimelineRange() {
   if (waterTimestamps.value.length > 0) {
@@ -1002,28 +1095,63 @@
 });
 
 const { endSimulate } = inject("simulateActions");
-function handleBack() {
-  endSimulate();
-  // 鍋滄瀹炴椂妯℃嫙瀹氭椂鍣�
-  EventBus.emit("close-time");
 
+async function handleBack() {
+  // 瀹炴椂妯℃嫙寮圭獥纭鏄繑鍥炴柟妗堝垪琛ㄨ繕鏄仠姝㈡ā鎷�
+  if (selectedScheme.value.type === 2) {
+    try {
+      await ElMessageBox.confirm("鏂规鏈仠姝㈡椂缁撴潫妯℃嫙鍚庯紝鍚庡彴灏嗗仠姝㈣绠�", {
+        confirmButtonText: "杩斿洖鍒楄〃",
+        cancelButtonText: "缁撴潫妯℃嫙",
+        type: "warning",
+      });
+      // 鐢ㄦ埛鐐瑰嚮浜嗙‘璁わ紝杩欓噷涓嶆墽琛屼换浣曟搷浣滐紝浠呭叧闂璇濇
+    } catch (error) {
+      stopSim(selectedScheme.value.id).then((res) => {
+        if (res.code == 404) {
+          ElMessage.warning("璇ユ湇鍔″凡鍋滄");
+        } else {
+          ElMessage.success("鏈嶅姟姝e湪鍋滄涓�");
+        }
+      });
+      // return;
+    }
+  }
+  // 涓嶇type鏄笉鏄�2锛屾渶缁堥兘鎵ц缁撴潫妯℃嫙鐨勬搷浣�
+  endSimulation();
+}
+
+async function endSimulation() {
+  EventBus.emit("close-time");
+  endSimulate();
   isWaterPrimitiveCreated.value = false;
+
+  // 缁撴潫璁$畻鍜屽仠姝㈡嬀鍙�
   if (ratelevelRef.value) {
     ratelevelRef.value.endCalculation();
     ratelevelRef.value.stopPicking();
   }
+
+  // 娓呴櫎鐐�
   if (crossRef.value) {
     crossRef.value.clearPoints();
     console.log("鎵ц鍒犻櫎鐐瑰姛鑳�");
   }
+
   emit("isColorRender", false);
+
+  // 寤惰繜鍒犻櫎闆ㄩ噺鍥惧眰
   setTimeout(() => {
     mapUtils.delRain();
   }, 3000);
+
   destoryWaterPrimitive();
+
+  // 鍙戦�佷簨浠堕殣钘忕浉鍏充俊鎭�
   EventBus.emit("hide-schemeInfo");
   EventBus.emit("clear-water-depth");
   EventBus.emit("clear-water-velocity");
+
   ElMessage({ message: "妯℃嫙杩涚▼姝e湪鍏抽棴涓�...", type: "success" });
 }
 </script>
diff --git a/src/components/monifangzhen/schemeCard.vue b/src/components/monifangzhen/schemeCard.vue
index ec72b32..413b52c 100644
--- a/src/components/monifangzhen/schemeCard.vue
+++ b/src/components/monifangzhen/schemeCard.vue
@@ -29,6 +29,9 @@
             @click="startPlay(item)"
             >杩涘叆妯℃嫙</el-button
           >
+          <el-button size="small" v-show="item.type == 2" @click="rePlay(item)"
+            >鍘嗗彶鍥炴斁</el-button
+          >
           <!--  :disabled="item.status !== 2" -->
         </div>
       </div>
@@ -50,7 +53,15 @@
 
 <script setup>
 import { EventBus } from "@/eventBus"; // 寮曞叆浜嬩欢鎬荤嚎
-import { onMounted, ref, watch, defineEmits, onUnmounted } from "vue";
+import {
+  nextTick,
+  onMounted,
+  ref,
+  watch,
+  defineEmits,
+  onUnmounted,
+  inject,
+} from "vue";
 import dayjs from "dayjs";
 import { initeWaterPrimitiveView } from "@/utils/water";
 import Message from "@/components/tools/Message.vue";
@@ -61,11 +72,11 @@
 import { ElMessage, ElMessageBox } from "element-plus";
 const emit = defineEmits(["start", "end", "reset", "closeBtn"]);
 import {
-  getRegionData,
   getSimData,
   deleteSimData,
   getSimStart,
   getSimDataById,
+  getSimresult,
 } from "@/api/trApi.js";
 
 const simStore = useSimStore();
@@ -101,8 +112,9 @@
 // 瀹炴椂妯℃嫙浜斿垎閽熻姹備竴娆$殑瀹氭椂鍣�
 const realTimeSimInterval = ref(null);
 
+const { startSimulate, endSimulate } = inject("simulateActions");
+
 async function startPlay(item) {
-  console.log(item, "item");
   if (item.status === 2) {
     ElMessage.warning("褰撳墠鏂规姝e湪鍒嗘瀽涓�,鏃犳硶杩涘叆妯℃嫙锛�");
     return;
@@ -131,7 +143,7 @@
     currentScheme.value = item;
     schemeInfoShow.value = true;
     emit("closeBtn", false);
-    emit("start");
+    startSimulate();
     return;
   }
 
@@ -151,47 +163,35 @@
     return;
   }
 
-  // 澶勭悊 type == 2 鐨勬儏鍐碉紙瀹炴椂妯℃嫙锛�
-  if (item.type === 2) {
-    // 娓呴櫎宸叉湁瀹氭椂鍣紝闃叉閲嶅鍚姩
-    if (realTimeSimInterval.value) {
-      clearInterval(realTimeSimInterval.value);
-    }
-
-    // 鍗冲埢鎵ц涓�娆�
-    await executeRealTimeSimulation(item);
-
-    // 姣忛殧 5 鍒嗛挓鎵ц涓�娆�
-    realTimeSimInterval.value = setInterval(() => {
-      executeRealTimeSimulation(item);
-    }, 5 * 60 * 1000); // 5鍒嗛挓
-
-    return;
-  }
-
   // 榛樿鎯呭喌锛氭湁鏈嶅姟鍚嶇О
   simStore.setSelectedScheme(item);
 }
 
-// 灏佽瀹炴椂妯℃嫙鐨勫紓姝ユ搷浣�
-async function executeRealTimeSimulation(item) {
-  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) {
-      simStore.layerDate = ress.data;
-      initeWaterPrimitiveView();
-      emit("start");
-    }
-  } catch (e) {
-    console.error("瀹炴椂妯℃嫙鑾峰彇妯℃嫙鏁版嵁澶辫触锛�", e);
-  }
+// 瀹炴椂妯℃嫙鍘嗗彶鍥炴斁
+function rePlay(item) {
+  // 褰撳墠閫変腑鐨勬柟妗�
+  simStore.setSelectedScheme(item);
+  // 鎷縤d鍘昏姹俽esults鎺ュ彛锛屽鏋滈暱搴︿笉涓�0锛屽垯鍙互杩涜鍘嗗彶鍥炴斁
+  getSimresult(item.id)
+    .then((res) => {
+      if (res.code == 500) {
+        // 濡傛灉闀垮害涓�0锛屾彁绀虹敤鎴峰苟涓斾笉杩涜鍚庣画鎿嶄綔
+        ElMessage.warning("鎻愮ず锛氭病鏈夊彲鍥炴斁鐨勬暟鎹紒");
+        return; // 闃绘鍚庣画鎿嶄綔
+      } else {
+        simStore.rePlayList = res.data;
+        console.log(simStore.rePlayList, "lisi");
+      }
+      // 浣跨敤 nextTick 纭繚 DOM 鏇存柊鍚庡啀鎵ц鍚庣画鎿嶄綔
+      nextTick(() => {
+        initeWaterPrimitiveView();
+        startSimulate();
+      });
+    })
+    .catch((error) => {
+      console.log("璇锋眰澶辫触锛�", error);
+      // 閿欒澶勭悊
+    });
 }
 
 function handleBack(value) {
@@ -221,10 +221,10 @@
         item.result == "鍒涘缓浠跨湡" ||
         item.result == "瀹屾垚" ||
         item.result == "-1" ||
-        item.result == null
+        item.result == "鍋滄" ||
+        item.result == "杩涜涓�"
     );
     simAPIStore.shouldPoll = !shouldStop; // 淇敼 Pinia 鐘舵��
-    console.log(shouldStop, "aaaaaaaaaaaaaaaa");
     // 3. 濡傛灉闇�瑕佸仠姝�
     if (shouldStop) {
       if (intervalId) {
diff --git a/src/store/simulation.js b/src/store/simulation.js
index 2b74dcb..a1b2f8a 100644
--- a/src/store/simulation.js
+++ b/src/store/simulation.js
@@ -2,6 +2,8 @@
 import { defineStore } from 'pinia'
 import { ref } from 'vue'
 export const useSimStore = defineStore('simulation', () => {
+    // 鍘嗗彶鍥炴斁鍒楄〃
+    const rePlayList = ref([])
     // 鍖椾含甯傛墍鏈夋潙鐨刢ode
     const townCodeAll = ref([])
     // 瀹炴椂妯℃嫙鏈�鏂扮殑layer
@@ -47,10 +49,22 @@
     // 闄嶉洦鍗曚綅
     const intensityUnit = ref()
     const setSelectedScheme = (scheme) => {
-        selectedScheme.value = scheme
-        rainFalls.value = JSON.parse(scheme.data).rainfalls
-        intensityUnit.value = JSON.parse(scheme.data).intensityUnit
-    }
+        selectedScheme.value = scheme;
+
+        try {
+            const parsedData = JSON.parse(scheme.data);
+
+            // 鍙湁褰� rainfalls 鍜� intensityUnit 瀛樺湪涓旈潪绌烘椂鎵嶈祴鍊�
+            if (parsedData.rainfalls && parsedData.intensityUnit) {
+                rainFalls.value = parsedData.rainfalls;
+                intensityUnit.value = parsedData.intensityUnit;
+            } else {
+                console.warn("缂哄皯蹇呰鐨� rainfalls 鎴� intensityUnit 瀛楁");
+            }
+        } catch (error) {
+            console.error("瑙f瀽 scheme.data 鍑洪敊", error);
+        }
+    };
     const clearSelectedScheme = () => {
         selectedScheme.value = null
     }
@@ -200,6 +214,7 @@
         devices,
         frameNum,
         layerDate,
+        rePlayList,
 
         // 鏂规鐩稿叧鏂规硶
         setSchemCard,
diff --git a/src/views/left/CitySim.vue b/src/views/left/CitySim.vue
index eefcfd3..9ecf788 100644
--- a/src/views/left/CitySim.vue
+++ b/src/views/left/CitySim.vue
@@ -495,7 +495,9 @@
       : undefined,
   }));
 
-  console.log(rawRainFallList, "鍘熷闄嶉洦鏁版嵁");
+  // 鏇存柊 forms.rainFallList锛屽彲鐢ㄤ簬鍥捐〃鏄剧ず绛夌敤閫�
+  forms.rainFallList = rawRainFallList;
+
 
   // 鍒ゆ柇鏄惁涓烘暣灏忔椂鏁版嵁锛堝嵆鐩搁偦鏃堕棿闂撮殧鏄惁涓烘暣灏忔椂锛�
   const isHourlyData = checkIfHourlyData(rawRainFallList);
@@ -513,9 +515,6 @@
       intensity: item.intensity,
     }));
   }
-
-  // 鏇存柊 forms.rainFallList锛屽彲鐢ㄤ簬鍥捐〃鏄剧ず绛夌敤閫�
-  forms.rainFallList = rawRainFallList;
 
   // 璁$畻璧峰鏃堕棿鍜岀粨鏉熸椂闂达紙姣鏁帮級
   const firstTime = parseDateTime(hourlyRainfallList[0]?.time);
diff --git a/src/views/left/KGSimOption/RealTimeSimulation.vue b/src/views/left/KGSimOption/RealTimeSimulation.vue
index 4dc917b..7db609f 100644
--- a/src/views/left/KGSimOption/RealTimeSimulation.vue
+++ b/src/views/left/KGSimOption/RealTimeSimulation.vue
@@ -81,7 +81,8 @@
 import { useSimStore } from "@/store/simulation.js";
 import { EventBus } from "@/eventBus"; // 寮曞叆浜嬩欢鎬荤嚎
 import { getDeviceInfoSHG, getYLJData } from "@/api/hpApi";
-import { getSimStart, getSimDataById } from "@/api/trApi";
+import { getSimStart, getSimDataById, getSimresult } from "@/api/trApi";
+import { ControlSchemeType } from "@/assets/js/lib-pixelstreamingfrontend.esm";
 
 // 鑾峰彇 Store 瀹炰緥
 const simAPIStore = SimAPIStore();
@@ -219,6 +220,8 @@
 
 // 瀹炴椂妯℃嫙瀹氭椂鍣�
 let pollingInterval = null;
+// 鐢ㄤ簬璁板綍涓婃鏁版嵁鏉℃暟
+let lastDataLength = 0;
 
 async function startPlay() {
   // 寮�濮嬫ā鎷熷墠闇�瑕佸厛淇濆瓨鏂规
@@ -246,30 +249,27 @@
   });
 
   try {
-    // 璋冪敤姹傝В鍣ㄥ苟鍒濆鍖栨ā鎷�
-    const resStart = await getSimStart(schemeId);
+    // 鍚姩妯℃嫙
+    await getSimStart(schemeId);
 
-    // 璇锋眰瀹屾垚鍚庡叧闂姞杞芥彁绀�
-    loadingMessage.close();
-
-    if (resStart.code === 200) {
-      const res = await getSimDataById(schemeId);
-      simStore.setSelectedScheme(res.data[0]);
-
-      simStore.layerDate = resStart.data;
-      initeWaterPrimitiveView();
-
+    // 棣栨璇锋眰寤惰繜 90s
+    setTimeout(async () => {
       try {
-        startSimulate(); // 杩欓噷鍙兘浼氭姤閿�
-      } catch (error) {
-        console.error("璋冪敤 startSimulate 鍑洪敊锛�", error);
-      }
+        const res = await getSimresult(schemeId);
+        console.log(res.data, "瀹炴椂妯℃嫙 - 鍒濆缁撴灉");
 
-      // 寮�濮嬭疆璇换鍔★細姣� 5 鍒嗛挓璋冪敤涓�娆� getSimStart 骞舵洿鏂版柟妗堟暟鎹�
-      startPolling(schemeId);
-    } else {
-      ElMessage.error(resStart.message || "璋冪敤姹傝В鍣ㄥけ璐�");
-    }
+        if (res.data.length > 0) {
+          handleNewData(res.data, schemeId);
+        }
+
+        // 鏄剧ず缁撴灉骞跺紑濮嬭疆璇�
+        loadingMessage.close();
+        startPolling(schemeId);
+      } catch (error) {
+        console.error("棣栨璇锋眰妯℃嫙缁撴灉澶辫触", error);
+        loadingMessage.close();
+      }
+    }, 3 * 60 * 1000); // 1.5 鍒嗛挓鍚庣涓�娆¤姹�
   } catch (error) {
     loadingMessage.close();
     ElMessage.error("璇锋眰澶辫触锛�" + (error.message || "鏈煡閿欒"));
@@ -277,27 +277,85 @@
   }
 }
 
-// 鍚姩杞鍑芥暟
+// 瀹氭椂浜斿垎閽熻姹�
 function startPolling(schemeId) {
-  stopPolling(); // 閬垮厤閲嶅鍚姩
+  stopPolling(); // 纭繚涓嶄細閲嶅鍚姩
 
   pollingInterval = setInterval(async () => {
     try {
-      const resStart = await getSimStart(schemeId);
+      const res = await getSimresult(schemeId);
 
-      if (resStart.code === 200) {
-        const res = await getSimDataById(schemeId);
-        simStore.setSelectedScheme(res.data[0]); // 鏇存柊鏂规鏁版嵁
-        simStore.layerDate = resStart.data; // 鏇存柊 layer 鏁版嵁
+      if (res.data && res.data.length > 0) {
+        if (res.data.length === lastDataLength) {
+          console.log("涓昏疆璇細鏃犳柊鏁版嵁锛屽垏鎹负 10 绉掗珮棰戣疆璇�");
 
-        console.log("杞鑾峰彇鏈�鏂版暟鎹垚鍔�");
-      } else {
-        console.warn("杞璇锋眰澶辫触锛�", resStart.message);
+          clearInterval(pollingInterval);
+          pollingInterval = null;
+
+          startFastPolling(schemeId); // 鍚姩楂橀杞
+        } else {
+          handleNewData(res.data, schemeId);
+        }
       }
     } catch (error) {
-      console.error("杞璇锋眰寮傚父锛�", error);
+      console.error("杞鑾峰彇妯℃嫙缁撴灉澶辫触", error);
     }
-  }, 5 * 60 * 1000); // 姣� 5 鍒嗛挓鎵ц涓�娆�
+  }, 5.6 * 60 * 1000); // 姣� 5.5 鍒嗛挓鎵ц涓�娆�
+}
+
+let fastPollingInterval = null;
+// 濡傛灉浜斿垎閽熸病鎷垮埌鏈�鏂扮殑鏁版嵁锛屽垯寮�鍚崄绉掗挓璋冪敤涓�娆★紝鎷垮埌鏈�鏂扮殑鏁版嵁灏卞仠姝�
+function startFastPolling(schemeId) {
+  fastPollingInterval = setInterval(async () => {
+    try {
+      const res = await getSimresult(schemeId);
+
+      if (res.data && res.data.length > 0) {
+        if (res.data.length !== lastDataLength) {
+          console.log("楂橀杞锛氭娴嬪埌鏂版暟鎹紝鎭㈠涓昏疆璇�");
+
+          clearInterval(fastPollingInterval);
+          fastPollingInterval = null;
+
+          handleNewData(res.data, schemeId);
+
+          startPolling(schemeId); // 閲嶆柊鍚姩涓昏疆璇�
+        }
+      }
+    } catch (error) {
+      console.error("楂橀杞鑾峰彇妯℃嫙缁撴灉澶辫触", error);
+    }
+  }, 10 * 1000); // 姣� 10 绉掓墽琛屼竴娆�
+}
+
+// 鎷垮彇鏈�鏂扮殑layer.json瀛樺偍鍒皃inia涓�
+async function handleNewData(dataArray, schemeId) {
+  // 鎷挎湇鍔″悕绉�
+  const res = await getSimDataById(schemeId);
+  simStore.setSelectedScheme(res.data[0]); // 鏇存柊鏂规鏁版嵁
+
+  const latestItem = dataArray[dataArray.length - 1];
+  const currentLength = dataArray.length;
+
+  if (currentLength <= lastDataLength) {
+    console.log("鏈疆鏃犳柊鏁版嵁锛堥暱搴︽湭鍙樺寲锛�");
+    return;
+  }
+
+  // 鏇存柊鏍囪瘑
+  lastDataLength = currentLength;
+
+  // 鎵ц鏇存柊閫昏緫
+  console.log("妫�娴嬪埌鏂版暟鎹紝鏇存柊涓�...");
+  console.log(latestItem, "last");
+  simStore.layerDate = latestItem;
+  initeWaterPrimitiveView();
+
+  try {
+    startSimulate();
+  } catch (error) {
+    console.error("璋冪敤 startSimulate 鍑洪敊锛�", error);
+  }
 }
 
 // 鍋滄杞鍑芥暟
@@ -305,8 +363,14 @@
   if (pollingInterval) {
     clearInterval(pollingInterval);
     pollingInterval = null;
-    console.log("杞宸插仠姝�");
   }
+
+  if (fastPollingInterval) {
+    clearInterval(fastPollingInterval);
+    fastPollingInterval = null;
+  }
+
+  console.log("杞宸插仠姝�");
 }
 
 EventBus.on("close-time", () => {

--
Gitblit v1.9.3