yanghao 1 Minggu lalu
induk
melakukan
800051b36b
56 mengubah file dengan 301 tambahan dan 101 penghapusan
  1. 1 1
      index.html
  2. TEMPAT SAMPAH
      public/js/jessibuca-pro/bg.jpg
  3. 0 0
      public/js/jessibuca-pro/decoder-pro-audio.js
  4. TEMPAT SAMPAH
      public/js/jessibuca-pro/decoder-pro-audio.wasm
  5. 0 0
      public/js/jessibuca-pro/decoder-pro-hard-not-wasm.js
  6. 0 0
      public/js/jessibuca-pro/decoder-pro-hard.js
  7. 8 0
      public/js/jessibuca-pro/decoder-pro-mt-worker.js
  8. TEMPAT SAMPAH
      public/js/jessibuca-pro/decoder-pro-mt-worker.wasm
  9. 0 0
      public/js/jessibuca-pro/decoder-pro-mt-worker.worker.js
  10. 0 0
      public/js/jessibuca-pro/decoder-pro-mt.js
  11. 7 0
      public/js/jessibuca-pro/decoder-pro-simd-mt-worker.js
  12. TEMPAT SAMPAH
      public/js/jessibuca-pro/decoder-pro-simd-mt-worker.wasm
  13. 0 0
      public/js/jessibuca-pro/decoder-pro-simd-mt-worker.worker.js
  14. 0 0
      public/js/jessibuca-pro/decoder-pro-simd-mt.js
  15. 0 0
      public/js/jessibuca-pro/decoder-pro-simd.js
  16. TEMPAT SAMPAH
      public/js/jessibuca-pro/decoder-pro-simd.wasm
  17. 0 0
      public/js/jessibuca-pro/decoder-pro.js
  18. TEMPAT SAMPAH
      public/js/jessibuca-pro/decoder-pro.wasm
  19. TEMPAT SAMPAH
      public/js/jessibuca-pro/expand-hover.png
  20. TEMPAT SAMPAH
      public/js/jessibuca-pro/expand.png
  21. TEMPAT SAMPAH
      public/js/jessibuca-pro/jessibuca-logo.png
  22. 0 0
      public/js/jessibuca-pro/jessibuca-pro-multi.js
  23. 0 0
      public/js/jessibuca-pro/jessibuca-pro-talk.js
  24. 0 0
      public/js/jessibuca-pro/jessibuca-pro.js
  25. TEMPAT SAMPAH
      public/js/jessibuca-pro/logo.png
  26. TEMPAT SAMPAH
      public/js/jessibuca-pro/zoom-stop-hover.png
  27. TEMPAT SAMPAH
      public/js/jessibuca-pro/zoom-stop.png
  28. TEMPAT SAMPAH
      src/assets/icon/clear.png
  29. TEMPAT SAMPAH
      src/assets/icon/download.png
  30. TEMPAT SAMPAH
      src/assets/icon/fangda-hov.png
  31. TEMPAT SAMPAH
      src/assets/icon/fangda.png
  32. TEMPAT SAMPAH
      src/assets/icon/guangquan+.png
  33. TEMPAT SAMPAH
      src/assets/icon/guangquan-.png
  34. TEMPAT SAMPAH
      src/assets/icon/guangquan-hov+.png
  35. TEMPAT SAMPAH
      src/assets/icon/guangquan-hov-.png
  36. TEMPAT SAMPAH
      src/assets/icon/icon-card.png
  37. TEMPAT SAMPAH
      src/assets/icon/icon-ercode.png
  38. TEMPAT SAMPAH
      src/assets/icon/icon-font.png
  39. TEMPAT SAMPAH
      src/assets/icon/icon-fullscreen.png
  40. TEMPAT SAMPAH
      src/assets/icon/icon-info.png
  41. TEMPAT SAMPAH
      src/assets/icon/icon-list.png
  42. TEMPAT SAMPAH
      src/assets/icon/icon-rank-1.png
  43. TEMPAT SAMPAH
      src/assets/icon/icon-rank-2.png
  44. TEMPAT SAMPAH
      src/assets/icon/icon-rank-3.png
  45. TEMPAT SAMPAH
      src/assets/icon/icon-rank-4.png
  46. TEMPAT SAMPAH
      src/assets/icon/icon-search.png
  47. TEMPAT SAMPAH
      src/assets/icon/jujiao+.png
  48. TEMPAT SAMPAH
      src/assets/icon/jujiao-.png
  49. TEMPAT SAMPAH
      src/assets/icon/jujiao-hov+.png
  50. TEMPAT SAMPAH
      src/assets/icon/jujiao-hov-.png
  51. TEMPAT SAMPAH
      src/assets/icon/save.png
  52. TEMPAT SAMPAH
      src/assets/icon/suoxiao-hov.png
  53. TEMPAT SAMPAH
      src/assets/icon/suoxiao.png
  54. 35 51
      src/views/pms/video_center/device/index.vue
  55. 3 3
      src/views/pms/video_center/sip/components/player/deviceLiveStream.vue
  56. 247 46
      src/views/pms/video_center/sip/components/player/player.vue

+ 1 - 1
index.html

@@ -5,7 +5,7 @@
     <script type="text/javascript" src="/js/base64.min.js"></script>
     <script src="https://api.map.baidu.com/api?v=3.0&ak=c0crhdxQ5H7WcqbcazGr7mnHrLa4GmO0"></script>
 
-    <!-- <script src="/js/jessibuca-pro/jessibuca-pro.js"></script> -->
+    <script src="/js/jessibuca-pro/jessibuca-pro.js"></script>
     <script type="text/javascript" src="/js/EasyWasmPlayer.js"></script>
     <meta charset="UTF-8" />
     <link rel="icon" href="/favicon.ico" />

TEMPAT SAMPAH
public/js/jessibuca-pro/bg.jpg


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro-audio.js


TEMPAT SAMPAH
public/js/jessibuca-pro/decoder-pro-audio.wasm


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro-hard-not-wasm.js


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro-hard.js


File diff ditekan karena terlalu besar
+ 8 - 0
public/js/jessibuca-pro/decoder-pro-mt-worker.js


TEMPAT SAMPAH
public/js/jessibuca-pro/decoder-pro-mt-worker.wasm


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro-mt-worker.worker.js


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro-mt.js


File diff ditekan karena terlalu besar
+ 7 - 0
public/js/jessibuca-pro/decoder-pro-simd-mt-worker.js


TEMPAT SAMPAH
public/js/jessibuca-pro/decoder-pro-simd-mt-worker.wasm


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro-simd-mt-worker.worker.js


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro-simd-mt.js


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro-simd.js


TEMPAT SAMPAH
public/js/jessibuca-pro/decoder-pro-simd.wasm


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/decoder-pro.js


TEMPAT SAMPAH
public/js/jessibuca-pro/decoder-pro.wasm


TEMPAT SAMPAH
public/js/jessibuca-pro/expand-hover.png


TEMPAT SAMPAH
public/js/jessibuca-pro/expand.png


TEMPAT SAMPAH
public/js/jessibuca-pro/jessibuca-logo.png


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/jessibuca-pro-multi.js


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/jessibuca-pro-talk.js


File diff ditekan karena terlalu besar
+ 0 - 0
public/js/jessibuca-pro/jessibuca-pro.js


TEMPAT SAMPAH
public/js/jessibuca-pro/logo.png


TEMPAT SAMPAH
public/js/jessibuca-pro/zoom-stop-hover.png


TEMPAT SAMPAH
public/js/jessibuca-pro/zoom-stop.png


TEMPAT SAMPAH
src/assets/icon/clear.png


TEMPAT SAMPAH
src/assets/icon/download.png


TEMPAT SAMPAH
src/assets/icon/fangda-hov.png


TEMPAT SAMPAH
src/assets/icon/fangda.png


TEMPAT SAMPAH
src/assets/icon/guangquan+.png


TEMPAT SAMPAH
src/assets/icon/guangquan-.png


TEMPAT SAMPAH
src/assets/icon/guangquan-hov+.png


TEMPAT SAMPAH
src/assets/icon/guangquan-hov-.png


TEMPAT SAMPAH
src/assets/icon/icon-card.png


TEMPAT SAMPAH
src/assets/icon/icon-ercode.png


TEMPAT SAMPAH
src/assets/icon/icon-font.png


TEMPAT SAMPAH
src/assets/icon/icon-fullscreen.png


TEMPAT SAMPAH
src/assets/icon/icon-info.png


TEMPAT SAMPAH
src/assets/icon/icon-list.png


TEMPAT SAMPAH
src/assets/icon/icon-rank-1.png


TEMPAT SAMPAH
src/assets/icon/icon-rank-2.png


TEMPAT SAMPAH
src/assets/icon/icon-rank-3.png


TEMPAT SAMPAH
src/assets/icon/icon-rank-4.png


TEMPAT SAMPAH
src/assets/icon/icon-search.png


TEMPAT SAMPAH
src/assets/icon/jujiao+.png


TEMPAT SAMPAH
src/assets/icon/jujiao-.png


TEMPAT SAMPAH
src/assets/icon/jujiao-hov+.png


TEMPAT SAMPAH
src/assets/icon/jujiao-hov-.png


TEMPAT SAMPAH
src/assets/icon/save.png


TEMPAT SAMPAH
src/assets/icon/suoxiao-hov.png


TEMPAT SAMPAH
src/assets/icon/suoxiao.png


+ 35 - 51
src/views/pms/video_center/device/index.vue

@@ -36,14 +36,12 @@
             size="default"
             style="width: 150px"
           >
-           
-
-              <el-option
-                v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_STATUS)"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value"
-              />
+            <el-option
+              v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_STATUS)"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
           </el-select>
         </el-form-item>
         <el-form-item>
@@ -65,7 +63,7 @@
     </el-card>
 
     <el-card
-      class="main-card"
+      class="main-card border-none!"
       shadow="never"
       v-if="showType == 'list'"
       :style="showSearch ? '' : 'margin:0'"
@@ -104,7 +102,7 @@
         </div>
 
         <div>
-          <el-radio-group class="float-right ml-10"  plain v-model="showType">
+          <el-radio-group class="float-right ml-10" plain v-model="showType">
             <el-radio-button label="card"
               ><el-icon><Menu /></el-icon
             ></el-radio-button>
@@ -183,11 +181,7 @@
         </el-table-column>
         <el-table-column label="状态" align="center" prop="status" width="80">
           <template #default="scope">
-            <dict-tag
-              :type="DICT_TYPE.IOT_DEVICE_STATUS"
-              :value="scope.row.status"
-             
-            />
+            <dict-tag :type="DICT_TYPE.IOT_DEVICE_STATUS" :value="scope.row.status" />
           </template>
         </el-table-column>
         <el-table-column label="信号" align="center" prop="rssi" width="60">
@@ -212,8 +206,7 @@
         </el-table-column>
         <el-table-column label="定位方式" align="center" prop="locationWay" width="100">
           <template #default="scope">
-          
-             <dict-tag :type="DICT_TYPE.VIDEO_CENTER_LOCATION_WAY" :value="scope.row.locationWay" />
+            <dict-tag :type="DICT_TYPE.VIDEO_CENTER_LOCATION_WAY" :value="scope.row.locationWay" />
           </template>
         </el-table-column>
         <el-table-column label="固件版本" align="center" prop="firmwareVersion" width="100">
@@ -322,7 +315,7 @@
         </div>
 
         <div>
-          <el-radio-group class="float-right ml-10" plain  v-model="showType">
+          <el-radio-group class="float-right ml-10" plain v-model="showType">
             <el-radio-button label="card"
               ><el-icon><Menu /></el-icon
             ></el-radio-button>
@@ -355,29 +348,28 @@
                 >
                   <el-tooltip class="item" effect="dark" content="分享的设备" placement="top-start">
                     <svg-icon
-                      class="mr5"
+                      class="mr-5"
                       icon-class="share"
                       style="font-size: 20px; vertical-align: -6px"
                       v-if="item.isOwner != 1"
                     />
                   </el-tooltip>
                   <svg-icon icon-class="device" v-if="item.isOwner == 1" />
+
                   <b class="card-item__title" @click="handleDeviceDetail(item)">{{
                     item.deviceName
                   }}</b>
 
-                  <dict-tag
-                    :options="iot_device_status"
-                    :value="item.status"
-                    size="default"
-                    style="display: inline-block"
-                  />
+                  <dict-tag :type="DICT_TYPE.IOT_DEVICE_STATUS" :value="item.status" />
                 </el-link>
               </el-col>
               <el-col :span="1.5" style="font-size: 20px; padding-top: 5px; cursor: pointer">
-                
-
-                <el-image style="width: 20px; height: 20px" :src="qrcode" :fit="fit" @click="openSummaryDialog(item)" />
+                <el-image
+                  style="width: 20px; height: 20px"
+                  :src="qrcode"
+                  :fit="fit"
+                  @click="openSummaryDialog(item)"
+                />
               </el-col>
               <el-col :span="5">
                 <div style="font-size: 28px; color: #ccc">
@@ -401,15 +393,17 @@
 
             <el-row :gutter="10">
               <el-col :span="17">
-                <div style="text-align: left; line-height: 40px; white-space: nowrap">
-                  <el-tag v-if="item.protocolCode" class="mr5" type="primary" size="default">
+                <div
+                  style="text-align: left; line-height: 40px; white-space: nowrap;"
+                >
+                  <el-tag v-if="item.protocolCode" class="mr-5" type="primary" size="default">
                     {{ item.protocolCode }}
                   </el-tag>
-                  <el-tag v-if="item.transport" class="mr5" type="primary" size="default">
+                  <el-tag v-if="item.transport" class="mr-5" type="primary" size="default">
                     {{ item.transport }}
                   </el-tag>
                 </div>
-                <el-descriptions :column="1" size="default" style="white-space: nowrap">
+                <el-descriptions :column="1" size="small" style="white-space: nowrap">
                   <el-descriptions-item label="编号">
                     <span class="font-primary">{{ item.serialNumber }}</span>
                   </el-descriptions-item>
@@ -457,13 +451,13 @@
             </el-row>
 
             <div class="card-item__footer">
-              <el-button class="delete-btn" size="default" @click="handleDelete(item)"
+              <el-button class="delete-btn" size="small" @click="handleDelete(item)"
                 >删除</el-button
               >
-              <el-button class="detail-btn" size="default" @click="handleEditDevice(item, 'basic')"
+              <el-button class="detail-btn" size="small" @click="handleEditDevice(item, 'basic')"
                 >查看详情</el-button
               >
-              <el-button size="default" @click="handleRunDevice(item)">运行状态</el-button>
+              <el-button size="small" @click="handleRunDevice(item)">运行状态</el-button>
             </div>
           </el-card>
         </el-col>
@@ -547,7 +541,7 @@ import videoImage from '@/assets/imgs/video.svg'
 import productImage from '@/assets/imgs/product.svg'
 import qrcode from '@/assets/imgs/qrcode.png'
 
-import {DICT_TYPE, getDictLabel, getStrDictOptions } from "@/utils/dict";
+import { DICT_TYPE, getDictLabel, getStrDictOptions } from '@/utils/dict'
 
 const { proxy } = getCurrentInstance()
 // Vue Router 和 Store
@@ -555,12 +549,6 @@ const router = useRouter()
 const route = useRoute()
 const store = useStore()
 
-
-const iot_device_status = ref([])
-const iot_is_enable = ref([])
-const iot_location_way = ref([])
-const iot_transport_type = ref([])
-
 // Refs
 const queryFormRef = ref()
 const batchImportRef = ref()
@@ -619,7 +607,7 @@ const isSubDev = ref(false)
 
 // 生命周期钩子
 onMounted(() => {
-   const time = route.query.t
+  const time = route.query.t
   if (time != null && time != uniqueId.value) {
     uniqueId.value = time
     // 页码筛选
@@ -648,7 +636,6 @@ onMounted(() => {
       queryParams.productId = null
       queryParams.groupId = null
     }
-    
   }
 
   getList()
@@ -694,7 +681,6 @@ onActivated(() => {
 // 方法定义
 /* 连接Mqtt消息服务器 */
 async function connectMqtt() {
- 
   if (proxy.$mqttTool.client == null) {
     await proxy.$mqttTool.connect()
   }
@@ -704,7 +690,6 @@ async function connectMqtt() {
 
 /* Mqtt回调处理  */
 function mqttCallback() {
- 
   proxy.$mqttTool.client.on('message', (topic, message, buffer) => {
     let topics = topic.split('/')
     let productId = topics[1]
@@ -743,7 +728,6 @@ function handleCommand(command) {
 
 //批量导入设备
 function handleBatchImport() {
-  
   if (batchImportRef.value) {
     batchImportRef.value.showDialog()
     batchImportRef.value.importForm.productId = null
@@ -864,12 +848,10 @@ function mqttSubscribe(list) {
 /** 查询设备分组列表 */
 const userStore = useUserStoreWithOut()
 
-
 /** 查询所有简短设备列表 */
 function getList() {
   loading.value = true
   queryParams.params = {}
-  
 
   listDeviceShort(queryParams)
     .then((response) => {
@@ -1036,7 +1018,7 @@ function getImg(row) {
   .main-card.el-card {
     margin-top: 20px;
     padding-bottom: 50px;
-    border: 0;
+    border: none;
 
     .card-toolbar {
       display: flex;
@@ -1142,7 +1124,9 @@ function getImg(row) {
 
     .card-item__footer {
       margin-top: 1em;
-      text-align: right;
+      display: flex;
+      justify-content: center;
+      padding: 0 5px;
 
       .el-button {
         background: #f5f7fa;

+ 3 - 3
src/views/pms/video_center/sip/components/player/deviceLiveStream.vue

@@ -39,14 +39,14 @@
       class="components-container"
       style="margin-top: 10px;"
     />
-
-   
   </div>
 </template>
 
 <script setup>
 import { ref, reactive, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
 import Player from './player.vue'
+
+
 import { startPlay, closeStream, listChannel } from '@/api/pms/video/channel'
 import { startPlayRecord } from '@/api/pms/video/record'
 
@@ -193,7 +193,7 @@ const startPlayer = () => {
   } else {
     // 直播播放
     startPlay(deviceId.value, channelId.value).then((response) => {
-    
+      console.log('开始播放:' + deviceId.value + ' : ' + channelId.value)
       streamId.value = response.streamId
       playurl.value = response.playurl
       playerRef.value?.play(playurl.value)

+ 247 - 46
src/views/pms/video_center/sip/components/player/player.vue

@@ -1,7 +1,61 @@
 <template>
   <div class="root">
     <div class="container-shell">
-      <div id="container" ref="containerRef" :style="{width: width, height: height}"></div>
+      <div id="container" ref="container" :style="{ width: width, height: height }"></div>
+    </div>
+    <div id="jb-pro-ptz-btns" style="display: none">
+      <div class="jb-pro-ptz-btns">
+        <div class="jb-pro-ptz-btn">
+          <div class="jb-pro-ptz-expand jb-pro-ptz-icon">
+            <div class="jb-pro-ptz-expand-icon-fangda icon" onclick="handlePtzScale('fangda')"></div>
+            <span class="icon-title-tips">
+              <span class="icon-title">放大</span>
+            </span>
+          </div>
+          <div class="jb-pro-ptz-narrow jb-pro-ptz-icon">
+            <div class="jb-pro-ptz-narrow-icon-suoxiao icon" onclick="handlePtzScale('suoxiao')"></div>
+            <span class="icon-title-tips">
+              <span class="icon-title">缩小</span>
+            </span>
+          </div>
+        </div>
+
+        <div class="jb-pro-ptz-btn">
+          <div class="jb-pro-ptz-aperture-far jb-pro-ptz-icon">
+            <div
+              class="jb-pro-ptz-aperture-icon-guangquan icon"
+              onclick="handlePtzScale('guangquan')"
+            ></div>
+            <span class="icon-title-tips">
+              <span class="icon-title">光圈+</span>
+            </span>
+          </div>
+          <div class="jb-pro-ptz-aperture-near jb-pro-ptz-icon">
+            <div
+              class="jb-pro-ptz-aperture-icon-guangquan- icon"
+              onclick="handlePtzScale('guangquan-')"
+            ></div>
+            <span class="icon-title-tips">
+              <span class="icon-title">光圈-</span>
+            </span>
+          </div>
+        </div>
+
+        <div class="jb-pro-ptz-btn">
+          <div class="jb-pro-ptz-focus-far jb-pro-ptz-icon">
+            <div class="jb-pro-ptz-focus-icon-jujiao icon" onclick="handlePtzScale('jujiao')"></div>
+            <span class="icon-title-tips">
+              <span class="icon-title">聚焦+</span>
+            </span>
+          </div>
+          <div class="jb-pro-ptz-focus-near jb-pro-ptz-icon">
+            <div class="jb-pro-ptz-focus-icon-jujiao- icon" onclick="handlePtzScale('jujiao-')"></div>
+            <span class="icon-title-tips">
+              <span class="icon-title">聚焦-</span>
+            </span>
+          </div>
+        </div>
+      </div>
     </div>
   </div>
 </template>
@@ -9,12 +63,13 @@
 <script setup>
 import { ref, reactive, onMounted, onBeforeUnmount, watch, nextTick } from 'vue'
 import { ptzdirection, ptzscale } from '@/api/pms/video/sipdevice'
+import { func } from 'vue-types'
 
 // 定义props
 const props = defineProps({
   playerinfo: {
     type: Object,
-    default: null,
+    default: null
   },
   width: {
     type: String,
@@ -27,7 +82,7 @@ const props = defineProps({
 })
 
 // 定义响应式数据
-const containerRef = ref(null)
+const container = ref(null)
 const isPlaybackPause = ref(false)
 const useWebGPU = ref(false)
 const isInit = ref(false)
@@ -38,24 +93,25 @@ const operateBtns = reactive({
   fullscreen: true,
   zoom: true,
   play: true,
-  audio: true,
+  audio: true
 })
 
 // jessibucaPlayer实例存储
 let jessibucaPlayer = {}
 
 // Watch playerinfo变化
-watch(() => props.playerinfo, (newVal, oldVal) => {
-  console.log('playerinfo 发生变化')
-  playinfo.value = newVal
-  if (newVal && newVal.playtype !== '') {
-    playtype.value = newVal.playtype
+watch(
+  () => props.playerinfo,
+  (newVal, oldVal) => {
+    playinfo.value = newVal
+    if (newVal && newVal.playtype !== '') {
+      playtype.value = newVal.playtype
+    }
   }
-})
+)
 
 // 组件挂载时执行
 onMounted(() => {
-  console.log("component mounted")
   playinfo.value = props.playerinfo
   if (playinfo.value && playinfo.value.playtype !== '') {
     playtype.value = playinfo.value.playtype
@@ -90,7 +146,7 @@ const init = () => {
   if (useVconsole && window.VConsole) {
     new window.VConsole()
   }
-  
+
   nextTick(() => {
     initplayer()
   })
@@ -100,11 +156,11 @@ const init = () => {
 const initplayer = () => {
   isPlaybackPause.value = false
   initconf()
-  
+
   jessibucaPlayer[currentInstanceId.value] = new window.JessibucaPro({
-    container: containerRef.value,
-    decoder: '/js/jessibuca-pro/decoder-pro.js',
+    container: container.value,
     videoBuffer: Number(0.2), // 缓存时长
+    decoder: '/js/jessibuca-pro/decoder-pro.js',
     isResize: false,
     useWCS: false,
     useMSE: false,
@@ -112,22 +168,87 @@ const initplayer = () => {
     wcsUseVideoRender: false,
     loadingText: '加载中',
     debug: false,
-    debugLevel: "debug",
+    debugLevel: 'debug',
     showBandwidth: true, // 显示网速
     showPlaybackOperate: true,
     operateBtns: { ...operateBtns },
     forceNoOffscreen: true,
     isNotMute: true, // 默认关闭声音
     showPerformance: false,
-    // playFailedAndReplay: true,
-    // networkDelayTimeoutReplay: true,
     playbackForwardMaxRateDecodeIFrame: 4,
-    useWebGPU: useWebGPU.value, // 使用WebGPU
+    useWebGPU: useWebGPU.value // 使用WebGPU
   })
-  
+
   let jessibuca = jessibucaPlayer[currentInstanceId.value]
+
   initcallback(jessibuca)
+
   isInit.value = true
+  initPtzBtns()
+}
+
+function initPtzBtns() {
+  const ptzBtns = document.querySelector('.jessibuca-ptz-controls')
+  ptzBtns.appendChild(document.querySelector('#jb-pro-ptz-btns .jb-pro-ptz-btns').cloneNode(true))
+  ptzBtns.querySelector('.jb-pro-ptz-expand-icon-fangda').addEventListener('click', () => {
+    handlePtzScale('fangda')
+  })
+  ptzBtns.querySelector('.jb-pro-ptz-narrow-icon-suoxiao').addEventListener('click', () => {
+    handlePtzScale('suoxiao')
+  })
+  ptzBtns.querySelector('.jb-pro-ptz-aperture-icon-guangquan').addEventListener('click', () => {
+    handlePtzScale('guangquan')
+  })
+  ptzBtns.querySelector('.jb-pro-ptz-aperture-icon-guangquan-').addEventListener('click', () => {
+    handlePtzScale('guangquan-')
+  })
+  ptzBtns.querySelector('.jb-pro-ptz-focus-icon-jujiao').addEventListener('click', () => {
+    handlePtzScale('jujiao')
+  })
+  ptzBtns.querySelector('.jb-pro-ptz-focus-icon-jujiao-').addEventListener('click', () => {
+    handlePtzScale('jujiao-')
+  })
+}
+
+function handlePtzScale(arrow) {
+  let inOut = 0
+  let irisInOut = 0
+  let focusInOut = 0
+  switch (arrow) {
+    case 'fangda': {
+      inOut = 1
+      break
+    }
+    case 'suoxiao': {
+      inOut = 2
+      break
+    }
+    case 'guangquan': {
+      irisInOut = 1
+      break
+    }
+    case 'guangquan-': {
+      irisInOut = 2
+      break
+    }
+    case 'jujiao': {
+      focusInOut = 1
+      break
+    }
+    case 'jujiao-': {
+      focusInOut = 2
+      break
+    }
+  }
+
+  var data = {
+    inOut: inOut,
+    irisInOut: irisInOut,
+    focusInOut: focusInOut
+  }
+  if (playinfo.value && playinfo.value.playtype !== '') {
+    ptzscale(playinfo.value.deviceId, playinfo.value.channelId, data).then((response) => {})
+  }
 }
 
 // 初始化配置
@@ -146,11 +267,11 @@ const initcallback = (jessibuca) => {
   jessibuca.on('error', function (error) {
     console.log('jessibuca error', error)
   })
-  
-  jessibuca.on("playFailedAndPaused", function (reason, lastFrameInfo, msg) {
+
+  jessibuca.on('playFailedAndPaused', function (reason, lastFrameInfo, msg) {
     console.log('playFailedAndPaused', reason, msg)
   })
-  
+
   jessibuca.on('visibilityChange', (value) => {
     if (value === true) {
       // 窗口显示
@@ -160,27 +281,25 @@ const initcallback = (jessibuca) => {
       console.log('visibilityChange false')
     }
   })
-  
+
   jessibuca.on('pause', function (pause) {
     console.log('pause success!', pause)
   })
-  
-  jessibuca.on('play', function (flag) {
-    console.log('play!', flag)
-  })
-  
+
+  jessibuca.on('play', function (flag) {})
+
   jessibuca.on('loading', function (load) {
     console.log('loading success!', load)
   })
-  
+
   jessibuca.on('stats', function (s) {
     // console.log('stats is', s)
   })
-  
+
   jessibuca.on('timeout', function (error) {
     console.log('timeout:', error)
   })
-  
+
   jessibuca.on('playbackPreRateChange', (rate) => {
     jessibuca.forward(rate)
   })
@@ -193,12 +312,12 @@ const initcallback = (jessibuca) => {
       pre++
     }
   })
-  
+
   jessibuca.on(window.JessibucaPro.EVENTS.ptz, (arrow) => {
     console.log('ptz arrow', arrow)
     handlePtz(arrow)
   })
-  
+
   jessibuca.on('crashLog', (data) => {
     console.log('crashLog is', data)
   })
@@ -213,12 +332,16 @@ const registercallback = (events, func) => {
 
 // 判断是否为移动设备
 const isMobile = () => {
-  return /iphone|ipad|android.*mobile|windows.*phone|blackberry.*mobile/i.test(window.navigator.userAgent.toLowerCase())
+  return /iphone|ipad|android.*mobile|windows.*phone|blackberry.*mobile/i.test(
+    window.navigator.userAgent.toLowerCase()
+  )
 }
 
 // 判断是否为平板设备
 const isPad = () => {
-  return /ipad|android(?!.*mobile)|tablet|kindle|silk/i.test(window.navigator.userAgent.toLowerCase())
+  return /ipad|android(?!.*mobile)|tablet|kindle|silk/i.test(
+    window.navigator.userAgent.toLowerCase()
+  )
 }
 
 // 播放
@@ -261,13 +384,13 @@ const handlePtz = (arrow) => {
   } else if (arrow === 'down') {
     upDown = 2
   }
-  
-  var data = {
+
+  const data = {
     leftRight: leftRight,
     upDown: upDown,
-    moveSpeed: 125,
+    moveSpeed: 125
   }
-  
+
   if (playinfo.value && playinfo.value.playtype !== '') {
     ptzdirection(playinfo.value.deviceId, playinfo.value.channelId, data).then(async (response) => {
       //console.log("云台方向控制:" + JSON.stringify(response))
@@ -287,11 +410,11 @@ const playback = (url, playTimes) => {
       isCacheBeforeDecodeForFpsRender: false, // rfs渲染时,是否在解码前缓存数据
       supportWheel: true, // 是否支持滚动轴切换精度。
       rateConfig: [
-        {label: '正常', value: 1},
-        {label: '2倍', value: 2},
-        {label: '4倍', value: 4},
-        {label: '8倍', value: 8},
-      ],
+        { label: '正常', value: 1 },
+        { label: '2倍', value: 2 },
+        { label: '4倍', value: 4 },
+        { label: '8倍', value: 8 }
+      ]
     })
     isPlaybackPause.value = false
   }
@@ -377,6 +500,8 @@ defineExpose({
 #container {
   background: rgba(13, 14, 27, 0.7);
   border-radius: 5px;
+  width: 600px;
+  height: 500px;
 }
 
 .err {
@@ -405,4 +530,80 @@ defineExpose({
     height: 52.7vw;
   }
 }
-</style>
+
+.jb-pro-ptz-btns {
+  .jb-pro-ptz-btn {
+    display: flex;
+    justify-content: space-around;
+
+    .jb-pro-ptz-icon {
+      position: relative;
+
+      .icon {
+        width: 28px;
+        height: 28px;
+        margin-top: 3px;
+      }
+    }
+
+    .jb-pro-ptz-expand-icon-fangda {
+      background-image: url('@/assets/icon/fangda.png');
+    }
+
+    .jb-pro-ptz-narrow-icon-suoxiao {
+      background-image: url('@/assets/icon/suoxiao.png');
+    }
+
+    .jb-pro-ptz-aperture-icon-guangquan {
+      background-image: url('@/assets/icon/guangquan+.png');
+    }
+
+    .jb-pro-ptz-aperture-icon-guangquan- {
+      background-image: url('@/assets/icon/guangquan-.png');
+    }
+
+    .jb-pro-ptz-focus-icon-jujiao {
+      background-image: url('@/assets/icon/jujiao+.png');
+    }
+
+    .jb-pro-ptz-focus-icon-jujiao- {
+      background-image: url('@/assets/icon/jujiao-.png');
+    }
+
+    .jb-pro-ptz-icon:hover {
+      .icon-title-tips {
+        visibility: visible;
+        opacity: 1;
+      }
+
+      .jb-pro-ptz-expand-icon-fangda {
+        background-image: url('@/assets/icon/fangda-hov.png');
+      }
+
+      .jb-pro-ptz-narrow-icon-suoxiao {
+        background-image: url('@/assets/icon/suoxiao-hov.png');
+      }
+
+      .jb-pro-ptz-aperture-icon-guangquan {
+        background-image: url('@/assets/icon/guangquan-hov+.png');
+      }
+
+      .jb-pro-ptz-aperture-icon-guangquan- {
+        background-image: url('@/assets/icon/guangquan-hov-.png');
+      }
+
+      .jb-pro-ptz-focus-icon-jujiao {
+        background-image: url('@/assets/icon/jujiao-hov+.png');
+      }
+
+      .jb-pro-ptz-focus-icon-jujiao- {
+        background-image: url('@/assets/icon/jujiao-hov-.png');
+      }
+    }
+  }
+
+  img {
+    cursor: pointer;
+  }
+}
+</style>

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini