public/CimSDK/Workers/image/richtextpoint1.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/trApi.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/上传.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/发起请求.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/已上传.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/已断面.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/已流速.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/断面.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/流速.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/流速1.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/img/timeline/确认.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/menu/CrossSectionalAnalysis.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/menu/TimeLine.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/menu/flowRate_waterLevel.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
public/CimSDK/Workers/image/richtextpoint1.pngsrc/api/trApi.js
@@ -122,11 +122,25 @@ throw new Error(`HTTP error! status: ${response.status}`); } const jsonData = await response.json(); // è§£æ JSON æ°æ® console.log(jsonData,'jsonjsonjsonjson') console.log(jsonData, "jsonjsonjsonjson"); return parseWaterSimulationData(jsonData); // è°ç¨è§£æå½æ° } catch (error) { console.error("è¯·æ±æè§£ææ°æ®æ¶åºé:", error); return null; } } // è·åæ°´ä½æ°´æ·± export async function getFlowRate(data) { // console.log(data,'åéçæ°æ®ï¼'); try { const res = await instance.get("/simu/position", { params: data }); return res.data; // è¿åå®é æ°æ®ï¼é常 res.data ææ¯æ¥å£è¿åçå å®¹ï¼ } catch (error) { console.error("Error fetching data:", error); throw error; // æåºé误ï¼è®©è°ç¨æ¹å¯ä»¥æè· } } // ************************************************************************************************************** src/assets/img/timeline/ÉÏ´«.png
src/assets/img/timeline/·¢ÆðÇëÇó.png
src/assets/img/timeline/ÒÑÉÏ´«.png
src/assets/img/timeline/ÒѶÏÃæ.png
src/assets/img/timeline/ÒÑÁ÷ËÙ.png
src/assets/img/timeline/¶ÏÃæ.png
src/assets/img/timeline/Á÷ËÙ.pngsrc/assets/img/timeline/Á÷ËÙ1.png
src/assets/img/timeline/È·ÈÏ.png
src/components/menu/CrossSectionalAnalysis.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,170 @@ <template> <div style="display: flex; justify-content: space-between;"> <div @click="initPickHandler"> <img v-if="!isPicking" src="@/assets/img/timeline/æé¢.png" style="width: 26px;height: 26px;" /> <img v-else src="@/assets/img/timeline/å·²æé¢.png" style="width: 26px;height: 26px;" /> </div> <div @click="confirmPoints"> <img v-if="!isUploaded" src="@/assets/img/timeline/ä¸ä¼ .png" style="width: 26px;height: 26px;" /> <img v-else src="@/assets/img/timeline/å·²ä¸ä¼ .png" style="width: 26px;height: 26px;" /> </div> <div @click="clearPoints"> <img src="@/assets/img/timeline/æ¸ é¤.png" style="width: 26px;height: 26px;" /> </div> </div> </template> <script setup> import { ElMessage } from 'element-plus'; import { ref, onMounted ,defineExpose } from "vue"; const viewer = window.viewer; let pickedPointsCross = ref([]); let pickHandlerCross = null; let isWallCreated = ref(false); // æ°å¢ç¶æåéï¼æ è®°å¢ä½æ¯å¦å·²å建 let isPicking = ref(false); // æ¯å¦æ£å¨æ¾åç¹ const isUploaded = ref(false); // æ§å¶æ¯å¦å·²ä¸ä¼ // è·åæé¢åæ function getPickPosition(windowPosition) { if (!viewer) return null; const cartesian = viewer.scene.pickPosition(windowPosition); if (!cartesian) return null; const cartographic = Cesium.Cartographic.fromCartesian(cartesian); const longitude = Cesium.Math.toDegrees(cartographic.longitude); const latitude = Cesium.Math.toDegrees(cartographic.latitude); const terrainHeight = viewer.scene.globe.getHeight(cartographic); if (!terrainHeight) return null; const positionWithTerrainHeight = Cesium.Cartesian3.fromRadians( cartographic.longitude, cartographic.latitude, terrainHeight ); return { cartesian: positionWithTerrainHeight, longitude, latitude }; } // éå两个æé¢ç¹åæ å¹¶ç»å¶æé¢æªé¢ function addPointToViewer(point) { if (pickedPointsCross.value.length >= 2) { clearPoints(); } pickedPointsCross.value.push(point); drawPointOnMap(point); if (pickedPointsCross.value.length === 2) { // ElMessage.success('å½å两ç¹åæ å·²éåå®æï¼æ£å¨çææé¢æªé¢ï¼'); drawWall(pickedPointsCross.value[0], pickedPointsCross.value[1]); isWallCreated.value = true; // 设置为已å建å¢ä½ } } let pickedEntitiesIds = ref([]); // ç¨äºåå¨å建çç¹åå¢çID // ç»å¶ä¸¤ä¸ªæé¢ç¹åæ ï¼å¹¶è®°å½å ¶ID function drawPointOnMap(point) { const entity = viewer.entities.add({ position: point.cartesian, point: { color: Cesium.Color.RED, outlineColor: Cesium.Color.YELLOW, outlineWidth: 2, pixelSize: 8 // åç¹åå¾å¤§å° } }); pickedEntitiesIds.value.push(entity.id); // è®°å½å®ä½ID } // å建æé¢æªé¢ï¼å¹¶è®°å½å ¶ID function drawWall(startPoint, endPoint) { const entity = viewer.entities.add({ wall: { positions: [startPoint.cartesian, endPoint.cartesian], material: Cesium.Color.YELLOW, heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, } }); pickedEntitiesIds.value.push(entity.id); // è®°å½å®ä½ID } // ä¿®æ¹åçæ¸ é¤å½æ°ï¼åªæ¸ é¤å建çç¹åå¢ function clearPoints() { for (const id of pickedEntitiesIds.value) { viewer.entities.remove(viewer.entities.getById(id)); } pickedPointsCross.value = []; pickedEntitiesIds.value = []; isWallCreated.value = false; isUploaded.value = false; } // æ¾åç¹åæ ç¶åç»ç¹ï¼ç®åçï¼ function initPickHandler() { // åæ¢ç¶æï¼å¦æä¹å卿¾åï¼è¿æ¬¡å°±æ¯åæ¶æ¾å if (isPicking.value) { if (pickHandlerCross) { pickHandlerCross.destroy(); pickHandlerCross = null; } isPicking.value = false; isUploaded.value = false; ElMessage.info('å·²å ³é--æé¢æªé¢--æ¾åç¹åæ åè½ï¼'); return; } // è¿å ¥æ¾åæ¨¡å¼ ElMessage.success(`å¼å§--æé¢æªé¢--æ¾ååæ åè½ï¼è¯·ç¹å»å°å¾éæ©ç¹ä½ï¼éåå®è¯·åæ¶å ³éï¼é¿å å½±åå ¶ä»åè½ï¼`); isPicking.value = true; if (!viewer?.scene?.canvas) return; // 鿝æ§ç handler if (pickHandlerCross) { pickHandlerCross.destroy(); pickHandlerCross = null; } // åå»ºæ° handler pickHandlerCross = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); const clickAction = (movement) => { const position = getPickPosition(movement.position); if (position) { addPointToViewer(position); } }; pickHandlerCross.setInputAction(clickAction, Cesium.ScreenSpaceEventType.LEFT_CLICK); } // 确认æé®ç¹å»äºä»¶,åé请æ±è°ç¨æ¥å£ function confirmPoints() { if (pickedPointsCross.value.length < 2) { ElMessage.warning('请å éæ©ä¸¤ä¸ªç¹ååè¿è¡ç¡®è®¤ï¼'); return; } const point1 = pickedPointsCross.value[0]; const point2 = pickedPointsCross.value[1]; console.log('第ä¸ä¸ªç¹ä¿¡æ¯ï¼', { longitude: point1.longitude, latitude: point1.latitude, cartesian: point1.cartesian }); console.log('第äºä¸ªç¹ä¿¡æ¯ï¼', { longitude: point2.longitude, latitude: point2.latitude, cartesian: point2.cartesian }); isUploaded.value = true; // 设置为已ä¸ä¼ ç¶æ ElMessage.success('æ£å¨è¿è¡--æé¢æªé¢--æ°æ®åæä¸ä¼ ï¼è¯·ç¨ç...'); } defineExpose({ clearPoints }); </script> 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> @@ -35,33 +25,18 @@ <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> @@ -70,36 +45,24 @@ <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> <ratelevel ref="ratelevelRef" :playing-time="sendCurrentPlayingTime" @finish-calculation="handleFinishCalculation" style=" margin-top: 12px; margin-left: 28px; margin-right: 10px; justify-content: flex-end; " ></ratelevel> <el-button @click="handleBack" style="margin-top: 3px; margin-left: 30px; margin-right: 10px" >ç»ææ¨¡æ</el-button > <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;" /> --> </div> <el-button @click="handleBack" style="margin-top: 3px; margin-left: 28px; margin-right: 10px;width: 75%;height: 30%;">ç»ææ¨¡æ</el-button> </div> </div> </template> @@ -112,9 +75,10 @@ defineProps, onBeforeUnmount, inject, reactive, reactive } from "vue"; import ratelevel from "@/components/menu/flowRate_waterLevel.vue"; import crossanalysis from "@/components/menu/CrossSectionalAnalysis.vue"; import dayjs from "dayjs"; import { @@ -135,12 +99,7 @@ const simStore = useSimStore(); const { selectedScheme } = storeToRefs(simStore); const emit = defineEmits([ "timeUpdate", "isPlaying", "playbackFinished", "isColorRender", ]); const emit = defineEmits(["timeUpdate", "isPlaying", "playbackFinished", "isColorRender"]); // å®ä¹props const props = defineProps({ waterSimulateParams: { @@ -153,6 +112,7 @@ // ååºå¼ç¶æ let serviceInfo = ref(null); // å½åæ¹æ¡çæå¡å°å const ratelevelRef = ref(null); // è·ååç»ä»¶å®ä¾çå¼ç¨ const crossRef = ref(null); // è·ååç»ä»¶å®ä¾çå¼ç¨ const currentPlayingTime = ref(""); // å½åææ¾æ¶é´ const sendCurrentPlayingTime = ref(""); // å½åææ¾æ¶é´ const isPlaying = ref(false); @@ -173,7 +133,7 @@ rainSize: 0.5, rainSpeed: 50, rainColor: "#99B3CC", rainDensity: 30, // é¨çå¯åº¦ rainDensity: 30 // é¨çå¯åº¦ }); // 计ç®å±æ§ const progressPercentage = computed( @@ -203,7 +163,7 @@ baseUrl: `/simu/${serviceInfo}`, // baseUrl: `/simu/c2h1dc`, interval: intervalMap[playbackRate.value], colorRender: isColorRenderEnabled.value, colorRender: isColorRenderEnabled.value }); isWaterPrimitiveCreated.value = true; } else { @@ -237,8 +197,8 @@ return; // 黿¢åç»é»è¾æ§è¡ } if (isWaterPrimitiveCreated.value) { console.log("å½åæ¯å¦å¼å¯ä¸é¢æ¸²æï¼", enabled); emit("isColorRender", enabled); console.log('å½åæ¯å¦å¼å¯ä¸é¢æ¸²æï¼', enabled); emit("isColorRender", enabled) toggleWaterColorRender(enabled); } }; @@ -292,112 +252,103 @@ // 注æï¼ææ¶ data å¯è½æ¯ä¸ä¸ªå符串ï¼ä¾å¦ JSON åç¬¦ä¸²ï¼ let data = selectedScheme.value.data; // 妿æ¯å符串ï¼åå°è¯è§£ææå¯¹è±¡ if (typeof data === "string") { if (typeof data === 'string') { try { data = JSON.parse(data); console.log("è§£æåçé鍿°æ®ï¼", data); console.log('è§£æåçé鍿°æ®ï¼', 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: 40, density: 35, color: "#ADD8E6", color: '#ADD8E6' }, { name: "大é¨", name: '大é¨', min: 25, max: 49.9, size: 1.0, speed: 70, density: 60, color: "#ADD8E6", color: '#ADD8E6' }, { name: "æ´é¨", name: 'æ´é¨', min: 50, max: 99.9, size: 1.3, speed: 90, density: 80, color: "#ADD8E6", color: '#ADD8E6' }, { name: "大æ´é¨", name: '大æ´é¨', min: 100, size: 1.6, speed: 110, density: 100, 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.5, speed: 30, density: 20, color: "#F0F8FF" }; return { name: 'æ é¨', size: 0.5, speed: 30, density: 20, color: '#F0F8FF' }; } // æ ¹æ®ææ¾è¿åº¦æ´æ°å¤©æ°ææï¼å·²ä¼åï¼ let lastUsedIndex = -1; // ç¼åä¸ä¸æ¬¡ä½¿ç¨çç´¢å¼ï¼é²æ¢é夿´æ° let lastRainValue = null; function updateWeatherByProgress() { if (rainFallValues.value.length === 0) return; console.log( `æ¶é´è½´æ»æ¶é¿: ${duration.value}, å½åæ¶é´: ${currentTime.value}` ); // æå°æ¶é´è½´ä¿¡æ¯ // 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]; @@ -408,7 +359,7 @@ // console.log(`æ£å¨å¤ççé¨éæ°æ®ç¹: å½å=${currentRain}, ä¸ä¸ä¸ª=${nextRain}, æå¼å=${rainValue.toFixed(2)}, ç´¢å¼=${index}`); // 妿å½åç´¢å¼æªåå䏿å¼å·®å¼ä¸å¤§ï¼è·³è¿é夿´æ° if (index === lastUsedIndex && Math.abs(rainValue - lastRainValue) < 0.1) { console.log("ç±äºæ°æ®æ æ¾èååï¼è·³è¿æ¬æ¬¡æ´æ°"); // console.log('ç±äºæ°æ®æ æ¾èååï¼è·³è¿æ¬æ¬¡æ´æ°'); return; } @@ -418,10 +369,10 @@ // è·å对åºçé¨å½¢é ç½® const rainLevel = getRainLevel(rainValue); if (rainLevel.name === "æ é¨") { if (rainLevel.name === 'æ é¨') { // æ é¨ç¶æï¼æ¸ é¤é¨æ mapUtils.delRain(); console.log("æ§è¡äºæ é¨ç¶æï¼æ¸ é¤äºé¨æ"); console.log('æ§è¡äºæ é¨ç¶æï¼æ¸ é¤äºé¨æ'); return; } @@ -430,9 +381,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); } @@ -469,7 +420,7 @@ // è®¾ç½®ææ¾éç const setPlaybackRate = (rate) => { isColorRenderEnabled.value = false; isColorRenderEnabled.value = false playbackRate.value = rate; showSpeedMenu.value = false; // 忢å½åææ¾ @@ -509,8 +460,7 @@ // ç´æ¥æ¾å°æè¿ç 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); @@ -542,7 +492,7 @@ () => selectedScheme.value, (newVal) => { if (newVal) { console.log("é䏿¹æ¡å·²æ¹å:", newVal); console.log('é䏿¹æ¡å·²æ¹å:', newVal) } } ); @@ -555,9 +505,7 @@ .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); } } @@ -592,17 +540,15 @@ const schemeInfo = selectedScheme.value; serviceInfo = schemeInfo.serviceName; // console.log('è·åå°ç serviceName:', serviceInfo); getRainfallData(); getRainfallData() // æ ¹æ®layer.jsonå»è·åæ¶é´è½´ä¿¡æ¯ const { waterTimestamps: timestamps } = await fetchWaterSimulationData( serviceInfo ); const { waterTimestamps: timestamps } = await fetchWaterSimulationData(serviceInfo); // ç°å¨æ¯æç §æ»å ±æå¤å°ä¸ªç¹æ¥æ¸²ææ¶é´è½´ if (timestamps) { 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" ); @@ -634,10 +580,13 @@ const { endSimulate } = inject("simulateActions"); function handleBack() { endSimulate(); EventBus.emit("close-selectArea"); isWaterPrimitiveCreated.value = false; if (ratelevelRef.value) { ratelevelRef.value.endCalculation(); ratelevelRef.value.stopPicking(); } if (crossRef.value) { crossRef.value.clearPoints(); } emit("isColorRender", false); setTimeout(() => { @@ -658,7 +607,7 @@ left: 50%; transform: translateX(-50%); z-index: 99; width: 38%; width: 44%; height: 10%; /* background-color: #1a2634; */ background: url("@/assets/img/menubar/bar.png"); @@ -741,7 +690,7 @@ .timeline { margin-top: 10px; position: relative; flex: 1; flex: 0.9; } .dates { src/components/menu/flowRate_waterLevel.vue
@@ -2,15 +2,9 @@ <div style="display: flex;justify-content: space-between;"> <!-- éç¹æé® --> <div @click="togglePick" :class="['pick-button', { active: isPickingActive }]"> <img src="@/assets/img/timeline/åæ .png" style="width: 26px;height: 26px;" /> <!-- <span v-if="isPickingActive">忢æ¾å</span> <span v-else>å¼å§æ¾å</span> --> <img v-if="!isPickingActive" src="@/assets/img/timeline/æµé.png" style="width: 28px;height: 28px;" /> <img v-else src="@/assets/img/timeline/å·²æµé.png" style="width: 28px;height: 28px;" /> </div> <!-- å¼å§è®¡ç®æé® --> <!-- <div @click="startCalculation"> <img src="@/assets/img/timeline/æ°´ä½.png" style="margin-top: -4px;width: 34px;height: 34px;" /> </div> --> <!-- ç»æè®¡ç®æé® --> <div @click="endCalculation"> <img src="@/assets/img/timeline/æ¸ é¤.png" style="width: 26px;height: 26px;" /> </div> @@ -20,11 +14,17 @@ <script setup> import { defineProps, watch, ref, onMounted, defineExpose } from "vue"; import { ElMessage } from 'element-plus'; import { getFlowRate } from "@/api/trApi.js"; import { useSimStore } from "@/store/simulation"; import { storeToRefs } from "pinia"; const simStore = useSimStore(); const { selectedScheme } = storeToRefs(simStore); const pickedPoints = ref([]); const handler = ref(null); const isPickingActive = ref(false); const currentTime = ref(0); let serviceInfo = ref(null); const props = defineProps({ playingTime: { @@ -33,14 +33,6 @@ } }); watch( () => props.playingTime, (newVal) => { currentTime.value = newVal; }, { immediate: true } ); // Cesium viewer åå§åç¸å ³é»è¾ const viewer = window.viewer; function getPickPosition(windowPosition) { @@ -59,13 +51,15 @@ } function addPointToViewer(point, index) { const displayTime = currentTime.value || "æªè®¾ç½®æ¶é´"; const schemeInfo = selectedScheme.value; serviceInfo = schemeInfo.serviceName; // æ·»å æ ç¾ï¼ç¡®ä¿å®ä½å建æ¶å å«label屿§ï¼ // å建 label å®ä½ const labelEntity = viewer.entities.add({ position: point.cartesian, label: { text: `æµéç¹ ${index + 1}\nç»åº¦: ${point.longitude.toFixed(6)}\n纬度: ${point.latitude.toFixed(6)}\næ¶é´: ${displayTime}`, font: '14pt monospace', text: `æµéç¹ ${pickedPoints.value.length + 1}\næ°´æ·±: çå¾ å¯å¨...\næµé: çå¾ å¯å¨...`, font: 'bold 14pt monospace', style: Cesium.LabelStyle.FILL_AND_OUTLINE, fillColor: Cesium.Color.YELLOW, outlineColor: Cesium.Color.BLACK, @@ -77,29 +71,38 @@ showBackground: true, scale: 1, distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000), pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.3) pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.3), } }); const groundPosition = Cesium.Cartesian3.fromRadians( point.longitude * Math.PI / 180, point.latitude * Math.PI / 180, 0 ); const cylinderEntity = viewer.entities.add({ position: groundPosition, // åºé¨ä½ç½® cylinder: { length: 190.0, topRadius: 1.0, bottomRadius: 1.0, material: Cesium.Color.YELLOW, outline: true, outlineColor: Cesium.Color.YELLOW, slices: 32, heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND, distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000) } }); // æ·»å åç´çº¿ const lineEntity = viewer.entities.add({ polyline: { positions: [point.cartesian, Cesium.Cartesian3.fromRadians(point.longitude * Math.PI / 180, point.latitude * Math.PI / 180, 0)], width: 2, material: new Cesium.PolylineOutlineMaterialProperty({ color: Cesium.Color.RED.withAlpha(0.8), outlineColor: Cesium.Color.WHITE, outlineWidth: 4 }), distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 5000), pixelOffsetScaleByDistance: new Cesium.NearFarScalar(100, 1.0, 5000, 0.3) } // è¯·æ±æ°æ®å¹¶æ´æ° label getFlowRateInfo(point.longitude, point.latitude, displayTime).then(result => { updateLabel(pickedPoints.value.length - 1, result.depth, result.velocity); }); // ä¿å labelEntity å lineEntity // åå¨å®ä½å¼ç¨ pickedPoints.value.push({ labelEntity, lineEntity, cylinderEntity, // 使ç¨åæ±ä»£æ¿ line å circle longitude: point.longitude, latitude: point.latitude }); @@ -107,13 +110,11 @@ function initPickHandler() { if (!viewer?.scene?.canvas) return; if (handler.value) { handler.value.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); handler.value.destroy(); handler.value = null; } handler.value = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); handler.value.setInputAction((movement) => { @@ -121,21 +122,20 @@ if (position) { const index = pickedPoints.value.length; addPointToViewer(position, index); console.log('æ§è¡å ç¹å·¥ä½'); } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); } function startPicking() { // pickedPoints.value = []; // viewer.entities.removeAll(); if (!handler.value) { initPickHandler(); // åªæç¬¬ä¸æ¬¡æåå§å initPickHandler(); } isPickingActive.value = true; ElMessage.success('å¼å§æ¾ååæ ï¼è¯·ç¹å»å°å¾éæ©ç¹ä½ï¼'); ElMessage.success(`å¼å§--æµéæµé--æ¾ååæ åè½ï¼è¯·ç¹å»å°å¾éæ©ç¹ä½ï¼éåå®è¯·åæ¶å ³éï¼é¿å å½±åå ¶ä»åè½ï¼`); } function stopPicking() { if (handler.value) { handler.value.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); @@ -147,61 +147,76 @@ function togglePick() { if (isPickingActive.value) { stopPicking(); // è°ç¨ stopPicking æ¥æ£ç¡®å°åæ¢éåè¿ç¨ isPickingActive.value = false; // ç¡®ä¿ isPickingActive 设置为 false ElMessage.success('å½ååæ å·²éåå®æï¼æ°´ä½æµéæµéåå¤å®æ¯ï¼'); stopPicking(); isPickingActive.value = false; ElMessage.info('å·²å ³é--æµéæµé--æ¾åç¹åæ åè½ï¼'); console.log(pickedPoints.value, 'æç»éåçç¹'); } else { startPicking(); isPickingActive.value = true; // å¨å¼å§éåå设置为 true isPickingActive.value = true; } } // å½ currentTime æ¹åæ¶æ´æ°ææç¹ç label ä¸çæ¶é´æ³ // ä¿®æ¹watché»è¾ watch( () => props.playingTime, (newVal) => { currentTime.value = newVal || "æªè®¾ç½®æ¶é´"; updateAllLabels(); async (newVal, oldVal) => { if (newVal !== oldVal) { currentTime.value = newVal || "æªè®¾ç½®æ¶é´"; await updateAllLabels(); } }, { immediate: true } ); function updateAllLabels() { pickedPoints.value.forEach((pointInfo, index) => { if (pointInfo.labelEntity && pointInfo.labelEntity.label) { pointInfo.labelEntity.label.text = `æµéç¹ ${index + 1}\nç»åº¦: ${pointInfo.longitude.toFixed(6)}\n纬度: ${pointInfo.latitude.toFixed(6)}\næ¶é´: ${currentTime.value}`; } }); async function updateAllLabels() { for (const pointInfo of pickedPoints.value) { if (!pointInfo || !pointInfo.labelEntity) continue; const result = await getFlowRateInfo(pointInfo.longitude, pointInfo.latitude, currentTime.value); updateLabel(pointInfo, result.depth, result.velocity); } } function startCalculation() { console.log('éåçåæ ç¹ï¼', pickedPoints.value); console.log(`å½åæ¶é´ï¼${currentTime.value}`); function updateLabel(pointInfo, depth, velocity) { if (pointInfo.labelEntity && pointInfo.labelEntity.label) { pointInfo.labelEntity.label.text = ` æµéç¹ ${pickedPoints.value.findIndex(p => p === pointInfo) + 1} æ°´æ·±: ${depth} m æµé: ${velocity} m/s `.trim(); } } function endCalculation() { // console.log('ç±æ¬åè½åå»ºçææ label å polyline entities:'); // pickedPoints.value.forEach((pointInfo, index) => { // console.log(`æµéç¹ ${index + 1}:`); // console.log('Label Entity:', pointInfo.labelEntity); // console.log('Polyline Entity:', pointInfo.lineEntity); // }); // console.log('å½å Cesium 䏿æå®ä½å表:'); // viewer.entities.values.forEach((entity, idx) => { // console.log(`å®ä½ #${idx}:`, entity); // }); pickedPoints.value.forEach(pointInfo => { if (pointInfo.labelEntity) viewer.entities.remove(pointInfo.labelEntity); if (pointInfo.lineEntity) viewer.entities.remove(pointInfo.lineEntity); if (pointInfo.cylinderEntity) viewer.entities.remove(pointInfo.cylinderEntity); }); pickedPoints.value = []; } defineExpose({ endCalculation endCalculation, stopPicking }); function getFlowRateInfo(lon, lat, time) { const params = { lon: lon, lat: lat, time: time, serviceName: serviceInfo }; return getFlowRate(params).then(data => { // console.log('è·åå°çæ°æ®:', data); if (data && data.code === 200) { return { depth: data.data.depth.toFixed(2), velocity: data.data.velocity.toFixed(2) }; } else { return { depth: 'N/A', velocity: 'N/A' }; } }).catch(error => { console.error('è·åæ°æ®æ¶åçé误:', error); return { depth: 'N/A', velocity: 'N/A' }; }); } </script> <style lang="less" scoped></style>