wangjuncheng
2025-05-15 f16045cde17854377084335c478e3cae0d08d6b8
change
已添加6个文件
已修改8个文件
595 ■■■■ 文件已修改
src/api/trApi.js 2 ●●● 补丁 | 查看 | 原始文档 | 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/components/menu/TimeLine.vue 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/menu/flowRate_waterLevel.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/monifangzhen/schemeInfo.vue 150 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tools/Legend_mnfz.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tools/Legend_yhgl.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/tools/Legend_zhjc.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/water.js 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/GisView.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mnfz.vue 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/trApi.js
@@ -94,7 +94,7 @@
// é€šè¿‡æŽ¥å£åŽ»è¯·æ±‚json,将请求的json解析获取泥石流参数
export async function fetchWaterSimulationData() {
  try {
    const response = await fetch("/simu/c2h1dc/layer.json"); // å‘起请求
    const response = await fetch("/simu/20250515111549/layer.json"); // å‘起请求
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
src/assets/img/timeline/×ø±ê.png
src/assets/img/timeline/ˮλ.png
src/assets/img/timeline/Á÷ËÙ.png
src/assets/img/timeline/Çå³ý.png
src/components/menu/TimeLine.vue
@@ -28,6 +28,10 @@
        <div v-for="(date, index) in visibleDates" :key="index" class="date-label">
          <!-- {{ formatDate(date) }} -->
        </div>
        <!-- ä¸“题渲染:
        <el-switch v-model="isColorRenderEnabled" @change="handleColorRenderChange" style="margin-top:-3px"
          :disabled="!isPlaying || !isWaterPrimitiveCreated" /> -->
        <!-- active-text="开" inactive-text="关" -->
      </div>
      <div class="timeline-track" ref="timelineTrack" @click="seekToPosition">
        <div class="timeline-progress" :style="{ width: progressPercentage + '%' }"></div>
@@ -39,7 +43,12 @@
        </div>
      </div>
    </div>
    <el-button @click="handleBack" style="margin-top: 26px; margin-left: 30px; margin-right: 10px">结束模拟</el-button>
    <div>
      <ratelevel ref="ratelevelRef" :playing-time="sendCurrentPlayingTime" @finish-calculation="handleFinishCalculation"
        style="margin-top: 8px; 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>
  </div>
</template>
@@ -54,14 +63,16 @@
  inject,
  reactive
} from "vue";
import ratelevel from "@/components/menu/flowRate_waterLevel.vue";
import dayjs from "dayjs";
import { getRainfall } from "@/api/index";
import {
  createWaterPrimitive,
  destoryWaterPrimitive,
  pauseWaterSimulation,
  resumeWaterSimulation,
  setTimeForWaterSimulation,
  toggleWaterColorRender,
} from "@/utils/water";
import mapUtils from "@/utils/tools.js";
import { fetchWaterSimulationData } from "@/api/trApi.js";
@@ -71,9 +82,7 @@
import { storeToRefs } from "pinia";
const simStore = useSimStore();
const { selectedScheme } = storeToRefs(simStore);
const emit = defineEmits(["timeUpdate", "isPlaying", "playbackFinished"]);
const emit = defineEmits(["timeUpdate", "isPlaying", "playbackFinished", "isColorRender"]);
// å®šä¹‰props
const props = defineProps({
  waterSimulateParams: {
@@ -83,9 +92,10 @@
    }),
  },
});
// å“åº”式状态
const ratelevelRef = ref(null); // èŽ·å–å­ç»„ä»¶å®žä¾‹çš„å¼•ç”¨
const currentPlayingTime = ref(""); // å½“前播放时间
const sendCurrentPlayingTime = ref(""); // å½“前播放时间
const isPlaying = ref(false);
const playbackFinished = ref(true);
const currentTime = ref(0);
@@ -96,7 +106,7 @@
const waterTimestamps = ref([]); // å­˜å‚¨æ—¶é—´è½´æ•°æ®
const timeMarkers = ref([]);
const timelineTrack = ref(null);
// æ–°å¢žæ ‡è¯†å˜é‡
const isColorRenderEnabled = ref(false); // å‡è®¾è¿™æ˜¯ä½ çš„颜色渲染开关状态
const isWaterPrimitiveCreated = ref(false);
let playInterval = null;
const isRainEnabled = ref(false);
@@ -107,8 +117,6 @@
  rainDensity: 30 // é›¨çš„密度
});
// è®¡ç®—属性
const startDate = computed(() => dayjs(props.waterSimulateParams.date[0]));
const endDate = computed(() => dayjs(props.waterSimulateParams.date[1]));
const progressPercentage = computed(
  () => (currentTime.value / duration.value) * 100
);
@@ -117,40 +125,62 @@
    new Set(waterTimestamps.value.map((ts) => dayjs(ts).format("YYYY-MM-DD")))
  ).map((date) => dayjs(date).toDate())
);
const currentTimeFormatted = computed(() => formatTime(currentTime.value));
// æ’­æ”¾æŽ§åˆ¶
const togglePlay = () => {
  if (!isPlaying.value && currentTime.value >= duration.value)
    currentTime.value = 0; // å¦‚果已经播放完毕,重置时间
    currentTime.value = 0;
  isPlaying.value = !isPlaying.value;
  emit("isPlaying", isPlaying.value);
  if (isPlaying.value) {
    startPlayback();
    if (!isWaterPrimitiveCreated.value) {
      // ç¬¬ä¸€æ¬¡æ’­æ”¾æ—¶åˆ›å»ºæ°´ä½“模拟层
      console.log(selectedScheme.value, '这里是当前方案的全部信息');
      createWaterPrimitive({ interval: intervalMap[playbackRate.value], baseUrl: "/simu/c2h1dc" });
      isWaterPrimitiveCreated.value = true; // æ ‡è®°ä¸ºå·²åˆ›å»º
      // è¿™é‡Œé€šè¿‡water.js中去发送请求获取水面模拟
      createWaterPrimitive({
        baseUrl: "/simu/20250515111549",
        interval: intervalMap[playbackRate.value],
        colorRender: isColorRenderEnabled.value
      });
      isWaterPrimitiveCreated.value = true;
    } else {
      // åŽç»­æ’­æ”¾æ—¶è°ƒç”¨æ¢å¤æŽ¥å£
      resumeWaterSimulation();
      toggleWaterColorRender(isColorRenderEnabled.value); // æ›´æ–°é¢œè‰²æ¸²æŸ“
    }
    if (currentTime.value === 0) emit("playbackFinished", false);
    // æ¢å¤ä¸‹é›¨æ•ˆæžœ
    if (isRainEnabled.value) {
      mapUtils.toggleRain(rainParams, true);
    }
  } else {
    stopPlayback();
    pauseWaterSimulation(); // è°ƒç”¨æš‚停接口
    // åœæ­¢ä¸‹é›¨æ•ˆæžœ
    isRainEnabled.value = true; // ä¿å­˜å½“前需要下雨的状态
    pauseWaterSimulation();
    isRainEnabled.value = true;
    setTimeout(() => {
      mapUtils.delRain();
    }, 3000);
  }
};
// é¢œè‰²æ¸²æŸ“切换事件
const handleColorRenderChange = (enabled) => {
  if (!isPlaying.value) {
    ElMessage({
      message: "请先启动水体模拟后再进行专题效果切换。",
      type: "warning",
    });
    return; // é˜»æ­¢åŽç»­é€»è¾‘执行
  }
  if (isWaterPrimitiveCreated.value) {
    console.log('当前是否开启专题渲染:', enabled);
    emit("isColorRender", enabled)
    toggleWaterColorRender(enabled);
  }
};
const intervalMap = {
  1: 1000, // 1倍速
  2: 500, // 2倍速
@@ -159,7 +189,7 @@
};
// æ’­æ”¾é€»è¾‘
const startPlayback = () => {
  const interval = intervalMap[playbackRate.value] || 1000; // é»˜è®¤ä¸º1000
  // const interval = intervalMap[playbackRate.value] || 1000; // é»˜è®¤ä¸º1000
  clearInterval(playInterval); // æ¸…除之前的定时器
  playInterval = setInterval(() => {
    const timeIncrement = playbackRate.value; // å€é€Ÿä½œä¸ºå¢žé‡
@@ -419,9 +449,12 @@
  () => currentTime.value,
  () => {
    if (waterTimestamps.value.length > 0) {
      currentPlayingTime.value = dayjs(waterTimestamps.value[0])
      sendCurrentPlayingTime.value = dayjs(waterTimestamps.value[0])
        .add(currentTime.value, "second")
        .format("YYYY-MM-DD mm:ss");
        .valueOf(); // ä½¿ç”¨ valueOf() èŽ·å–åŽŸå§‹æ—¶é—´æˆ³
      // æ›´æ–° currentPlayingTime æ ¼å¼åŒ–后的时间字符串
      currentPlayingTime.value = dayjs(sendCurrentPlayingTime.value).format("YYYY-MM-DD HH:mm:ss");
      EventBus.emit("time-update", currentPlayingTime.value);
    }
  }
@@ -432,12 +465,12 @@
  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
    dayjs(sorted.at(-1)).diff(dayjs(sorted[0]), "second") / 5
  );
  return Array.from({ length: 8 }, (_, i) =>
  return Array.from({ length: 6 }, (_, i) =>
    dayjs(sorted[0])
      .add(i * interval, "second")
      .format("mm:ss")
      .format("HH:mm:ss")
  );
}
@@ -453,11 +486,13 @@
onMounted(async () => {
  try {
    getRainfallData()
    // æ ¹æ®layer.json去获取时间轴信息
    const { waterTimestamps: timestamps } = await fetchWaterSimulationData();
    if (timestamps) {
      waterTimestamps.value = timestamps;
      updateTimelineRange();
      timeMarkers.value = generateTimeMarkers(timestamps);
      sendCurrentPlayingTime.value = timestamps[0]
      currentPlayingTime.value = dayjs(timestamps[0]).format(
        "YYYY-MM-DD HH:mm:ss"
      );
@@ -492,6 +527,10 @@
const { endSimulate } = inject("simulateActions");
function handleBack() {
  if (ratelevelRef.value) {
    ratelevelRef.value.endCalculation();
  }
  emit("isColorRender", false);
  setTimeout(() => {
    mapUtils.delRain();
  }, 3000);
src/components/menu/flowRate_waterLevel.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,192 @@
<template>
    <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> -->
        </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>
    </div>
</template>
<script setup>
import { defineProps, watch, ref, onMounted, defineExpose } from "vue";
import { ElMessage } from 'element-plus';
const pickedPoints = ref([]);
const handler = ref(null);
const isPickingActive = ref(false);
const currentTime = ref(0);
const props = defineProps({
    playingTime: {
        type: String,
        required: true
    }
});
watch(
    () => props.playingTime,
    (newVal) => {
        currentTime.value = newVal;
    },
    { immediate: true }
);
// Cesium viewer åˆå§‹åŒ–相关逻辑
const viewer = window.viewer;
function getPickPosition(windowPosition) {
    if (!viewer) return null;
    viewer.scene.globe.depthTestAgainstTerrain = true;
    const cartesian = viewer.scene.pickPosition(windowPosition);
    if (!cartesian) return null;
    const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    cartographic.height += 200.0;
    return {
        cartesian: Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height),
        longitude: Cesium.Math.toDegrees(cartographic.longitude),
        latitude: Cesium.Math.toDegrees(cartographic.latitude),
        height: cartographic.height
    };
}
function addPointToViewer(point, index) {
    // ç¡®ä¿ currentTime æœ‰åˆç†å€¼
    const displayTime = currentTime.value || "未设置时间";
    // æ·»åŠ æ ‡ç­¾ï¼ˆç¡®ä¿å®žä½“åˆ›å»ºæ—¶åŒ…å«label属性)
    const entity = 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',  // å‡å°å­—体大小
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            fillColor: Cesium.Color.YELLOW,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,  // å‡å°è½®å»“宽度
            verticalOrigin: Cesium.VerticalOrigin.CENTER,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            backgroundColor: Cesium.Color.fromCssColorString('rgba(0,0,0,0.7)'),
            backgroundPadding: new Cesium.Cartesian2(10, 10),  // å‡å°èƒŒæ™¯å¡«å……
            showBackground: true,
            scale: 1,  // è®¾ç½®ç¼©æ”¾æ¯”例
            maximumScale: 1.5,  // è®¾ç½®æœ€å¤§ç¼©æ”¾æ¯”例
        }
    });
    // æ·»åŠ åž‚ç›´çº¿
    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({
                outlineWidth: 4,
                outlineColor: Cesium.Color.WHITE
            })
        }
    });
    // å­˜å‚¨ç‚¹çš„信息(包含完整的entity引用)
    pickedPoints.value.push({
        entity: entity,
        longitude: point.longitude,
        latitude: point.latitude,
    });
}
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) => {
        const position = getPickPosition(movement.position);
        if (position) {
            const index = pickedPoints.value.length;
            addPointToViewer(position, index);
        }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
function startPicking() {
    // pickedPoints.value = [];
    // viewer.entities.removeAll();
    if (!handler.value) {
        initPickHandler(); // åªæœ‰ç¬¬ä¸€æ¬¡æ‰åˆå§‹åŒ–
    }
    isPickingActive.value = true;
    ElMessage.success('开始拾取坐标,请点击地图选择点位!');
}
function stopPicking() {
    if (handler.value) {
        handler.value.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        handler.value.destroy();
        handler.value = null;
    }
    isPickingActive.value = false;
}
function togglePick() {
    if (isPickingActive.value) {
        stopPicking(); // è°ƒç”¨ stopPicking æ¥æ­£ç¡®åœ°åœæ­¢é€‰å–过程
        isPickingActive.value = false; // ç¡®ä¿ isPickingActive è®¾ç½®ä¸º false
        ElMessage.success('当前坐标已选取完成!水位流速测量准备完毕!');
        console.log(pickedPoints.value, '最终选取的点');
    } else {
        startPicking();
        isPickingActive.value = true; // åœ¨å¼€å§‹é€‰å–前设置为 true
    }
}
// å½“ currentTime æ”¹å˜æ—¶æ›´æ–°æ‰€æœ‰ç‚¹çš„ label ä¸­çš„æ—¶é—´æˆ³
// ä¿®æ”¹watch逻辑
watch(
    () => props.playingTime,
    (newVal) => {
        currentTime.value = newVal || "未设置时间";
        updateAllLabels();
    },
    { immediate: true }
);
function updateAllLabels() {
    pickedPoints.value.forEach((pointInfo, index) => {
        if (pointInfo.entity && pointInfo.entity.label) {
            pointInfo.entity.label.text =
                `测量点 ${index + 1}\n经度: ${pointInfo.longitude.toFixed(6)}\n纬度: ${pointInfo.latitude.toFixed(6)}\n时间: ${currentTime.value}`;
        }
    });
}
function startCalculation() {
    console.log('选取的坐标点:', pickedPoints.value);
    console.log(`当前时间:${currentTime.value}`);
}
function endCalculation() {
    ElMessage.success('清除所有测量点!');
    pickedPoints.value = [];
    viewer.entities.removeAll();
    // currentTime.value = 0;
}
defineExpose({
    endCalculation
});
</script>
<style lang="less" scoped></style>
src/components/monifangzhen/schemeInfo.vue
@@ -1,9 +1,9 @@
<template>
  <div class="listCard">
    <div class="top"><span>方案详情</span>
      <div @click="togglePick" :class="['pick-button', { active: isPickingActive }]">
      <!-- <div @click="togglePick" :class="['pick-button', { active: isPickingActive }]">
        {{ isPickingActive ? '进行计算' : '开始拾取' }}
      </div>
      </div> -->
    </div>
    <div class="details">
      <div v-if="formattedData.length" class="input-group">
@@ -34,9 +34,7 @@
// çŠ¶æ€ç®¡ç†
const formattedData = ref([]);
const pickedPoints = ref([]);
const handler = ref(null);
const isPickingActive = ref(false);
// æ˜ å°„表
const areaTypeMap = {
@@ -148,88 +146,90 @@
  },
  { immediate: true }
);
// const pickedPoints = ref([]);
// const handler = ref(null);
// const isPickingActive = ref(false);
// // æ‹¾å–相关逻辑
// const viewer = window.viewer;
// æ‹¾å–相关逻辑
const viewer = window.viewer;
// function getPickPosition(windowPosition) {
//   if (!viewer) return null;
//   viewer.scene.globe.depthTestAgainstTerrain = true;
//   const cartesian = viewer.scene.pickPosition(windowPosition);
//   if (!cartesian) return null;
function getPickPosition(windowPosition) {
  if (!viewer) return null;
  viewer.scene.globe.depthTestAgainstTerrain = true;
  const cartesian = viewer.scene.pickPosition(windowPosition);
  if (!cartesian) return null;
  const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
//   const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
  
  // åœ¨åŽŸæœ‰é«˜åº¦ä¸Šå¢žåŠ 300ç±³
  cartographic.height += 80.0;
//   // åœ¨åŽŸæœ‰é«˜åº¦ä¸Šå¢žåŠ 300ç±³
//   cartographic.height += 80.0;
  return {
    cartesian: Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height),
    longitude: Cesium.Math.toDegrees(cartographic.longitude),
    latitude: Cesium.Math.toDegrees(cartographic.latitude),
    height: cartographic.height
  };
}
//   return {
//     cartesian: Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, cartographic.height),
//     longitude: Cesium.Math.toDegrees(cartographic.longitude),
//     latitude: Cesium.Math.toDegrees(cartographic.latitude),
//     height: cartographic.height
//   };
// }
function addPointToViewer(point, index) {
  const entity = viewer.entities.add({
    position: point.cartesian,
    billboard: {
      // image: '../path/to/your/icon.png', // æ›¿æ¢ä¸ºä½ çš„图标路径
      width: 32, // å›¾æ ‡å®½åº¦
      height: 32, // å›¾æ ‡é«˜åº¦
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM
    },
    label: {
      text: `Point ${index + 1}\n经度: ${point.longitude.toFixed(6)}\n纬度: ${point.latitude.toFixed(6)}`,
      font: '14pt monospace',
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      outlineWidth: 2,
      verticalOrigin: Cesium.VerticalOrigin.TOP,
      pixelOffset: new Cesium.Cartesian2(0, -40), // è°ƒæ•´æ ‡ç­¾ç›¸å¯¹äºŽå›¾æ ‡çš„偏移量
      fillColor: Cesium.Color.WHITE,
      outlineColor: Cesium.Color.BLACK
    }
  });
// function addPointToViewer(point, index) {
//   const entity = viewer.entities.add({
//     position: point.cartesian,
//     billboard: {
//       // image: '../path/to/your/icon.png', // æ›¿æ¢ä¸ºä½ çš„图标路径
//       width: 32, // å›¾æ ‡å®½åº¦
//       height: 32, // å›¾æ ‡é«˜åº¦
//       verticalOrigin: Cesium.VerticalOrigin.BOTTOM
//     },
//     label: {
//       text: `Point ${index + 1}\n经度: ${point.longitude.toFixed(6)}\n纬度: ${point.latitude.toFixed(6)}`,
//       font: '14pt monospace',
//       style: Cesium.LabelStyle.FILL_AND_OUTLINE,
//       outlineWidth: 2,
//       verticalOrigin: Cesium.VerticalOrigin.TOP,
//       pixelOffset: new Cesium.Cartesian2(0, -40), // è°ƒæ•´æ ‡ç­¾ç›¸å¯¹äºŽå›¾æ ‡çš„偏移量
//       fillColor: Cesium.Color.WHITE,
//       outlineColor: Cesium.Color.BLACK
//     }
//   });
  // å¯é€‰ï¼šå­˜å‚¨å®žä½“引用以便后续操作
  pickedPoints.value.push(entity);
}
//   // å¯é€‰ï¼šå­˜å‚¨å®žä½“引用以便后续操作
//   pickedPoints.value.push(entity);
// }
function initPickHandler() {
  if (!viewer?.scene?.canvas) return;
  handler.value = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// function initPickHandler() {
//   if (!viewer?.scene?.canvas) return;
//   handler.value = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  handler.value.setInputAction((movement) => {
    const position = getPickPosition(movement.position);
    if (position) {
      const index = pickedPoints.value.length;
      pickedPoints.value.push(position);
      addPointToViewer(position, index);
    }
  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}
//   handler.value.setInputAction((movement) => {
//     const position = getPickPosition(movement.position);
//     if (position) {
//       const index = pickedPoints.value.length;
//       pickedPoints.value.push(position);
//       addPointToViewer(position, index);
//     }
//   }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// }
function togglePick() {
  isPickingActive.value ? stopPicking() : startPicking();
}
// function togglePick() {
//   isPickingActive.value ? stopPicking() : startPicking();
// }
function startPicking() {
  pickedPoints.value = [];
  viewer.entities.removeAll();
  !handler.value && initPickHandler();
  isPickingActive.value = true;
}
// function startPicking() {
//   pickedPoints.value = [];
//   viewer.entities.removeAll();
//   !handler.value && initPickHandler();
//   isPickingActive.value = true;
// }
function stopPicking() {
  if (handler.value) {
    handler.value.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
    handler.value.destroy();
    handler.value = null;
  }
// function stopPicking() {
//   if (handler.value) {
//     handler.value.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
//     handler.value.destroy();
//     handler.value = null;
//   }
  isPickingActive.value = false;
}
//   isPickingActive.value = false;
// }
</script>
<style lang="less" scoped>
src/components/tools/Legend_mnfz.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
<template>
  <div class="legend-container">
    <div class="legend-title">水位高度图例</div>
    <ul class="legend-list">
      <li v-for="(item, index) in waterHeightLevels" :key="index" class="legend-item">
        <span class="legend-color-box" :style="{ 'background-color': item.color }"></span>
        <span class="legend-label">{{ item.height }} ç±³</span>
      </li>
    </ul>
  </div>
</template>
<script setup>
import { onMounted, ref } from "vue";
// å®šä¹‰æ°´ä½é«˜åº¦æ•°æ®
const waterHeightLevels = ref([
  { height: 0.5, color: "#09a2dc" },
  { height: 1.0, color: "#58c196" },
  { height: 1.5, color: "#bedf74" },
  { height: 2.0, color: "#d7f06e" },
  { height: 2.5, color: "#ffe930" },
  { height: 3.0, color: "#fdd10a" },
  { height: 4.0, color: "#feb652" },
  { height: 5.0, color: "#fd7f06" },
  { height: 10.0, color: "#fe2b07" },
]);
onMounted(()=>{
})
</script>
<style lang="less" scoped>
.legend-container {
  padding: 1rem;
  border: 1px solid #ddd;
  border-radius: 8px;
  max-width: 100%;
  width: auto;
  font-size: clamp(10px, 1vw, 14px);
}
.legend-title {
  width: 100%;
  text-align: center;
  letter-spacing: 2px;
  font-weight: 600;
  font-size: clamp(16px, 1vw, 20px);
}
.legend-list {
  list-style: none;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.legend-item {
  display: flex;
  align-items: center;
}
.legend-color-box {
  width: 60px;
  height: 10px;
  margin-right: 0.5rem;
  display: inline-block;
}
.legend-label {
  font-size: inherit;
}
</style>
src/components/tools/Legend_yhgl.vue
@@ -1,6 +1,6 @@
<template>
  <div class="legend-container">
    <div class="legend-title">图例说明</div>
    <div class="legend-title">监测位置图例</div>
    <ul class="legend-list">
      <li v-for="(item, index) in legendItems" :key="index" class="legend-item">
        <img :src="getImageUrl(item.icon)" :alt="item.label" class="legend-icon" />
src/components/tools/Legend_zhjc.vue
@@ -1,6 +1,6 @@
<template>
  <div class="legend-container">
    <div class="legend-title">图例说明</div>
    <div class="legend-title">监测设备图例</div>
    <ul class="legend-list">
      <li v-for="(item, index) in legendItems" :key="index" class="legend-item">
        <img :src="getImageUrl(item.icon)" :alt="item.label" class="legend-icon" />
src/utils/water.js
@@ -17,20 +17,34 @@
 * åˆ›å»ºæ°´ä½“模拟层
 * @param {Object} options - å¯é€‰å‚æ•°
 * @param {number} options.interval - æ°´ä½“模拟的时间间隔(单位:毫秒)
 * @param {string} options.baseUrl - ä»¿çœŸæœåŠ¡åœ°å€
 * @param {boolean} options.colorRender - æ˜¯å¦å¯ç”¨é¢œè‰²æ¸²æŸ“
 */
export function createWaterPrimitive(options = {}) {
  const { baseUrl = "/simu/c2h1dc", interval = 1000 } = options; // é»˜è®¤ baseUrl å’Œ interval
  water = earthCtrl.simulate.createWaterSimulateLayer({
    baseUrl,     // ä»¿çœŸæœåŠ¡ URL
    interval,    // åŠ¨æ€è®¾ç½® interval
    color: new SmartEarth.Cesium.Color.fromCssColorString("#D4F2E7"),
    loop: false, // æ˜¯å¦å¾ªçŽ¯æ’­æ”¾
    callback: timeCallback, // å›žè°ƒå‡½æ•°
  });
  console.log(`Water simulation started with baseUrl: ${baseUrl}, interval: ${interval}ms`);
}
  const { baseUrl = "/simu/c2h1dc", interval = 1000, colorRender = true } = options;
  water = earthCtrl.simulate.createWaterSimulateLayer({
    baseUrl,
    interval,
    color: new SmartEarth.Cesium.Color.fromCssColorString("#D4F2E7"),
    loop: false,
    callback: timeCallback,
    waterHeightLevels: [
      { height: 0.5, color: "#09a2dc" },
      { height: 1.0, color: "#58c196" },
      { height: 1.5, color: "#bedf74" },
      { height: 2.0, color: "#d7f06e" },
      { height: 2.5, color: "#ffe930" },
      { height: 3.0, color: "#fdd10a" },
      { height: 4.0, color: "#feb652" },
      { height: 5.0, color: "#fd7f06" },
      { height: 10.0, color: "#fe2b07" },
    ],
    colorRender, // æŽ§åˆ¶æ˜¯å¦å¯ç”¨é¢œè‰²æ¸²æŸ“
  });
  console.log(`Water simulation started with baseUrl: ${baseUrl}, interval: ${interval}ms, colorRender: ${colorRender}`);
}
/**
 * åˆå§‹åŒ–水体模拟视图
 */
@@ -77,28 +91,39 @@
/**
 * è·³è½¬åˆ°æŸä¸ªæ—¶é—´ç‚¹çš„æ°´é¢çŠ¶æ€
 * @param {number} closestIndex - ç›®æ ‡æ—¶é—´æˆ³ç´¢å¼•
 */
export function setTimeForWaterSimulation(closestIndex) {
  console.log(closestIndex,'index');
  if (water) {
    const imageList = water.getTimeList(); // èŽ·å–æ‰€æœ‰å¯ç”¨æ—¶é—´æˆ³
    if (imageList.length === 0) {
    const imageList = water.getTimeList();
    if (!imageList.length) {
      console.warn("No timestamps available for water simulation.");
      return;
    }
    const idx = Math.floor(Math.random() * imageList.length); // éšæœºé€‰æ‹©ä¸€ä¸ªæ—¶é—´æˆ³
    console.log(
      `Jumping to timestamp: count:[${imageList.length}], index:[${idx}]`
    );
    water.setTime(imageList[closestIndex]); // è®¾ç½®æ—¶é—´æˆ³ï¼Œè·³è½¬åˆ°å¯¹åº”时刻
    const idx = Math.floor(Math.random() * imageList.length);
    console.log(`Jumping to timestamp: count:[${imageList.length}], index:[${closestIndex}]`);
    water.setTime(imageList[closestIndex]);
  } else {
    console.warn("No water simulation to set time for.");
  }
}
/**
 * è®¾ç½®æˆ–关闭颜色渲染
 * @param {boolean} enabled
 */
export function toggleWaterColorRender(enabled) {
  if (water) {
    water.colorRender = enabled;
    console.log(`Water color render set to: ${enabled}`);
  } else {
    console.warn("No water simulation to toggle color rendering.");
  }
}
/**
 * æ—¶é—´æˆ³å›žè°ƒå‡½æ•°
 * @param {number} timeStamp - å½“前时间戳
 */
src/views/GisView.vue
@@ -444,7 +444,7 @@
  initMap();
  // åœ¨ä½ çš„初始化代码中调用这个函数
  addCityPolygon();
  initHandler();
  // initHandler();
  // initView()
  loadAreaPolygon("/json/nsl_area.geojson");
  loadAreaPolygonAll("/json/geometry.json", true);
src/views/mnfz.vue
@@ -12,7 +12,9 @@
    :waterSimulateParams="waterSimulateParams"
    @playbackFinished="playbackFinished"
    @end="endSimulate"
    @isColorRender="isColorRender"
  />
  <LegendMNFZ class="legend" v-if="isShowLegend"></LegendMNFZ>
  <DebuffDetail
    v-if="showDebuffDetail"
    @open="openDetail"
@@ -25,6 +27,7 @@
import { EventBus } from "@/eventBus"; // å¼•入事件总线
import { ref, onMounted, onUnmounted, provide } from "vue";
import TimeLine from "@/components/menu/TimeLine.vue";
import LegendMNFZ from "@/components/tools/Legend_mnfz.vue";
import Left from "./left/Left.vue";
import echartInfo from "@/components/monifangzhen/echartInfo.vue";
import DebuffDetail from "@/components/tools/DebuffDetail.vue";
@@ -49,6 +52,7 @@
const showDebuffTable = ref(false);
const isDynamicMode = ref(false);
const isFinish = ref(true);
const isShowLegend = ref(false);
const treeMap = new Map();
@@ -538,6 +542,10 @@
function playbackFinished(val) {
  isFinish.value = val;
}
function isColorRender(val){
  console.log('这里打印是否显示水位图例的值:',val);
  isShowLegend.value = val
}
// å®šä¹‰å…¨å±€å˜é‡å­˜å‚¨å½“前正在闪动的面片
let flashingPolygon = null;
@@ -645,4 +653,12 @@
</script>
<style lang="less" scoped>
@import url("../assets/css/home.css");
.legend {
    // background: url("@/assets/img/right/rightbg.png");
    color: white;
    position: fixed;
    bottom: 6%;
    right: 20%;
    z-index: 3333;
}
</style>