添加发送媒体流, 添加媒体服务器节点管理ui,修复修改密码

This commit is contained in:
648540858 2021-09-25 22:12:15 +08:00
parent acd2347bea
commit 9d4d968eaa
30 changed files with 890 additions and 47 deletions

View File

@ -140,6 +140,7 @@ create table media_server
streamNoneReaderDelayMS int not null,
rtpEnable int not null,
rtpPortRange varchar(50) not null,
sendRtpPortRange varchar(50) not null,
recordAssistPort int not null,
defaultServer int not null,
createTime varchar(50) not null,

View File

@ -18,6 +18,9 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
/**
* @author lin
*/
@WebFilter(filterName = "ApiAccessFilter", urlPatterns = "/api/*", asyncSupported=true)
public class ApiAccessFilter extends OncePerRequestFilter {

View File

@ -68,6 +68,10 @@ public class MediaConfig{
@Value("${media.rtp.port-range}")
private String rtpPortRange;
@Value("${media.rtp.send-port-range}")
private String sendRtpPortRange;
@Value("${media.record-assist-port:0}")
private Integer recordAssistPort = 0;
@ -165,6 +169,14 @@ public class MediaConfig{
}
}
public String getSipDomain() {
return sipDomain;
}
public String getSendRtpPortRange() {
return sendRtpPortRange;
}
public MediaServerItem getMediaSerItem(){
MediaServerItem mediaServerItem = new MediaServerItem();
mediaServerItem.setId(id);
@ -185,6 +197,7 @@ public class MediaConfig{
mediaServerItem.setStreamNoneReaderDelayMS(streamNoneReaderDelayMS);
mediaServerItem.setRtpEnable(rtpEnable);
mediaServerItem.setRtpPortRange(rtpPortRange);
mediaServerItem.setSendRtpPortRange(sendRtpPortRange);
mediaServerItem.setRecordAssistPort(recordAssistPort);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

View File

@ -21,6 +21,9 @@ import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.ConnectException;
/**
* @author lin
*/
@SuppressWarnings(value = {"rawtypes", "unchecked"})
@Configuration
public class ProxyServletConfig {
@ -35,7 +38,7 @@ public class ProxyServletConfig {
@Bean
public ServletRegistrationBean zlmServletRegistrationBean(){
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZLMProxySerlet(),"/zlm/*");
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZlmProxyServlet(),"/zlm/*");
servletRegistrationBean.setName("zlm_Proxy");
servletRegistrationBean.addInitParameter("targetUri", "http://127.0.0.1:6080");
servletRegistrationBean.addUrlMappings();
@ -45,7 +48,7 @@ public class ProxyServletConfig {
return servletRegistrationBean;
}
class ZLMProxySerlet extends ProxyServlet{
class ZlmProxyServlet extends ProxyServlet{
@Override
protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) {
String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString);

View File

@ -8,6 +8,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.HashMap;
import java.util.Map;
@ -44,8 +45,15 @@ public class ZLMRTPServerFactory {
Map<String, Object> param = new HashMap<>();
int result = -1;
int newPort = getPortFromportRange(mediaServerItem);
param.put("port", newPort);
/**
* 不设置推流端口端则使用随机端口
*/
if (StringUtils.isEmpty(mediaServerItem.getSendRtpPortRange())){
param.put("port", 0);
}else {
int newPort = getPortFromportRange(mediaServerItem);
param.put("port", newPort);
}
param.put("enable_tcp", 1);
param.put("stream_id", streamId);
JSONObject openRtpServerResultJson = zlmresTfulUtils.openRtpServer(mediaServerItem, param);
@ -53,24 +61,24 @@ public class ZLMRTPServerFactory {
if (openRtpServerResultJson != null) {
switch (openRtpServerResultJson.getInteger("code")){
case 0:
result= newPort;
result= openRtpServerResultJson.getInteger("port");
break;
case -300: // id已经存在, 可能已经在其他端口推流
Map<String, Object> closeRtpServerParam = new HashMap<>();
closeRtpServerParam.put("stream_id", streamId);
zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam);
result = newPort;
result = createRTPServer(mediaServerItem, streamId);;
break;
case -400: // 端口占用
result= createRTPServer(mediaServerItem, streamId);
break;
default:
logger.error("创建RTP Server 失败 {}: " + openRtpServerResultJson.getString("msg"), newPort);
logger.error("创建RTP Server 失败 {}: " + openRtpServerResultJson.getString("msg"), param.get("port"));
break;
}
}else {
// 检查ZLM状态
logger.error("创建RTP Server 失败 {}: 请检查ZLM服务", newPort);
logger.error("创建RTP Server 失败 {}: 请检查ZLM服务", param.get("port"));
}
return result;
}
@ -98,7 +106,7 @@ public class ZLMRTPServerFactory {
private int getPortFromportRange(MediaServerItem mediaServerItem) {
int currentPort = mediaServerItem.getCurrentPort();
if (currentPort == 0) {
String[] portRangeStrArray = mediaServerItem.getRtpPortRange().split(",");
String[] portRangeStrArray = mediaServerItem.getSendRtpPortRange().split(",");
portRangeArray[0] = Integer.parseInt(portRangeStrArray[0]);
portRangeArray[1] = Integer.parseInt(portRangeStrArray[1]);
}
@ -229,7 +237,9 @@ public class ZLMRTPServerFactory {
*/
public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) {
JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId);
if (mediaInfo == null) return 0;
if (mediaInfo == null) {
return 0;
}
return mediaInfo.getInteger("totalReaderCount");
}

View File

@ -108,8 +108,10 @@ public class ZLMRunner implements CommandLineRunner {
}
public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) {
if (startGetMedia == null) return null;
if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) return null;
if (startGetMedia == null) { return null;}
if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) {
return null;
}
JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
ZLMServerConfig ZLMServerConfig = null;
if (responseJSON != null) {

View File

@ -41,14 +41,20 @@ public class MediaServerItem{
private boolean rtpEnable;
private boolean status;
private String rtpPortRange;
private String sendRtpPortRange;
private int recordAssistPort;
private String createTime;
private String updateTime;
private String lastKeepaliveTime;
private boolean defaultServer;
private SsrcConfig ssrcConfig;
@ -82,6 +88,7 @@ public class MediaServerItem{
secret = zlmServerConfig.getApiSecret();
streamNoneReaderDelayMS = zlmServerConfig.getGeneralStreamNoneReaderDelayMS();
rtpEnable = false; // 默认使用单端口;直到用户自己设置开启多端口
rtpPortRange = "30000,30500"; // 默认使用30000,30500作为级联时发送流的端口号
recordAssistPort = 0; // 默认关闭
}
@ -278,5 +285,27 @@ public class MediaServerItem{
this.currentPort = currentPort;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getLastKeepaliveTime() {
return lastKeepaliveTime;
}
public void setLastKeepaliveTime(String lastKeepaliveTime) {
this.lastKeepaliveTime = lastKeepaliveTime;
}
public String getSendRtpPortRange() {
return sendRtpPortRange;
}
public void setSendRtpPortRange(String sendRtpPortRange) {
this.sendRtpPortRange = sendRtpPortRange;
}
}

View File

@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import java.util.List;
@ -49,7 +50,11 @@ public interface IMediaServerService {
void clearMediaServerForOnline();
void add(MediaServerItem mediaSerItem);
WVPResult<String> add(MediaServerItem mediaSerItem);
void resetOnlineServerItem(MediaServerItem serverItem);
WVPResult<MediaServerItem> checkMediaServer(String ip, int port, String secret);
boolean checkMediaRecordServer(String ip, int port);
}

View File

@ -1,5 +1,6 @@
package com.genersoft.iot.vmp.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
@ -14,10 +15,11 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig;
import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.service.bean.SSRCInfo;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.storager.dao.MediaServerMapper;
import com.genersoft.iot.vmp.utils.redis.JedisUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -56,9 +58,6 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
@Autowired
private MediaServerMapper mediaServerMapper;
@Autowired
private IRedisCatchStorage redisCatchStorage;
@Autowired
private VideoStreamSessionManager streamSession;
@ -97,7 +96,9 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
@Override
public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId) {
if (mediaServerItem == null || mediaServerItem.getId() == null) return null;
if (mediaServerItem == null || mediaServerItem.getId() == null) {
return null;
}
// 获取mediaServer可用的ssrc
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerItem.getId();
@ -107,7 +108,9 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
return null;
}else {
String ssrc = ssrcConfig.getPlaySsrc();
if (streamId == null) streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
if (streamId == null) {
streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase();
}
int rtpServerPort = mediaServerItem.getRtpProxyPort();
if (mediaServerItem.isRtpEnable()) {
rtpServerPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId);
@ -131,7 +134,9 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
@Override
public void releaseSsrc(MediaServerItem mediaServerItem, String ssrc) {
if (mediaServerItem == null || ssrc == null) return;
if (mediaServerItem == null || ssrc == null) {
return;
}
SsrcConfig ssrcConfig = mediaServerItem.getSsrcConfig();
ssrcConfig.releaseSsrc(ssrc);
mediaServerItem.setSsrcConfig(ssrcConfig);
@ -141,7 +146,6 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
/**
* zlm 重启后重置他的推流信息 TODO 给正在使用的设备发送停止命令
* @param mediaServerItem
*/
@Override
public void clearRTPServer(MediaServerItem mediaServerItem) {
@ -174,9 +178,15 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
public List<MediaServerItem> getAll() {
List<MediaServerItem> result = new ArrayList<>();
List<Object> mediaServerKeys = redisUtil.scan(String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX));
for (int i = 0; i < mediaServerKeys.size(); i++) {
String key = (String) mediaServerKeys.get(i);
result.add((MediaServerItem)redisUtil.get(key));
String onlineKey = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
for (Object mediaServerKey : mediaServerKeys) {
String key = (String) mediaServerKey;
MediaServerItem mediaServerItem = (MediaServerItem) redisUtil.get(key);
// 检查状态
if (redisUtil.zScore(onlineKey, mediaServerItem.getId()) != null) {
mediaServerItem.setStatus(true);
}
result.add(mediaServerItem);
}
return result;
}
@ -208,7 +218,9 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
*/
@Override
public MediaServerItem getOne(String mediaServerId) {
if (mediaServerId == null) return null;
if (mediaServerId == null) {
return null;
}
String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + mediaServerId;
return (MediaServerItem)redisUtil.get(key);
}
@ -225,8 +237,34 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
}
@Override
public void add(MediaServerItem mediaSerItem) {
mediaServerMapper.add(mediaSerItem);
public WVPResult<String> add(MediaServerItem mediaServerItem) {
WVPResult<String> result = new WVPResult<>();
mediaServerItem.setCreateTime(this.format.format(System.currentTimeMillis()));
mediaServerItem.setUpdateTime(this.format.format(System.currentTimeMillis()));
JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
if (responseJSON != null) {
JSONArray data = responseJSON.getJSONArray("data");
if (data != null && data.size() > 0) {
ZLMServerConfig zlmServerConfig= JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) {
result.setCode(-1);
result.setMsg("保存失败媒体服务ID [ " + zlmServerConfig.getGeneralMediaServerId() + " ] 已存在,请修改媒体服务器配置");
return result;
}
zlmServerConfig.setIp(mediaServerItem.getIp());
handLeZLMServerConfig(zlmServerConfig);
result.setCode(0);
result.setMsg("success");
}else {
result.setCode(-1);
result.setMsg("连接失败");
}
}else {
result.setCode(-1);
result.setMsg("连接失败");
}
return result;
}
/**
@ -249,13 +287,27 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
// docker部署不会使用zlm配置的端口号不是默认的则不做更新 配置修改需要自行修改server配置;
MediaServerItem serverItemFromConfig = mediaConfig.getMediaSerItem();
serverItemFromConfig.setId(zlmServerConfig.getGeneralMediaServerId());
if (mediaConfig.getHttpPort() == 0) serverItemFromConfig.setHttpPort(zlmServerConfig.getHttpPort());
if (mediaConfig.getHttpSSlPort() == 0) serverItemFromConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
if (mediaConfig.getRtmpPort() == 0) serverItemFromConfig.setRtmpPort(zlmServerConfig.getRtmpPort());
if (mediaConfig.getRtmpSSlPort() == 0) serverItemFromConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
if (mediaConfig.getRtspPort() == 0) serverItemFromConfig.setRtspPort(zlmServerConfig.getRtspPort());
if (mediaConfig.getRtspSSLPort() == 0) serverItemFromConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
if (mediaConfig.getRtpProxyPort() == 0) serverItemFromConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
if (mediaConfig.getHttpPort() == 0) {
serverItemFromConfig.setHttpPort(zlmServerConfig.getHttpPort());
}
if (mediaConfig.getHttpSSlPort() == 0) {
serverItemFromConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport());
}
if (mediaConfig.getRtmpPort() == 0) {
serverItemFromConfig.setRtmpPort(zlmServerConfig.getRtmpPort());
}
if (mediaConfig.getRtmpSSlPort() == 0) {
serverItemFromConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
}
if (mediaConfig.getRtspPort() == 0) {
serverItemFromConfig.setRtspPort(zlmServerConfig.getRtspPort());
}
if (mediaConfig.getRtspSSLPort() == 0) {
serverItemFromConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
}
if (mediaConfig.getRtpProxyPort() == 0) {
serverItemFromConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
}
if (serverItem != null){
mediaServerMapper.delDefault();
mediaServerMapper.add(serverItemFromConfig);
@ -319,9 +371,10 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
@Override
public void addCount(String mediaServerId) {
if (mediaServerId == null) return;
if (mediaServerId == null) {
return;
}
String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX;
Double aDouble = redisUtil.zScore(key, mediaServerId);
redisUtil.zIncrScore(key, mediaServerId, 1);
}
@ -399,4 +452,71 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
}
@Override
public WVPResult<MediaServerItem> checkMediaServer(String ip, int port, String secret) {
WVPResult<MediaServerItem> result = new WVPResult<>();
if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) {
result.setCode(-1);
result.setMsg("此连接已存在");
return result;
}
MediaServerItem mediaServerItem = new MediaServerItem();
mediaServerItem.setIp(ip);
mediaServerItem.setHttpPort(port);
mediaServerItem.setSecret(secret);
JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem);
if (responseJSON == null) {
result.setCode(-1);
result.setMsg("连接失败");
return result;
}
JSONArray data = responseJSON.getJSONArray("data");
ZLMServerConfig zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class);
if (zlmServerConfig == null) {
result.setCode(-1);
result.setMsg("读取配置失败");
return result;
}
if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) {
result.setCode(-1);
result.setMsg("媒体服务ID [" + zlmServerConfig.getGeneralMediaServerId() + " ] 已存在,请修改媒体服务器配置");
return result;
}
mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpPort());
mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort());
mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort());
mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort());
mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport());
mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort());
mediaServerItem.setStreamIp(ip);
mediaServerItem.setHookIp(sipConfig.getIp());
mediaServerItem.setSdpIp(ip);
mediaServerItem.setStreamNoneReaderDelayMS(zlmServerConfig.getGeneralStreamNoneReaderDelayMS());
result.setCode(0);
result.setMsg("成功");
result.setData(mediaServerItem);
return result;
}
@Override
public boolean checkMediaRecordServer(String ip, int port) {
boolean result = false;
OkHttpClient client = new OkHttpClient();
String url = String.format("http://%s:%s/index/api/record", ip, port);
FormBody.Builder builder = new FormBody.Builder();
Request request = new Request.Builder()
.get()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
if (response != null) {
result = true;
}
} catch (Exception e) {}
return result;
}
}

View File

@ -32,6 +32,7 @@ public interface MediaServerMapper {
"streamNoneReaderDelayMS, " +
"rtpEnable, " +
"rtpPortRange, " +
"sendRtpPortRange, " +
"recordAssistPort, " +
"defaultServer, " +
"createTime, " +
@ -55,6 +56,7 @@ public interface MediaServerMapper {
"${streamNoneReaderDelayMS}, " +
"${rtpEnable}, " +
"'${rtpPortRange}', " +
"'${sendRtpPortRange}', " +
"${recordAssistPort}, " +
"${defaultServer}, " +
"'${createTime}', " +
@ -79,6 +81,7 @@ public interface MediaServerMapper {
"<if test=\"streamNoneReaderDelayMS != null\">, streamNoneReaderDelayMS=${streamNoneReaderDelayMS}</if>" +
"<if test=\"rtpEnable != null\">, rtpEnable=${rtpEnable}</if>" +
"<if test=\"rtpPortRange != null\">, rtpPortRange='${rtpPortRange}'</if>" +
"<if test=\"sendRtpPortRange != null\">, sendRtpPortRange='${sendRtpPortRange}'</if>" +
"<if test=\"secret != null\">, secret='${secret}'</if>" +
"<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" +
"WHERE id='${id}'"+

View File

@ -57,7 +57,9 @@ public class ServerController {
@ApiOperation("流媒体服务列表")
@GetMapping(value = "/media_server/list")
@ResponseBody
public WVPResult<List<MediaServerItem>> getMediaServerList(){
public WVPResult<List<MediaServerItem>> getMediaServerList(boolean detail){
List<MediaServerItem> all = mediaServerService.getAll();
WVPResult<List<MediaServerItem>> result = new WVPResult<>();
result.setCode(0);
result.setMsg("success");
@ -87,6 +89,60 @@ public class ServerController {
return result;
}
@ApiOperation("测试流媒体服务")
@ApiImplicitParams({
@ApiImplicitParam(name="ip", value = "流媒体服务IP", dataTypeClass = String.class),
@ApiImplicitParam(name="port", value = "流媒体服务HTT端口", dataTypeClass = Integer.class),
@ApiImplicitParam(name="secret", value = "流媒体服务secret", dataTypeClass = String.class),
})
@GetMapping(value = "/media_server/check")
@ResponseBody
public WVPResult<MediaServerItem> checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret){
return mediaServerService.checkMediaServer(ip, port, secret);
}
@ApiOperation("测试流媒体录像管理服务")
@ApiImplicitParams({
@ApiImplicitParam(name="ip", value = "流媒体服务IP", dataTypeClass = String.class),
@ApiImplicitParam(name="port", value = "流媒体服务HTT端口", dataTypeClass = Integer.class),
@ApiImplicitParam(name="secret", value = "流媒体服务secret", dataTypeClass = String.class),
})
@GetMapping(value = "/media_server/record/check")
@ResponseBody
public WVPResult<String> checkMediaRecordServer(@RequestParam String ip, @RequestParam int port){
boolean checkResult = mediaServerService.checkMediaRecordServer(ip, port);
WVPResult<String> result = new WVPResult<>();
if (checkResult) {
result.setCode(0);
result.setMsg("success");
}else {
result.setCode(-1);
result.setMsg("连接失败");
}
return result;
}
@ApiOperation("保存流媒体服务")
@ApiImplicitParams({
@ApiImplicitParam(name="mediaServerItem", value = "流媒体信息", dataTypeClass = MediaServerItem.class)
})
@PostMapping(value = "/media_server/save")
@ResponseBody
public WVPResult<String> checkMediaServer(@RequestBody MediaServerItem mediaServerItem){
if (mediaServerService.getOne(mediaServerItem.getId()) != null) {
mediaServerService.update(mediaServerItem);
}else {
return mediaServerService.add(mediaServerItem);
}
WVPResult<String> result = new WVPResult<>();
result.setCode(0);
result.setMsg("success");
return result;
}
@ApiOperation("重启服务")
@GetMapping(value = "/restart")
@ResponseBody
@ -155,6 +211,8 @@ public class ServerController {
case "base":
jsonObject.put("base", userSetup);
break;
default:
break;
}
}
result.setData(jsonObject);

View File

@ -119,6 +119,8 @@ media:
enable: true
# [可选] 在此范围内选择端口用于媒体流传输,
port-range: 30000,30500 # 端口范围
# [可选] 国标级联在此范围内选择端口发送媒体流,
send-port-range: 30000,30500 # 端口范围
# 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载 0 表示不使用
record-assist-port: 0

View File

@ -63,6 +63,8 @@ media:
enable: true
# [可选] 在此范围内选择端口用于媒体流传输,
port-range: 30000,30500 # 端口范围
# [可选] 国标级联在此范围内选择端口发送媒体流,
send-port-range: 30000,30500 # 端口范围
# 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载 0 表示不使用
record-assist-port: 0

Binary file not shown.

View File

@ -27,6 +27,7 @@ module.exports = {
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'@static': resolve('static'),
}
},
module: {

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -111,7 +111,7 @@
},
getMediaServerList: function (){
let that = this;
that.mediaServerObj.getMediaServerList((data)=>{
that.mediaServerObj.getOnlineMediaServerList((data)=>{
that.mediaServerList = data.data;
if (that.mediaServerList.length > 0) {
that.mediaServerId = that.mediaServerList[0].id

View File

@ -60,7 +60,7 @@
<el-button-group>
<el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button>
<el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button>
<el-button size="mini" icon="el-icon-delete" type="primary" @click="edit(scope.row)">编辑</el-button>
<el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button>
<el-button size="mini" icon="el-icon-delete" type="danger" v-if="scope.row.online==0" @click="deleteDevice(scope.row)">删除</el-button>
</el-button-group>
</template>

View File

@ -0,0 +1,159 @@
<template>
<div id="mediaServerManger">
<el-container>
<el-header>
<uiHeader></uiHeader>
</el-header>
<el-main id="msMain">
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;">
<span style="font-size: 1rem; font-weight: bold;">节点列表</span>
</div>
<div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;">
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="add">添加节点</el-button>
</div>
<el-row :gutter="12">
<el-col :span="num" v-for="item in mediaServerList" :key="item.id">
<el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card">
<div class="card-img-zlm"></div>
<div style="padding: 14px;text-align: left">
<span style="font-size: 16px">{{item.id}}</span>
<div style="margin-top: 13px; line-height: 12px; ">
<span style="font-size: 14px; color: #999; margin-top: 5px">创建时间 {{item.createTime}}</span>
<el-button icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">编辑</el-button>
</div>
</div>
<i v-if="item.status" class="iconfont icon-online server-card-status-online" title="在线"></i>
<i v-if="!item.status" class="iconfont icon-online server-card-status-offline" title="离线"></i>
</el-card>
</el-col>
</el-row>
<mediaServerEdit ref="mediaServerEdit" ></mediaServerEdit>
</el-main>
</el-container>
</div>
</template>
<script>
import uiHeader from './UiHeader.vue'
import MediaServer from './service/MediaServer'
import mediaServerEdit from './dialog/MediaServerEdit'
export default {
name: 'mediaServerManger',
components: {
uiHeader,mediaServerEdit
},
data() {
return {
mediaServerObj : new MediaServer(),
mediaServerList: [], //
winHeight: window.innerHeight - 200,
updateLooper: false,
currentPage:1,
count:15,
num: this.getNumberByWidth(),
total:0,
};
},
computed: {
},
mounted() {
this.initData();
this.updateLooper = setInterval(this.initData, 2000);
},
destroyed() {
clearTimeout(this.updateLooper);
},
methods: {
initData: function() {
this.getServerList()
},
currentChange: function(val){
this.currentPage = val;
this.getServerList();
},
handleSizeChange: function(val){
this.count = val;
this.getServerList();
},
getServerList: function(){
this.mediaServerObj.getMediaServerList((data)=>{
this.mediaServerList = data.data;
})
},
add: function (){
this.$refs.mediaServerEdit.openDialog(null, this.initData)
},
edit: function (row){
this.$refs.mediaServerEdit.openDialog(row, this.initData)
},
getNumberByWidth(){
let candidateNums = [1, 2, 3, 4, 6, 8, 12, 24]
let clientWidth = window.innerWidth - 30;
let interval = 20;
let itemWidth = 360;
let num = (clientWidth + interval)/(itemWidth + interval)
let result = Math.ceil(24/num);
let resultVal = 24;
for (let i = 0; i < candidateNums.length; i++) {
let value = candidateNums[i]
if (i + 1 >= candidateNums.length) {
return 24;
}
if (value <= result && candidateNums[i + 1] > result ) {
return value;
}
}
console.log("aadada: "+ resultVal)
return resultVal;
},
dateFormat: function(/** timestamp=0 **/) {
var ts = arguments[0] || 0;
var t,y,m,d,h,i,s;
t = ts ? new Date(ts*1000) : new Date();
y = t.getFullYear();
m = t.getMonth()+1;
d = t.getDate();
h = t.getHours();
i = t.getMinutes();
s = t.getSeconds();
//
return y+'-'+(m<10?'0'+m:m)+'-'+(d<10?'0'+d:d)+' '+(h<10?'0'+h:h)+':'+(i<10?'0'+i:i)+':'+(s<10?'0'+s:s);
}
}
};
</script>
<style>
.server-card{
position: relative;
margin-bottom: 20px;
}
.card-img-zlm{
width: 200px; height: 200px;
background: url('~@static/images/zlm-logo.png') no-repeat center;
background-position: center;
background-size: contain;
margin: 0 auto;
}
.server-card-status-online{
position: absolute;
right: 20px;
top: 20px;
color: #3caf36;
font-size: 18px;
}
.server-card-status-offline{
position: absolute;
right: 20px;
top: 20px;
color: #808080;
font-size: 18px;
}
.server-card:hover {
border: 1px solid #adadad;
}
</style>

View File

@ -6,6 +6,7 @@
<el-menu-item index="/pushVideoList">推流列表</el-menu-item>
<el-menu-item index="/streamProxyList">拉流代理</el-menu-item>
<el-menu-item index="/cloudRecord">云端录像</el-menu-item>
<el-menu-item index="/mediaServerManger">节点管理</el-menu-item>
<el-menu-item index="/parentPlatformList/15/1">国标级联</el-menu-item>
<el-menu-item @click="openDoc">在线文档</el-menu-item>
<!-- <el-submenu index="/setting">-->

View File

@ -139,7 +139,7 @@ export default {
this.initTable();
this.updateData();
this.chartInterval = setInterval(this.updateData, 3000);
this.mediaServer.getMediaServerList((data)=>{
this.mediaServer.getOnlineMediaServerList((data)=>{
this.mediaServerList = data.data;
if (this.mediaServerList && this.mediaServerList.length > 0) {
this.mediaServerChoose = this.mediaServerList[0].id

View File

@ -0,0 +1,368 @@
<template>
<div id="mediaServerEdit" v-loading="isLoging">
<el-dialog
title="媒体节点"
:width="dialogWidth"
top="2rem"
:close-on-click-modal="false"
:visible.sync="showDialog"
:destroy-on-close="true"
@close="close()"
>
<div id="formStep" style="margin-top: 1rem; margin-right: 20px;">
<el-form v-if="currentStep == 1" ref="mediaServerForm" :rules="rules" :model="mediaServerForm" label-width="140px" >
<el-form-item label="IP" prop="ip">
<el-input v-model="mediaServerForm.ip" placeholder="媒体服务IP" clearable></el-input>
</el-form-item>
<el-form-item label="HTTP端口" prop="port">
<el-input v-model="mediaServerForm.httpPort" placeholder="媒体服务HTTP端口" clearable></el-input>
</el-form-item>
<el-form-item label="SECRET" prop="secret">
<el-input v-model="mediaServerForm.secret" placeholder="媒体服务SECRET" clearable></el-input>
</el-form-item>
<el-form-item>
<div style="float: right;">
<el-button type="primary" v-if="currentStep === 1 && serverCheck === 1" @click="next" >下一步</el-button>
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="checkServer" >测试</el-button>
<i v-if="serverCheck === 1" class="el-icon-success" style="color: #3caf36"></i>
<i v-if="serverCheck === -1" class="el-icon-error" style="color: #c80000"></i>
</div>
</el-form-item>
</el-form>
<el-row :gutter="24">
<el-col :span="12">
<el-form v-if="currentStep === 2 || currentStep === 3" ref="mediaServerForm1" :rules="rules" :model="mediaServerForm" label-width="140px" >
<el-form-item label="IP" prop="ip">
<el-input v-if="currentStep === 2" v-model="mediaServerForm.ip" disabled></el-input>
<el-input v-if="currentStep === 3" v-model="mediaServerForm.ip"></el-input>
</el-form-item>
<el-form-item label="HTTP端口" prop="port">
<el-input v-if="currentStep === 2" v-model="mediaServerForm.httpPort" disabled></el-input>
<el-input v-if="currentStep === 3" v-model="mediaServerForm.httpPort"></el-input>
</el-form-item>
<el-form-item label="SECRET" prop="secret">
<el-input v-if="currentStep === 2" v-model="mediaServerForm.secret" disabled></el-input>
<el-input v-if="currentStep === 3" v-model="mediaServerForm.secret"></el-input>
</el-form-item>
<el-form-item label="HOOK IP" prop="ip">
<el-input v-model="mediaServerForm.hookIp" placeholder="媒体服务HOOK_IP" clearable></el-input>
</el-form-item>
<el-form-item label="SDP IP" prop="ip">
<el-input v-model="mediaServerForm.sdpIp" placeholder="媒体服务SDP_IP" clearable></el-input>
</el-form-item>
<el-form-item label="流IP" prop="ip">
<el-input v-model="mediaServerForm.streamIp" placeholder="媒体服务流IP" clearable></el-input>
</el-form-item>
<el-form-item label="HTTPS PORT" prop="port">
<el-input v-model="mediaServerForm.httpSSlPort" placeholder="媒体服务HTTPS_PORT" clearable></el-input>
</el-form-item>
<el-form-item label="RTSP PORT" prop="port">
<el-input v-model="mediaServerForm.rtspPort" placeholder="媒体服务RTSP_PORT" clearable></el-input>
</el-form-item>
<el-form-item label="RTSPS PORT" prop="port">
<el-input v-model="mediaServerForm.rtspSSLPort" placeholder="媒体服务RTSPS_PORT" clearable></el-input>
</el-form-item>
</el-form>
</el-col>
<el-col :span="12">
<el-form v-if="currentStep === 2 || currentStep === 3" ref="mediaServerForm2" :rules="rules" :model="mediaServerForm" label-width="180px" >
<el-form-item label="RTMP PORT" prop="port">
<el-input v-model="mediaServerForm.rtmpPort" placeholder="媒体服务RTMP_PORT" clearable></el-input>
</el-form-item>
<el-form-item label="RTMPS PORT" prop="port">
<el-input v-model="mediaServerForm.rtmpSSlPort" placeholder="媒体服务RTMPS_PORT" clearable></el-input>
</el-form-item>
<el-form-item label="自动配置媒体服务" >
<el-switch v-model="mediaServerForm.autoConfig"></el-switch>
</el-form-item>
<el-form-item label="收流端口模式" >
<el-switch active-text="多端口" inactive-text="单端口" v-model="mediaServerForm.rtpEnable"></el-switch>
</el-form-item>
<el-form-item v-if="!mediaServerForm.rtpEnable" label="收流端口" prop="port">
<el-input v-model.number="mediaServerForm.rtpProxyPort" clearable></el-input>
</el-form-item>
<el-form-item v-if="mediaServerForm.rtpEnable" label="收流端口" prop="port">
<el-input v-model="mediaServerForm.rtpPortRange1" placeholder="起始" clearable style="width: 100px" prop="port"></el-input>
-
<el-input v-model="mediaServerForm.rtpPortRange2" placeholder="终止" clearable style="width: 100px" prop="port"></el-input>
</el-form-item>
<el-form-item label="推流端口" prop="port">
<el-input v-model="mediaServerForm.sendRtpPortRange1" placeholder="起始" clearable style="width: 100px" prop="port"></el-input>
-
<el-input v-model="mediaServerForm.sendRtpPortRange2" placeholder="终止" clearable style="width: 100px" prop="port"></el-input>
</el-form-item>
<el-form-item label="无人观看多久后停止拉流" >
<el-input v-model.number="mediaServerForm.streamNoneReaderDelayMS" clearable></el-input>
</el-form-item>
<el-form-item label="录像管理服务端口" prop="port">
<el-input v-model.number="mediaServerForm.recordAssistPort">
<!-- <el-button v-if="mediaServerForm.recordAssistPort > 0" slot="append" type="primary" @click="checkRecordServer">测试</el-button>-->
<el-button v-if="mediaServerForm.recordAssistPort > 0" class="el-icon-check" slot="append" type="primary" @click="checkRecordServer"></el-button>
</el-input>
<i v-if="recordServerCheck == 1" class="el-icon-success" style="color: #3caf36; position: absolute;top: 14px;"></i>
<i v-if="recordServerCheck == 2" class="el-icon-loading" style="color: #3caf36; position: absolute;top: 14px;"></i>
<i v-if="recordServerCheck === -1" class="el-icon-error" style="color: #c80000; position: absolute;top: 14px;"></i>
</el-form-item>
<el-form-item>
<div style="float: right;">
<el-button type="primary" @click="onSubmit" >提交</el-button>
<el-button @click="close">取消</el-button>
</div>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</el-dialog>
</div>
</template>
<script>
import MediaServer from './../service/MediaServer'
export default {
name: "streamProxyEdit",
props: {},
computed: {},
created() {
this.setDialogWidth()
},
data() {
const isValidIp = (rule, value, callback) => { // IP
var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
console.log(this.mediaServerForm.ip)
if (!reg.test(this.mediaServerForm.ip)) {
return callback(new Error('请输入有效的IP地址'))
} else {
callback()
}
return true
}
const isValidPort = (rule, value, callback) => { // IP
var reg = /^(([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5]))$/
if (!reg.test(this.mediaServerForm.httpPort)) {
return callback(new Error('请输入有效的端口号'))
} else {
callback()
}
return true
}
return {
dialogWidth: 0,
defaultWidth: 1000,
listChangeCallback: null,
showDialog: false,
isLoging: false,
dialogLoading: false,
currentStep: 1,
platformList: [],
mediaServer: new MediaServer(),
serverCheck: 0,
recordServerCheck: 0,
mediaServerForm: {
id: "",
ip: "",
autoConfig: true,
hookIp: "",
sdpIp: "",
streamIp: "",
streamNoneReaderDelayMS: "",
secret: "035c73f7-bb6b-4889-a715-d9eb2d1925cc",
httpPort: "",
httpSSlPort: "",
recordAssistPort: "",
rtmpPort: "",
rtmpSSlPort: "",
rtpEnable: false,
rtpPortRange: "",
sendRtpPortRange: "",
rtpPortRange1: "",
rtpPortRange2: "",
sendRtpPortRange1: "",
sendRtpPortRange2: "",
rtpProxyPort: "",
rtspPort: "",
rtspSSLPort: "",
},
rules: {
ip: [{ required: true, validator: isValidIp, message: '请输入有效的IP地址', trigger: 'blur' }],
port: [{ required: true, validator: isValidPort, message: '请输入有效的端口号', trigger: 'blur' }],
secret: [{ required: true, message: "请输入secret", trigger: "blur" }],
timeout_ms: [{ required: true, message: "请输入FFmpeg推流成功超时时间", trigger: "blur" }],
ffmpeg_cmd_key: [{ required: false, message: "请输入FFmpeg命令参数模板可选", trigger: "blur" }],
},
};
},
methods: {
setDialogWidth() {
let val = document.body.clientWidth
if (val < this.defaultWidth) {
this.dialogWidth = '100%'
} else {
this.dialogWidth = this.defaultWidth + 'px'
}
},
openDialog: function (param, callback) {
this.showDialog = true;
this.listChangeCallback = callback;
if (param != null) {
this.mediaServerForm = param;
this.currentStep = 3;
if (param.rtpPortRange) {
let rtpPortRange = this.mediaServerForm.rtpPortRange.split(",");
if (rtpPortRange.length > 0) {
this.mediaServerForm["rtpPortRange1"] = rtpPortRange[0]
this.mediaServerForm["rtpPortRange2"] = rtpPortRange[1]
}
}
let sendRtpPortRange = this.mediaServerForm.sendRtpPortRange.split(",");
this.mediaServerForm["sendRtpPortRange1"] = sendRtpPortRange[0]
this.mediaServerForm["sendRtpPortRange2"] = sendRtpPortRange[1]
}
},
checkServer: function() {
let that = this;
that.serverCheck = 0;
that.mediaServer.checkServer(that.mediaServerForm, data =>{
if (data.code === 0) {
if (parseInt(that.mediaServerForm.httpPort) !== parseInt(data.data.httpPort)) {
that.$message({
showClose: true,
message: '如果你正在使用docker部署你的媒体服务请注意的端口映射。',
type: 'warning',
duration: 0
});
}
let httpPort = that.mediaServerForm.httpPort;
that.mediaServerForm = data.data;
that.mediaServerForm.httpPort = httpPort;
that.mediaServerForm.autoConfig = true;
that.mediaServerForm.sendRtpPortRange1 = 30000
that.mediaServerForm.sendRtpPortRange2 = 30500
that.mediaServerForm.rtpPortRange1 = 30000
that.mediaServerForm.rtpPortRange2 = 30500
that.serverCheck = 1;
}else {
that.serverCheck = -1;
that.$message({
showClose: true,
message: data.msg,
type: "error",
});
}
})
},
next: function (){
this.currentStep = 2;
this.defaultWidth = 900;
this.setDialogWidth();
},
checkRecordServer: function (){
let that = this;
that.recordServerCheck = 2;
if (that.mediaServerForm.recordAssistPort <= 0 || that.mediaServerForm.recordAssistPort > 65535 ) {
that.recordServerCheck = -1;
that.$message({
showClose: true,
message: "端口号应该在-65535之间",
type: "error",
});
return;
}
that.mediaServer.checkRecordServer(that.mediaServerForm, data =>{
if (data.code === 0) {
that.recordServerCheck = 1;
}else {
that.recordServerCheck = -1;
that.$message({
showClose: true,
message: data.msg,
type: "error",
});
}
})
},
onSubmit: function () {
this.dialogLoading = true;
let that = this;
if (this.mediaServerForm.rtpEnable) {
this.mediaServerForm.rtpPortRange = this.mediaServerForm.rtpPortRange1 + "," + this.mediaServerForm.rtpPortRange2;
}
this.mediaServerForm.sendRtpPortRange = this.mediaServerForm.sendRtpPortRange1 + "," + this.mediaServerForm.sendRtpPortRange2;
that.mediaServer.addServer(this.mediaServerForm, data => {
if (data.code === 0) {
that.$message({
showClose: true,
message: "保存成功",
type: "success",
});
if (this.listChangeCallback) this.listChangeCallback();
that.close()
}else {
that.$message({
showClose: true,
message: data.msg,
type: "error",
});
}
})
},
close: function () {
this.showDialog = false;
this.dialogLoading = false;
this.mediaServerForm = {
id: "",
ip: "",
autoConfig: true,
hookIp: "",
sdpIp: "",
streamIp: "",
streamNoneReaderDelayMS: "",
secret: "035c73f7-bb6b-4889-a715-d9eb2d1925cc",
httpPort: "",
httpSSlPort: "",
recordAssistPort: "",
rtmpPort: "",
rtmpSSlPort: "",
rtpEnable: false,
rtpPortRange: "",
sendRtpPortRange: "",
rtpPortRange1: "",
rtpPortRange2: "",
sendRtpPortRange1: "",
sendRtpPortRange2: "",
rtpProxyPort: "",
rtspPort: "",
rtspSSLPort: "",
};
this.listChangeCallback = null
this.currentStep = 1;
},
deviceGBIdExit: async function (deviceGbId) {
var result = false;
var that = this;
await that.$axios({
method: 'post',
url:`/api/platform/exit/${deviceGbId}`
}).then(function (res) {
result = res.data;
}).catch(function (error) {
console.log(error);
});
return result;
},
checkExpires: function() {
if (this.platform.enable && this.platform.expires == "0") {
this.platform.expires = "300";
}
}
},
};
</script>

View File

@ -203,7 +203,7 @@ export default {
}).catch(function (error) {
console.log(error);
});
this.mediaServer.getMediaServerList((data)=>{
this.mediaServer.getOnlineMediaServerList((data)=>{
this.mediaServerList = data;
})
},

View File

@ -89,7 +89,7 @@ export default {
method: 'post',
url:"/api/user/changePassword",
params: {
oldpassword: crypto.createHash('md5').update(this.oldPassword, "utf8").digest('hex'),
oldPassword: crypto.createHash('md5').update(this.oldPassword, "utf8").digest('hex'),
password: this.newPassword
}
}).then((res)=> {

View File

@ -82,7 +82,7 @@ export default {
},
getMediaServerList: function (){
let that = this;
that.mediaServerObj.getMediaServerList((data)=>{
that.mediaServerObj.getOnlineMediaServerList((data)=>{
that.mediaServerList = data.data;
})
},

View File

@ -6,7 +6,7 @@ class MediaServer{
this.$axios = axios;
}
getMediaServerList(callback){
getOnlineMediaServerList(callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/online/list`,
@ -16,6 +16,16 @@ class MediaServer{
console.log(error);
});
}
getMediaServerList(callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/list`,
}).then(function (res) {
if (typeof (callback) == "function") callback(res.data)
}).catch(function (error) {
console.log(error);
});
}
getMediaServer(id, callback){
this.$axios({
@ -27,6 +37,49 @@ class MediaServer{
console.log(error);
});
}
checkServer(param, callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/check`,
params: {
ip: param.ip,
port: param.httpPort,
secret: param.secret
}
}).then(function (res) {
if (typeof (callback) == "function") callback(res.data)
}).catch(function (error) {
console.log(error);
});
}
checkRecordServer(param, callback){
this.$axios({
method: 'get',
url:`/api/server/media_server/record/check`,
params: {
ip: param.ip,
port: param.recordAssistPort
}
}).then(function (res) {
if (typeof (callback) == "function") callback(res.data)
}).catch(function (error) {
console.log(error);
});
}
addServer(param, callback){
this.$axios({
method: 'post',
url:`/api/server/media_server/save`,
data: param
}).then(function (res) {
if (typeof (callback) == "function") callback(res.data)
}).catch(function (error) {
console.log(error);
});
}
}
export default MediaServer;

View File

@ -10,6 +10,7 @@ import devicePosition from '../components/devicePosition.vue'
import login from '../components/Login.vue'
import parentPlatformList from '../components/ParentPlatformList.vue'
import cloudRecord from '../components/CloudRecord.vue'
import mediaServerManger from '../components/MediaServerManger.vue'
import test from '../components/test.vue'
import web from '../components/setting/Web.vue'
import sip from '../components/setting/Sip.vue'
@ -70,6 +71,11 @@ export default new VueRouter({
name: 'cloudRecord',
component: cloudRecord,
},
{
path: '/mediaServerManger',
name: 'mediaServerManger',
component: mediaServerManger,
},
{
path: '/setting/web',
name: 'web',

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 1291092 */
src: url('iconfont.woff2?t=1626163621710') format('woff2'),
url('iconfont.woff?t=1626163621710') format('woff'),
url('iconfont.ttf?t=1626163621710') format('truetype');
src: url('iconfont.woff2?t=1631767887536') format('woff2'),
url('iconfont.woff?t=1631767887536') format('woff'),
url('iconfont.ttf?t=1631767887536') format('truetype');
}
.iconfont {
@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-online:before {
content: "\e600";
}
.icon-xiangqing2:before {
content: "\e798";
}

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB