Commit 9b9a13ab36fe93153148a489436e04b12aabcdd6

Authored by 648540858
1 parent fd3a4ef4

国标录像UI重构

src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java
... ... @@ -10,6 +10,7 @@ import org.slf4j.Logger;
10 10 import org.slf4j.LoggerFactory;
11 11 import org.springframework.beans.factory.annotation.Autowired;
12 12 import org.springframework.http.HttpStatus;
  13 +import org.springframework.util.ObjectUtils;
13 14 import org.springframework.web.filter.OncePerRequestFilter;
14 15  
15 16 import javax.servlet.*;
... ... @@ -51,6 +52,9 @@ public class ApiAccessFilter extends OncePerRequestFilter {
51 52  
52 53 LogDto logDto = new LogDto();
53 54 logDto.setName(uriName);
  55 + if (ObjectUtils.isEmpty(username)) {
  56 + username = "";
  57 + }
54 58 logDto.setUsername(username);
55 59 logDto.setAddress(servletRequest.getRemoteAddr());
56 60 logDto.setResult(HttpStatus.valueOf(servletResponse.getStatus()).toString());
... ...
web_src/src/components/CloudRecordDetail.vue
... ... @@ -30,7 +30,7 @@
30 30 </el-aside>
31 31 <el-main style="padding: 22px">
32 32 <div class="playBox" :style="playerStyle">
33   - <player ref="recordVideoPlayer" :videoUrl="videoUrl" fluent autoplay :height="true" ></player>
  33 + <player ref="recordVideoPlayer" :videoUrl="videoUrl" :height="true" style="width: 100%" ></player>
34 34 </div>
35 35 <div class="player-option-box" >
36 36 <el-slider
... ... @@ -310,7 +310,20 @@
310 310 let h = parseInt(val/3600);
311 311 let m = parseInt((val - h*3600)/60);
312 312 let s = parseInt(val - h*3600 - m*60);
313   - return h + ":" + m + ":" + s
  313 +
  314 + let hStr = h;
  315 + let mStr = m;
  316 + let sStr = s;
  317 + if (h < 10) {
  318 + hStr = "0" + hStr;
  319 + }
  320 + if (m < 10) {
  321 + mStr = "0" + mStr;s
  322 + }
  323 + if (s < 10) {
  324 + sStr = "0" + sStr;
  325 + }
  326 + return hStr + ":" + mStr + ":" + sStr
314 327 },
315 328 deleteRecord(){
316 329 // TODO
... ...
web_src/src/components/GBRecordDetail.vue 0 → 100644
  1 +<template>
  2 + <div style="width: 100%">
  3 + <div class="page-header" >
  4 + <div class="page-title">
  5 + <el-page-header @back="goBack" content="国标录像"></el-page-header>
  6 + </div>
  7 + </div>
  8 + <el-container>
  9 + <el-aside width="300px">
  10 + <div class="record-list-box-box">
  11 + <el-date-picker size="mini" v-model="chooseDate" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="dateChange()"></el-date-picker>
  12 + <div class="record-list-box" v-loading="recordsLoading" :style="recordListStyle">
  13 + <ul v-if="detailFiles.length >0" class="infinite-list record-list" >
  14 + <li v-for="item in detailFiles" class="infinite-list-item record-list-item" >
  15 +
  16 + <el-tag v-if="chooseFile != item" @click="checkedFile(item)">
  17 + <i class="el-icon-video-camera" ></i>
  18 + {{ moment(item.startTime).format('HH:mm:ss')}}-{{ moment(item.endTime).format('HH:mm:ss')}}
  19 + </el-tag>
  20 + <el-tag v-if="chooseFile == item" type="danger" >
  21 + <i class="el-icon-video-camera" ></i>
  22 + {{ moment(item.startTime).format('HH:mm:ss')}}-{{ moment(item.endTime).format('HH:mm:ss')}}
  23 + </el-tag>
  24 + <i style="color: #409EFF;margin-left: 5px;" class="el-icon-download" @click="downloadRecord(item)" ></i>
  25 + </li>
  26 + </ul>
  27 + </div>
  28 + <div size="mini" v-if="detailFiles.length ==0" class="record-list-no-val" >暂无数据</div>
  29 + </div>
  30 +
  31 + </el-aside>
  32 + <el-main style="padding-bottom: 10px;">
  33 + <div class="playBox" :style="playerStyle">
  34 + <player ref="recordVideoPlayer"
  35 + :videoUrl="videoUrl"
  36 + :error="videoError"
  37 + :message="videoError"
  38 + :hasAudio="hasAudio"
  39 + style="max-height: 100%"
  40 + fluent autoplay live ></player>
  41 + </div>
  42 + <div class="player-option-box">
  43 + <div>
  44 + <el-button-group >
  45 + <el-button size="mini" class="iconfont icon-zanting" title="开始" @click="gbPause()"></el-button>
  46 + <el-button size="mini" class="iconfont icon-kaishi" title="暂停" @click="gbPlay()"></el-button>
  47 + <el-dropdown size="mini" title="播放倍速" style="margin-left: 1px;" @command="gbScale">
  48 + <el-button size="mini">
  49 + 倍速 <i class="el-icon-arrow-down el-icon--right"></i>
  50 + </el-button>
  51 + <el-dropdown-menu slot="dropdown">
  52 + <el-dropdown-item command="0.25">0.25倍速</el-dropdown-item>
  53 + <el-dropdown-item command="0.5">0.5倍速</el-dropdown-item>
  54 + <el-dropdown-item command="1.0">1倍速</el-dropdown-item>
  55 + <el-dropdown-item command="2.0">2倍速</el-dropdown-item>
  56 + <el-dropdown-item command="4.0">4倍速</el-dropdown-item>
  57 + </el-dropdown-menu>
  58 + </el-dropdown>
  59 + <el-button size="mini" class="iconfont icon-xiazai1" title="下载选定录像" @click="downloadRecord()"></el-button>
  60 + <el-button v-if="sliderMIn === 0 && sliderMax === 86400" size="mini" class="iconfont icon-slider" title="放大滑块" @click="setSliderFit()"></el-button>
  61 + <el-button v-if="sliderMIn !== 0 || sliderMax !== 86400" size="mini" class="iconfont icon-slider-right" title="恢复滑块" @click="setSliderFit()"></el-button>
  62 + </el-button-group>
  63 + </div>
  64 + <el-slider
  65 + class="playtime-slider"
  66 + v-model="playTime"
  67 + id="playtimeSlider"
  68 + :disabled="detailFiles.length === 0"
  69 + :min="sliderMIn"
  70 + :max="sliderMax"
  71 + :range="true"
  72 + :format-tooltip="playTimeFormat"
  73 + @change="playTimeChange"
  74 + :marks="playTimeSliderMarks">
  75 + </el-slider>
  76 + <div class="slider-val-box">
  77 + <div class="slider-val" v-for="item of detailFiles" :style="'width:' + getDataWidth(item) + '%; left:' + getDataLeft(item) + '%'"></div>
  78 + </div>
  79 + </div>
  80 +
  81 + </el-main>
  82 + </el-container>
  83 + <recordDownload ref="recordDownload"></recordDownload>
  84 + </div>
  85 +</template>
  86 +
  87 +
  88 +<script>
  89 + import uiHeader from '../layout/UiHeader.vue'
  90 + import player from './common/jessibuca.vue'
  91 + import moment from 'moment'
  92 + import recordDownload from './dialog/recordDownload.vue'
  93 + export default {
  94 + name: 'app',
  95 + components: {
  96 + uiHeader, player,recordDownload
  97 + },
  98 + data() {
  99 + return {
  100 + deviceId: this.$route.params.deviceId,
  101 + channelId: this.$route.params.channelId,
  102 + recordsLoading: false,
  103 + sliderTime: 0,
  104 + seekTime: 0,
  105 + recordStartTime: 0,
  106 + streamId: "",
  107 + hasAudio: false,
  108 + detailFiles: [],
  109 + chooseDate: null,
  110 + videoUrl: null,
  111 + chooseFile: null,
  112 + streamInfo: null,
  113 + app: null,
  114 + mediaServerId: null,
  115 + ssrc: null,
  116 +
  117 + sliderMIn: 0,
  118 + sliderMax: 86400,
  119 + autoPlay: true,
  120 + taskUpdate: null,
  121 + tabVal: "running",
  122 + recordListStyle: {
  123 + height: this.winHeight + "px",
  124 + overflow: "auto",
  125 + margin: "10px auto 10px auto"
  126 + },
  127 + playerStyle: {
  128 + "margin": "0 auto 20px auto",
  129 + "height": this.winHeight + "px",
  130 + },
  131 + winHeight: window.innerHeight - 240,
  132 + playTime: 0,
  133 + playTimeSliderMarks: {
  134 + 0: "00:00",
  135 + 3600: "01:00",
  136 + 7200: "02:00",
  137 + 10800: "03:00",
  138 + 14400: "04:00",
  139 + 18000: "05:00",
  140 + 21600: "06:00",
  141 + 25200: "07:00",
  142 + 28800: "08:00",
  143 + 32400: "09:00",
  144 + 36000: "10:00",
  145 + 39600: "11:00",
  146 + 43200: "12:00",
  147 + 46800: "13:00",
  148 + 50400: "14:00",
  149 + 54000: "15:00",
  150 + 57600: "16:00",
  151 + 61200: "17:00",
  152 + 64800: "18:00",
  153 + 68400: "19:00",
  154 + 72000: "20:00",
  155 + 75600: "21:00",
  156 + 79200: "22:00",
  157 + 82800: "23:00",
  158 + 86400: "24:00",
  159 + },
  160 + };
  161 + },
  162 + computed: {
  163 +
  164 + },
  165 + mounted() {
  166 + this.recordListStyle.height = this.winHeight + "px";
  167 + this.playerStyle["height"] = this.winHeight + "px";
  168 + this.chooseDate = moment().format('YYYY-MM-DD')
  169 + this.dateChange();
  170 + },
  171 + destroyed() {
  172 + this.$destroy('recordVideoPlayer');
  173 + },
  174 + methods: {
  175 + dateChange(){
  176 + if (!this.chooseDate) {
  177 + return;
  178 + }
  179 + this.recordsLoading = true;
  180 + this.detailFiles = [];
  181 + let startTime = this.chooseDate + " 00:00:00";
  182 + let endTime = this.chooseDate + " 23:59:59";
  183 + this.$axios({
  184 + method: 'get',
  185 + url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime
  186 + }).then((res)=>{
  187 + this.recordsLoading = false;
  188 + if(res.data.code === 0) {
  189 + // 处理时间信息
  190 + this.detailFiles = res.data.data.recordList;
  191 +
  192 + }else {
  193 + this.$message({
  194 + showClose: true,
  195 + message: res.data.msg,
  196 + type: "error",
  197 + });
  198 + }
  199 +
  200 + }).catch((e)=> {
  201 + this.recordsLoading = false;
  202 + // that.videoHistory.searchHistoryResult = falsificationData.recordData;
  203 + });
  204 + },
  205 + moment: function (v) {
  206 + return moment(v)
  207 + },
  208 + videoError: function (e) {
  209 + console.log("播放器错误:" + JSON.stringify(e));
  210 + },
  211 + checkedFile(file){
  212 + this.chooseFile = file;
  213 + // 开始回放
  214 + this.playRecord(file)
  215 +
  216 + },
  217 + playRecord: function (row) {
  218 +
  219 + let startTime = row.startTime
  220 + this.recordStartTime = row.startTime
  221 + this.showTimeText = row.startTime.split(" ")[1]
  222 + let endTime = row.endTime
  223 + this.sliderTime = 0;
  224 + this.seekTime = new Date(endTime).getTime() - new Date(startTime).getTime();
  225 + if (this.streamId !== "") {
  226 + this.stopPlayRecord(()=> {
  227 + this.streamId = "";
  228 + this.playRecord(row);
  229 + })
  230 + } else {
  231 + this.$axios({
  232 + method: 'get',
  233 + url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' +
  234 + endTime
  235 + }).then((res)=> {
  236 + if (res.data.code === 0) {
  237 + this.streamInfo = res.data.data;
  238 + this.app = this.streamInfo.app;
  239 + this.streamId = this.streamInfo.stream;
  240 + this.mediaServerId = this.streamInfo.mediaServerId;
  241 + this.ssrc = this.streamInfo.ssrc;
  242 + this.videoUrl = this.getUrlByStreamInfo();
  243 + }else {
  244 + this.$message({
  245 + showClose: true,
  246 + message: res.data.msg,
  247 + type: "error",
  248 + });
  249 + }
  250 + });
  251 + }
  252 + },
  253 + gbPlay(){
  254 + console.log('前端控制:播放');
  255 + this.$axios({
  256 + method: 'get',
  257 + url: '/api/playback/resume/' + this.streamId
  258 + }).then((res)=> {
  259 + this.$refs[this.activePlayer].play(this.videoUrl)
  260 + });
  261 + },
  262 + gbPause(){
  263 + console.log('前端控制:暂停');
  264 + this.$axios({
  265 + method: 'get',
  266 + url: '/api/playback/pause/' + this.streamId
  267 + }).then(function (res) {});
  268 + },
  269 + gbScale(command){
  270 + console.log('前端控制:倍速 ' + command);
  271 + this.$axios({
  272 + method: 'get',
  273 + url: `/api/playback/speed/${this.streamId }/${command}`
  274 + }).then(function (res) {});
  275 + },
  276 + downloadRecord: function (row) {
  277 + if (!row) {
  278 + let startTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + this.playTime[0]*1000).format("YYYY-MM-DD HH:mm:ss");
  279 + let endTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + this.playTime[1]*1000).format("YYYY-MM-DD HH:mm:ss");
  280 + console.log(startTimeStr);
  281 + console.log(endTimeStr);
  282 + row = {
  283 + startTime: startTimeStr,
  284 + endTime: endTimeStr
  285 + }
  286 + }
  287 + if (this.streamId !== "") {
  288 + this.stopPlayRecord(()=> {
  289 + this.streamId = "";
  290 + this.downloadRecord(row);
  291 + })
  292 + }else {
  293 + this.$axios({
  294 + method: 'get',
  295 + url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
  296 + row.endTime + '&downloadSpeed=4'
  297 + }).then( (res)=> {
  298 + if (res.data.code === 0) {
  299 + let streamInfo = res.data.data;
  300 + this.$refs.recordDownload.openDialog(this.deviceId, this.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId);
  301 + }else {
  302 + this.$message({
  303 + showClose: true,
  304 + message: res.data.msg,
  305 + type: "error",
  306 + });
  307 + }
  308 + });
  309 + }
  310 + },
  311 + stopDownloadRecord: function (callback) {
  312 + this.$refs["recordVideoPlayer"].pause();
  313 + this.videoUrl = '';
  314 + this.$axios({
  315 + method: 'get',
  316 + url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
  317 + }).then((res)=> {
  318 + if (callback) callback(res)
  319 + });
  320 + },
  321 + stopPlayRecord: function (callback) {
  322 + this.$refs["recordVideoPlayer"].pause();
  323 + this.videoUrl = '';
  324 + this.$axios({
  325 + method: 'get',
  326 + url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
  327 + }).then(function (res) {
  328 + if (callback) callback()
  329 + });
  330 + },
  331 + getDataWidth(item){
  332 + let timeForFile = this.getTimeForFile(item);
  333 + let result = (timeForFile[2])/((this.sliderMax - this.sliderMIn)*1000)
  334 + return result*100
  335 + },
  336 + getDataLeft(item){
  337 + let timeForFile = this.getTimeForFile(item);
  338 + let differenceTime = timeForFile[0].getTime() - new Date(this.chooseDate + " 00:00:00").getTime()
  339 + return parseFloat((differenceTime - this.sliderMIn * 1000)/((this.sliderMax - this.sliderMIn)*1000))*100 ;
  340 + },
  341 + getUrlByStreamInfo(){
  342 + if (location.protocol === "https:") {
  343 + this.videoUrl = this.streamInfo["wss_flv"]
  344 + }else {
  345 + this.videoUrl = this.streamInfo["ws_flv"]
  346 + }
  347 + return this.videoUrl;
  348 +
  349 + },
  350 + playTimeChange(val){
  351 + console.log(val)
  352 + let maxTime = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1])[1];
  353 +
  354 + let startTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + val[0]*1000).format("YYYY-MM-DD HH:mm:ss");
  355 + let endTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + val[1]*1000).format("YYYY-MM-DD HH:mm:ss");
  356 + console.log(startTimeStr);
  357 + console.log(endTimeStr);
  358 +
  359 + this.checkedFile({
  360 + startTime: startTimeStr,
  361 + endTime: endTimeStr,
  362 + });
  363 + },
  364 + setSliderFit() {
  365 + if (this.sliderMIn === 0 && this.sliderMax === 86400) {
  366 + if (this.detailFiles.length > 0){
  367 + let timeForFile = this.getTimeForFile(this.detailFiles[0]);
  368 + let lastTimeForFile = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1]);
  369 + let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
  370 + let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
  371 +
  372 + this.playTime = parseInt(timeNum/1000)
  373 + this.sliderMIn = parseInt(timeNum/1000 - timeNum/1000%(60*60))
  374 + this.sliderMax = parseInt(lastTimeNum/1000 - lastTimeNum/1000%(60*60)) + 60*60
  375 +
  376 + this.playTime = [this.sliderMIn, this.sliderMax];
  377 + }
  378 + }else {
  379 + this.sliderMIn = 0;
  380 + this.sliderMax = 86400;
  381 + }
  382 + },
  383 + getTimeForFile(file){
  384 + let startTime = new Date(file.startTime);
  385 + let endTime = new Date(file.endTime);
  386 + return [startTime, endTime, endTime.getTime() - startTime.getTime()];
  387 + },
  388 + playTimeFormat(val){
  389 + let h = parseInt(val/3600);
  390 + let m = parseInt((val - h*3600)/60);
  391 + let s = parseInt(val - h*3600 - m*60);
  392 +
  393 + let hStr = h;
  394 + let mStr = m;
  395 + let sStr = s;
  396 + if (h < 10) {
  397 + hStr = "0" + hStr;
  398 + }
  399 + if (m < 10) {
  400 + mStr = "0" + mStr;s
  401 + }
  402 + if (s < 10) {
  403 + sStr = "0" + sStr;
  404 + }
  405 + return hStr + ":" + mStr + ":" + sStr
  406 + },
  407 + goBack(){
  408 + window.history.go(-1);
  409 + }
  410 + }
  411 + };
  412 +</script>
  413 +
  414 +<style>
  415 + .el-slider__runway {
  416 + background-color:rgba(206, 206, 206, 0.47) !important;
  417 + }
  418 + .el-slider__bar {
  419 + background-color: rgba(153, 153, 153, 0) !important;
  420 + }
  421 + .playtime-slider {
  422 + position: relative;
  423 + z-index: 100;
  424 + }
  425 + .data-picker-true{
  426 +
  427 + }
  428 + .data-picker-true:after{
  429 + content: "";
  430 + position: absolute;
  431 + width: 4px;
  432 + height: 4px;
  433 + background-color: #606060;
  434 + border-radius: 4px;
  435 + left: 45%;
  436 + top: 74%;
  437 +
  438 + }
  439 + .data-picker-false{
  440 +
  441 + }
  442 + .slider-val-box{
  443 + height: 6px;
  444 + position: relative;
  445 + top: -22px;
  446 + }
  447 + .slider-val{
  448 + height: 6px;
  449 + background-color: #007CFF;
  450 + position: absolute;
  451 + }
  452 + .record-list-box-box{
  453 + width: 250px;
  454 + float: left;
  455 + }
  456 + .record-list-box{
  457 + overflow: auto;
  458 + width: 220px;
  459 + list-style: none;
  460 + padding: 0;
  461 + margin: 0;
  462 + margin-top: 0px;
  463 + padding: 1rem 0;
  464 + background-color: #FFF;
  465 + margin-top: 10px;
  466 + }
  467 + .record-list{
  468 + list-style: none;
  469 + padding: 0;
  470 + margin: 0;
  471 + background-color: #FFF;
  472 +
  473 + }
  474 + .record-list-no-val {
  475 + position: absolute;
  476 + color: #9f9f9f;
  477 + top: 50%;
  478 + left: 110px;
  479 + }
  480 + .record-list-item{
  481 + padding: 0;
  482 + margin: 0;
  483 + margin: 0.5rem 0;
  484 + cursor: pointer;
  485 + }
  486 + .record-list-option {
  487 + width: 10px;
  488 + float: left;
  489 + margin-top: 39px;
  490 +
  491 + }
  492 + .player-option-box{
  493 + padding: 0 20px;
  494 + }
  495 +</style>
... ...
web_src/src/components/channelList.vue
... ... @@ -269,10 +269,10 @@ export default {
269 269 });
270 270 },
271 271 queryRecords: function (itemData) {
272   - var format = moment().format("yyyy-MM-DD");
273 272 let deviceId = this.deviceId;
274 273 let channelId = itemData.channelId;
275   - this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format})
  274 +
  275 + this.$router.push(`/gbRecordDetail/${deviceId}/${channelId}`)
276 276 },
277 277 stopDevicePush: function (itemData) {
278 278 var that = this;
... ...
web_src/src/components/console.vue
... ... @@ -101,11 +101,14 @@ export default {
101 101 window.clearTimeout(this.timer);
102 102 }
103 103 this.timer = setTimeout(()=>{
104   - this.getSystemInfo();
105   - this.getLoad();
106   - this.timer = null;
107   - this.loopForSystemInfo()
108   - this.getResourceInfo()
  104 + if (this.$route.path === "/console") {
  105 + this.getSystemInfo();
  106 + this.getLoad();
  107 + this.timer = null;
  108 + this.loopForSystemInfo()
  109 + this.getResourceInfo()
  110 + }
  111 +
109 112 }, 2000)
110 113 },
111 114 getSystemInfo: function (){
... ...
web_src/src/components/console/ConsoleResource.vue
1 1 <template >
2 2 <div id="consoleResource" style="width: 100%; height: 100%; background: #FFFFFF; text-align: center">
3 3 <div style="width: 50%;height: 50%; float:left; ">
4   - <el-progress :width="100" :stroke-width="8" type="circle" :percentage="Math.floor(deviceInfo.online/deviceInfo.total*100)" style="margin-top: 20px; font-size: 18px"></el-progress>
  4 + <el-progress v-if="deviceInfo.total > 0" :width="100" :stroke-width="8" type="circle" :percentage="Math.floor(deviceInfo.online/deviceInfo.total*100)" style="margin-top: 20px; font-size: 18px"></el-progress>
  5 + <el-progress v-if="deviceInfo.total === 0" :width="100" :stroke-width="8" type="circle" :percentage="0" style="margin-top: 20px; font-size: 18px"></el-progress>
5 6 <div class="resourceInfo">
6 7 设备总数:{{deviceInfo.total}}<br/>
7 8 在线数:{{deviceInfo.online}}
8 9 </div>
9 10 </div>
10 11 <div style="width: 50%;height: 50%; float:left; ">
11   - <el-progress :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(channelInfo.online/channelInfo.total*100)" style="margin-top: 20px"></el-progress>
  12 + <el-progress v-if="channelInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(channelInfo.online/channelInfo.total*100)" style="margin-top: 20px"></el-progress>
  13 + <el-progress v-if="channelInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
12 14 <div class="resourceInfo">
13 15 通道总数:{{channelInfo.total}}<br/>
14 16 在线数:{{channelInfo.online}}
15 17 </div>
16 18 </div>
17 19 <div style="width: 50%;height: 50%; float:left; ">
18   - <el-progress :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(pushInfo.online/pushInfo.total*100)" style="margin-top: 20px"></el-progress>
  20 + <el-progress v-if="pushInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(pushInfo.online/pushInfo.total*100)" style="margin-top: 20px"></el-progress>
  21 + <el-progress v-if="pushInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
19 22 <div class="resourceInfo">
20 23 推流总数:{{pushInfo.total}}<br/>
21 24 在线数:{{pushInfo.online}}
22 25 </div>
23 26 </div>
24 27 <div style="width: 50%;height: 50%; float:left; ">
25   - <el-progress :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(proxyInfo.online/proxyInfo.total*100)" style="margin-top: 20px"></el-progress>
  28 + <el-progress v-if="proxyInfo.total > 0" :width="100" :stroke-width="10" type="circle" :percentage="Math.floor(proxyInfo.online/proxyInfo.total*100)" style="margin-top: 20px"></el-progress>
  29 + <el-progress v-if="proxyInfo.total === 0" :width="100" :stroke-width="10" type="circle" :percentage="0" style="margin-top: 20px"></el-progress>
26 30 <div class="resourceInfo">
27 31 拉流代理总数:{{proxyInfo.total}}<br/>
28 32 在线数:{{proxyInfo.online}}
... ...
web_src/src/components/dialog/devicePlayer.vue
... ... @@ -23,11 +23,6 @@
23 23 <div id="shared" style="text-align: right; margin-top: 1rem;">
24 24 <el-tabs v-model="tabActiveName" @tab-click="tabHandleClick" >
25 25 <el-tab-pane label="实时视频" name="media">
26   - <div style="margin-bottom: 0.5rem;">
27   - <!-- <el-button type="primary" size="small" @click="playRecord(true, '')">播放</el-button>-->
28   - <!-- <el-button type="primary" size="small" @click="startRecord()">录制</el-button>-->
29   - <!-- <el-button type="primary" size="small" @click="stopRecord()">停止录制</el-button>-->
30   - </div>
31 26 <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
32 27 <span style="width: 5rem; line-height: 2.5rem; text-align: right;">播放地址:</span>
33 28 <el-input v-model="getPlayerShared.sharedUrl" :disabled="true" >
... ... @@ -148,51 +143,6 @@
148 143 </div>
149 144 </el-tab-pane>
150 145 <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
151   - <el-tab-pane label="录像查询" name="record" v-if="showRrecord">
152   - <div style="width: 100%;">
153   - <div style="width: 100%; text-align: left">
154   - <span>录像控制</span>
155   - <el-button-group style="margin-left: 1rem;">
156   - <el-button size="mini" class="iconfont icon-zanting" title="开始" @click="gbPause()"></el-button>
157   - <el-button size="mini" class="iconfont icon-kaishi" title="暂停" @click="gbPlay()"></el-button>
158   - <el-dropdown size="mini" title="播放倍速" style="margin-left: 1px;" @command="gbScale">
159   - <el-button size="mini">
160   - 倍速 <i class="el-icon-arrow-down el-icon--right"></i>
161   - </el-button>
162   - <el-dropdown-menu slot="dropdown">
163   - <el-dropdown-item command="0.25">0.25倍速</el-dropdown-item>
164   - <el-dropdown-item command="0.5">0.5倍速</el-dropdown-item>
165   - <el-dropdown-item command="1.0">1倍速</el-dropdown-item>
166   - <el-dropdown-item command="2.0">2倍速</el-dropdown-item>
167   - <el-dropdown-item command="4.0">4倍速</el-dropdown-item>
168   - </el-dropdown-menu>
169   - </el-dropdown>
170   - </el-button-group>
171   - <el-date-picker style="float: right;" size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="日期" @change="queryRecords()"></el-date-picker>
172   - </div>
173   - <div style="width: 100%; text-align: left">
174   - <span class="demonstration" style="padding: 12px 36px 12px 0;float: left;">{{showTimeText}}</span>
175   - <el-slider style="width: 80%; float:left;" v-model="sliderTime" @change="gbSeek" :show-tooltip="false"></el-slider>
176   - </div>
177   - </div>
178   -
179   -
180   - <el-table :data="videoHistory.searchHistoryResult" height="150" v-loading="recordsLoading">
181   - <el-table-column label="名称" prop="name"></el-table-column>
182   - <el-table-column label="文件" prop="filePath"></el-table-column>
183   - <el-table-column label="开始时间" prop="startTime" :formatter="timeFormatter"></el-table-column>
184   - <el-table-column label="结束时间" prop="endTime" :formatter="timeFormatter"></el-table-column>
185   -
186   - <el-table-column label="操作">
187   - <template slot-scope="scope">
188   - <el-button-group>
189   - <el-button icon="el-icon-video-play" size="mini" @click="playRecord(scope.row)">播放</el-button>
190   - <el-button icon="el-icon-download" size="mini" @click="downloadRecord(scope.row)">下载</el-button>
191   - </el-button-group>
192   - </template>
193   - </el-table-column>
194   - </el-table>
195   - </el-tab-pane>
196 146 <!--遥控界面-->
197 147 <el-tab-pane label="云台控制" name="control" v-if="showPtz">
198 148 <div style="display: flex; justify-content: left;">
... ... @@ -286,21 +236,18 @@
286 236 </el-tabs>
287 237 </div>
288 238 </el-dialog>
289   - <recordDownload ref="recordDownload"></recordDownload>
290 239 </div>
291 240 </template>
292 241  
293 242 <script>
294 243 import rtcPlayer from '../dialog/rtcPlayer.vue'
295 244 import LivePlayer from '@liveqing/liveplayer'
296   -// import player from '../dialog/easyPlayer.vue'
297 245 import jessibucaPlayer from '../common/jessibuca.vue'
298   -import recordDownload from '../dialog/recordDownload.vue'
299 246 export default {
300 247 name: 'devicePlayer',
301 248 props: {},
302 249 components: {
303   - LivePlayer, jessibucaPlayer, rtcPlayer, recordDownload,
  250 + LivePlayer, jessibucaPlayer, rtcPlayer,
304 251 },
305 252 computed: {
306 253 getPlayerShared: function () {
... ... @@ -328,10 +275,6 @@ export default {
328 275 livePlayer : ["ws_flv", "wss_flv"],
329 276 webRTC: ["rtc", "rtcs"],
330 277 },
331   - videoHistory: {
332   - date: '',
333   - searchHistoryResult: [] //媒体流历史记录搜索结果
334   - },
335 278 showVideoDialog: false,
336 279 streamId: '',
337 280 app : '',
... ... @@ -357,7 +300,6 @@ export default {
357 300 tracks: [],
358 301 coverPlaying:false,
359 302 tracksLoading: false,
360   - recordPlay: "",
361 303 showPtz: true,
362 304 showRrecord: true,
363 305 tracksNotLoaded: false,
... ... @@ -418,11 +360,6 @@ export default {
418 360 case "media":
419 361 this.play(param.streamInfo, param.hasAudio)
420 362 break;
421   - case "record":
422   - this.showVideoDialog = true;
423   - this.videoHistory.date = param.date;
424   - this.queryRecords()
425   - break;
426 363 case "streamPlay":
427 364 this.tabActiveName = "media";
428 365 this.showRrecord = false;
... ... @@ -433,9 +370,6 @@ export default {
433 370 break;
434 371 }
435 372 },
436   - timeAxisSelTime: function (val) {
437   - console.log(val)
438   - },
439 373 play: function (streamInfo, hasAudio) {
440 374 this.streamInfo = streamInfo;
441 375 this.hasAudio = hasAudio;
... ... @@ -531,10 +465,6 @@ export default {
531 465 this.convertStop();
532 466 }
533 467 this.convertKey = ''
534   - if (this.recordPlay != '') {
535   - this.stopPlayRecord();
536   - }
537   - this.recordPlay = ''
538 468 },
539 469  
540 470 copySharedInfo: function (data) {
... ... @@ -559,137 +489,6 @@ export default {
559 489 }
560 490 );
561 491 },
562   -
563   - queryRecords: function () {
564   - if (!this.videoHistory.date) {
565   - return;
566   - }
567   - this.recordsLoading = true;
568   - this.videoHistory.searchHistoryResult = [];
569   - let that = this;
570   - var startTime = this.videoHistory.date + " 00:00:00";
571   - var endTime = this.videoHistory.date + " 23:59:59";
572   - this.$axios({
573   - method: 'get',
574   - url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime
575   - }).then(function (res) {
576   - console.log(res)
577   - that.recordsLoading = false;
578   - if(res.data.code === 0) {
579   - // 处理时间信息
580   - that.videoHistory.searchHistoryResult = res.data.data.recordList;
581   - }else {
582   - this.$message({
583   - showClose: true,
584   - message: res.data.msg,
585   - type: "error",
586   - });
587   - }
588   -
589   - }).catch(function (e) {
590   - console.log(e.message);
591   - // that.videoHistory.searchHistoryResult = falsificationData.recordData;
592   - });
593   -
594   - },
595   - onTimeChange: function (video) {
596   - // this.queryRecords()
597   - },
598   - playRecord: function (row) {
599   - let that = this;
600   -
601   - let startTime = row.startTime
602   - this.recordStartTime = row.startTime
603   - this.showTimeText = row.startTime.split(" ")[1]
604   - let endtime = row.endTime
605   - this.sliderTime = 0;
606   - this.seekTime = new Date(endtime).getTime() - new Date(startTime).getTime();
607   - console.log(this.seekTime)
608   - if (that.streamId != "") {
609   - that.stopPlayRecord(function () {
610   - that.streamId = "";
611   - that.playRecord(row);
612   - })
613   - } else {
614   - this.$axios({
615   - method: 'get',
616   - url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
617   - row.endTime
618   - }).then(function (res) {
619   - if (res.data.code === 0) {
620   - that.streamInfo = res.data.data;
621   - that.app = that.streamInfo.app;
622   - that.streamId = that.streamInfo.stream;
623   - that.mediaServerId = that.streamInfo.mediaServerId;
624   - that.ssrc = that.streamInfo.ssrc;
625   - that.videoUrl = that.getUrlByStreamInfo();
626   - }else {
627   - that.$message({
628   - showClose: true,
629   - message: res.data.msg,
630   - type: "error",
631   - });
632   - }
633   - that.recordPlay = true;
634   - });
635   - }
636   - },
637   - stopPlayRecord: function (callback) {
638   - this.$refs[this.activePlayer].pause();
639   - this.videoUrl = '';
640   - this.$axios({
641   - method: 'get',
642   - url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
643   - }).then(function (res) {
644   - if (callback) callback()
645   - });
646   - },
647   - downloadRecord: function (row) {
648   - let that = this;
649   - if (that.streamId != "") {
650   - that.stopDownloadRecord(function (res) {
651   - if (res.code == 0) {
652   - that.streamId = "";
653   - that.downloadRecord(row);
654   - }else {
655   - this.$message({
656   - showClose: true,
657   - message: res.data.msg,
658   - type: "error",
659   - });
660   - }
661   -
662   - })
663   - } else {
664   - this.$axios({
665   - method: 'get',
666   - url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
667   - row.endTime + '&downloadSpeed=4'
668   - }).then(function (res) {
669   - if (res.data.code == 0) {
670   - let streamInfo = res.data.data;
671   - that.recordPlay = false;
672   - that.$refs.recordDownload.openDialog(that.deviceId, that.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId);
673   - }else {
674   - that.$message({
675   - showClose: true,
676   - message: res.data.msg,
677   - type: "error",
678   - });
679   - }
680   - });
681   - }
682   - },
683   - stopDownloadRecord: function (callback) {
684   - this.$refs[this.activePlayer].pause();
685   - this.videoUrl = '';
686   - this.$axios({
687   - method: 'get',
688   - url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
689   - }).then((res)=> {
690   - if (callback) callback(res)
691   - });
692   - },
693 492 ptzCamera: function (command) {
694 493 console.log('云台控制:' + command);
695 494 let that = this;
... ... @@ -728,52 +527,6 @@ export default {
728 527 url: '/api/ptz/front_end_command/' + this.deviceId + '/' + this.channelId + '?cmdCode=' + cmdCode + '&parameter1=' + groupNum + '&parameter2=' + parameter + '&combindCode2=0'
729 528 }).then(function (res) {});
730 529 },
731   - formatTooltip: function (val) {
732   - var h = parseInt(val / 60);
733   - var hStr = h < 10 ? ("0" + h) : h;
734   - var s = val % 60;
735   - var sStr = s < 10 ? ("0" + s) : s;
736   - return h + ":" + sStr;
737   - },
738   - timeFormatter: function (row, column, cellValue, index) {
739   - return cellValue.split(" ")[1];
740   - },
741   - mergeTime: function (timeArray) {
742   - var resultArray = [];
743   - for (let i = 0; i < timeArray.length; i++) {
744   - var startTime = new Date(timeArray[i].startTime);
745   - var endTime = new Date(timeArray[i].endTime);
746   - if (i == 0) {
747   - resultArray[0] = {
748   - startTime: startTime,
749   - endTime: endTime
750   - }
751   - }
752   - for (let j = 0; j < resultArray.length; j++) {
753   - if (startTime > resultArray[j].endTime) { // 合并
754   - if (startTime - resultArray[j].endTime <= 1000) {
755   - resultArray[j].endTime = endTime;
756   - } else {
757   - resultArray[resultArray.length] = {
758   - startTime: startTime,
759   - endTime: endTime
760   - }
761   - }
762   - } else if (resultArray[j].startTime > endTime) { // 合并
763   - if (resultArray[j].startTime - endTime <= 1000) {
764   - resultArray[j].startTime = startTime;
765   - } else {
766   - resultArray[resultArray.length] = {
767   - startTime: startTime,
768   - endTime: endTime
769   - }
770   - }
771   - }
772   - }
773   - }
774   - console.log(resultArray)
775   - return resultArray;
776   - },
777 530 copyUrl: function (dropdownItem){
778 531 console.log(dropdownItem)
779 532 this.$copyText(dropdownItem).then((e)=> {
... ... @@ -782,47 +535,7 @@ export default {
782 535  
783 536 })
784 537 },
785   - gbPlay(){
786   - console.log('前端控制:播放');
787   - this.$axios({
788   - method: 'get',
789   - url: '/api/playback/resume/' + this.streamId
790   - }).then((res)=> {
791   - this.$refs[this.activePlayer].play(this.videoUrl)
792   - });
793   - },
794   - gbPause(){
795   - console.log('前端控制:暂停');
796   - this.$axios({
797   - method: 'get',
798   - url: '/api/playback/pause/' + this.streamId
799   - }).then(function (res) {});
800   - },
801   - gbScale(command){
802   - console.log('前端控制:倍速 ' + command);
803   - this.$axios({
804   - method: 'get',
805   - url: `/api/playback/speed/${this.streamId }/${command}`
806   - }).then(function (res) {});
807   - },
808   - gbSeek(val){
809   - console.log('前端控制:seek ');
810   - console.log(this.seekTime);
811   - console.log(this.sliderTime);
812   - let showTime = new Date(new Date(this.recordStartTime).getTime() + this.seekTime * val / 100)
813   - let hour = showTime.getHours();
814   - let minutes = showTime.getMinutes();
815   - let seconds = showTime.getSeconds();
816   - this.showTimeText = (hour < 10?("0" + hour):hour) + ":" + (minutes<10?("0" + minutes):minutes) + ":" + (seconds<10?("0" + seconds):seconds)
817   - this.$axios({
818   - method: 'get',
819   - url: `/api/playback/seek/${this.streamId }/` + Math.floor(this.seekTime * val / 100000)
820   - }).then( (res)=> {
821   - setTimeout(()=>{
822   - this.$refs[this.activePlayer].play(this.videoUrl)
823   - }, 600)
824   - });
825   - },
  538 +
826 539  
827 540  
828 541 }
... ...
web_src/src/router/index.js
... ... @@ -5,6 +5,7 @@ import Layout from &quot;../layout/index.vue&quot;
5 5 import console from '../components/console.vue'
6 6 import deviceList from '../components/DeviceList.vue'
7 7 import channelList from '../components/channelList.vue'
  8 +import gbRecordDetail from '../components/GBRecordDetail.vue'
8 9 import pushVideoList from '../components/PushVideoList.vue'
9 10 import streamProxyList from '../components/StreamProxyList.vue'
10 11 import map from '../components/map.vue'
... ... @@ -65,6 +66,11 @@ export default new VueRouter({
65 66 component: channelList,
66 67 },
67 68 {
  69 + path: '/gbRecordDetail/:deviceId/:channelId/',
  70 + name: 'gbRecordDetail',
  71 + component: gbRecordDetail,
  72 + },
  73 + {
68 74 path: '/parentPlatformList/:count/:page',
69 75 name: 'parentPlatformList',
70 76 component: parentPlatformList,
... ...
web_src/static/css/iconfont.css
1 1 @font-face {
2 2 font-family: "iconfont"; /* Project id 1291092 */
3   - src: url('iconfont.woff2?t=1655453611360') format('woff2'),
4   - url('iconfont.woff?t=1655453611360') format('woff'),
5   - url('iconfont.ttf?t=1655453611360') format('truetype');
  3 + src: url('iconfont.woff2?t=1673251105600') format('woff2'),
  4 + url('iconfont.woff?t=1673251105600') format('woff'),
  5 + url('iconfont.ttf?t=1673251105600') format('truetype');
6 6 }
7 7  
8 8 .iconfont {
... ... @@ -13,6 +13,14 @@
13 13 -moz-osx-font-smoothing: grayscale;
14 14 }
15 15  
  16 +.icon-slider:before {
  17 + content: "\e7e0";
  18 +}
  19 +
  20 +.icon-slider-right:before {
  21 + content: "\ea19";
  22 +}
  23 +
16 24 .icon-list:before {
17 25 content: "\e7de";
18 26 }
... ...
web_src/static/css/iconfont.woff2
No preview for this file type