Преглед изворни кода

```
feat(mr): 新增获取设备流和球机信息接口及功能实现

- 在 `mr.js` 中新增 `API_MR_STREAMS_GET` 和 `API_INFO_BC_GET` 接口,用于获取设备视频流和球机信息
- 更新 `LayoutMain.vue` 布局结构,调整左侧插槽的显示逻辑
- 在 `Three3D/index.vue` 中增强精灵图标数据绑定,支持传递 RtspMain 参数,并修复事件发射问题
- 系统 store 中增加 `getStream` 方法以调用新接口获取视频流地址
- 调整 home 页面及其子组件布局与数据交互方式,统一通过 getStream 获取视频流
- 优化高级联动、巡航等模块视频初始化逻辑,适配新的流媒体获取方式
- 统一视频 URL 的获取方式,移除旧有拼接逻辑
```

gitboyzcf пре 3 недеља
родитељ
комит
75549712b2

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

@@ -1,6 +1,17 @@
 import storage from '@/utils/storage'
 import { request } from '@/api/request.js'
+
+const noMr = import.meta.env.VITE_APP_API_BASEURL.split('api')[0]
 export default {
+  // 根据设备ID获取流
+  API_MR_STREAMS_GET(data = {}) {
+    return request({
+      baseURL: noMr,
+      url: `/api/streams`,
+      method: 'post',
+      data
+    })
+  },
   // 获取相机
   API_MR_CAMERA_GET(data = {}) {
     return request({
@@ -240,6 +251,14 @@ export default {
       data
     })
   },
+  // 获取所有球机
+  API_INFO_BC_GET(params = {}) {
+    return request({
+      url: `/api/BallCamera/Info`,
+      method: 'get',
+      params
+    })
+  },
   // 云台控制
   API_PTZ_MOVE_START_POST(params = {}, data = {}) {
     return request({

+ 2 - 2
src/layout/LayoutMain.vue

@@ -1,12 +1,12 @@
 <template>
   <div class="layout-main flex-1 h-0 relative color-#f0f0f0">
     <!-- <div class="layout-main-left absolute left-15px top-70px"> -->
-    <!-- <div class="layout-main-left absolute left-15px top-15px">
+    <div class="layout-main-left absolute left-15px top-15px">
       <slot name="left"></slot>
     </div>
     <div class="layout-main-right absolute right-15px top-15px">
       <slot name="right"></slot>
-    </div> -->
+    </div>
     <div class="layout-main-bottom w-50% absolute left-50% translate-x-[-50%] bottom--1066px">
       <slot name="bottom"></slot>
     </div>

+ 11 - 4
src/layout/Three3D/index.vue

@@ -66,7 +66,7 @@
   }
   const sprites = []
   function addSprite(arr = []) {
-    arr.forEach(({ x, y, z, id }) => {
+    arr.forEach(({ x, y, z, id, RtspMain }) => {
       const sprite = new THREE.Sprite(
         new THREE.SpriteMaterial({
           map: new THREE.TextureLoader().load('textures/video-icon.png'),
@@ -74,7 +74,8 @@
         })
       )
       sprite.vData = {
-        id
+        id,
+        RtspMain
       }
       sprite.position.set(x, y, z)
       sprite.scale.set(0.4, 0.45, 0.5)
@@ -103,7 +104,7 @@
           useHomeStore.temp = 'video'
           useSystemStore.deviceInfo = target.vData
           storage.local.set('d_id', target.vData.id)
-          // emits('onGetData', target.vData)
+          emits('onGetData', target.vData)
         })
       }
     })
@@ -167,7 +168,13 @@
             //   { x: -0.5, y: -0.16, z: -1.5 },
             //   { x: -0.5, y: -0.8, z: 1 }
             // ]
-            const sprites = res.map((item) => ({ x: item.X, y: item.Y, z: item.Z, id: item.Id }))
+            const sprites = res.map((item) => ({
+              x: item.X,
+              y: item.Y,
+              z: item.Z,
+              id: item.Id,
+              RtspMain: item.RtspMain
+            }))
             addSprite(sprites)
           }
         })

+ 23 - 1
src/stores/modules/system.js

@@ -1,7 +1,13 @@
 import { piniaStore } from '@/stores'
 import storage from '@/utils/storage'
 
-const { API_PANORAMA_POST, API_CLIP_INFO_GET, API_DEVICE_GET, API_MR_VIDEO_LIST_GET } = useRequest()
+const {
+  API_PANORAMA_POST,
+  API_CLIP_INFO_GET,
+  API_DEVICE_GET,
+  API_MR_VIDEO_LIST_GET,
+  API_MR_STREAMS_GET
+} = useRequest()
 export const useSystemStore = defineStore('systemStore', {
   state: () => ({
     ip:
@@ -80,6 +86,22 @@ export const useSystemStore = defineStore('systemStore', {
       const { width, height } = pD.getBoundingClientRect()
 
       this.ratio = { wR: width / pD.videoWidth, hR: height / pD.videoHeight }
+    },
+    async getStream(data = {}) {
+      const d = Object.assign(
+        {
+          device_id: '1723678178923719873',
+          steam_type: 'live',
+          quality: 'low',
+          from: 0,
+          to: 0,
+          user_data: {}
+        },
+        data,
+        { device_id: `${data.device_id}` }
+      )
+      const res = await API_MR_STREAMS_GET(d)
+      return res
     }
   }
 })

+ 1 - 1
src/stores/modules/tag.js

@@ -11,7 +11,7 @@ export const useTagStore = defineStore('tag', {
     async getGroupTag() {
       const { API_GETGROUP_GET, API_TAGLIST_GET } = useRequest()
       // const listGroup = await API_GETGROUP_GET({ type: 'all' })
-      const list = await API_TAGLIST_GET({ type: 'alltag' })
+      const list = await API_TAGLIST_GET({ type: 'all' })
       const temp = () => {
         return (
           list?.map((item, i) => {

+ 8 - 6
src/views/VideoBox/index.vue

@@ -89,7 +89,8 @@
   import 'vue-photo-zoom-pro/dist/style/vue-photo-zoom-pro.css'
 
   const props = defineProps({
-    id: Number
+    id: Number,
+    RtspMain: String
   })
   const useHomeStore = useOutsideHomeStore()
   const useSystem = useOutsideSystemStore()
@@ -104,11 +105,11 @@
   let tagListClone = []
 
   const init = async () => {
-    const url = videoList.value.pano_view.replace('{14}', useSystem.deviceInfo.id)
     loading.value = true
+    const { url } = await useSystem.getStream({ device_id: props.id })
+    useSystem.videoUrl = url
+    console.log('url', url)
     try {
-      // await useSystem.getDeviceInfo()
-      console.log('websocket请求')
       playerObj = omatVideoPlayer(
         '.pub-video',
         url,
@@ -163,8 +164,8 @@
     magnifyingFlag.value = flag
     if (flag) {
       if (magnifyingWorkerObj) return
-      const url = videoList.value.pano_view.replace('{14}', useSystem.deviceInfo.id)
-      magnifyingWorkerObj = omatVideoPlayer('.zoom-video', url, () => {
+      // const url = videoList.value.pano_view.replace('{14}', useSystem.deviceInfo.id)
+      magnifyingWorkerObj = omatVideoPlayer('.zoom-video', useSystem.videoUrl, () => {
         isZoom.value = false
         zoomRef.value.mouseEnter()
       })
@@ -240,6 +241,7 @@
 
   onMounted(() => {
     init()
+    console.log(props.RtspMain)
     document.body.addEventListener('keyup', keyupHedler)
   })
   onUnmounted(() => {

+ 2 - 2
src/views/home/home.vue

@@ -31,7 +31,7 @@
       <VideoBox v-else-if="!isMap" v-bind="{ ...data }" />
     </template>
     <template #bottom>
-      <MiddleBottomBox />
+      <MiddleBottomBox v-bind="{ ...data }" />
     </template>
   </Layout>
 </template>
@@ -80,7 +80,7 @@
   const getData = (v) => {
     data.value = v
   }
-  useSystem.getVideoUrl()
+  // useSystem.getVideoUrl()
 </script>
 
 <style>

+ 1 - 1
src/views/home/leftbox/topBox.vue

@@ -4,7 +4,7 @@
       id="aqsj-echarts"
       ref="echartsRef"
       width="100%"
-      height="325px"
+      height="332px"
       :loading="loading"
       :fullOptions="fullOptions"
     />

+ 2 - 5
src/views/home/middleBottomBox/components/advancedLinkage.vue

@@ -62,13 +62,10 @@
 
   let playerObj = null
 
-  const videoList = computed(() => useSystem.videoList)
-
   const init = async () => {
-    const url = videoList.value.third.replace('{4}', uuid()).replace('{13}', props.data.id)
-    console.log(url)
-
+    // const url = videoList.value.third.replace('{4}', uuid()).replace('{13}', props.data.id)
     loading.value = true
+    const { url } = await useSystem.getStream({ device_id: props.data.address })
     try {
       // await useSystem.getDeviceInfo()
       console.log('websocket请求')

+ 10 - 7
src/views/home/middleBottomBox/components/glance.vue

@@ -19,7 +19,7 @@
           >
             <Icon icon="loading" color="#007bff" width="40" height="40" />
           </div>
-          <div
+          <!-- <div
             v-if="!isVideo && !useSystem.videoList.ball_camera"
             absolute
             top-0
@@ -35,7 +35,7 @@
                 <n-button size="small" @click="reconnect"> 重连 </n-button>
               </template>
             </n-empty>
-          </div>
+          </div> -->
 
           <!-- 操作按钮 -->
           <div
@@ -92,7 +92,7 @@
 
   const clearCom = inject('clearCom')
   const useSystem = useOutsideSystemStore()
-  const { API_CLICKTOSEE_POST, API_LY_B_RELOGIN_POST } = useRequest()
+  const { API_CLICKTOSEE_POST, API_LY_B_RELOGIN_POST, API_INFO_BC_GET } = useRequest()
 
   const isVideo = ref(true)
 
@@ -136,12 +136,15 @@
   const playerObj = shallowRef(null)
   provide('playerObj', playerObj)
 
-  const getWss = () => {
+  const getWss = async () => {
+    const info = await API_INFO_BC_GET({ CameraId: props.data.id })
+    const { url } = await useSystem.getStream({ device_id: info.RtspUrl })
+
     nextTick(() => {
       isVideo.value = true
-      const url = useSystem.videoList.ball_camera
-        .replace('{4}', uuid())
-        .replace('{12}', props.data.id)
+      // const url = useSystem.videoList.ball_camera
+      //   .replace('{4}', uuid())
+      //   .replace('{12}', props.data.id)
 
       playerObj.value = omatVideoPlayer(
         '.glance-ps-video' + props.currentActive,

+ 3 - 3
src/views/home/middleBottomBox/components/tour.vue

@@ -80,7 +80,7 @@
   const tourId = ref('')
   const clearCom = inject('clearCom')
   let playerObj = null
-  const videoList = computed(() => useSystem.videoList)
+  const videoUrl = computed(() => useSystem.videoUrl)
 
   const tempArr = ref([
     // {
@@ -129,7 +129,7 @@
       const params1 = tempArr.value[0]
       params1.z = 99
       params1.show = true
-      const url = videoList.value.pano_view.replace('{14}', useSystem.deviceInfo.id)
+      // const url = videoList.value.pano_view.replace('{14}', useSystem.deviceInfo.id)
       loading.value = true
 
       try {
@@ -137,7 +137,7 @@
         console.log('websocket请求')
         playerObj = omatVideoPlayer(
           '.t-video' + props.currentActive,
-          url,
+          videoUrl.value,
           () => {
             const videoDom = document.querySelector('.t-video' + props.currentActive)
             console.log(videoDom.style.transform)

+ 5 - 2
src/views/home/middleBottomBox/index.vue

@@ -15,10 +15,10 @@
           @click="handleClick"
         />
       </div>
-      <transition name="scaleHide">
+      <transition name="scaleHide" @after-enter="onAfterEnter">
         <div v-if="show" :class="['part-plan w-full flex gap-2 justify-between']">
           <div
-            class="w-50% h-full flex flex-col aspect-ratio-video bg-#00000080 overflow-hidden"
+            class="w-50% relative flex flex-col bg-#00000080 overflow-hidden"
             v-for="(part, i) in partList"
             :key="i"
           >
@@ -51,6 +51,9 @@
     show.value = !show.value
     $mitt.emit('onVideoShow', show.value)
   }
+  const onAfterEnter = (el) => {
+    el.style.height = '267px'
+  }
   watch(
     () => useHomeStore.temp,
     (newV) => {

+ 1 - 1
src/views/home/rightbox/topBox.vue

@@ -20,7 +20,7 @@
         <ECharts
           id="bjzx-echarts"
           width="100%"
-          height="230px"
+          height="232px"
           :loading="loading"
           :fullOptions="fullOptions"
         />