ebc

index.vue 12KB

    <template> <div class="page-main"> <t-button-group class="top-btn"> <t-button v-for="(item,index) in sceneList" :key="index" :value="item.monitorSceneId" :color="item.monitorSceneId === selectedMonitorScene ? 'primary' : 'secondary'" @click="tabClick(item.monitorSceneId)"> {{ item.monitorSceneName }} </t-button> </t-button-group> <div class="page-top"> <span>风场:</span> <t-select v-model="gateFieldData" clearable @change="getSceneList()"> <t-option v-for="(item,index) in organizationList" :key="index" :value="item.id">{{ item.name }}</t-option> </t-select> </div> <div class="page-bottom grid-demo"> <t-col v-for="(item,index) in videoList" :span="viewLayoutSpan" :key="index" :value="item.resourceToolId" style="margin-top:24px"> <video-player :ref="'video'+index" :options="videoOptions[index]" :playsinline="false" :events="events" class="vjs-custom-skin videoPlayer" @dblclick="handlefullscreenchange" ></video-player> </t-col> <!-- <rtmp-video :list="getVideoPlayList(item)" @goDistinguishRecord="goDistinguishRecord(item.resourceToolId)" @videoReplay="handleReview"></rtmp-video> --> </div> <t-pager :page-size="videoPageSize" :current="videoCurrent" :total="videoTotal" :sizer-range="[ 1, 4, 9, 16 ]" class="pager" show-elevator @on-change="onChangeGate"></t-pager> <replay-dialog :list="replayList" :visibled.sync="showReplayDialog" @get-list="queryMonitorVideoLog" /> </div> </template> <script> import sysapi from '@/api/videoSurveillance' import RtmpVideo from './components/rtmpVideoPlay' import ReplayDialog from './components/ReplayDialog' import formatDateTime from '@/utils/formatDateTime.js' import videojs from 'video.js' window.videojs = videojs require('video.js/dist/lang/zh-CN.js') require('video.js/dist/video-js.min.css') export default { components: { ReplayDialog, RtmpVideo }, filters: { handleText (value) { if (!value) return '' if (value.length > 13) { return value.slice(0, 13) + '...' } return value } }, data () { return { viewLayoutSpan: 3, events: ['fullscreenchange'], videoOptions: [], videoCurrent: 1, // 大门分页数据 videoPageSize: 10, // 大门分页数据 videoTotal: 0, // 大门分页总数 tabId: 1, paramsObj: { // 接口请求数据 page: 0, limit: 10 }, organizationList: [], // 风场数据 gateFieldData: '', videoList: [], // 场景数据列表 sceneList: [], // 场景列表 selectedMonitorScene: '', // 当前选择场景 videoPlayList: [], showReplayDialog: false, replayList: '', beginDay: formatDateTime(new Date(+new Date() - 10 * 60 * 1000), 'yyyy-MM-dd hh:mm:ss'), endDay: formatDateTime(new Date(), 'yyyy-MM-dd hh:mm:ss') // beginDay: '2020-12-19 20:14:00', // endDay: '2020-12-19 20:14:00' } }, computed: { player() { return this.$refs.videoPlayer1.player } }, mounted () { this.getWindFiledList() // 获取风场列表 }, methods: { // 修改视频组件控制栏的元素以及样式 async createMyButton () { this.$nextTick(() => { const bars = document.querySelectorAll('.vjs-control-bar') let time = document.getElementsByClassName('vjs-current-time vjs-time-control vjs-control') let start = document.getElementsByClassName('vjs-play-control vjs-control vjs-button') let volume = document.getElementsByClassName('vjs-volume-panel vjs-control vjs-volume-panel-horizontal') let text = document.getElementsByClassName('vjs-live-control vjs-control') bars.forEach((item, index) => { time.forEach(item => { item.remove() }) start.forEach(item => { item.remove() }) volume.forEach(item => { item.remove() }) text.forEach(item => { item.remove() }) let txt = document.createElement('span') txt.innerHTML = '集控室(人脸识别)' txt.style.marginLeft = '12px' let btn = document.createElement('button') btn.style.color = 'white' btn.style.cursor = 'pointer' btn.style.marginLeft = 'auto' btn.className = 'aidicon aidicon-image-outline' btn.setAttribute('title', '识别记录') btn.addEventListener('click', () => { this.goDistinguishRecord() }) let btn1 = document.createElement('button') btn1.style.color = 'white' btn1.style.cursor = 'pointer' btn1.className = 'aidicon aidicon-piechart-outline' btn1.setAttribute('title', '视频回放') btn1.addEventListener('click', () => { this.handleReview(this.videoList[index].resourceToolId) }) item.appendChild(txt) item.appendChild(btn) item.appendChild(btn1) }) }) }, // 获取场景列表 getSceneList () { this.sceneList = [] this.videoList = [] this.organizationList.forEach((element, index) => { if (element.id === this.gateFieldData) { sysapi.getMonitorScene(this.organizationList[index].id).then((resp) => { this.sceneList = resp.data.data || [] if (resp.data.data[0].monitorViewLayout === '1X1') { this.viewLayoutSpan = 10 this.videoPageSize = 1 } else if (resp.data.data[0].monitorViewLayout === '2X2') { this.viewLayoutSpan = 6 this.videoPageSize = 4 } else if (resp.data.data[0].monitorViewLayout === '3X3') { this.viewLayoutSpan = 4 this.videoPageSize = 9 } else if (resp.data.data[0].monitorViewLayout === '4X4') { this.viewLayoutSpan = 3 this.videoPageSize = 16 } this.tabClick(this.sceneList[0].monitorSceneId) }) } }) }, // 向服务器发送请求获取视频回放数据 async queryMonitorVideoLog (data) { let res = [] if (data) { res = await sysapi.queryMonitorVideoLog({ params: { id: this.replayId, ...data } }) } else { res = await sysapi.queryMonitorVideoLog({ params: { id: this.replayId, beginDay: this.beginDay, endDay: this.endDay } }) } if (res.status === 200) { this.replayList = res.data.data } else { this.$Message.danger('视频列表数据获取失败!') } }, // 显示视频回放对话框 handleReview (id) { this.replayId = id this.queryMonitorVideoLog() this.showReplayDialog = true }, // 切换场景 async tabClick (id) { this.selectedMonitorScene = id this.paramsObj.page = 0 this.videoList = [] this.tabId = id this.videoCurrent = 1 this.getVideoSurveillanceData() }, // 获取风场下拉框列表 async getWindFiledList () { sysapi.getDepartments().then(resp => { this.organizationList = resp.data.data this.gateFieldData = this.organizationList[0].id this.getSceneList() }, err => { this.$Message.danger('获取风场列表失败!') console.log(err) }) }, handlefullscreenchange(val) { // 因为我是又封装了一个组件,打印val会有相应所需的属性,全屏状态为:isFullscreen_ val.isFullscreen_ = !val.isFullscreen_ // this.$emit('fullscreenchange', val) }, // 获得风场大门数据 getVideoSurveillanceData () { var id = this.tabId this.paramsObj.page = this.videoCurrent sysapi.getVideoSurveillanceData({ params: { monitorSceneId: id } }).then(res => { this.videoList = res.data.data for (let i in res.data.data) { let obj = { autoplay: true, // 如果true,浏览器准备好时开始回放。 muted: true, // 默认情况下将会消除任何音频。 loop: false, // 导致视频一结束就重新开始。 preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持) language: 'zh-CN', aspectRatio: '13:10', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3") // fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。 // 是否流体自适应容器宽高 fluid: true, // // 设置视频播放器的显示宽度(以像素为单位) // width: '100px', // // 设置视频播放器的显示高度(以像素为单位) // height: '300px', sources: [{ withCredentials: false, type: 'application/x-mpegURL', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目 src: res.data.data[i].videoUrl // url地址 }], flash: { hls: { withCredentials: false } }, html5: { hls: { withCredentials: false } }, notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。 controlBar: { timeDivider: false, durationDisplay: false, remainingTimeDisplay: false, fullscreenToggle: true, // 全屏按钮, pictureInPictureToggle: false } } this.videoOptions.push(obj) } this.createMyButton() }) }, // 进入识别记录界面 goDistinguishRecord (id) { this.$router.push({ path: '/videoSurveillance/distinguishRecord', query: { videoId: id } }) }, // 风场大门分页 onChangeGate (val) { this.videoCurrent = val this.getVideoSurveillanceData() } } } </script> <style lang="scss" scoped> .page-main { padding: 30px 24px 24px 24px; .top-btn { float: right; } .page-bottom { display: flex; width: 100%; flex-wrap: wrap; margin-left: -24px; .card-video-first, .card-video { width: 354px; height: 240px; margin-top: 20px; .card-image { width: 100%; height: 100%; } .bottom { padding: 0 12px; display: flex; align-items: center; background-color: rgba(0, 0, 0, 0.5); height: 40px; color: #fff; font-size: 14px; .bottom-btn { color: #fff; border: none; padding: 0 !important; &:hover { color: #0089d4; } } } } .card-video { .card-footer { padding: 0px 0 0 24px !important; background: none; width: 100%; position: absolute; border-top: none; bottom: 0px; } .card-block, .card-video-block { margin-left: 24px; padding: 0 !important; } } } .pager { margin-right: auto; margin: 21px 0px 24px 0; float: right; } .vjs-custom-skin > .video-js .vjs-control-bar .vjs-fullscreen-control{ height:38px !important; } .video-js .vjs-control{ cursor: pointer; width: 28px; margin-right:12px; } .vjs-control-bar{ display: flex; justify-content: center; align-items: center; } .video-js button{ font-size:16px; } .aidicon-image-outline:hover{ color: #0089d4 !important; } .aidicon-piechart-outline:hover{ color: #0089d4 !important; } .vjs-icon-placeholder:hover{ color: #0089d4 !important; }.vjs-icon-placeholder{ font-size: 13px; display: flex; justify-content: center; align-items: center; } .vjs-tech { pointer-events: none; } } </style>