xieb
2023-11-21 5f35a4891178ece4fc611ecb515610841abe0f43
Merge remote-tracking branch 'origin/demo' into demo
5 files modified
235 ■■■■ changed files
src/components/GMap.vue 1 ●●●● patch | view | raw | blame | history
src/components/g-map/DroneControlPanel.vue 9 ●●●● patch | view | raw | blame | history
src/hooks/use-cesium-tsa.ts 27 ●●●●● patch | view | raw | blame | history
src/pages/page-web/projects/routeLine.vue 195 ●●●● patch | view | raw | blame | history
src/pages/page-web/projects/tsa.vue 3 ●●●● patch | view | raw | blame | history
src/components/GMap.vue
@@ -1240,6 +1240,7 @@
    watch(() => openDroneControl.value, (is: boolean) => {
      if (!is) {
        cesium.removeById('rangeEllipse')
        cesium.removeAllDataSource()
        return
      }
      // 设置无人机范围
src/components/g-map/DroneControlPanel.vue
@@ -321,6 +321,7 @@
import { parseJsonFile } from '/@/utils/geo-utils'
import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
import * as Cesium from 'cesium'
import { start } from 'repl'
const props = defineProps<{
    sn: string,
    deviceInfo: DeviceInfoType,
@@ -526,8 +527,14 @@
  flyByArea(sn, dockPoint, jsonPath, radius, deviceSn, payloadIndex).then(res => {
    const targetPoint = res.data
    console.log('targetPoint====', targetPoint)
    // 机场位置
    const startPoint = {
      lon: props.deviceInfo.dock.basic_osd.longitude,
      lat: props.deviceInfo.dock.basic_osd.latitude
    }
    targetPoint.unshift(startPoint)
    // 获取到点之后在图上绘点
    targetPoint.forEach((point, index) => {
    targetPoint.forEach((point: { lon: number; lat: number }, index: number) => {
      console.log(point)
      const setting = {
        longitude: point.lon,
src/hooks/use-cesium-tsa.ts
@@ -146,12 +146,12 @@
    }
  }
  function removeAllDataSource() {
    viewer.dataSources.removeAll()
  function removeAllDataSource () {
    viewer?.dataSources.removeAll()
  }
  // 清除所有标记点
  function removeAllPoint() {
  function removeAllPoint () {
    if (viewer) {
      viewer?.entities?.removeAll()
    }
@@ -185,15 +185,23 @@
    })
  }
  let leftClickHandler: Cesium.ScreenSpaceEventHandler
  // 添加点击事件
  const addClickEvent = (sid: string, cb: Function) => {
    const handler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas)
    handler.setInputAction(function (click: { position: Cesium.Cartesian2 }) {
    if (leftClickHandler) {
      removeClickEvent()
    }
    leftClickHandler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas)
    leftClickHandler.setInputAction(function (click: { position: Cesium.Cartesian2 }) {
      const pick = viewer?.scene.pick(click.position)
      if (pick && pick.id._id === sid) {
        cb(click, pick, viewer)
        cb(click, pick, viewer, handler)
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  }
  // 移除事件
  const removeClickEvent = () => {
    leftClickHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
  }
  // 添加线段
@@ -290,8 +298,8 @@
  // 加载json文件
  const loadGeoJson = (url: string) => {
    const option = {
      stroke: Cesium.Color.HOTPINK,
      fill: Cesium.Color.PINK,
      stroke: Cesium.Color.HOTPINK.withAlpha(0.5),
      fill: Cesium.Color.PINK.withAlpha(0.3),
      strokeWidth: 3,
    }
    const promise = Cesium.GeoJsonDataSource.load(url, option)
@@ -348,6 +356,7 @@
    addEllipse,
    loadGeoJson,
    removeAllDataSource,
    addClickEvent
    addClickEvent,
    removeClickEvent
  }
}
src/pages/page-web/projects/routeLine.vue
@@ -1,13 +1,13 @@
<template>
    <div class="project-wayline-wrapper height-100">
      <a-spin :spinning="loading" :delay="300" tip="加载中" size="large">
  <div class="project-wayline-wrapper height-100">
    <a-spin :spinning="loading" :delay="300" tip="加载中" size="large">
      <div style="height: 50px; line-height: 50px; border-bottom: 1px solid #4f4f4f; font-weight: 450;">
        <a-row>
          <a-col :span="1"></a-col>
          <a-col :span="15">历史航线</a-col>
        </a-row>
      </div>
      <div :style="{ height : height + 'px'}" class="scrollbar">
      <div :style="{ height: height + 'px' }" class="scrollbar">
        <div id="data" class="height-100 uranus-scrollbar" v-if="routeLine.length !== 0" @scroll="onScroll">
          <div v-for="wayline in routeLine" :key="wayline.id">
            <div class="wayline-panel" style="padding-top: 5px;" @click="selectRoute(wayline)">
@@ -36,9 +36,22 @@
          <a-empty :image-style="{ height: '60px', marginTop: '60px' }" />
        </div>
      </div>
      </a-spin>
    </a-spin>
    <!-- 地图内弹窗 -->
    <div class="popup-box" ref="popup">
      <div class="PopUp">
        <img :src="currentWayline.photo_url" alt="photo">
        <div>
          <div>云台偏航角:{{ currentWayline.gimbal_yaw_degree }}</div>
          <div>拍摄绝对高度:{{ currentWayline.absolute_altitude }}</div>
          <div>拍摄相对高度:{{ currentWayline.relative_altitude }}</div>
          <div>媒体拍摄时间:{{ currentWayline.created_time }}</div>
        </div>
      </div>
    </div>
  </template>
  </div>
</template>
<script lang="ts" setup>
import { reactive } from '@vue/reactivity'
@@ -51,11 +64,12 @@
import * as Cesium from 'cesium'
import { convertTimestampToDate } from '/@/utils/time'
import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
import { NONAME } from 'dns'
const loading = ref(false)
const { appContext } = getCurrentInstance()
const store = useMyStore()
const pagination :IPage = {
const pagination: IPage = {
  page: 1,
  total: -1,
  page_size: 10
@@ -64,7 +78,16 @@
const workspaceId = computed(() => store.state.common.projectId || localStorage.getItem(ELocalStorageKey.WorkspaceId))
const canRefresh = ref(true)
const height = ref()
const { removeById, addPolyline, getEntityById, flyTo, removeAllPoint } = cesiumOperation()
const { addPoint, addClickEvent, removeClickEvent, removeById, addPolyline, getEntityById, flyTo, removeAllPoint, removeAllDataSource } = cesiumOperation()
const isShowPopUp = ref<boolean>(false)
const popup = ref(null)
const currentWayline = ref({
  photo_url: '',
  gimbal_yaw_degree: '',
  absolute_altitude: '',
  relative_altitude: '',
  created_time: ''
})
onMounted(() => {
  const parent = document.getElementsByClassName('scrollbar').item(0)?.parentNode as HTMLDivElement
@@ -91,17 +114,30 @@
  pagination.page = res.data.pagination.page
}
async function selectRoute (wayline) {
async function selectRoute (wayline: { start_time: string; id: string }) {
  currentWayline.value = {
    photo_url: 'https://dev.jxpskj.com:8026/cloud-bucket/5abb3b6e-cb42-40e4-b086-9c24db0e8765/DJI_202311171122_004_5abb3b6e-cb42-40e4-b086-9c24db0e8765/DJI_20231117112319_0001_W_%E8%88%AA%E7%82%B91.jpeg',
    gimbal_yaw_degree: '81°',
    absolute_altitude: '120m',
    relative_altitude: '120m',
    created_time: new Date(wayline.start_time).toLocaleString()
  }
  // currentWayline.value = wayline
  // 判断是否有历史航线的id实体
  const entity = getEntityById('drone_route_history')
  const billboard = getEntityById('start_point_billboard')
  billboard && removeById('start_point_billboard')
  const element: HTMLDivElement | any = document.querySelector('.popup-box') || popup.value
  if (entity) {
    removeById('drone_route_history')
    removeClickEvent()
    element.style.display = 'none'
  }
  // 航线经纬度存储数组
  let routeLine = []
  let routeLine: Cesium.Cartesian3[] | any = []
  const res = await getHistoryDetail(wayline.id)
  if (res.code !== 0) return
  res.data.forEach(v => {
  res.data.forEach((v: { longitude: number; latitude: number }) => {
    routeLine.push(v.longitude)
    routeLine.push(v.latitude)
  })
@@ -110,6 +146,60 @@
    latitude: routeLine[1]
  }
  routeLine = Cesium.Cartesian3.fromDegreesArray(routeLine)
  // 添加起飞点图片
  const billboardSetting = {
    ...pointOption,
    billboard: {
      id: 'start_point_img',
      image: 'https://dev.jxpskj.com:8026/cloud-bucket/5abb3b6e-cb42-40e4-b086-9c24db0e8765/DJI_202311171122_004_5abb3b6e-cb42-40e4-b086-9c24db0e8765/DJI_20231117112319_0001_W_%E8%88%AA%E7%82%B91.jpeg',
      width: 40,
      height: 40,
      pixelOffset: new Cesium.Cartesian2(0, -10),
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      // scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.0),
    },
    point: {
      pixelSize: 5,
      color: Cesium.Color.RED,
      outlineColor: Cesium.Color.WHITE,
      outlineWidth: 2
    },
    label: {
      text: '起飞点',
      font: '12pt monospace',
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      outlineWidth: 1,
      verticalOrigin: Cesium.VerticalOrigin.TOP,
      pixelOffset: new Cesium.Cartesian2(0, 10)
    },
    id: 'start_point_billboard'
  }
  addPoint(billboardSetting)
  // 添加广告牌点击事件
  addClickEvent('start_point_billboard', addBillboard)
  function addBillboard (_click: any, _pick: any, viewer: { container: { append: (arg0: any) => void }; scene: Cesium.Scene }) {
    viewer.scene.postRender.removeEventListener(addBillboard)
    viewer.container.append(element)
    if (isShowPopUp.value) {
      element.style.display = 'none'
    } else {
      element.style.display = 'block'
    }
    isShowPopUp.value = !isShowPopUp.value
    const { longitude, latitude } = pointOption
    viewer.scene.postRender.addEventListener(() => {
      const windowCoord = Cesium.SceneTransforms.wgs84ToWindowCoordinates(
        viewer.scene,
        Cesium.Cartesian3.fromDegrees(longitude, latitude, 0)
      )
      const x = windowCoord.x + 40
      const y = windowCoord.y - (element.offsetHeight / 2) - 40
      element.style.transform = `
        translate3d(${Math.round(x)}px,${Math.round(y)}px, 0)
      `
    })
  }
  // 无人机历史路线轨迹
  const routeTrajectory = {
    longitude: 115.85666327144976,
@@ -132,6 +222,10 @@
    getHistoryWay()
  }
}
onMounted(() => {
  removeAllPoint()
})
onUnmounted(() => {
  // removeById('drone_route_history')
  removeAllPoint()
@@ -139,29 +233,62 @@
</script>
  <style lang="scss" scoped>
  .wayline-panel {
    background: #3c3c3c;
    margin-left: auto;
    margin-right: auto;
    margin-top: 10px;
    height: 90px;
    width: 95%;
    font-size: 13px;
    border-radius: 2px;
    cursor: pointer;
    .title {
      display: flex;
      flex-direction: row;
      align-items: center;
      height: 30px;
      font-weight: bold;
      margin: 0px 10px 0 10px;
<style lang="scss" scoped>
.wayline-panel {
  background: #3c3c3c;
  margin-left: auto;
  margin-right: auto;
  margin-top: 10px;
  height: 90px;
  width: 95%;
  font-size: 13px;
  border-radius: 2px;
  .title {
    display: flex;
    flex-direction: row;
    align-items: center;
    height: 30px;
    font-weight: bold;
    margin: 0px 10px 0 10px;
  }
}
.popup-box {
  position: absolute;
  top: 0;
  left: 0;
  display: none;
  .PopUp {
    width: 250px;
    background-color: #fff;
    padding: 5px;
    border: 1px solid #f5f5f5;
    position: relative;
    &::after {
      content: '';
      position: absolute;
      top: calc(50% - 6px);
      left: -9px;
      width: 0px;
      height: 0px;
      border-style: solid;
      border-width: 12px;
      border-color: #fff #fff transparent transparent;
      transform: rotate(225deg);
    }
    img {
      width: 100%;
    }
  }
  .uranus-scrollbar {
    overflow: auto;
    scrollbar-width: thin;
    scrollbar-color: #c5c8cc transparent;
  }
  </style>
}
.uranus-scrollbar {
  overflow: auto;
  scrollbar-width: thin;
  scrollbar-color: #c5c8cc transparent;
}
</style>
src/pages/page-web/projects/tsa.vue
@@ -415,7 +415,8 @@
        width: 36,
        height: 36,
        scale: 1.0,
      }
      },
      id: 'aerodrome'
    }
    cesium.addPoint(setting)
    // cesium.flyTo(setting)