Koishi hai 10 meses
pai
achega
19bbdeb1e7

+ 77 - 72
src/tools/lightsign.js

@@ -1,6 +1,6 @@
 export default class AdvancedBillboardGenerator {
   constructor() {
-    this.cache = new Map();
+    // this.cache = new Map();
   }
 
   // 生成高级灯牌
@@ -8,7 +8,7 @@ export default class AdvancedBillboardGenerator {
     const {
       title,
       statusItems = [],
-      width = 120,
+      width = 140,
       backgroundColor = "rgba(13, 38, 77, 0.95)",
       borderGradient = ["#00e5ff", "#0077ff"],
       titleColor = "#4fc3f7",
@@ -16,19 +16,21 @@ export default class AdvancedBillboardGenerator {
       labelColor = "#b3e5fc",
       padding = 8,
       titleHeight = 30,
-      itemHeight = 25,
+      itemHeight = 24,
       titleStrokeStyle = "#000",
       titleStrokeWidth = 0,
       labelStrokeStyle = "#000",
       labelStrokeWidth = 0,
       valueStrokeStyle = "#000",
       valueStrokeWidth = 0,
+      showzb = true,
     } = options;
 
-    const cacheKey = JSON.stringify(options);
-    if (this.cache.has(cacheKey)) {
-      return this.cache.get(cacheKey);
-    }
+    // const cacheKey = JSON.stringify(options);
+    // const cacheKey = title;
+    // if (this.cache.has(cacheKey)) {
+    //   return this.cache.get(cacheKey);
+    // }
 
     const canvas = document.createElement("canvas");
     const ctx = canvas.getContext("2d");
@@ -51,56 +53,59 @@ export default class AdvancedBillboardGenerator {
     );
 
     // 绘制标题
-    ctx.fillStyle = titleColor;
-    ctx.font = "bold 14px sans-serif";
-    ctx.textAlign = "center";
-
-    // 绘制描边
-    if (titleStrokeWidth > 0) {
-      ctx.strokeStyle = titleStrokeStyle;
-      ctx.lineWidth = titleStrokeWidth;
-      ctx.strokeText(title, width / 2, padding + 14);
-    }
+    if (showzb) {
+      ctx.fillStyle = titleColor;
+      ctx.font = "bold 14px sans-serif";
+      ctx.textAlign = "center";
+
+      // 绘制描边
+      if (titleStrokeWidth > 0) {
+        ctx.strokeStyle = titleStrokeStyle;
+        ctx.lineWidth = titleStrokeWidth;
+        ctx.strokeText(title, width / 2, padding + 14);
+      }
 
-    ctx.fillText(title, width / 2, padding + 14);
+      ctx.fillText(title, width / 2, padding + 14);
 
-    // 绘制状态项
-    statusItems.forEach((item, index) => {
-      const y = titleHeight + padding + index * itemHeight;
+      // 绘制状态项
+      statusItems.forEach((item, index) => {
+        const y = titleHeight + padding + index * itemHeight;
 
-      // 标签
-      ctx.fillStyle = labelColor;
-      ctx.font = "12px sans-serif";
-      ctx.textAlign = "left";
+        // 标签
+        ctx.fillStyle = labelColor;
+        ctx.font = "12px sans-serif";
+        ctx.textAlign = "left";
 
-      // 绘制 label 描边
-      if (labelStrokeWidth > 0) {
-        ctx.strokeStyle = labelStrokeStyle;
-        ctx.lineWidth = labelStrokeWidth;
-        ctx.strokeText(item.label, padding, y + 12);
-      }
+        // 绘制 label 描边
+        if (labelStrokeWidth > 0) {
+          ctx.strokeStyle = labelStrokeStyle;
+          ctx.lineWidth = labelStrokeWidth;
+          ctx.strokeText(item.label, padding, y + 12);
+        }
 
-      ctx.fillText(item.label + ":", padding, y + 12);
+        ctx.fillText(item.label + ":", padding, y + 12);
 
-      // 值
-      ctx.fillStyle = valueColor;
-      ctx.font = "bold 12px sans-serif";
-      ctx.textAlign = "right";
+        // 值
+        ctx.fillStyle = valueColor;
+        ctx.font = "bold 12px sans-serif";
+        ctx.textAlign = "left";
 
-      // 绘制 value 描边
-      if (valueStrokeWidth > 0) {
-        ctx.strokeStyle = valueStrokeStyle;
-        ctx.lineWidth = valueStrokeWidth;
-        ctx.strokeText(item.value, width - padding, y + 12);
-      }
+        // 绘制 value 描边
+        if (valueStrokeWidth > 0) {
+          ctx.strokeStyle = valueStrokeStyle;
+          ctx.lineWidth = valueStrokeWidth;
+          ctx.strokeText(item.value, width / 2 - padding / 2, y + 12);
+        }
 
-      ctx.fillText(item.value, width - padding, y + 12);
-    });
+        ctx.fillText(item.value, width / 2 - padding / 2, y + 12);
+      });
+    }
 
-    const dataURL = canvas.toDataURL();
-    this.cache.set(cacheKey, dataURL);
+    // const dataURL = canvas.toDataURL();
+    // this.cache.set(cacheKey, dataURL);
+    // this.cache.set(cacheKey, canvas);
 
-    return dataURL;
+    return canvas;
   }
 
   drawAdvancedBackground(ctx, width, height, bgColor, borderGradient) {
@@ -114,34 +119,35 @@ export default class AdvancedBillboardGenerator {
     gradient.addColorStop(0, borderGradient[0]);
     gradient.addColorStop(1, borderGradient[1]);
 
-    this.drawRoundedRect(
-      ctx,
-      2,
-      2,
-      width - 4,
-      height - 4,
-      borderRadius - 2,
-      gradient,
-      2
-    );
+    // this.drawRoundedRect(
+    //   ctx,
+    //   2,
+    //   2,
+    //   width - 4,
+    //   height - 4,
+    //   borderRadius - 2,
+    //   gradient,
+    //   2
+    // );
 
     // 内发光效果
-    ctx.shadowColor = borderGradient[0];
-    ctx.shadowBlur = 10;
-    this.drawRoundedRect(
-      ctx,
-      4,
-      4,
-      width - 8,
-      height - 8,
-      borderRadius - 4,
-      "transparent",
-      1
-    );
-    ctx.shadowBlur = 0;
+    // ctx.shadowColor = borderGradient[0];
+    // ctx.shadowBlur = 10;
+    // this.drawRoundedRect(
+    //   ctx,
+    //   4,
+    //   4,
+    //   width - 8,
+    //   height - 8,
+    //   borderRadius - 4,
+    //   "transparent",
+    //   2
+    // );
+    // ctx.shadowBlur = 0;
   }
 
   drawRoundedRect(ctx, x, y, width, height, radius, color, lineWidth = 0) {
+    radius = 0;
     ctx.beginPath();
     ctx.moveTo(x + radius, y);
     ctx.lineTo(x + width - radius, y);
@@ -158,8 +164,7 @@ export default class AdvancedBillboardGenerator {
       ctx.strokeStyle = color;
       ctx.lineWidth = lineWidth;
       ctx.stroke();
-    }
-    else {
+    } else {
       ctx.fillStyle = color;
       ctx.fill();
     }

+ 2 - 2
src/tools/ws.js

@@ -2,8 +2,8 @@ class WebSocketService {
     constructor() {
         this.socket = null;
         this.reconnectAttempts = 0;
-        this.maxReconnectAttempts = 5;
-        this.reconnectInterval = 3000; // 3秒
+        this.maxReconnectAttempts = 5; // 5 次
+        this.reconnectInterval = 3; // 3 秒
         this.messageHandlers = new Map();
         this.isConnected = false;
         this.url = null;

+ 240 - 139
src/views/cesiumComponents/windMap2D.vue

@@ -130,7 +130,7 @@ import ModelUnpack from "@/components/modelUnpack.vue";
 import { WindLayer } from "cesium-wind";
 import windGridData from "./windGridData.json";
 
-import AdvancedBillboardGenerator from "@/tools/lightsign.js";
+// import AdvancedBillboardGenerator from "@/tools/lightsign.js";
 
 // import { useWebSocket } from "@/tools/websocket.js";
 
@@ -202,7 +202,7 @@ export default {
       allStationentitys: [],
       allWindEntitys: [],
       urlTiles: "/public/static/tiles/{z}/{x}/{y}.jpg",
-      entityxyArray: [],
+      zbLabelList: [],
       isFakeData: false,
       fakeDataTimmer: null,
     };
@@ -438,7 +438,7 @@ export default {
         },
         onError: (error) => {
           console.log("❌ WebSocket 错误:", error);
-          return;
+          return
           if (stationName === "MYFDC") {
             fjLonLatJson = JSON.parse(JSON.stringify(fjMYLonLatJson));
           } else if (stationName === "JNWHZ") {
@@ -449,7 +449,7 @@ export default {
             fjLonLatJson = JSON.parse(JSON.stringify(fjSMSLonLatJson));
           }
 
-          let wtArray = wsRes.windMachineList;
+          let wtArray = JSON.parse(JSON.stringify(wsRes.windMachineList));
           this.isFakeData = true;
 
           this.fakeDataTimmer = setInterval(() => {
@@ -479,6 +479,7 @@ export default {
                   this.showAnimatewind(viewer, e);
                 }
               }
+              this.changeZb(fjMix);
             });
 
             this.fjLonLatJsonArr = fjLonLatJson;
@@ -524,6 +525,7 @@ export default {
               this.showAnimatewind(viewer, e);
             }
           }
+          this.changeZb(fjMix);
         });
 
         this.fjLonLatJsonArr = fjLonLatJson;
@@ -606,96 +608,94 @@ export default {
     addSvg(viewer, uri, lon, lat, val, index) {
       let that = this;
       const findRes =
-        that.entityxyArray.find((findEle) => {
+        that.zbLabelList.find((findEle) => {
           return findEle.fjbh === val.fjbh;
         }) || null;
-      if (findRes) {
-        this.changeFjData(val);
-      } else {
+      if (!findRes) {
         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 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 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 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");
 
@@ -726,7 +726,7 @@ export default {
           },
           label: {
             // text: val.name ? val.name : val.plantname,
-            text: val.name,
+            text: val.fjbh,
             font: "14px sans-serif",
             fillColor: Cesium.Color.fromBytes(255, 255, 255),
           },
@@ -746,66 +746,167 @@ export default {
           }
         }, 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;
+    changeZb(model) {
+      const glText = this.isFakeData
+        ? this.randomNum(100, 1000)
+        : model.actualPower.toFixed(2);
+
+      const fsText = this.isFakeData
+        ? this.randomNum(100, 1000)
+        : model.rotateSpeed.toFixed(2);
+
+      const zsText = this.isFakeData
+        ? this.randomNum(100, 1000)
+        : model.windSpeed.toFixed(2);
+
+      const zbMap = {
+        glText: `${glText} MW`,
+        fsText: `${fsText} m/s`,
+        zsText: `${zsText} p`,
+      };
+
+      const position = Cesium.Cartesian3.fromDegrees(
+        model.longitude,
+        model.latitude,
+        0
+      );
+
+      const zbhj =
+        this.zbLabelList.find((ele) => {
+          return ele.fjbh === model.fjbh;
         }) || null;
-      if (findRes) {
-        const statusItems = [
-          {
-            label: "功率",
-            value: `${
-              this.isFakeData
-                ? this.randomNum(100, 1000)
-                : fjItem.actualPower.toFixed(2)
-            }MW`,
+
+      if (zbhj?.fjbh) {
+        zbhj.zb.forEach((ele) => {
+          if (ele.zb) {
+            const spText = ele.label.text._value.split(": ");
+            ele.label.text._value = `${spText[0]}: ${zbMap[ele.zb]}`;
+          }
+        });
+      } else {
+        const wtName = this.viewer.entities.add({
+          position,
+          label: {
+            text: model.fjbh,
+            font: "14pt sans-serif",
+            fillColor: new Cesium.Color.fromCssColorString("#4fc3f7"), // 填充颜色
+            outlineColor: Cesium.Color.BLACK, // 轮廓颜色
+            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+            outlineWidth: 2,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            showBackground: false, // 显示背景
+            backgroundColor: new Cesium.Color.fromCssColorString(
+              "rgba(13, 38, 77, 0.5)"
+            ), // 背景颜色
+            backgroundPadding: new Cesium.Cartesian2(10, 10), // 背景内边距
+            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直对齐方式
+            horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平对齐方式
+            pixelOffset: new Cesium.Cartesian2(80, -60), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 6000米内
+              1,
+              9000, // 9000米外
+              0.8
+            ),
           },
-          {
-            label: "风速",
-            value: `${
-              this.isFakeData
-                ? this.randomNum(100, 1000)
-                : fjItem.windSpeed.toFixed(1)
-            }m/s`,
+        });
+
+        const glZb = this.viewer.entities.add({
+          position,
+          label: {
+            text: `功率: ${glText} MW`,
+            font: "14pt sans-serif",
+            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+            outlineWidth: 2,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            showBackground: false, // 显示背景
+            backgroundColor: new Cesium.Color.fromCssColorString(
+              "rgba(13, 38, 77, 0.5)"
+            ), // 背景颜色
+            backgroundPadding: new Cesium.Cartesian2(10, 10), // 背景内边距
+            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直对齐方式
+            horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平对齐方式
+            pixelOffset: new Cesium.Cartesian2(80, -40), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 6000米内
+              1,
+              9000, // 9000米外
+              0.8
+            ),
           },
-          {
-            label: "转速",
-            value: `${
-              this.isFakeData
-                ? this.randomNum(100, 1000)
-                : fjItem.rotateSpeed.toFixed(1)
-            }p`,
+        });
+
+        glZb.zb = "glText";
+
+        const fsZb = this.viewer.entities.add({
+          position,
+          label: {
+            text: `风速: ${fsText}`,
+            font: "14pt sans-serif",
+            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+            outlineWidth: 2,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            showBackground: false, // 显示背景
+            backgroundColor: new Cesium.Color.fromCssColorString(
+              "rgba(13, 38, 77, 0.5)"
+            ), // 背景颜色
+            backgroundPadding: new Cesium.Cartesian2(10, 10), // 背景内边距
+            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直对齐方式
+            horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平对齐方式
+            pixelOffset: new Cesium.Cartesian2(80, -20), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 6000米内
+              1,
+              9000, // 9000米外
+              0.8
+            ),
           },
-        ];
+        });
 
-        // 使用高级灯牌生成器
-        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,
+        fsZb.zb = "fsText";
+
+        const zsZb = this.viewer.entities.add({
+          position,
+          label: {
+            text: `转速: ${zsText}`,
+            font: "14pt sans-serif",
+            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+            outlineWidth: 2,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            showBackground: false, // 显示背景
+            backgroundColor: new Cesium.Color.fromCssColorString(
+              "rgba(13, 38, 77, 0.5)"
+            ), // 背景颜色
+            backgroundPadding: new Cesium.Cartesian2(10, 10), // 背景内边距
+            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直对齐方式
+            horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平对齐方式
+            pixelOffset: new Cesium.Cartesian2(80, 0), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 6000米内
+              1,
+              9000, // 9000米外
+              0.8
+            ),
+          },
         });
 
-        findRes.billboard.image._value = billboardImage;
+        zsZb.zb = "zsText";
+
+        this.zbLabelList.push({
+          fjbh: model.fjbh,
+          zb: [wtName, glZb, fsZb, zsZb],
+        });
       }
     },
 

+ 330 - 136
src/views/cesiumComponents/windMap3D.vue

@@ -108,7 +108,7 @@ import hd from "@/assets/windimgs/fanSvg/hd.png";
 //光伏电站展示图标
 import gf from "@/assets/windimgs/fanSvg/gf.png";
 
-import benchmark from "@/assets/cesiumImg/benchmark.png"
+import benchmark from "@/assets/cesiumImg/benchmark.png";
 
 import windHome from "@/components/windHome/index.vue";
 import windPro from "@/components/windProDetail/windProblem.vue";
@@ -122,6 +122,8 @@ import AdvancedBillboardGenerator from "@/tools/lightsign.js";
 
 import webSocketService from "@/tools/ws.js";
 
+// const advancedGenerator = new AdvancedBillboardGenerator();
+
 export default {
   name: "windMap3D",
   components: {
@@ -134,7 +136,7 @@ export default {
   },
   data() {
     return {
-        benchmark,
+      benchmark,
       restLatLon: [
         {
           longitude: 114.48789,
@@ -194,6 +196,7 @@ export default {
       isFakeData: false,
       fakeDataTimmer: null,
       isFirstAdd: true,
+      zbLabelList: [],
     };
   },
   mounted() {
@@ -505,6 +508,7 @@ export default {
         },
         onError: (error) => {
           console.log("❌ WebSocket 错误:", error);
+          return;
           if (stationName === "MYFDC") {
             fjLonLatJson = JSON.parse(JSON.stringify(fjMYLonLatJson));
           } else if (stationName === "JNWHZ") {
@@ -532,18 +536,12 @@ export default {
           this.fjLonLatJsonArr = fjLonLatJson;
 
           this.fakeDataTimmer = setInterval(() => {
-            // viewer.entities.removeAll();
-
-            fjLonLatJson.data.forEach((e) => {
-              let fjItem =
-                wtArray.find((findEle) => {
-                  return findEle.fjbh === e.fjbh;
+            wtArray.forEach((fjzbItem) => {
+              const jwdItem =
+                fjLonLatJson.data.find((findEle) => {
+                  return findEle.fjbh === fjzbItem.fjbh;
                 }) || {};
-              const fjMix = Object.assign({}, e, fjItem);
-              fjMix.status = this.getStatus(fjMix.fjzt);
-              e = fjMix;
-
-              this.changeZb(e);
+              this.changeZb(Object.assign({}, jwdItem, fjzbItem));
             });
           }, 1000);
         },
@@ -579,15 +577,12 @@ export default {
         this.fjLonLatJsonArr = fjLonLatJson;
         this.isFirstAdd = false;
 
-        fjLonLatJson.data.forEach((e) => {
-          let fjItem =
-            wtArray.find((findEle) => {
-              return findEle.fjbh === e.fjbh;
+        wtArray.forEach((fjzbItem) => {
+          const jwdItem =
+            fjLonLatJson.data.find((findEle) => {
+              return findEle.fjbh === fjzbItem.fjbh;
             }) || {};
-          const fjMix = Object.assign({}, e, fjItem);
-          fjMix.status = this.getStatus(fjMix.fjzt);
-          e = fjMix;
-          this.changeZb(e);
+          this.changeZb(Object.assign({}, jwdItem, fjzbItem));
         });
       });
 
@@ -738,16 +733,16 @@ export default {
       const statueZh = this.getWtStatue(status, "zh");
 
       if (model.bgFj === "1") {
-            const benchmark = viewer.entities.add({
-                position,
-                billboard: { 
-                    image: that.benchmark, 
-                    scale: 0.8,
-                    pixelOffset: new Cesium.Cartesian2(50, -25),
-                    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
-                } // 偏移避免重叠
-            });
-        }
+        const benchmark = viewer.entities.add({
+          position,
+          billboard: {
+            image: that.benchmark,
+            scale: 0.8,
+            pixelOffset: new Cesium.Cartesian2(50, -25),
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+          }, // 偏移避免重叠
+        });
+      }
 
       const entity = viewer.entities.add({
         name, // 模型名称
@@ -820,9 +815,6 @@ export default {
         }
       }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
 
-      // 使用高级灯牌生成器
-      const advancedGenerator = new AdvancedBillboardGenerator();
-
       let statusItems = [
         {
           label: "功率",
@@ -830,7 +822,7 @@ export default {
             this.isFakeData
               ? this.randomNum(100, 1000)
               : model.actualPower.toFixed(2)
-          }MW`,
+          } MW`,
         },
         {
           label: "风速",
@@ -838,7 +830,7 @@ export default {
             this.isFakeData
               ? this.randomNum(100, 1000)
               : model.windSpeed.toFixed(1)
-          }m/s`,
+          } m/s`,
         },
         {
           label: "转速",
@@ -846,119 +838,322 @@ export default {
             this.isFakeData
               ? this.randomNum(100, 1000)
               : model.rotateSpeed.toFixed(1)
-          }p`,
+          } 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;
+      // const billboardImage = advancedGenerator.generateAdvancedBillboard({
+      //   title: name,
+      //   statusItems,
+      //   borderGradient: ["#ccc", "#ccc"],
+      //   backgroundColor: "rgba(13, 38, 77, 0.5)",
+      //   padding: 6,
+      //   titleHeight: 22,
+      //   itemHeight: 17,
+      //   titleColor: "#1890ff",
+      //   titleStrokeStyle: "#000",
+      //   titleStrokeWidth: 1,
+      //   labelStrokeStyle: "#000",
+      //   labelStrokeWidth: 1,
+      //   valueStrokeStyle: "#000",
+      //   valueStrokeWidth: 1,
+      // });
 
-      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 // 完全透明
-          // ),
-        },
-      });
+      // let entityxy =
+      //   this.entityxyArray.find((findEle) => {
+      //     return findEle.fjbh === model.fjbh;
+      //   }) || null;
+
+      // 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);
+      // entityxy.fjbh = model.fjbh;
+      // this.entityxyArray.push(entityxy);
     },
 
     changeZb(model) {
       // 使用高级灯牌生成器
-      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 glText = this.isFakeData
+        ? this.randomNum(100, 1000)
+        : model.actualPower.toFixed(2);
+
+      const fsText = this.isFakeData
+        ? this.randomNum(100, 1000)
+        : model.rotateSpeed.toFixed(2);
+
+      const zsText = this.isFakeData
+        ? this.randomNum(100, 1000)
+        : model.windSpeed.toFixed(2);
+
+      const zbMap = {
+        glText: `${glText} MW`,
+        fsText: `${fsText} m/s`,
+        zsText: `${zsText} p`,
+      };
 
-      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: model.fjbh,
-        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 position = Cesium.Cartesian3.fromDegrees(
+        model.longitude,
+        model.latitude,
+        0
+      );
 
-      let entityxy =
-        this.entityxyArray.find((findEle) => {
-          return findEle.fjbh === model.fjbh;
+      const zbhj =
+        this.zbLabelList.find((ele) => {
+          return ele.fjbh === model.fjbh;
         }) || null;
 
-      if (entityxy) {
-        entityxy.billboard.image._value = billboardImage;
+      if (zbhj?.fjbh) {
+        zbhj.zb.forEach((ele) => {
+          if (ele.zb) {
+            const spText = ele.label.text._value.split(": ");
+            ele.label.text._value = `${spText[0]}: ${zbMap[ele.zb]}`;
+          }
+        });
+      } else {
+        const wtName = this.viewer.entities.add({
+          position,
+          label: {
+            text: model.fjbh,
+            font: "14pt sans-serif",
+            fillColor: new Cesium.Color.fromCssColorString("#4fc3f7"), // 填充颜色
+            outlineColor: Cesium.Color.BLACK, // 轮廓颜色
+            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+            outlineWidth: 2,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            showBackground: false, // 显示背景
+            backgroundColor: new Cesium.Color.fromCssColorString(
+              "rgba(13, 38, 77, 0.5)"
+            ), // 背景颜色
+            backgroundPadding: new Cesium.Cartesian2(10, 10), // 背景内边距
+            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直对齐方式
+            horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平对齐方式
+            pixelOffset: new Cesium.Cartesian2(80, -60), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 6000米内
+              1,
+              9000, // 9000米外
+              0.8
+            ),
+          },
+        });
+
+        const glZb = this.viewer.entities.add({
+          position,
+          label: {
+            text: `功率: ${glText} MW`,
+            font: "14pt sans-serif",
+            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+            outlineWidth: 2,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            showBackground: false, // 显示背景
+            backgroundColor: new Cesium.Color.fromCssColorString(
+              "rgba(13, 38, 77, 0.5)"
+            ), // 背景颜色
+            backgroundPadding: new Cesium.Cartesian2(10, 10), // 背景内边距
+            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直对齐方式
+            horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平对齐方式
+            pixelOffset: new Cesium.Cartesian2(80, -40), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 6000米内
+              1,
+              9000, // 9000米外
+              0.8
+            ),
+          },
+        });
+
+        glZb.zb = "glText";
+
+        const fsZb = this.viewer.entities.add({
+          position,
+          label: {
+            text: `风速: ${fsText}`,
+            font: "14pt sans-serif",
+            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+            outlineWidth: 2,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            showBackground: false, // 显示背景
+            backgroundColor: new Cesium.Color.fromCssColorString(
+              "rgba(13, 38, 77, 0.5)"
+            ), // 背景颜色
+            backgroundPadding: new Cesium.Cartesian2(10, 10), // 背景内边距
+            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直对齐方式
+            horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平对齐方式
+            pixelOffset: new Cesium.Cartesian2(80, -20), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 6000米内
+              1,
+              9000, // 9000米外
+              0.8
+            ),
+          },
+        });
+
+        fsZb.zb = "fsText";
+
+        const zsZb = this.viewer.entities.add({
+          position,
+          label: {
+            text: `转速: ${zsText}`,
+            font: "14pt sans-serif",
+            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+            outlineWidth: 2,
+            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+            showBackground: false, // 显示背景
+            backgroundColor: new Cesium.Color.fromCssColorString(
+              "rgba(13, 38, 77, 0.5)"
+            ), // 背景颜色
+            backgroundPadding: new Cesium.Cartesian2(10, 10), // 背景内边距
+            verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直对齐方式
+            horizontalOrigin: Cesium.HorizontalOrigin.LEFT, // 水平对齐方式
+            pixelOffset: new Cesium.Cartesian2(80, 0), // 原来是-20,现在改为30,向上移动
+            eyeOffset: new Cesium.Cartesian3(0, 0, 0), // 保持固定大小
+            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+            scaleByDistance: new Cesium.NearFarScalar(
+              6000, // 6000米内
+              1,
+              9000, // 9000米外
+              0.8
+            ),
+          },
+        });
+
+        zsZb.zb = "zsText";
+
+        this.zbLabelList.push({
+          fjbh: model.fjbh,
+          zb: [wtName, glZb, fsZb, zsZb],
+        });
       }
+
+      // entity.label.text._value
+      // const billboardImage = advancedGenerator.generateAdvancedBillboard({
+      //   title: model.fjbh,
+      //   statusItems,
+      //   borderGradient: ["#ccc", "#ccc"],
+      //   backgroundColor: "rgba(13, 38, 77, 0.5)",
+      //   padding: 6,
+      //   titleHeight: 22,
+      //   itemHeight: 17,
+      //   titleColor: "#1890ff",
+      //   titleStrokeStyle: "#000",
+      //   titleStrokeWidth: 1,
+      //   labelStrokeStyle: "#000",
+      //   labelStrokeWidth: 1,
+      //   valueStrokeStyle: "#000",
+      //   valueStrokeWidth: 1,
+      // });
+
+      // this.billboardImageList.push(billboardImage);
+
+      // let entityxy =
+      //   this.entityxyArray.find((findEle) => {
+      //     return findEle.fjbh === model.fjbh;
+      //   }) || null;
+
+      // for (let i = 0; i < this.entityxyArray.length; i++) {
+      //   if (this.entityxyArray[i].fjbh === model.fjbh) {
+      //     let entityxy = Cesium.clone(this.entityxyArray[i]);
+      //     entityxy.fjbh = this.entityxyArray[i].fjbh;
+      //     entityxy.billboard = null;
+      //     entityxy.billboard = {
+      //       image: billboardImage.toDataURL("image/png"),
+      //       scale: 1,
+      //       width: billboardImage.width,
+      //       height: billboardImage.height,
+      //       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.2倍大小
+      //         9000, // 10000米外
+      //         1 // 1.05倍大小
+      //       ),
+      //     };
+      //     this.viewer.entities.remove(this.entityxyArray[i]);
+      //     this.viewer.entities.add(entityxy);
+      //     this.entityxyArray.splice(i, 1, entityxy);
+      //     break;
+      //   }
+      // }
+
+      // if (entityxy) {
+      //   entityxy.billboard = {
+      //     image: billboardImage.toDataURL("image/png"),
+      //     scale: 1,
+      //     width: billboardImage.width,
+      //     height: billboardImage.height,
+      //     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.2倍大小
+      //       9000, // 10000米外
+      //       1 // 1.05倍大小
+      //     ),
+      //   };
+      // }
     },
 
     // 右键展示元素
@@ -1097,7 +1292,6 @@ export default {
       document.addEventListener("keydown", keyDownHandler);
     },
     showMessage(type, val) {
-      console.log("type===>>>", type);
       this.windDrawer = true;
       this.windDrawerHeader = val.name + "数据详情";
       if (type === "basic") {