Browse Source

视频监控更换插件

fangq 3 năm trước cách đây
mục cha
commit
9c90f9a064

+ 1 - 0
smart-city-grid-yinchuan-manage/public/index.html

@@ -26,6 +26,7 @@
   <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=cbb265e2a60bbbc04a52eec4eecdeb12&plugin=AMap.PolygonEditor,AMap.Driving"></script>
   <script src="https://webapi.amap.com/ui/1.1/main.js?v=1.0.11"></script>
   <script src="https://a.amap.com/jsapi_demos/static/demo-center/js/demoutils.js"></script>
+  <script src="./jessibuca.js"></script>
   <!-- <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" /> -->
   <!-- 在线图标库 -->
   <link rel="stylesheet" href="//at.alicdn.com/t/font_2204151_xo638r0axs.css" />

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
smart-city-grid-yinchuan-manage/public/jessibuca.js


+ 1 - 1
smart-city-grid-yinchuan-manage/src/page/login/index.vue

@@ -29,7 +29,7 @@
             <!--<a href="#"
                @click.stop="activeName='code'">{{ $t('login.phoneLogin') }}</a>-->
             <a href="#"
-               @click.stop="activeName='third'">{{ $t('login.thirdLogin') }}</a>
+               @click.stop="activeName='third'">天翼账号登陆</a>
           </div>
         </div>
 

+ 458 - 86
smart-city-grid-yinchuan-manage/src/views/smartapplication/videoSurveillance.vue

@@ -1,42 +1,118 @@
 <template>
-  <basic-container>
+  <div>
     <el-row>
-      <el-col span="2" align="right" style="font-size: large;" v-if="tenantType!=1">所属小区:</el-col>
-      <el-col span="2" align="right" style="font-size: large;" v-if="tenantType==1">所属区域:</el-col>
-      <el-col span="4" align="left">
-        <el-select size="small" v-model="selectResidential" filterable  clearable @change="residentialIdChange()">
-          <el-option v-for="item in residentialList" :key="item.id" :label="item.name" :value="item.id">
-          </el-option>
-        </el-select>
-
-      </el-col>
-
-      <el-col span="2" align="right" style="font-size: large;">所属楼栋:</el-col>
-      <el-col span="4" align="left">
-        <el-select size="small" v-model="selectBuilding" filterable placeholder="所属楼栋"  clearable>
-          <el-option v-for="item in buildingList" :key="item.id" :label="item.name" :value="item.id">
-          </el-option>
-        </el-select>
-
+      <basic-container>
+        <el-col span="2" align="right" style="font-size: large;" v-if="tenantType!=1">所属小区:</el-col>
+        <el-col span="2" align="right" style="font-size: large;" v-if="tenantType==1">所属区域:</el-col>
+        <el-col span="4" align="left">
+          <el-select size="small" v-model="selectResidential" filterable  clearable @change="residentialIdChange()">
+            <el-option v-for="item in residentialList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <el-col span="2" align="right" style="font-size: large;">所属楼栋:</el-col>
+        <el-col span="4" align="left">
+          <el-select size="small" v-model="selectBuilding" filterable placeholder="所属楼栋"  clearable>
+            <el-option v-for="item in buildingList" :key="item.id" :label="item.name" :value="item.id">
+            </el-option>
+          </el-select>
+        </el-col>
+        <!--<el-col span="2" align="right" style="font-size: large;">设备名称:</el-col>
+        <el-col span="4" align="left">
+          <el-input v-model="deviceName" size="mini" clearable></el-input>
+        </el-col>-->
+      </basic-container>
+    </el-row>
+    <el-row>
+      <!--<el-col :span="5">
+        <basic-container>
+          <avue-tree :option="treeOption" :data="treeData" @node-click="nodeClick">
+            <template slot-scope="scope" slot="menu">
+              <div class="avue-tree__item">自定义按钮</div>
+            </template>
+          </avue-tree>
+        </basic-container>
+      </el-col>-->
+      <el-col :span="5">
+        <basic-container>
+          <el-aside style="background-color: rgb(238, 241, 246)">
+            <el-tree :props="treeOption" :data="treeData" :expand-on-click-node="false" default-expand-all>
+                  <span class="custom-tree-node" slot-scope="{ node, data }">
+                    <span>{{ node.label }}</span>
+                    <span>
+                      <el-button
+                        type="text"
+                        size="mini"
+                        v-if="!data.isPlay"
+                        @click="() => playOne(data)">
+                        预览
+                      </el-button>
+                      <!--<el-button v-if="data.isPlay" style="color:red"
+                        type="text"
+                        size="mini"
+                        @click="() => stopOne(data)">
+                        停止
+                      </el-button>-->
+                      <!--<span v-if="data.isPlay === 2" style="color:red"
+                         type="text"
+                         size="mini">
+                        异常
+                      </span>-->
+                    </span>
+                  </span>
+            </el-tree>
+          </el-aside>
+        </basic-container>
       </el-col>
-      <el-col span="4" align="right" style="font-size: large;">设备名称:</el-col>
-      <el-col span="6" align="left">
-        <el-input v-model="deviceName" size="mini" clearable></el-input>
+      <el-col :span="19">
+        <basic-container>
+          <div>
+            <el-radio-group v-model="screen" size="mini">
+              <el-radio-button :label="1">单屏</el-radio-button>
+              <el-radio-button :label="4">四分屏</el-radio-button>
+              <el-radio-button :label="6">六分屏</el-radio-button>
+              <!--                <el-radio-button :label="9">九分屏</el-radio-button>-->
+              <!--                <el-radio-button :label="16">十六分屏</el-radio-button>-->
+              <el-radio-button :label="0">重置</el-radio-button>
+            </el-radio-group>
+          </div>
+          <div id="videoSurveillance" style="margin-top: 20px;">
+            <!--<div class="item1" v-for="(item,index) in data1" :key="index" v-if="screen == 1">
+              <div align="center">{{item.name}}</div>
+              <div class="container" :id="'videoId' + index" controls="true" width="100%" height="100%" muted>
+              </div>
 
+            </div>
+            <div class="item4" v-for="(item,index) in data4" :key="index" v-if="screen == 4">
+              <div align="center">{{item.name}}</div>
+              <div class="container" :id="'videoId' + index" controls="true" width="100%" height="100%" muted>
+              </div>
+            </div>-->
+            <div class="item6" v-for="index in screen" :key="index">
+              <div align="center">{{data6[index-1].name}}</div>
+              <div class="container" :id="'videoId' + (index-1)" controls="true" width="100%" height="100%" muted>
+              </div>
+            </div>
+            <!--              <div class="item9" v-for="(item,index) in data9" :key="index" v-if="screen == 9">-->
+            <!--                <div align="center">{{item.name}}</div>-->
+            <!--                <video :id="'videoId' + index" controls="true" width="100%" height="100%">-->
+            <!--                </video>-->
+            <!--              </div>-->
+            <!--              <div class="item16" v-for="(item,index) in data16" :key="index" v-if="screen == 16">-->
+            <!--                <div align="center">{{item.name}}</div>-->
+            <!--                <video :id="'videoId' + index" controls="true" width="100%" height="100%">-->
+            <!--                </video>-->
+            <!--              </div>-->
+          </div>
+        </basic-container>
       </el-col>
     </el-row>
-    <div id="videoSurveillance" style="margin-top: 20px;">
-      <div class="item" v-for="(item,index) in data" :key="index">
-        <div align="center">{{item.name}}</div>
-        <video :id="'videoId'+index" controls="true" width="100%" height="100%">
-        </video>
-      </div>
-    </div>
-  </basic-container>
+  </div>
 </template>
 
 
 <script>
+  import axios from 'axios';
   import {
     getList
   } from "@/api/community/building"
@@ -52,27 +128,48 @@
   import {
     mapGetters
   } from "vuex";
+  import {getDeptTree, getDeptLazyTree} from "@/api/system/dept";
+  import {getVideoUrl, stopPlay, play, stop} from "../../api/smartapplication/videoclouddevice";
   export default {
     data() {
       return {
+        screen:1,
+        treeData: [],
+        treeOption:{
+          label: 'deviceName',
+          value: "deviceNum",
+        },
         selectBuilding: "",
-        buildingList:[],
+        buildingList: [],
         tenantType: "",
         deviceName: "",
         selectResidential: "",
         loading: false,
         residentialList: [],
         value: [],
-        baseUrlVedio: "https://stream.nxzhsq.cn:18866/live?url=",
-        data: []
+        baseUrlVideo: "wss://stream.nxzhsq.cn:4433/live/",
+        /*videoUrls: [
+          "http://218.95.222.35:6004/ffcs/l_496eb2ec86ae6fe0df8bae80f4a6dfdc.flv",
+          "http://218.95.222.35:6004/ffcs/l_40b9785eb77d07d0e6116500b410543d.flv",
+          "http://218.95.222.35:6004/ffcs/l_38ead8964fb226cf7baac8e651c47e1d.flv",
+          "http://218.95.222.35:6004/ffcs/l_96394b46d0e0b6001f7a25798e3fde99.flv",
+          "http://218.95.222.35:6004/ffcs/l_2ee052454eea010ce317a68b74cb2855.flv",
+          "http://218.95.222.35:6004/ffcs/l_4b5591c690dae718f2ef9e52ea5a3163.flv"
+          ],*/
+        data:[],
+        data1: [{name:"", isPlay:false, index: 0}],
+        data4: [{name:"", isPlay:false, index: 0},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false}],
+        data6: [{name:"", isPlay:false, index: 0},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false}],
+        // data9: [{name:"", isPlay:false, index: 0},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false}],
+        // data16: [{name:"", isPlay:false, index: 0},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false}
+        //         ,{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false},{name:"", isPlay:false}],
       }
     },
-    computed:{
+    computed: {
       ...mapGetters(["userInfo"])
     },
     mounted() {
       getTenantTypeDetailByTenantId(this.userInfo.tenant_id).then(res => {
-
         if (res.data.data.tenantType == 1) {
           this.tenantType = 1;
         }
@@ -80,77 +177,308 @@
       //  请求获取小区列表
       getAllList().then(res => {
         this.residentialList = res.data.data;
-
       })
-      this.onLoad()
+      this.onLoad();
+      this.changeVideoWH();
     },
-    watch:{
-      "selectResidential":function(){
-        this.onLoad()
+    watch: {
+      "selectResidential": function () {
+        this.loadVideoDeviceList()
       },
-      "selectBuilding":function(){
-        this.onLoad()
+      "selectBuilding": function () {
+        this.loadVideoDeviceList()
       },
-      "deviceName":function(){
-        this.onLoad()
-      }
+      "deviceName": function () {
+        this.loadVideoDeviceList()
+      },
+      "screen": function (newV, oldV) {
+        let it = this;
+        if (newV < oldV){
+          for (let i = 0; i < oldV; i++) {
+            if (i >= newV){
+              let one = it.data6[i];
+              one.isPlay = false;
+              one.name = '';
+              if (one.jessibuca){
+                one.jessibuca.destroy();
+              }
+            }
+          }
+        }
+        setTimeout(function () {
+          it.changeVideoWH()
+        }, 500)
+
+      },
+    },
+    unmounted() {
+      this.data6.forEach(item => {
+        if (item.jessibuca) {
+          item.jessibuca.destroy();
+        }
+      })
     },
     methods: {
+      changeVideoWH(){
+        let num = this.screen > 1 ? this.screen / 2 : this.screen;
+        let panelW = document.querySelector('#videoSurveillance').clientWidth;
+        let videoW = (panelW - num * 20) / num;
+        let videoH = videoW / 1.8;
+        let arr = document.querySelectorAll('.container');
+        for (let i = 0; i < arr.length; i++) {
+          let vitem = arr[i];
+          vitem.style.width = videoW + 'px';
+          vitem.style.height = videoH + 'px';
+        }
+      },
       play() {
-        this.data.map((item, index) => {
-          try {
-            let videoElement = document.getElementById('videoId' + index);
-            let flvPlayer = flvjs.createPlayer({
-              type: 'flv',
-              url: item.src
-            });
-            flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
-              // errType是 NetworkError时,对应errDetail有:Exception、HttpStatusCodeInvalid、ConnectingTimeout、EarlyEof、UnrecoverableEarlyEof
-              // errType是 MediaError时,对应errDetail是MediaMSEError
-            });
-            flvPlayer.on(flvjs.Events.MEDIA_SOURCE_CLOSE || flvjs.Events.MEDIA_SOURCE_ENDED, () => {})
-            flvPlayer.attachMediaElement(videoElement);
-            flvPlayer.load();
-            flvPlayer.play();
-          } catch (e) {
-            console.log(e);
-          }
-
-        })
+        if(this.screen === 1){
+          this.data1.map((item, index) => {
+            try {
+              let videoElement = document.getElementById(item.deviceNum);
+              if(videoElement){
+                let flvPlayer = flvjs.createPlayer({
+                  type: 'flv',
+                  url: item.rtspUrl
+                });
+                flvPlayer.on(flvjs.Events.ERROR, (errType, errDetail) => {
+                  // errType是 NetworkError时,对应errDetail有:Exception、HttpStatusCodeInvalid、ConnectingTimeout、EarlyEof、UnrecoverableEarlyEof
+                  // errType是 MediaError时,对应errDetail是MediaMSEError
+                });
+                flvPlayer.on(flvjs.Events.MEDIA_SOURCE_CLOSE || flvjs.Events.MEDIA_SOURCE_ENDED, () => {});
+                flvPlayer.attachMediaElement(videoElement);
+                flvPlayer.load();
+                flvPlayer.play();
+              }
+            } catch (e) {
+              console.log(e);
+            }
+          })
+        }
       },
-      residentialIdChange(params={}){
+      residentialIdChange(params = {}) {
         params.residentialId = this.selectResidential;
-        getList(1,500,params).then((res)=>{
+        getList(1, 500, params).then((res) => {
           this.selectBuilding = "",
-          this.buildingList = res.data.data.records;
+            this.buildingList = res.data.data.records;
         })
       },
+      syncVideoUrl(accountName, deviceNum) {
+        getVideoUrl(accountName, deviceNum, "1").then(res => {
+          this.$message({
+            type: "success",
+            message: res.data.msg
+          });
+          this.onLoad();
+        })
+      },
+      loadVideoDeviceList(){
+        let that = this;
+        if (this.value && (this.selectResidential != "" || this.selectBuilding != "" || this.deviceName != "")) {
+          getByResidentialAndDeviceName(this.selectResidential, this.selectBuilding, this.deviceName).then(res =>{
+            const data = res.data.data;
+            data.forEach(item =>{
+              let obj = {};
+              obj.deviceName = item.deviceName;
+              obj.deviceNum = item.deviceNum;
+              obj.rtspUrl = item.rtspUrl;
+              obj.isOnline = item.isOnline;
+              obj.accountName = item.accountName;
+              obj.isPlay = false;
+              that.treeData.push(obj);
+            })
+          });
+        }
+      },
+      getUrlAndPlay(obj,item,index){
+        getVideoUrl(obj.accountName, obj.deviceNum).then(res => {
+          if (obj.isOnline === 1 && res.data.data) {
+            let videoUrl = res.data.data;
+            // let videoUrl = this.videoUrls[Math.ceil(Math.random()*5) - 1];
+            item.videoUrl = videoUrl;
+            try {
+              let videoElement = document.getElementById("videoId" + index);
+              let flvPlayer = this.createJessibuca({}, videoElement)
+              flvPlayer.play(videoUrl);
+              flvPlayer.mute();
+              item.jessibuca = flvPlayer;
+              item.isPlay = true;
+              item.name = obj.deviceName;
+            } catch (e) {
+              console.log(e);
+            }
+          }
+        });
+      },
+      playVideo(item){
+        item.jessibuca.play(item.videoUrl);
+        item.isPlay = true;
+      },
+      stopVideo(item){
+        item.jessibuca.pause();
+        item.playing = false;
+        item.isPlay = false;
+      },
+      playOne(obj) {
+        for (let i = 0; i < this.screen; i++) {
+          let item = this.data6[i];
+          if (!item.isPlay){
+            this.getUrlAndPlay(obj,item,i);
+            break
+          }
+        }
+      },
       onLoad() {
+        this.play();
         let _this = this;
-        if (this.value&&(this.selectResidential != ""||this.selectBuilding != "" || this.deviceName !="")) {
-          getByResidentialAndDeviceName(this.selectResidential,this.selectBuilding,this.deviceName).then(res => {
+        if (this.value && (this.selectResidential != "" || this.selectBuilding != "" || this.deviceName != "")) {
+          getByResidentialAndDeviceName(this.selectResidential, this.selectBuilding, this.deviceName).then(res => {
             if (res.data.code == 200) {
               this.data = [];
               const data = res.data.data;
               data.forEach(item => {
-                if(item.isOnline == 1 && item.rtspUrl){
-                  let obj = {};
-                  obj.src = this.baseUrlVedio + item.rtspUrl + "&&&ffmpeg=true";
-                  obj.name = item.deviceName;
-                  this.data.push(obj);
-                }
-              })
-              // _this.play();
-              setTimeout(function() {
-                _this.play();
-              }, 1000)
+                getVideoUrl(item.accountName, item.deviceNum, "1").then(res => {
+                  if (item.isOnline === 1 && res.data.data) {
+                    let obj = {};
+                    obj.src = _this.baseUrlVideo + res.data.data;
+                    obj.name = item.deviceName;
+                    obj.deviceNum = item.deviceNum;
+                    _this.data.push(obj);
+                    setTimeout(function() {
+                      _this.playOne(obj);
+                    }, 1000)
+                  }
+                });
+              });
             }
-
           });
-        }else{
-          this.data = [];
+        } else {
+          _this.data = [];
         }
-      }
+      },
+      createJessibuca(options, element) {
+        options = options || {};
+        let jessibuca = new window.Jessibuca(
+          Object.assign(
+            {
+              container: element,
+              videoBuffer: 0.2, // 缓存时长
+              isResize: false,
+              useWCS: false,
+              useMSE: true,
+              // background: "bg.jpg",
+              loadingText: "疯狂加载中...",
+              // hasAudio:false,
+              debug: false,
+              supportDblclickFullscreen: false,
+              showBandwidth: false, // 显示网速
+              operateBtns: {
+                fullscreen: true,
+                screenshot: false,
+                play: true,
+                audio: false,
+              },
+              vod: false,
+              forceNoOffscreen: true,
+              isNotMute: false,
+              timeout: 10
+            },
+            options
+          )
+        );
+        var _this = this;
+        jessibuca.on("load", function () {
+          // console.log("on load");
+        });
+
+        jessibuca.on("log", function (msg) {
+          // console.log("on log", msg);
+        });
+        jessibuca.on("record", function (msg) {
+          // console.log("on record:", msg);
+        });
+        jessibuca.on("pause", function () {
+          // console.log("on pause");
+          _this.playing = false;
+        });
+        jessibuca.on("play", function () {
+          // console.log("on play");
+          _this.playing = true;
+        });
+        jessibuca.on("fullscreen", function (msg) {
+          // console.log("on fullscreen", msg);
+        });
+
+        jessibuca.on("mute", function (msg) {
+          // console.log("on mute", msg);
+          _this.quieting = msg;
+        });
+
+        jessibuca.on("mute", function (msg) {
+          // console.log("on mute2", msg);
+        });
+
+        jessibuca.on("audioInfo", function (msg) {
+          // console.log("audioInfo", msg);
+        });
+
+        // this.jessibuca.on("bps", function (bps) {
+        //   // console.log('bps', bps);
+        // });
+        // let _ts = 0;
+        // this.jessibuca.on("timeUpdate", function (ts) {
+        //     console.log('timeUpdate,old,new,timestamp', _ts, ts, ts - _ts);
+        //     _ts = ts;
+        // });
+
+        jessibuca.on("videoInfo", function (info) {
+          // console.log("videoInfo", info);
+        });
+
+        jessibuca.on("error", function (error) {
+          console.log("error", error);
+        });
+
+        jessibuca.on("timeout", function () {
+          console.log("timeout");
+        });
+
+        jessibuca.on('start', function () {
+          // console.log('frame start');
+        })
+
+        jessibuca.on("performance", function (performance) {
+          var show = "卡顿";
+          if (performance === 2) {
+            show = "非常流畅";
+          } else if (performance === 1) {
+            show = "流畅";
+          }
+          _this.performance = show;
+        });
+        jessibuca.on('buffer', function (buffer) {
+          // console.log('buffer', buffer);
+        })
+
+        jessibuca.on('stats', function (stats) {
+          // console.log('stats', stats);
+        })
+
+        jessibuca.on('kBps', function (kBps) {
+          // console.log('kBps', kBps);
+        });
+
+        jessibuca.on("play", () => {
+          // this.playing = true;
+          // this.loaded = true;
+          // this.quieting = jessibuca.isMute();
+        });
+
+        jessibuca.on('recordingTimestamp', (ts) => {
+          // console.log('recordingTimestamp', ts);
+        })
+        return jessibuca;
+      },
     }
   }
 </script>
@@ -164,11 +492,55 @@
     flex-wrap: wrap;
     box-sizing: border-box;
 
-    .item {
-      width: calc(~"25% - 10px");
+    .item1 {
+      /*width: calc(~"100%");*/
+      overflow: hidden;
+      border-radius: 5px;
+      margin: 5px;
+    }
+    .item4 {
+      /*width: calc(~"40%");*/
+      overflow: hidden;
+      border-radius: 5px;
+      margin: 5px;
+    }
+    .item6 {
+      /*width: calc(~"30%");*/
+      overflow: hidden;
+      border-radius: 5px;
+      margin: 5px;
+    }
+    .item9 {
+      /*width: calc(~"30%");*/
       overflow: hidden;
       border-radius: 5px;
       margin: 5px;
     }
+    .item16 {
+      /*width: calc(~"24%");*/
+      overflow: hidden;
+      border-radius: 5px;
+      margin: 5px;
+    }
+  }
+  .custom-tree-node {
+    flex: 1;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    font-size: 14px;
+    padding-right: 8px;
+  }
+
+  .container {
+    background: rgba(13, 14, 27, 0.7);
+    width: 640px;
+    height: 398px;
+  }
+  @media (max-width: 720px) {
+    .container {
+      width: 90vw;
+      height: 52.7vw;
+    }
   }
 </style>

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác