Browse Source

fix🐛: 添加细节放大镜、点位删除

gitboyzcf 2 weeks ago
parent
commit
049720482e

+ 8 - 0
src/api/modules/mr.js

@@ -37,6 +37,14 @@ export default {
       data
     })
   },
+  // 删除相机
+  API_MR_CAMERA_DELETE(data = {}) {
+    return request({
+      url: `/api/Camera`,
+      method: 'delete',
+      data
+    })
+  },
   // 获取视频播放地址列表
   API_MR_VIDEO_LIST_GET(data = {}) {
     return request({

+ 76 - 4
src/layout/Three3D/components/rightClick.vue

@@ -2,25 +2,33 @@
   <ul
     v-if="show"
     :style="{ top: y + 'px', left: x + 'px' }"
-    class="three-create-tag absolute c-#fff right-box py-1 flex flex-col items-center justify-center bg-#2262acb3"
+    :class="[
+      'three-create-tag absolute c-#fff right-box py-1 flex flex-col items-center justify-center bg-#2262acb3',
+      flag === 'add' ? 'bg-#2262acb3' : 'bg-#eab308b3'
+    ]"
   >
     <li
-      class="px-4 py-1 cursor-pointer hover:bg-#2262ac mb-2 last:mb-0"
+      :class="[
+        'px-4 py-1 cursor-pointer hover:bg-#2262ac mb-2 last:mb-0',
+        item.type === 'add' ? 'hover:bg-#2262ac' : 'hover:bg-#eab308'
+      ]"
       @click="item.handler"
-      v-for="(item, i) in menu"
+      v-for="(item, i) in menuComp"
       :key="i"
       >{{ item.label }}</li
     >
   </ul>
 </template>
 <script setup>
-  import { useModal } from 'naive-ui'
+  import { NButton, useModal } from 'naive-ui'
   import AddDevice from './addDevice.vue'
 
+  const { API_MR_CAMERA_DELETE } = useRequest()
   const addSprite = inject('addSprite')
   const show = defineModel()
   const modal = useModal()
   const props = defineProps({
+    flag: String, // add del
     x: {
       type: Number,
       default: 0
@@ -34,6 +42,7 @@
   const menu = [
     {
       label: '创建点位',
+      type: 'add',
       handler: () => {
         show.value = false
         modal.create({
@@ -52,6 +61,69 @@
             })
         })
       }
+    },
+    {
+      label: '删除点位',
+      type: 'del',
+      handler: () => {
+        show.value = false
+        modal.create({
+          title: '删除点位',
+          preset: 'card',
+          maskClosable: false,
+          trapFocus: false,
+          style: {
+            marginTop: '10%'
+          },
+          content: () =>
+            h('div', [
+              h('p', '确定删除该点位吗?'),
+              [
+                h('div', { class: 'flex justify-end mt-4' }, [
+                  h(
+                    NButton,
+                    {
+                      onClick: async () => {
+                        // addSprite(props.intersection, 'del')
+                        console.log(props.intersection)
+                        await API_MR_CAMERA_DELETE({
+                          id: props.intersection.object.vData.id
+                        })
+                        props.intersection.object.parent.remove(props.intersection.object)
+                        modal.destroyAll()
+                      }
+                    },
+                    () => '确定'
+                  )
+                ])
+              ]
+            ])
+        })
+      }
+    },
+    {
+      label: '编辑点位',
+      type: 'edit',
+      handler: () => {
+        show.value = false
+        modal.create({
+          title: '编辑点位',
+          preset: 'card',
+          maskClosable: false,
+          trapFocus: false,
+          style: {
+            marginTop: '10%'
+          },
+          content: () =>
+            h(AddDevice, {
+              intersection: props.intersection,
+              addSprite,
+              onCloseAddTagModal: () => modal.destroyAll()
+            })
+        })
+      }
     }
   ]
+
+  const menuComp = computed(() => menu.filter((item) => item.type === props.flag))
 </script>

+ 14 - 6
src/layout/Three3D/index.vue

@@ -11,6 +11,7 @@
     />
     <RightClick
       v-model="rightClickD.show"
+      :flag="rightClickFlag"
       :x="rightClickD.x"
       :y="rightClickD.y"
       :intersection="rightClickD.intersection"
@@ -41,6 +42,7 @@
     y: 0,
     intersection: null
   })
+  const rightClickFlag = ref('add')
 
   const { API_MR_CAMERA_GET, API_MR_VIDEO_LIST_GET } = useRequest()
   const useHomeStore = useOutsideHomeStore()
@@ -84,7 +86,9 @@
       const sprite = new THREE.Sprite(
         new THREE.SpriteMaterial({
           map: new THREE.TextureLoader().load('textures/video-icon.png'),
-          color: 0xffffff
+          color: 0xffffff,
+          depthWrite: false, //深度写入属性
+          depthTest: false //depthTest属性值默认true,设置为false可以关闭深度测试.
         })
       )
       sprite.vData = {
@@ -145,15 +149,19 @@
     const intersects = raycaster.intersectObjects(scene.children, true)
 
     if (intersects.length > 0) {
-      if (intersects[0].object.type === 'Sprite') return
+      if (intersects[0].object.type === 'Sprite') {
+        rightClickFlag.value = 'del'
+        rightClickD.intersection = intersects[0]
+      } else {
+        rightClickFlag.value = 'add'
+        rightClickD.intersection = intersects[0].point
+      }
       // 显示右键菜单
-
       rightClickD.show = true
       rightClickD.x = event.clientX / getAutofitScale()
       rightClickD.y = event.clientY / getAutofitScale()
 
       // 存储交点信息
-      rightClickD.intersection = intersects[0].point
     } else {
       // 如果没有点击到物体,隐藏菜单
       rightClickD.show = false
@@ -396,9 +404,9 @@
   function toggleHeatmapVisibility(visible) {
     if (heatmapMesh) {
       heatmapMesh.visible = visible
-      if(visible){
+      if (visible) {
         translateCamera({ x: 0, y: 10, z: 20 }, { x: 0, y: 0, z: 0 }, 1)
-      }else{
+      } else {
         translateCamera({ x: 0, y: 2, z: 10 }, { x: 0, y: 0, z: 0 }, 1)
       }
     }

+ 62 - 3
src/views/home/middleBottomBox/components/partBox.vue

@@ -3,7 +3,19 @@
     <div class="part-box-wrapper h-full">
       <UseFullscreen class="h-full" v-slot="{ toggle, isFullscreen }">
         <div class="part-video-box relative screen-full-target h-full">
-          <pub-video-new :newClass="'p-video' + currentActive" />
+          <vue-photo-zoom-pro
+            ref="zoomRef"
+            class="w-full h-full"
+            :scale="3"
+            :width="150"
+            :disabled-event="isZoom"
+          >
+            <pub-video-new :newClass="'p-video' + currentActive" />
+            <template v-slot:zoomer>
+              <pub-video-new :newClass="'p-zoom-video' + currentActive" :key="resetKey" />
+            </template>
+          </vue-photo-zoom-pro>
+
           <!-- 操作按钮 -->
           <div class="part-main-btn-box" absolute top-10px right-10px flex flex-row-reverse z-999>
             <!-- 全屏按钮 -->
@@ -38,8 +50,12 @@
               height="25"
               cursor-pointer
               alt="关闭画面"
-              @click="closeVideo(currentActive)"
+              @click="closeVideo()"
             />
+            <span
+              class="size-28px mr-1 color-#8ac5ff cursor-pointer i-ph:magnifying-glass-plus"
+              @click="magnifying(!magnifyingFlag)"
+            ></span>
           </div>
           <div
             v-if="!playerObj"
@@ -64,6 +80,7 @@
   import { uuid, getAutofitScale } from '@/utils'
   import { omatVideoPlayer } from '@/assets/js/video-lib/flv/omatVideoPlayer'
   import { UseFullscreen } from '@vueuse/components'
+  import VuePhotoZoomPro from 'vue-photo-zoom-pro'
 
   const useSystem = useOutsideSystemStore()
 
@@ -95,7 +112,6 @@
           videoUrl.value,
           () => {
             const videoDom = document.querySelector('.p-video' + props.currentActive)
-            console.log(useSystem.partObj)
             setTimeout(() => {
               videoDom.style.width = videoDom.videoWidth + 'px'
               const { width, height } = videoDom.getBoundingClientRect()
@@ -123,7 +139,50 @@
     })
   }
 
+  let magnifyingWorkerObj = null
+  const isZoom = ref(true)
+  const zoomRef = ref(null)
+  const resetKey = ref(uuid())
+  const magnifyingFlag = ref(false)
+  const magnifying = (flag) => {
+    zoomRef.value?.mouseLeave()
+    magnifyingFlag.value = flag
+    if (flag) {
+      if (magnifyingWorkerObj) return
+      // const url = videoList.value.pano_view.replace('{14}', useSystem.deviceInfo.id)
+      magnifyingWorkerObj = omatVideoPlayer(
+        '.p-zoom-video' + props.currentActive,
+        videoUrl.value,
+        () => {
+          const videoDom = document.querySelector('.p-zoom-video' + props.currentActive)
+          const videoDomOrigin = document.querySelector('.p-video' + props.currentActive)
+          setTimeout(() => {
+            videoDom.style.width = videoDomOrigin.videoWidth + 'px'
+            const { width, height } = videoDomOrigin.getBoundingClientRect()
+            const { PartCenterY: py, PartCenterX: px } = useSystem.partObj
+            const [x, y] = [
+              px < 237 ? 0 : px > width ? width : px - 237,
+              py < 132 ? 0 : py > height ? height : py - 132
+            ]
+            videoDom.style.transform = `translate(${-x}px, ${-y}px)`
+            isZoom.value = false
+            zoomRef.value.mouseEnter()
+          }, 200)
+        }
+      )
+    } else {
+      isZoom.value = true
+      zoomRef.value.mouseLeave()
+      magnifyingWorkerObj?.destroyed()
+      resetKey.value = uuid()
+      magnifyingWorkerObj = null
+    }
+  }
+
   const closeVideo = () => {
+    if (magnifyingFlag.value) {
+      magnifying(false)
+    }
     closeWorker()
   }
   // 关闭线程