From d3e7a1953618d73ffb1a480cb7c6afda42246460 Mon Sep 17 00:00:00 2001 From: guonan <guonan201020@163.com> Date: 星期四, 19 六月 2025 17:15:24 +0800 Subject: [PATCH] 提交 --- src/components/menu/TimeLine.vue | 230 ++++++++++++++++++++++++++++++++++++++------------------- 1 files changed, 152 insertions(+), 78 deletions(-) diff --git a/src/components/menu/TimeLine.vue b/src/components/menu/TimeLine.vue index c2cd6ea..bf2ed73 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"> <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,18 +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" /> + <div> + 涓撻娓叉煋: + <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> @@ -45,27 +70,53 @@ <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 class="date-part">{{ time.split(' ')[0] }}</div> - <div class="time-part">{{ time.split(' ')[1] }}</div> + <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> </div> </div> </div> <div> - <div style="display: flex;"> - <ratelevel ref="ratelevelRef" :playing-time="sendCurrentPlayingTime" + <div style="display: flex"> + <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="margin-top: 12px; margin-left: 16px; margin-right: 20px;justify-content: flex-end;" /> - + style=" + margin-top: 12px; + margin-left: 28px; + margin-right: 10px; + justify-content: flex-end; + " + /> + <crossanalysis + ref="crossRef" + style=" + margin-top: 12px; + margin-left: 16px; + margin-right: 20px; + justify-content: flex-end; + " + /> </div> - <el-button @click="handleBack" - style="margin-top: 3px; margin-left: 28px; margin-right: 10px;width: 75%;height: 30%;">缁撴潫妯℃嫙</el-button> + <el-button + @click="handleBack" + style=" + margin-top: 3px; + margin-left: 28px; + margin-right: 10px; + width: 75%; + height: 30%; + " + >缁撴潫妯℃嫙</el-button + > </div> - </div> </template> @@ -78,7 +129,7 @@ defineProps, onBeforeUnmount, inject, - reactive + reactive, } from "vue"; import ratelevel from "@/components/menu/flowRate_waterLevel.vue"; import crossanalysis from "@/components/menu/CrossSectionalAnalysis.vue"; @@ -100,9 +151,14 @@ import { useSimStore } from "@/store/simulation"; import { storeToRefs } from "pinia"; const simStore = useSimStore(); -const { selectedScheme } = storeToRefs(simStore); +const { selectedScheme, frameNum } = storeToRefs(simStore); -const emit = defineEmits(["timeUpdate", "isPlaying", "playbackFinished", "isColorRender"]); +const emit = defineEmits([ + "timeUpdate", + "isPlaying", + "playbackFinished", + "isColorRender", +]); // 瀹氫箟props const props = defineProps({ waterSimulateParams: { @@ -136,10 +192,10 @@ rainSize: 0.5, rainSpeed: 50, rainColor: "#99B3CC", - rainDensity: 30 // 闆ㄧ殑瀵嗗害 + rainDensity: 30, // 闆ㄧ殑瀵嗗害 }); -let minFlowRate = ref() -let maxFlowRate = ref() +let minFlowRate = ref(); +let maxFlowRate = ref(); // 璁$畻灞炴�� const progressPercentage = computed( () => (currentTime.value / duration.value) * 100 @@ -204,8 +260,8 @@ return; // 闃绘鍚庣画閫昏緫鎵ц } if (isWaterPrimitiveCreated.value) { - console.log('褰撳墠鏄惁寮�鍚笓棰樻覆鏌擄細', enabled); - emit("isColorRender", enabled) + console.log("褰撳墠鏄惁寮�鍚笓棰樻覆鏌擄細", enabled); + emit("isColorRender", enabled); toggleWaterColorRender(enabled); } }; @@ -259,93 +315,100 @@ // 娉ㄦ剰锛氭湁鏃� data 鍙兘鏄竴涓瓧绗︿覆锛堜緥濡� JSON 瀛楃涓诧級 let data = selectedScheme.value.data; // 濡傛灉鏄瓧绗︿覆锛屽垯灏濊瘯瑙f瀽鎴愬璞� - if (typeof data === 'string') { + if (typeof data === "string") { try { data = JSON.parse(data); - console.log('瑙f瀽鍚庣殑闄嶉洦鏁版嵁锛�', data); + console.log("瑙f瀽鍚庣殑闄嶉洦鏁版嵁锛�", data); } catch (e) { console.error("data 涓嶆槸鏈夋晥鐨� JSON 瀛楃涓�"); return; } } // 鎵撳嵃闄嶉洦寮哄害鐨勫崟浣� - console.log('闄嶉洦寮哄害鐨勫崟浣嶆槸锛�', data.intensityUnit); + console.log("闄嶉洦寮哄害鐨勫崟浣嶆槸锛�", data.intensityUnit); // 鏍规嵁 intensityUnit 璋冩暣 rainfalls 涓殑 intensity 鍊� - if (data.intensityUnit === 'mm/min') { - data.rainfalls.forEach(r => r.intensity *= 60); - console.log('灏� mm/min 杞崲涓� mm/h 鍚庣殑 rainfalls:', data.rainfalls); - } else if (data.intensityUnit === 'mm/5min') { - data.rainfalls.forEach(r => r.intensity *= 12); - console.log('灏� mm/5min 杞崲涓� mm/h 鍚庣殑 rainfalls:', data.rainfalls); - } else if (data.intensityUnit !== 'mm/h') { - console.warn('鏈煡鐨� intensity 鍗曚綅锛屾棤娉曡繘琛岃浆鎹�'); + if (data.intensityUnit === "mm/min") { + data.rainfalls.forEach((r) => (r.intensity *= 60)); + console.log("灏� mm/min 杞崲涓� mm/h 鍚庣殑 rainfalls:", data.rainfalls); + } else if (data.intensityUnit === "mm/5min") { + data.rainfalls.forEach((r) => (r.intensity *= 12)); + console.log("灏� mm/5min 杞崲涓� mm/h 鍚庣殑 rainfalls:", data.rainfalls); + } else if (data.intensityUnit !== "mm/h") { + console.warn("鏈煡鐨� intensity 鍗曚綅锛屾棤娉曡繘琛岃浆鎹�"); } const rainfallList = data.rainfalls; - console.log('鏈�缁堢殑 rainfallList:', rainfallList); + console.log("鏈�缁堢殑 rainfallList:", rainfallList); // 鎻愬彇 intensity 鍊� - rainFallValues.value = rainfallList.map(r => r.intensity); + rainFallValues.value = rainfallList.map((r) => r.intensity); minRainValue.value = Math.min(...rainFallValues.value); maxRainValue.value = Math.max(...rainFallValues.value); - console.log('褰撳墠鏂规涓嬫渶灏忛洦閲忓拰鏈�澶ч洦閲忥細', minRainValue.value, maxRainValue.value); + console.log( + "褰撳墠鏂规涓嬫渶灏忛洦閲忓拰鏈�澶ч洦閲忥細", + minRainValue.value, + maxRainValue.value + ); } // 瀹氫箟闄嶉洦绛夌骇鍙婂叾瀵瑰簲鐨勮瑙夊弬鏁� const rainLevels = [ { - name: '灏忛洦', + name: "灏忛洦", min: 0.1, max: 9.9, - size: 0.5, // 闆ㄦ淮澶у皬锛氭洿灏� - speed: 20, // 涓嬭惤閫熷害锛氭洿鎱� - density: 15, // 闆ㄦ淮瀵嗗害锛氭洿绋�鐤� - color: '#ADD8E6' // 娴呰摑鑹诧紝璞″緛杞绘煍鐨勫皬闆� + size: 0.5, // 闆ㄦ淮澶у皬锛氭洿灏� + speed: 20, // 涓嬭惤閫熷害锛氭洿鎱� + density: 15, // 闆ㄦ淮瀵嗗害锛氭洿绋�鐤� + color: "#ADD8E6", // 娴呰摑鑹诧紝璞″緛杞绘煍鐨勫皬闆� }, { - name: '涓洦', + name: "涓洦", min: 10, max: 24.9, size: 0.7, speed: 28, density: 23, - color: '#ADD8E6' + color: "#ADD8E6", }, { - name: '澶ч洦', + name: "澶ч洦", min: 25, max: 49.9, size: 1.0, speed: 36, density: 31, - color: '#ADD8E6' + color: "#ADD8E6", }, { - name: '鏆撮洦', + name: "鏆撮洦", min: 50, max: 99.9, size: 1.3, speed: 42, density: 39, - color: '#ADD8E6' + color: "#ADD8E6", }, { - name: '澶ф毚闆�', + name: "澶ф毚闆�", min: 100, size: 1.6, speed: 50, density: 47, - color: '#ADD8E6' - } + color: "#ADD8E6", + }, ]; // 鏍规嵁闄嶉洦閲忚繑鍥炲搴旂殑闆ㄥ舰閰嶇疆 function getRainLevel(rainValue) { for (let level of rainLevels) { - if (level.min <= rainValue && (level.max === undefined || rainValue <= level.max)) { + if ( + level.min <= rainValue && + (level.max === undefined || rainValue <= level.max) + ) { return level; } } // 榛樿鏃犻洦鐘舵�� - return { name: '鏃犻洦', size: 0.3, speed: 10, density: 10, color: '#F0F8FF' }; + return { name: "鏃犻洦", size: 0.3, speed: 10, density: 10, color: "#F0F8FF" }; } // 鏍规嵁鎾斁杩涘害鏇存柊澶╂皵鏁堟灉锛堝凡浼樺寲锛� let lastUsedIndex = -1; // 缂撳瓨涓婁竴娆′娇鐢ㄧ殑绱㈠紩锛岄槻姝㈤噸澶嶆洿鏂� @@ -355,14 +418,14 @@ // console.log(`鏃堕棿杞存�绘椂闀�: ${duration.value}, 褰撳墠鏃堕棿: ${currentTime.value}`); // 鎵撳嵃鏃堕棿杞翠俊鎭� const progress = currentTime.value / duration.value; const floatIndex = progress * (rainFallValues.value.length - 1); - const index = Math.floor(floatIndex); // 褰撳墠绱㈠紩 + const index = Math.floor(floatIndex); // 褰撳墠绱㈠紩 const nextIndex = Math.min(index + 1, rainFallValues.value.length - 1); // 涓嬩竴绱㈠紩 const currentRain = rainFallValues.value[index]; const nextRain = rainFallValues.value[nextIndex]; // 鍚敤鎻掑�硷紙alpha 骞虫粦杩囨浮锛� const alpha = floatIndex - index; // const rainValue = currentRain + (nextRain - currentRain) * alpha; - const rainValue = currentRain + (nextRain - currentRain) + const rainValue = currentRain + (nextRain - currentRain); // 鎵撳嵃褰撳墠澶勭悊鐨勯洦閲忔暟鎹� // console.log(`姝e湪澶勭悊鐨勯洦閲忔暟鎹偣: 褰撳墠=${currentRain}, 涓嬩竴涓�=${nextRain}, 鎻掑�煎悗=${rainValue.toFixed(2)}, 绱㈠紩=${index}`); // 濡傛灉褰撳墠绱㈠紩鏈彉鍖栦笖鎻掑�煎樊寮備笉澶э紝璺宠繃閲嶅鏇存柊 @@ -389,9 +452,9 @@ rainSize: rainLevel.size, rainSpeed: rainLevel.speed, rainDensity: rainLevel.density, - rainColor: rainLevel.color + rainColor: rainLevel.color, }; - console.log('褰撳墠闆ㄩ噺鏁版嵁锛�', rainValue, '褰撳墠闆ㄥ舰锛�', rainLevel); + console.log("褰撳墠闆ㄩ噺鏁版嵁锛�", rainValue, "褰撳墠闆ㄥ舰锛�", rainLevel); // 璋冪敤宸ュ叿鏂规硶鏇存柊闆ㄦ晥 mapUtils.toggleRain(rainParams, true); } @@ -428,7 +491,7 @@ // 璁剧疆鎾斁閫熺巼 const setPlaybackRate = (rate) => { - isColorRenderEnabled.value = false + isColorRenderEnabled.value = false; playbackRate.value = rate; showSpeedMenu.value = false; // 鍋滄褰撳墠鎾斁 @@ -468,7 +531,8 @@ // 鐩存帴鎵惧埌鏈�杩戠殑 timestamp 绱㈠紩 const closestIndex = findClosestTimestampIndex(targetTime); const baseTimestamp = waterTimestamps.value[0]; - currentTime.value = (waterTimestamps.value[closestIndex] - baseTimestamp) / 1000; + currentTime.value = + (waterTimestamps.value[closestIndex] - baseTimestamp) / 1000; // 鏇存柊姘翠綋妯℃嫙鏃堕棿 setTimeForWaterSimulation(closestIndex); @@ -500,7 +564,7 @@ () => selectedScheme.value, (newVal) => { if (newVal) { - console.log('閫変腑鏂规宸叉敼鍙�:', newVal) + console.log("閫変腑鏂规宸叉敼鍙�:", newVal); } } ); @@ -513,7 +577,9 @@ .valueOf(); // 浣跨敤 valueOf() 鑾峰彇鍘熷鏃堕棿鎴� // 鏇存柊 currentPlayingTime 鏍煎紡鍖栧悗鐨勬椂闂村瓧绗︿覆 - currentPlayingTime.value = dayjs(sendCurrentPlayingTime.value).format("YYYY-MM-DD HH:mm:ss"); + currentPlayingTime.value = dayjs(sendCurrentPlayingTime.value).format( + "YYYY-MM-DD HH:mm:ss" + ); EventBus.emit("time-update", currentPlayingTime.value); } } @@ -549,23 +615,32 @@ serviceInfo = schemeInfo.serviceName; // console.log('鑾峰彇鍒扮殑 serviceName:', serviceInfo); - getRainfallData() + getRainfallData(); // 鏍规嵁layer.json鍘昏幏鍙栨椂闂磋酱淇℃伅 - const { waterTimestamps: timestamps, watersMaxHeight, watersMinHeight } = await fetchWaterSimulationData(serviceInfo); - console.log('褰撳墠鏂规涓嬬殑鏈�澶ф按浣嶆繁搴﹀拰鏈�灏忔按浣嶆繁搴�',watersMaxHeight,watersMinHeight); - + const { + waterTimestamps: timestamps, + watersMaxHeight, + watersMinHeight, + } = await fetchWaterSimulationData(serviceInfo); + console.log( + "褰撳墠鏂规涓嬬殑鏈�澶ф按浣嶆繁搴﹀拰鏈�灏忔按浣嶆繁搴�", + watersMaxHeight, + watersMinHeight + ); + // 鐜板湪鏄寜鐓ф�诲叡鏈夊灏戜釜鐐规潵娓叉煋鏃堕棿杞� if (timestamps) { + frameNum.value = timestamps.length; waterTimestamps.value = timestamps; updateTimelineRange(); timeMarkers.value = generateTimeMarkers(timestamps); - sendCurrentPlayingTime.value = timestamps[0] + sendCurrentPlayingTime.value = timestamps[0]; currentPlayingTime.value = dayjs(timestamps[0]).format( "YYYY-MM-DD HH:mm:ss" ); } - minFlowRate = watersMinHeight - maxFlowRate = watersMaxHeight + minFlowRate = watersMinHeight; + maxFlowRate = watersMaxHeight; } catch (error) { console.error("Error loading water simulation data:", error); ElMessage({ @@ -600,8 +675,7 @@ } if (crossRef.value) { crossRef.value.clearPoints(); - console.log('鎵ц鍒犻櫎鐐瑰姛鑳�'); - + console.log("鎵ц鍒犻櫎鐐瑰姛鑳�"); } emit("isColorRender", false); setTimeout(() => { -- Gitblit v1.9.3