From 1119a7837323e052d3e6256cddd3283d919bd959 Mon Sep 17 00:00:00 2001
From: guonan <guonan201020@163.com>
Date: 星期四, 26 六月 2025 15:44:02 +0800
Subject: [PATCH] 提交

---
 src/components/menu/TimeLine.vue |  302 ++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 228 insertions(+), 74 deletions(-)

diff --git a/src/components/menu/TimeLine.vue b/src/components/menu/TimeLine.vue
index e18acb9..f4b1380 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>
@@ -91,6 +130,7 @@
   onBeforeUnmount,
   inject,
   reactive,
+  watchEffect,
 } from "vue";
 import ratelevel from "@/components/menu/flowRate_waterLevel.vue";
 import crossanalysis from "@/components/menu/CrossSectionalAnalysis.vue";
@@ -174,6 +214,9 @@
     new Set(waterTimestamps.value.map((ts) => dayjs(ts).format("YYYY-MM-DD")))
   ).map((date) => dayjs(date).toDate())
 );
+
+// 鎴戦渶瑕佸姞涓�涓垽鏂�
+const finishPlay = ref(false);
 // 鎾斁鎺у埗
 const togglePlay = () => {
   // 杩欓噷搴旇鍐嶈瀹氬嚑涓檺鍒讹紝濡傛灉缂哄皯浠�涔堟暟鎹紝鏃犳硶杩涜浠跨湡
@@ -241,38 +284,96 @@
   8: 125, // 8鍊嶉��
 };
 // 鎾斁閫昏緫
+// const startPlayback = () => {
+//   clearInterval(playInterval);
+
+//   playInterval = setInterval(() => {
+//     // 鎵惧埌褰撳墠鏃堕棿瀵瑰簲鐨勭储寮�
+//     const currentIndex = findClosestTimestampIndex(currentTime.value);
+//     const nextIndex = currentIndex + 1;
+
+//     // 濡傛灉宸茬粡鏄渶鍚庝竴涓椂闂寸偣锛屽仠姝㈡挱鏀�
+//     if (nextIndex >= waterTimestamps.value.length) {
+//       currentTime.value = duration.value;
+//       stopPlayback();
+//       isPlaying.value = false;
+//       emit("isPlaying", false);
+//       emit("playbackFinished", true);
+//       return;
+//     }
+
+//     // 鏇存柊鏃堕棿涓轰笅涓�涓椂闂寸偣鐨勬椂闂村樊锛堢锛�
+//     const nextTimestamp = waterTimestamps.value[nextIndex];
+//     const baseTimestamp = waterTimestamps.value[0];
+//     currentTime.value = (nextTimestamp - baseTimestamp) / 1000;
+
+//     // 瑙﹀彂鏇存柊
+//     if (selectedScheme.value.type !== 2) {
+//       updateWaterColorByTime();
+//       updateWeatherByProgress();
+//     }
+
+//     const progress = currentTime.value / duration.value;
+//     emit("timeUpdate", progress * 100);
+//   }, 1000 / playbackRate.value); // 鏍规嵁鎾斁閫熺巼璋冩暣闂撮殧
+// };
 const startPlayback = () => {
   clearInterval(playInterval);
 
-  playInterval = setInterval(() => {
-    // 鎵惧埌褰撳墠鏃堕棿瀵瑰簲鐨勭储寮�
-    const currentIndex = findClosestTimestampIndex(currentTime.value);
-    const nextIndex = currentIndex + 1;
+  if (selectedScheme.value.type === 2) {
+    // 绫诲瀷涓� 2锛氭瘡 5 绉掕烦鍔ㄤ竴娆�
+    playInterval = setInterval(() => {
+      const fiveSeconds = 5;
+      const totalDuration = duration.value; // 鎬绘椂闀匡紙绉掞級
 
-    // 濡傛灉宸茬粡鏄渶鍚庝竴涓椂闂寸偣锛屽仠姝㈡挱鏀�
-    if (nextIndex >= waterTimestamps.value.length) {
-      currentTime.value = duration.value;
-      stopPlayback();
-      isPlaying.value = false;
-      emit("isPlaying", false);
-      emit("playbackFinished", true);
-      return;
-    }
+      currentTime.value += fiveSeconds;
 
-    // 鏇存柊鏃堕棿涓轰笅涓�涓椂闂寸偣鐨勬椂闂村樊锛堢锛�
-    const nextTimestamp = waterTimestamps.value[nextIndex];
-    const baseTimestamp = waterTimestamps.value[0];
-    currentTime.value = (nextTimestamp - baseTimestamp) / 1000;
+      if (currentTime.value >= totalDuration) {
+        currentTime.value = totalDuration;
+        stopPlayback();
+        isPlaying.value = false;
+        finishPlay.value = true;
+        emit("isPlaying", false);
+        emit("playbackFinished", true);
+        return;
+      }
 
-    // 瑙﹀彂鏇存柊
-    if (selectedScheme.value.type !== 2) {
+      // 瑙﹀彂杩涘害鏇存柊
+      const progress = currentTime.value / totalDuration;
+      emit("timeUpdate", progress * 100);
+
+      // 濡傛灉闇�瑕佽Е鍙戞煇浜涙洿鏂板嚱鏁帮紝涔熷彲浠ヤ繚鐣�
       updateWaterColorByTime();
       updateWeatherByProgress();
-    }
+    }, 5000); // 姣� 5 绉掓墽琛屼竴娆�
+  } else {
+    // 杩欓噷闈㈣繕鏄綘鐨勬挱鏀句唬鐮侊紝涓婇潰鐨刬f涓槸浜旂閽熻烦鍔ㄤ竴娆$殑瀹炴椂妯℃嫙
+    playInterval = setInterval(() => {
+      const currentIndex = findClosestTimestampIndex(currentTime.value);
+      const nextIndex = currentIndex + 1;
 
-    const progress = currentTime.value / duration.value;
-    emit("timeUpdate", progress * 100);
-  }, 1000 / playbackRate.value); // 鏍规嵁鎾斁閫熺巼璋冩暣闂撮殧
+      if (nextIndex >= waterTimestamps.value.length) {
+        currentTime.value = duration.value;
+        stopPlayback();
+        isPlaying.value = false;
+        emit("isPlaying", false);
+        emit("playbackFinished", true);
+        return;
+      }
+
+      const nextTimestamp = waterTimestamps.value[nextIndex];
+      const baseTimestamp = waterTimestamps.value[0];
+      currentTime.value = (nextTimestamp - baseTimestamp) / 1000;
+
+      if (selectedScheme.value.type !== 2) {
+        updateWaterColorByTime();
+        updateWeatherByProgress();
+      }
+
+      const progress = currentTime.value / duration.value;
+      emit("timeUpdate", progress * 100);
+    }, 1000 / playbackRate.value);
+  }
 };
 // 闄嶉洦鍙樺寲閮ㄥ垎
 // 闄嶉洦鏁版嵁鐩稿叧鍙橀噺
@@ -428,10 +529,10 @@
 }
 // 鍏ㄥ眬鐘舵�佽褰�
 const colorState = {
-  maxStage: 0,       // 璁板綍鍘嗗彶鏈�楂橀樁娈�
-  maxAlpha: -0.3,    // 璁板綍鍘嗗彶鏈�灏忛�忔槑搴︼紙璐熷�硷級
+  maxStage: 0, // 璁板綍鍘嗗彶鏈�楂橀樁娈�
+  maxAlpha: -0.3, // 璁板綍鍘嗗彶鏈�灏忛�忔槑搴︼紙璐熷�硷級
   maxLuminance: 240.4, // 璁板綍鍘嗗彶鏈�浣庝寒搴︼紙瀵瑰簲stage 0鍒濆鍊硷級
-  currentColor: "#F5F0E6" // 褰撳墠棰滆壊
+  currentColor: "#F5F0E6", // 褰撳墠棰滆壊
 };
 
 function updateWaterColorByTime() {
@@ -448,16 +549,16 @@
     { hex: "#D4B483", luminance: 184.0 }, // stage 3
     { hex: "#B78B6A", luminance: 148.4 }, // stage 4
     { hex: "#8B5A3A", luminance: 101.0 }, // stage 5
-    { hex: "#4A3123", luminance: 54.9 }   // stage 6
+    { hex: "#4A3123", luminance: 54.9 }, // stage 6
   ];
-  const alphaStops = [1
-    -0.3,   // stage 0
-    -0.4,   // stage 1
-    -0.5,   // stage 2
-    -0.6,   // stage 3
-    -0.7,   // stage 4
-    -0.75,  // stage 5
-    -0.8    // stage 6
+  const alphaStops = [
+    1 - 0.3, // stage 0
+    -0.4, // stage 1
+    -0.5, // stage 2
+    -0.6, // stage 3
+    -0.7, // stage 4
+    -0.75, // stage 5
+    -0.8, // stage 6
   ];
   // 3. 鏇存柊闃舵鐘舵��
   updateStageState(intensity, IR);
@@ -472,10 +573,15 @@
   function calculateRainData() {
     const initialTimestamp = new Date(rainTotalInfo.value[0].time).getTime();
     const currentTimestamp = new Date(
-      rainTotalInfo.value[Math.min(
-        Math.floor(currentTime.value / duration.value * (rainTotalInfo.value.length - 1)),
-        rainTotalInfo.value.length - 2
-      )].time
+      rainTotalInfo.value[
+        Math.min(
+          Math.floor(
+            (currentTime.value / duration.value) *
+              (rainTotalInfo.value.length - 1)
+          ),
+          rainTotalInfo.value.length - 2
+        )
+      ].time
     ).getTime();
 
     // 闄嶉洦寮哄害璁$畻锛堝甫鎻掑�硷級
@@ -486,7 +592,8 @@
       index = rainTotalInfo.value.length - 2; // 闃叉 index+1 瓒婄晫
     }
     const lerpAlpha = floatIndex - index;
-    const intensity = rainTotalInfo.value[index].intensity * (1 - lerpAlpha) +
+    const intensity =
+      rainTotalInfo.value[index].intensity * (1 - lerpAlpha) +
       rainTotalInfo.value[index + 1].intensity * lerpAlpha;
 
     // 涓寸晫闄嶉洦寮哄害璁$畻
@@ -524,7 +631,13 @@
     const stageThresholds = [0, 0.2, 0.4, 0.6, 0.8, 1.0];
     const lowerThreshold = stageThresholds[colorState.maxStage - 1] * IR;
     const upperThreshold = stageThresholds[colorState.maxStage] * IR;
-    const ratio = Math.min(1, Math.max(0, (intensity - lowerThreshold) / (upperThreshold - lowerThreshold)));
+    const ratio = Math.min(
+      1,
+      Math.max(
+        0,
+        (intensity - lowerThreshold) / (upperThreshold - lowerThreshold)
+      )
+    );
 
     // 棰滆壊鎻掑��
     const startColor = colorStops[colorState.maxStage];
@@ -538,22 +651,26 @@
       colorState.maxLuminance = newLuminance;
       colorState.maxAlpha = Math.min(
         colorState.maxAlpha,
-        lerp(alphaStops[colorState.maxStage], alphaStops[colorState.maxStage + 1], ratio)
+        lerp(
+          alphaStops[colorState.maxStage],
+          alphaStops[colorState.maxStage + 1],
+          ratio
+        )
       );
     }
 
-    console.log(`闃舵: ${colorState.maxStage} | 浜害: ${colorState.maxLuminance.toFixed(1)} | 棰滆壊: ${colorState.currentColor}`);
+    console.log(
+      `闃舵: ${colorState.maxStage} | 浜害: ${colorState.maxLuminance.toFixed(
+        1
+      )} | 棰滆壊: ${colorState.currentColor}`
+    );
   }
 
   // 棰滆壊鎻掑�煎伐鍏峰嚱鏁�
   function lerpColor(c1, c2, t) {
     const [r1, g1, b1] = hexToRgb(c1);
     const [r2, g2, b2] = hexToRgb(c2);
-    return rgbToHex(
-      r1 + (r2 - r1) * t,
-      g1 + (g2 - g1) * t,
-      b1 + (b2 - b1) * t
-    );
+    return rgbToHex(r1 + (r2 - r1) * t, g1 + (g2 - g1) * t, b1 + (b2 - b1) * t);
   }
 
   function calculateLuminance(hex) {
@@ -567,7 +684,9 @@
   }
 
   function rgbToHex(r, g, b) {
-    return `#${[r, g, b].map(x => Math.round(x).toString(16).padStart(2, '0')).join('')}`;
+    return `#${[r, g, b]
+      .map((x) => Math.round(x).toString(16).padStart(2, "0"))
+      .join("")}`;
   }
 
   function lerp(a, b, t) {
@@ -774,16 +893,17 @@
   { immediate: true }
 );
 
-onMounted(async () => {
+const jsonFetch = ref(null);
+
+// 鎻愬彇涓虹嫭绔嬪嚱鏁�
+async function initializeSimulationData(force = false) {
   try {
-    // 褰撳墠鏂规鐨勬墍鏈変俊鎭�
     const schemeInfo = selectedScheme.value;
-    const jsonFetch = ref(null);
     serviceInfo = schemeInfo.serviceName;
-    if (selectedScheme.value.type == 2) {
+
+    if (schemeInfo.type == 2) {
       speedShow.value = false;
       jsonFetch.value = layerDate.value;
-      // serviceInfo = layerDate.value;
     } else {
       getRainfallData();
       speedShow.value = true;
@@ -792,19 +912,20 @@
 
     // console.log('鑾峰彇鍒扮殑 serviceName:', serviceInfo);
 
-    // 鏍规嵁layer.json鍘昏幏鍙栨椂闂磋酱淇℃伅
+    // 鏍规嵁 layer.json 鑾峰彇鏃堕棿杞翠俊鎭�
     const {
       waterTimestamps: timestamps,
       watersMaxHeight,
       watersMinHeight,
     } = await fetchWaterSimulationData(serviceInfo, jsonFetch.value);
+
     console.log(
       "褰撳墠鏂规涓嬬殑鏈�澶ф按浣嶆繁搴﹀拰鏈�灏忔按浣嶆繁搴�",
       watersMaxHeight,
       watersMinHeight
     );
 
-    // 鐜板湪鏄寜鐓ф�诲叡鏈夊灏戜釜鐐规潵娓叉煋鏃堕棿杞�
+    // 鏇存柊鏃堕棿杞寸浉鍏虫暟鎹�
     if (timestamps) {
       frameNum.value = timestamps.length;
       waterTimestamps.value = timestamps;
@@ -815,6 +936,7 @@
         "YYYY-MM-DD HH:mm:ss"
       );
     }
+
     minFlowRate = watersMinHeight;
     maxFlowRate = watersMaxHeight;
   } catch (error) {
@@ -824,7 +946,36 @@
       type: "warning",
     });
   }
+}
+
+// 鎸傝浇鏃惰皟鐢�
+onMounted(async () => {
+  // 鍥犱负杩欎釜鍑芥暟瀹炴椂妯℃嫙鐩戝惉涔熼渶瑕佷娇鐢紝鎵�浠ュ皝瑁呬簡涓�涓嚱鏁�
+  await initializeSimulationData();
 });
+
+const shouldAutoPlay = ref(false);
+
+// 鐩戝惉 layerDate 鍙樺寲鍚庢爣璁板噯澶囨挱鏀�
+watch(
+  () => layerDate.value,
+  async (newVal) => {
+    if (selectedScheme.value.type === 2 && newVal) {
+      shouldAutoPlay.value = true;
+    }
+  },
+  { deep: true }
+);
+
+// 绛夊緟 finishPlay 鎴愬姛鍚庡啀鎾斁
+watchEffect(() => {
+  if (shouldAutoPlay.value && finishPlay.value && !isPlaying.value) {
+    initializeSimulationData();
+    togglePlay();
+    shouldAutoPlay.value = false;
+  }
+});
+
 // 鏍规嵁杩斿洖鏁版嵁鐨勪釜鏁板幓娓叉煋鏃堕棿杞�
 function updateTimelineRange() {
   if (waterTimestamps.value.length > 0) {
@@ -844,6 +995,9 @@
 const { endSimulate } = inject("simulateActions");
 function handleBack() {
   endSimulate();
+  // 鍋滄瀹炴椂妯℃嫙瀹氭椂鍣�
+  EventBus.emit("close-time");
+
   isWaterPrimitiveCreated.value = false;
   if (ratelevelRef.value) {
     ratelevelRef.value.endCalculation();

--
Gitblit v1.9.3