Quellcode durchsuchen

视频中心修改样式

yanghao vor 1 Woche
Ursprung
Commit
c33e60f065

+ 1 - 1
.env.local

@@ -4,7 +4,7 @@ NODE_ENV=development
 VITE_DEV=true
 
 # 请求路径
-VITE_BASE_URL='http://192.168.188.149:8080' # 192.168.188.149:48080 https://iot.deepoil.cc
+VITE_BASE_URL='http://192.168.188.150:8080' # 192.168.188.149:48080 https://iot.deepoil.cc
 
 # MQTT服务地址
 VITE_MQTT_SERVER_URL = 'ws://localhost:8083/mqtt'

+ 1 - 1
src/api/pms/video/channel.ts

@@ -3,7 +3,7 @@ import request from '@/config/axios'
 // 查询监控设备通道信息列表
 export async function listChannel(query) {
   return await request.get({
-    url: '/rq/yf-sip-device-channel/list',
+    url: '/rq/yf-sip-device-channel/page',
     params: query
   })
 }

+ 1 - 1
src/api/pms/video/sipdevice.ts

@@ -10,7 +10,7 @@ export function listSipDevice(query) {
 
 export function listSipDeviceChannel(deviceId) {
   return request.get({
-    url: '/sip/device/listchannel/'+ deviceId,
+    url: '/rq/yf-sip-device/listchannel/'+ deviceId,
     
   })
 }

+ 1 - 0
src/assets/svgs/device.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1640528598588" class="icon" viewBox="0 0 1280 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="16798" xmlns:xlink="http://www.w3.org/1999/xlink" width="160" height="128"><defs><style type="text/css"></style></defs><path d="M153.64583333 62h984.375C1176.87083362 62 1208.33333333 93.5 1208.33333333 132.3125v205.49999971c0 38.85000029-31.5 70.35000029-70.3125 70.35000029H153.64583333A70.3125 70.3125 0 0 1 83.33333333 337.85V132.3125C83.33333333 93.46249971 114.83333333 62 153.64583333 62z m104.92499971 138.44999971a34.61249971 34.61249971 0 0 0 0 69.22500029h212.02500058a34.61249971 34.61249971 0 0 0 0-69.22500029H258.57083304zM153.64583333 615.87500029h984.375c38.85000029 0 70.3125 31.5 70.3125 70.3125v205.5375C1208.33333333 930.53750029 1176.83333333 962 1138.02083333 962H153.64583333A70.3125 70.3125 0 0 1 83.33333333 891.6875v-205.49999971c0-38.85000029 31.5-70.35000029 70.3125-70.35000029z m104.92499971 138.4875a34.61249971 34.61249971 0 1 0 0 69.22499942h212.02500058a34.61249971 34.61249971 0 1 0 0-69.22499942H258.57083304z" p-id="16799"></path></svg>

Datei-Diff unterdrückt, da er zu groß ist
+ 1 - 0
src/assets/svgs/share.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/assets/svgs/wifi_0.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/assets/svgs/wifi_1.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/assets/svgs/wifi_2.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/assets/svgs/wifi_3.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
src/assets/svgs/wifi_4.svg


+ 4 - 1
src/utils/dict.ts

@@ -307,6 +307,9 @@ export enum DICT_TYPE {
   VIDEO_CENTER_TRANSPORT_TYPE = 'iot_transport_type', // 传输方式
   VIDEO_CENTER_VERTIFICATE_METHOD = 'iot_vertificate_method', // 认证方式
   VIDEO_CENTER_NETWORK_METHOD = 'iot_network_method', // 联网方式
-
+  VIDEO_DEVICE_STATUS = 'video_device_status', // 设备状态
+  CHANNEL_TYPE = 'channel_type',
+  VIDEO_TYPE = 'video_type',
+  VIDEO_PRODUCT_TYPE = 'video_product_type',
 
 }

+ 4 - 2
src/views/pms/video_center/category/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div style="padding: 6px">
-    <el-card v-show="showSearch" style="margin-bottom: 5px" shadow="never"> 
+    <el-card v-show="showSearch" style="margin-bottom: 5px;border: 0;" shadow="never"> 
 
       <el-form :model="queryParams" ref="queryFormRef" inline style="margin-bottom: -20px">
         <el-form-item :label="t('product.index091251-2')" prop="categoryName">
@@ -23,7 +23,7 @@
       </el-form>
     </el-card>
 
-    <el-card class="main-card" shadow="never">
+    <el-card class="main-card" shadow="never" style="border: 0;">
       <div class="card-toolbar mb8">
         <el-button type="primary" :icon="Plus" size="default" @click="handleAdd">新增</el-button>
       </div>
@@ -55,6 +55,7 @@
               size="small"
               type="primary"
               plain
+              text
               style="padding: 5px"
               :icon="View"
               @click="handleUpdate(scope.row)"
@@ -66,6 +67,7 @@
               size="small"
               type="danger"
               plain
+              text
               style="padding: 5px"
               :icon="Delete"
               @click="handleDelete(scope.row)"

+ 29 - 0
src/views/pms/video_center/device/device-edit.vue

@@ -915,6 +915,35 @@ const formatThingsModel = (data) => {
   // 实现保持原样,仅语法调整
 }
 
+function loadBMap() {
+    return new Promise(function(resolve, reject) {
+        if (typeof BMap !== 'undefined') {
+            resolve(BMap)
+            return true
+        }
+        window.onBMapCallback = function() {
+            resolve(BMap)
+        }
+        // 使用https协议需要添加一下meta标签
+        let protocolStr = document.location.protocol;  
+        if(protocolStr == "https:")  
+        {  
+            let meta = document.createElement('meta')
+            meta.httpEquiv = 'Content-Security-Policy'
+            meta.content ='upgrade-insecure-requests'
+            meta.onerror = reject
+            document.head.appendChild(meta)
+        }       
+        // 引入百度地图
+        let script = document.createElement('script')
+        script.type = 'text/javascript'
+        script.src =
+            'https://api.map.baidu.com/api?v=3.0&ak=c0crhdxQ5H7WcqbcazGr7mnHrLa4GmO0&type=webgl'
+        script.onerror = reject
+        document.head.appendChild(script)
+    })
+}
+
 const loadMap = () => {
   nextTick(() => {
     loadBMap().then(() => {

+ 43 - 31
src/views/pms/video_center/device/index.vue

@@ -37,7 +37,7 @@
             style="width: 150px"
           >
             <el-option
-              v-for="dict in getStrDictOptions(DICT_TYPE.IOT_DEVICE_STATUS)"
+              v-for="dict in getStrDictOptions(DICT_TYPE.VIDEO_DEVICE_STATUS)"
               :key="dict.value"
               :label="dict.label"
               :value="dict.value"
@@ -63,15 +63,16 @@
     </el-card>
 
     <el-card
-      class="main-card border-none!"
+      class="main-card border-0!"
       shadow="never"
       v-if="showType == 'list'"
       :style="showSearch ? '' : 'margin:0'"
+      style="border: 0;"
     >
       <div class="card-toolbar mb8">
         <div>
           <el-dropdown class="mr10" @command="handleCommand">
-            <el-button size="default" type="primary" :icon="Plus">
+            <el-button size="small" type="primary" :icon="Plus">
               新增
               <el-icon class="el-icon--right"><arrow-down /></el-icon>
             </el-button>
@@ -181,7 +182,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.VIDEO_DEVICE_STATUS" :value="scope.row.status" />
           </template>
         </el-table-column>
         <el-table-column label="信号" align="center" prop="rssi" width="60">
@@ -226,7 +227,7 @@
         </el-table-column>
         <el-table-column
           label="操作"
-          align="left"
+          align="center"
           class-name="small-padding fixed-width"
           fixed="right"
           width="200"
@@ -275,11 +276,12 @@
       shadow="never"
       v-if="showType == 'card'"
       :style="showSearch ? '' : 'margin:0'"
+       style="border: 0;"
     >
       <div class="card-toolbar mb8">
         <div>
           <el-dropdown class="mr10" @command="handleCommand">
-            <el-button size="default" type="primary" :icon="Plus">
+            <el-button size="small" type="primary" :icon="Plus">
               新增
               <el-icon class="el-icon--right"><arrow-down /></el-icon>
             </el-button>
@@ -338,32 +340,32 @@
           :key="index"
           style="margin-bottom: 30px; text-align: center"
         >
-          <el-card :body-style="{ padding: '20px' }" shadow="hover" class="card-item">
+          <el-card :body-style="{ padding: '20px' }" shadow="hover" class="card-item"  style="border: 0;">
             <el-row :gutter="10" justify="space-between">
-              <el-col :span="19" style="text-align: left">
+              <el-col :span="18" style="text-align: left">
                 <el-link
                   type=""
                   :underline="false"
                   style="font-weight: bold; font-size: 16px; line-height: 32px"
                 >
                   <el-tooltip class="item" effect="dark" content="分享的设备" placement="top-start">
-                    <svg-icon
-                      class="mr-5"
-                      icon-class="share"
+                    <Icon
+                      icon="svg-icon: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)">{{
+                  <Icon icon="svg-icon:device" v-if="item.isOwner == 1" />
+
+                  <span class="card-item__title" @click="handleDeviceDetail(item)">{{
                     item.deviceName
-                  }}</b>
+                  }}</span>
 
-                  <dict-tag :type="DICT_TYPE.IOT_DEVICE_STATUS" :value="item.status" />
+                  <dict-tag :type="DICT_TYPE.VIDEO_DEVICE_STATUS" :value="item.status" />
                 </el-link>
               </el-col>
-              <el-col :span="1.5" style="font-size: 20px; padding-top: 5px; cursor: pointer">
+              <el-col :span="3" style="font-size: 20px; padding-top: 5px; cursor: pointer">
                 <el-image
                   style="width: 20px; height: 20px"
                   :src="qrcode"
@@ -371,31 +373,36 @@
                   @click="openSummaryDialog(item)"
                 />
               </el-col>
-              <el-col :span="5">
-                <div style="font-size: 28px; color: #ccc">
-                  <svg-icon v-if="item.status == 3 && item.rssi >= '-55'" icon-class="wifi_4" />
-                  <svg-icon
+              <el-col :span="2">
+                <div style="font-size: 28px; color: #ccc;">
+                  <Icon icon="svg-icon:wifi_4" style="font-size: 26px;" v-if="item.status == 3 && item.rssi >= '-55'" />
+
+                  <Icon
+                    style="font-size: 26px;"
+                    icon="svg-icon:wifi_3"
                     v-else-if="item.status == 3 && item.rssi >= '-70' && item.rssi < '-55'"
-                    icon-class="wifi_3"
                   />
-                  <svg-icon
+
+                  <Icon
+                  style="font-size: 26px;"
+                    icon="svg-icon:wifi_2"
                     v-else-if="item.status == 3 && item.rssi >= '-85' && item.rssi < '-70'"
-                    icon-class="wifi_2"
                   />
-                  <svg-icon
+
+                  <Icon
+                  style="font-size: 26px;"
+                    icon="svg-icon:wifi_1"
                     v-else-if="item.status == 3 && item.rssi >= '-100' && item.rssi < '-85'"
-                    icon-class="wifi_1"
                   />
-                  <svg-icon v-else icon-class="wifi_0" />
+
+                  <Icon icon="svg-icon:wifi_0" v-else style="font-size: 26px;" />
                 </div>
               </el-col>
             </el-row>
 
             <el-row :gutter="10">
               <el-col :span="17">
-                <div
-                  style="text-align: left; line-height: 40px; white-space: nowrap;"
-                >
+                <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>
@@ -410,8 +417,8 @@
                   <el-descriptions-item label="产品">
                     {{ item.productName }}
                   </el-descriptions-item>
-                  <el-descriptions-item label="激活时间">
-                    {{ parseTime(item.activeTime, '{y}-{m}-{d}') }}
+                  <el-descriptions-item label="创建时间">
+                    {{ parseTime(item.createTime, '{y}-{m}-{d}') }}
                   </el-descriptions-item>
                 </el-descriptions>
               </el-col>
@@ -541,6 +548,8 @@ import videoImage from '@/assets/imgs/video.svg'
 import productImage from '@/assets/imgs/product.svg'
 import qrcode from '@/assets/imgs/qrcode.png'
 
+import SvgIcon from '@/components/SvgIcon/index.vue'
+
 import { DICT_TYPE, getDictLabel, getStrDictOptions } from '@/utils/dict'
 
 const { proxy } = getCurrentInstance()
@@ -1114,6 +1123,9 @@ function getImg(row) {
     .card-item__title {
       vertical-align: -2px;
       margin-right: 0.5em;
+      font-size: 16px;
+      line-height: 32px;
+      color: black;
     }
 
     .el-descriptions {

+ 17 - 12
src/views/pms/video_center/product/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="product normal-form" style="padding: 6px">
-    <el-card style="margin: 20px">
+    <el-card style="margin: 20px;border:0; margin-top: 10px;" shadow="never">
       <el-form
         ref="queryFormRef"
         :inline="true"
@@ -61,7 +61,7 @@
         </el-form-item>
       </el-form>
     </el-card>
-    <el-card class="main-card" shadow="never" style="margin: 20px">
+    <el-card class="main-card" shadow="never" style="margin: 20px;border:0">
       <div class="card-toolbar mb8">
         <el-button
          
@@ -98,7 +98,7 @@
             :xl="6"
             style="margin-bottom: 30px; text-align: center"
           >
-            <el-card :body-style="{ padding: '20px' }" shadow="hover" class="card-item">
+            <el-card :body-style="{ padding: '20px' }" shadow="hover" class="card-item" style="border: 0;">
               <el-row type="flex" :gutter="10" justify="space-between">
                 <el-col :span="16" style="text-align: left">
                   <el-link
@@ -125,18 +125,18 @@
                     <b class="card-item__title" @click="handleDeviceDetail(item)">{{
                       item.productName
                     }}</b>
-                    <el-tag type="info">{{ item.tenantName }}</el-tag>
+                    <!-- <el-tag type="info">{{ item.tenantName }}</el-tag> -->
                   </el-link>
                 </el-col>
                 <el-col type="flex" :span="8">
                   <li
                     v-if="item.status == 2"
-                    class="table-status success"
+                    class="table-status text-[#67c23a]"
                     style="text-align: right"
                   >
                     <span class="status-content">已发布</span>
                   </li>
-                  <li v-else class="table-status" style="text-align: right">
+                  <li v-else class="table-status text-[#999999]" style="text-align: right">
                     <span class="status-content">未发布</span>
                   </li>
                 </el-col>
@@ -152,11 +152,11 @@
                       <el-link type="primary" :underline="false">{{ item.categoryName }}</el-link>
                     </el-descriptions-item>
                     <el-descriptions-item label="产品类型">
-                      <dict-tag :options="iot_device_type" :value="item.deviceType" />
+                      <dict-tag :type="DICT_TYPE.VIDEO_PRODUCT_TYPE" :value="item.deviceType" />
                     </el-descriptions-item>
                     <el-descriptions-item label="联网方式">
                       <dict-tag
-                        :options="iot_network_method"
+                        :type="DICT_TYPE.VIDEO_CENTER_NETWORK_METHOD"
                         :value="item.networkMethod"
                       />
                     </el-descriptions-item>
@@ -289,12 +289,12 @@
           <el-table-column label="所属分类" align="left" prop="categoryName" min-width="120" />
           <el-table-column label="所属类型" align="left" prop="deviceType" min-width="120">
             <template #default="{ row }">
-              <dict-tag :options="iot_device_type" :value="row.deviceType" />
+              <dict-tag :type="DICT_TYPE.VIDEO_PRODUCT_TYPE" :value="row.deviceType" />
             </template>
           </el-table-column>
           <el-table-column label="联网方式" align="left" prop="networkMethod" min-width="120">
             <template #default="{ row }">
-              <dict-tag :options="iot_network_method" :value="row.networkMethod" />
+              <dict-tag :type="DICT_TYPE.VIDEO_CENTER_NETWORK_METHOD" :value="row.networkMethod" />
             </template>
           </el-table-column>
           <el-table-column label="设备授权" align="center" prop="isAuthorize" min-width="120">
@@ -313,7 +313,7 @@
           </el-table-column>
           <el-table-column
             label="操作"
-            align="left"
+            align="center"
             class-name="small-padding fixed-width"
             fixed="right"
             width="300"
@@ -358,7 +358,8 @@
         </el-table>
       </template>
       <el-empty v-else description="暂无数据,请添加产品" />
-      <el-pagination
+     <div class="mt-5 flex justify-right">
+         <el-pagination
         v-show="total > 0"
         :total="total"
         v-model:current-page="queryParams.pageNum"
@@ -368,6 +369,7 @@
         @update:current-page="getList"
         @update:page-size="getList"
       />
+     </div>
 
      
     </el-card>
@@ -388,6 +390,7 @@ import productSvg from '@/assets/imgs/product.svg'
 import videoSvg from '@/assets/imgs/video.svg'
 import gatewaySvg from '@/assets/imgs/gateway.svg'
 import { getDicts } from '@/api/pms/video/dicts'
+import { DICT_TYPE } from '@/utils/dict'
 
 
 const { t } = useI18n() // 国际化
@@ -719,6 +722,8 @@ if (route.query.t) {
     .card-item__footer {
       margin-top: 1em;
       text-align: right;
+      display: flex;
+      justify-content: center;
 
       .el-button {
         background: #f5f7fa;

+ 2 - 2
src/views/pms/video_center/protocol/index.vue

@@ -1,6 +1,6 @@
 <template>
   <div style="padding: 6px">
-    <el-card v-show="showSearch" style="margin-bottom: 6px">
+    <el-card v-show="showSearch" style="margin-bottom: 6px;border: 0;" shadow="never">
       <el-form 
         ref="queryFormRef" 
         :inline="true" 
@@ -33,7 +33,7 @@
       </el-form>
     </el-card>
 
-    <el-card style="padding-bottom: 80px">
+    <el-card style="padding-bottom: 80px;border: 0;" shadow="never">
       <el-table 
         :border="false" 
         v-loading="loading" 

+ 3 - 3
src/views/pms/video_center/sip/channel.vue

@@ -62,7 +62,7 @@
       <el-table-column :label="t('sip.channel998532-5')" 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.VIDEO_DEVICE_STATUS" :value="scope.row.status" />
         </template>
       </el-table-column>
       <el-table-column
@@ -187,8 +187,8 @@ const getList = () => {
   loading.value = true
   listChannel(queryParams).then((response) => {
    
-    channelList.value = response
-    total.value = response.length
+    channelList.value = response.list
+    total.value = response.list.length
     loading.value = false
   })
 }

+ 4 - 4
src/views/pms/video_center/sip/components/player/DeviceTree.vue

@@ -1,6 +1,6 @@
 <template>
   <div id="DeviceTree" style="width: 100%; height: 100%; background-color: #ffffff; overflow: auto">
-    <div style="line-height: 3vh; margin-bottom: 10px; font-size: 17px;" class="pl-5 mt-5">设备列表</div>
+    <div style="line-height: 3vh; margin-bottom: 10px; font-size: 17px;" class="pl-5 mt-2">设备列表</div>
     <el-tree 
       ref="treeRef" 
       :props="defaultProps" 
@@ -149,7 +149,7 @@ const handleNodeClick = (data, node, element) => {
 const loadNode = (node, resolve) => {
   if (node.level === 0) {
     listDeviceShort(queryParams).then((response) => {
-      const data = response.rows
+      const data = response
       if (data.length > 0) {
         let nodeList = []
         for (let i = 0; i < data.length; i++) {
@@ -171,8 +171,8 @@ const loadNode = (node, resolve) => {
   } else {
     let channelArray = []
     listSipDeviceChannel(node.data.userData.serialNumber).then((res) => {
-      if (res.data != null) {
-        channelArray = channelArray.concat(res.data)
+      if (res != null) {
+        channelArray = channelArray.concat(res)
         channelDataHandler(channelArray, resolve)
       } else {
         resolve([])

+ 26 - 5
src/views/pms/video_center/sip/components/player/jessibuca.vue

@@ -62,6 +62,7 @@ onMounted(() => {
     // console.error(msg)
   }
   
+  // 确保DOM已经渲染完毕后再初始化播放器
   nextTick(() => {
     updatePlayerDomSize()
     window.onresize = () => {
@@ -71,7 +72,13 @@ onMounted(() => {
     let paramUrl = decodeURIComponent(route.params.url)
     let url = props.videoUrl !== undefined ? props.videoUrl : paramUrl
     console.log("初始化时的地址为: " + url)
-    play(url)
+    
+    // 确保容器已准备就绪
+    if (container.value) {
+      play(url)
+    } else {
+      console.error("Container element is not available")
+    }
   })
 })
 
@@ -88,7 +95,9 @@ onUnmounted(() => {
 watch(
   () => props.videoUrl,
   (newData, oldData) => {
-    play(newData)
+    if (container.value) {
+      play(newData)
+    }
   },
   { immediate: true }
 )
@@ -112,13 +121,19 @@ const updatePlayerDomSize = () => {
 }
 
 // 创建播放器实例
-const create = () => {
+function create() {
+  // 确保容器存在
+  if (!container.value) {
+    console.error("Cannot create player: container is not ready")
+    return
+  }
+  
   let options = {}
   const uid = route.params._uid || Date.now() // 使用时间戳作为唯一标识
   
   jessibucaPlayer[uid] = new window.JessibucaPro(Object.assign(
     {
-      container: container.value,
+      container: container.value, // 确保传递正确的容器元素
       autoWasm: true,
       background: "",
       controlAutoHide: false,
@@ -226,9 +241,15 @@ const create = () => {
 }
 
 // 播放视频
-const play = (url) => {
+function play(url){
   const uid = route.params._uid || Date.now()
   
+  // 确保容器已准备就绪
+  if (!container.value) {
+    console.error("Cannot play: container is not ready")
+    return
+  }
+  
   if (jessibucaPlayer[uid]) {
     destroy().then(() => {
       if (jessibucaPlayer[uid] && jessibucaPlayer[uid].hasLoaded()) {

+ 541 - 458
src/views/pms/video_center/sip/index.vue

@@ -1,164 +1,278 @@
 <template>
-    <div>
-        <el-card class="main-card">
-            <el-form :model="queryParams" ref="queryFormRef" :inline="true"  style="margin-bottom: -20px">
-                <el-form-item :label="t('sip.index998533-0')" prop="deviceSipId">
-                    <el-input v-model="queryParams.deviceSipId" :placeholder="t('sip.index998533-1')" clearable size="small" @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item :label="t('sip.index998533-2')" prop="channelSipId">
-                    <el-input v-model="queryParams.channelSipId" :placeholder="t('sip.index998533-3')" clearable size="small" @keyup.enter="handleQuery" />
-                </el-form-item>
-                <el-form-item :label="t('sip.index998533-4')" prop="status">
-                    <el-select v-model="queryParams.status" :placeholder="t('sip.index998533-5')" clearable size="small" style="width: 150px;">
-                        <el-option v-for="dict in my_dict.type.iot_device_status" :key="dict.value" :label="dict.label" :value="dict.value"  />
-                    </el-select>
-                </el-form-item>
-                <el-form-item>
-                    <el-button type="primary" :icon="Search" size="small" @click="handleQuery">{{ t('search') }}</el-button>
-                    <el-button :icon="Refresh" size="small" @click="resetQuery">{{ t('reset') }}</el-button>
-                </el-form-item>
-            </el-form>
-        </el-card>
-        <el-card class="main-card mt-5">
-            <div class="mb20">
-                <el-button type="primary" plain :icon="Plus" size="small" @click="handleAdd">
-                    添加
-                </el-button>
-                <el-button type="danger" plain :icon="Delete" size="small" :disabled="multiple || isGeneralUser"  @click="handleDelete">
-                   删除
-                </el-button>
-            </div>
-            <el-table v-loading="loading" :data="sipidList" @selection-change="handleSelectionChange" @cell-dblclick="celldblclick">
-                <el-table-column type="selection" :selectable="selectable" width="55" align="center" />
-                <el-table-column label="设备编号" align="center" prop="deviceSipId">
-                    <template #default="scope">
-                        <el-link :underline="false" type="primary" @click="handleViewDevice(scope.row.deviceSipId)">{{ scope.row.deviceSipId }}</el-link>
-                    </template>
-                </el-table-column>
-                <el-table-column :label="t('sip.index998533-2')" align="center" prop="channelSipId" />
-                <el-table-column :label="t('sip.index998533-4')" align="center" prop="status" width="80">
-                    <template #default="scope">
-                        <dict-tag :options="my_dict.type.iot_device_status" :value="scope.row.status" size="small" />
-                    </template>
-                </el-table-column>
-                <el-table-column :label="t('sip.index998533-8')" align="center" prop="productName" />
-                <el-table-column :label="t('sip.index998533-9')" align="center" prop="deviceType">
-                    <template #default="scope">
-                        <dict-tag :options="my_dict.type.video_type" :value="scope.row.deviceType" />
-                    </template>
-                </el-table-column>
-                <el-table-column :label="t('sip.index998533-15')" align="center" prop="channelType">
-                    <template #default="scope">
-                        <dict-tag :options="my_dict.type.channel_type" :value="scope.row.channelType" />
-                    </template>
-                </el-table-column>
-                <el-table-column :label="t('sip.index998533-10')" align="center" prop="citycode" />
-                <el-table-column :label="t('sip.index998533-11')" align="center" prop="registerTime" width="180">
-                    <template #default="scope">
-                        <span>{{ parseTime(scope.row.registerTime, '{y}-{m}-{d} {h}:{m}:{s}') }}</span>
-                    </template>
-                </el-table-column>
-                <el-table-column :label="t('opation')" align="center" class-name="small-padding fixed-width">
-                    <template #default="scope">
-                        <el-button size="small" type="primary" link :icon="Edit" @click="handleBinding(scope.row)">{{ t('sip.index998533-12') }}</el-button>
-                    </template>
-                </el-table-column>
-            </el-table>
-            <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
-        </el-card>
-
-        <el-dialog :title="title" v-model="open" width="450px" append-to-body>
-            <el-form :model="createForm"  ref="createFormRef">
-                <el-form-item :label="t('sip.index998533-13')">
-                    <el-cascader :options="cityOptions" v-model="createForm.city" @change="changeProvince" :props="{ checkStrictly: true }" />
-                </el-form-item>
-                <el-form-item :label="t('sip.index998533-9')" prop="deviceType">
-                    <el-select v-model="createForm.deviceType" :placeholder="t('sip.index998533-14')">
-                        <el-option v-for="dict in my_dict.type.video_type" :key="dict.value" :label="dict.label" :value="dict.value" />
-                    </el-select>
-                </el-form-item>
-                <el-form-item :label="t('sip.index998533-15')" prop="channelType">
-                    <el-select v-model="createForm.channelType" :placeholder="t('sip.index998533-16')">
-                        <el-option v-for="dict in my_dict.type.channel_type" :key="dict.value" :label="dict.label" :value="dict.value" />
-                    </el-select>
-                </el-form-item>
-                <el-form-item :label="t('sip.index998533-8')" prop="productName">
-                    <el-input readonly v-model="createForm.productName" :placeholder="t('sip.index998533-17')">
-                        <template #append>
-                            <el-button @click="selectProduct()">{{ t('sip.index998533-18') }}</el-button>
-                        </template>
-                    </el-input>
-                </el-form-item>
-                <el-form-item :label="t('sip.index998533-20')" prop="createNum">
-                    <el-input-number controls-position="right" v-model="createForm.createNum" :max="10" :placeholder="t('sip.index998533-19')" style="width: 330px" />
-                </el-form-item>
-            </el-form>
-            <template #footer>
-                <div class="dialog-footer">
-                    <el-button type="primary" @click="submitForm">{{ t('sip.index998533-21') }}</el-button>
-                    <el-button @click="cancel">{{ t('cancel') }}</el-button>
-                </div>
+  <div>
+    <el-card class="main-card" shadow="never" style="border: 0">
+      <el-form :model="queryParams" ref="queryFormRef" :inline="true" style="margin-bottom: -20px">
+        <el-form-item :label="t('sip.index998533-0')" prop="deviceSipId">
+          <el-input
+            v-model="queryParams.deviceSipId"
+            :placeholder="t('sip.index998533-1')"
+            clearable
+            size="small"
+            @keyup.enter="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item :label="t('sip.index998533-2')" prop="channelSipId">
+          <el-input
+            v-model="queryParams.channelSipId"
+            :placeholder="t('sip.index998533-3')"
+            clearable
+            size="small"
+            @keyup.enter="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item :label="t('sip.index998533-4')" prop="status">
+          <el-select
+            v-model="queryParams.status"
+            :placeholder="t('sip.index998533-5')"
+            clearable
+            size="small"
+            style="width: 150px"
+          >
+           <el-option
+              v-for="dict in getStrDictOptions(DICT_TYPE.VIDEO_DEVICE_STATUS)"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+
+           
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" :icon="Search" size="small" @click="handleQuery">搜素</el-button>
+          <el-button :icon="Refresh" size="small" @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+    <el-card class="main-card mt-5" shadow="never" style="border: 0">
+      <div class="mb-10">
+        <el-button type="primary" plain :icon="Plus" size="small" @click="handleAdd">
+          添加
+        </el-button>
+        <el-button
+          type="danger"
+          plain
+          :icon="Delete"
+          size="small"
+          :disabled="multiple || isGeneralUser"
+          @click="handleDelete"
+        >
+          删除
+        </el-button>
+      </div>
+      <el-table
+        v-loading="loading"
+        :data="sipidList"
+        @selection-change="handleSelectionChange"
+        @cell-dblclick="celldblclick"
+      >
+        <el-table-column type="selection" :selectable="selectable" width="55" align="center" />
+        <el-table-column label="设备编号" align="center" prop="deviceSipId">
+          <template #default="scope">
+            <el-link
+              :underline="false"
+              type="primary"
+              @click="handleViewDevice(scope.row.deviceSipId)"
+              >{{ scope.row.deviceSipId }}</el-link
+            >
+          </template>
+        </el-table-column>
+        <el-table-column :label="t('sip.index998533-2')" align="center" prop="channelSipId" />
+        <el-table-column :label="t('sip.index998533-4')" align="center" prop="status" width="80">
+          <template #default="scope">
+            <dict-tag
+              :type="DICT_TYPE.VIDEO_DEVICE_STATUS"
+              :value="scope.row.status"
+              size="small"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column :label="t('sip.index998533-8')" align="center" prop="productName" />
+        <el-table-column :label="t('sip.index998533-9')" align="center" prop="deviceType">
+          <template #default="scope">
+            <dict-tag :options="DICT_TYPE.VIDEO_TYPE" :value="scope.row.deviceType" />
+          </template>
+        </el-table-column>
+        <el-table-column :label="t('sip.index998533-15')" align="center" prop="channelType">
+          <template #default="scope">
+            <dict-tag :options="DICT_TYPE.CHANNEL_TYPE" :value="scope.row.channelType" />
+          </template>
+        </el-table-column>
+        <el-table-column :label="t('sip.index998533-10')" align="center" prop="citycode" />
+        <el-table-column
+          :label="t('sip.index998533-11')"
+          align="center"
+          prop="registerTime"
+          width="180"
+        >
+          <template #default="scope">
+            <span>{{ parseTime(scope.row.registerTime, '{y}-{m}-{d} {h}:{m}:{s}') }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="操作"
+          align="center"
+          class-name="small-padding fixed-width"
+        >
+          <template #default="scope">
+            <el-button
+              size="small"
+              type="primary"
+              link
+              :icon="Edit"
+              @click="handleBinding(scope.row)"
+              >{{ t('sip.index998533-12') }}</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination
+        v-show="total > 0"
+        :total="total"
+        v-model:page="queryParams.pageNum"
+        v-model:limit="queryParams.pageSize"
+        @pagination="getList"
+      />
+    </el-card>
+
+    <el-dialog :title="title" v-model="open" width="450px" append-to-body>
+      <el-form :model="createForm" ref="createFormRef">
+        <el-form-item :label="t('sip.index998533-13')">
+          <el-cascader
+            :options="cityOptions"
+            v-model="createForm.city"
+            @change="changeProvince"
+            :props="{ checkStrictly: true }"
+          />
+        </el-form-item>
+        <el-form-item :label="t('sip.index998533-9')" prop="deviceType">
+          <el-select v-model="createForm.deviceType" :placeholder="t('sip.index998533-14')">
+        
+            <el-option
+              v-for="dict in getStrDictOptions(DICT_TYPE.VIDEO_TYPE)"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="t('sip.index998533-15')" prop="channelType">
+          <el-select v-model="createForm.channelType" :placeholder="t('sip.index998533-16')">
+        
+
+            <el-option
+              v-for="dict in getStrDictOptions(DICT_TYPE.CHANNEL_TYPE)"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="t('sip.index998533-8')" prop="productName">
+          <el-input
+            readonly
+            v-model="createForm.productName"
+            :placeholder="t('sip.index998533-17')"
+          >
+            <template #append>
+              <el-button @click="selectProduct()">{{ t('sip.index998533-18') }}</el-button>
             </template>
-        </el-dialog>
-        <el-dialog :title="title" v-model="bindingOpen" width="450px" append-to-body>
-            <el-form :model="form" ref="formRef">
-                <el-form-item :label="t('sip.index998533-22')" prop="deviceId">
-                    <el-select style="width: 210px" v-model="form.reDeviceId" size="small" :placeholder="t('sip.index998533-23')" filterable @change="handleUpdateDeviceItem">
-                        <el-option v-for="(item, index) in deviceList" :key="index" :label="item.deviceName" :value="item.deviceId" />
-                    </el-select>
-                </el-form-item>
-                <el-form-item :label="t('sip.index998533-24')" prop="sceneId">
-                    <el-select style="width: 210px" v-model="form.reSceneModelId" size="small" :placeholder="t('sip.index998533-25')" filterable>
-                        <el-option v-for="(item, index) in sceneList" :key="index" :label="item.sceneModelName" :value="item.sceneModelId" />
-                    </el-select>
-                </el-form-item>
-            </el-form>
-            <template #footer>
-                <div class="dialog-footer">
-                    <el-button type="primary" @click="submitFormBinding">{{ t('confirm') }}</el-button>
-                    <el-button @click="cancelBinding">{{ t('cancel') }}</el-button>
-                </div>
-            </template>
-        </el-dialog>
-
-        <!-- 选择产品 -->
-        <product-list ref="productListRef" @product-event="getProductData" />
-    </div>
+          </el-input>
+        </el-form-item>
+        <el-form-item :label="t('sip.index998533-20')" prop="createNum">
+          <el-input-number
+            controls-position="right"
+            v-model="createForm.createNum"
+            :max="10"
+            :placeholder="t('sip.index998533-19')"
+            style="width: 330px"
+          />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">{{ t('sip.index998533-21') }}</el-button>
+          <el-button @click="cancel">取消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <el-dialog :title="title" v-model="bindingOpen" width="450px" append-to-body>
+      <el-form :model="form" ref="formRef">
+        <el-form-item :label="t('sip.index998533-22')" prop="deviceId">
+          <el-select
+            style="width: 210px"
+            v-model="form.reDeviceId"
+            size="small"
+            :placeholder="t('sip.index998533-23')"
+            filterable
+            @change="handleUpdateDeviceItem"
+          >
+            <el-option
+              v-for="(item, index) in deviceList"
+              :key="index"
+              :label="item.deviceName"
+              :value="item.deviceId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item :label="t('sip.index998533-24')" prop="sceneId">
+          <el-select
+            style="width: 210px"
+            v-model="form.reSceneModelId"
+            size="small"
+            :placeholder="t('sip.index998533-25')"
+            filterable
+          >
+            <el-option
+              v-for="(item, index) in sceneList"
+              :key="index"
+              :label="item.sceneModelName"
+              :value="item.sceneModelId"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitFormBinding">确定</el-button>
+          <el-button @click="cancelBinding">取消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 选择产品 -->
+    <product-list ref="productListRef" @product-event="getProductData" />
+  </div>
 </template>
 
-
-
 <script setup>
 import { ref, reactive, watch, onMounted } from 'vue'
 import { useRouter } from 'vue-router'
 import { useStore } from 'vuex'
 import { Search, Refresh, Plus, Delete, Edit } from '@element-plus/icons-vue'
-import { regionData } from 'element-china-area-data'
+import { regionData,codeToText } from 'element-china-area-data'
 import { listChannel, getChannel, delChannel, addChannel, binding } from '@/api/pms/video/channel'
 import { getDeviceBySerialNumber, listDeviceShort } from '@/api/pms/video/device'
 import { getSceneModelList } from '@/api/pms/video/list'
 import productList from './product-list.vue'
-
+import { DICT_TYPE, getDictLabel, getStrDictOptions } from '@/utils/dict'
 
 // 使用组合式API
 const router = useRouter()
 const store = useStore()
 const { t } = useI18n() // 国际化
 
-
-
 // 定义 props
 const props = defineProps({
-    product: {
-        type: Object,
-        default: null,
-    },
+  product: {
+    type: Object,
+    default: null
+  }
 })
 
 // 定义 emits
 const emit = defineEmits(['productEvent'])
 
-
 function parseTime(time, pattern) {
   if (arguments.length === 0 || !time) {
     return null
@@ -168,12 +282,15 @@ function parseTime(time, pattern) {
   if (typeof time === 'object') {
     date = time
   } else {
-    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
+    if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
       time = parseInt(time)
     } else if (typeof time === 'string') {
-      time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
+      time = time
+        .replace(new RegExp(/-/gm), '/')
+        .replace('T', ' ')
+        .replace(new RegExp(/\.[\d]{3}/gm), '')
     }
-    if ((typeof time === 'number') && (time.toString().length === 10)) {
+    if (typeof time === 'number' && time.toString().length === 10) {
       time = time * 1000
     }
     date = new Date(time)
@@ -190,7 +307,9 @@ function parseTime(time, pattern) {
   const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
     let value = formatObj[key]
     // Note: getDay() returns 0 on Sunday
-    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value] }
+    if (key === 'a') {
+      return ['日', '一', '二', '三', '四', '五', '六'][value]
+    }
     if (result.length > 0 && value < 10) {
       value = '0' + value
     }
@@ -205,15 +324,6 @@ const createFormRef = ref(null)
 const formRef = ref(null)
 const productListRef = ref(null)
 
-// 字典数据(需要根据实际项目情况调整)
-const my_dict = {
-    type: {
-        iot_device_status: [],
-        video_type: [],
-        channel_type: []
-    }
-}
-
 // 响应式数据
 const isGeneralUser = ref(true)
 const loading = ref(true)
@@ -231,116 +341,116 @@ const city = ref('')
 
 // 查询参数
 const queryParams = reactive({
-    pageNum: 1,
-    pageSize: 10,
-    deviceSipId: null,
-    deviceChannelId: null,
-    status: null,
+  pageNum: 1,
+  pageSize: 10,
+  deviceSipId: null,
+  deviceChannelId: null,
+  status: null
 })
 
 // 表单参数
 const createForm = reactive({
-    city: '',
-    deviceType: '',
-    channelType: '',
-    createNum: 1,
-    remark: '',
-    area: '',
-    productId: null,
-    productName: '',
-    tenantId: null,
-    tenantName: '',
-    citycode: ''
+  city: '',
+  deviceType: '',
+  channelType: '',
+  createNum: 1,
+  remark: '',
+  area: '',
+  productId: null,
+  productName: '',
+  tenantId: null,
+  tenantName: '',
+  citycode: ''
 })
 
 const form = reactive({})
 
 // 表单校验规则
 const rules = {
-    protocol: [
-        {
-            required: true,
-            message: t('sip.index998533-26'),
-            trigger: 'blur',
-        },
-    ],
-    ip: [
-        {
-            required: true,
-            message: t('sip.index998533-27'),
-            trigger: 'blur',
-        },
-    ],
-    domain: [
-        {
-            required: true,
-            message: t('sip.index998533-28'),
-            trigger: 'blur',
-        },
-    ],
-    secret: [
-        {
-            required: true,
-            message: t('sip.index998533-29'),
-            trigger: 'blur',
-        },
-    ],
-    portHttp: [
-        {
-            required: true,
-            message: t('sip.index998533-30'),
-            trigger: 'blur',
-        },
-    ],
-    portHttps: [
-        {
-            required: true,
-            message: t('sip.index998533-31'),
-            trigger: 'blur',
-        },
-    ],
-    portRtmp: [
-        {
-            required: true,
-            message: t('sip.index998533-32'),
-            trigger: 'blur',
-        },
-    ],
-    portRtsp: [
-        {
-            required: true,
-            message: t('sip.index998533-33'),
-            trigger: 'blur',
-        },
-    ],
-    rtpPortRange: [
-        {
-            required: true,
-            message: t('sip.index998533-34'),
-            trigger: 'blur',
-        },
-    ],
-    delFlag: [
-        {
-            required: true,
-            message: t('sip.index998533-35'),
-            trigger: 'blur',
-        },
-    ],
-    createBy: [
-        {
-            required: true,
-            message: t('sip.index998533-36'),
-            trigger: 'blur',
-        },
-    ],
-    createTime: [
-        {
-            required: true,
-            message: t('sip.index998533-37'),
-            trigger: 'blur',
-        },
-    ],
+  protocol: [
+    {
+      required: true,
+      message: t('sip.index998533-26'),
+      trigger: 'blur'
+    }
+  ],
+  ip: [
+    {
+      required: true,
+      message: t('sip.index998533-27'),
+      trigger: 'blur'
+    }
+  ],
+  domain: [
+    {
+      required: true,
+      message: t('sip.index998533-28'),
+      trigger: 'blur'
+    }
+  ],
+  secret: [
+    {
+      required: true,
+      message: t('sip.index998533-29'),
+      trigger: 'blur'
+    }
+  ],
+  portHttp: [
+    {
+      required: true,
+      message: t('sip.index998533-30'),
+      trigger: 'blur'
+    }
+  ],
+  portHttps: [
+    {
+      required: true,
+      message: t('sip.index998533-31'),
+      trigger: 'blur'
+    }
+  ],
+  portRtmp: [
+    {
+      required: true,
+      message: t('sip.index998533-32'),
+      trigger: 'blur'
+    }
+  ],
+  portRtsp: [
+    {
+      required: true,
+      message: t('sip.index998533-33'),
+      trigger: 'blur'
+    }
+  ],
+  rtpPortRange: [
+    {
+      required: true,
+      message: t('sip.index998533-34'),
+      trigger: 'blur'
+    }
+  ],
+  delFlag: [
+    {
+      required: true,
+      message: t('sip.index998533-35'),
+      trigger: 'blur'
+    }
+  ],
+  createBy: [
+    {
+      required: true,
+      message: t('sip.index998533-36'),
+      trigger: 'blur'
+    }
+  ],
+  createTime: [
+    {
+      required: true,
+      message: t('sip.index998533-37'),
+      trigger: 'blur'
+    }
+  ]
 }
 
 // 城市选项
@@ -348,330 +458,303 @@ const cityOptions = regionData
 
 // 监听 product prop 变化
 watch(
-    () => props.product,
-    (newVal, oldVal) => {
-        productInfo.value = newVal
-        if (productInfo.value && productInfo.value.productId != 0) {
-            queryParams.productId = productInfo.value.productId
-            // deviceParams.productId = productInfo.value.productId
-            getList()
-        }
+  () => props.product,
+  (newVal, oldVal) => {
+    productInfo.value = newVal
+    if (productInfo.value && productInfo.value.productId != 0) {
+      queryParams.productId = productInfo.value.productId
+      // deviceParams.productId = productInfo.value.productId
+      getList()
     }
+  }
 )
 
 // 查看设备操作
 const handleViewDevice = (serialNumber) => {
-    router.push({
-        path: '/iot/device',
-        query: {
-            t: Date.now(),
-            sn: serialNumber,
-        },
-    })
+  router.push({
+    path: '/videocenter/device',
+    query: {
+      t: Date.now(),
+      sn: serialNumber
+    }
+  })
 }
 
 // 选择产品
 const selectProduct = () => {
-    open.value = false
-    productListRef.value.open = true
-    productListRef.value.getList()
+  open.value = false
+  productListRef.value.open = true
+  productListRef.value.getList()
 }
 
 // 获取选中的产品
 const getProductData = (product) => {
-    open.value = true
-    createForm.productId = product.productId
-    createForm.productName = product.productName
-    createForm.tenantId = product.tenantId
-    createForm.tenantName = product.tenantName
+  open.value = true
+  createForm.productId = product.productId
+  createForm.productName = product.productName
+  createForm.tenantId = product.tenantId
+  createForm.tenantName = product.tenantName
 }
 
 // 行政区划改变
 const changeProvince = (data) => {
-    // if (data && data[0] != null && data[1] != null && data[2] != null) {
-    //     const str = CodeToText[data[0]] + '/' + CodeToText[data[1]] + '/' + CodeToText[data[2]]
-    //     createForm.citycode = str
-    // }
+  if (data && data[0] != null && data[1] != null && data[2] != null) {
+      const str = codeToText[data[0]] + '/' + codeToText[data[1]] + '/' + codeToText[data[2]]
+      createForm.citycode = str
+  }
 }
 
 // 获取设备详情
 const getDeviceBySerial = (serialNumber) => {
-    openDevice.value = true
-    getDeviceBySerialNumber(serialNumber).then((response) => {
-        // device.value = response.data
-    })
+  openDevice.value = true
+  getDeviceBySerialNumber(serialNumber).then((response) => {
+    // device.value = response.data
+  })
 }
 
 // 查询通道列表
 const getList = () => {
-    // listChannel(queryParams).then((response) => {
-    //     sipidList.value = response.rows
-    //     total.value = response.total
-    //     loading.value = false
-    // })
-
-    // 模拟数据
-    setTimeout(() => {
-        sipidList.value = [
-            {
-                id: 1,
-                deviceSipId: '31010000010010',
-                channelSipId: '31010000020010',
-                status: 1,
-                productName: '测试产品A',
-                deviceType: '摄像头',
-                channelType: '视频通道',
-                citycode: '上海/上海市/黄浦区',
-                registerTime: 1696118400000,
-            },
-            {
-                id: 2,
-                deviceSipId: '31010000010020',
-                channelSipId: '31010000020020',
-                status: 2,
-                productName: '测试产品B',
-                deviceType: '摄像头',
-                channelType: '视频通道',
-                citycode: '上海/上海市/徐汇区',
-                registerTime: 1696204800000,
-            },
-        ]
-        total.value = sipidList.value.length
-        loading.value = false
-    }, 500)
+  listChannel(queryParams).then((response) => {
+      sipidList.value = response.list
+      total.value = response.total
+      loading.value = false
+  })
 }
 
 // 取消按钮
 const cancel = () => {
-    open.value = false
-    reset()
+  open.value = false
+  reset()
 }
 
 // 表单重置
 const reset = () => {
-    Object.assign(createForm, {
-        id: null,
-        deviceSipId: null,
-        channelSipId: null,
-        status: 0,
-        registertime: null,
-        createBy: null,
-        createTime: null,
-        updateBy: null,
-        updateTime: null,
-        remark: null,
-        createNum: 1,
-    })
-    // resetForm('createForm')
+  Object.assign(createForm, {
+    id: null,
+    deviceSipId: null,
+    channelSipId: null,
+    status: 0,
+    registertime: null,
+    createBy: null,
+    createTime: null,
+    updateBy: null,
+    updateTime: null,
+    remark: null,
+    createNum: 1
+  })
+  // resetForm('createForm')
 }
 
 // 搜索按钮操作
 const handleQuery = () => {
-    loading.value = true
-    queryParams.pageNum = 1
-    getList()
+  loading.value = true
+  queryParams.pageNum = 1
+  getList()
 }
 
 // 重置按钮操作
 const resetQuery = () => {
-    // resetForm('queryForm')
-    handleQuery()
+  // resetForm('queryForm')
+  handleQuery()
 }
 
 // 多选框选中数据
 const handleSelectionChange = (selection) => {
-    ids.value = selection.map((item) => item.id)
-    multiple.value = !selection.length
+  ids.value = selection.map((item) => item.id)
+  multiple.value = !selection.length
 }
 
 // 批量新增按钮操作
 const handleAdd = () => {
-    reset()
-    open.value = true
-    title.value = t('sip.index998533-38')
+  reset()
+  open.value = true
+  title.value = t('sip.index998533-38')
 }
 
 // 修改按钮操作
 const handleUpdate = (row) => {
-    reset()
-    const id = row.id || ids.value
-    console.log(row)
-    getChannel(id).then((response) => {
-        Object.assign(createForm, response.data)
-        open.value = true
-        title.value = t('sip.index998533-39')
-    })
+  reset()
+  const id = row.id || ids.value
+  console.log(row)
+  getChannel(id).then((response) => {
+    Object.assign(createForm, response.data)
+    open.value = true
+    title.value = t('sip.index998533-39')
+  })
 }
 
 // 处理绑定
 const handleBinding = (row) => {
-    Object.assign(form, row)
-    bindingOpen.value = true
-    title.value = t('sip.index998533-40')
+  Object.assign(form, row)
+  bindingOpen.value = true
+  title.value = t('sip.index998533-40')
 }
 
 // 获取设备列表
 const getDeviceList = () => {
-    const params = {
-        showChild: true,
-        pageNum: 1,
-        pageSize: 9999,
+  const params = {
+    showChild: true,
+    pageNum: 1,
+    pageSize: 9999
+  }
+  listDeviceShort(params).then((res) => {
+    if (res.code === 200) {
+      deviceList.value = res.rows
+    } else {
+      // $message.error(res.msg)
     }
-    listDeviceShort(params).then((res) => {
-        if (res.code === 200) {
-            deviceList.value = res.rows
-        } else {
-            // $message.error(res.msg)
-        }
-    })
+  })
 }
 
 // 获取场景列表数据
 const getSceneListDatas = () => {
-    const params = {
-        pageNum: 1,
-        pageSize: 9999,
+  const params = {
+    pageNum: 1,
+    pageSize: 9999
+  }
+  getSceneModelList(params).then((res) => {
+    if (res.code === 200) {
+      sceneList.value = res.rows
+    } else {
+      // $message.error(res.msg)
     }
-    getSceneModelList(params).then((res) => {
-        if (res.code === 200) {
-            sceneList.value = res.rows
-        } else {
-            // $message.error(res.msg)
-        }
-    })
+  })
 }
 
 // 取消绑定
 const cancelBinding = () => {
-    bindingOpen.value = false
-    reset()
+  bindingOpen.value = false
+  reset()
 }
 
 // 确认绑定设备或场景
 const submitFormBinding = () => {
-    const data = {
-        channelId: form.channelSipId,
-        reDeviceId: form.reDeviceId,
-        reSceneModelId: form.reSceneModelId,
+  const data = {
+    channelId: form.channelSipId,
+    reDeviceId: form.reDeviceId,
+    reSceneModelId: form.reSceneModelId
+  }
+  binding(data).then((response) => {
+    if (response.code === 200) {
+      bindingOpen.value = false
+      ElMessage.success(t('sip.index998533-41'))
+    } else {
+      ElMessage.error('失败')
     }
-    binding(data).then((response) => {
-        if (response.code === 200) {
-            bindingOpen.value = false
-            // $message.success(t('sip.index.998533-41'))
-        } else {
-            // $message.error(response.msg)
-        }
-    })
+  })
 }
 
 // 提交按钮
 const submitForm = () => {
-    if (createForm.createNum < 1) {
-        // $modal.alertError(t('sip.index.998533-42'))
-        return
-    }
-    if (!createForm.productId || createForm.productId == 0) {
-        // $modal.alertError(t('sip.index.998533-43'))
-        return
-    }
-    createForm.deviceSipId = createForm.city[2] + '0000' + createForm.deviceType + '0'
-    createForm.channelSipId = createForm.city[2] + '0000' + createForm.channelType + '0'
-    if (createForm.deviceType !== '' && createForm.channelType !== '' && createForm.city.length === 3) {
-        console.log(createForm)
-        addChannel(createForm.createNum, createForm).then((response) => {
-            // $modal.msgSuccess(t('addSuccess'))
-            open.value = false
-            getList()
-        })
-    } else {
-        // $message({
-        //     type: 'error',
-        //     message: t('sip.index.998533-44'),
-        // })
-    }
+  if (createForm.createNum < 1) {
+    // $modal.alertError(t('sip.index.998533-42'))
+    return
+  }
+  if (!createForm.productId || createForm.productId == 0) {
+    // $modal.alertError(t('sip.index.998533-43'))
+    return
+  }
+  createForm.deviceSipId = createForm.city[2] + '0000' + createForm.deviceType + '0'
+  createForm.channelSipId = createForm.city[2] + '0000' + createForm.channelType + '0'
+  if (
+    createForm.deviceType !== '' &&
+    createForm.channelType !== '' &&
+    createForm.city.length === 3
+  ) {
+    console.log(createForm)
+    addChannel(createForm.createNum, createForm).then((response) => {
+      // $modal.msgSuccess(t('addSuccess'))
+      open.value = false
+      getList()
+    })
+  } else {
+    // $message({
+    //     type: 'error',
+    //     message: t('sip.index.998533-44'),
+    // })
+  }
 }
 
 // 删除按钮操作
 const handleDelete = (row) => {
-    const sipIds = row.id || ids.value
-    // $modal
-    //     .confirm(t('sip.index.998533-45') + sipIds + t('notify.channel.index.333541-18'))
-    //     .then(function() {
-    //         return delChannel(sipIds)
-    //     })
-    //     .then(() => {
-    //         getList()
-    //         // $modal.msgSuccess(t('delSuccess'))
-    //     })
-    //     .catch(() => {})
+  const sipIds = row.id || ids.value
+  // $modal
+  //     .confirm(t('sip.index.998533-45') + sipIds + t('notify.channel.index.333541-18'))
+  //     .then(function() {
+  //         return delChannel(sipIds)
+  //     })
+  //     .then(() => {
+  //         getList()
+  //         // $modal.msgSuccess(t('delSuccess'))
+  //     })
+  //     .catch(() => {})
 }
 
 // 禁用有绑定设备的复选框,status:1=未使用,2=已使用
 const selectable = (row) => {
-    if (row.status == 2 || isGeneralUser.value) {
-        return false
-    }
-    return true
+  if (row.status == 2 || isGeneralUser.value) {
+    return false
+  }
+  return true
 }
 
 // 表格增加复制功能
 const celldblclick = (row, column, cell, event) => {
-    // $copyText(row[column.property]).then(
-    //     (e) => {
-    //         onCopy()
-    //     },
-    //     function(e) {
-    //         onError()
-    //     }
-    // )
+  // $copyText(row[column.property]).then(
+  //     (e) => {
+  //         onCopy()
+  //     },
+  //     function(e) {
+  //         onError()
+  //     }
+  // )
 }
 
 // 复制成功
 const onCopy = () => {
-    // $notify({
-    //     title: t('success'),
-    //     message: t('sip.index.998533-46'),
-    //     type: 'success',
-    //     offset: 50,
-    //     duration: 2000,
-    // })
+  // $notify({
+  //     title: t('success'),
+  //     message: t('sip.index.998533-46'),
+  //     type: 'success',
+  //     offset: 50,
+  //     duration: 2000,
+  // })
 }
 
 // 复制失败
 const onError = () => {
-    // $notify({
-    //     title: t('fail'),
-    //     message: t('sip.index.998533-47'),
-    //     type: 'error',
-    //     offset: 50,
-    //     duration: 2000,
-    // })
+  // $notify({
+  //     title: t('fail'),
+  //     message: t('sip.index.998533-47'),
+  //     type: 'error',
+  //     offset: 50,
+  //     duration: 2000,
+  // })
 }
 
 // 处理更新设备项
 const handleUpdateDeviceItem = (value) => {
-    // 实现具体逻辑
+  // 实现具体逻辑
 }
 
 // 生命周期钩子
 onMounted(() => {
-    // 普通用户只能查看自己的通道
-    // if (store.state.user.roles.indexOf('general') === -1) {
-    //     isGeneralUser.value = false
-    // }
-    getList()
-    // getDeviceList()
-    // getSceneListDatas()
+  // 普通用户只能查看自己的通道
+  // if (store.state.user.roles.indexOf('general') === -1) {
+  //     isGeneralUser.value = false
+  // }
+  getList()
+  // getDeviceList()
+  // getSceneListDatas()
 })
 </script>
 
-
 <style scoped>
 .createNum {
-    width: 300px;
+  width: 300px;
 }
 
 .createNum input {
-    width: 260px;
+  width: 260px;
 }
-</style>
+</style>

+ 2 - 2
src/views/pms/video_center/sip/mediaServer.vue

@@ -1,7 +1,7 @@
 <template>
   <div id="mediaServer" class="iot-sip-mediaServer">
-    <el-card style="padding-bottom: 100px" v-loading="loading">
-      <div class="mb20">
+    <el-card style="padding-bottom: 100px;border: 0;" v-loading="loading" shadow="never">
+      <div class="mb-8">
         <el-button
           type="primary"
         

+ 12 - 8
src/views/pms/video_center/sip/product-list.vue

@@ -23,7 +23,7 @@
                 <el-table-column :label="t('sip.product-list998536-1')" align="center" prop="tenantName" />
                 <el-table-column :label="t('sip.product-list998536-2')" align="center" prop="networkMethod">
                     <template #default="scope">
-                        <dict-tag :options="dict.type.iot_network_method" :value="scope.row.networkMethod" />
+                        <dict-tag :options="DICT_TYPE.VIDEO_CENTER_NETWORK_METHOD" :value="scope.row.networkMethod" />
                     </template>
                 </el-table-column>
                 <el-table-column :label="t('sip.mediaServer998535-4')" align="center" prop="createTime" width="100">
@@ -36,9 +36,9 @@
             <pagination v-show="total > 0" v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNum" :total="total" @pagination="getList" />
         </div>
         <template #footer>
-            <div class="dialog-footer">
-                <el-button type="primary" @click="confirmSelectProduct">{{ t('confirm') }}</el-button>
-                <el-button @click="closeDialog">{{ t('close') }}</el-button>
+            <div class="dialog-footer mt-10 flex justify-end">
+                <el-button type="primary" @click="confirmSelectProduct">确认</el-button>
+                <el-button @click="closeDialog">关闭</el-button>
             </div>
         </template>
     </el-dialog>
@@ -48,6 +48,7 @@
 import { ref, reactive, onMounted } from 'vue'
 import { Search, Refresh } from '@element-plus/icons-vue'
 import { listProduct } from '@/api/pms/video/product'
+import { DICT_TYPE, getDictLabel, getIntDictOptions } from '@/utils/dict'
 
 
 function parseTime(time, pattern) {
@@ -133,10 +134,10 @@ const getList = () => {
     loading.value = true
     listProduct(queryParams).then((response) => {
         // 产品列表初始化isSelect值,用于单选
-        for (let i = 0; i < response.rows.length; i++) {
-            response.rows[i].isSelect = false
+        for (let i = 0; i < response.list.length; i++) {
+            response.list[i].isSelect = false
         }
-        productList.value = response.rows
+        productList.value = response.list
         total.value = response.total
         if (props.productId != 0) {
             setRadioSelected(props.productId)
@@ -206,6 +207,9 @@ onMounted(() => {
 
 // 暴露方法给父组件调用
 defineExpose({
-    open
+    open,
+    getList,
+   
+   
 })
 </script>

+ 202 - 164
src/views/pms/video_center/sip/splitview.vue

@@ -1,42 +1,84 @@
 <template>
-    <div style="height: 100%">
-        <el-card id="devicePosition" style="height: calc(100% - 40px)" :body-style="{ padding: '0px' }">
-            <el-container v-loading="loading" style="height: 100%" :element-loading-text="t('sip.splitview998531-0')">
-                <el-aside width="250px" style="background-color: #ffffff">
-                    <DeviceTree :click-event="clickEvent" />
-                </el-aside>
-                <el-main style="padding: 0">
-                    <div height="5vh" style="text-align: left; font-size: 17px; line-height: 5vh; margin-bottom: 10px">
-                        {{ t('sip.splitview998531-1') }}
-                        <el-button type="success" style="margin-left: 10px" :class="{ active: spilt == 1 }" @click="spilt = 1" :icon="FullScreen" plain size="small">
-                            {{ t('sip.splitview998531-2') }}
-                        </el-button>
-                        <el-button type="info" style="margin-left: 10px" :class="{ active: spilt == 4 }" @click="spilt = 4" :icon="Menu" plain size="small">
-                            {{ t('sip.splitview998531-3') }}
-                        </el-button>
-                        <el-button type="warning" style="margin-left: 10px" :class="{ active: spilt == 9 }" @click="spilt = 9" :icon="Grid" plain size="small">
-                            {{ t('sip.splitview998531-4') }}
-                        </el-button>
-                    </div>
-                    <div style="height: 85vh; display: flex; flex-wrap: wrap">
-                        <div v-for="i in spilt" :key="i" class="play-box" :style="liveStyle" :class="{ redborder: playerIdx == i - 1 }" @click="playerIdx = i - 1">
-                            <div v-if="!videoUrl[i - 1]" style="color: #ffffff; font-size: 30px; font-weight: bold">{{ i }}</div>
-                            <player 
-                                v-else 
-                                :ref="el => setPlayerRef(el, i-1)"
-                                :video-url="videoUrl[i - 1]" 
-                                fluent 
-                                autoplay 
-                                @screenshot="shot" 
-                                class="player-wrap" 
-                                @destroy="destroy" 
-                            />
-                        </div>
-                    </div>
-                </el-main>
-            </el-container>
-        </el-card>
-    </div>
+  <div style="height: 100%">
+    <el-card id="devicePosition" shadow="never" style="height: calc(100% - 40px);border: 0;" :body-style="{ padding: '0px' }" class="border-none">
+      <el-container
+        v-loading="loading"
+        style="height: 100%"
+        :element-loading-text="t('sip.splitview998531-0')"
+      >
+        <el-aside width="250px" style="background-color: #ffffff">
+          <DeviceTree :click-event="clickEvent" />
+        </el-aside>
+        <el-main style="padding: 0">
+          <div
+            height="5vh"
+            style="text-align: left; font-size: 17px; line-height: 5vh; margin-bottom: 10px"
+          >
+            {{ t('sip.splitview998531-1') }}
+            <el-button
+              type="success"
+              style="margin-left: 10px"
+              :class="{ active: spilt == 1 }"
+              @click="spilt = 1"
+              :icon="FullScreen"
+              plain
+              size="small"
+            >
+              {{ t('sip.splitview998531-2') }}
+            </el-button>
+            <el-button
+              type="info"
+              style="margin-left: 10px"
+              :class="{ active: spilt == 4 }"
+              @click="spilt = 4"
+              :icon="Menu"
+              plain
+              size="small"
+            >
+              {{ t('sip.splitview998531-3') }}
+            </el-button>
+            <el-button
+              type="warning"
+              style="margin-left: 10px"
+              :class="{ active: spilt == 9 }"
+              @click="spilt = 9"
+              :icon="Grid"
+              plain
+              size="small"
+            >
+              {{ t('sip.splitview998531-4') }}
+            </el-button>
+          </div>
+          <div style="height: 85vh; display: flex; flex-wrap: wrap">
+            <div
+              v-for="i in spilt"
+              :key="i"
+              class="play-box"
+              :style="liveStyle"
+              :class="{ redborder: playerIdx == i - 1 }"
+              @click="playerIdx = i - 1"
+            >
+              <div
+                v-if="!videoUrl[i - 1]"
+                style="color: #ffffff; font-size: 30px; font-weight: bold"
+                >{{ i }}</div
+              >
+              <player
+                v-else
+                :ref="(el) => setPlayerRef(el, i - 1)"
+                :video-url="videoUrl[i - 1]"
+                fluent
+                autoplay
+                @screenshot="shot"
+                class="player-wrap"
+                @destroy="destroy"
+              />
+            </div>
+          </div>
+        </el-main>
+      </el-container>
+    </el-card>
+  </div>
 </template>
 
 <script setup>
@@ -47,7 +89,7 @@ import player from './components/player/jessibuca.vue'
 import DeviceTree from './components/player/DeviceTree.vue'
 import { startPlay } from '@/api/pms/video/channel'
 
-const { t } = useI18n() 
+const { t } = useI18n()
 
 // 使用组合式API
 const route = useRoute()
@@ -66,204 +108,200 @@ const loading = ref(false)
 
 // 设置播放器引用
 const setPlayerRef = (el, index) => {
-    if (el) {
-        playerRefs.value[index] = el
-    }
+  if (el) {
+    playerRefs.value[index] = el
+  }
 }
 
 // 计算属性 - 直播样式
 const liveStyle = computed(() => {
-    let style = { width: '81%', height: '99%' }
-    switch (spilt.value) {
-        case 4:
-            style = { width: '40%', height: '49%' }
-            break
-        case 9:
-            style = { width: '27%', height: '32%' }
-            break
+  let style = { width: '81%', height: '99%' }
+  switch (spilt.value) {
+    case 4:
+      style = { width: '40%', height: '49%' }
+      break
+    case 9:
+      style = { width: '27%', height: '32%' }
+      break
+  }
+
+  nextTick(() => {
+    for (let i = 0; i < spilt.value; i++) {
+      const player = playerRefs.value[i]
+      if (player && typeof player.updatePlayerDomSize === 'function') {
+        player.updatePlayerDomSize()
+      }
     }
-    
-    nextTick(() => {
-        for (let i = 0; i < spilt.value; i++) {
-            const player = playerRefs.value[i]
-            if (player && typeof player.updatePlayerDomSize === 'function') {
-                player.updatePlayerDomSize()
-            }
-        }
-    })
-    
-    return style
+  })
+
+  return style
 })
 
 // 监听分屏变化
 watch(spilt, (newValue) => {
-    console.log('切换画幅;' + newValue)
-    for (let i = 1; i <= newValue; i++) {
-        const player = playerRefs.value[i-1]
-        if (player) {
-            nextTick(() => {
-                if (typeof player.resize === 'function') {
-                    player.resize()
-                }
-            })
+  for (let i = 1; i <= newValue; i++) {
+    const player = playerRefs.value[i - 1]
+    if (player) {
+      nextTick(() => {
+        if (typeof player.resize === 'function') {
+          player.resize()
         }
+      })
     }
-    window.localStorage.setItem('split', newValue.toString())
+  }
+  window.localStorage.setItem('split', newValue.toString())
 })
 
 // 监听路由变化
 watch(
-    () => route.fullPath,
-    () => {
-        checkPlayByParam()
-    }
+  () => route.fullPath,
+  () => {
+    checkPlayByParam()
+  }
 )
 
 // 生命周期钩子
 onMounted(() => {
-    checkPlayByParam()
+  checkPlayByParam()
 })
 
 onUnmounted(() => {
-    clearTimeout(updateLooper.value)
+  clearTimeout(updateLooper.value)
 })
 
 // 销毁事件
 const destroy = (idx) => {
-    console.log(idx)
-    clear(idx.substring(idx.length - 1))
+  console.log(idx)
+  clear(idx.substring(idx.length - 1))
 }
 
 // 点击事件
 const clickEvent = (data) => {
-    if (data.channelSipId) {
-        sendDevicePush(data)
-    }
+  if (data.channelSipId) {
+    sendDevicePush(data)
+  }
 }
 
 // 通知设备上传媒体流
 const sendDevicePush = (itemData) => {
-    save(itemData)
-    let deviceId = itemData.deviceSipId
-    let channelId = itemData.channelSipId
-    console.log('通知设备推流1:' + deviceId + ' : ' + channelId)
-    let idxTmp = playerIdx.value
-    loading.value = true
-    
-    startPlay(deviceId, channelId)
-        .then((response) => {
-            console.log('开始播放:' + deviceId + ' : ' + channelId)
-            console.log('流媒体信息:' + response.data)
-            let res = response.data
-            console.log('playurl:' + res.playurl)
-            console.log('protocol:' + window.location.protocol)
-            
-            if (window.location.protocol === 'http:') {
-                itemData.playUrl = res.ws_flv
-            } else {
-                itemData.playUrl = res.wss_flv
-            }
-            itemData.streamId = res.streamId
-            setPlayUrl(itemData.playUrl, idxTmp)
-        })
-        .finally(() => {
-            loading.value = false
-        })
+  save(itemData)
+  let deviceId = itemData.deviceSipId
+  let channelId = itemData.channelSipId
+
+  let idxTmp = playerIdx.value
+  loading.value = true
+
+  startPlay(deviceId, channelId)
+    .then((response) => {
+      let res = response
+
+      if (window.location.protocol === 'http:') {
+          itemData.playUrl = res.ws_flv
+        
+      } else {
+        itemData.playUrl = res.wss_flv
+      }
+      itemData.streamId = res.streamId
+      setPlayUrl(itemData.playUrl, idxTmp)
+    })
+    .finally(() => {
+      loading.value = false
+    })
 }
 
 // 设置播放URL
 const setPlayUrl = (url, idx) => {
-    const newVideoUrls = [...videoUrl.value]
-    newVideoUrls[idx] = url
-    videoUrl.value = newVideoUrls
-    
-    setTimeout(() => {
-        window.localStorage.setItem('videoUrl', JSON.stringify(videoUrl.value))
-    }, 100)
+  const newVideoUrls = [...videoUrl.value]
+  newVideoUrls[idx] = url
+  videoUrl.value = newVideoUrls
+
+  setTimeout(() => {
+    window.localStorage.setItem('videoUrl', JSON.stringify(videoUrl.value))
+  }, 100)
 }
 
 // 检查播放参数
 const checkPlayByParam = () => {
-    let { deviceId, channelId } = route.query
-    if (deviceId && channelId) {
-        sendDevicePush({ deviceId, channelId })
-    }
+  let { deviceId, channelId } = route.query
+  if (deviceId && channelId) {
+    sendDevicePush({ deviceId, channelId })
+  }
 }
 
 // 截图处理
 const shot = (e) => {
-    var base64ToBlob = function (code) {
-        let parts = code.split(';base64,')
-        let contentType = parts[0].split(':')[1]
-        let raw = window.atob(parts[1])
-        let rawLength = raw.length
-        let uInt8Array = new Uint8Array(rawLength)
-        for (let i = 0; i < rawLength; ++i) {
-            uInt8Array[i] = raw.charCodeAt(i)
-        }
-        return new Blob([uInt8Array], {
-            type: contentType,
-        })
+  var base64ToBlob = function (code) {
+    let parts = code.split(';base64,')
+    let contentType = parts[0].split(':')[1]
+    let raw = window.atob(parts[1])
+    let rawLength = raw.length
+    let uInt8Array = new Uint8Array(rawLength)
+    for (let i = 0; i < rawLength; ++i) {
+      uInt8Array[i] = raw.charCodeAt(i)
     }
-    
-    let aLink = document.createElement('a')
-    let blob = base64ToBlob(e)
-    let evt = document.createEvent('HTMLEvents')
-    evt.initEvent('click', true, true)
-    aLink.download = 't("sip.splitview.998531-5")' // 注意:这里需要使用正确的国际化处理
-    aLink.href = URL.createObjectURL(blob)
-    aLink.click()
+    return new Blob([uInt8Array], {
+      type: contentType
+    })
+  }
+
+  let aLink = document.createElement('a')
+  let blob = base64ToBlob(e)
+  let evt = document.createEvent('HTMLEvents')
+  evt.initEvent('click', true, true)
+  aLink.download = 't("sip.splitview998531-5")' 
+  aLink.href = URL.createObjectURL(blob)
+  aLink.click()
 }
 
 // 保存数据
 const save = (item) => {
-    let dataStr = window.localStorage.getItem('playData') || '[]'
-    let data = JSON.parse(dataStr)
-    data[playerIdx.value] = item
-    window.localStorage.setItem('playData', JSON.stringify(data))
+  let dataStr = window.localStorage.getItem('playData') || '[]'
+  let data = JSON.parse(dataStr)
+  data[playerIdx.value] = item
+  window.localStorage.setItem('playData', JSON.stringify(data))
 }
 
 // 清除数据
 const clear = (idx) => {
-    let dataStr = window.localStorage.getItem('playData') || '[]'
-    let data = JSON.parse(dataStr)
-    data[idx - 1] = null
-    console.log(data)
-    window.localStorage.setItem('playData', JSON.stringify(data))
+  let dataStr = window.localStorage.getItem('playData') || '[]'
+  let data = JSON.parse(dataStr)
+  data[idx - 1] = null
+  console.log(data)
+  window.localStorage.setItem('playData', JSON.stringify(data))
 }
 </script>
 
 <style scoped>
 .btn {
-    margin: 0 10px;
+  margin: 0 10px;
 }
 
 .btn:hover {
-    color: #409eff;
+  color: #409eff;
 }
 
 .btn.active {
-    color: #409eff;
+  color: #409eff;
 }
 
 .redborder {
-    border: 2px solid red !important;
+  border: 2px solid red !important;
 }
 
 .play-box {
-    background-color: #000000;
-    border: 1px solid #505050;
-    display: flex;
-    align-items: center;
-    justify-content: center;
-    margin-right: 10px;
-    position: relative;
-    border-radius: 5px;
+  background-color: #000000;
+  border: 1px solid #505050;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 10px;
+  position: relative;
+  border-radius: 5px;
 }
 
 .player-wrap {
-    position: absolute;
-    top: 0px;
-    height: 100% !important;
+  position: absolute;
+  top: 0px;
+  height: 100% !important;
 }
-</style>
+</style>

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.