Koishi 3 месяцев назад
Родитель
Сommit
d64fad4b60

+ 2 - 0
.env.development

@@ -1,3 +1,5 @@
+VITE_APP_ENV_NAME="dev"
+
 # 获取天气数据
 VITE_APP_API=https://api.openweathermap.org
 

+ 5 - 1
.env.production

@@ -1,2 +1,6 @@
+VITE_APP_ENV_NAME="pro"
+
 # 获取天气数据
-VITE_APP_API=https://api.openweathermap.org
+VITE_APP_API=https://api.openweathermap.org
+
+VITE_APP_WS_URL=ws://10.121.128.117:8431/

+ 3 - 3
src/tools/ws.js

@@ -28,18 +28,18 @@ class WebSocketService {
             autoReconnect = true,
             maxReconnectAttempts = 5,
             reconnectInterval = 3000,
-            baseURL = "",
+            baseURL = import.meta.env.VITE_APP_WS_URL,
             url = "",
         } = options;
 
-        this.url = `${baseURL || process.env.VITE_APP_WS_URL}${url}`;
+        this.url = `${baseURL}${url}`;
 
         this.autoReconnect = autoReconnect;
         this.maxReconnectAttempts = maxReconnectAttempts;
         this.reconnectInterval = reconnectInterval;
 
         try {
-            this.socket = new WebSocket(url, protocols);
+            this.socket = new WebSocket(`${baseURL}${url}`, protocols);
 
             this.socket.onopen = (event) => {
                 console.log('WebSocket 连接成功');

+ 354 - 147
src/views/cesiumComponents/windMap2D.vue

@@ -130,7 +130,9 @@ import windGridData from "./windGridData.json";
 
 import AdvancedBillboardGenerator from "@/tools/lightsign.js";
 
-import { useWebSocket } from "@/tools/websocket.js";
+// import { useWebSocket } from "@/tools/websocket.js";
+
+import webSocketService from "@/tools/ws.js";
 
 export default {
   name: "windMap2D",
@@ -197,6 +199,9 @@ export default {
       allStationentitys: [],
       allWindEntitys: [],
       urlTiles: "/public/static/tiles/{z}/{x}/{y}.jpg",
+      entityxyArray: [],
+      isFakeData: false,
+      fakeDataTimmer: null,
     };
   },
   mounted() {
@@ -205,6 +210,11 @@ export default {
       this.loading = false;
     }, 1000);
   },
+
+  unmounted() {
+    clearInterval(this.fakeDataTimmer);
+    this.fakeDataTimmer = null;
+  },
   methods: {
     async initCesium() {
       const box = document.getElementById("cesiumContainer");
@@ -228,8 +238,10 @@ export default {
         // minimumLevel: 11,
         maximumLevel: 18,
         // url: this.urlTiles,
-        // url: "/static/ditu/{z}/{x}/{y}.png",
-        url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
+        url:
+          import.meta.env.VITE_APP_ENV_NAME === "dev"
+            ? "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}"
+            : "/static/ditu/{z}/{x}/{y}.png",
         credit: "影像地图",
       });
       imageryProvider.alpha = 0.55; // 透明度
@@ -397,56 +409,164 @@ export default {
       let fjLonLatJson = [];
       this.fjLonLatJsonArr = [];
       let url = "";
+
       //   旺海庄:DHWH  苏木山:DHSM 营盘梁:DHYP 迈越:HZMY
+      // if (stationName === "MYFDC") {
+      //   fjLonLatJson = fjMYLonLatJson;
+      //   url = "ws://10.121.128.117:8431/ws/HZMY";
+      // } else if (stationName === "JNWHZ") {
+      //   fjLonLatJson = fjWHZLonLatJson;
+      //   url = "ws://10.121.128.117:8431/ws/DHWH";
+      // } else if (stationName === "JNYPL") {
+      //   fjLonLatJson = fjYPLLonLatJson;
+      //   url = "ws://10.121.128.117:8431/ws/DHYP";
+      // } else if (stationName === "JNSMS") {
+      //   fjLonLatJson = fjSMSLonLatJson;
+      //   url = "ws://10.121.128.117:8431/ws/DHSM";
+      // }
+
+      webSocketService.connect({
+        url: `ws/${this.getWsUrl(stationName)}`,
+        autoReconnect: true,
+        maxReconnectAttempts: 5,
+        reconnectInterval: 3000,
+        onOpen: (event) => {
+          console.log("✅ WebSocket 连接成功", event);
+        },
+        onError: (error) => {
+          console.log("❌ WebSocket 错误:", error);
+          return;
+          if (stationName === "MYFDC") {
+            fjLonLatJson = JSON.parse(JSON.stringify(fjMYLonLatJson));
+          } else if (stationName === "JNWHZ") {
+            fjLonLatJson = JSON.parse(JSON.stringify(fjWHZLonLatJson));
+          } else if (stationName === "JNYPL") {
+            fjLonLatJson = JSON.parse(JSON.stringify(fjYPLLonLatJson));
+          } else if (stationName === "JNSMS") {
+            fjLonLatJson = JSON.parse(JSON.stringify(fjSMSLonLatJson));
+          }
+
+          let wtArray = wsRes.windMachineList;
+          this.isFakeData = true;
+
+          this.fakeDataTimmer = setInterval(() => {
+            fjLonLatJson.data.forEach((e) => {
+              let fjItem =
+                wtArray.find((findEle) => {
+                  return findEle.fjbh === e.fjbh;
+                }) || {};
+              const fjMix = Object.assign({}, e, fjItem);
+              fjMix.status = this.getStatus(fjMix.fjzt);
+              e = fjMix;
+              if (e.status) {
+                if (e.status === 1) {
+                  this.showStatuswind(viewer, e, dj);
+                } else if (e.status === 2) {
+                  this.showStatuswind(viewer, e, gz);
+                } else if (e.status === 3) {
+                  this.showStatuswind(viewer, e, jx);
+                } else if (e.status === 4) {
+                  this.showStatuswind(viewer, e, xd);
+                } else if (e.status === 5) {
+                  this.showStatuswind(viewer, e, lx);
+                } else if (e.status === 6) {
+                  this.showStatuswind(viewer, e, sl);
+                } else {
+                  //并网风机
+                  this.showAnimatewind(viewer, e);
+                }
+              }
+            });
+
+            this.fjLonLatJsonArr = fjLonLatJson;
+          }, 1000);
+        },
+      });
+
+      webSocketService.on("message", (res) => {
+        if (stationName === "MYFDC") {
+          fjLonLatJson = fjMYLonLatJson;
+        } else if (stationName === "JNWHZ") {
+          fjLonLatJson = fjWHZLonLatJson;
+        } else if (stationName === "JNYPL") {
+          fjLonLatJson = fjYPLLonLatJson;
+        } else if (stationName === "JNSMS") {
+          fjLonLatJson = fjSMSLonLatJson;
+        }
+
+        let wtArray = res.windMachineList;
+        fjLonLatJson.data.forEach((e, index) => {
+          let fjItem =
+            wtArray.find((findEle) => {
+              return findEle.fjbh === e.fjbh;
+            }) || {};
+          const fjMix = Object.assign({}, e, fjItem);
+          fjMix.status = this.getStatus(fjMix);
+          e = fjMix;
+          if (e.status) {
+            if (e.status === 1) {
+              this.showStatuswind(viewer, e, dj);
+            } else if (e.status === 2) {
+              this.showStatuswind(viewer, e, gz);
+            } else if (e.status === 3) {
+              this.showStatuswind(viewer, e, jx);
+            } else if (e.status === 4) {
+              this.showStatuswind(viewer, e, xd);
+            } else if (e.status === 5) {
+              this.showStatuswind(viewer, e, lx);
+            } else if (e.status === 6) {
+              this.showStatuswind(viewer, e, sl);
+            } else {
+              //并网风机
+              this.showAnimatewind(viewer, e);
+            }
+          }
+        });
+
+        this.fjLonLatJsonArr = fjLonLatJson;
+      });
+
+      // const ws = useWebSocket(url);
+      // let wtArray = ws.messages.windMachineList;
+      // this.fjLonLatJsonArr = fjLonLatJson;
+
+      this.resetWindViewport();
+    },
+
+    getWsUrl(stationName) {
+      let wsurl = "";
       if (stationName === "MYFDC") {
-        fjLonLatJson = fjMYLonLatJson;
-        url = "ws://10.121.128.117:8431/ws/HZMY";
+        wsurl = "HZMY";
       } else if (stationName === "JNWHZ") {
-        fjLonLatJson = fjWHZLonLatJson;
-        url = "ws://10.121.128.117:8431/ws/DHWH";
+        wsurl = "DHWH";
       } else if (stationName === "JNYPL") {
-        fjLonLatJson = fjYPLLonLatJson;
-        url = "ws://10.121.128.117:8431/ws/DHYP";
+        wsurl = "DHYP";
       } else if (stationName === "JNSMS") {
-        fjLonLatJson = fjSMSLonLatJson;
-        url = "ws://10.121.128.117:8431/ws/DHSM";
+        wsurl = "DHSM";
       }
+      return wsurl;
+    },
 
-      const ws = useWebSocket(url);
-      // let wtArray = ws.messages.windMachineList
-      // this.fjLonLatJsonArr = fjLonLatJson;
-
-      let wtArray = wsRes.windMachineList;
-      this.fjLonLatJsonArr = wsRes.windMachineList;
-
-      console.log(789789, wtArray);
-      fjLonLatJson.data.forEach((e, index) => {
-        let fjItem =
-          wtArray.find((findEle) => {
-            return findEle.fjbh === e.fjbh;
-          }) || {};
-        const dataMix = Object.assign({}, e, fjItem);
-        if (dataMix.status) {
-          if (dataMix.status === 1) {
-            this.showStatuswind(viewer, dataMix, dj);
-          } else if (dataMix.status === 2) {
-            this.showStatuswind(viewer, dataMix, gz);
-          } else if (dataMix.status === 3) {
-            this.showStatuswind(viewer, dataMix, jx);
-          } else if (dataMix.status === 4) {
-            this.showStatuswind(viewer, dataMix, xd);
-          } else if (dataMix.status === 5) {
-            this.showStatuswind(viewer, dataMix, lx);
-          } else if (dataMix.status === 6) {
-            this.showStatuswind(viewer, dataMix, sl);
-          } else {
-            //并网风机
-            this.showAnimatewind(viewer, dataMix);
-          }
-        }
-      });
-      this.resetWindViewport();
+    getStatus(sName) {
+      let status = 0;
+      if (/待机/.test(sName)) {
+        status = 1;
+      } else if (/故障/.test(sName)) {
+        status = 2;
+      } else if (/检修/.test(sName)) {
+        status = 3;
+      } else if (/限电/.test(sName)) {
+        status = 4;
+      } else if (/离线/.test(sName)) {
+        status = 5;
+      } else if (/受累/.test(sName)) {
+        status = 6;
+      } else if (/并网/.test(sName)) {
+        status = 7;
+      }
+      return status;
     },
+
     // 根据状态展示不同颜色风机贴图
     showStatuswind(viewer, e, type, index) {
       this.addSvg(
@@ -458,6 +578,7 @@ export default {
         Math.random().toFixed(4) * 10000
       );
     },
+
     // 风机柱与扇叶分开展示转动效果贴图
     showAnimatewind(viewer, e, index) {
       this.addSvgs(
@@ -477,116 +598,202 @@ export default {
         Math.random().toFixed(3) * 2000
       );
     },
+
     //添加svg或png贴图
     addSvg(viewer, uri, lon, lat, val, index) {
-      console.log(3333, val);
       let that = this;
-      let ids = that.generateUniqueId(val.id);
-      const position = Cesium.Cartesian3.fromDegrees(lon, lat);
+      const findRes =
+        that.entityxyArray.find((findEle) => {
+          return findEle.fjbh === val.fjbh;
+        }) || null;
+      if (findRes) {
+        this.changeFjData(val);
+      } else {
+        let ids = that.generateUniqueId(val.id);
+        const position = Cesium.Cartesian3.fromDegrees(lon, lat);
+
+        // 使用高级灯牌生成器
+        const advancedGenerator = new AdvancedBillboardGenerator();
+
+        let statusItems = [
+          {
+            label: "功率",
+            value: `${
+              this.isFakeData
+                ? this.randomNum(100, 1000)
+                : val.actualPower.toFixed(2)
+            }MW`,
+          },
+          {
+            label: "风速",
+            value: `${
+              this.isFakeData
+                ? this.randomNum(100, 1000)
+                : val.windSpeed.toFixed(1)
+            }m/s`,
+          },
+          {
+            label: "转速",
+            value: `${
+              this.isFakeData
+                ? this.randomNum(100, 1000)
+                : val.rotateSpeed.toFixed(1)
+            }p`,
+          },
+          // { label: "其他参数A", value: "...." },
+          // { label: "其他参数B", value: "...." },
+          // { label: "其他参数C", value: "...." },
+          // { label: "其他参数D", value: "...." },
+          // { label: "其他参数E", value: "...." },
+          // { label: "其他参数F", value: "...." },
+        ];
+
+        const billboardImage = advancedGenerator.generateAdvancedBillboard({
+          title: val.fjbh,
+          statusItems,
+          // borderGradient: ["#00e5ff", "#2979ff"],
+          borderGradient: ["#ccc", "#ccc"],
+          backgroundColor: "transparent",
+          padding: 6,
+          titleHeight: 22,
+          itemHeight: 17,
+          titleColor: "#1890ff",
+          titleStrokeStyle: "#000",
+          titleStrokeWidth: 1,
+          labelStrokeStyle: "#000",
+          labelStrokeWidth: 1,
+          valueStrokeStyle: "#000",
+          valueStrokeWidth: 1,
+        });
 
-      // 使用高级灯牌生成器
-      const advancedGenerator = new AdvancedBillboardGenerator();
-
-      let statusItems = [];
-      const statusArray = [
-        { label: "功率", value: `${val.actualPower.toFixed(2)}MW` },
-        { label: "风速", value: `${val.windSpeed.toFixed(1)}m/s` },
-        { label: "转速", value: `${val.rotateSpeed.toFixed(1)}p` },
-        // { label: "其他参数A", value: "...." },
-        // { label: "其他参数B", value: "...." },
-        // { label: "其他参数C", value: "...." },
-        // { label: "其他参数D", value: "...." },
-        // { label: "其他参数E", value: "...." },
-        // { label: "其他参数F", value: "...." },
-      ];
-
-      statusItems = statusArray;
-
-      const billboardImage = advancedGenerator.generateAdvancedBillboard({
-        title: val.name,
-        statusItems,
-        // borderGradient: ["#00e5ff", "#2979ff"],
-        borderGradient: ["#ccc", "#ccc"],
-        backgroundColor: "transparent",
-        padding: 6,
-        titleHeight: 22,
-        itemHeight: 17,
-        titleColor: "#1890ff",
-        titleStrokeStyle: "#000",
-        titleStrokeWidth: 1,
-        labelStrokeStyle: "#000",
-        labelStrokeWidth: 1,
-        valueStrokeStyle: "#000",
-        valueStrokeWidth: 1,
-      });
+        const entityxy = viewer.entities.add({
+          name: val.name,
+          position,
+          billboard: {
+            image: billboardImage,
+            scale: 1,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 原来已经是CENTER,现在改为BOTTOM
+            pixelOffset: new Cesium.Cartesian2(80, -50), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            // heightReference: Cesium.HeightReference.NONE,
+            // 近大远小
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 5010米内
+              1.2, // 1倍大小
+              9000, // 10000米外
+              1 // 0.1倍大小
+            ),
+
+            // 透明度渐变
+            // translucencyByDistance: new Cesium.NearFarScalar(
+            //   6000, // 500米内
+            //   1.0, // 完全不透明
+            //   9000, // 3000米外
+            //   0.5 // 完全透明
+            // ),
+          },
+        });
 
-      const entityxy = viewer.entities.add({
-        name: val.name,
-        position,
-        billboard: {
-          image: billboardImage,
-          scale: 1,
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 原来已经是CENTER,现在改为BOTTOM
-          pixelOffset: new Cesium.Cartesian2(80, -50), // 原来是-20,现在改为30,向上移动
-          eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
-          // heightReference: Cesium.HeightReference.NONE,
-          // 近大远小
-          scaleByDistance: new Cesium.NearFarScalar(
-            6000, // 5010米内
-            1.2, // 1倍大小
-            9000, // 10000米外
-            1 // 0.1倍大小
-          ),
-
-          // 透明度渐变
-          // translucencyByDistance: new Cesium.NearFarScalar(
-          //   6000, // 500米内
-          //   1.0, // 完全不透明
-          //   9000, // 3000米外
-          //   0.5 // 完全透明
-          // ),
-        },
-      });
+        const btn = document.getElementById("windBtn");
 
-      const btn = document.getElementById("windBtn");
+        btn.addEventListener("click", function (event) {
+          entityxy.show = !entityxy.show;
+        });
 
-      btn.addEventListener("click", function (event) {
-        entityxy.show = !entityxy.show;
-      });
+        const entity = viewer.entities.add({
+          id: ids,
+          position, // 模型位置
+          billboard: {
+            image: uri, // 也可以是 SVG 路径,如 'icon.svg'
+            scale: 0.5,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+            // 模型贴地
+            //   heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+          },
+          label: {
+            // text: val.name ? val.name : val.plantname,
+            text: val.name,
+            font: "14px sans-serif",
+            fillColor: Cesium.Color.fromBytes(255, 255, 255),
+          },
+        });
+        // 创建事件处理器
+        const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
+        handler.setInputAction(function (movement) {
+          var position = movement.position;
+          var pickedObject = viewer.scene.pick(position);
+          if (pickedObject && pickedObject.id.id === ids) {
+            console.log("你点击了标签或模型!", entity);
+            console.log("标签或模型数据!", val);
+            that.modelVal = val;
+            // 找到实体,显示包含实体信息的弹框
+            that.showRightClickPopup(position, val);
+            return;
+          }
+        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
+        this.allWindEntitys.push({ entity, handler });
 
-      const entity = viewer.entities.add({
-        id: ids,
-        position, // 模型位置
-        billboard: {
-          image: uri, // 也可以是 SVG 路径,如 'icon.svg'
-          scale: 0.5,
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
-          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
-          // 模型贴地
-          //   heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
-        },
-        label: {
-          // text: val.name ? val.name : val.plantname,
-          text: val.name,
-          font: "14px sans-serif",
-          fillColor: Cesium.Color.fromBytes(255, 255, 255),
-        },
-      });
-      // 创建事件处理器
-      const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
-      handler.setInputAction(function (movement) {
-        var position = movement.position;
-        var pickedObject = viewer.scene.pick(position);
-        if (pickedObject && pickedObject.id.id === ids) {
-          console.log("你点击了标签或模型!", entity);
-          console.log("标签或模型数据!", val);
-          that.modelVal = val;
-          // 找到实体,显示包含实体信息的弹框
-          that.showRightClickPopup(position, val);
-          return;
-        }
-      }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
-      this.allWindEntitys.push({ entity, handler });
+        entityxy.fjbh = val.fjbh;
+        this.entityxyArray.push(entityxy);
+      }
+    },
+
+    changeFjData(fjItem) {
+      const findRes =
+        this.entityxyArray.find((findEle) => {
+          return findEle.fjbh === fjItem.fjbh;
+        }) || null;
+      if (findRes) {
+        const statusItems = [
+          {
+            label: "功率",
+            value: `${
+              this.isFakeData
+                ? this.randomNum(100, 1000)
+                : fjItem.actualPower.toFixed(2)
+            }MW`,
+          },
+          {
+            label: "风速",
+            value: `${
+              this.isFakeData
+                ? this.randomNum(100, 1000)
+                : fjItem.windSpeed.toFixed(1)
+            }m/s`,
+          },
+          {
+            label: "转速",
+            value: `${
+              this.isFakeData
+                ? this.randomNum(100, 1000)
+                : fjItem.rotateSpeed.toFixed(1)
+            }p`,
+          },
+        ];
+
+        // 使用高级灯牌生成器
+        const advancedGenerator = new AdvancedBillboardGenerator();
+        const billboardImage = advancedGenerator.generateAdvancedBillboard({
+          title: findRes.fjbh,
+          statusItems,
+          // borderGradient: ["#00e5ff", "#2979ff"],
+          borderGradient: ["#ccc", "#ccc"],
+          backgroundColor: "transparent",
+          padding: 6,
+          titleHeight: 22,
+          itemHeight: 17,
+          titleColor: "#1890ff",
+          titleStrokeStyle: "#000",
+          titleStrokeWidth: 1,
+          labelStrokeStyle: "#000",
+          labelStrokeWidth: 1,
+          valueStrokeStyle: "#000",
+          valueStrokeWidth: 1,
+        });
+
+        findRes.billboard.image._value = billboardImage;
+      }
     },
 
     randomNum(minNum, maxNum) {

+ 201 - 85
src/views/cesiumComponents/windMap3D.vue

@@ -87,6 +87,7 @@ import fjMYLonLatJson from "../fjLonLatJson/fj_MY.json";
 import fjWHZLonLatJson from "../fjLonLatJson/fj_WHZ.json"; //京能旺海庄
 import fjYPLLonLatJson from "../fjLonLatJson/fj_YPL.json"; //京能营盘梁
 import fjSMSLonLatJson from "../fjLonLatJson/fj_SMS.json"; //京能苏木山
+import wsRes from "../fjLonLatJson/wsRes.json"; // 模拟 ws 返回数据
 import mountainPosJson from "../fjLonLatJson/mountainPos.json";
 import allStationJson from "./allStationJson.json";
 import basicGeoJson from "../../assets/geoJson/basic.json";
@@ -117,6 +118,8 @@ import { HeightReference } from "cesium";
 
 import AdvancedBillboardGenerator from "@/tools/lightsign.js";
 
+import webSocketService from "@/tools/ws.js";
+
 export default {
   name: "windMap3D",
   components: {
@@ -184,6 +187,9 @@ export default {
       verticalExaggeration: 1.0,
       infoBoxes: [],
       entityxy: {},
+      entityxyArray: [],
+      isFakeData: false,
+      fakeDataTimmer: null,
     };
   },
   mounted() {
@@ -251,10 +257,11 @@ export default {
     // 初始化底图
     async initCesiumBaseMapImage() {
       const imageryProvider = await new Cesium.UrlTemplateImageryProvider({
-        // url: "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
-        // url: "https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",
         // url: "http://localhost:3007/tiles/map/{z}/{x}/{y}",
-        url: "/static/ditu/{z}/{x}/{y}.png",
+        url:
+          import.meta.env.VITE_APP_ENV_NAME === "dev"
+            ? "https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}"
+            : "/static/ditu/{z}/{x}/{y}.png",
         // minimumLevel: 11,
         maximumLevel: 24,
         credit: "影像地图",
@@ -479,33 +486,118 @@ export default {
       let stationName = this.$route.query.nameEn;
       let fjLonLatJson = [];
       this.fjLonLatJsonArr = [];
+
+      webSocketService.connect({
+        url: `ws/${this.getWsUrl(stationName)}`,
+        autoReconnect: true,
+        maxReconnectAttempts: 5,
+        reconnectInterval: 3000,
+        onOpen: (event) => {
+          console.log("✅ WebSocket 连接成功", event);
+        },
+        onError: (error) => {
+          console.log("❌ WebSocket 错误:", error);
+          if (stationName === "MYFDC") {
+            fjLonLatJson = JSON.parse(JSON.stringify(fjMYLonLatJson));
+          } else if (stationName === "JNWHZ") {
+            fjLonLatJson = JSON.parse(JSON.stringify(fjWHZLonLatJson));
+          } else if (stationName === "JNYPL") {
+            fjLonLatJson = JSON.parse(JSON.stringify(fjYPLLonLatJson));
+          } else if (stationName === "JNSMS") {
+            fjLonLatJson = JSON.parse(JSON.stringify(fjSMSLonLatJson));
+          }
+
+          let wtArray = JSON.parse(JSON.stringify(wsRes.windMachineList));
+          this.isFakeData = true;
+
+          fjLonLatJson.data.forEach((e) => {
+            let fjItem =
+              wtArray.find((findEle) => {
+                return findEle.fjbh === e.fjbh;
+              }) || {};
+            const fjMix = Object.assign({}, e, fjItem);
+            fjMix.status = this.getStatus(fjMix.fjzt);
+            e = fjMix;
+
+            this.showStatuswind(viewer, e);
+          });
+          this.fjLonLatJsonArr = fjLonLatJson;
+
+          this.fakeDataTimmer = setInterval(() => {
+            // viewer.entities.removeAll();
+          }, 5000);
+        },
+      });
+
+      webSocketService.on("message", (res) => {
+        if (stationName === "MYFDC") {
+          fjLonLatJson = fjMYLonLatJson;
+        } else if (stationName === "JNWHZ") {
+          fjLonLatJson = fjWHZLonLatJson;
+        } else if (stationName === "JNYPL") {
+          fjLonLatJson = fjYPLLonLatJson;
+        } else if (stationName === "JNSMS") {
+          fjLonLatJson = fjSMSLonLatJson;
+        }
+
+        let wtArray = res.windMachineList;
+
+        fjLonLatJson.data.forEach((e, index) => {
+          let fjItem =
+            wtArray.find((findEle) => {
+              return findEle.fjbh === e.fjbh;
+            }) || {};
+          const fjMix = Object.assign({}, e, fjItem);
+          e = fjMix;
+
+          this.showStatuswind(viewer, e);
+        });
+
+        this.fjLonLatJsonArr = fjLonLatJson;
+      });
+
+      this.resetWindViewport();
+    },
+
+    getWsUrl(stationName) {
+      let wsurl = "";
       if (stationName === "MYFDC") {
-        fjLonLatJson = fjMYLonLatJson;
+        wsurl = "HZMY";
       } else if (stationName === "JNWHZ") {
-        fjLonLatJson = fjWHZLonLatJson;
+        wsurl = "DHWH";
       } else if (stationName === "JNYPL") {
-        fjLonLatJson = fjYPLLonLatJson;
+        wsurl = "DHYP";
       } else if (stationName === "JNSMS") {
-        fjLonLatJson = fjSMSLonLatJson;
+        wsurl = "DHSM";
       }
-      this.fjLonLatJsonArr = fjLonLatJson;
-      fjLonLatJson.data.forEach((e, index) => {
-        this.showStatuswind(viewer, e);
-      });
-
-      //   let mountainMsg = mountainPosJson.data.find(it => it.stationName === stationName)
+      return wsurl;
+    },
 
-      //     this.addTreeain(
-      //         viewer,
-      //         mountainMsg
-      //     );
-      this.resetWindViewport();
+    getStatus(sName) {
+      let status = 0;
+      if (/待机/.test(sName)) {
+        status = 1;
+      } else if (/故障/.test(sName)) {
+        status = 2;
+      } else if (/检修/.test(sName)) {
+        status = 3;
+      } else if (/限电/.test(sName)) {
+        status = 4;
+      } else if (/离线/.test(sName)) {
+        status = 5;
+      } else if (/受累/.test(sName)) {
+        status = 6;
+      } else if (/并网/.test(sName)) {
+        status = 7;
+      }
+      return status;
     },
+
     // 根据状态展示不同颜色风机贴图
     showStatuswind(viewer, e) {
       this.addModel(
         viewer,
-        e.name,
+        e.fjbh,
         e.longitude,
         e.latitude,
         e.status,
@@ -592,8 +684,11 @@ export default {
         },
       });
     },
+
     //添加模型
     addModel(viewer, name, lon, lat, status, height, model) {
+      let that = this;
+
       const hpRoll = new Cesium.HeadingPitchRoll(45.0, 0.0, 0.0);
       const position = Cesium.Cartesian3.fromDegrees(lon, lat, height || 0);
       const orientation = Cesium.Transforms.headingPitchRollQuaternion(
@@ -605,7 +700,6 @@ export default {
       const statueFJ = this.getWtStatue(status, "en");
       const statueZh = this.getWtStatue(status, "zh");
 
-      let that = this;
       const entity = viewer.entities.add({
         name, // 模型名称
         position, // 模型位置
@@ -631,71 +725,6 @@ export default {
         },
       });
 
-      // 使用高级灯牌生成器
-      const advancedGenerator = new AdvancedBillboardGenerator();
-
-      let statusItems = [];
-      const statusArray = [
-        { label: "风速", value: "10m/s" },
-        { label: "状态", value: statueZh },
-        { label: "转速", value: "1000p" },
-        { label: "功率", value: "50kW" },
-        { label: "其他参数A", value: "...." },
-        { label: "其他参数B", value: "...." },
-        { label: "其他参数C", value: "...." },
-        { label: "其他参数D", value: "...." },
-        { label: "其他参数E", value: "...." },
-        { label: "其他参数F", value: "...." },
-      ];
-
-      for (let i = 0; i <= this.randomNum(1, 9); i++) {
-        statusItems.push(statusArray[i]);
-      }
-
-      const billboardImage = advancedGenerator.generateAdvancedBillboard({
-        title: name,
-        statusItems,
-        borderGradient: ["#ccc", "#ccc"],
-        backgroundColor: "transparent",
-        padding: 6,
-        titleHeight: 22,
-        itemHeight: 17,
-        titleColor: "#1890ff",
-        titleStrokeStyle: "#000",
-        titleStrokeWidth: 1,
-        labelStrokeStyle: "#000",
-        labelStrokeWidth: 1,
-        valueStrokeStyle: "#000",
-        valueStrokeWidth: 1,
-      });
-
-      const entityxy = viewer.entities.add({
-        name,
-        position,
-        billboard: {
-          image: billboardImage,
-          scale: 1,
-          verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 原来已经是CENTER,现在改为BOTTOM
-          pixelOffset: new Cesium.Cartesian2(80, -50), // 原来是-20,现在改为30,向上移动
-          eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
-          heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
-          scaleByDistance: new Cesium.NearFarScalar(
-            6000, // 5010米内
-            1.2, // 1倍大小
-            9000, // 10000米外
-            1 // 0.1倍大小
-          ),
-
-          // 透明度渐变
-          // translucencyByDistance: new Cesium.NearFarScalar(
-          //   6000, // 500米内
-          //   1.0, // 完全不透明
-          //   9000, // 3000米外
-          //   0.5 // 完全透明
-          // ),
-        },
-      });
-
       const btn = document.getElementById("windBtn");
 
       btn.addEventListener("click", function (event) {
@@ -741,7 +770,94 @@ export default {
           return;
         }
       }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
+
+      // 使用高级灯牌生成器
+      const advancedGenerator = new AdvancedBillboardGenerator();
+
+      let statusItems = [
+        {
+          label: "功率",
+          value: `${
+            this.isFakeData
+              ? this.randomNum(100, 1000)
+              : model.actualPower.toFixed(2)
+          }MW`,
+        },
+        {
+          label: "风速",
+          value: `${
+            this.isFakeData
+              ? this.randomNum(100, 1000)
+              : model.windSpeed.toFixed(1)
+          }m/s`,
+        },
+        {
+          label: "转速",
+          value: `${
+            this.isFakeData
+              ? this.randomNum(100, 1000)
+              : model.rotateSpeed.toFixed(1)
+          }p`,
+        },
+      ];
+
+      const billboardImage = advancedGenerator.generateAdvancedBillboard({
+        title: name,
+        statusItems,
+        borderGradient: ["#ccc", "#ccc"],
+        backgroundColor: "transparent",
+        padding: 6,
+        titleHeight: 22,
+        itemHeight: 17,
+        titleColor: "#1890ff",
+        titleStrokeStyle: "#000",
+        titleStrokeWidth: 1,
+        labelStrokeStyle: "#000",
+        labelStrokeWidth: 1,
+        valueStrokeStyle: "#000",
+        valueStrokeWidth: 1,
+      });
+
+      let entityxy =
+        this.entityxyArray.find((findEle) => {
+          return findEle.fjbh === model.fjbh;
+        }) || null;
+
+      if (entityxy) {
+        entityxy.billboard.image._value = billboardImage;
+      } else {
+        entityxy = viewer.entities.add({
+          name,
+          position,
+          billboard: {
+            image: billboardImage,
+            scale: 1,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 原来已经是CENTER,现在改为BOTTOM
+            pixelOffset: new Cesium.Cartesian2(80, -50), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 5010米内
+              1.2, // 1倍大小
+              9000, // 10000米外
+              1 // 0.1倍大小
+            ),
+
+            // 透明度渐变
+            // translucencyByDistance: new Cesium.NearFarScalar(
+            //   6000, // 500米内
+            //   1.0, // 完全不透明
+            //   9000, // 3000米外
+            //   0.5 // 完全透明
+            // ),
+          },
+        });
+
+        entityxy.fjbh = model.fjbh;
+        this.entityxyArray.push(entityxy);
+      }
     },
+
     // 右键展示元素
     showRightClickPopup(screenPosition, val) {
       // 创建或获取弹框元素

+ 1 - 1
src/views/cesiumComponents/windView.vue

@@ -37,7 +37,7 @@
                 <el-option
                 v-for="(item, index) in fjLonLatJsonArr"
                 :key="index"
-                :label="item.name"
+                :label="item.fjbh"
                 :value="index"
                 />
             </el-select>

+ 1 - 1
src/views/fjLonLatJson/fj_MY.json

@@ -3,7 +3,7 @@
         {
             "longitude": 114.49562,
             "latitude": 35.35543,
-            "jbh": "001",
+            "fjbh": "001",
             "status": 1,
             "height": 1000
         },