From 9361943e47a09ea46f76adf06fa0d24a07ac711d Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: 星期一, 26 十月 2020 11:40:46 +0800 Subject: [PATCH] 修复ui录象播放 优化录象查询接口 --- src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java | 25 + src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java | 2 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 10 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java | 5 web_src/src/components/gb28181/devicePlayer.vue | 722 ++++++++++++++++++++++--------------- web_src/package.json | 1 src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java | 40 ++ src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java | 72 +++ web_src/package-lock.json | 5 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java | 2 web_src/index.html | 2 src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java | 2 src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java | 8 web_src/src/components/Login.vue | 10 web_src/src/main.js | 2 /dev/null | 98 ----- src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java | 21 + web_src/src/components/channelList.vue | 24 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 28 + src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java | 11 20 files changed, 648 insertions(+), 442 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java index 98592bd..f80fd0e 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -18,6 +18,8 @@ public static final String PLAYER_PREFIX = "VMP_player_"; + public static final String PLAY_BLACK_PREFIX = "VMP_playback_"; + public static final String EVENT_ONLINE_REGISTER = "1"; public static final String EVENT_ONLINE_KEEPLIVE = "2"; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java index 20605b1..1533b66 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java @@ -1,12 +1,18 @@ package com.genersoft.iot.vmp.gb28181.bean; +import org.jetbrains.annotations.NotNull; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + /** * @Description:璁惧褰曞儚bean * @author: swwheihei * @date: 2020骞�5鏈�8鏃� 涓嬪崍2:06:54 */ -public class RecordItem { +public class RecordItem implements Comparable<RecordItem>{ private String deviceId; @@ -97,4 +103,21 @@ public void setRecorderId(String recorderId) { this.recorderId = recorderId; } + + @Override + public int compareTo(@NotNull RecordItem recordItem) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + try { + Date startTime_now = sdf.parse(startTime); + Date startTime_param = sdf.parse(recordItem.getStartTime()); + if (startTime_param.compareTo(startTime_now) > 0) { + return -1; + }else { + return 1; + } + } catch (ParseException e) { + e.printStackTrace(); + } + return 0; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index 0fdc897..7d5d10c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -80,7 +80,7 @@ * @param startTime 寮�濮嬫椂闂�,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss */ - public String playbackStreamCmd(Device device,String channelId, String startTime, String endTime); + public StreamInfo playbackStreamCmd(Device device,String channelId, String startTime, String endTime); /** * 瑙嗛娴佸仠姝� diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index e2c11cb..047918c 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -279,7 +279,7 @@ * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss */ @Override - public String playbackStreamCmd(Device device, String channelId, String startTime, String endTime) { + public StreamInfo playbackStreamCmd(Device device, String channelId, String startTime, String endTime) { try { MediaServerConfig mediaInfo = storager.getMediaInfo(); String ssrc = streamSession.createPlayBackSsrc(); @@ -324,7 +324,13 @@ ClientTransaction transaction = transmitRequest(device, request); streamSession.put(ssrc, transaction); - return ssrc; + + StreamInfo streamInfo = new StreamInfo(); + streamInfo.setSsrc(ssrc); + streamInfo.setCahnnelId(channelId); + streamInfo.setDeviceID(device.getDeviceId()); + boolean b = storager.startPlayBlack(streamInfo); + return streamInfo; } catch ( SipException | ParseException | InvalidArgumentException e) { e.printStackTrace(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java index f4411e1..ec19cd5 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java @@ -2,11 +2,7 @@ import java.io.ByteArrayInputStream; import java.text.ParseException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; @@ -316,6 +312,7 @@ record.setRecorderId(XmlUtil.getText(itemRecord,"RecorderID")); recordList.add(record); } +// recordList.sort(Comparator.naturalOrder()); recordInfo.setRecordList(recordList); } @@ -349,9 +346,13 @@ // 璧板埌杩欓噷锛屾湁浠ヤ笅鍙兘锛�1銆佹病鏈夊綍鍍忎俊鎭�,绗竴娆℃敹鍒皉ecordinfo鐨勬秷鎭嵆杩斿洖鍝嶅簲鏁版嵁锛屾棤redis鎿嶄綔 // 2銆佹湁褰曞儚鏁版嵁锛屼笖绗竴娆″嵆鏀跺埌瀹屾暣鏁版嵁锛岃繑鍥炲搷搴旀暟鎹紝鏃爎edis鎿嶄綔 // 3銆佹湁褰曞儚鏁版嵁锛屽湪瓒呮椂鏃堕棿鍐呮敹鍒板娆″寘缁勮鍚庢暟閲忚冻澶燂紝杩斿洖鏁版嵁 + + // 瀵硅褰曡繘琛屾帓搴� RequestMessage msg = new RequestMessage(); msg.setDeviceId(deviceId); msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO); + // 鑷劧椤哄簭鎺掑簭, 鍏冪礌杩涜鍗囧簭鎺掑垪 + recordInfo.getRecordList().sort(Comparator.naturalOrder()); msg.setData(recordInfo); deferredResultHolder.invokeResult(msg); } catch (DocumentException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index 96b4af2..6fd4cf5 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -130,17 +130,27 @@ String streamId = json.getString("id"); -// String ssrc = String.format("%10d", Integer.parseInt(streamId, 16)); // ZLM 瑕佹眰澶у啓涓旈浣嶈ˉ闆� String ssrc = new DecimalFormat("0000000000").format(Integer.parseInt(streamId, 16)); - StreamInfo streamInfo = storager.queryPlayBySSRC(ssrc); - if ("rtp".equals(app) && streamInfo != null ) { + StreamInfo streamInfoForPlay = storager.queryPlayBySSRC(ssrc); + if ("rtp".equals(app) && streamInfoForPlay != null ) { MediaServerConfig mediaInfo = storager.getMediaInfo(); - streamInfo.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); - streamInfo.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); - streamInfo.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId)); - streamInfo.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); - streamInfo.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId)); - storager.startPlay(streamInfo); + streamInfoForPlay.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlay.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlay.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId)); + streamInfoForPlay.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlay.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId)); + storager.startPlay(streamInfoForPlay); + } + + StreamInfo streamInfoForPlayBack = storager.queryPlayBlackBySSRC(ssrc); + if ("rtp".equals(app) && streamInfoForPlayBack != null ) { + MediaServerConfig mediaInfo = storager.getMediaInfo(); + streamInfoForPlayBack.setFlv(String.format("http://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlayBack.setWs_flv(String.format("ws://%s:%s/rtp/%s.flv", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlayBack.setRtmp(String.format("rtmp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtmpPort(), streamId)); + streamInfoForPlayBack.setHls(String.format("http://%s:%s/rtp/%s/hls.m3u8", mediaInfo.getLocalIP(), mediaInfo.getHttpPort(), streamId)); + streamInfoForPlayBack.setRtsp(String.format("rtsp://%s:%s/rtp/%s", mediaInfo.getLocalIP(), mediaInfo.getRtspPort(), streamId)); + storager.startPlayBlack(streamInfoForPlayBack); } // TODO Auto-generated method stub diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java index 422f622..f44e7df 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMUtils.java @@ -30,11 +30,6 @@ param.put("stream_id", streamId); JSONObject jsonObject = zlmresTfulUtils.openRtpServer(param); if (jsonObject.getInteger("code") == 0) { - System.out.println(11111111); - System.out.println(streamId); - System.out.println(ssrc); - System.out.println(newPort); - System.out.println(jsonObject.toJSONString()); return newPort; } else { return getNewRTPPort(ssrc); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java index 0894fe2..2680922 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java @@ -183,4 +183,12 @@ StreamInfo queryPlayByDevice(String deviceId, String code); Map<String, StreamInfo> queryPlayByDeviceId(String deviceId); + + boolean startPlayBlack(StreamInfo streamInfo); + + boolean stopPlayBlack(StreamInfo streamInfo); + + StreamInfo queryPlayBlackByDevice(String deviceId, String channelId); + + StreamInfo queryPlayBlackBySSRC(String ssrc); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java index 1e68095..de94f86 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/jdbc/VideoManagerJdbcStoragerImpl.java @@ -190,6 +190,27 @@ @Override public Map<String, StreamInfo> queryPlayByDeviceId(String deviceId) { + + return null; + } + + @Override + public boolean startPlayBlack(StreamInfo streamInfo) { + return false; + } + + @Override + public boolean stopPlayBlack(StreamInfo streamInfo) { + return false; + } + + @Override + public StreamInfo queryPlayBlackByDevice(String deviceId, String channelId) { + return null; + } + + @Override + public StreamInfo queryPlayBlackBySSRC(String ssrc) { return null; } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java index 10f3815..e69a645 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/redis/VideoManagerRedisStoragerImpl.java @@ -411,6 +411,14 @@ } @Override + public StreamInfo queryPlayBlackBySSRC(String ssrc) { +// List<Object> playLeys = redis.keys(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, ssrc)); + List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, ssrc)); + if (playLeys == null || playLeys.size() == 0) return null; + return (StreamInfo)redis.get(playLeys.get(0).toString()); + } + + @Override public StreamInfo queryPlayByDevice(String deviceId, String code) { // List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, @@ -498,5 +506,37 @@ } + @Override + public boolean startPlayBlack(StreamInfo stream) { + return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getSsrc(),stream.getDeviceID(), stream.getCahnnelId()), + stream); + } + + @Override + public boolean stopPlayBlack(StreamInfo streamInfo) { + if (streamInfo == null) return false; + DeviceChannel deviceChannel = queryChannel(streamInfo.getDeviceID(), streamInfo.getCahnnelId()); + if (deviceChannel != null) { + deviceChannel.setSsrc(null); + deviceChannel.setPlay(false); + updateChannel(streamInfo.getDeviceID(), deviceChannel); + } + return redis.del(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, + streamInfo.getSsrc(), + streamInfo.getDeviceID(), + streamInfo.getCahnnelId())); + } + + @Override + public StreamInfo queryPlayBlackByDevice(String deviceId, String code) { + String format = String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, + deviceId, + code); + List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, + deviceId, + code)); + if (playLeys == null || playLeys.size() == 0) return null; + return (StreamInfo)redis.get(playLeys.get(0).toString()); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java index 134e692..ea2a062 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/play/PlayController.java @@ -70,7 +70,7 @@ }else { streamInfo = storager.queryPlayByDevice(deviceId, channelId); JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); - if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo.getFlv() != null){ + if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo != null && streamInfo.getFlv() != null){ JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId); if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) { lockFlag = false; diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java index cc3961b..e53cbbf 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/playback/PlaybackController.java @@ -1,5 +1,9 @@ package com.genersoft.iot.vmp.vmanager.playback; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -30,7 +34,10 @@ @Autowired private IVideoManagerStorager storager; - + + @Autowired + private ZLMRESTfulUtils zlmresTfulUtils; + @GetMapping("/playback/{deviceId}/{channelId}") public ResponseEntity<String> play(@PathVariable String deviceId,@PathVariable String channelId, String startTime, String endTime){ @@ -43,25 +50,70 @@ logger.warn(log); return new ResponseEntity<String>(log,HttpStatus.BAD_REQUEST); } - + Device device = storager.queryVideoDevice(deviceId); - String ssrc = cmder.playbackStreamCmd(device, channelId, startTime, endTime); + StreamInfo streamInfo = storager.queryPlayBlackByDevice(deviceId, channelId); + + if (streamInfo != null) { + cmder.streamByeCmd(streamInfo.getSsrc()); + } + +// }else { +// String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); +// JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); +// if (rtpInfo.getBoolean("exist")) { +// return new ResponseEntity<String>(JSON.toJSONString(streamInfo),HttpStatus.OK); +// }else { +// storager.stopPlayBlack(streamInfo); +// streamInfo = cmder.playbackStreamCmd(device, channelId, startTime, endTime); +// } +// } + streamInfo = cmder.playbackStreamCmd(device, channelId, startTime, endTime); + + String streamId = String.format("%08x", Integer.parseInt(streamInfo.getSsrc())).toUpperCase(); if (logger.isDebugEnabled()) { - logger.debug("璁惧鍥炴斁 API璋冪敤锛宻src锛�"+ssrc+",ZLMedia streamId:"+Integer.toHexString(Integer.parseInt(ssrc))); + logger.debug("璁惧鍥炴斁 API璋冪敤锛宻src锛�" + streamInfo.getSsrc() + ",ZLMedia streamId:" + streamId); } - - if(ssrc!=null) { - JSONObject json = new JSONObject(); - json.put("ssrc", ssrc); - return new ResponseEntity<String>(json.toString(),HttpStatus.OK); + // 绛夊緟鎺ㄦ祦, TODO 榛樿瓒呮椂15s + boolean lockFlag = true; + long lockStartTime = System.currentTimeMillis(); + while (lockFlag) { + try { + if (System.currentTimeMillis() - lockStartTime > 75 * 1000) { + storager.stopPlayBlack(streamInfo); + return new ResponseEntity<String>("timeout",HttpStatus.OK); + }else { + streamInfo = storager.queryPlayBlackByDevice(deviceId, channelId); + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); + if (rtpInfo != null && rtpInfo.getBoolean("exist") && streamInfo.getFlv() != null){ + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId); + if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) { + lockFlag = false; + JSONArray tracks = mediaInfo.getJSONArray("tracks"); + streamInfo.setTracks(tracks); + storager.startPlayBlack(streamInfo); + }else { + + } + }else { + Thread.sleep(2000); + continue; + }; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + if(streamInfo!=null) { + return new ResponseEntity<String>(JSON.toJSONString(streamInfo),HttpStatus.OK); } else { logger.warn("璁惧鍥炴斁API璋冪敤澶辫触锛�"); return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); } } - @PostMapping("/playback/{ssrc}/stop") + @RequestMapping("/playback/{ssrc}/stop") public ResponseEntity<String> playStop(@PathVariable String ssrc){ cmder.streamByeCmd(ssrc); diff --git a/web_src/index.html b/web_src/index.html index cb0b3df..9c4e39b 100644 --- a/web_src/index.html +++ b/web_src/index.html @@ -3,7 +3,7 @@ <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> - <title>GB28181服务器</title> + <title>鍥芥爣28181</title> </head> <body> <script type="text/javascript" src="./js/liveplayer-lib.min.js"></script> diff --git a/web_src/package-lock.json b/web_src/package-lock.json index f031dcc..e00c5ce 100644 --- a/web_src/package-lock.json +++ b/web_src/package-lock.json @@ -5843,6 +5843,11 @@ "minimist": "^1.2.5" } }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npm.taobao.org/moment/download/moment-2.29.1.tgz?cache=0&sync_timestamp=1601983423917&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmoment%2Fdownload%2Fmoment-2.29.1.tgz", + "integrity": "sha1-sr52n6MZQL6e7qZGnAdeNQBvo9M=" + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz", diff --git a/web_src/package.json b/web_src/package.json index 8f2b3e2..05178d4 100644 --- a/web_src/package.json +++ b/web_src/package.json @@ -15,6 +15,7 @@ "core-js": "^2.6.5", "echarts": "^4.7.0", "element-ui": "2.10.1", + "moment": "^2.29.1", "vue": "^2.6.11", "vue-clipboard2": "^0.3.1", "vue-cookies": "^1.7.4", diff --git a/web_src/src/components/Loading.vue b/web_src/src/components/Loading.vue deleted file mode 100644 index 433705e..0000000 --- a/web_src/src/components/Loading.vue +++ /dev/null @@ -1,98 +0,0 @@ -//loading鏁堟灉缁勪欢 - -<template> -<div class="loadEffect" :style="{marginTop: marginTop? marginTop : '50%'}"> - <span class="ld-span"></span> - <span class="ld-span"></span> - <span class="ld-span"></span> - <span class="ld-span"></span> - <span class="ld-span"></span> - <span class="ld-span"></span> - <span class="ld-span"></span> - <span class="ld-span"></span> -</div> -</template> - -<script> -export default { - name: 'Loading', - props: ["marginTop"] - -} -</script> - -<style scoped> -.loadEffect{ - width: 100px; - height: 100px; - position: relative; - margin: 0 auto; - position: relative; - top:-50px; - margin-top:50%; - transform: scale(.5) -} -.loadEffect .ld-span{ - display: inline-block; - width: 20px; - height: 20px; - border-radius: 50%; - background: #67e7d5; - position: absolute; - -webkit-animation: load 1.04s ease infinite; -} -@-webkit-keyframes load{ - 0%{ - -webkit-transform: scale(1.2); - opacity: 1; - } - 100%{ - -webkit-transform: scale(.3); - opacity: 0.5; - } -} -.loadEffect .ld-span:nth-child(1){ - left: 0; - top: 50%; - margin-top:-10px; - -webkit-animation-delay:0.13s; -} -.loadEffect .ld-span:nth-child(2){ - left: 14px; - top: 14px; - -webkit-animation-delay:0.26s; -} -.loadEffect .ld-span:nth-child(3){ - left: 50%; - top: 0; - margin-left: -10px; - -webkit-animation-delay:0.39s; -} -.loadEffect .ld-span:nth-child(4){ - top: 14px; - right:14px; - -webkit-animation-delay:0.52s; -} -.loadEffect .ld-span:nth-child(5){ - right: 0; - top: 50%; - margin-top:-10px; - -webkit-animation-delay:0.65s; -} -.loadEffect .ld-span:nth-child(6){ - right: 14px; - bottom:14px; - -webkit-animation-delay:0.78s; -} -.loadEffect .ld-span:nth-child(7){ - bottom: 0; - left: 50%; - margin-left: -10px; - -webkit-animation-delay:0.91s; -} -.loadEffect .ld-span:nth-child(8){ - bottom: 14px; - left: 14px; - -webkit-animation-delay:1.04s; -} -</style> diff --git a/web_src/src/components/Login.vue b/web_src/src/components/Login.vue index 030d3ee..f047c5d 100644 --- a/web_src/src/components/Login.vue +++ b/web_src/src/components/Login.vue @@ -10,16 +10,14 @@ <div class="log-logo">Welcome!</div> <div class="log-text"></div> </div> - <div class="log-email"> + <div class="log-email" v-loading="isLoging" > <input type="text" placeholder="鐢ㄦ埛鍚�" :class="'log-input' + (username==''?' log-input-empty':'')" v-model="username"><input type="password" placeholder="瀵嗙爜" :class="'log-input' + (password==''?' log-input-empty':'')" v-model="password"> <a href="javascript:;" class="log-btn" @click="login" >鐧诲綍</a> </div> - <Loading v-if="isLoging" marginTop="-30%"></Loading> </div> </template> <script> -import Loading from './Loading.vue' import crypto from 'crypto' export default { name: 'Login', @@ -29,9 +27,6 @@ username: '', password: '' } - }, - components:{ - Loading }, created(){ var that = this; @@ -79,7 +74,8 @@ } }) .catch(function (error) { - console.log(error); + that.$message.error(error.response.statusText); + that.isLoging = false; }); diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 4bcbe31..930da5b 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -26,7 +26,7 @@ </el-select> </div> - <devicePlayer ref="devicePlayer"></devicePlayer> + <devicePlayer ref="devicePlayer" v-loading="isLoging"></devicePlayer> <!--璁惧鍒楄〃--> <el-table ref="channelListTable" :data="deviceChannelList" :height="winHeight" border style="width: 100%"> <el-table-column prop="channelId" label="閫氶亾缂栧彿" width="210"> @@ -58,8 +58,8 @@ <el-button size="mini" icon="el-icon-video-play" @click="sendDevicePush(scope.row)">鎾斁</el-button> <el-button size="mini" icon="el-icon-switch-button" type="danger" v-if="scope.row.play" @click="stopDevicePush(scope.row)">鍋滄</el-button> <el-button size="mini" icon="el-icon-s-open" type="primary" v-if="scope.row.parental == 1" @click="changeSubchannel(scope.row)">鏌ョ湅</el-button> - <!-- <el-button size="mini" icon="el-icon-video-camera" type="primary" >璁惧褰曡薄</el-button>--> - <!-- <el-button size="mini" @click="sendDevicePush(scope.row)">褰曞儚鏌ヨ</el-button> --> + <el-button size="mini" icon="el-icon-video-camera" type="primary" @click="queryRecords(scope.row)">璁惧褰曡薄</el-button> +<!-- <el-button size="mini" @click="sendDevicePush(scope.row)">褰曞儚鏌ヨ</el-button> --> </el-button-group> </template> </el-table-column> @@ -69,20 +69,18 @@ </el-main> </el-container> - <Loading v-if="isLoging" marginTop="-50%"></Loading> </div> </template> <script> import devicePlayer from './gb28181/devicePlayer.vue' import uiHeader from './UiHeader.vue' -import Loading from './Loading.vue' +import moment from "moment"; export default { name: 'channelList', components: { devicePlayer, - uiHeader, - Loading + uiHeader }, data() { return { @@ -209,13 +207,23 @@ let ssrc = res.data.ssrc; that.isLoging = false; if (!!ssrc) { - that.$refs.devicePlayer.play(res.data, deviceId, channelId, itemData.hasAudio); + // that.$refs.devicePlayer.play(res.data, deviceId, channelId, itemData.hasAudio); + that.$refs.devicePlayer.openDialog("media", deviceId, channelId,{ + streamInfo: res.data, + hasAudio: itemData.hasAudio + }); that.initData(); } else { that.$message.error(res.data); } }).catch(function (e) {}); }, + queryRecords: function (itemData) { + var format = moment().format("YYYY-M-D"); + let deviceId = this.deviceId; + let channelId = itemData.channelId; + this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date:format}) + }, stopDevicePush: function (itemData) { console.log(itemData) var that = this; diff --git a/web_src/src/components/gb28181/devicePlayer.vue b/web_src/src/components/gb28181/devicePlayer.vue index a86455c..8502ee1 100644 --- a/web_src/src/components/gb28181/devicePlayer.vue +++ b/web_src/src/components/gb28181/devicePlayer.vue @@ -1,123 +1,196 @@ <template> -<div id="devicePlayer"> - <el-dialog title="瑙嗛鎾斁" top="0" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()"> - <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :hasaudio="hasaudio" fluent autoplay live></LivePlayer> - <div id="shared" style="text-align: right; margin-top: 1rem;"> - <el-tabs v-model="tabActiveName"> - <el-tab-pane label="濯掍綋娴佷俊鎭�" name="media"> - <div style="margin-bottom: 0.5rem;"> - <el-button type="primary" size="small" @click="playRecord(true, '')">鎾斁</el-button> - <el-button type="primary" size="small" @click="startRecord()">褰曞埗</el-button> - <el-button type="primary" size="small" @click="stopRecord()">鍋滄褰曞埗</el-button> - </div> - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">鎾斁鍦板潃锛�</span> - <el-input v-model="getPlayerShared.sharedUrl" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedUrl)"></el-input> - </div> - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe锛�</span> - <el-input v-model="getPlayerShared.sharedIframe" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedIframe)"></el-input> - </div> - <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> - <span style="width: 5rem; line-height: 2.5rem; text-align: right;">璧勬簮鍦板潃锛�</span> - <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedRtmp)"></el-input> - </div> - </el-tab-pane> - <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> - <el-tab-pane label="褰曞儚鏌ヨ" name="second"> - <el-date-picker v-model="videoHistory.startTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="寮�濮嬫椂闂�" @change="recordList()"></el-date-picker> - <el-date-picker v-model="videoHistory.endTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="缁撴潫鏃堕棿" @change="recordList()"></el-date-picker> - <el-table :data="videoHistory.searchHistoryResult" style="width: 100%"> - <el-table-column label="鍚嶇О" prop="name" width="150"></el-table-column> - <el-table-column label="鏂囦欢" prop="filePath" width="300"></el-table-column> - <el-table-column label="寮�濮嬫椂闂�" prop="startTime" width="160"></el-table-column> - <el-table-column label="缁撴潫鏃堕棿" prop="endTime" width="160"></el-table-column> + <div id="devicePlayer"> + <el-dialog title="瑙嗛鎾斁" top="0" :close-on-click-modal="false" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="close()"> + <LivePlayer v-if="showVideoDialog" ref="videoPlayer" :videoUrl="videoUrl" :error="videoError" :hasaudio="hasaudio" fluent autoplay live ></LivePlayer> + <div id="shared" style="text-align: right; margin-top: 1rem;"> + <el-tabs v-model="tabActiveName"> + <el-tab-pane label="瀹炴椂瑙嗛" name="media"> + <div style="margin-bottom: 0.5rem;"> +<!-- <el-button type="primary" size="small" @click="playRecord(true, '')">鎾斁</el-button>--> +<!-- <el-button type="primary" size="small" @click="startRecord()">褰曞埗</el-button>--> +<!-- <el-button type="primary" size="small" @click="stopRecord()">鍋滄褰曞埗</el-button>--> + </div> + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">鎾斁鍦板潃锛�</span> + <el-input v-model="getPlayerShared.sharedUrl" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedUrl)"></el-input> + </div> + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">iframe锛�</span> + <el-input v-model="getPlayerShared.sharedIframe" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedIframe)"></el-input> + </div> + <div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;"> + <span style="width: 5rem; line-height: 2.5rem; text-align: right;">璧勬簮鍦板潃锛�</span> + <el-input v-model="getPlayerShared.sharedRtmp" :disabled="true" v-on:click.native="copySharedInfo(getPlayerShared.sharedRtmp)"></el-input> + </div> + </el-tab-pane> + <!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}--> + <el-tab-pane label="褰曞儚鏌ヨ" name="record"> + <el-date-picker size="mini" v-model="videoHistory.date" type="date" value-format="yyyy-MM-dd" placeholder="鏃ユ湡" + @change="queryRecords()"></el-date-picker> +<!-- <el-slider style="margin: 0 1rem 1rem 1rem;"--> +<!-- v-model="timeVal"--> +<!-- :min="timeMin"--> +<!-- :max="timeMax"--> +<!-- :step="5"--> +<!-- :marks="getTimeMakrs()"--> +<!-- :format-tooltip="formatTooltip">--> +<!-- </el-slider>--> +<!-- <range-slider :min="timeMin"--> +<!-- :max="timeMax"--> +<!-- :step="5"></range-slider>--> - <el-table-column label="鎿嶄綔"> - <template slot-scope="scope"> - <el-button type="primary" size="mini" @click="playRecord(false, scope.row)">鎾斁</el-button> - </template> - </el-table-column> - </el-table> - </el-tab-pane> - <!--閬ユ帶鐣岄潰--> - <el-tab-pane label="浜戝彴鎺у埗" name="third"> - <div style="display: flex; justify-content: center;"> - <div class="control-wrapper"> - <div class="control-btn control-top" @mousedown="ptzCamera(0, 1, 0)" @mouseup="ptzCamera(0, 0, 0)"> - <i class="el-icon-caret-top"></i> - <div class="control-inner-btn control-inner"></div> - </div> - <div class="control-btn control-left" @mousedown="ptzCamera(1, 0, 0)" @mouseup="ptzCamera(0, 0, 0)"> - <i class="el-icon-caret-left"></i> - <div class="control-inner-btn control-inner"></div> - </div> - <div class="control-btn control-bottom" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)"> - <i class="el-icon-caret-bottom"></i> - <div class="control-inner-btn control-inner"></div> - </div> - <div class="control-btn control-right" @mousedown="ptzCamera(2, 0, 0)" @mouseup="ptzCamera(0, 0, 0)"> - <i class="el-icon-caret-right"></i> - <div class="control-inner-btn control-inner"></div> - </div> - <div class="control-round"> - <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div> - </div> +<!-- <el-date-picker v-model="videoHistory.endTime" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" placeholder="缁撴潫鏃堕棿"--> +<!-- @change="recordList()"></el-date-picker>--> + <el-table :data="videoHistory.searchHistoryResult" height="150" v-load="recordsLoading"> + <el-table-column label="鍚嶇О" prop="name"></el-table-column> + <el-table-column label="鏂囦欢" prop="filePath"></el-table-column> + <el-table-column label="寮�濮嬫椂闂�" prop="startTime" :formatter="timeFormatter"></el-table-column> + <el-table-column label="缁撴潫鏃堕棿" prop="endTime" :formatter="timeFormatter"></el-table-column> - <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera(0, 0, 2)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-in" style="font-size: 1.875rem;"></i></div> - <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera(0, 0, 1)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-out"></i></div> - </div> - </div> + <el-table-column label="鎿嶄綔" > + <template slot-scope="scope"> + <el-button icon="el-icon-video-play" size="mini" @click="playRecord(scope.row)">鎾斁</el-button> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <!--閬ユ帶鐣岄潰--> + <el-tab-pane label="浜戝彴鎺у埗" name="control"> + <div style="display: flex; justify-content: center;"> + <div class="control-wrapper"> + <div class="control-btn control-top" @mousedown="ptzCamera(0, 1, 0)" @mouseup="ptzCamera(0, 0, 0)"> + <i class="el-icon-caret-top"></i> + <div class="control-inner-btn control-inner"></div> + </div> + <div class="control-btn control-left" @mousedown="ptzCamera(1, 0, 0)" @mouseup="ptzCamera(0, 0, 0)"> + <i class="el-icon-caret-left"></i> + <div class="control-inner-btn control-inner"></div> + </div> + <div class="control-btn control-bottom" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)"> + <i class="el-icon-caret-bottom"></i> + <div class="control-inner-btn control-inner"></div> + </div> + <div class="control-btn control-right" @mousedown="ptzCamera(2, 0, 0)" @mouseup="ptzCamera(0, 0, 0)"> + <i class="el-icon-caret-right"></i> + <div class="control-inner-btn control-inner"></div> + </div> + <div class="control-round"> + <div class="control-round-inner"><i class="fa fa-pause-circle"></i></div> + </div> + <div style="position: absolute; left: 7.25rem; top: 1.25rem" @mousedown="ptzCamera(0, 0, 2)" @mouseup="ptzCamera(0, 0, 0)"><i + class="el-icon-zoom-in" style="font-size: 1.875rem;"></i></div> + <div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;" @mousedown="ptzCamera(0, 0, 1)" + @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-out"></i></div> + </div> + </div> - </el-tab-pane> - </el-tabs> - </div> - </el-dialog> -</div> + </el-tab-pane> + </el-tabs> + </div> + </el-dialog> + </div> </template> <script> -import LivePlayer from '@liveqing/liveplayer' -export default { - name: 'devicePlayer', - props: {}, - components: { - LivePlayer - }, - computed: { - getPlayerShared: function () { - return { - sharedUrl: window.location.host + '/' + this.videoUrl, - sharedIframe: '<iframe src="' + window.location.host + '/' + this.videoUrl + '"></iframe>', - sharedRtmp: this.videoUrl - }; - } - }, - created() { - // this.videoHistory.searchHistoryResult = falsificationData.recordData.recordList; - }, - data() { + import LivePlayer from '@liveqing/liveplayer' + export default { + name: 'devicePlayer', + props: {}, + components: { + LivePlayer + }, + computed: { + getPlayerShared: function() { return { - video: 'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4', - videoUrl: '', - videoHistory: { - startTime: '', - endTime: '', - searchHistoryResult: [] //濯掍綋娴佸巻鍙茶褰曟悳绱㈢粨鏋� - }, - showVideoDialog: false, - normalssrc: '', - ssrc: '', - deviceId: '', - channelId: '', - tabActiveName: 'media', - hasaudio: false + sharedUrl: window.location.host + '/' + this.videoUrl, + sharedIframe: '<iframe src="' + window.location.host + '/' + this.videoUrl + '"></iframe>', + sharedRtmp: this.videoUrl + }; + } + }, + created() { + }, + data() { + return { + video:'http://lndxyj.iqilu.com/public/upload/2019/10/14/8c001ea0c09cdc59a57829dabc8010fa.mp4', + videoUrl: '', + videoHistory: { + date: '', + searchHistoryResult: [] //濯掍綋娴佸巻鍙茶褰曟悳绱㈢粨鏋� + }, + timeMakrs:{ + // 0 : "0:00", + // // 60 : "1:00", + // 120 : "2:00", + // // 180 : "3:00", + // 240 : "4:00", + // // 300 : "5:00", + // 360 : "6:00", + // // 420 : "7:00", + // 480 : "8:00", + // 540 : "9:00", + 600: "10:00", + // 660 : "11:00", + 720 : "12:00", + // 780 : "13:00", + 840 : "14:00", + // 900 : "15:00", + 960 : "16:00", + // 1020 : "17:00", + 1080 : "18:00", + // 1140 : "19:00", + // 1200 : "20:00", + // // 1260 : "21:00", + // 1320 : "22:00", + // // 1380 : "23:00", + // 1440 : "24:00" + }, + showVideoDialog: false, + ssrc: '', + deviceId: '', + channelId: '', + tabActiveName: 'media', + hasaudio: false, + loadingRecords: false, + recordsLoading: false, + timeVal: 0, + timeMin: 0, + timeMax: 1440, - }; - }, - methods: { + }; + }, + methods: { + openDialog: function (tab, deviceId, channelId, param) { + this.tabActiveName = tab; + this.channelId = channelId; + this.deviceId = deviceId; + this.ssrc = ""; + this.videoUrl = "" + if (!!this.$refs.videoPlayer) { + this.$refs.videoPlayer.pause(); + } - play: function (streamInfo, deviceId, channelId, hasAudio) { + switch(tab) { + case "media": + this.play(param.streamInfo, param.hasAudio) + break; + case "record": + this.showVideoDialog = true; + + this.videoHistory.date = param.date; + this.queryRecords() + break; + case "control": + break; + } + }, + timeAxisSelTime:function (val) { + console.log(val) + }, + getTimeMakrs(){ + return this.timeMakrs; + }, + play: function (streamInfo, hasAudio) { this.hasaudio = hasAudio; // 鏍规嵁濯掍綋娴佷俊鎭簩娆″垽鏂� if (!!streamInfo.tracks && streamInfo.tracks.length > 0) { @@ -130,8 +203,6 @@ this.hasaudio = realHasAudio && this.hasaudio; } this.ssrc = streamInfo.ssrc; - this.deviceId = deviceId; - this.channelId = channelId; // this.$refs.videoPlayer.hasaudio = hasAudio; // this.videoUrl = streamInfo.flv + "?" + new Date().getTime(); this.videoUrl = streamInfo.ws_flv; @@ -165,211 +236,276 @@ ); }, - recordList: function () { - if (!this.videoHistory.startTime || !this.videoHistory.endTime) { - return; - } - let that = this; - this.$axios({ - method: 'get', - url: '/api/record/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.videoHistory - .startTime + '&endTime=' + this.videoHistory.endTime - }).then(function (res) { - console.log(JSON.stringify(res)); - }).catch(function (e) { - // that.videoHistory.searchHistoryResult = falsificationData.recordData; - }); + queryRecords: function() { + if (!this.videoHistory.date) { + return; + } + this.recordsLoading = true; + let that = this; + var startTime = this.videoHistory.date + " 00:00:00"; + var endTime = this.videoHistory.date + " 23:59:59"; + this.$axios({ + method: 'get', + url: '/api/record/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime + }).then(function(res) { + // 澶勭悊鏃堕棿淇℃伅 + that.videoHistory.searchHistoryResult = res.data.recordList; + that.recordsLoading = false; + }).catch(function(e) { + // that.videoHistory.searchHistoryResult = falsificationData.recordData; + }); - }, - playRecord: function (isBackLive, rowData) { - let that = this; - if (isBackLive) { - this.videoUrl = this.getVideoUrlBySsrc(this.normalssrc); - return; - } - this.$axios({ - method: 'get', - url: '/api/playback/' + this.deviceId + '/' + this.channelId + '?startTime=' + rowData.startTime + '&endTime=' + - rowData.endTime - }).then(function (res) { - let ssrc = res.data.ssrc; - that.videoUrl = that.getVideoUrlBySsrc(ssrc); - //that.videoUrl='http://hls.cntv.kcdnvip.com/asp/hls/main/0303000a/3/default/f466089412c04a759c5515dbfcc3ac3d/main.m3u8?maxbr=2048'; - }); - - }, - ptzCamera: function (leftRight, upDown, zoom) { - console.log('浜戝彴鎺у埗锛�' + leftRight + ' : ' + upDown + " : " + zoom); - let that = this; - this.$axios({ - method: 'post', - url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown + - '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50' - }).then(function (res) {}); - }, - //////////////////////鎾斁鍣ㄤ簨浠跺鐞�////////////////////////// - videoError: function (e) { - console.log("鎾斁鍣ㄩ敊璇細" + JSON.stringify(e)); + }, + onTimeChange: function (video) { + // this.queryRecords() + }, + playRecord: function(row) { + let that = this; + if (that.ssrc != "") { + that.stopPlayRecord(function (){ + that.ssrc = "", + that.playRecord(row); + }) + }else { + this.$axios({ + method: 'get', + url: '/api/playback/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' + + row.endTime + }).then(function(res) { + var streamInfo = res.data; + that.ssrc = streamInfo.ssrc; + that.videoUrl = streamInfo.ws_flv; + }); } - } -}; + }, + stopPlayRecord: function (callback) { + this.$refs.videoPlayer.pause(); + this.videoUrl = ''; + this.$axios({ + method: 'get', + url: '/api/playback/' + this.ssrc + '/stop' + }).then(function(res) { + if (callback) callback() + }); + }, + ptzCamera: function(leftRight, upDown, zoom) { + console.log('浜戝彴鎺у埗锛�' + leftRight + ' : ' + upDown + " : " + zoom); + let that = this; + this.$axios({ + method: 'post', + url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown + + '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50' + }).then(function(res) {}); + }, + //////////////////////鎾斁鍣ㄤ簨浠跺鐞�////////////////////////// + videoError:function(e){ + console.log("鎾斁鍣ㄩ敊璇細"+JSON.stringify(e)); + }, + formatTooltip:function(val) { + var h = parseInt(val/60); + var hStr = h< 10 ? ("0" + h):h; + var s = val%60; + var sStr = s< 10 ? ("0" + s):s; + return h + ":" + sStr; + }, + timeFormatter: function (row, column, cellValue, index) { + return cellValue.split( " ")[1]; + }, + mergeTime: function (timeArray) { + var resultArray = []; + for (let i = 0; i < timeArray.length; i++) { + var startTime = new Date(timeArray[i].startTime); + var endTime = new Date(timeArray[i].endTime); + if (i ==0) { + resultArray[0] = { + startTime: startTime, + endTime: endTime + } + } + for (let j = 0; j < resultArray.length; j++) { + if (startTime > resultArray[j].endTime ) { // 鍚堝苟 + if (startTime - resultArray[j].endTime <= 1000){ + resultArray[j].endTime = endTime; + }else { + resultArray[resultArray.length] = { + startTime: startTime, + endTime: endTime + } + } + }else if(resultArray[j].startTime > endTime ) { // 鍚堝苟 + if (resultArray[j].startTime - endTime <= 1000) { + resultArray[j].startTime = startTime; + }else { + resultArray[resultArray.length] = { + startTime: startTime, + endTime: endTime + } + } + } + } + } + console.log(resultArray) + return resultArray; + } + } + }; </script> <style> -.control-wrapper { - position: relative; - width: 6.25rem; - height: 6.25rem; - max-width: 6.25rem; - max-height: 6.25rem; - margin: 0 auto; - border-radius: 100%; - float: left; -} + .control-wrapper { + position: relative; + width: 6.25rem; + height: 6.25rem; + max-width: 6.25rem; + max-height: 6.25rem; + margin: 0 auto; + border-radius: 100%; + float: left; + } -.control-btn { - display: flex; - justify-content: center; - position: absolute; - width: 44%; - height: 44%; - border-radius: 5px; - border: 1px solid #78aee4; - box-sizing: border-box; - transition: all 0.3s linear; -} + .control-btn { + display: flex; + justify-content: center; + position: absolute; + width: 44%; + height: 44%; + border-radius: 5px; + border: 1px solid #78aee4; + box-sizing: border-box; + transition: all 0.3s linear; + } -.control-btn i { - font-size: 20px; - color: #78aee4; - display: flex; - justify-content: center; - align-items: center; -} + .control-btn i { + font-size: 20px; + color: #78aee4; + display: flex; + justify-content: center; + align-items: center; + } -.control-round { - position: absolute; - top: 21%; - left: 21%; - width: 58%; - height: 58%; - background: #fff; - border-radius: 100%; -} + .control-round { + position: absolute; + top: 21%; + left: 21%; + width: 58%; + height: 58%; + background: #fff; + border-radius: 100%; + } -.control-round-inner { - position: absolute; - left: 15%; - top: 15%; - display: flex; - justify-content: center; - align-items: center; - width: 70%; - height: 70%; - font-size: 40px; - color: #78aee4; - border: 1px solid #78aee4; - border-radius: 100%; - transition: all 0.3s linear; -} + .control-round-inner { + position: absolute; + left: 15%; + top: 15%; + display: flex; + justify-content: center; + align-items: center; + width: 70%; + height: 70%; + font-size: 40px; + color: #78aee4; + border: 1px solid #78aee4; + border-radius: 100%; + transition: all 0.3s linear; + } -.control-inner-btn { - position: absolute; - width: 60%; - height: 60%; - background: #fafafa; -} + .control-inner-btn { + position: absolute; + width: 60%; + height: 60%; + background: #fafafa; + } -.control-top { - top: -8%; - left: 27%; - transform: rotate(-45deg); - border-radius: 5px 100% 5px 0; -} + .control-top { + top: -8%; + left: 27%; + transform: rotate(-45deg); + border-radius: 5px 100% 5px 0; + } -.control-top i { - transform: rotate(45deg); - border-radius: 5px 100% 5px 0; -} + .control-top i { + transform: rotate(45deg); + border-radius: 5px 100% 5px 0; + } -.control-top .control-inner { - left: -1px; - bottom: 0; - border-top: 1px solid #78aee4; - border-right: 1px solid #78aee4; - border-radius: 0 100% 0 0; -} + .control-top .control-inner { + left: -1px; + bottom: 0; + border-top: 1px solid #78aee4; + border-right: 1px solid #78aee4; + border-radius: 0 100% 0 0; + } -.control-top .fa { - transform: rotate(45deg) translateY(-7px); -} + .control-top .fa { + transform: rotate(45deg) translateY(-7px); + } -.control-left { - top: 27%; - left: -8%; - transform: rotate(45deg); - border-radius: 5px 0 5px 100%; -} + .control-left { + top: 27%; + left: -8%; + transform: rotate(45deg); + border-radius: 5px 0 5px 100%; + } -.control-left i { - transform: rotate(-45deg); -} + .control-left i { + transform: rotate(-45deg); + } -.control-left .control-inner { - right: -1px; - top: -1px; - border-bottom: 1px solid #78aee4; - border-left: 1px solid #78aee4; - border-radius: 0 0 0 100%; -} + .control-left .control-inner { + right: -1px; + top: -1px; + border-bottom: 1px solid #78aee4; + border-left: 1px solid #78aee4; + border-radius: 0 0 0 100%; + } -.control-left .fa { - transform: rotate(-45deg) translateX(-7px); -} + .control-left .fa { + transform: rotate(-45deg) translateX(-7px); + } -.control-right { - top: 27%; - right: -8%; - transform: rotate(45deg); - border-radius: 5px 100% 5px 0; -} + .control-right { + top: 27%; + right: -8%; + transform: rotate(45deg); + border-radius: 5px 100% 5px 0; + } -.control-right i { - transform: rotate(-45deg); -} + .control-right i { + transform: rotate(-45deg); + } -.control-right .control-inner { - left: -1px; - bottom: -1px; - border-top: 1px solid #78aee4; - border-right: 1px solid #78aee4; - border-radius: 0 100% 0 0; -} + .control-right .control-inner { + left: -1px; + bottom: -1px; + border-top: 1px solid #78aee4; + border-right: 1px solid #78aee4; + border-radius: 0 100% 0 0; + } -.control-right .fa { - transform: rotate(-45deg) translateX(7px); -} + .control-right .fa { + transform: rotate(-45deg) translateX(7px); + } -.control-bottom { - left: 27%; - bottom: -8%; - transform: rotate(45deg); - border-radius: 0 5px 100% 5px; -} + .control-bottom { + left: 27%; + bottom: -8%; + transform: rotate(45deg); + border-radius: 0 5px 100% 5px; + } -.control-bottom i { - transform: rotate(-45deg); -} + .control-bottom i { + transform: rotate(-45deg); + } -.control-bottom .control-inner { - top: -1px; - left: -1px; - border-bottom: 1px solid #78aee4; - border-right: 1px solid #78aee4; - border-radius: 0 0 100% 0; -} + .control-bottom .control-inner { + top: -1px; + left: -1px; + border-bottom: 1px solid #78aee4; + border-right: 1px solid #78aee4; + border-radius: 0 0 100% 0; + } -.control-bottom .fa { - transform: rotate(-45deg) translateY(7px); -} + .control-bottom .fa { + transform: rotate(-45deg) translateY(7px); + } </style> diff --git a/web_src/src/main.js b/web_src/src/main.js index 1b31f7b..6f88c2a 100644 --- a/web_src/src/main.js +++ b/web_src/src/main.js @@ -6,8 +6,8 @@ import router from './router/index.js'; import axios from 'axios'; import VueCookies from 'vue-cookies'; - import echarts from 'echarts'; + import VueClipboard from 'vue-clipboard2' Vue.use(VueClipboard) Vue.use(ElementUI); -- Gitblit v1.8.0