From f54c45de2ec6dfadc825c064b75e6707513bd094 Mon Sep 17 00:00:00 2001 From: wangjuncheng <1> Date: 星期一, 28 四月 2025 10:07:08 +0800 Subject: [PATCH] change --- src/components/menu/TimeLine.vue | 336 ++++++++++++++++++++------------------------------------ 1 files changed, 120 insertions(+), 216 deletions(-) diff --git a/src/components/menu/TimeLine.vue b/src/components/menu/TimeLine.vue index b8cec2a..dd4acc6 100644 --- a/src/components/menu/TimeLine.vue +++ b/src/components/menu/TimeLine.vue @@ -2,30 +2,20 @@ <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> @@ -34,29 +24,18 @@ <div class="timeline"> <div class="dates"> - <div - v-for="(date, index) in visibleDates" - :key="index" - class="date-label" - > - {{ formatDate(date) }} + <div class="current-date"> + 褰撳墠鎾斁鏃堕棿锛歿{ currentPlayingTime }} + </div> + <div v-for="(date, index) in visibleDates" :key="index" class="date-label"> + <!-- {{ formatDate(date) }} --> </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="time-markers"> - <div - v-for="(time, index) in timeMarkers" - :key="index" - class="time-marker" - > + <div v-for="(time, index) in timeMarkers" :key="index" class="time-marker"> {{ time }} </div> </div> @@ -70,7 +49,6 @@ import { ref, computed, - onUnmounted, onMounted, watch, defineProps, @@ -79,11 +57,13 @@ } from "vue"; import dayjs from "dayjs"; import { createWaterPrimitive, destoryWaterPrimitive } from "@/utils/water"; -import { getRainfall } from "@/api/index"; -import { EventBus } from "@/eventBus"; // 寮曞叆浜嬩欢鎬荤嚎 -import { ElMessage } from 'element-plus' +import { fetchWaterSimulationData } from "@/api/trApi.js"; +import { EventBus } from "@/eventBus"; +import { ElMessage } from 'element-plus'; +const emit = defineEmits(["timeUpdate", "isPlaying", "playbackFinished"]); +// 瀹氫箟props const props = defineProps({ waterSimulateParams: { type: Object, @@ -92,229 +72,145 @@ }), }, }); + // 鍝嶅簲寮忕姸鎬� +const currentPlayingTime = ref(""); // 褰撳墠鎾斁鏃堕棿 const isPlaying = ref(false); const playbackFinished = ref(true); const currentTime = ref(0); -const duration = ref(86400); // 涓�澶╃殑绉掓暟 -const playbackRate = ref(1); +const duration = ref(60); // 涓�澶╃殑绉掓暟 +const playbackRate = ref(8); const playbackRates = ref([1, 2, 4, 8]); const showSpeedMenu = ref(false); - -const timeMarkers = ref([ - "00:00", - "03:19", - "06:39", - "09:59", - "13:19", - "16:39", - "19:59", - "23:19", -]); +const waterTimestamps = ref([]); // 瀛樺偍鏃堕棿杞存暟鎹� +const timeMarkers = ref([]); const timelineTrack = ref(null); -const startDate = computed(() => { - return dayjs(props.waterSimulateParams.date[0]); -}); -const endDate = computed(() => { - return dayjs(props.waterSimulateParams.date[1]); -}); let playInterval = null; // 璁$畻灞炴�� -const progressPercentage = computed(() => { - return (currentTime.value / duration.value) * 100; -}); +const startDate = computed(() => dayjs(props.waterSimulateParams.date[0])); +const endDate = computed(() => dayjs(props.waterSimulateParams.date[1])); +const progressPercentage = computed(() => (currentTime.value / duration.value) * 100); +const visibleDates = computed(() => + Array.from( + new Set(waterTimestamps.value.map((ts) => dayjs(ts).format("YYYY-MM-DD"))) + ).map((date) => dayjs(date).toDate()) +); +const currentTimeFormatted = computed(() => formatTime(currentTime.value)); -const visibleDates = computed(() => { - // 鐢熸垚鏃堕棿杞翠笂鏄剧ず鐨勬棩鏈� - const dates = []; - const currentDateValue = dayjs(startDate.value); - const endDateValue = dayjs(endDate.value); - - // let tempDate = currentDateValue - // while (tempDate.isSame(endDateValue) || tempDate.isBefore(endDateValue)) { - // dates.push(tempDate.toDate()) - // tempDate = tempDate.add(1, 'day') - // } - - return [currentDateValue, endDateValue]; -}); - -const currentTimeFormatted = computed(() => { - return formatTime(currentTime.value); -}); - +// 鎾斁鎺у埗 const togglePlay = () => { // 濡傛灉褰撳墠鏄仠姝㈢姸鎬佷笖宸茬粡鎾斁瀹屾瘯锛岀偣鍑绘椂閲嶇疆鏃堕棿 - if (!isPlaying.value && currentTime.value >= duration.value) { - currentTime.value = 0; - emit("timeUpdate", progressPercentage.value); - // earthCtrl.environment.disableEffect("rain"); - } - + if (!isPlaying.value && currentTime.value >= duration.value) currentTime.value = 0; isPlaying.value = !isPlaying.value; emit("isPlaying", isPlaying.value); - if (isPlaying.value) { startPlayback(); // 濡傛灉鏄粠澶村紑濮嬫挱鏀� - if (currentTime.value === 0) { - emit("playbackFinished", false); - } - } else { - stopPlayback(); - } + if (currentTime.value === 0) emit("playbackFinished", false); + } else stopPlayback(); }; - +const intervalMap = { + 1: 1000, // 1鍊嶉�� + 2: 500, // 2鍊嶉�� + 4: 250, // 4鍊嶉�� + 8: 125, // 8鍊嶉�� +}; const startPlayback = () => { - // earthCtrl.environment.showEffect("rain"); + // 鏍规嵁褰撳墠鍊嶉�熻幏鍙栧搴旂殑 interval + const interval = intervalMap[playbackRate.value] || 1000; // 榛樿涓�1000 + // 璋冪敤 createWaterPrimitive 骞朵紶閫� interval + createWaterPrimitive({ interval }); clearInterval(playInterval); playInterval = setInterval(() => { - currentTime.value += 600 * playbackRate.value; - // emit("playbackFinished", true); - + // 璁$畻姣忔澧炲姞鐨勬椂闂撮噺 + const timeIncrement = playbackRate.value; // 鍊嶉�熺洿鎺ヤ綔涓哄閲� + currentTime.value += timeIncrement; + // 濡傛灉瓒呰繃鎬绘椂闀匡紝鍒欏仠姝㈡挱鏀� if (currentTime.value >= duration.value) { - emit("playbackFinished", false); - currentTime.value = duration.value; // 鍋滃湪鏈�鍚庝竴甯� - stopPlayback(); // 鍋滄鎾斁 - isPlaying.value = false; // 鏇存柊鎾斁鐘舵�� - emit("isPlaying", isPlaying.value); // 閫氱煡鎾斁鐘舵�佸彉鍖� - emit("playbackFinished", true); // 閫氱煡鎾斁瀹屾垚 - emit("timeUpdate", progressPercentage.value); // 鏇存柊杩涘害鏉′綅缃� + stopPlayback(); + isPlaying.value = false; + emit("isPlaying", false); + emit("playbackFinished", true); } - + // 瑙﹀彂鏃堕棿鏇存柊浜嬩欢 emit("timeUpdate", progressPercentage.value); - }, 1000); + }, 1000); // 姣忕鏇存柊涓�娆� }; -const stopPlayback = () => { - // earthCtrl.environment.disableEffect("rain"); - clearInterval(playInterval); -}; - -const skipForward = () => { - // 鍚戝墠璺宠浆10鍒嗛挓 - currentTime.value = Math.min(currentTime.value + 600, duration.value); - emit("timeUpdate", progressPercentage.value); -}; - -const skipBackward = () => { - // 鍚戝悗璺宠浆10鍒嗛挓 - currentTime.value = Math.max(currentTime.value - 600, 0); - emit("timeUpdate", progressPercentage.value); -}; - -const toggleSpeedMenu = () => { - showSpeedMenu.value = !showSpeedMenu.value; -}; - +const stopPlayback = () => clearInterval(playInterval); +const skipForward = () => (currentTime.value = Math.min(currentTime.value + 1, duration.value)); // 鍚戝墠璺宠浆1绉� +const skipBackward = () => (currentTime.value = Math.max(currentTime.value - 1, 0)); // 鍚戝悗璺宠浆1绉� +const toggleSpeedMenu = () => (showSpeedMenu.value = !showSpeedMenu.value); const setPlaybackRate = (rate) => { playbackRate.value = rate; showSpeedMenu.value = false; - - if (isPlaying.value) { - stopPlayback(); - startPlayback(); - } + if (isPlaying.value) stopPlayback(), startPlayback(); // 濡傛灉姝e湪鎾斁锛屽垯閲嶆柊鍚姩浠ュ簲鐢ㄦ柊鐨勯�熺巼 }; - -const formatTime = (seconds) => { - const hours = Math.floor(seconds / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - const secs = Math.floor(seconds % 60); - - return `${hours.toString().padStart(2, "0")}:${minutes - .toString() - .padStart(2, "0")}:${secs.toString().padStart(2, "0")}`; -}; - -const formatDate = (date) => { - return dayjs(date).format("YYYY-MM-DD"); -}; - const seekToPosition = (event) => { const rect = timelineTrack.value.getBoundingClientRect(); - const clickPosition = event.clientX - rect.left; - const percentage = clickPosition / rect.width; - - currentTime.value = percentage * duration.value; + const percentage = (event.clientX - rect.left) / rect.width; + currentTime.value = Math.round(percentage * duration.value); emit("timeUpdate", progressPercentage.value); + if (waterTimestamps.value.length > 0) { + const clickedTimestamp = dayjs(waterTimestamps.value[0]).add(currentTime.value, "second"); + console.log("Clicked timestamp:", clickedTimestamp.valueOf(), clickedTimestamp.format("YYYY-MM-DD HH:mm:ss")); + } }; - -const rainFallData = ref([]); -function getRainfallData() { - getRainfall().then((res) => { - // rainFallData.value = res.data.map(item => { - // return dayjs(item.time).format("HH:mm") - // }) - - // const rainfallData = res.data.map(item => { - // return item.rainfall - // }) - rainFallData.value = res.data; - }); -} - -let mockTimer = null; -let currentRainfall = ref(0.0001); -function randomMockWater() { - let delay = (3 / playbackRate.value) * 1000; - if (delay < 1000) { - delay = 1000; +watch(() => currentTime.value, () => { + if (waterTimestamps.value.length > 0) { + currentPlayingTime.value = dayjs(waterTimestamps.value[0]) + .add(currentTime.value, "second") + .format("YYYY-MM-DD mm:ss"); } - if (mockTimer) { - clearImmediate(mockTimer); - mockTimer = null; - } - mockTimer = setTimeout(() => { - const rainfall = rainFallData.value.find( - (item) => - dayjs(item.time).format("HH:mm:ss") == currentTimeFormatted.value - ); - if (rainfall && rainfall.total) { - // console.log(rainfall.total); - - createWaterPrimitive(rainfall.total / 50000); - } - }, delay); -} -watch( - () => currentTime.value, - () => { - randomMockWater(); - } -); - -// 瀹氫箟缁勪欢浜嬩欢 -const emit = defineEmits(["timeUpdate", "isPlaying", "playbackFinished"]); - -// 鍒濆鍖栨椂瑙﹀彂涓�娆℃椂闂存洿鏂帮紝纭繚鐖剁粍浠惰兘鑾峰彇鍒濆鏃堕棿 -onMounted(() => { - getRainfallData(); - emit("timeUpdate", progressPercentage.value); }); +// 鏃堕棿鏍囪鐢熸垚 +function generateTimeMarkers(timestamps) { + if (!timestamps || timestamps.length === 0) return []; + const sorted = [...timestamps].sort((a, b) => dayjs(a).diff(dayjs(b))); + const interval = Math.floor(dayjs(sorted.at(-1)).diff(dayjs(sorted[0]), "second") / 7); + return Array.from({ length: 8 }, (_, i) => dayjs(sorted[0]).add(i * interval, "second").format("mm:ss")); +} +watch(() => waterTimestamps.value, (newTimestamps) => { + if (newTimestamps.length > 0) timeMarkers.value = generateTimeMarkers(newTimestamps); +}, { immediate: true }); + +onMounted(async () => { + try { + const { waterTimestamps: timestamps } = await fetchWaterSimulationData(); + if (timestamps) { + waterTimestamps.value = timestamps; + updateTimelineRange(); + timeMarkers.value = generateTimeMarkers(timestamps); + currentPlayingTime.value = dayjs(timestamps[0]).format("YYYY-MM-DD HH:mm:ss"); + } + } catch (error) { + console.error("Error loading water simulation data:", error); + } +}); + +function updateTimelineRange() { + if (waterTimestamps.value.length > 0) { + const [first, last] = [waterTimestamps.value[0], waterTimestamps.value.at(-1)]; + props.waterSimulateParams.date = [dayjs(first).toISOString(), dayjs(last).toISOString()]; + duration.value = dayjs(last).diff(dayjs(first), "second"); + console.log("Updated timeline range:", { ...props.waterSimulateParams, duration: duration.value }); + } +} onBeforeUnmount(() => { stopPlayback(); - let delay = (3 / playbackRate.value) * 1000; - - setTimeout(() => { - destoryWaterPrimitive(); - }, delay); + destoryWaterPrimitive(); }); -const { startSimulate, endSimulate } = inject("simulateActions"); -// 杩斿洖鎸夐挳鐐瑰嚮浜嬩欢 +const { endSimulate } = inject("simulateActions"); function handleBack() { - ElMessage({ - message: '妯℃嫙杩涚▼姝e湪鍏抽棴涓�...', - type: 'success', - }) + ElMessage({ message: '妯℃嫙杩涚▼姝e湪鍏抽棴涓�...', type: 'success' }); // 鏄剧ず娑堟伅閫氱煡鐢ㄦ埛妯℃嫙杩涚▼姝e湪鍏抽棴 endSimulate(); + destoryWaterPrimitive(); EventBus.emit("hide-schemeInfo"); } </script> - <style scoped> .timeline-container { display: flex; @@ -395,7 +291,7 @@ } .speed-menu div { - padding: 5px 10px; + /* padding: 5px 5px; */ text-align: center; } @@ -406,7 +302,7 @@ } .timeline { - margin-top: 20px; + margin-top: 10px; position: relative; flex: 1; } @@ -460,8 +356,16 @@ } .time-marker { + margin-top: 5px; font-size: 12px; color: #fff; - transform: translateX(-50%); + transform: translateX(-20%); +} + +.current-date { + margin-bottom: 5px; + font-size: 15px; + color: #fff; + transform: translateX(-3%); } </style> -- Gitblit v1.9.3