更改底图颜色
This commit is contained in:
		
							parent
							
								
									d8f87fdf88
								
							
						
					
					
						commit
						0e36765929
					
				| 
						 | 
				
			
			@ -14,6 +14,7 @@
 | 
			
		|||
        "@vue-office/excel": "^1.7.11",
 | 
			
		||||
        "@vue-office/pdf": "^2.0.10",
 | 
			
		||||
        "axios": "^1.1.3",
 | 
			
		||||
        "be-full": "^0.1.4",
 | 
			
		||||
        "core-js": "^3.8.3",
 | 
			
		||||
        "echarts": "^5.5.1",
 | 
			
		||||
        "echarts-gl": "^2.0.9",
 | 
			
		||||
| 
						 | 
				
			
			@ -5289,6 +5290,11 @@
 | 
			
		|||
      "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/be-full": {
 | 
			
		||||
      "version": "0.1.4",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/be-full/-/be-full-0.1.4.tgz",
 | 
			
		||||
      "integrity": "sha512-Nj3yBvk8rxhBhDv6YROxP9ynTA5H0l9lMjU+XqEAY4rTLJ68l2+n0geWCoeTqAxhOFedtbmYCpxFzMxMA8CnUg=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/big.js": {
 | 
			
		||||
      "version": "5.2.2",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/big.js/-/big.js-5.2.2.tgz",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
    "@vue-office/excel": "^1.7.11",
 | 
			
		||||
    "@vue-office/pdf": "^2.0.10",
 | 
			
		||||
    "axios": "^1.1.3",
 | 
			
		||||
    "be-full": "^0.1.4",
 | 
			
		||||
    "core-js": "^3.8.3",
 | 
			
		||||
    "echarts": "^5.5.1",
 | 
			
		||||
    "echarts-gl": "^2.0.9",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,7 +83,7 @@
 | 
			
		|||
        height: 100%;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        flex-wrap: wrap;
 | 
			
		||||
        flex-wrap: nowrap;
 | 
			
		||||
        .el-form-item {
 | 
			
		||||
          margin-right: 3%;
 | 
			
		||||
          margin-bottom: 13px;
 | 
			
		||||
| 
						 | 
				
			
			@ -596,3 +596,60 @@
 | 
			
		|||
.el-picker-panel__icon-btn {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
.custom-class {
 | 
			
		||||
  .el-dialog {
 | 
			
		||||
    height: 50% !important;
 | 
			
		||||
    .el-dialog__header {
 | 
			
		||||
      .el-dialog__headerbtn {
 | 
			
		||||
        top: 30px;
 | 
			
		||||
        right: 40px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .el-dialog__body {
 | 
			
		||||
      height: calc(100% - 140px);
 | 
			
		||||
      .block {
 | 
			
		||||
        width: 80%;
 | 
			
		||||
        margin: 0 auto;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        .demonstration {
 | 
			
		||||
          width: 100px;
 | 
			
		||||
          color: #fff;
 | 
			
		||||
        }
 | 
			
		||||
        .el-slider {
 | 
			
		||||
          width: calc(100% - 120px);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .el-dialog__footer {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
.custom-table {
 | 
			
		||||
  .el-dialog {
 | 
			
		||||
    height: 80% !important;
 | 
			
		||||
    .el-dialog__header {
 | 
			
		||||
      .el-dialog__headerbtn {
 | 
			
		||||
        top: 30px;
 | 
			
		||||
        right: 40px;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .el-dialog__body {
 | 
			
		||||
      height: calc(100% - 110px);
 | 
			
		||||
 | 
			
		||||
      .table-container {
 | 
			
		||||
        height: calc(100% - 50px);
 | 
			
		||||
        margin-top: 0;
 | 
			
		||||
        padding-top: 0;
 | 
			
		||||
        .table-box {
 | 
			
		||||
          height: 90%;
 | 
			
		||||
          .el-table__body-wrapper {
 | 
			
		||||
            overflow: auto;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    .el-dialog__footer {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,8 @@ import {
 | 
			
		|||
  Upload,
 | 
			
		||||
  Dropdown,
 | 
			
		||||
  DropdownMenu,
 | 
			
		||||
  DropdownItem
 | 
			
		||||
  DropdownItem,
 | 
			
		||||
  Slider
 | 
			
		||||
} from "element-ui";
 | 
			
		||||
import "element-ui/lib/theme-chalk/index.css";
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +68,7 @@ Vue.use(Switch);
 | 
			
		|||
Vue.use(Timeline);
 | 
			
		||||
Vue.use(TimelineItem);
 | 
			
		||||
Vue.use(Upload);
 | 
			
		||||
Vue.use(Slider);
 | 
			
		||||
 | 
			
		||||
Vue.prototype.$message = Message;
 | 
			
		||||
Vue.prototype.$confirm = MessageBox.confirm;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,9 @@ const getters = {
 | 
			
		|||
  targetCode: (state) => state.chart.targetCode, //防护目标单一点击更改两侧数据
 | 
			
		||||
  airspaceCode: (state) => state.chart.airspaceCode, //低空空域单一点击更改两侧数据
 | 
			
		||||
  positionPoint: (state) => state.chart.positionPoint, //实时位置更新
 | 
			
		||||
  isZoomedIn: (state) => state.chart.isZoomedIn //音频是否打开
 | 
			
		||||
  isZoomedIn: (state) => state.chart.isZoomedIn, //音频是否打开
 | 
			
		||||
  SliderValue: (state) => state.chart.SliderValue, //音量值
 | 
			
		||||
  checkFlag: (state) => state.chart.checkFlag, //轨迹查看按钮
 | 
			
		||||
  clearTrajectory: (state) => state.chart.clearTrajectory //清空轨迹
 | 
			
		||||
};
 | 
			
		||||
export default getters;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,10 @@ const user = {
 | 
			
		|||
    airspaceCode: {},
 | 
			
		||||
 | 
			
		||||
    positionPoint: false, // 位置上报
 | 
			
		||||
    isZoomedIn: true // 音频是否打开
 | 
			
		||||
    isZoomedIn: true, // 音频是否打开
 | 
			
		||||
    SliderValue: 0, // 音频滑动条值
 | 
			
		||||
    checkFlag: false, // 轨迹查看按钮
 | 
			
		||||
    clearTrajectory: false // 清除过往轨迹
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  mutations: {
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +41,15 @@ const user = {
 | 
			
		|||
    },
 | 
			
		||||
    SET_ISZOOMEDIN: (state, value) => {
 | 
			
		||||
      state.isZoomedIn = value;
 | 
			
		||||
    },
 | 
			
		||||
    SET_SILDERVALUE: (state, value) => {
 | 
			
		||||
      state.SliderValue = value;
 | 
			
		||||
    },
 | 
			
		||||
    SET_CHECKFLAG: (state, value) => {
 | 
			
		||||
      state.checkFlag = value;
 | 
			
		||||
    },
 | 
			
		||||
    SET_CLEARTRAJECTORY: (state, value) => {
 | 
			
		||||
      state.clearTrajectory = value;
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -190,7 +190,7 @@
 | 
			
		|||
      loop
 | 
			
		||||
      ref="uavAudio"
 | 
			
		||||
      v-show="iswarning"
 | 
			
		||||
      style="display: none"
 | 
			
		||||
      style="display: none; pointer-events: auto"
 | 
			
		||||
      id="uavAudio"
 | 
			
		||||
    >
 | 
			
		||||
      <source src="@/assets/img/wargin.mp3" type="audio/mpeg" />
 | 
			
		||||
| 
						 | 
				
			
			@ -211,7 +211,6 @@ import Style from "ol/style/Style";
 | 
			
		|||
import Stroke from "ol/style/Stroke";
 | 
			
		||||
import { fromLonLat, toLonLat } from "ol/proj";
 | 
			
		||||
import { whitListAdd } from "@/api/whitList.js";
 | 
			
		||||
import AMapLoader from "@amap/amap-jsapi-loader";
 | 
			
		||||
import QRCode from "qrcode";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
| 
						 | 
				
			
			@ -257,7 +256,7 @@ export default {
 | 
			
		|||
    };
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    ...mapGetters(["isZoomedIn"])
 | 
			
		||||
    ...mapGetters(["isZoomedIn", "SliderValue"])
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    this.endTime = moment.utc().format("YYYY-MM-DD HH:mm:ss");
 | 
			
		||||
| 
						 | 
				
			
			@ -276,6 +275,18 @@ export default {
 | 
			
		|||
      },
 | 
			
		||||
      deep: true
 | 
			
		||||
    },
 | 
			
		||||
    SliderValue: {
 | 
			
		||||
      handler(newVal) {
 | 
			
		||||
        if (newVal) {
 | 
			
		||||
          console.log("SliderValue:", newVal);
 | 
			
		||||
          const media = this.$refs.uavAudio;
 | 
			
		||||
          if (media) {
 | 
			
		||||
            media.volume = newVal / 100;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      deep: true
 | 
			
		||||
    },
 | 
			
		||||
    signaData: {
 | 
			
		||||
      handler(newVal) {
 | 
			
		||||
        if (newVal) {
 | 
			
		||||
| 
						 | 
				
			
			@ -359,8 +370,9 @@ export default {
 | 
			
		|||
          if (this.drones) {
 | 
			
		||||
            mapUavFiex(this.drones, window.olMap);
 | 
			
		||||
          }
 | 
			
		||||
          let alarm = this.drones.find((d) => d.alarmLevel === 1);
 | 
			
		||||
          let alarm = this.drones.find((d) => d.alarmLevel === 0);
 | 
			
		||||
          const media = this.$refs.uavAudio;
 | 
			
		||||
          const savedVolume = localStorage.getItem("soundValue");
 | 
			
		||||
          if (alarm) {
 | 
			
		||||
            this.iswarning = true;
 | 
			
		||||
            this.$nextTick(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -370,6 +382,11 @@ export default {
 | 
			
		|||
                  .play()
 | 
			
		||||
                  .then(() => {
 | 
			
		||||
                    console.log("播放成功,取消静音");
 | 
			
		||||
                    if (savedVolume !== null) {
 | 
			
		||||
                      media.volume = savedVolume / 100;
 | 
			
		||||
                    } else {
 | 
			
		||||
                      media.volume = 1;
 | 
			
		||||
                    }
 | 
			
		||||
                    if (this.isZoomedIn) {
 | 
			
		||||
                      media.muted = false; // 播放成功后取消静音
 | 
			
		||||
                    } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -468,6 +485,7 @@ export default {
 | 
			
		|||
    enableAudio() {
 | 
			
		||||
      this.iswarning = true;
 | 
			
		||||
      const media = this.$refs.uavAudio;
 | 
			
		||||
      const savedVolume = localStorage.getItem("soundValue");
 | 
			
		||||
      let time = setInterval(() => {
 | 
			
		||||
        console.log("用户手动启用音频", media);
 | 
			
		||||
        if (media !== undefined) {
 | 
			
		||||
| 
						 | 
				
			
			@ -477,6 +495,11 @@ export default {
 | 
			
		|||
          } else {
 | 
			
		||||
            media.muted = true; // 初始静音
 | 
			
		||||
          }
 | 
			
		||||
          if (savedVolume !== null) {
 | 
			
		||||
            media.volume = savedVolume / 100;
 | 
			
		||||
          } else {
 | 
			
		||||
            media.volume = 1;
 | 
			
		||||
          }
 | 
			
		||||
          media
 | 
			
		||||
            .play()
 | 
			
		||||
            .then(() => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@
 | 
			
		|||
import { mapGetters } from "vuex";
 | 
			
		||||
import { HomeSyncLocation } from "@/api/home";
 | 
			
		||||
import _ from "lodash";
 | 
			
		||||
import { fromLonLat } from "ol/proj";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "header-top",
 | 
			
		||||
| 
						 | 
				
			
			@ -41,12 +42,13 @@ export default {
 | 
			
		|||
      isAdmins: false,
 | 
			
		||||
      leftText: "平台已连接",
 | 
			
		||||
      rightText: "定位正常",
 | 
			
		||||
      latitude: null,
 | 
			
		||||
      longitude: null,
 | 
			
		||||
      latitude: "",
 | 
			
		||||
      longitude: "",
 | 
			
		||||
      lastUpdated: "",
 | 
			
		||||
      watchId: null,
 | 
			
		||||
      timer: null,
 | 
			
		||||
      showPermissionPrompt: false
 | 
			
		||||
      showPermissionPrompt: false,
 | 
			
		||||
      retryCount: 0
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
| 
						 | 
				
			
			@ -60,14 +62,15 @@ export default {
 | 
			
		|||
    this.timer = setInterval(() => {
 | 
			
		||||
      this.updateTime();
 | 
			
		||||
    }, 1000);
 | 
			
		||||
    this.$on("retry-tracking", this.startTracking);
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    positionPoint: {
 | 
			
		||||
      handler(newVal, oldVal) {
 | 
			
		||||
        if (newVal) {
 | 
			
		||||
          console.log("定位更新:", this.latitude, this.longitude);
 | 
			
		||||
          const newLocation = [this.longitude, this.latitude]; // 新的位置坐标
 | 
			
		||||
          const zoomLevel = 13; // 目标缩放级别
 | 
			
		||||
      handler(newVal) {
 | 
			
		||||
        if (newVal && this.latitude && this.longitude) {
 | 
			
		||||
          const newLocation = fromLonLat([this.longitude, this.latitude]);
 | 
			
		||||
          this.$message.success(this.longitude + "," + this.latitude);
 | 
			
		||||
          const zoomLevel = 13;
 | 
			
		||||
          window.olMap.getView().animate({
 | 
			
		||||
            center: newLocation,
 | 
			
		||||
            zoom: zoomLevel
 | 
			
		||||
| 
						 | 
				
			
			@ -75,9 +78,9 @@ export default {
 | 
			
		|||
          this.startTracking();
 | 
			
		||||
        }
 | 
			
		||||
        this.$store.commit("SET_POSITIONPOINT", false);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    deep: true
 | 
			
		||||
      },
 | 
			
		||||
      deep: true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    updateTime() {
 | 
			
		||||
| 
						 | 
				
			
			@ -97,9 +100,9 @@ export default {
 | 
			
		|||
        (position) => this.handleSuccess(position),
 | 
			
		||||
        (error) => this.handleError(error),
 | 
			
		||||
        {
 | 
			
		||||
          enableHighAccuracy: false,
 | 
			
		||||
          timeout: 15000,
 | 
			
		||||
          maximumAge: 0
 | 
			
		||||
          enableHighAccuracy: true,
 | 
			
		||||
          timeout: 30000,
 | 
			
		||||
          maximumAge: 10000
 | 
			
		||||
        }
 | 
			
		||||
      );
 | 
			
		||||
    },
 | 
			
		||||
| 
						 | 
				
			
			@ -119,13 +122,17 @@ export default {
 | 
			
		|||
          if (res.code === 0) {
 | 
			
		||||
            this.leftText = "平台已连接";
 | 
			
		||||
            this.rightText = "定位正常";
 | 
			
		||||
            if (!latitude && res.data.fallbackLocation) {
 | 
			
		||||
              this.handleSuccess({
 | 
			
		||||
                coords: { latitude: this.latitude, longitude: this.longitude }
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
          } else {
 | 
			
		||||
            this.leftText = "平台连接失败";
 | 
			
		||||
            this.rightText = "定位异常";
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
        .catch((err) => {
 | 
			
		||||
          console.error("上报失败:", err);
 | 
			
		||||
          this.leftText = "平台连接失败";
 | 
			
		||||
          this.rightText = "定位异常";
 | 
			
		||||
        });
 | 
			
		||||
| 
						 | 
				
			
			@ -135,10 +142,12 @@ export default {
 | 
			
		|||
      this.longitude = position.coords.longitude;
 | 
			
		||||
      this.lastUpdated = new Date().toLocaleString();
 | 
			
		||||
      this.showPermissionPrompt = false;
 | 
			
		||||
      this.retryCount = 0;
 | 
			
		||||
      this.syncLocation(this.latitude, this.longitude);
 | 
			
		||||
    },
 | 
			
		||||
    handleError(error) {
 | 
			
		||||
      let message = "";
 | 
			
		||||
      this.retryCount = this.retryCount || 0;
 | 
			
		||||
      switch (error.code) {
 | 
			
		||||
        case error.PERMISSION_DENIED:
 | 
			
		||||
          message = "请允许地理位置权限";
 | 
			
		||||
| 
						 | 
				
			
			@ -147,21 +156,31 @@ export default {
 | 
			
		|||
          break;
 | 
			
		||||
        case error.POSITION_UNAVAILABLE:
 | 
			
		||||
          message = "无法获取位置信息";
 | 
			
		||||
          setTimeout(() => this.startTracking(), 5000);
 | 
			
		||||
          if (this.retryCount < 3) {
 | 
			
		||||
            this.retryCount++;
 | 
			
		||||
            setTimeout(() => this.startTracking(), 5000);
 | 
			
		||||
          } else {
 | 
			
		||||
            this.$message.error("多次尝试后仍无法定位,请检查设备设置");
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        case error.TIMEOUT:
 | 
			
		||||
          message = "获取位置超时";
 | 
			
		||||
          setTimeout(() => this.startTracking(), 5000);
 | 
			
		||||
          if (this.retryCount < 3) {
 | 
			
		||||
            this.retryCount++;
 | 
			
		||||
            setTimeout(() => this.startTracking(), 5000);
 | 
			
		||||
          } else {
 | 
			
		||||
            this.$message.error("定位超时,请检查网络或 GPS 信号");
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
          message = "未知错误";
 | 
			
		||||
      }
 | 
			
		||||
      this.leftText = message;
 | 
			
		||||
      this.rightText = "定位异常";
 | 
			
		||||
      console.error("定位错误:", error);
 | 
			
		||||
    },
 | 
			
		||||
    retryTracking() {
 | 
			
		||||
      this.showPermissionPrompt = false;
 | 
			
		||||
      this.retryCount = 0;
 | 
			
		||||
      this.startTracking();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			@ -181,11 +200,9 @@ export default {
 | 
			
		|||
  font-size: 20px;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.time {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.actions span {
 | 
			
		||||
  margin-left: 10px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +215,8 @@ export default {
 | 
			
		|||
  padding: 15px;
 | 
			
		||||
  border: 1px solid #ddd;
 | 
			
		||||
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
 | 
			
		||||
  z-index: 1000;
 | 
			
		||||
  z-index: 10000;
 | 
			
		||||
  pointer-events: auto;
 | 
			
		||||
}
 | 
			
		||||
.permission-prompt p {
 | 
			
		||||
  margin: 0 0 10px;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +1,10 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <fit-screen :width="1280" :height="800" mode="fit">
 | 
			
		||||
    <div id="home">
 | 
			
		||||
      <contentData
 | 
			
		||||
        id="contentData"
 | 
			
		||||
        :signaData="signaData"
 | 
			
		||||
        :homeData="homeData"
 | 
			
		||||
      />
 | 
			
		||||
      <map-control
 | 
			
		||||
        id="mapControl"
 | 
			
		||||
        :signaData="signaData"
 | 
			
		||||
        :homeData="homeData"
 | 
			
		||||
      />
 | 
			
		||||
    </div>
 | 
			
		||||
  </fit-screen>
 | 
			
		||||
  <!-- <fit-screen :width="1280" :height="800" mode="fit"> -->
 | 
			
		||||
  <div id="home">
 | 
			
		||||
    <contentData id="contentData" :signaData="signaData" :homeData="homeData" />
 | 
			
		||||
    <map-control id="mapControl" :signaData="signaData" :homeData="homeData" />
 | 
			
		||||
  </div>
 | 
			
		||||
  <!-- </fit-screen> -->
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
| 
						 | 
				
			
			@ -21,6 +13,7 @@ import mapControl from "./mapControl/index.vue";
 | 
			
		|||
import contentData from "./contentData/index.vue";
 | 
			
		||||
import { Homeview } from "@/api/home.js";
 | 
			
		||||
import * as signalR from "@microsoft/signalr";
 | 
			
		||||
import { beFull } from "be-full";
 | 
			
		||||
export default {
 | 
			
		||||
  name: "HomeIndex",
 | 
			
		||||
  data() {
 | 
			
		||||
| 
						 | 
				
			
			@ -44,6 +37,21 @@ export default {
 | 
			
		|||
    this.timeInterval = setInterval(() => {
 | 
			
		||||
      this.initHomeData();
 | 
			
		||||
    }, 2000);
 | 
			
		||||
    // 全屏
 | 
			
		||||
    this.$confirm("是否全屏?", "提示", {
 | 
			
		||||
      confirmButtonText: "确定",
 | 
			
		||||
      cancelButtonText: "取消",
 | 
			
		||||
      type: "warning"
 | 
			
		||||
    })
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        beFull();
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
        this.$message({
 | 
			
		||||
          type: "info",
 | 
			
		||||
          message: "已取消"
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    initHomeData() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,6 @@
 | 
			
		|||
 | 
			
		||||
<script>
 | 
			
		||||
import { login, loginPosition } from "@/api/login.js";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "my-Login", // 组件名称
 | 
			
		||||
  data() {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +47,8 @@ export default {
 | 
			
		|||
      },
 | 
			
		||||
      errors: {},
 | 
			
		||||
      value: "",
 | 
			
		||||
      tipShow: false
 | 
			
		||||
      tipShow: false,
 | 
			
		||||
      positionList: []
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
| 
						 | 
				
			
			@ -91,6 +91,7 @@ export default {
 | 
			
		|||
            loginPosition(arrParams).then((positionRes) => {
 | 
			
		||||
              if (positionRes.code === 0) {
 | 
			
		||||
                localStorage.setItem("PositionIds", positionRes.data); // 阵地权限
 | 
			
		||||
                this.$message.success("登录成功");
 | 
			
		||||
              } else {
 | 
			
		||||
                this.$message.error(positionRes.msg);
 | 
			
		||||
              }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,11 +3,14 @@
 | 
			
		|||
    <div class="zoom-level" @click="soundAndMenu">
 | 
			
		||||
      <img :src="zoomLevelImage" alt="" />
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="btn-container" v-if="closeBtnVisible">
 | 
			
		||||
      <el-button @click="handleClickClose()">返回</el-button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div id="map" ref="olMap" class="map-container"></div>
 | 
			
		||||
    <div class="pointingNorth" @click="mapNorth">
 | 
			
		||||
      <img src="@/assets/img/user.png" alt="" />
 | 
			
		||||
      <img src="@/assets/img/setup.png" alt="" />
 | 
			
		||||
      <img src="@/assets/img/query.png" alt="" />
 | 
			
		||||
    <div class="pointingNorth">
 | 
			
		||||
      <img src="@/assets/img/user.png" alt="" @click="userOpen" />
 | 
			
		||||
      <img src="@/assets/img/setup.png" alt="" @click="setupOpen" />
 | 
			
		||||
      <img src="@/assets/img/query.png" alt="" @click="queryOpen" />
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="configuration">
 | 
			
		||||
      <div class="refresh" @click="refreshClick">
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +23,33 @@
 | 
			
		|||
        <img src="@/assets/img/icon_model.png" alt="" />
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <el-dialog
 | 
			
		||||
      title="设置"
 | 
			
		||||
      :visible.sync="dialogVisible"
 | 
			
		||||
      width="50%"
 | 
			
		||||
      :before-close="handleClose"
 | 
			
		||||
      append-to-body
 | 
			
		||||
      class="custom-class"
 | 
			
		||||
    >
 | 
			
		||||
      <div class="block">
 | 
			
		||||
        <span class="demonstration">预警声音设置</span>
 | 
			
		||||
        <el-slider v-model="value2"></el-slider>
 | 
			
		||||
      </div>
 | 
			
		||||
      <span slot="footer" class="dialog-footer">
 | 
			
		||||
        <el-button @click="dialogVisible = false">取 消</el-button>
 | 
			
		||||
        <el-button type="primary" @click="determine"> 确 定 </el-button>
 | 
			
		||||
      </span>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
    <el-dialog
 | 
			
		||||
      title="查询"
 | 
			
		||||
      :visible.sync="dialogQueryVisible"
 | 
			
		||||
      width="90%"
 | 
			
		||||
      :before-close="handleClose"
 | 
			
		||||
      append-to-body
 | 
			
		||||
      class="custom-table"
 | 
			
		||||
    >
 | 
			
		||||
      <AlertDialog />
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,31 +60,32 @@ import View from "ol/View";
 | 
			
		|||
import TileLayer from "ol/layer/Tile";
 | 
			
		||||
import { fromLonLat } from "ol/proj";
 | 
			
		||||
import XYZ from "ol/source/XYZ";
 | 
			
		||||
 | 
			
		||||
import VectorLayer from "ol/layer/Vector";
 | 
			
		||||
import VectorSource from "ol/source/Vector";
 | 
			
		||||
import Feature from "ol/Feature";
 | 
			
		||||
import Point from "ol/geom/Point";
 | 
			
		||||
import LineString from "ol/geom/LineString";
 | 
			
		||||
import Style from "ol/style/Style";
 | 
			
		||||
import Icon from "ol/style/Icon";
 | 
			
		||||
import Stroke from "ol/style/Stroke";
 | 
			
		||||
import Fill from "ol/style/Fill";
 | 
			
		||||
import Text from "ol/style/Text";
 | 
			
		||||
import CircleStyle from "ol/style/Circle";
 | 
			
		||||
import Static from "ol/source/ImageStatic.js";
 | 
			
		||||
 | 
			
		||||
import uaImg from "@/assets/img/icon_uav.png";
 | 
			
		||||
import { Feature, Overlay } from "ol";
 | 
			
		||||
import { Point, MultiPolygon } from "ol/geom";
 | 
			
		||||
import { Vector as VectorLayer } from "ol/layer";
 | 
			
		||||
import { Vector as VectorSource } from "ol/source";
 | 
			
		||||
import { Style, Fill, Stroke, Circle } from "ol/style";
 | 
			
		||||
import GeoJSON from "ol/format/GeoJSON";
 | 
			
		||||
import AlertDialog from "../menuData/AlertDialog.vue";
 | 
			
		||||
import { devPositionList } from "@/api/position.js";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: "HomeMap",
 | 
			
		||||
  components: {
 | 
			
		||||
    AlertDialog
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      map: null,
 | 
			
		||||
      zoomLevel: null,
 | 
			
		||||
      isZoomedIn: true,
 | 
			
		||||
      isZoomedOut: false,
 | 
			
		||||
      showPermissionPrompt: false
 | 
			
		||||
      showPermissionPrompt: false,
 | 
			
		||||
      dialogVisible: false,
 | 
			
		||||
      value2: 0,
 | 
			
		||||
      currentBaseMap: "gaode",
 | 
			
		||||
      dialogQueryVisible: false,
 | 
			
		||||
      closeBtnVisible: false
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  created() {
 | 
			
		||||
| 
						 | 
				
			
			@ -65,14 +96,127 @@ export default {
 | 
			
		|||
    this.initMap();
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    ...mapGetters(["statePage", "cityCode"]),
 | 
			
		||||
    ...mapGetters(["statePage", "cityCode", "checkFlag"]),
 | 
			
		||||
    zoomLevelImage() {
 | 
			
		||||
      return this.isZoomedIn
 | 
			
		||||
        ? require("@/assets/img/sound.png")
 | 
			
		||||
        : require("@/assets/img/mute.png");
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    checkFlag: {
 | 
			
		||||
      handler(newVal) {
 | 
			
		||||
        this.closeBtnVisible = newVal;
 | 
			
		||||
        this.dialogQueryVisible = false;
 | 
			
		||||
      },
 | 
			
		||||
      deep: true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    handleClickClose() {
 | 
			
		||||
      this.$store.commit("SET_CHECKFLAG", false);
 | 
			
		||||
      this.$store.commit("SET_CLEARTRAJECTORY", true);
 | 
			
		||||
    },
 | 
			
		||||
    initPositon() {
 | 
			
		||||
      let positionIds = {
 | 
			
		||||
        pageNum: 1,
 | 
			
		||||
        pageSize: 10000
 | 
			
		||||
      };
 | 
			
		||||
      devPositionList(positionIds).then((devRes) => {
 | 
			
		||||
        if (devRes.code === 0) {
 | 
			
		||||
          let positionRes = localStorage.getItem("PositionIds");
 | 
			
		||||
          this.positionList = devRes.data.items;
 | 
			
		||||
          const matchedList = this.positionList.filter((item) =>
 | 
			
		||||
            positionRes.includes(item.id)
 | 
			
		||||
          );
 | 
			
		||||
          this.loadGeoJson(matchedList);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // 加载 GeoJSON 数据并绘制
 | 
			
		||||
    loadGeoJson(value) {
 | 
			
		||||
      // 清空已有图层
 | 
			
		||||
      this.clearLayer();
 | 
			
		||||
 | 
			
		||||
      // 创建矢量源
 | 
			
		||||
      const source = new VectorSource();
 | 
			
		||||
 | 
			
		||||
      // 解析 GeoJSON 数据
 | 
			
		||||
      const geojsonFormat = new GeoJSON();
 | 
			
		||||
      value.forEach((item) => {
 | 
			
		||||
        // 解析 regionJson 为 OpenLayers 特征
 | 
			
		||||
        const feature = geojsonFormat.readFeature(JSON.parse(item.regionJson), {
 | 
			
		||||
          dataProjection: "EPSG:4326", // 输入数据为 WGS84
 | 
			
		||||
          featureProjection: "EPSG:3857" // 转换为地图投影
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 设置多边形样式:透明蓝色填充,蓝色边框
 | 
			
		||||
        feature.setStyle(
 | 
			
		||||
          new Style({
 | 
			
		||||
            fill: new Fill({
 | 
			
		||||
              color: "rgba(0, 0, 255, 0.3)" // 透明蓝色填充
 | 
			
		||||
            }),
 | 
			
		||||
            stroke: new Stroke({
 | 
			
		||||
              color: "#0000FF", // 蓝色边框
 | 
			
		||||
              width: 2
 | 
			
		||||
            })
 | 
			
		||||
          })
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // 添加多边形到源
 | 
			
		||||
        source.addFeature(feature);
 | 
			
		||||
 | 
			
		||||
        // 添加中心点
 | 
			
		||||
        const centerFeature = new Feature({
 | 
			
		||||
          geometry: new Point(fromLonLat([item.lon, item.lat]))
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // 设置中心点样式:红色圆点
 | 
			
		||||
        centerFeature.setStyle(
 | 
			
		||||
          new Style({
 | 
			
		||||
            image: new Circle({
 | 
			
		||||
              radius: 6,
 | 
			
		||||
              fill: new Fill({
 | 
			
		||||
                color: "#FF0000" // 红色填充
 | 
			
		||||
              }),
 | 
			
		||||
              stroke: new Stroke({
 | 
			
		||||
                color: "#FFFFFF", // 白色边框
 | 
			
		||||
                width: 1
 | 
			
		||||
              })
 | 
			
		||||
            })
 | 
			
		||||
          })
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // 添加中心点到源
 | 
			
		||||
        source.addFeature(centerFeature);
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // 创建矢量图层
 | 
			
		||||
      this.vectorLayer = new VectorLayer({
 | 
			
		||||
        source: source,
 | 
			
		||||
        zIndex: 10 // 设置图层优先级
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // 添加到父组件的地图
 | 
			
		||||
      window.olMap.addLayer(this.vectorLayer);
 | 
			
		||||
      // 跳转到 GeoJSON 数据区域
 | 
			
		||||
      if (source.getFeatures().length > 0) {
 | 
			
		||||
        const extent = source.getExtent(); // 获取所有特征的边界框
 | 
			
		||||
        window.olMap.getView().fit(extent, {
 | 
			
		||||
          padding: [50, 50, 50, 50], // 四周留白(像素)
 | 
			
		||||
          maxZoom: 15, // 最大缩放级别
 | 
			
		||||
          duration: 500 // 动画持续时间(毫秒)
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // 清空图层
 | 
			
		||||
    clearLayer() {
 | 
			
		||||
      if (this.vectorLayer) {
 | 
			
		||||
        window.olMap.removeLayer(this.vectorLayer);
 | 
			
		||||
        this.vectorLayer = null;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    refreshClick() {
 | 
			
		||||
      // 刷新页面
 | 
			
		||||
      window.location.reload();
 | 
			
		||||
| 
						 | 
				
			
			@ -95,16 +239,6 @@ export default {
 | 
			
		|||
    soundAndMenu() {
 | 
			
		||||
      this.isZoomedIn = !this.isZoomedIn;
 | 
			
		||||
      this.$store.commit("SET_ISZOOMEDIN", this.isZoomedIn);
 | 
			
		||||
      // const media = document.getElementById("uavAudio");
 | 
			
		||||
      // if (media) {
 | 
			
		||||
      //   media.muted = !this.isZoomedIn; // isZoomedIn为true时静音
 | 
			
		||||
      //   if (!this.isZoomedIn) {
 | 
			
		||||
      //     // 取消静音时尝试播放
 | 
			
		||||
      //     media.play().catch((error) => {
 | 
			
		||||
      //       console.log("播放失败,可能需要用户交互:", error);
 | 
			
		||||
      //     });
 | 
			
		||||
      //   }
 | 
			
		||||
      // }
 | 
			
		||||
    },
 | 
			
		||||
    initMap() {
 | 
			
		||||
      // 初始化 OpenLayers 地图
 | 
			
		||||
| 
						 | 
				
			
			@ -120,11 +254,36 @@ export default {
 | 
			
		|||
            })
 | 
			
		||||
          }),
 | 
			
		||||
          new TileLayer({
 | 
			
		||||
            name: "tianditu",
 | 
			
		||||
            name: "tianditu", // 图层名称
 | 
			
		||||
            visible: false,
 | 
			
		||||
            source: new XYZ({
 | 
			
		||||
              url: "https://{a-d}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png"
 | 
			
		||||
              url: "http://webrd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=7",
 | 
			
		||||
              layer: "img",
 | 
			
		||||
              style: "default",
 | 
			
		||||
              matrixSet: "c",
 | 
			
		||||
              format: "tiles",
 | 
			
		||||
              tileLoadFunction: function (imageTile, src) {
 | 
			
		||||
                // 使用滤镜 将白色修改为深色
 | 
			
		||||
                const img = new Image();
 | 
			
		||||
                // img.crossOrigin = ''
 | 
			
		||||
                // 设置图片不从缓存取,从缓存取可能会出现跨域,导致加载失败
 | 
			
		||||
                img.setAttribute("crossOrigin", "anonymous");
 | 
			
		||||
                img.onload = function () {
 | 
			
		||||
                  const canvas = document.createElement("canvas");
 | 
			
		||||
                  const w = img.width;
 | 
			
		||||
                  const h = img.height;
 | 
			
		||||
                  canvas.width = w;
 | 
			
		||||
                  canvas.height = h;
 | 
			
		||||
                  const context = canvas.getContext("2d");
 | 
			
		||||
                  context.filter =
 | 
			
		||||
                    "grayscale(98%) invert(100%) sepia(20%) hue-rotate(180deg) saturate(1600%) brightness(80%) contrast(90%)";
 | 
			
		||||
                  context.drawImage(img, 0, 0, w, h, 0, 0, w, h);
 | 
			
		||||
                  imageTile.getImage().src = canvas.toDataURL("image/png");
 | 
			
		||||
                };
 | 
			
		||||
                img.src = src;
 | 
			
		||||
              }
 | 
			
		||||
            }),
 | 
			
		||||
            visible: false
 | 
			
		||||
            format: new GeoJSON()
 | 
			
		||||
          })
 | 
			
		||||
        ],
 | 
			
		||||
        view: new View({
 | 
			
		||||
| 
						 | 
				
			
			@ -159,6 +318,7 @@ export default {
 | 
			
		|||
      this.zoomLevel = Math.round(this.map.getView().getZoom());
 | 
			
		||||
    },
 | 
			
		||||
    onMapLoad(map) {
 | 
			
		||||
      this.initPositon();
 | 
			
		||||
      // 地图加载完成后的处理
 | 
			
		||||
      const camera = window.mapConfig || {};
 | 
			
		||||
      if (camera.isCamera) {
 | 
			
		||||
| 
						 | 
				
			
			@ -172,17 +332,87 @@ export default {
 | 
			
		|||
        map.getView().setMaxZoom(18); // 最大缩放等级
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    mapNorth() {
 | 
			
		||||
      // 指北:将地图旋转角度重置为 0
 | 
			
		||||
      const view = this.map.getView();
 | 
			
		||||
      const currentCenter = view.getCenter();
 | 
			
		||||
      const currentZoom = view.getZoom();
 | 
			
		||||
      view.animate({
 | 
			
		||||
        center: currentCenter,
 | 
			
		||||
        zoom: currentZoom < 3 ? 10 : currentZoom, // 确保最小缩放等级
 | 
			
		||||
        rotation: 0, // 指北
 | 
			
		||||
        duration: 500 // 动画持续时间
 | 
			
		||||
      });
 | 
			
		||||
    handleClose() {
 | 
			
		||||
      this.dialogVisible = false;
 | 
			
		||||
      this.dialogQueryVisible = false;
 | 
			
		||||
    },
 | 
			
		||||
    userOpen() {
 | 
			
		||||
      this.$confirm("是否退出登录?", "提示", {
 | 
			
		||||
        confirmButtonText: "确定",
 | 
			
		||||
        cancelButtonText: "取消",
 | 
			
		||||
        type: "warning"
 | 
			
		||||
      })
 | 
			
		||||
        .then(() => {
 | 
			
		||||
          this.$router.push({ name: "login" });
 | 
			
		||||
          localStorage.removeItem("setToken");
 | 
			
		||||
          localStorage.removeItem("expires");
 | 
			
		||||
          localStorage.removeItem("userId");
 | 
			
		||||
          localStorage.removeItem("isAdmin");
 | 
			
		||||
          localStorage.removeItem("PositionIds");
 | 
			
		||||
        })
 | 
			
		||||
        .catch(() => {
 | 
			
		||||
          this.$message({
 | 
			
		||||
            type: "info",
 | 
			
		||||
            message: "已取消退出登录"
 | 
			
		||||
          });
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    setupOpen() {
 | 
			
		||||
      this.dialogVisible = true;
 | 
			
		||||
      const media = this.$refs.uavAudio;
 | 
			
		||||
      const savedVolume = localStorage.getItem("soundValue");
 | 
			
		||||
      if (savedVolume !== null) {
 | 
			
		||||
        this.value2 = Number(savedVolume);
 | 
			
		||||
      } else {
 | 
			
		||||
        this.value2 = media.volume * 100;
 | 
			
		||||
      }
 | 
			
		||||
      localStorage.setItem("soundValue", this.value2);
 | 
			
		||||
    },
 | 
			
		||||
    determine() {
 | 
			
		||||
      // 确定时保存音量到 localStorage
 | 
			
		||||
      localStorage.setItem("soundValue", this.value2);
 | 
			
		||||
      this.$store.commit("SET_SILDERVALUE", this.value2);
 | 
			
		||||
      this.dialogVisible = false; // 可选:关闭弹窗
 | 
			
		||||
    },
 | 
			
		||||
    queryOpen() {
 | 
			
		||||
      this.dialogQueryVisible = true;
 | 
			
		||||
    },
 | 
			
		||||
    headdenForm(value, type) {
 | 
			
		||||
      let params = {};
 | 
			
		||||
      if (type === "search") {
 | 
			
		||||
        params = JSON.parse(JSON.stringify(this.$refs.myForm.ruleForm));
 | 
			
		||||
        if (params.dateRange && params.dateRange.length === 2) {
 | 
			
		||||
          params.strartDate = moment(params.dateRange[0]).format("YYYY-MM-DD");
 | 
			
		||||
          params.endDate = moment(params.dateRange[1]).format("YYYY-MM-DD");
 | 
			
		||||
        }
 | 
			
		||||
        this.$delete(params, "dateRange");
 | 
			
		||||
        params.pageNum = this.paginationParam.currentPage;
 | 
			
		||||
        params.pageSize = this.paginationParam.size;
 | 
			
		||||
        alarmList(params).then((res) => {
 | 
			
		||||
          if (res.code === 0) {
 | 
			
		||||
            this.tableData = res.data.items.map((item) => {
 | 
			
		||||
              const { isWhitelist, duration, frequency, ...rest } = item;
 | 
			
		||||
              return {
 | 
			
		||||
                ...rest,
 | 
			
		||||
                isattacked: item.isattacked ? "是" : "否",
 | 
			
		||||
                duration: String(item.duration),
 | 
			
		||||
                frequency: String(item.frequency)
 | 
			
		||||
              };
 | 
			
		||||
            });
 | 
			
		||||
            this.paginationParam.total = res.data.total;
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    handleSizeChange(value) {
 | 
			
		||||
      console.log(value);
 | 
			
		||||
      this.paginationParam.size = value;
 | 
			
		||||
      this.headdenForm({}, "search");
 | 
			
		||||
    },
 | 
			
		||||
    handlePageChange(value) {
 | 
			
		||||
      console.log(value);
 | 
			
		||||
      this.paginationParam.currentPage = value;
 | 
			
		||||
      this.headdenForm({}, "search");
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -205,6 +435,13 @@ export default {
 | 
			
		|||
      height: 48px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .btn-container {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 70px;
 | 
			
		||||
    right: 100px;
 | 
			
		||||
    z-index: 1000;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
  }
 | 
			
		||||
  .configuration {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    bottom: 32px;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@
 | 
			
		|||
            :underline="false"
 | 
			
		||||
            @click="handleClick(data, 'playback')"
 | 
			
		||||
          >
 | 
			
		||||
            轨迹回放
 | 
			
		||||
            查看
 | 
			
		||||
          </el-link>
 | 
			
		||||
        </template>
 | 
			
		||||
      </my-table>
 | 
			
		||||
| 
						 | 
				
			
			@ -57,8 +57,15 @@
 | 
			
		|||
 | 
			
		||||
<script>
 | 
			
		||||
"use script";
 | 
			
		||||
import { mapGetters } from "vuex";
 | 
			
		||||
import { alarmList, alarmDetail } from "@/api/alarm.js";
 | 
			
		||||
import moment from "moment";
 | 
			
		||||
import { Map, View, Feature, Overlay } from "ol";
 | 
			
		||||
import { LineString, Point } from "ol/geom";
 | 
			
		||||
import { Vector as VectorLayer } from "ol/layer";
 | 
			
		||||
import { Vector as VectorSource } from "ol/source";
 | 
			
		||||
import { Style, Stroke } from "ol/style";
 | 
			
		||||
import { fromLonLat } from "ol/proj";
 | 
			
		||||
export default {
 | 
			
		||||
  name: "webDevice",
 | 
			
		||||
  data() {
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +157,7 @@ export default {
 | 
			
		|||
          align: "center"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          label: "持续时间(秒)",
 | 
			
		||||
          label: "持续时间",
 | 
			
		||||
          prop: "duration",
 | 
			
		||||
          align: "center"
 | 
			
		||||
        },
 | 
			
		||||
| 
						 | 
				
			
			@ -186,9 +193,7 @@ export default {
 | 
			
		|||
        // },
 | 
			
		||||
        {
 | 
			
		||||
          slot: "operate",
 | 
			
		||||
          label: "操作",
 | 
			
		||||
          width: 250,
 | 
			
		||||
          fixed: "right"
 | 
			
		||||
          label: "操作"
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      paginationParam: {
 | 
			
		||||
| 
						 | 
				
			
			@ -204,6 +209,18 @@ export default {
 | 
			
		|||
      historyList: []
 | 
			
		||||
    };
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    ...mapGetters(["clearTrajectory"])
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    clearTrajectory(newVal) {
 | 
			
		||||
      if (newVal) {
 | 
			
		||||
        this.clearTrack();
 | 
			
		||||
        this.$store.commit("SET_CLEARTRAJECTORY", false);
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    deep: true
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    this.headdenForm({}, "search");
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			@ -245,11 +262,97 @@ export default {
 | 
			
		|||
              };
 | 
			
		||||
            });
 | 
			
		||||
            this.paginationParam.total = res.data.total;
 | 
			
		||||
            // this.tableData = [
 | 
			
		||||
            //   {
 | 
			
		||||
            //     batchId: "1936635182949994496",
 | 
			
		||||
            //     startTime: "2025-06-22 11:59:43",
 | 
			
		||||
            //     endTime: "2025-06-22 12:02:10",
 | 
			
		||||
            //     duration: 147,
 | 
			
		||||
            //     model: "8",
 | 
			
		||||
            //     sn: "1581F6CDC23B6003DTL2",
 | 
			
		||||
            //     frequency: 0,
 | 
			
		||||
            //     isWhitelist: false,
 | 
			
		||||
            //     whitelist: null,
 | 
			
		||||
            //     positionId: "1924768527160578048",
 | 
			
		||||
            //     positionName: "louding"
 | 
			
		||||
            //   }
 | 
			
		||||
            // ];
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      console.log(value);
 | 
			
		||||
    },
 | 
			
		||||
    // 绘制轨迹线
 | 
			
		||||
    drawTrack() {
 | 
			
		||||
      // 清空之前的轨迹
 | 
			
		||||
      this.clearTrack();
 | 
			
		||||
 | 
			
		||||
      // 转换坐标为 OpenLayers 格式 (EPSG:3857)
 | 
			
		||||
      const coordinates = this.historyList.map((item) =>
 | 
			
		||||
        fromLonLat([item.lon, item.lat])
 | 
			
		||||
      );
 | 
			
		||||
      console.log(coordinates, "coordinates");
 | 
			
		||||
      // 创建线条几何
 | 
			
		||||
      const lineFeature = new Feature({
 | 
			
		||||
        geometry: new LineString(coordinates)
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // 设置线条样式:宽度10,颜色蓝色
 | 
			
		||||
      lineFeature.setStyle(
 | 
			
		||||
        new Style({
 | 
			
		||||
          stroke: new Stroke({
 | 
			
		||||
            color: "#ff0000",
 | 
			
		||||
            width: 7
 | 
			
		||||
          })
 | 
			
		||||
        })
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      // 创建矢量图层
 | 
			
		||||
      const source = new VectorSource({
 | 
			
		||||
        features: [lineFeature]
 | 
			
		||||
      });
 | 
			
		||||
      this.trackLayer = new VectorLayer({
 | 
			
		||||
        source: source,
 | 
			
		||||
        zIndex: 10 // 设置图层优先级
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // 添加到父组件的地图
 | 
			
		||||
      window.olMap.addLayer(this.trackLayer);
 | 
			
		||||
      window.olMap.getView().animate({
 | 
			
		||||
        center: [coordinates[0][0], coordinates[0][1]],
 | 
			
		||||
        zoom: 15
 | 
			
		||||
      });
 | 
			
		||||
      // 添加点击删除功能
 | 
			
		||||
      // this.addClickToRemove();
 | 
			
		||||
    },
 | 
			
		||||
    // 添加点击删除轨迹功能
 | 
			
		||||
    addClickToRemove() {
 | 
			
		||||
      window.olMap.on("singleclick", (event) => {
 | 
			
		||||
        const feature = window.olMap.forEachFeatureAtPixel(
 | 
			
		||||
          event.pixel,
 | 
			
		||||
          (feat) => feat
 | 
			
		||||
        );
 | 
			
		||||
        if (
 | 
			
		||||
          feature &&
 | 
			
		||||
          this.trackLayer.getSource().getFeatures().includes(feature)
 | 
			
		||||
        ) {
 | 
			
		||||
          // 确认点击的是轨迹线
 | 
			
		||||
          if (confirm("是否关闭该轨迹?")) {
 | 
			
		||||
            this.clearTrack();
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
    handleClickClose() {
 | 
			
		||||
      this.clearTrack();
 | 
			
		||||
    },
 | 
			
		||||
    // 清空轨迹
 | 
			
		||||
    clearTrack() {
 | 
			
		||||
      if (this.trackLayer) {
 | 
			
		||||
        window.olMap.removeLayer(this.trackLayer);
 | 
			
		||||
        this.trackLayer = null;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    // 停用 编辑 删除
 | 
			
		||||
    handleClick(value, type) {
 | 
			
		||||
      let params = { batchid: value.batchId };
 | 
			
		||||
| 
						 | 
				
			
			@ -258,55 +361,75 @@ export default {
 | 
			
		|||
        alarmDetail(params).then((res) => {
 | 
			
		||||
          if (res.code === 0) {
 | 
			
		||||
            console.log(res.data, "res.data");
 | 
			
		||||
            this.historyList = res.data;
 | 
			
		||||
            // this.historyList = [
 | 
			
		||||
            //   {
 | 
			
		||||
            //     lon: 109.056198,
 | 
			
		||||
            //     lat: 38.674443,
 | 
			
		||||
            //     alt: 0,
 | 
			
		||||
            //     createTime: "2025-03-30 03:44:21",
 | 
			
		||||
            //     alarmLevel: 0
 | 
			
		||||
            //   },
 | 
			
		||||
            //   {
 | 
			
		||||
            //     lon: 109.081454,
 | 
			
		||||
            //     lat: 38.664766,
 | 
			
		||||
            //     alt: 0,
 | 
			
		||||
            //     createTime: "2025-03-30 03:44:22",
 | 
			
		||||
            //     alarmLevel: 0
 | 
			
		||||
            //   },
 | 
			
		||||
            //   {
 | 
			
		||||
            //     lon: 109.101687,
 | 
			
		||||
            //     lat: 38.632524,
 | 
			
		||||
            //     alt: 0,
 | 
			
		||||
            //     createTime: "2025-03-30 03:44:25",
 | 
			
		||||
            //     alarmLevel: 0
 | 
			
		||||
            //   },
 | 
			
		||||
            //   {
 | 
			
		||||
            //     lon: 109.063063,
 | 
			
		||||
            //     lat: 38.622878,
 | 
			
		||||
            //     alt: 0,
 | 
			
		||||
            //     createTime: "2025-03-30 03:44:30",
 | 
			
		||||
            //     alarmLevel: 0
 | 
			
		||||
            //   },
 | 
			
		||||
            //   {
 | 
			
		||||
            //     lon: 109.016034,
 | 
			
		||||
            //     lat: 38.635138,
 | 
			
		||||
            //     alt: 0,
 | 
			
		||||
            //     createTime: "2025-03-30 03:44:35",
 | 
			
		||||
            //     alarmLevel: 0
 | 
			
		||||
            //   },
 | 
			
		||||
            //   {
 | 
			
		||||
            //     lon: 108.991419,
 | 
			
		||||
            //     lat: 38.659515,
 | 
			
		||||
            //     alt: 0,
 | 
			
		||||
            //     createTime: "2025-03-30 03:44:38",
 | 
			
		||||
            //     alarmLevel: 0
 | 
			
		||||
            //   }
 | 
			
		||||
            // ];
 | 
			
		||||
            this.historyList = [
 | 
			
		||||
              {
 | 
			
		||||
                lon: 118.71041006571824,
 | 
			
		||||
                lat: 32.031231916027345,
 | 
			
		||||
                alt: 41.3,
 | 
			
		||||
                app_lat: 32.03116889069689,
 | 
			
		||||
                app_lon: 118.71035276996328,
 | 
			
		||||
                createTime: "2025-06-14 15:31:28",
 | 
			
		||||
                alarmLevel: 0
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                lon: 118.7104387135957,
 | 
			
		||||
                lat: 32.03126056390482,
 | 
			
		||||
                alt: 41.3,
 | 
			
		||||
                app_lat: 32.03116889069689,
 | 
			
		||||
                app_lon: 118.71035276996328,
 | 
			
		||||
                createTime: "2025-06-14 15:31:30",
 | 
			
		||||
                alarmLevel: 0
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                lon: 118.71056476425662,
 | 
			
		||||
                lat: 32.03135796668825,
 | 
			
		||||
                alt: 45.7,
 | 
			
		||||
                app_lat: 32.03116889069689,
 | 
			
		||||
                app_lon: 118.71034704038777,
 | 
			
		||||
                createTime: "2025-06-14 15:32:04",
 | 
			
		||||
                alarmLevel: 0
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                lon: 118.71056476425662,
 | 
			
		||||
                lat: 32.03135796668825,
 | 
			
		||||
                alt: 45.7,
 | 
			
		||||
                app_lat: 32.03116316112139,
 | 
			
		||||
                app_lon: 118.71034704038777,
 | 
			
		||||
                createTime: "2025-06-14 15:32:06",
 | 
			
		||||
                alarmLevel: 0
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                lon: 118.71034704038777,
 | 
			
		||||
                lat: 32.031077217488956,
 | 
			
		||||
                alt: 24.4,
 | 
			
		||||
                app_lat: 32.03117462027238,
 | 
			
		||||
                app_lon: 118.71036422911426,
 | 
			
		||||
                createTime: "2025-06-14 15:32:49",
 | 
			
		||||
                alarmLevel: 0
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                lon: 118.71038141784075,
 | 
			
		||||
                lat: 32.03106575833797,
 | 
			
		||||
                alt: 22.3,
 | 
			
		||||
                app_lat: 32.03116889069689,
 | 
			
		||||
                app_lon: 118.71035276996328,
 | 
			
		||||
                createTime: "2025-06-14 15:32:55",
 | 
			
		||||
                alarmLevel: 0
 | 
			
		||||
              },
 | 
			
		||||
              {
 | 
			
		||||
                lon: 118.71036995868977,
 | 
			
		||||
                lat: 32.03092824852607,
 | 
			
		||||
                alt: 34.6,
 | 
			
		||||
                app_lat: 32.03118034984788,
 | 
			
		||||
                app_lon: 118.71035849953877,
 | 
			
		||||
                createTime: "2025-06-14 15:33:54",
 | 
			
		||||
                alarmLevel: 0
 | 
			
		||||
              }
 | 
			
		||||
            ];
 | 
			
		||||
            this.drawTrack();
 | 
			
		||||
            this.$store.commit("SET_CHECKFLAG", true);
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
        this.title = "轨迹回放";
 | 
			
		||||
        this.drawer = true;
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    handleSizeChange(value) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,7 @@ module.exports = defineConfig({
 | 
			
		|||
  productionSourceMap: false,
 | 
			
		||||
  transpileDependencies: true,
 | 
			
		||||
  devServer: {
 | 
			
		||||
    host: "127.0.0.1",
 | 
			
		||||
    host: "192.168.1.9",
 | 
			
		||||
    port: 9997,
 | 
			
		||||
    open: true,
 | 
			
		||||
    proxy: {}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue