mirror of
https://gitee.com/pan648540858/wvp-GB28181-pro.git
synced 2026-06-12 14:47:49 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
645811dbff
@ -28,7 +28,8 @@ ZLM使用文档 [https://github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZL
|
||||
|
||||
# 付费社群
|
||||
[](https://t.zsxq.com/0d8VAD3Dm)
|
||||
> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。加入三天内不满意可以直接退款,大家不需要有顾虑,来白嫖三天也不是不可以。
|
||||
> 收费是为了提供更好的服务,也是对作者更大的激励。加入星球的用户三天后可以私信我留下微信号,我会拉大家入群。加入三天内不满意可以直接自行推出,星球会直接退款给大家。
|
||||
> 星球还提供了基于主线master分支的打包, 会随时更新。
|
||||
|
||||
# gitee同步仓库
|
||||
https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||
@ -109,9 +110,11 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git
|
||||
- [X] 支持Mysql,Postgresql,金仓等数据库
|
||||
- [X] 支持Onvif(目前在onvif分支,需要安装onvif服务,服务请在知识星球获取)
|
||||
|
||||
|
||||
|
||||
# 非开源的内容
|
||||
- [X] ONVIF设备的接入,支持点播,云台控制,国标级联点播,自动点播。在[知识星球](https://t.zsxq.com/10WAnH2MP)放了试用安装包以及使用教程,没有使用时间限制,需要源码可以星球私信我或者邮箱联系。
|
||||
- [X] 支持国标28181-2022协议,支持巡航轨迹查询,PTZ精准控制,存储卡格式化,设备软件升级,OSD配置,h265+aac,支持辅码流,录像倒放等。具体的功能列表可在[知识星球](https://t.zsxq.com/18GXkpkqs)查看,需要源码和测试可以在星球私信联系或者发邮件给我
|
||||
- [X] ONVIF设备的接入,支持点播,云台控制,国标级联点播,自动点播。试用安装包以及使用教程: [知识星球](https://t.zsxq.com/10WAnH2MP),没有使用时间限制,需要源码可以星球私信我或者邮箱联系。
|
||||
- [X] 支持国标28181-2022协议,支持巡航轨迹查询,PTZ精准控制,存储卡格式化,设备软件升级,OSD配置,h265+aac,支持辅码流,录像倒放等。具体的功能列表可在[知识星球](https://t.zsxq.com/18GXkpkqs)查看,试用安装包: [知识星球](https://t.zsxq.com/UJ6V3),没有使用时间限制,需要源码可以星球私信我或者邮箱联系。
|
||||
|
||||
|
||||
# 授权协议
|
||||
|
||||
20
buildPackage.sh
Executable file
20
buildPackage.sh
Executable file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 获取当前日期并格式化为 YYYY-MM-DD 的形式
|
||||
current_date=$(date +"%Y-%m-%d")
|
||||
|
||||
mkdir -p "$current_date"/数据库
|
||||
|
||||
cp -r ./数据库/2.7.3 "$current_date"/数据库
|
||||
|
||||
cp src/main/resources/配置详情.yml "$current_date"
|
||||
cp src/main/resources/application-dev.yml "$current_date"/application.yml
|
||||
|
||||
cp ./target/wvp-pro-*.jar "$current_date"
|
||||
|
||||
zip -r "$current_date".zip "$current_date"
|
||||
|
||||
rm -rf "$current_date"
|
||||
|
||||
exit 0
|
||||
|
||||
2
pom.xml
2
pom.xml
@ -11,7 +11,7 @@
|
||||
|
||||
<groupId>com.genersoft</groupId>
|
||||
<artifactId>wvp-pro</artifactId>
|
||||
<version>2.7.3</version>
|
||||
<version>2.7.18</version>
|
||||
<name>web video platform</name>
|
||||
<description>国标28181视频平台</description>
|
||||
<packaging>${project.packaging}</packaging>
|
||||
|
||||
12
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Preset.java
Executable file
12
src/main/java/com/genersoft/iot/vmp/gb28181/bean/Preset.java
Executable file
@ -0,0 +1,12 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Preset {
|
||||
|
||||
private String presetId;
|
||||
|
||||
private String presetName;
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
|
||||
/**
|
||||
* @author chenjialing
|
||||
*/
|
||||
public class PresetQuerySipReq {
|
||||
|
||||
private String presetId;
|
||||
|
||||
private String presetName;
|
||||
|
||||
public String getPresetId() {
|
||||
return presetId;
|
||||
}
|
||||
|
||||
public void setPresetId(String presetId) {
|
||||
this.presetId = presetId;
|
||||
}
|
||||
|
||||
public String getPresetName() {
|
||||
return presetName;
|
||||
}
|
||||
|
||||
public void setPresetName(String presetName) {
|
||||
this.presetName = presetName;
|
||||
}
|
||||
}
|
||||
@ -28,7 +28,10 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.context.request.async.DeferredResult;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.sip.message.Response;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ -98,22 +101,40 @@ public class CommonChannelController {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Operation(summary = "获取通道列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Operation(summary = "获取关联行政区划通道列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@Parameter(name = "count", description = "每页查询数量", required = true)
|
||||
@Parameter(name = "query", description = "查询内容")
|
||||
@Parameter(name = "online", description = "是否在线")
|
||||
@Parameter(name = "hasCivilCode", description = "是否分配行政区划")
|
||||
@GetMapping("/list")
|
||||
public PageInfo<CommonGBChannel> queryList(int page, int count,
|
||||
@Parameter(name = "civilCode", description = "行政区划")
|
||||
@GetMapping("/civilcode/list")
|
||||
public PageInfo<CommonGBChannel> queryListByCivilCode(int page, int count,
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) Boolean online,
|
||||
@RequestParam(required = false) Boolean hasCivilCode,
|
||||
@RequestParam(required = false) Boolean hasGroup){
|
||||
@RequestParam(required = false) Integer channelType,
|
||||
@RequestParam(required = false) String civilCode){
|
||||
if (ObjectUtils.isEmpty(query)){
|
||||
query = null;
|
||||
}
|
||||
return channelService.queryList(page, count, query, online, hasCivilCode, hasGroup);
|
||||
return channelService.queryListByCivilCode(page, count, query, online, channelType, civilCode);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取关联业务分组通道列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@Parameter(name = "count", description = "每页查询数量", required = true)
|
||||
@Parameter(name = "query", description = "查询内容")
|
||||
@Parameter(name = "online", description = "是否在线")
|
||||
@Parameter(name = "groupDeviceId", description = "业务分组下的父节点ID")
|
||||
@GetMapping("/parent/list")
|
||||
public PageInfo<CommonGBChannel> queryListByParentId(int page, int count,
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) Boolean online,
|
||||
@RequestParam(required = false) Integer channelType,
|
||||
@RequestParam(required = false) String groupDeviceId){
|
||||
if (ObjectUtils.isEmpty(query)){
|
||||
query = null;
|
||||
}
|
||||
return channelService.queryListByParentId(page, count, query, online, channelType, groupDeviceId);
|
||||
}
|
||||
|
||||
@Operation(summary = "通道设置行政区划", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@ -182,16 +203,39 @@ public class CommonChannelController {
|
||||
|
||||
@Operation(summary = "播放通道", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@GetMapping("/play")
|
||||
public DeferredResult<WVPResult<StreamContent>> deleteChannelToGroupByGbDevice(Integer channelId){
|
||||
public DeferredResult<WVPResult<StreamContent>> deleteChannelToGroupByGbDevice(HttpServletRequest request, Integer channelId){
|
||||
Assert.notNull(channelId,"参数异常");
|
||||
CommonGBChannel channel = channelService.getOne(channelId);
|
||||
Assert.notNull(channel, "通道不存在");
|
||||
|
||||
DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
|
||||
|
||||
ErrorCallback<StreamInfo> callback = (code, msg, data) -> {
|
||||
ErrorCallback<StreamInfo> callback = (code, msg, streamInfo) -> {
|
||||
if (code == InviteErrorCode.SUCCESS.getCode()) {
|
||||
result.setResult(WVPResult.success(new StreamContent(data)));
|
||||
WVPResult<StreamContent> wvpResult = WVPResult.success();
|
||||
if (streamInfo != null) {
|
||||
if (userSetting.getUseSourceIpAsStreamIp()) {
|
||||
streamInfo=streamInfo.clone();//深拷贝
|
||||
String host;
|
||||
try {
|
||||
URL url=new URL(request.getRequestURL().toString());
|
||||
host=url.getHost();
|
||||
} catch (MalformedURLException e) {
|
||||
host=request.getLocalAddr();
|
||||
}
|
||||
streamInfo.channgeStreamIp(host);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(streamInfo.getMediaServer().getTranscodeSuffix())
|
||||
&& !"null".equalsIgnoreCase(streamInfo.getMediaServer().getTranscodeSuffix())) {
|
||||
streamInfo.setStream(streamInfo.getStream() + "_" + streamInfo.getMediaServer().getTranscodeSuffix());
|
||||
}
|
||||
wvpResult.setData(new StreamContent(streamInfo));
|
||||
}else {
|
||||
wvpResult.setCode(code);
|
||||
wvpResult.setMsg(msg);
|
||||
}
|
||||
|
||||
result.setResult(wvpResult);
|
||||
}else {
|
||||
result.setResult(WVPResult.fail(code, msg));
|
||||
}
|
||||
|
||||
@ -296,13 +296,10 @@ public class DeviceQuery {
|
||||
@Parameter(name = "device", description = "设备", required = true)
|
||||
@PostMapping("/device/update/")
|
||||
public void updateDevice(Device device){
|
||||
|
||||
if (device != null && device.getDeviceId() != null) {
|
||||
if (device.getSubscribeCycleForMobilePosition() > 0 && device.getMobilePositionSubmissionInterval() <= 0) {
|
||||
device.setMobilePositionSubmissionInterval(5);
|
||||
}
|
||||
deviceService.updateCustomDevice(device);
|
||||
if (device == null || device.getDeviceId() == null || device.getId() <= 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR400);
|
||||
}
|
||||
deviceService.updateCustomDevice(device);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -40,12 +40,13 @@ public class GroupController {
|
||||
@GetMapping("/tree/list")
|
||||
public List<GroupTree> queryForTree(
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) Integer parent
|
||||
@RequestParam(required = false) Integer parent,
|
||||
@RequestParam(required = false) Boolean hasChannel
|
||||
){
|
||||
if (ObjectUtils.isEmpty(query)) {
|
||||
query = null;
|
||||
}
|
||||
return groupService.queryForTree(query, parent);
|
||||
return groupService.queryForTree(query, parent, hasChannel);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新分组")
|
||||
@ -68,6 +69,14 @@ public class GroupController {
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "获取所属的行政区划下的行政区划")
|
||||
@Parameter(name = "deviceId", description = "当前的行政区划", required = false)
|
||||
@ResponseBody
|
||||
@GetMapping("/path")
|
||||
public List<Group> getPath(String deviceId, String businessGroup){
|
||||
return groupService.getPath(deviceId, businessGroup);
|
||||
}
|
||||
|
||||
// @Operation(summary = "根据分组Id查询分组")
|
||||
// @Parameter(name = "groupDeviceId", description = "分组节点编号", required = true)
|
||||
// @ResponseBody
|
||||
|
||||
@ -18,16 +18,13 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
@Tag(name = "媒体流相关")
|
||||
@Controller
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/api/media")
|
||||
public class MediaController {
|
||||
|
||||
@ -24,10 +24,10 @@ import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.UUID;
|
||||
|
||||
@Tag(name = "云台控制")
|
||||
@Tag(name = "前端设备控制")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/ptz")
|
||||
@RequestMapping("/api/front-end")
|
||||
public class PtzController {
|
||||
|
||||
@Autowired
|
||||
@ -39,30 +39,67 @@ public class PtzController {
|
||||
@Autowired
|
||||
private DeferredResultHolder resultHolder;
|
||||
|
||||
/***
|
||||
* 云台控制
|
||||
* @param deviceId 设备id
|
||||
* @param channelId 通道id
|
||||
* @param command 控制指令
|
||||
* @param horizonSpeed 水平移动速度
|
||||
* @param verticalSpeed 垂直移动速度
|
||||
* @param zoomSpeed 缩放速度
|
||||
*/
|
||||
@Operation(summary = "通用前端控制命令(参考国标文档A.3.1指令格式)", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "cmdCode", description = "指令码(对应国标文档指令格式中的字节4)", required = true)
|
||||
@Parameter(name = "parameter1", description = "数据一(对应国标文档指令格式中的字节5, 范围0-255)", required = true)
|
||||
@Parameter(name = "parameter2", description = "数据二(对应国标文档指令格式中的字节6, 范围0-255)", required = true)
|
||||
@Parameter(name = "combindCode2", description = "组合码二(对应国标文档指令格式中的字节7, 范围0-16)", required = true)
|
||||
@GetMapping("/common/{deviceId}/{channelId}")
|
||||
public void frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,Integer cmdCode, Integer parameter1, Integer parameter2, Integer combindCode2){
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,cmdCode:%d parameter1:%d parameter2:%d",deviceId, channelId, cmdCode, parameter1, parameter2));
|
||||
}
|
||||
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||
|
||||
if (parameter1 == null || parameter1 < 0 || parameter1 > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "parameter1 为 1-255的数字");
|
||||
}
|
||||
if (parameter2 == null || parameter2 < 0 || parameter2 > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "parameter1 为 1-255的数字");
|
||||
}
|
||||
if (combindCode2 == null || combindCode2 < 0 || combindCode2 > 16) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "parameter1 为 1-255的数字");
|
||||
}
|
||||
try {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 前端控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Operation(summary = "云台控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop", required = true)
|
||||
@Parameter(name = "horizonSpeed", description = "水平速度", required = true)
|
||||
@Parameter(name = "verticalSpeed", description = "垂直速度", required = true)
|
||||
@Parameter(name = "zoomSpeed", description = "缩放速度", required = true)
|
||||
@PostMapping("/control/{deviceId}/{channelId}")
|
||||
public void ptz(@PathVariable String deviceId,@PathVariable String channelId, String command, int horizonSpeed, int verticalSpeed, int zoomSpeed){
|
||||
@Parameter(name = "horizonSpeed", description = "水平速度(0-255)", required = true)
|
||||
@Parameter(name = "verticalSpeed", description = "垂直速度(0-255)", required = true)
|
||||
@Parameter(name = "zoomSpeed", description = "缩放速度(0-16)", required = true)
|
||||
@GetMapping("/ptz/{deviceId}/{channelId}")
|
||||
public void ptz(@PathVariable String deviceId,@PathVariable String channelId, String command, Integer horizonSpeed, Integer verticalSpeed, Integer zoomSpeed){
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,command:%s ,horizonSpeed:%d ,verticalSpeed:%d ,zoomSpeed:%d",deviceId, channelId, command, horizonSpeed, verticalSpeed, zoomSpeed));
|
||||
}
|
||||
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||
if (horizonSpeed == null) {
|
||||
horizonSpeed = 100;
|
||||
}else if (horizonSpeed < 0 || horizonSpeed > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "horizonSpeed 为 1-255的数字");
|
||||
}
|
||||
if (verticalSpeed == null) {
|
||||
verticalSpeed = 100;
|
||||
}else if (verticalSpeed < 0 || verticalSpeed > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "verticalSpeed 为 1-255的数字");
|
||||
}
|
||||
if (zoomSpeed == null) {
|
||||
zoomSpeed = 16;
|
||||
}else if (zoomSpeed < 0 || zoomSpeed > 16) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "zoomSpeed 为 1-255的数字");
|
||||
}
|
||||
|
||||
int cmdCode = 0;
|
||||
switch (command){
|
||||
case "left":
|
||||
@ -103,44 +140,79 @@ public class PtzController {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
try {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 云台控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "通用前端控制命令", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Operation(summary = "光圈控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "cmdCode", description = "指令码", required = true)
|
||||
@Parameter(name = "parameter1", description = "数据一", required = true)
|
||||
@Parameter(name = "parameter2", description = "数据二", required = true)
|
||||
@Parameter(name = "combindCode2", description = "组合码二", required = true)
|
||||
@PostMapping("/front_end_command/{deviceId}/{channelId}")
|
||||
public void frontEndCommand(@PathVariable String deviceId,@PathVariable String channelId,int cmdCode, int parameter1, int parameter2, int combindCode2){
|
||||
@Parameter(name = "command", description = "控制指令,允许值: in, out, stop", required = true)
|
||||
@Parameter(name = "speed", description = "光圈速度(0-255)", required = true)
|
||||
@GetMapping("/fi/iris/{deviceId}/{channelId}")
|
||||
public void iris(@PathVariable String deviceId,@PathVariable String channelId, String command, Integer speed){
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(String.format("设备云台控制 API调用,deviceId:%s ,channelId:%s ,cmdCode:%d parameter1:%d parameter2:%d",deviceId, channelId, cmdCode, parameter1, parameter2));
|
||||
log.debug("设备光圈控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,speed:{} ",deviceId, channelId, command, speed);
|
||||
}
|
||||
Device device = deviceService.getDeviceByDeviceId(deviceId);
|
||||
|
||||
try {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 前端控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
int cmdCode = 0x40;
|
||||
switch (command){
|
||||
case "in":
|
||||
cmdCode = 0x44;
|
||||
break;
|
||||
case "out":
|
||||
cmdCode = 0x48;
|
||||
break;
|
||||
case "stop":
|
||||
speed = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, cmdCode, 0, speed, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "聚焦控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: near, far, stop", required = true)
|
||||
@Parameter(name = "speed", description = "聚焦速度(0-255)", required = true)
|
||||
@GetMapping("/fi/focus/{deviceId}/{channelId}")
|
||||
public void focus(@PathVariable String deviceId,@PathVariable String channelId, String command, Integer speed){
|
||||
|
||||
@Operation(summary = "预置位查询", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("设备聚焦控制 API调用,deviceId:{} ,channelId:{} ,command:{} ,speed:{} ",deviceId, channelId, command, speed);
|
||||
}
|
||||
|
||||
if (speed == null) {
|
||||
speed = 100;
|
||||
}else if (speed < 0 || speed > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "verticalSpeed 为 1-255的数字");
|
||||
}
|
||||
|
||||
int cmdCode = 0x40;
|
||||
switch (command){
|
||||
case "near":
|
||||
cmdCode = 0x42;
|
||||
break;
|
||||
case "far":
|
||||
cmdCode = 0x41;
|
||||
break;
|
||||
case "stop":
|
||||
speed = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, cmdCode, speed, 0, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "查询预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@GetMapping("/preset/query/{deviceId}/{channelId}")
|
||||
public DeferredResult<String> presetQueryApi(@PathVariable String deviceId, @PathVariable String channelId) {
|
||||
public DeferredResult<String> queryPreset(@PathVariable String deviceId, @PathVariable String channelId) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("设备预置位查询API调用");
|
||||
}
|
||||
@ -175,4 +247,248 @@ public class PtzController {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Operation(summary = "预置位指令-设置预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
|
||||
@GetMapping("/preset/add/{deviceId}/{channelId}")
|
||||
public void addPreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
|
||||
if (presetId == null || presetId < 1 || presetId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x81, 1, presetId, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "预置位指令-调用预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
|
||||
@GetMapping("/preset/call/{deviceId}/{channelId}")
|
||||
public void callPreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
|
||||
if (presetId == null || presetId < 1 || presetId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x82, 1, presetId, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "预置位指令-删除预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
|
||||
@GetMapping("/preset/delete/{deviceId}/{channelId}")
|
||||
public void deletePreset(@PathVariable String deviceId, @PathVariable String channelId, Integer presetId) {
|
||||
if (presetId == null || presetId < 1 || presetId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x83, 1, presetId, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-加入巡航点", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "cruiseId", description = "巡航组号(0-255)", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
|
||||
@GetMapping("/cruise/point/add/{deviceId}/{channelId}")
|
||||
public void addCruisePoint(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId, Integer presetId) {
|
||||
if (presetId == null || cruiseId == null || presetId < 1 || presetId > 255 || cruiseId < 0 || cruiseId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "编号必须为1-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x84, cruiseId, presetId, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-删除一个巡航点", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "cruiseId", description = "巡航组号(1-255)", required = true)
|
||||
@Parameter(name = "presetId", description = "预置位编号(0-255, 为0时删除整个巡航)", required = true)
|
||||
@GetMapping("/cruise/point/delete/{deviceId}/{channelId}")
|
||||
public void deleteCruisePoint(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId, Integer presetId) {
|
||||
if (presetId == null || presetId < 0 || presetId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为0-255之间的数字, 为0时删除整个巡航");
|
||||
}
|
||||
if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x85, cruiseId, presetId, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-设置巡航速度", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "cruiseId", description = "巡航组号(0-255)", required = true)
|
||||
@Parameter(name = "speed", description = "巡航速度(1-4095)", required = true)
|
||||
@GetMapping("/cruise/speed/{deviceId}/{channelId}")
|
||||
public void setCruiseSpeed(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId, Integer speed) {
|
||||
if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
|
||||
}
|
||||
if (speed == null || speed < 1 || speed > 4095) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航速度必须为1-4095之间的数字");
|
||||
}
|
||||
int parameter2 = speed & 0xFF;
|
||||
int combindCode2 = speed >> 8;
|
||||
frontEndCommand(deviceId, channelId, 0x86, cruiseId, parameter2, combindCode2);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-设置巡航停留时间", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "cruiseId", description = "巡航组号", required = true)
|
||||
@Parameter(name = "time", description = "巡航停留时间(1-4095)", required = true)
|
||||
@GetMapping("/cruise/time/{deviceId}/{channelId}")
|
||||
public void setCruiseTime(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId, Integer time) {
|
||||
if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
|
||||
}
|
||||
if (time == null || time < 1 || time > 4095) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航停留时间必须为1-4095之间的数字");
|
||||
}
|
||||
int parameter2 = time & 0xFF;
|
||||
int combindCode2 = time >> 8;
|
||||
frontEndCommand(deviceId, channelId, 0x87, cruiseId, parameter2, combindCode2);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-开始巡航", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "cruiseId", description = "巡航组号)", required = true)
|
||||
@GetMapping("/cruise/start/{deviceId}/{channelId}")
|
||||
public void startCruise(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId) {
|
||||
if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x88, cruiseId, 0, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "巡航指令-停止巡航", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "cruiseId", description = "巡航组号", required = true)
|
||||
@GetMapping("/cruise/stop/{deviceId}/{channelId}")
|
||||
public void stopCruise(@PathVariable String deviceId, @PathVariable String channelId, Integer cruiseId) {
|
||||
if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "扫描指令-开始自动扫描", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||
@GetMapping("/scan/start/{deviceId}/{channelId}")
|
||||
public void startScan(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId) {
|
||||
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x89, scanId, 0, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "扫描指令-停止自动扫描", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||
@GetMapping("/scan/stop/{deviceId}/{channelId}")
|
||||
public void stopScan(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId) {
|
||||
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "扫描指令-设置自动扫描左边界", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||
@GetMapping("/scan/set/left/{deviceId}/{channelId}")
|
||||
public void setScanLeft(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId) {
|
||||
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x89, scanId, 1, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "扫描指令-设置自动扫描右边界", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||
@GetMapping("/scan/set/right/{deviceId}/{channelId}")
|
||||
public void setScanRight(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId) {
|
||||
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, 0x89, scanId, 2, 0);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "扫描指令-设置自动扫描速度", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||
@Parameter(name = "speed", description = "自动扫描速度(1-4095)", required = true)
|
||||
@GetMapping("/scan/set/speed/{deviceId}/{channelId}")
|
||||
public void setScanSpeed(@PathVariable String deviceId, @PathVariable String channelId, Integer scanId, Integer speed) {
|
||||
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||
}
|
||||
if (speed == null || speed < 1 || speed > 4095) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "自动扫描速度必须为1-4095之间的数字");
|
||||
}
|
||||
int parameter2 = speed & 0xFF;
|
||||
int combindCode2 = speed >> 8;
|
||||
frontEndCommand(deviceId, channelId, 0x8A, scanId, parameter2, combindCode2);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "辅助开关控制指令-雨刷控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: on, off", required = true)
|
||||
@GetMapping("/wiper/{deviceId}/{channelId}")
|
||||
public void wiper(@PathVariable String deviceId,@PathVariable String channelId, String command){
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("辅助开关控制指令-雨刷控制 API调用,deviceId:{} ,channelId:{} ,command:{}",deviceId, channelId, command);
|
||||
}
|
||||
|
||||
int cmdCode = 0;
|
||||
switch (command){
|
||||
case "on":
|
||||
cmdCode = 0x8c;
|
||||
break;
|
||||
case "off":
|
||||
cmdCode = 0x8d;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, cmdCode, 1, 0, 0);
|
||||
}
|
||||
|
||||
@Operation(summary = "辅助开关控制指令", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "deviceId", description = "设备国标编号", required = true)
|
||||
@Parameter(name = "channelId", description = "通道国标编号", required = true)
|
||||
@Parameter(name = "command", description = "控制指令,允许值: on, off", required = true)
|
||||
@Parameter(name = "switchId", description = "开关编号", required = true)
|
||||
@GetMapping("/auxiliary/{deviceId}/{channelId}")
|
||||
public void auxiliarySwitch(@PathVariable String deviceId,@PathVariable String channelId, String command, Integer switchId){
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("辅助开关控制指令-雨刷控制 API调用,deviceId:{} ,channelId:{} ,command:{}, switchId: {}",deviceId, channelId, command, switchId);
|
||||
}
|
||||
|
||||
int cmdCode = 0;
|
||||
switch (command){
|
||||
case "on":
|
||||
cmdCode = 0x8c;
|
||||
break;
|
||||
case "off":
|
||||
cmdCode = 0x8d;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
frontEndCommand(deviceId, channelId, cmdCode, switchId, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,12 +57,13 @@ public class RegionController {
|
||||
@GetMapping("/tree/list")
|
||||
public List<RegionTree> queryForTree(
|
||||
@RequestParam(required = false) String query,
|
||||
@RequestParam(required = false) Integer parent
|
||||
@RequestParam(required = false) Integer parent,
|
||||
@RequestParam(required = false) Boolean hasChannel
|
||||
){
|
||||
if (ObjectUtils.isEmpty(query)) {
|
||||
query = null;
|
||||
}
|
||||
return regionService.queryForTree(query, parent);
|
||||
return regionService.queryForTree(query, parent, hasChannel);
|
||||
}
|
||||
|
||||
@Operation(summary = "更新区域")
|
||||
@ -109,6 +110,14 @@ public class RegionController {
|
||||
return regionService.getAllChild(parent);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取所属的行政区划下的行政区划")
|
||||
@Parameter(name = "deviceId", description = "当前的行政区划", required = false)
|
||||
@ResponseBody
|
||||
@GetMapping("/path")
|
||||
public List<Region> getPath(String deviceId){
|
||||
return regionService.getPath(deviceId);
|
||||
}
|
||||
|
||||
@Operation(summary = "从通道中同步行政区划")
|
||||
@ResponseBody
|
||||
@GetMapping("/sync")
|
||||
|
||||
@ -119,6 +119,7 @@ public interface CommonGBChannelMapper {
|
||||
", gb_block = #{gbBlock}" +
|
||||
", gb_address = #{gbAddress}" +
|
||||
", gb_parental = #{gbParental}" +
|
||||
", gb_parent_id = #{gbParentId}" +
|
||||
", gb_safety_way = #{gbSafetyWay}" +
|
||||
", gb_register_way = #{gbRegisterWay}" +
|
||||
", gb_cert_num = #{gbCertNum}" +
|
||||
@ -255,10 +256,17 @@ public interface CommonGBChannelMapper {
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryByStreamProxyId")
|
||||
CommonGBChannel queryByStreamProxyId(@Param("streamProxyId") Integer streamProxyId);
|
||||
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryList")
|
||||
List<CommonGBChannel> queryList(@Param("query") String query, @Param("online") Boolean online,
|
||||
@Param("hasCivilCode") Boolean hasCivilCode,
|
||||
@Param("hasGroup") Boolean hasGroup);
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryListByCivilCode")
|
||||
List<CommonGBChannel> queryListByCivilCode(@Param("query") String query, @Param("online") Boolean online,
|
||||
@Param("channelType") Integer channelType, @Param("civilCode") String civilCode);
|
||||
|
||||
|
||||
|
||||
@SelectProvider(type = ChannelProvider.class, method = "queryListByParentId")
|
||||
List<CommonGBChannel> queryListByParentId(@Param("query") String query, @Param("online") Boolean online,
|
||||
@Param("channelType") Integer channelType, @Param("groupDeviceId") String groupDeviceId);
|
||||
|
||||
|
||||
|
||||
@Select("<script>" +
|
||||
" select " +
|
||||
|
||||
@ -5,13 +5,11 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelReduce;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.provider.DeviceChannelProvider;
|
||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
||||
import com.genersoft.iot.vmp.web.gb28181.dto.DeviceChannelExtend;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 用于存储设备通道信息
|
||||
@ -551,7 +549,7 @@ public interface DeviceChannelMapper {
|
||||
"</script>")
|
||||
void updateStreamGPS(List<GPSMsgInfo> gpsMsgInfoList);
|
||||
|
||||
@Update("UPDATE wvp_device_channel SET status=#{status} WHERE device_id=#{deviceId} AND channel_id=#{channelId}")
|
||||
@Update("UPDATE wvp_device_channel SET status=#{status} WHERE device_db_id=#{deviceDbId} AND device_id=#{deviceId}")
|
||||
void updateStatus(DeviceChannel channel);
|
||||
|
||||
|
||||
|
||||
@ -246,24 +246,12 @@ public interface DeviceMapper {
|
||||
|
||||
@Update(value = {" <script>" +
|
||||
"UPDATE wvp_device " +
|
||||
"SET update_time=#{updateTime}" +
|
||||
"<if test=\"name != null\">, custom_name=#{name}</if>" +
|
||||
"<if test=\"password != null\">, password=#{password}</if>" +
|
||||
"<if test=\"streamMode != null\">, stream_mode=#{streamMode}</if>" +
|
||||
"<if test=\"ip != null\">, ip=#{ip}</if>" +
|
||||
"<if test=\"sdpIp != null\">, sdp_ip=#{sdpIp}</if>" +
|
||||
"<if test=\"port != null\">, port=#{port}</if>" +
|
||||
"<if test=\"charset != null\">, charset=#{charset}</if>" +
|
||||
"<if test=\"subscribeCycleForCatalog != null\">, subscribe_cycle_for_catalog=#{subscribeCycleForCatalog}</if>" +
|
||||
"<if test=\"subscribeCycleForMobilePosition != null\">, subscribe_cycle_for_mobile_position=#{subscribeCycleForMobilePosition}</if>" +
|
||||
"<if test=\"mobilePositionSubmissionInterval != null\">, mobile_position_submission_interval=#{mobilePositionSubmissionInterval}</if>" +
|
||||
"<if test=\"subscribeCycleForAlarm != null\">, subscribe_cycle_for_alarm=#{subscribeCycleForAlarm}</if>" +
|
||||
"<if test=\"ssrcCheck != null\">, ssrc_check=#{ssrcCheck}</if>" +
|
||||
"<if test=\"asMessageChannel != null\">, as_message_channel=#{asMessageChannel}</if>" +
|
||||
"<if test=\"broadcastPushAfterAck != null\">, broadcast_push_after_ack=#{broadcastPushAfterAck}</if>" +
|
||||
"<if test=\"geoCoordSys != null\">, geo_coord_sys=#{geoCoordSys}</if>" +
|
||||
"<if test=\"mediaServerId != null\">, media_server_id=#{mediaServerId}</if>" +
|
||||
"WHERE device_id=#{deviceId}"+
|
||||
"SET update_time=#{updateTime}, custom_name=#{name} , password=#{password}, stream_mode=#{streamMode}" +
|
||||
", ip=#{ip}, sdp_ip=#{sdpIp}, port=#{port}, charset=#{charset}, subscribe_cycle_for_catalog=#{subscribeCycleForCatalog}" +
|
||||
", subscribe_cycle_for_mobile_position=#{subscribeCycleForMobilePosition}, mobile_position_submission_interval=#{mobilePositionSubmissionInterval}" +
|
||||
", subscribe_cycle_for_alarm=#{subscribeCycleForAlarm}, ssrc_check=#{ssrcCheck}, as_message_channel=#{asMessageChannel}" +
|
||||
", broadcast_push_after_ack=#{broadcastPushAfterAck}, geo_coord_sys=#{geoCoordSys}, media_server_id=#{mediaServerId}" +
|
||||
" WHERE id=#{id}"+
|
||||
" </script>"})
|
||||
void updateCustom(Device device);
|
||||
|
||||
@ -342,7 +330,11 @@ public interface DeviceMapper {
|
||||
" FROM wvp_device de" +
|
||||
" where 1 = 1 "+
|
||||
" <if test='status != null'> AND de.on_line=${status}</if>"+
|
||||
" <if test='query != null'> AND (coalesce(custom_name, name) LIKE '%${query}%' OR device_id LIKE '%${query}%' OR ip LIKE '%${query}%')</if> " +
|
||||
" <if test='query != null'> AND (" +
|
||||
" coalesce(custom_name, name) LIKE concat('%',#{query},'%') escape '/' " +
|
||||
" OR device_id LIKE concat('%',#{query},'%') escape '/' " +
|
||||
" OR ip LIKE concat('%',#{query},'%') escape '/')" +
|
||||
"</if> " +
|
||||
" order by create_time desc "+
|
||||
" </script>")
|
||||
List<Device> getDeviceList(@Param("query") String query, @Param("status") Boolean status);
|
||||
|
||||
@ -71,7 +71,7 @@ public interface PlatformMapper {
|
||||
" ) as channel_count" +
|
||||
" FROM wvp_platform pp where 1=1 " +
|
||||
" <if test='query != null'> " +
|
||||
" AND (pp.name LIKE concat('%',#{query},'%') OR pp.server_gb_id LIKE concat('%',#{query},'%') )</if> " +
|
||||
" AND (pp.name LIKE concat('%',#{query},'%') escape '/' OR pp.server_gb_id LIKE concat('%',#{query},'%') escape '/' )</if> " +
|
||||
" order by pp.id desc"+
|
||||
" </script>")
|
||||
List<Platform> queryList(@Param("query") String query);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package com.genersoft.iot.vmp.gb28181.dao;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Group;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Region;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RegionTree;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
@ -27,7 +26,7 @@ public interface RegionMapper {
|
||||
|
||||
@Select(value = {" <script>" +
|
||||
"SELECT * from wvp_common_region WHERE 1=1 " +
|
||||
" <if test='query != null'> AND (device_id LIKE concat('%',#{query},'%') OR name LIKE concat('%',#{query},'%'))</if> " +
|
||||
" <if test='query != null'> AND (device_id LIKE concat('%',#{query},'%') escape '/' OR name LIKE concat('%',#{query},'%') escape '/')</if> " +
|
||||
" <if test='parentId != null'> AND parent_device_id = #{parentId}</if> " +
|
||||
"ORDER BY id " +
|
||||
" </script>"})
|
||||
@ -80,7 +79,7 @@ public interface RegionMapper {
|
||||
" where " +
|
||||
" <if test='parentId != null'> parent_id = #{parentId} </if> " +
|
||||
" <if test='parentId == null'> parent_id is null </if> " +
|
||||
" <if test='query != null'> AND (device_id LIKE concat('%',#{query},'%') OR name LIKE concat('%',#{query},'%'))</if> " +
|
||||
" <if test='query != null'> AND (device_id LIKE concat('%',#{query},'%') escape '/' OR name LIKE concat('%',#{query},'%') escape '/')</if> " +
|
||||
" </script>")
|
||||
List<RegionTree> queryForTree(@Param("query") String query, @Param("parentId") Integer parentId);
|
||||
|
||||
|
||||
@ -117,13 +117,13 @@ public class ChannelProvider {
|
||||
}
|
||||
|
||||
|
||||
public String queryList(Map<String, Object> params ){
|
||||
public String queryListByCivilCode(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(BASE_SQL);
|
||||
sqlBuild.append(" where channel_type = 0 ");
|
||||
if (params.get("query") != null) {
|
||||
sqlBuild.append(" AND (coalesce(gb_device_id, device_id) LIKE concat('%',#{query},'%')" +
|
||||
" OR coalesce(gb_name, name) LIKE concat('%',#{query},'%') )")
|
||||
sqlBuild.append(" AND (coalesce(gb_device_id, device_id) LIKE concat('%',#{query},'%') escape '/'" +
|
||||
" OR coalesce(gb_name, name) LIKE concat('%',#{query},'%') escape '/' )")
|
||||
;
|
||||
}
|
||||
if (params.get("online") != null && (Boolean)params.get("online")) {
|
||||
@ -132,18 +132,53 @@ public class ChannelProvider {
|
||||
if (params.get("online") != null && !(Boolean)params.get("online")) {
|
||||
sqlBuild.append(" AND coalesce(gb_status, status) = 'OFF'");
|
||||
}
|
||||
if (params.get("hasCivilCode") != null && (Boolean)params.get("hasCivilCode")) {
|
||||
sqlBuild.append(" AND coalesce(gb_civil_code, civil_code) is not null");
|
||||
}
|
||||
if (params.get("hasCivilCode") != null && !(Boolean)params.get("hasCivilCode")) {
|
||||
if (params.get("civilCode") != null) {
|
||||
sqlBuild.append(" AND coalesce(gb_civil_code, civil_code) = #{civilCode}");
|
||||
}else {
|
||||
sqlBuild.append(" AND coalesce(gb_civil_code, civil_code) is null");
|
||||
}
|
||||
if (params.get("hasGroup") != null && (Boolean)params.get("hasGroup")) {
|
||||
sqlBuild.append(" AND coalesce(gb_parent_id, parent_id) is not null");
|
||||
if (params.get("channelType") != null) {
|
||||
if ((Integer)params.get("channelType") == 0) {
|
||||
sqlBuild.append(" AND device_db_id is not null");
|
||||
}else if ((Integer)params.get("channelType") == 1) {
|
||||
sqlBuild.append(" AND stream_push_id is not null");
|
||||
}else if ((Integer)params.get("channelType") == 2) {
|
||||
sqlBuild.append(" AND stream_proxy_id is not null");
|
||||
}
|
||||
}
|
||||
if (params.get("hasGroup") != null && !(Boolean)params.get("hasGroup")) {
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
public String queryListByParentId(Map<String, Object> params ){
|
||||
StringBuilder sqlBuild = new StringBuilder();
|
||||
sqlBuild.append(BASE_SQL);
|
||||
sqlBuild.append(" where channel_type = 0 ");
|
||||
if (params.get("query") != null) {
|
||||
sqlBuild.append(" AND (coalesce(gb_device_id, device_id) LIKE concat('%',#{query},'%') escape '/'" +
|
||||
" OR coalesce(gb_name, name) LIKE concat('%',#{query},'%') escape '/' )")
|
||||
;
|
||||
}
|
||||
if (params.get("online") != null && (Boolean)params.get("online")) {
|
||||
sqlBuild.append(" AND coalesce(gb_status, status) = 'ON'");
|
||||
}
|
||||
if (params.get("online") != null && !(Boolean)params.get("online")) {
|
||||
sqlBuild.append(" AND coalesce(gb_status, status) = 'OFF'");
|
||||
}
|
||||
if (params.get("groupDeviceId") != null) {
|
||||
sqlBuild.append(" AND coalesce(gb_parent_id, parent_id) = #{groupDeviceId}");
|
||||
}else {
|
||||
sqlBuild.append(" AND coalesce(gb_parent_id, parent_id) is null");
|
||||
}
|
||||
|
||||
if (params.get("channelType") != null) {
|
||||
if ((Integer)params.get("channelType") == 0) {
|
||||
sqlBuild.append(" AND device_db_id is not null");
|
||||
}else if ((Integer)params.get("channelType") == 1) {
|
||||
sqlBuild.append(" AND stream_push_id is not null");
|
||||
}else if ((Integer)params.get("channelType") == 2) {
|
||||
sqlBuild.append(" AND stream_proxy_id is not null");
|
||||
}
|
||||
}
|
||||
return sqlBuild.toString();
|
||||
}
|
||||
|
||||
|
||||
@ -71,8 +71,8 @@ public class DeviceChannelProvider {
|
||||
"OR (LENGTH(coalesce(dc.gb_device_id, dc.device_id))=LENGTH(#{civilCode}) + 2) AND coalesce(dc.gb_device_id, dc.device_id) LIKE concat(#{civilCode},'%'))");
|
||||
}
|
||||
if (params.get("query") != null && !ObjectUtils.isEmpty(params.get("query"))) {
|
||||
sqlBuild.append(" AND (coalesce(dc.gb_device_id, dc.device_id) LIKE concat('%',#{query},'%')" +
|
||||
" OR coalesce(dc.gb_name, dc.name) LIKE concat('%',#{query},'%'))")
|
||||
sqlBuild.append(" AND (coalesce(dc.gb_device_id, dc.device_id) LIKE concat('%',#{query},'%') escape '/'" +
|
||||
" OR coalesce(dc.gb_name, dc.name) LIKE concat('%',#{query},'%') escape '/')")
|
||||
;
|
||||
}
|
||||
if (params.get("online") != null && (Boolean)params.get("online")) {
|
||||
|
||||
@ -41,7 +41,9 @@ public interface IGbChannelService {
|
||||
|
||||
void reset(int id);
|
||||
|
||||
PageInfo<CommonGBChannel> queryList(int page, int count, String query, Boolean online, Boolean hasCivilCode, Boolean hasGroup);
|
||||
PageInfo<CommonGBChannel> queryListByCivilCode(int page, int count, String query, Boolean online, Integer channelType, String civilCode);
|
||||
|
||||
PageInfo<CommonGBChannel> queryListByParentId(int page, int count, String query, Boolean online, Integer channelType, String groupDeviceId);
|
||||
|
||||
void removeCivilCode(List<Region> allChildren);
|
||||
|
||||
|
||||
@ -14,11 +14,13 @@ public interface IGroupService {
|
||||
|
||||
Group queryGroupByDeviceId(String regionDeviceId);
|
||||
|
||||
List<GroupTree> queryForTree(String query, Integer parent);
|
||||
List<GroupTree> queryForTree(String query, Integer parent, Boolean hasChannel);
|
||||
|
||||
void syncFromChannel();
|
||||
|
||||
boolean delete(int id);
|
||||
|
||||
boolean batchAdd(List<Group> groupList);
|
||||
|
||||
List<Group> getPath(String deviceId, String businessGroup);
|
||||
}
|
||||
|
||||
21
src/main/java/com/genersoft/iot/vmp/gb28181/service/IPTZService.java
Executable file
21
src/main/java/com/genersoft/iot/vmp/gb28181/service/IPTZService.java
Executable file
@ -0,0 +1,21 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service;
|
||||
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Preset;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface IPTZService {
|
||||
|
||||
|
||||
List<Preset> queryPresetList(String deviceId, String channelDeviceId);
|
||||
|
||||
void addPreset(Preset preset);
|
||||
|
||||
void deletePreset(Integer qq);
|
||||
|
||||
void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed);
|
||||
|
||||
void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2);
|
||||
}
|
||||
@ -27,11 +27,13 @@ public interface IRegionService {
|
||||
|
||||
Region queryRegionByDeviceId(String regionDeviceId);
|
||||
|
||||
List<RegionTree> queryForTree(String query, Integer parent);
|
||||
List<RegionTree> queryForTree(String query, Integer parent, Boolean hasChannel);
|
||||
|
||||
void syncFromChannel();
|
||||
|
||||
boolean delete(int id);
|
||||
|
||||
boolean batchAdd(List<Region> regionList);
|
||||
|
||||
List<Region> getPath(String deviceId);
|
||||
}
|
||||
|
||||
@ -609,6 +609,11 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
parentId = channelId;
|
||||
}
|
||||
}
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<DeviceChannel> all = channelMapper.queryChannels(deviceDbId, civilCode, businessGroupId, parentId, query, channelType, online,null);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
@ -624,7 +629,11 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService {
|
||||
if (device == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到设备:" + deviceId);
|
||||
}
|
||||
// 获取到所有正在播放的流
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
PageHelper.startPage(page, count);
|
||||
List<DeviceChannel> all = channelMapper.queryChannels(device.getId(), null,null, null, query, hasSubChannel, online,null);
|
||||
return new PageInfo<>(all);
|
||||
|
||||
@ -19,7 +19,6 @@ import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask;
|
||||
import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask;
|
||||
import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
|
||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
@ -34,7 +33,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
@ -51,9 +49,6 @@ import java.util.concurrent.TimeUnit;
|
||||
@DS("master")
|
||||
public class DeviceServiceImpl implements IDeviceService {
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
|
||||
@Autowired
|
||||
private DynamicTask dynamicTask;
|
||||
|
||||
@ -421,34 +416,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
|
||||
@Override
|
||||
public void updateCustomDevice(Device device) {
|
||||
Device deviceInStore = deviceMapper.getDeviceByDeviceId(device.getDeviceId());
|
||||
Device deviceInStore = deviceMapper.query(device.getId());
|
||||
if (deviceInStore == null) {
|
||||
log.warn("更新设备时未找到设备信息");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(device.getName())) {
|
||||
deviceInStore.setName(device.getName());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(device.getCharset())) {
|
||||
deviceInStore.setCharset(device.getCharset());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(device.getMediaServerId())) {
|
||||
deviceInStore.setMediaServerId(device.getMediaServerId());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(device.getCharset())) {
|
||||
deviceInStore.setCharset(device.getCharset());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(device.getSdpIp())) {
|
||||
deviceInStore.setSdpIp(device.getSdpIp());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(device.getPassword())) {
|
||||
deviceInStore.setPassword(device.getPassword());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(device.getStreamMode())) {
|
||||
deviceInStore.setStreamMode(device.getStreamMode());
|
||||
}
|
||||
deviceInStore.setBroadcastPushAfterAck(device.isBroadcastPushAfterAck());
|
||||
// 目录订阅相关的信息
|
||||
if (deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) {
|
||||
if (device.getSubscribeCycleForCatalog() > 0) {
|
||||
@ -513,13 +485,9 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
if (device.getCharset() == null) {
|
||||
deviceInStore.setCharset("GB2312");
|
||||
}
|
||||
//SSRC校验
|
||||
deviceInStore.setSsrcCheck(device.isSsrcCheck());
|
||||
//作为消息通道
|
||||
deviceInStore.setAsMessageChannel(device.isAsMessageChannel());
|
||||
|
||||
deviceMapper.updateCustom(deviceInStore);
|
||||
redisCatchStorage.updateDevice(deviceInStore);
|
||||
deviceMapper.updateCustom(device);
|
||||
redisCatchStorage.updateDevice(device);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -551,6 +519,11 @@ public class DeviceServiceImpl implements IDeviceService {
|
||||
@Override
|
||||
public PageInfo<Device> getAll(int page, int count, String query, Boolean status) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<Device> all = deviceMapper.getDeviceList(query, status);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@ -156,7 +156,7 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
}
|
||||
List<CommonGBChannel> onlineChannelList = commonGBChannelMapper.queryInListByStatus(commonGBChannelList, "ON");
|
||||
if (onlineChannelList.isEmpty()) {
|
||||
log.warn("[多个通道离线] 更新失败, 参数内通道已经离线, 无需更新");
|
||||
log.info("[多个通道离线] 更新失败, 参数内通道已经离线, 无需更新");
|
||||
return 0;
|
||||
}
|
||||
int limitCount = 1000;
|
||||
@ -388,10 +388,26 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<CommonGBChannel> queryList(int page, int count, String query, Boolean online, Boolean hasCivilCode,
|
||||
Boolean hasGroup) {
|
||||
public PageInfo<CommonGBChannel> queryListByCivilCode(int page, int count, String query, Boolean online, Integer channelType, String civilCode) {
|
||||
PageHelper.startPage(page, count);
|
||||
List<CommonGBChannel> all = commonGBChannelMapper.queryList(query, online, hasCivilCode, hasGroup);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<CommonGBChannel> all = commonGBChannelMapper.queryListByCivilCode(query, online, channelType, civilCode);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<CommonGBChannel> queryListByParentId(int page, int count, String query, Boolean online, Integer channelType, String groupDeviceId) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<CommonGBChannel> all = commonGBChannelMapper.queryListByParentId(query, online, channelType, groupDeviceId);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.CommonGBChannelMapper;
|
||||
import com.genersoft.iot.vmp.gb28181.dao.GroupMapper;
|
||||
@ -8,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IGroupService;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -15,10 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 区域管理类
|
||||
@ -154,7 +153,7 @@ public class GroupServiceImpl implements IGroupService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GroupTree> queryForTree(String query, Integer parentId) {
|
||||
public List<GroupTree> queryForTree(String query, Integer parentId, Boolean hasChannel) {
|
||||
|
||||
List<GroupTree> groupTrees = groupManager.queryForTree(query, parentId);
|
||||
if (parentId == null) {
|
||||
@ -162,7 +161,7 @@ public class GroupServiceImpl implements IGroupService {
|
||||
}
|
||||
// 查询含有的通道
|
||||
Group parentGroup = groupManager.queryOne(parentId);
|
||||
if (parentGroup != null ) {
|
||||
if (parentGroup != null && hasChannel != null && hasChannel) {
|
||||
List<GroupTree> groupTreesForChannel = commonGBChannelMapper.queryForGroupTreeByParentId(query, parentGroup.getDeviceId());
|
||||
if (!ObjectUtils.isEmpty(groupTreesForChannel)) {
|
||||
groupTrees.addAll(groupTreesForChannel);
|
||||
@ -247,4 +246,37 @@ public class GroupServiceImpl implements IGroupService {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Group> getPath(String deviceId, String businessGroup) {
|
||||
Group businessGroupInDb = groupManager.queryBusinessGroup(businessGroup);
|
||||
if (businessGroupInDb == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "业务分组不存在");
|
||||
}
|
||||
List<Group> groupList = new LinkedList<>();
|
||||
groupList.add(businessGroupInDb);
|
||||
Group group = groupManager.queryOneByDeviceId(deviceId, businessGroup);
|
||||
if (group == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "虚拟组织不存在");
|
||||
}
|
||||
groupList.add(group);
|
||||
List<Group> allParent = getAllParent(group);
|
||||
groupList.addAll(allParent);
|
||||
return groupList;
|
||||
}
|
||||
|
||||
private List<Group> getAllParent(Group group) {
|
||||
if (group.getParentId() == null || group.getBusinessGroup() == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<Group> groupList = new ArrayList<>();
|
||||
Group parent = groupManager.queryOneByDeviceId(group.getParentDeviceId(), group.getBusinessGroup());
|
||||
if (parent == null) {
|
||||
return groupList;
|
||||
}
|
||||
List<Group> allParent = getAllParent(parent);
|
||||
allParent.add(parent);
|
||||
return allParent;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,62 @@
|
||||
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Preset;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IPTZService;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
import javax.sip.SipException;
|
||||
import java.text.ParseException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PTZServiceImpl implements IPTZService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private SIPCommander cmder;
|
||||
|
||||
|
||||
@Override
|
||||
public void ptz(Device device, String channelId, int cmdCode, int horizonSpeed, int verticalSpeed, int zoomSpeed) {
|
||||
try {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 云台控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frontEndCommand(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combindCode2) {
|
||||
try {
|
||||
cmder.frontEndCmd(device, channelId, cmdCode, parameter1, parameter2, combindCode2);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 前端控制: {}", e.getMessage());
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Preset> queryPresetList(String deviceId, String channelDeviceId) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPreset(Preset preset) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePreset(Integer qq) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -159,6 +159,11 @@ public class PlatformServiceImpl implements IPlatformService {
|
||||
@Override
|
||||
public PageInfo<Platform> queryPlatformList(int page, int count, String query) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<Platform> all = platformMapper.queryList(query);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
|
||||
@ -488,8 +488,7 @@ public class PlayServiceImpl implements IPlayService {
|
||||
log.info("[语音对讲]开始 获取发流端口失败 deviceId: {}, channelId: {},", device.getDeviceId(), channel.getDeviceId());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
sendRtpInfo.setOnlyAudio(true);
|
||||
sendRtpInfo.setPt(8);
|
||||
sendRtpInfo.setStatus(1);
|
||||
|
||||
@ -97,6 +97,11 @@ public class RegionServiceImpl implements IRegionService {
|
||||
@Override
|
||||
public PageInfo<Region> query(String query, int page, int count) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<Region> regionList = regionMapper.query(query, null);
|
||||
return new PageInfo<>(regionList);
|
||||
}
|
||||
@ -139,9 +144,14 @@ public class RegionServiceImpl implements IRegionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RegionTree> queryForTree(String query, Integer parent) {
|
||||
public List<RegionTree> queryForTree(String query, Integer parent, Boolean hasChannel) {
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<RegionTree> regionList = regionMapper.queryForTree(query, parent);
|
||||
if (parent != null) {
|
||||
if (parent != null && hasChannel != null && hasChannel) {
|
||||
Region parentRegion = regionMapper.queryOne(parent);
|
||||
if (parentRegion != null) {
|
||||
List<RegionTree> channelList = commonGBChannelMapper.queryForRegionTreeByCivilCode(query, parentRegion.getDeviceId());
|
||||
@ -224,4 +234,32 @@ public class RegionServiceImpl implements IRegionService {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Region> getPath(String deviceId) {
|
||||
Region region = regionMapper.queryByDeviceId(deviceId);
|
||||
if (region == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "行政区划不存在");
|
||||
}
|
||||
List<Region> allParent = getAllParent(region);
|
||||
allParent.add(region);
|
||||
return allParent;
|
||||
}
|
||||
|
||||
|
||||
private List<Region> getAllParent(Region region) {
|
||||
if (region.getParentId() == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
List<Region> regionList = new LinkedList<>();
|
||||
Region parent = regionMapper.queryByDeviceId(region.getParentDeviceId());
|
||||
if (parent == null) {
|
||||
return regionList;
|
||||
}
|
||||
regionList.add(parent);
|
||||
List<Region> allParent = getAllParent(parent);
|
||||
regionList.addAll(allParent);
|
||||
return regionList;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -91,17 +90,14 @@ public class SSRCFactory {
|
||||
* 获取后四位数SN,随机数
|
||||
*/
|
||||
private String getSN(String mediaServerId) {
|
||||
String sn = null;
|
||||
String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
|
||||
Long size = redisTemplate.opsForSet().size(redisKey);
|
||||
if (size == null || size == 0) {
|
||||
throw new RuntimeException("ssrc已经用完");
|
||||
} else {
|
||||
// 在集合中移除并返回一个随机成员。
|
||||
sn = (String) redisTemplate.opsForSet().pop(redisKey);
|
||||
redisTemplate.opsForSet().remove(redisKey, sn);
|
||||
return redisTemplate.opsForSet().pop(redisKey);
|
||||
}
|
||||
return sn;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -142,15 +142,10 @@ public class SIPCommander implements ISIPCommander {
|
||||
builder.append(strTmp, 0, 2);
|
||||
strTmp = String.format("%02X", parameter2);
|
||||
builder.append(strTmp, 0, 2);
|
||||
//优化zoom变倍速率
|
||||
if ((combineCode2 > 0) && (combineCode2 <16))
|
||||
{
|
||||
combineCode2 = 16;
|
||||
}
|
||||
strTmp = String.format("%X", combineCode2);
|
||||
builder.append(strTmp, 0, 1).append("0");
|
||||
strTmp = String.format("%02X", combineCode2 << 4);
|
||||
builder.append(strTmp, 0, 2);
|
||||
//计算校验码
|
||||
int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 & 0XF0)) % 0X100;
|
||||
int checkCode = (0XA5 + 0X0F + 0X01 + cmdCode + parameter1 + parameter2 + (combineCode2 << 4)) % 0X100;
|
||||
strTmp = String.format("%02X", checkCode);
|
||||
builder.append(strTmp, 0, 2);
|
||||
return builder.toString();
|
||||
|
||||
@ -737,6 +737,8 @@ public class SIPCommanderForPlatform implements ISIPCommanderForPlatform {
|
||||
}
|
||||
|
||||
content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc
|
||||
// f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
|
||||
content.append("f=v/////a/1/8/1\r\n");
|
||||
CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(platform.getDeviceIp()), platform.getTransport());
|
||||
|
||||
Request request = headerProviderPlatformProvider.createInviteRequest(platform, channel.getGbDeviceId(),
|
||||
|
||||
@ -2,7 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.respon
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Preset;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||
@ -79,11 +79,11 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent
|
||||
return;
|
||||
}
|
||||
int sumNum = Integer.parseInt(presetListNumElement.attributeValue("Num"));
|
||||
List<PresetQuerySipReq> presetQuerySipReqList = new ArrayList<>();
|
||||
List<Preset> presetQuerySipReqList = new ArrayList<>();
|
||||
if (sumNum > 0) {
|
||||
for (Iterator<Element> presetIterator = presetListNumElement.elementIterator(); presetIterator.hasNext(); ) {
|
||||
Element itemListElement = presetIterator.next();
|
||||
PresetQuerySipReq presetQuerySipReq = new PresetQuerySipReq();
|
||||
Preset presetQuerySipReq = new Preset();
|
||||
for (Iterator<Element> itemListIterator = itemListElement.elementIterator(); itemListIterator.hasNext(); ) {
|
||||
// 遍历item
|
||||
Element itemOne = itemListIterator.next();
|
||||
|
||||
@ -33,6 +33,10 @@ public class MediaInfo {
|
||||
private Integer width;
|
||||
@Schema(description = "视频高度")
|
||||
private Integer height;
|
||||
@Schema(description = "FPS")
|
||||
private Integer fps;
|
||||
@Schema(description = "丢包率")
|
||||
private Integer loss;
|
||||
@Schema(description = "音频编码类型")
|
||||
private String audioCodec;
|
||||
@Schema(description = "音频通道数")
|
||||
@ -58,6 +62,7 @@ public class MediaInfo {
|
||||
@Schema(description = "服务ID")
|
||||
private String serverId;
|
||||
|
||||
|
||||
public static MediaInfo getInstance(JSONObject jsonObject, MediaServer mediaServer, String serverId) {
|
||||
MediaInfo mediaInfo = new MediaInfo();
|
||||
mediaInfo.setMediaServer(mediaServer);
|
||||
@ -111,7 +116,14 @@ public class MediaInfo {
|
||||
Integer codecType = trackJson.getInteger("codec_type");
|
||||
Integer sampleRate = trackJson.getInteger("sample_rate");
|
||||
Integer height = trackJson.getInteger("height");
|
||||
Integer width = trackJson.getInteger("height");
|
||||
Integer width = trackJson.getInteger("width");
|
||||
Integer fps = trackJson.getInteger("fps");
|
||||
Integer loss = trackJson.getInteger("loss");
|
||||
Integer frames = trackJson.getInteger("frames");
|
||||
Long keyFrames = trackJson.getLongValue("key_frames");
|
||||
Integer gop_interval_ms = trackJson.getInteger("gop_interval_ms");
|
||||
Long gop_size = trackJson.getLongValue("gop_size");
|
||||
|
||||
Long duration = trackJson.getLongValue("duration");
|
||||
if (channels != null) {
|
||||
mediaInfo.setAudioChannels(channels);
|
||||
@ -125,6 +137,12 @@ public class MediaInfo {
|
||||
if (width != null) {
|
||||
mediaInfo.setWidth(width);
|
||||
}
|
||||
if (fps != null) {
|
||||
mediaInfo.setFps(fps);
|
||||
}
|
||||
if (loss != null) {
|
||||
mediaInfo.setLoss(loss);
|
||||
}
|
||||
if (duration > 0L) {
|
||||
mediaInfo.setDuration(duration);
|
||||
}
|
||||
|
||||
@ -14,7 +14,6 @@ import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent;
|
||||
import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerDeleteEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOfflineEvent;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOnlineEvent;
|
||||
@ -318,11 +317,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
redisTemplate.opsForHash().put(key, mediaServerInDataBase.getId(), mediaServerInDataBase);
|
||||
if (mediaServerInDataBase.isStatus()) {
|
||||
resetOnlineServerItem(mediaServerInDataBase);
|
||||
}else {
|
||||
// 发送事件
|
||||
MediaServerChangeEvent event = new MediaServerChangeEvent(this);
|
||||
event.setMediaServerItemList(mediaServerInDataBase);
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -444,11 +438,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
|
||||
mediaServerMapper.add(mediaServer);
|
||||
if (mediaServer.isStatus()) {
|
||||
mediaNodeServerService.online(mediaServer);
|
||||
}else {
|
||||
// 发送事件
|
||||
MediaServerChangeEvent event = new MediaServerChangeEvent(this);
|
||||
event.setMediaServerItemList(mediaServer);
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -118,15 +118,6 @@ public class ZLMHttpHookListener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。
|
||||
*/
|
||||
// @ResponseBody
|
||||
// @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8")
|
||||
// public HookResult onStreamChanged(@RequestBody JSONObject param) {
|
||||
// System.out.println(11);
|
||||
// return HookResult.SUCCESS();
|
||||
// }
|
||||
/**
|
||||
* rtsp/rtmp流注册或注销时触发此事件;此事件对回复不敏感。
|
||||
*/
|
||||
@ -299,7 +290,7 @@ public class ZLMHttpHookListener {
|
||||
@ResponseBody
|
||||
@PostMapping(value = "/on_record_mp4", produces = "application/json;charset=UTF-8")
|
||||
public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) {
|
||||
log.info("[ZLM HOOK] 录像完成事件:{}->{}", param.getMediaServerId(), param.getFile_path());
|
||||
log.info("[ZLM HOOK] 录像完成:时长: {}, {}->{}",param.getTime_len(), param.getMediaServerId(), param.getFile_path());
|
||||
|
||||
try {
|
||||
MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
|
||||
|
||||
@ -180,7 +180,7 @@ public class ZLMMediaNodeServerService implements IMediaNodeServerService {
|
||||
if (mediaList.getInteger("code") == 0) {
|
||||
JSONArray data = mediaList.getJSONArray("data");
|
||||
if (data == null) {
|
||||
return null;
|
||||
return streamInfoList;
|
||||
}
|
||||
JSONObject mediaJSON = data.getJSONObject(0);
|
||||
MediaInfo mediaInfo = MediaInfo.getInstance(mediaJSON, mediaServer, userSetting.getServerId());
|
||||
|
||||
@ -71,6 +71,11 @@ public class CloudRecordServiceImpl implements ICloudRecordService {
|
||||
|
||||
}
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<CloudRecordItem> all = cloudRecordServiceMapper.getList(query, app, stream, startTimeStamp, endTimeStamp,
|
||||
callId, mediaServerItems, null);
|
||||
return new PageInfo<>(all);
|
||||
|
||||
@ -41,7 +41,7 @@ public interface CloudRecordServiceMapper {
|
||||
"select * " +
|
||||
" from wvp_cloud_record " +
|
||||
" where 0 = 0" +
|
||||
" <if test='query != null'> AND (app LIKE concat('%',#{query},'%') OR stream LIKE concat('%',#{query},'%') )</if> " +
|
||||
" <if test='query != null'> AND (app LIKE concat('%',#{query},'%') escape '/' OR stream LIKE concat('%',#{query},'%') escape '/' )</if> " +
|
||||
" <if test= 'app != null '> and app=#{app}</if>" +
|
||||
" <if test= 'stream != null '> and stream=#{stream}</if>" +
|
||||
" <if test= 'startTimeStamp != null '> and end_time >= #{startTimeStamp}</if>" +
|
||||
|
||||
@ -30,7 +30,7 @@ import java.util.Map;
|
||||
* 拉流代理接口
|
||||
*/
|
||||
@Tag(name = "拉流代理", description = "")
|
||||
@Controller
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/api/proxy")
|
||||
public class StreamProxyController {
|
||||
|
||||
@ -48,8 +48,8 @@ public interface StreamProxyMapper {
|
||||
@SelectProvider(type = StreamProxyProvider.class, method = "selectOneByAppAndStream")
|
||||
StreamProxy selectOneByAppAndStream(@Param("app") String app, @Param("stream") String stream);
|
||||
|
||||
@SelectProvider(type = StreamProxyProvider.class, method = "selectForEnableInMediaServer")
|
||||
List<StreamProxy> selectForEnableInMediaServer(@Param("mediaServerId") String mediaServerId, @Param("enable") boolean enable);
|
||||
@SelectProvider(type = StreamProxyProvider.class, method = "selectForPushingInMediaServer")
|
||||
List<StreamProxy> selectForPushingInMediaServer(@Param("mediaServerId") String mediaServerId, @Param("enable") boolean enable);
|
||||
|
||||
|
||||
@Select("select count(1) from wvp_stream_proxy")
|
||||
|
||||
@ -19,9 +19,8 @@ public class StreamProxyProvider {
|
||||
return getBaseSelectSql() + " WHERE st.id = " + params.get("id");
|
||||
}
|
||||
|
||||
public String selectForEnableInMediaServer(Map<String, Object> params ){
|
||||
return getBaseSelectSql() + String.format(" WHERE st.enable=%s and st.media_server_id= '%s' order by st.create_time desc",
|
||||
params.get("enable"), params.get("mediaServerId"));
|
||||
public String selectForPushingInMediaServer(Map<String, Object> params ){
|
||||
return getBaseSelectSql() + " WHERE st.pulling=1 and st.media_server_id=#{mediaServerId} order by st.create_time desc";
|
||||
}
|
||||
|
||||
public String selectOneByAppAndStream(Map<String, Object> params ){
|
||||
@ -36,13 +35,13 @@ public class StreamProxyProvider {
|
||||
if (params.get("query") != null) {
|
||||
sqlBuild.append(" AND ")
|
||||
.append(" (")
|
||||
.append(" st.app LIKE ").append("'%").append(params.get("query")).append("%'")
|
||||
.append(" st.app LIKE ").append("'%").append(params.get("query")).append("%' escape '/'")
|
||||
.append(" OR")
|
||||
.append(" st.stream LIKE ").append("'%").append(params.get("query")).append("%'")
|
||||
.append(" st.stream LIKE ").append("'%").append(params.get("query")).append("%' escape '/'")
|
||||
.append(" OR")
|
||||
.append(" wdc.gb_device_id LIKE ").append("'%").append(params.get("query")).append("%'")
|
||||
.append(" wdc.gb_device_id LIKE ").append("'%").append(params.get("query")).append("%' escape '/'")
|
||||
.append(" OR")
|
||||
.append(" wdc.gb_name LIKE ").append("'%").append(params.get("query")).append("%'")
|
||||
.append(" wdc.gb_name LIKE ").append("'%").append(params.get("query")).append("%' escape '/'")
|
||||
.append(" )")
|
||||
;
|
||||
}
|
||||
|
||||
@ -246,6 +246,11 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
@Override
|
||||
public PageInfo<StreamProxy> getAll(Integer page, Integer count, String query, Boolean pulling, String mediaServerId) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<StreamProxy> all = streamProxyMapper.selectAll(query, pulling, mediaServerId);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
@ -291,7 +296,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
// 这里主要是控制数据库/redis缓存/以及zlm中存在的代理流 三者状态一致。以数据库中数据为根本
|
||||
redisCatchStorage.removeStream(mediaServer.getId(), "PULL");
|
||||
|
||||
List<StreamProxy> streamProxies = streamProxyMapper.selectForEnableInMediaServer(mediaServer.getId(), true);
|
||||
List<StreamProxy> streamProxies = streamProxyMapper.selectForPushingInMediaServer(mediaServer.getId(), true);
|
||||
if (streamProxies.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@ -348,18 +353,16 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
streamProxyMapper.deleteByList(streamProxiesForRemove);
|
||||
}
|
||||
|
||||
|
||||
if (!streamProxyMapForDb.isEmpty()) {
|
||||
for (StreamProxy streamProxy : streamProxyMapForDb.values()) {
|
||||
log.info("恢复流代理," + streamProxy.getApp() + "/" + streamProxy.getStream());
|
||||
mediaServerService.startProxy(mediaServer, streamProxy);
|
||||
streamProxyMapper.offline(streamProxy.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zlmServerOffline(MediaServer mediaServer) {
|
||||
List<StreamProxy> streamProxies = streamProxyMapper.selectForEnableInMediaServer(mediaServer.getId(), true);
|
||||
List<StreamProxy> streamProxies = streamProxyMapper.selectForPushingInMediaServer(mediaServer.getId(), true);
|
||||
|
||||
// 清理redis相关的缓存
|
||||
redisCatchStorage.removeStream(mediaServer.getId(), "PULL");
|
||||
@ -382,11 +385,14 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
|
||||
streamProxiesForSendMessage.add(streamProxy);
|
||||
}
|
||||
}
|
||||
// 移除开启了无人观看自动移除的流
|
||||
streamProxyMapper.deleteByList(streamProxiesForRemove);
|
||||
// 修改国标关联的国标通道的状态
|
||||
gbChannelService.offline(channelListForOffline);
|
||||
|
||||
if (!streamProxiesForRemove.isEmpty()) {
|
||||
// 移除开启了无人观看自动移除的流
|
||||
streamProxyMapper.deleteByList(streamProxiesForRemove);
|
||||
}
|
||||
if (!streamProxiesForRemove.isEmpty()) {
|
||||
// 修改国标关联的国标通道的状态
|
||||
gbChannelService.offline(channelListForOffline);
|
||||
}
|
||||
if (!streamProxiesForSendMessage.isEmpty()) {
|
||||
for (StreamProxy streamProxy : streamProxiesForSendMessage) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
|
||||
@ -84,7 +84,7 @@ public class StreamPush extends CommonGBChannel implements Comparable<StreamPush
|
||||
- DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(streamPushItem.getCreateTime())).intValue();
|
||||
}
|
||||
|
||||
public StreamPush getInstance(StreamInfo streamInfo) {
|
||||
public static StreamPush getInstance(StreamInfo streamInfo) {
|
||||
StreamPush streamPush = new StreamPush();
|
||||
streamPush.setApp(streamInfo.getApp());
|
||||
if (streamInfo.getMediaServer() != null) {
|
||||
|
||||
@ -43,7 +43,7 @@ import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Tag(name = "推流信息管理")
|
||||
@Controller
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/api/push")
|
||||
public class StreamPushController {
|
||||
|
||||
@ -48,8 +48,8 @@ public interface StreamPushMapper {
|
||||
" on st.id = wdc.stream_push_id " +
|
||||
" WHERE " +
|
||||
" 1=1 " +
|
||||
" <if test='query != null'> AND (st.app LIKE concat('%',#{query},'%') OR st.stream LIKE concat('%',#{query},'%') " +
|
||||
" OR wdc.gb_device_id LIKE concat('%',#{query},'%') OR wdc.gb_name LIKE concat('%',#{query},'%'))</if> " +
|
||||
" <if test='query != null'> AND (st.app LIKE concat('%',#{query},'%') escape '/' OR st.stream LIKE concat('%',#{query},'%') escape '/' " +
|
||||
" OR wdc.gb_device_id LIKE concat('%',#{query},'%') escape '/' OR wdc.gb_name LIKE concat('%',#{query},'%') escape '/')</if> " +
|
||||
" <if test='pushing == true' > AND st.pushing=1</if>" +
|
||||
" <if test='pushing == false' > AND st.pushing=0 </if>" +
|
||||
" <if test='mediaServerId != null' > AND st.media_server_id=#{mediaServerId} </if>" +
|
||||
|
||||
@ -175,6 +175,11 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
@Override
|
||||
public PageInfo<StreamPush> getPushList(Integer page, Integer count, String query, Boolean pushing, String mediaServerId) {
|
||||
PageHelper.startPage(page, count);
|
||||
if (query != null) {
|
||||
query = query.replaceAll("/", "//")
|
||||
.replaceAll("%", "/%")
|
||||
.replaceAll("_", "/_");
|
||||
}
|
||||
List<StreamPush> all = streamPushMapper.selectAll(query, pushing, mediaServerId);
|
||||
return new PageInfo<>(all);
|
||||
}
|
||||
@ -530,7 +535,7 @@ public class StreamPushServiceImpl implements IStreamPushService {
|
||||
String key = streamInfo.getApp() + "_" + streamInfo.getStream();
|
||||
StreamPush streamPushItem = result.get(key);
|
||||
if (streamPushItem == null) {
|
||||
streamPushItem = streamPushItem.getInstance(streamInfo);
|
||||
streamPushItem = StreamPush.getInstance(streamInfo);
|
||||
result.put(key, streamPushItem);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,9 @@ import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.media.bean.MediaInfo;
|
||||
import com.genersoft.iot.vmp.media.bean.MediaServer;
|
||||
import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent;
|
||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
||||
import com.genersoft.iot.vmp.service.bean.MediaServerLoad;
|
||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||
@ -28,6 +30,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import oshi.SystemInfo;
|
||||
@ -73,18 +76,18 @@ public class ServerController {
|
||||
@Autowired
|
||||
private IStreamPushService pushService;
|
||||
|
||||
|
||||
@Autowired
|
||||
private IStreamProxyService proxyService;
|
||||
|
||||
|
||||
@Value("${server.port}")
|
||||
private int serverPort;
|
||||
|
||||
|
||||
@Autowired
|
||||
private IRedisCatchStorage redisCatchStorage;
|
||||
|
||||
@Autowired
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
|
||||
@GetMapping(value = "/media_server/list")
|
||||
@ResponseBody
|
||||
@ -134,13 +137,17 @@ public class ServerController {
|
||||
@Parameter(name = "mediaServerItem", description = "流媒体信息", required = true)
|
||||
@PostMapping(value = "/media_server/save")
|
||||
@ResponseBody
|
||||
public void saveMediaServer(@RequestBody MediaServer mediaServerItem) {
|
||||
MediaServer mediaServerItemInDatabase = mediaServerService.getOneFromDatabase(mediaServerItem.getId());
|
||||
public void saveMediaServer(@RequestBody MediaServer mediaServer) {
|
||||
MediaServer mediaServerItemInDatabase = mediaServerService.getOneFromDatabase(mediaServer.getId());
|
||||
|
||||
if (mediaServerItemInDatabase != null) {
|
||||
mediaServerService.update(mediaServerItem);
|
||||
mediaServerService.update(mediaServer);
|
||||
} else {
|
||||
mediaServerService.add(mediaServerItem);
|
||||
mediaServerService.add(mediaServer);
|
||||
// 发送事件
|
||||
MediaServerChangeEvent event = new MediaServerChangeEvent(this);
|
||||
event.setMediaServerItemList(mediaServer);
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,6 +163,20 @@ public class ServerController {
|
||||
mediaServerService.delete(mediaServer);
|
||||
}
|
||||
|
||||
@Operation(summary = "获取流信息", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "app", description = "应用名", required = true)
|
||||
@Parameter(name = "stream", description = "流ID", required = true)
|
||||
@Parameter(name = "mediaServerId", description = "流媒体ID", required = true)
|
||||
@GetMapping(value = "/media_server/media_info")
|
||||
@ResponseBody
|
||||
public MediaInfo getMediaInfo(String app, String stream, String mediaServerId) {
|
||||
MediaServer mediaServer = mediaServerService.getOne(mediaServerId);
|
||||
if (mediaServer == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR100.getCode(), "流媒体不存在");
|
||||
}
|
||||
return mediaServerService.getMediaInfo(mediaServer, app, stream);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "重启服务", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@GetMapping(value = "/restart")
|
||||
|
||||
@ -4,7 +4,7 @@ import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.PresetQuerySipReq;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Preset;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
|
||||
@ -215,13 +215,13 @@ public class ApiDeviceController {
|
||||
}
|
||||
|
||||
deferredResultEx.setFilter(filterResult->{
|
||||
List<PresetQuerySipReq> presetQuerySipReqList = (List<PresetQuerySipReq>)filterResult;
|
||||
List<Preset> presetQuerySipReqList = (List<Preset>)filterResult;
|
||||
HashMap<String, Object> resultMap = new HashMap<>();
|
||||
resultMap.put("DeviceID", code);
|
||||
resultMap.put("Result", "OK");
|
||||
resultMap.put("SumNum", presetQuerySipReqList.size());
|
||||
ArrayList<Map<String, Object>> presetItemList = new ArrayList<>(presetQuerySipReqList.size());
|
||||
for (PresetQuerySipReq presetQuerySipReq : presetQuerySipReqList) {
|
||||
for (Preset presetQuerySipReq : presetQuerySipReqList) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("PresetID", presetQuerySipReq.getPresetId());
|
||||
item.put("PresetName", presetQuerySipReq.getPresetName());
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
"@wchbrad/vue-easy-tree": "^1.0.12",
|
||||
"axios": "^0.24.0",
|
||||
"core-js": "^2.6.5",
|
||||
"defineProperty": "link:@babel/runtime/helpers/defineProperty",
|
||||
"echarts": "^4.9.0",
|
||||
"element-ui": "^2.15.14",
|
||||
"fingerprintjs2": "^2.1.2",
|
||||
@ -24,7 +23,6 @@
|
||||
"ol": "^6.14.1",
|
||||
"postcss-pxtorem": "^5.1.1",
|
||||
"screenfull": "5.1.0",
|
||||
"slicedToArray": "link:@babel/runtime/helpers/slicedToArray",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"uuid": "^8.3.2",
|
||||
"v-charts": "^1.19.0",
|
||||
|
||||
@ -52,17 +52,17 @@
|
||||
<el-table-column prop="stream" label="流ID" width="380">
|
||||
</el-table-column>
|
||||
<el-table-column label="开始时间">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
{{formatTimeStamp(scope.row.startTime)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
{{formatTimeStamp(scope.row.endTime)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="时长">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-tag>{{formatTime(scope.row.timeLen)}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -71,7 +71,7 @@
|
||||
<el-table-column prop="mediaServerId" label="流媒体">
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" icon="el-icon-video-play" type="text" @click="play(scope.row)">播放
|
||||
</el-button>
|
||||
<el-button size="medium" icon="el-icon-download" type="text" @click="downloadFile(scope.row)">下载
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
<el-table-column prop="deviceId" label="设备编号" min-width="200" >
|
||||
</el-table-column>
|
||||
<el-table-column label="地址" min-width="160" >
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag v-if="scope.row.hostAddress" size="medium">{{ scope.row.hostAddress }}</el-tag>
|
||||
<el-tag v-if="!scope.row.hostAddress" size="medium">未知</el-tag>
|
||||
@ -40,7 +40,7 @@
|
||||
<el-table-column prop="transport" label="信令传输模式" min-width="120" >
|
||||
</el-table-column>
|
||||
<el-table-column label="流传输模式" min-width="160" >
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-select size="mini" @change="transportChange(scope.row)" v-model="scope.row.streamMode" placeholder="请选择" style="width: 120px">
|
||||
<el-option key="UDP" label="UDP" value="UDP"></el-option>
|
||||
<el-option key="TCP-ACTIVE" label="TCP主动模式" value="TCP-ACTIVE"></el-option>
|
||||
@ -51,7 +51,7 @@
|
||||
<el-table-column prop="channelCount" label="通道数" min-width="120" >
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.onLine">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.onLine">离线</el-tag>
|
||||
@ -68,7 +68,7 @@
|
||||
<!-- </el-table-column>-->
|
||||
|
||||
<el-table-column label="操作" min-width="380" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button type="text" size="medium" v-bind:disabled="scope.row.online==0" icon="el-icon-refresh" @click="refDevice(scope.row)"
|
||||
@mouseover="getTooltipContent(scope.row.deviceId)">刷新
|
||||
</el-button>
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
<el-table-column prop="name" label="名称"></el-table-column>
|
||||
<el-table-column prop="serverGBId" label="平台编号" min-width="200"></el-table-column>
|
||||
<el-table-column label="是否启用" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
|
||||
@ -27,7 +27,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.status">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.status">离线</el-tag>
|
||||
@ -35,7 +35,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="地址" min-width="160">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium">{{ scope.row.serverIp }}:{{ scope.row.serverPort }}</el-tag>
|
||||
</div>
|
||||
@ -45,7 +45,7 @@
|
||||
<el-table-column prop="transport" label="信令传输模式" min-width="120"></el-table-column>
|
||||
<el-table-column prop="channelCount" label="通道数" min-width="120"></el-table-column>
|
||||
<el-table-column label="订阅信息" min-width="120" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<i v-if="scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅"
|
||||
class="iconfont icon-gbaojings subscribe-on "></i>
|
||||
<i v-if="!scope.row.alarmSubscribe" style="font-size: 20px" title="报警订阅"
|
||||
@ -60,7 +60,7 @@
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" min-width="240" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="editPlatform(scope.row)">编辑</el-button>
|
||||
<el-button size="medium" icon="el-icon-share" type="text" @click="chooseChannel(scope.row)">通道共享
|
||||
</el-button>
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
<el-table-column prop="app" label="流应用名" min-width="120" show-overflow-tooltip/>
|
||||
<el-table-column prop="stream" label="流ID" min-width="120" show-overflow-tooltip/>
|
||||
<el-table-column label="流地址" min-width="250" show-overflow-tooltip >
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium">
|
||||
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" v-clipboard="scope.row.srcUrl" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></i>
|
||||
@ -47,7 +47,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="mediaServerId" label="流媒体" min-width="180" ></el-table-column>
|
||||
<el-table-column label="代理方式" width="100" >
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
{{scope.row.type === "default"? "默认":"FFMPEG代理"}}
|
||||
</div>
|
||||
@ -56,7 +56,7 @@
|
||||
|
||||
<el-table-column prop="gbDeviceId" label="国标编码" min-width="180" show-overflow-tooltip/>
|
||||
<el-table-column label="拉流状态" min-width="120" >
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.pulling">正在拉流</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.pulling">尚未拉流</el-tag>
|
||||
@ -64,7 +64,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="启用" min-width="120" >
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.enable">已启用</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.enable">未启用</el-tag>
|
||||
@ -73,7 +73,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" min-width="150" show-overflow-tooltip/>
|
||||
<el-table-column label="操作" width="400" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" icon="el-icon-video-play" type="text" @click="play(scope.row)">播放</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-switch-button" style="color: #f56c6c" type="text" v-if="scope.row.pulling" @click="stopPlay(scope.row)">停止</el-button>
|
||||
|
||||
@ -51,7 +51,7 @@
|
||||
<el-table-column prop="stream" label="流ID" min-width="200">
|
||||
</el-table-column>
|
||||
<el-table-column label="推流状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-tag size="medium" v-if="scope.row.pushing">推流中</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.pushing">已停止</el-tag>
|
||||
</template>
|
||||
@ -59,7 +59,7 @@
|
||||
<el-table-column prop="gbDeviceId" label="国标编码" min-width="200" >
|
||||
</el-table-column>
|
||||
<el-table-column label="位置信息" min-width="200">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<span size="medium" v-if="scope.row.gbLongitude && scope.row.gbLatitude">{{scope.row.gbLongitude}}<br/>{{scope.row.gbLatitude}}</span>
|
||||
<span size="medium" v-if="!scope.row.gbLongitude || !scope.row.gbLatitude">无</span>
|
||||
</template>
|
||||
@ -67,7 +67,7 @@
|
||||
<el-table-column prop="mediaServerId" label="流媒体" min-width="200" >
|
||||
</el-table-column>
|
||||
<el-table-column label="开始时间" min-width="200">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button-group>
|
||||
{{ scope.row.pushTime == null? "-":scope.row.pushTime }}
|
||||
</el-button-group>
|
||||
@ -76,7 +76,7 @@
|
||||
|
||||
|
||||
<el-table-column label="操作" min-width="360" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" icon="el-icon-video-play"@click="playPush(scope.row)" type="text">播放
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
<el-table-column prop="pushKey" label="pushkey" min-width="160"/>
|
||||
<el-table-column prop="role.name" label="类型" min-width="160"/>
|
||||
<el-table-column label="操作" min-width="450" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="edit(scope.row)">修改密码</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="changePushKey(scope.row)">修改pushkey</el-button>
|
||||
|
||||
@ -73,7 +73,7 @@
|
||||
<el-table-column prop="manufacturer" label="厂家" min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="位置信息" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<span size="medium" v-if="scope.row.longitude && scope.row.latitude">{{scope.row.longitude}}<br/>{{scope.row.latitude}}</span>
|
||||
<span size="medium" v-if="!scope.row.longitude || !scope.row.latitude">无</span>
|
||||
</template>
|
||||
@ -84,13 +84,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开启音频" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-switch @change="updateChannel(scope.row)" v-model="scope.row.hasAudio" active-color="#409EFF">
|
||||
</el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="码流类型" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-select size="mini" style="margin-right: 1rem;" @change="channelSubStreamChange(scope.row)" v-model="scope.row.streamIdentification"
|
||||
placeholder="请选择码流类型" default-first-option >
|
||||
<el-option label="stream:0(主码流)" value="stream:0"></el-option>
|
||||
@ -105,7 +105,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.status === 'ON'">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="scope.row.status !== 'ON'">离线</el-tag>
|
||||
@ -113,7 +113,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="340" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" v-bind:disabled="device == null || device.online === 0" icon="el-icon-video-play"
|
||||
type="text" @click="sendDevicePush(scope.row)">播放
|
||||
</el-button>
|
||||
|
||||
@ -7,7 +7,9 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="编码" >
|
||||
<el-input v-model="form.gbDeviceId" placeholder="请输入通道编码">
|
||||
<el-button slot="append" @click="buildDeviceIdCode(form.gbDeviceId)">生成</el-button>
|
||||
<template v-slot:append>
|
||||
<el-button @click="buildDeviceIdCode(form.gbDeviceId)">生成</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备厂商" >
|
||||
@ -18,7 +20,11 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="行政区域" >
|
||||
<el-input v-model="form.gbCivilCode" placeholder="请输入行政区域"></el-input>
|
||||
<el-input v-model="form.gbCivilCode" placeholder="请输入行政区域">
|
||||
<template v-slot:append>
|
||||
<el-button @click="chooseCivilCode()">选择</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="安装地址" >
|
||||
@ -31,7 +37,11 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="父节点编码" >
|
||||
<el-input v-model="form.gbParentId" placeholder="请输入父节点编码"></el-input>
|
||||
<el-input v-model="form.gbParentId" placeholder="请输入父节点编码或选择所属虚拟组织">
|
||||
<template v-slot:append>
|
||||
<el-button @click="chooseGroup()">选择</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备状态" >
|
||||
<el-select v-model="form.gbStatus" style="width: 100%" placeholder="请选择设备状态">
|
||||
@ -202,16 +212,22 @@
|
||||
|
||||
</el-form>
|
||||
<channelCode ref="channelCode"></channelCode>
|
||||
<chooseCivilCode ref="chooseCivilCode"></chooseCivilCode>
|
||||
<chooseGroup ref="chooseGroup"></chooseGroup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import channelCode from './../dialog/channelCode'
|
||||
import ChooseCivilCode from "../dialog/chooseCivilCode.vue";
|
||||
import ChooseGroup from "../dialog/chooseGroup.vue";
|
||||
|
||||
export default {
|
||||
name: "CommonChannelEdit",
|
||||
props: [ 'id', 'dataForm', 'saveSuccess', 'cancel'],
|
||||
components: {
|
||||
ChooseCivilCode,
|
||||
ChooseGroup,
|
||||
channelCode,
|
||||
},
|
||||
created() {
|
||||
@ -360,6 +376,17 @@ export default {
|
||||
console.log("code22===> " + code)
|
||||
}, deviceId);
|
||||
},
|
||||
chooseCivilCode: function (){
|
||||
this.$refs.chooseCivilCode.openDialog(code=>{
|
||||
this.form.gbCivilCode = code;
|
||||
});
|
||||
},
|
||||
chooseGroup: function (){
|
||||
this.$refs.chooseGroup.openDialog((deviceId, businessGroupId)=>{
|
||||
this.form.gbBusinessGroupId = businessGroupId;
|
||||
this.form.gbParentId = deviceId;
|
||||
});
|
||||
},
|
||||
cancelSubmit: function (){
|
||||
if(this.cancel) {
|
||||
this.cancel()
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
|
||||
</el-header>
|
||||
<el-main style="background-color: #ffffff;">
|
||||
<RegionTree v-if="showRegion" ref="regionTree" :edit="false" :showHeader="false" :clickEvent="treeNodeClickEvent" ></RegionTree>
|
||||
<GroupTree v-if="!showRegion" ref="groupTree" :edit="false" :showHeader="false" :clickEvent="treeNodeClickEvent" ></GroupTree>
|
||||
<RegionTree v-if="showRegion" ref="regionTree" :edit="false" :showHeader="false" :hasChannel="true" :clickEvent="treeNodeClickEvent" ></RegionTree>
|
||||
<GroupTree v-if="!showRegion" ref="groupTree" :edit="false" :showHeader="false" :hasChannel="true" :clickEvent="treeNodeClickEvent" ></GroupTree>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</div>
|
||||
|
||||
@ -4,20 +4,21 @@
|
||||
<div class="page-title">业务分组</div>
|
||||
<div class="page-header-btn">
|
||||
<div style="display: inline;">
|
||||
<el-input @input="search" style="visibility:hidden; margin-right: 1rem; width: 12rem;" size="mini" placeholder="关键字"
|
||||
<el-input @input="search" style="visibility:hidden; margin-right: 1rem; width: 12rem;" size="mini"
|
||||
placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
||||
|
||||
<el-checkbox v-model="showCode">显示编号</el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showHeader" style="height: 2rem; background-color: #FFFFFF" ></div>
|
||||
<div v-if="showHeader" style="height: 2rem; background-color: #FFFFFF"></div>
|
||||
<div>
|
||||
<vue-easy-tree
|
||||
class="flow-tree"
|
||||
ref="veTree"
|
||||
node-key="treeId"
|
||||
height="78vh"
|
||||
:height="treeHeight?treeHeight:'78vh'"
|
||||
lazy
|
||||
style="padding: 0 0 2rem 0.5rem"
|
||||
:load="loadNode"
|
||||
@ -27,20 +28,21 @@
|
||||
@node-contextmenu="contextmenuEventHandler"
|
||||
@node-click="nodeClickHandler"
|
||||
>
|
||||
<span class="custom-tree-node" slot-scope="{ node, data }">
|
||||
<span @click.stop v-if="edit">
|
||||
<el-radio v-if="node.data.type === 0 && node.level > 2" style="margin-right: 0" v-model="chooseId" @input="chooseIdChange(node.data.treeId, node.data.deviceId, node.data.businessGroup)" :label="node.data.deviceId">{{''}}</el-radio>
|
||||
<template v-slot:default="{ node, data }">
|
||||
<span class="custom-tree-node">
|
||||
<span v-if="node.data.type === 0 && chooseId !== node.data.deviceId" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
|
||||
<span v-if="node.data.type === 0 && chooseId === node.data.deviceId" style="color: #c60135;" class="iconfont icon-bianzubeifen3"></span>
|
||||
<span v-if="node.data.type === 1 && node.data.status === 'ON'" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
|
||||
<span v-if="node.data.type === 1 && node.data.status !== 'ON'" style="color: #808181" class="iconfont icon-shexiangtou2"></span>
|
||||
<span style=" padding-left: 1px" v-if="node.data.deviceId !=='' && showCode" :title="node.data.deviceId">{{ node.label }}(编号:{{ node.data.deviceId }})</span>
|
||||
<span style=" padding-left: 1px" v-if="node.data.deviceId ==='' || !showCode" :title="node.data.deviceId">{{ node.label }}</span>
|
||||
</span>
|
||||
<span v-if="node.data.type === 0" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
|
||||
<span v-if="node.data.type === 1 && node.data.status === 'ON'" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
|
||||
<span v-if="node.data.type === 1 && node.data.status !== 'ON'" style="color: #808181" class="iconfont icon-shexiangtou2"></span>
|
||||
<span style=" padding-left: 1px" v-if="node.data.deviceId !=='' && showCode" :title="node.data.deviceId">{{ node.label }}(编号:{{ node.data.deviceId }})</span>
|
||||
<span style=" padding-left: 1px" v-if="node.data.deviceId ==='' || !showCode" :title="node.data.deviceId">{{ node.label }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</vue-easy-tree>
|
||||
</div>
|
||||
<groupEdit ref="groupEdit"></groupEdit>
|
||||
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
|
||||
<gbChannelSelect ref="gbChannelSelect" dataType="group"></gbChannelSelect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -48,10 +50,12 @@
|
||||
import VueEasyTree from "@wchbrad/vue-easy-tree";
|
||||
import groupEdit from './../dialog/groupEdit'
|
||||
import gbDeviceSelect from './../dialog/GbDeviceSelect'
|
||||
import GbChannelSelect from "../dialog/GbChannelSelect.vue";
|
||||
|
||||
export default {
|
||||
name: 'DeviceTree',
|
||||
components: {
|
||||
GbChannelSelect,
|
||||
VueEasyTree, groupEdit, gbDeviceSelect
|
||||
},
|
||||
data() {
|
||||
@ -66,7 +70,7 @@ export default {
|
||||
treeData: [],
|
||||
}
|
||||
},
|
||||
props: ['edit', 'clickEvent', 'chooseIdChange', 'onChannelChange', 'showHeader'],
|
||||
props: ['edit','enableAddChannel', 'clickEvent', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToGroup', 'treeHeight'],
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
@ -92,7 +96,8 @@ export default {
|
||||
url: `/api/group/tree/list`,
|
||||
params: {
|
||||
query: this.searchSrt,
|
||||
parent: node.data.id
|
||||
parent: node.data.id,
|
||||
hasChannel: this.hasChannel
|
||||
}
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
@ -111,85 +116,53 @@ export default {
|
||||
if (!this.edit) {
|
||||
return;
|
||||
}
|
||||
console.log(node.level)
|
||||
if (node.data.type === 1) {
|
||||
data.parentId = node.parent.data.id;
|
||||
this.$contextmenu({
|
||||
items: [
|
||||
{
|
||||
label: "移除通道",
|
||||
icon: "el-icon-delete",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
console.log(data)
|
||||
this.$axios({
|
||||
method: "post",
|
||||
url: `/api/common/channel/group/delete`,
|
||||
data: {
|
||||
channelIds: [data.id]
|
||||
}
|
||||
}).then((res) => {
|
||||
console.log("移除成功")
|
||||
console.log(node)
|
||||
if (this.onChannelChange) {
|
||||
this.onChannelChange()
|
||||
}
|
||||
node.parent.loaded = false
|
||||
node.parent.expand();
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
if (node.data.type === 0) {
|
||||
let menuItem = [
|
||||
{
|
||||
label: "刷新节点",
|
||||
icon: "el-icon-refresh",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.refreshNode(node);
|
||||
}
|
||||
],
|
||||
event, // 鼠标事件信息
|
||||
customClass: "custom-class", // 自定义菜单 class
|
||||
zIndex: 3000, // 菜单样式 z-index
|
||||
});
|
||||
} else if (node.data.type === 0) {
|
||||
this.$contextmenu({
|
||||
items: [
|
||||
{
|
||||
label: "刷新节点",
|
||||
icon: "el-icon-refresh",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.refreshNode(node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "新建节点",
|
||||
icon: "el-icon-plus",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.addGroup(data.id, node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "编辑节点",
|
||||
icon: "el-icon-edit",
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.editGroup(data, node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "删除节点",
|
||||
icon: "el-icon-delete",
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.$confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.removeGroup(data.id, node)
|
||||
}).catch(() => {
|
||||
},
|
||||
{
|
||||
label: "新建节点",
|
||||
icon: "el-icon-plus",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.addGroup(data.id, node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "编辑节点",
|
||||
icon: "el-icon-edit",
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.editGroup(data, node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "删除节点",
|
||||
icon: "el-icon-delete",
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.$confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.removeGroup(data.id, node)
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
if (this.enableAddChannel) {
|
||||
menuItem.push(
|
||||
{
|
||||
label: "添加设备",
|
||||
icon: "el-icon-plus",
|
||||
@ -198,35 +171,32 @@ export default {
|
||||
this.addChannelFormDevice(data.id, node)
|
||||
}
|
||||
},
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: "移除设备",
|
||||
icon: "el-icon-delete",
|
||||
disabled: node.level <= 2,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.removeChannelFormDevice(data.id, node)
|
||||
}
|
||||
},
|
||||
// {
|
||||
// label: "导出",
|
||||
// icon: "el-icon-download",
|
||||
// disabled: false,
|
||||
// children: [
|
||||
// {
|
||||
// label: "导出到文件",
|
||||
// onClick: () => {
|
||||
//
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// label: "导出到其他平台",
|
||||
// onClick: () => {
|
||||
//
|
||||
// },
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: "添加通道",
|
||||
icon: "el-icon-plus",
|
||||
disabled: node.level <= 2,
|
||||
onClick: () => {
|
||||
this.addChannel(data.id, node)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
],
|
||||
this.$contextmenu({
|
||||
items: menuItem,
|
||||
event, // 鼠标事件信息
|
||||
customClass: "custom-class", // 自定义菜单 class
|
||||
zIndex: 3000, // 菜单样式 z-index
|
||||
@ -248,15 +218,15 @@ export default {
|
||||
node.parent.loaded = false
|
||||
node.parent.expand();
|
||||
if (this.onChannelChange) {
|
||||
this.onChannelChange()
|
||||
this.onChannelChange(node.data.deviceId)
|
||||
}
|
||||
}
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
addChannelFormDevice: function (id, node) {
|
||||
this.$refs.gbDeviceSelect.openDialog((rows)=>{
|
||||
this.$refs.gbDeviceSelect.openDialog((rows) => {
|
||||
let deviceIds = []
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
deviceIds.push(rows[i].id)
|
||||
@ -269,26 +239,26 @@ export default {
|
||||
businessGroup: node.data.businessGroup,
|
||||
deviceIds: deviceIds,
|
||||
}
|
||||
}).then((res)=> {
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.$message.success({
|
||||
showClose: true,
|
||||
message: "保存成功"
|
||||
})
|
||||
showClose: true,
|
||||
message: "保存成功"
|
||||
})
|
||||
if (this.onChannelChange) {
|
||||
this.onChannelChange()
|
||||
}
|
||||
console.log(node)
|
||||
node.loaded = false
|
||||
node.expand();
|
||||
}else {
|
||||
} else {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: error
|
||||
@ -298,7 +268,7 @@ export default {
|
||||
})
|
||||
},
|
||||
removeChannelFormDevice: function (id, node) {
|
||||
this.$refs.gbDeviceSelect.openDialog((rows)=>{
|
||||
this.$refs.gbDeviceSelect.openDialog((rows) => {
|
||||
let deviceIds = []
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
deviceIds.push(rows[i].id)
|
||||
@ -309,25 +279,25 @@ export default {
|
||||
data: {
|
||||
deviceIds: deviceIds,
|
||||
}
|
||||
}).then((res)=> {
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.$message.success({
|
||||
showClose: true,
|
||||
message: "保存成功"
|
||||
})
|
||||
showClose: true,
|
||||
message: "保存成功"
|
||||
})
|
||||
if (this.onChannelChange) {
|
||||
this.onChannelChange()
|
||||
}
|
||||
node.loaded = false
|
||||
node.expand();
|
||||
}else {
|
||||
} else {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: error
|
||||
@ -336,6 +306,13 @@ export default {
|
||||
});
|
||||
})
|
||||
},
|
||||
addChannel: function (id, node) {
|
||||
this.$refs.gbChannelSelect.openDialog((data) => {
|
||||
console.log("选择的数据")
|
||||
console.log(data)
|
||||
this.addChannelToGroup(node.data.deviceId, node.data.businessGroup, data)
|
||||
})
|
||||
},
|
||||
refreshNode: function (node) {
|
||||
console.log(node)
|
||||
node.loaded = false
|
||||
@ -356,10 +333,10 @@ export default {
|
||||
name: "",
|
||||
deviceId: "",
|
||||
civilCode: "",
|
||||
parentDeviceId: node.level > 2 ? node.data.deviceId:"",
|
||||
parentDeviceId: node.level > 2 ? node.data.deviceId : "",
|
||||
parentId: node.data.id,
|
||||
businessGroup: node.level > 2 ? node.data.businessGroup: node.data.deviceId,
|
||||
},form => {
|
||||
businessGroup: node.level > 2 ? node.data.businessGroup : node.data.deviceId,
|
||||
}, form => {
|
||||
console.log(node)
|
||||
node.loaded = false
|
||||
node.expand();
|
||||
@ -367,13 +344,14 @@ export default {
|
||||
},
|
||||
editGroup: function (id, node) {
|
||||
console.log(node)
|
||||
this.$refs.groupEdit.openDialog(node.data,form => {
|
||||
this.$refs.groupEdit.openDialog(node.data, form => {
|
||||
console.log(node)
|
||||
node.parent.loaded = false
|
||||
node.parent.expand();
|
||||
}, id);
|
||||
},
|
||||
nodeClickHandler: function (data, node, tree) {
|
||||
this.chooseId = data.deviceId;
|
||||
if (this.clickEvent) {
|
||||
this.clickEvent(data)
|
||||
}
|
||||
@ -402,6 +380,7 @@ export default {
|
||||
.device-offline {
|
||||
color: #727272;
|
||||
}
|
||||
|
||||
.custom-tree-node .el-radio__label {
|
||||
padding-left: 4px !important;
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
class="flow-tree"
|
||||
ref="veTree"
|
||||
node-key="treeId"
|
||||
height="78vh"
|
||||
:height="treeHeight?treeHeight:'78vh'"
|
||||
lazy
|
||||
style="padding: 0 0 2rem 0.5rem"
|
||||
:load="loadNode"
|
||||
@ -27,20 +27,21 @@
|
||||
@node-contextmenu="contextmenuEventHandler"
|
||||
@node-click="nodeClickHandler"
|
||||
>
|
||||
<span class="custom-tree-node" slot-scope="{ node, data }">
|
||||
<span @click.stop v-if="edit">
|
||||
<el-radio v-if="node.data.type === 0 && node.level !== 1 " style="margin-right: 0" v-model="chooseId" @input="chooseIdChange(node.data.treeId, node.data.deviceId)" :label="node.data.deviceId">{{''}}</el-radio>
|
||||
</span>
|
||||
<span v-if="node.data.type === 0" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
|
||||
<template class="custom-tree-node" v-slot:default="{ node, data }">
|
||||
<span class="custom-tree-node" >
|
||||
<span v-if="node.data.type === 0 && chooseId !== node.data.deviceId" style="color: #409EFF" class="iconfont icon-bianzubeifen3"></span>
|
||||
<span v-if="node.data.type === 0 && chooseId === node.data.deviceId" style="color: #c60135;" class="iconfont icon-bianzubeifen3"></span>
|
||||
<span v-if="node.data.type === 1 && node.data.status === 'ON'" style="color: #409EFF" class="iconfont icon-shexiangtou2"></span>
|
||||
<span v-if="node.data.type === 1 && node.data.status !== 'ON'" style="color: #808181" class="iconfont icon-shexiangtou2"></span>
|
||||
<span style=" padding-left: 1px" v-if="node.data.deviceId !=='' && showCode" :title="node.data.deviceId">{{ node.label }}(编号:{{ node.data.deviceId }})</span>
|
||||
<span style=" padding-left: 1px" v-if="node.data.deviceId ==='' || !showCode" :title="node.data.deviceId">{{ node.label }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</vue-easy-tree>
|
||||
</div>
|
||||
<regionEdit ref="regionEdit"></regionEdit>
|
||||
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
|
||||
<GbChannelSelect ref="gbChannelSelect" dataType="civilCode" ></GbChannelSelect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -48,10 +49,12 @@
|
||||
import VueEasyTree from "@wchbrad/vue-easy-tree";
|
||||
import regionEdit from './../dialog/regionEdit'
|
||||
import gbDeviceSelect from './../dialog/GbDeviceSelect'
|
||||
import GbChannelSelect from "../dialog/GbChannelSelect.vue";
|
||||
|
||||
export default {
|
||||
name: 'DeviceTree',
|
||||
components: {
|
||||
GbChannelSelect,
|
||||
VueEasyTree, regionEdit, gbDeviceSelect
|
||||
},
|
||||
data() {
|
||||
@ -65,7 +68,7 @@ export default {
|
||||
treeData: [],
|
||||
}
|
||||
},
|
||||
props: ['edit', 'clickEvent', 'chooseIdChange', 'onChannelChange', 'showHeader'],
|
||||
props: ['edit', 'enableAddChannel', 'clickEvent', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToCivilCode', 'treeHeight'],
|
||||
created() {
|
||||
},
|
||||
methods: {
|
||||
@ -91,7 +94,8 @@ export default {
|
||||
url: `/api/region/tree/list`,
|
||||
params: {
|
||||
query: this.searchSrt,
|
||||
parent: node.data.id
|
||||
parent: node.data.id,
|
||||
hasChannel: this.hasChannel
|
||||
}
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
@ -113,83 +117,52 @@ export default {
|
||||
return
|
||||
}
|
||||
console.log(node.level)
|
||||
if (node.data.type === 1) {
|
||||
data.parentId = node.parent.data.id;
|
||||
this.$contextmenu({
|
||||
items: [
|
||||
{
|
||||
label: "移除通道",
|
||||
icon: "el-icon-delete",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
console.log(data)
|
||||
this.$axios({
|
||||
method: "post",
|
||||
url: `/api/common/channel/region/delete`,
|
||||
data: {
|
||||
channelIds: [data.id]
|
||||
}
|
||||
}).then((res) => {
|
||||
console.log("移除成功")
|
||||
if (this.onChannelChange) {
|
||||
this.onChannelChange()
|
||||
}
|
||||
node.parent.loaded = false
|
||||
node.parent.expand();
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
if (node.data.type === 0) {
|
||||
let menuItem = [
|
||||
{
|
||||
label: "刷新节点",
|
||||
icon: "el-icon-refresh",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.refreshNode(node);
|
||||
}
|
||||
],
|
||||
event, // 鼠标事件信息
|
||||
customClass: "custom-class", // 自定义菜单 class
|
||||
zIndex: 3000, // 菜单样式 z-index
|
||||
});
|
||||
} else if (node.data.type === 0) {
|
||||
this.$contextmenu({
|
||||
items: [
|
||||
{
|
||||
label: "刷新节点",
|
||||
icon: "el-icon-refresh",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.refreshNode(node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "新建节点",
|
||||
icon: "el-icon-plus",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.addRegion(data.id, node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "编辑节点",
|
||||
icon: "el-icon-edit",
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.editCatalog(data, node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "删除节点",
|
||||
icon: "el-icon-delete",
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.$confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.removeRegion(data.id, node)
|
||||
}).catch(() => {
|
||||
},
|
||||
{
|
||||
label: "新建节点",
|
||||
icon: "el-icon-plus",
|
||||
disabled: false,
|
||||
onClick: () => {
|
||||
this.addRegion(data.id, node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "编辑节点",
|
||||
icon: "el-icon-edit",
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.editCatalog(data, node);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "删除节点",
|
||||
icon: "el-icon-delete",
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.$confirm('确定删除?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.removeRegion(data.id, node)
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
]
|
||||
if (this.enableAddChannel) {
|
||||
menuItem.push(
|
||||
{
|
||||
label: "添加设备",
|
||||
icon: "el-icon-plus",
|
||||
@ -197,36 +170,34 @@ export default {
|
||||
onClick: () => {
|
||||
this.addChannelFormDevice(data.id, node)
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: "移除设备",
|
||||
icon: "el-icon-delete",
|
||||
disabled: node.level === 1,
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.removeChannelFormDevice(data.id, node)
|
||||
}
|
||||
},
|
||||
// {
|
||||
// label: "导出",
|
||||
// icon: "el-icon-download",
|
||||
// disabled: false,
|
||||
// children: [
|
||||
// {
|
||||
// label: "导出到文件",
|
||||
// onClick: () => {
|
||||
//
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// label: "导出到其他平台",
|
||||
// onClick: () => {
|
||||
//
|
||||
// },
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
}
|
||||
)
|
||||
menuItem.push(
|
||||
{
|
||||
label: "添加通道",
|
||||
icon: "el-icon-plus",
|
||||
disabled: node.level === 1,
|
||||
onClick: () => {
|
||||
this.addChannel(data.id, node)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
],
|
||||
|
||||
this.$contextmenu({
|
||||
items: menuItem,
|
||||
event, // 鼠标事件信息
|
||||
customClass: "custom-class", // 自定义菜单 class
|
||||
zIndex: 3000, // 菜单样式 z-index
|
||||
@ -311,7 +282,7 @@ export default {
|
||||
message: "保存成功"
|
||||
})
|
||||
if (this.onChannelChange) {
|
||||
this.onChannelChange()
|
||||
this.onChannelChange(node.data.deviceId)
|
||||
}
|
||||
node.loaded = false
|
||||
node.expand();
|
||||
@ -331,6 +302,13 @@ export default {
|
||||
});
|
||||
})
|
||||
},
|
||||
addChannel: function (id, node) {
|
||||
this.$refs.gbChannelSelect.openDialog((data) => {
|
||||
console.log("选择的数据")
|
||||
console.log(data)
|
||||
this.addChannelToCivilCode(node.data.deviceId, data)
|
||||
})
|
||||
},
|
||||
refreshNode: function (node) {
|
||||
node.loaded = false
|
||||
node.expand();
|
||||
@ -366,14 +344,11 @@ export default {
|
||||
}, node.data);
|
||||
},
|
||||
nodeClickHandler: function (data, node, tree) {
|
||||
console.log(data)
|
||||
console.log(node)
|
||||
|
||||
this.chooseId = data.deviceId;
|
||||
if (this.clickEvent) {
|
||||
this.clickEvent(data)
|
||||
}
|
||||
// this.chooseId = data.id;
|
||||
// this.chooseName = data.name;
|
||||
// if (this.catalogIdChange)this.catalogIdChange(this.chooseId, this.chooseName);
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
|
||||
98
web_src/src/components/common/mediaInfo.vue
Normal file
98
web_src/src/components/common/mediaInfo.vue
Normal file
@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<div id="mediaInfo" >
|
||||
<el-button style="position: absolute; right: 1rem;" icon="el-icon-refresh-right" circle size="mini" @click="getMediaInfo"></el-button>
|
||||
<el-descriptions size="mini" :column="3" title="概况">
|
||||
<el-descriptions-item label="观看人数">{{ info.readerCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="网络">{{ formatByteSpeed() }}</el-descriptions-item>
|
||||
<el-descriptions-item label="持续时间">{{info.aliveSecond}}秒</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr">
|
||||
<el-descriptions size="mini" v-if="info.videoCodec" :column="2" title="视频信息">
|
||||
<el-descriptions-item label="编码">{{ info.videoCodec }}</el-descriptions-item>
|
||||
<el-descriptions-item label="分辨率"
|
||||
>{{ info.width }}x{{ info.height }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="FPS">{{ info.fps }}</el-descriptions-item>
|
||||
<el-descriptions-item label="丢包率">{{ info.loss }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<el-descriptions size="mini" v-if="info.audioCodec" :column="2" title="音频信息">
|
||||
<el-descriptions-item label="编码">
|
||||
{{ info.audioCodec }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="采样率">{{ info.audioSampleRate }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "mediaInfo",
|
||||
props: [ 'app', 'stream', 'mediaServerId'],
|
||||
components: {},
|
||||
created() {
|
||||
this.getMediaInfo()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
info: {}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getMediaInfo: function () {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/server/media_server/media_info`,
|
||||
params: {
|
||||
app: this.app,
|
||||
stream: this.stream,
|
||||
mediaServerId: this.mediaServerId,
|
||||
}
|
||||
}).then((res)=> {
|
||||
console.log(res.data.data);
|
||||
if (res.data.code === 0) {
|
||||
this.info = res.data.data
|
||||
}
|
||||
|
||||
}).catch((error)=> {
|
||||
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
formatByteSpeed: function (){
|
||||
let bytesSpeed = this.info.bytesSpeed
|
||||
let num = 1024.0 //byte
|
||||
if (bytesSpeed < num) return bytesSpeed + ' B/S'
|
||||
if (bytesSpeed < Math.pow(num, 2)) return (bytesSpeed / num).toFixed(2) + ' KB/S' //kb
|
||||
if (bytesSpeed < Math.pow(num, 3))
|
||||
return (bytesSpeed / Math.pow(num, 2)).toFixed(2) + ' MB/S' //M
|
||||
if (bytesSpeed < Math.pow(num, 4))
|
||||
return (bytesSpeed / Math.pow(num, 3)).toFixed(2) + ' G/S' //G
|
||||
return (bytesSpeed / Math.pow(num, 4)).toFixed(2) + ' T/S' //T
|
||||
},
|
||||
formatAliveSecond: function (){
|
||||
let aliveSecond = this.info.aliveSecond
|
||||
const h = parseInt(aliveSecond.value / 3600)
|
||||
const minute = parseInt((aliveSecond.value / 60) % 60)
|
||||
const second = Math.ceil(aliveSecond.value % 60)
|
||||
|
||||
const hours = h < 10 ? '0' + h : h
|
||||
const formatSecond = second > 59 ? 59 : second
|
||||
return `${hours > 0 ? `${hours}小时` : ''}${minute < 10 ? '0' + minute : minute}分${
|
||||
formatSecond < 10 ? '0' + formatSecond : formatSecond
|
||||
}秒`
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.channel-form {
|
||||
display: grid;
|
||||
background-color: #FFFFFF;
|
||||
padding: 1rem 2rem 0 2rem;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
426
web_src/src/components/common/ptzCruising.vue
Normal file
426
web_src/src/components/common/ptzCruising.vue
Normal file
@ -0,0 +1,426 @@
|
||||
<template>
|
||||
<div id="ptzCruising">
|
||||
<div style="display: grid; grid-template-columns: 80px auto; line-height: 28px">
|
||||
<span>巡航组号: </span>
|
||||
<el-input
|
||||
min="1"
|
||||
max="255"
|
||||
placeholder="巡航组号"
|
||||
addonBefore="巡航组号"
|
||||
addonAfter="(1-255)"
|
||||
v-model="cruiseId"
|
||||
size="mini"
|
||||
>
|
||||
</el-input>
|
||||
</div>
|
||||
<p>
|
||||
<el-tag v-for="(item, index) in presetList"
|
||||
key="item.presetId"
|
||||
closable
|
||||
@close="delPreset(item, index)"
|
||||
style="margin-right: 1rem; cursor: pointer"
|
||||
>
|
||||
{{item.presetName?item.presetName:item.presetId}}
|
||||
</el-tag>
|
||||
</p>
|
||||
|
||||
<el-form size="mini" :inline="true" v-if="selectPresetVisible">
|
||||
<el-form-item >
|
||||
<el-select v-model="selectPreset" placeholder="请选择预置点">
|
||||
<el-option
|
||||
v-for="item in allPresetList"
|
||||
:key="item.presetId"
|
||||
:label="item.presetName"
|
||||
:value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="addCruisePoint">保存</el-button>
|
||||
<el-button type="primary" @click="cancelAddCruisePoint">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button size="mini" v-else @click="selectPresetVisible=true">添加巡航点</el-button>
|
||||
|
||||
<el-form size="mini" :inline="true" v-if="setSpeedVisible">
|
||||
<el-form-item >
|
||||
<el-input
|
||||
min="1"
|
||||
max="4095"
|
||||
placeholder="巡航速度"
|
||||
addonBefore="巡航速度"
|
||||
addonAfter="(1-4095)"
|
||||
v-if="setSpeedVisible"
|
||||
v-model="cruiseSpeed"
|
||||
size="mini"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="setCruiseSpeed">保存</el-button>
|
||||
<el-button @click="cancelSetCruiseSpeed">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button v-else size="mini" @click="setSpeedVisible = true">设置巡航速度</el-button>
|
||||
|
||||
|
||||
|
||||
<el-form size="mini" :inline="true" v-if="setTimeVisible">
|
||||
<el-form-item >
|
||||
<el-input
|
||||
min="1"
|
||||
max="4095"
|
||||
placeholder="巡航停留时间(秒)"
|
||||
addonBefore="巡航停留时间(秒)"
|
||||
addonAfter="(1-4095)"
|
||||
style="width: 100%;"
|
||||
v-model="cruiseTime"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="setCruiseTime">保存</el-button>
|
||||
<el-button @click="cancelSetCruiseTime">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button v-else size="mini" @click="setTimeVisible = true">设置巡航时间</el-button>
|
||||
<el-button size="mini" @click="startCruise">开始巡航</el-button>
|
||||
<el-button size="mini" @click="stopCruise">停止巡航</el-button>
|
||||
<el-button size="mini" type="danger" @click="deleteCruise">删除巡航</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "ptzCruising",
|
||||
props: [ 'channelDeviceId', 'deviceId'],
|
||||
components: {},
|
||||
created() {
|
||||
this.getPresetList()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
cruiseId: 1,
|
||||
presetList: [],
|
||||
allPresetList: [],
|
||||
selectPreset: "",
|
||||
inputVisible: false,
|
||||
selectPresetVisible: false,
|
||||
setSpeedVisible: false,
|
||||
setTimeVisible: false,
|
||||
cruiseSpeed: '',
|
||||
cruiseTime: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getPresetList: function () {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/preset/query/${this.deviceId}/${this.channelDeviceId}`,
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.allPresetList = res.data.data;
|
||||
}
|
||||
|
||||
}).catch((error)=> {
|
||||
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
addCruisePoint: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/cruise/point/add/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
cruiseId: this.cruiseId,
|
||||
presetId: this.selectPreset.presetId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.presetList.push(this.selectPreset)
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
this.selectPreset = ""
|
||||
this.selectPresetVisible = false;
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
cancelAddCruisePoint: function () {
|
||||
this.selectPreset = ""
|
||||
this.selectPresetVisible = false;
|
||||
},
|
||||
delPreset: function (preset, index){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/cruise/point/delete/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
cruiseId: this.cruiseId,
|
||||
presetId: preset.presetId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.presetList.splice(index, 1)
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
deleteCruise: function (preset, index){
|
||||
this.$confirm("确定删除此巡航组", '提示', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/cruise/point/delete/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
cruiseId: this.cruiseId,
|
||||
presetId: 0
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.presetList = []
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
})
|
||||
},
|
||||
setCruiseSpeed: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/cruise/speed/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
cruiseId: this.cruiseId,
|
||||
speed: this.cruiseSpeed
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "保存成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
this.cruiseSpeed = ""
|
||||
this.setSpeedVisible = false
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
cancelSetCruiseSpeed: function (){
|
||||
this.cruiseSpeed = ""
|
||||
this.setSpeedVisible = false
|
||||
},
|
||||
setCruiseTime: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/cruise/time/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
cruiseId: this.cruiseId,
|
||||
time: this.cruiseTime
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "保存成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
this.setTimeVisible = false;
|
||||
this.cruiseTime = "";
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
cancelSetCruiseTime: function (){
|
||||
this.setTimeVisible = false;
|
||||
this.cruiseTime = "";
|
||||
},
|
||||
startCruise: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/cruise/start/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
cruiseId: this.cruiseId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "发送成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
stopCruise: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/cruise/stop/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
cruiseId: this.cruiseId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "发送成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.channel-form {
|
||||
display: grid;
|
||||
background-color: #FFFFFF;
|
||||
padding: 1rem 2rem 0 2rem;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
212
web_src/src/components/common/ptzPreset.vue
Normal file
212
web_src/src/components/common/ptzPreset.vue
Normal file
@ -0,0 +1,212 @@
|
||||
<template>
|
||||
<div id="ptzPreset" style="width: 100%">
|
||||
<el-tag v-for="item in presetList"
|
||||
key="item.presetId"
|
||||
closable
|
||||
@close="delPreset(item)"
|
||||
@click="gotoPreset(item)"
|
||||
size="mini"
|
||||
style="margin-right: 1rem; cursor: pointer; margin-bottom: 0.6rem"
|
||||
>
|
||||
{{item.presetName?item.presetName:item.presetId}}
|
||||
</el-tag>
|
||||
<el-input
|
||||
min="1"
|
||||
max="255"
|
||||
placeholder="预置位编号"
|
||||
addonBefore="预置位编号"
|
||||
addonAfter="(1-255)"
|
||||
style="width: 300px; vertical-align: bottom;"
|
||||
v-if="inputVisible"
|
||||
v-model="ptzPresetId"
|
||||
ref="saveTagInput"
|
||||
size="small"
|
||||
>
|
||||
<template v-slot:append>
|
||||
<el-button @click="addPreset()">保存</el-button>
|
||||
<el-button @click="cancel()">取消</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
<el-button v-else size="small" @click="showInput">+ 添加</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "ptzPreset",
|
||||
props: [ 'channelDeviceId', 'deviceId'],
|
||||
components: {},
|
||||
created() {
|
||||
this.getPresetList()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
presetList: [],
|
||||
inputVisible: false,
|
||||
ptzPresetId: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getPresetList: function () {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/preset/query/${this.deviceId}/${this.channelDeviceId}`,
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.presetList = res.data.data;
|
||||
// 防止出现表格错位
|
||||
this.$nextTick(() => {
|
||||
this.$refs.channelListTable.doLayout();
|
||||
})
|
||||
}
|
||||
|
||||
}).catch((error)=> {
|
||||
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
showInput() {
|
||||
this.inputVisible = true;
|
||||
this.$nextTick(_ => {
|
||||
this.$refs.saveTagInput.$refs.input.focus();
|
||||
});
|
||||
},
|
||||
addPreset: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/preset/add/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
presetId: this.ptzPresetId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
setTimeout(()=>{
|
||||
loading.close()
|
||||
this.inputVisible = false;
|
||||
this.ptzPresetId = ""
|
||||
this.getPresetList()
|
||||
}, 1000)
|
||||
}else {
|
||||
loading.close()
|
||||
this.inputVisible = false;
|
||||
this.ptzPresetId = ""
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
loading.close()
|
||||
this.inputVisible = false;
|
||||
this.ptzPresetId = ""
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
cancel: function () {
|
||||
this.inputVisible = false;
|
||||
this.ptzPresetId = ""
|
||||
},
|
||||
gotoPreset: function (preset){
|
||||
console.log(preset)
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/preset/call/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
presetId: preset.presetId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '调用成功',
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
delPreset: function (preset){
|
||||
this.$confirm("确定删除此预置位", '提示', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/preset/delete/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
presetId: preset.presetId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
setTimeout(()=>{
|
||||
loading.close()
|
||||
this.getPresetList()
|
||||
}, 1000)
|
||||
}else {
|
||||
loading.close()
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
}).catch((error)=> {
|
||||
loading.close()
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.channel-form {
|
||||
display: grid;
|
||||
background-color: #FFFFFF;
|
||||
padding: 1rem 2rem 0 2rem;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
</style>
|
||||
273
web_src/src/components/common/ptzScan.vue
Normal file
273
web_src/src/components/common/ptzScan.vue
Normal file
@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div id="ptzScan">
|
||||
<div style="display: grid; grid-template-columns: 80px auto; line-height: 28px">
|
||||
<span>扫描组号: </span>
|
||||
<el-input
|
||||
min="1"
|
||||
max="255"
|
||||
placeholder="扫描组号"
|
||||
addonBefore="扫描组号"
|
||||
addonAfter="(1-255)"
|
||||
v-model="scanId"
|
||||
size="mini"
|
||||
>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<el-button size="mini" @click="setScanLeft">设置左边界</el-button>
|
||||
<el-button size="mini" @click="setScanRight">设置右边界</el-button>
|
||||
|
||||
<el-form size="mini" :inline="true" v-if="setSpeedVisible">
|
||||
<el-form-item >
|
||||
<el-input
|
||||
min="1"
|
||||
max="4095"
|
||||
placeholder="巡航速度"
|
||||
addonBefore="巡航速度"
|
||||
addonAfter="(1-4095)"
|
||||
v-if="setSpeedVisible"
|
||||
v-model="speed"
|
||||
size="mini"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="setSpeed">保存</el-button>
|
||||
<el-button @click="cancelSetSpeed">取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button v-else size="mini" @click="setSpeedVisible = true">设置扫描速度</el-button>
|
||||
|
||||
<el-button size="mini" @click="startScan">开始自动扫描</el-button>
|
||||
<el-button size="mini" @click="stopScan">停止自动扫描</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "ptzScan",
|
||||
props: [ 'channelDeviceId', 'deviceId'],
|
||||
components: {},
|
||||
created() {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
scanId: 1,
|
||||
setSpeedVisible: false,
|
||||
speed: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
setSpeed: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/scan/set/speed/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
scanId: this.scanId,
|
||||
speed: this.speed
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "保存成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
this.speed = ""
|
||||
this.setSpeedVisible = false
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
cancelSetSpeed: function (){
|
||||
this.speed = ""
|
||||
this.setSpeedVisible = false
|
||||
},
|
||||
setScanLeft: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/scan/set/left/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
scanId: this.scanId,
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "保存成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
setScanRight: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/scan/set/right/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
scanId: this.scanId,
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "保存成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
this.setSpeedVisible = false;
|
||||
this.speed = "";
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
startScan: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/scan/start/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
scanId: this.scanId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "发送成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
stopScan: function (){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/scan/stop/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
scanId: this.scanId
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "发送成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.channel-form {
|
||||
display: grid;
|
||||
background-color: #FFFFFF;
|
||||
padding: 1rem 2rem 0 2rem;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
90
web_src/src/components/common/ptzSwitch.vue
Normal file
90
web_src/src/components/common/ptzSwitch.vue
Normal file
@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<div id="ptzScan">
|
||||
<el-form size="mini" :inline="true" >
|
||||
<el-form-item >
|
||||
<el-input
|
||||
min="1"
|
||||
max="4095"
|
||||
placeholder="开关编号"
|
||||
addonBefore="开关编号"
|
||||
addonAfter="(2-255)"
|
||||
v-model="switchId"
|
||||
size="mini"
|
||||
>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button size="mini" @click="open('on')">开启</el-button>
|
||||
<el-button size="mini" @click="open('off')">关闭</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "ptzScan",
|
||||
props: [ 'channelDeviceId', 'deviceId'],
|
||||
components: {},
|
||||
created() {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
switchId: 1,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open: function (command){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/auxiliary/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
command: command,
|
||||
switchId: this.switchId,
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "保存成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.channel-form {
|
||||
display: grid;
|
||||
background-color: #FFFFFF;
|
||||
padding: 1rem 2rem 0 2rem;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
70
web_src/src/components/common/ptzWiper.vue
Normal file
70
web_src/src/components/common/ptzWiper.vue
Normal file
@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div id="ptzWiper">
|
||||
<el-button size="mini" @click="open('on')">开启</el-button>
|
||||
<el-button size="mini" @click="open('off')">关闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "ptzWiper",
|
||||
props: [ 'channelDeviceId', 'deviceId'],
|
||||
components: {},
|
||||
created() {
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
open: function (command){
|
||||
const loading = this.$loading({
|
||||
lock: true,
|
||||
fullscreen: true,
|
||||
text: '正在发送指令',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
})
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/front-end/wiper/${this.deviceId}/${this.channelDeviceId}`,
|
||||
params: {
|
||||
command: command,
|
||||
}
|
||||
}).then((res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "保存成功",
|
||||
type: 'success'
|
||||
});
|
||||
}else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error)=> {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: error,
|
||||
type: 'error'
|
||||
});
|
||||
}).finally(()=>{
|
||||
loading.close()
|
||||
})
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.channel-form {
|
||||
display: grid;
|
||||
background-color: #FFFFFF;
|
||||
padding: 1rem 2rem 0 2rem;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
185
web_src/src/components/dialog/GbChannelSelect.vue
Normal file
185
web_src/src/components/dialog/GbChannelSelect.vue
Normal file
@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<div id="gbChannelSelect" v-loading="getChannelListLoading">
|
||||
<el-dialog
|
||||
title="添加国标通道"
|
||||
width="60%"
|
||||
top="2rem"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="showDialog"
|
||||
:destroy-on-close="true"
|
||||
append-to-body
|
||||
@close="close()"
|
||||
>
|
||||
<div class="page-header" style="width: 100%">
|
||||
<div class="page-header-btn" style="width: 100%; text-align: left">
|
||||
搜索:
|
||||
<el-input @input="getChannelList" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
||||
在线状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="online" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="在线" value="true"></el-option>
|
||||
<el-option label="离线" value="false"></el-option>
|
||||
</el-select>
|
||||
类型:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="channelType" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="国标设备" :value="0"></el-option>
|
||||
<el-option label="推流设备" :value="1"></el-option>
|
||||
<el-option label="拉流代理" :value="2"></el-option>
|
||||
</el-select>
|
||||
<el-button size="mini" :loading="getChannelListLoading"
|
||||
@click="getChannelList()">刷新</el-button>
|
||||
<el-button type="primary" size="mini" style="float: right" @click="onSubmit">确 定</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!--通道列表-->
|
||||
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
|
||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
|
||||
<el-table-column type="selection" width="55" >
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
|
||||
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
|
||||
<el-tag size="medium" effect="plain" type="warning" v-if="scope.row.streamProxyId">拉流代理</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="text-align: right"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="currentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="count"
|
||||
:page-sizes="[10, 25, 35, 50, 200, 1000, 50000]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: "gbChannelSelect",
|
||||
props: ['dataType', "selected"],
|
||||
computed: {},
|
||||
data() {
|
||||
return {
|
||||
showDialog: false,
|
||||
channelList: [], //设备列表
|
||||
currentDevice: {}, //当前操作设备对象
|
||||
searchSrt: "",
|
||||
online: null,
|
||||
channelType: "",
|
||||
videoComponentList: [],
|
||||
updateLooper: 0, //数据刷新轮训标志
|
||||
currentDeviceChannelsLenth: 0,
|
||||
winHeight: 580,
|
||||
currentPage: 1,
|
||||
count: 10,
|
||||
total: 0,
|
||||
getChannelListLoading: false,
|
||||
multipleSelection: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
initData: function () {
|
||||
this.getChannelList();
|
||||
},
|
||||
currentChange: function (val) {
|
||||
this.currentPage = val;
|
||||
this.getChannelList();
|
||||
},
|
||||
handleSizeChange: function (val) {
|
||||
this.count = val;
|
||||
this.getChannelList();
|
||||
},
|
||||
handleSelectionChange: function (val){
|
||||
this.multipleSelection = val;
|
||||
},
|
||||
getChannelList: function () {
|
||||
this.getChannelListLoading = true;
|
||||
if (this.dataType === "civilCode") {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/common/channel/civilcode/list`,
|
||||
params: {
|
||||
page: this.currentPage,
|
||||
count: this.count,
|
||||
channelType: this.channelType,
|
||||
query: this.searchSrt,
|
||||
online: this.online,
|
||||
}
|
||||
}).then( (res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.total = res.data.data.total;
|
||||
this.channelList = res.data.data.list;
|
||||
}
|
||||
this.getChannelListLoading = false;
|
||||
}).catch( (error)=> {
|
||||
console.error(error);
|
||||
this.getChannelListLoading = false;
|
||||
});
|
||||
}else {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/common/channel/parent/list`,
|
||||
params: {
|
||||
page: this.currentPage,
|
||||
count: this.count,
|
||||
query: this.searchSrt,
|
||||
channelType: this.channelType,
|
||||
online: this.online,
|
||||
}
|
||||
}).then( (res)=> {
|
||||
if (res.data.code === 0) {
|
||||
this.total = res.data.data.total;
|
||||
this.channelList = res.data.data.list;
|
||||
}
|
||||
this.getChannelListLoading = false;
|
||||
}).catch( (error)=> {
|
||||
console.error(error);
|
||||
this.getChannelListLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
openDialog: function (callback) {
|
||||
this.listChangeCallback = callback;
|
||||
this.showDialog = true;
|
||||
this.initData();
|
||||
},
|
||||
onSubmit: function () {
|
||||
if (this.listChangeCallback ) {
|
||||
this.listChangeCallback(this.multipleSelection)
|
||||
}
|
||||
this.showDialog = false;
|
||||
},
|
||||
close: function () {
|
||||
this.showDialog = false;
|
||||
},
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@ -40,7 +40,7 @@
|
||||
<el-table-column prop="manufacturer" label="厂家" min-width="120" >
|
||||
</el-table-column>
|
||||
<el-table-column label="地址" min-width="160" >
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag v-if="scope.row.hostAddress" size="medium">{{ scope.row.hostAddress }}</el-tag>
|
||||
<el-tag v-if="!scope.row.hostAddress" size="medium">未知</el-tag>
|
||||
@ -48,7 +48,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.onLine">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.onLine">离线</el-tag>
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
width="65rem"
|
||||
top="2rem"
|
||||
center
|
||||
:append-to-body="true"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="showVideoDialog"
|
||||
:destroy-on-close="false"
|
||||
|
||||
65
web_src/src/components/dialog/chooseCivilCode.vue
Normal file
65
web_src/src/components/dialog/chooseCivilCode.vue
Normal file
@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div id="chooseCivilCode" >
|
||||
<el-dialog
|
||||
title="选择行政区划"
|
||||
width="30%"
|
||||
top="5rem"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="showDialog"
|
||||
:destroy-on-close="true"
|
||||
@close="close()"
|
||||
>
|
||||
<RegionTree ref="regionTree" :showHeader=true :edit="true" :enableAddChannel="false" :clickEvent="treeNodeClickEvent"
|
||||
:onChannelChange="onChannelChange" :treeHeight="'45vh'"></RegionTree>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<div style="text-align: right">
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
<el-button @click="close">取消</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import RegionTree from "../common/RegionTree.vue";
|
||||
|
||||
export default {
|
||||
name: "chooseCivilCode",
|
||||
components: {RegionTree},
|
||||
props: {},
|
||||
computed: {},
|
||||
created() {},
|
||||
data() {
|
||||
return {
|
||||
showDialog: false,
|
||||
endCallback: false,
|
||||
regionDeviceId: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openDialog: function (callback) {
|
||||
this.showDialog = true;
|
||||
this.endCallback = callback;
|
||||
},
|
||||
onSubmit: function () {
|
||||
if (this.endCallback) {
|
||||
this.endCallback(this.regionDeviceId)
|
||||
}
|
||||
this.close();
|
||||
},
|
||||
close: function () {
|
||||
this.showDialog = false;
|
||||
},
|
||||
treeNodeClickEvent: function (region) {
|
||||
this.regionDeviceId = region.deviceId;
|
||||
},
|
||||
onChannelChange: function (deviceId) {
|
||||
//
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
71
web_src/src/components/dialog/chooseGroup.vue
Normal file
71
web_src/src/components/dialog/chooseGroup.vue
Normal file
@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div id="chooseGroup" >
|
||||
<el-dialog
|
||||
title="选择虚拟组织"
|
||||
width="30%"
|
||||
top="5rem"
|
||||
:append-to-body="true"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="showDialog"
|
||||
:destroy-on-close="true"
|
||||
@close="close()"
|
||||
>
|
||||
<GroupTree ref="regionTree" :showHeader=true :edit="true" :enableAddChannel="false" :clickEvent="treeNodeClickEvent"
|
||||
:onChannelChange="onChannelChange" :treeHeight="'45vh'"></GroupTree>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
<div style="text-align: right">
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
<el-button @click="close">取消</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import GroupTree from "../common/GroupTree.vue";
|
||||
|
||||
export default {
|
||||
name: "chooseCivilCode",
|
||||
components: {GroupTree},
|
||||
props: {},
|
||||
computed: {},
|
||||
created() {},
|
||||
data() {
|
||||
return {
|
||||
showDialog: false,
|
||||
endCallback: false,
|
||||
groupDeviceId: "",
|
||||
businessGroup: "",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openDialog: function (callback) {
|
||||
this.showDialog = true;
|
||||
this.endCallback = callback;
|
||||
},
|
||||
onSubmit: function () {
|
||||
if (this.endCallback) {
|
||||
this.endCallback(this.groupDeviceId, this.businessGroup)
|
||||
}
|
||||
this.close();
|
||||
},
|
||||
close: function () {
|
||||
this.showDialog = false;
|
||||
},
|
||||
treeNodeClickEvent: function (group) {
|
||||
if (group.deviceId === "" || group.deviceId === group.businessGroup) {
|
||||
return
|
||||
}
|
||||
this.groupDeviceId = group.deviceId;
|
||||
this.businessGroup = group.businessGroup;
|
||||
},
|
||||
onChannelChange: function (deviceId) {
|
||||
//
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
</div>
|
||||
<div id="shared" style="text-align: right; margin-top: 1rem;">
|
||||
|
||||
<el-tabs v-model="tabActiveName" @tab-click="tabHandleClick">
|
||||
<el-tab-pane label="实时视频" name="media">
|
||||
<div style="display: flex; margin-bottom: 0.5rem; height: 2.5rem;">
|
||||
@ -154,148 +155,84 @@
|
||||
<!--{"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="control" v-if="showPtz">
|
||||
<div style="display: flex; justify-content: left;">
|
||||
<div class="control-wrapper">
|
||||
<div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')">
|
||||
<i class="el-icon-caret-top"></i>
|
||||
<div class="control-inner-btn control-inner"></div>
|
||||
<div style="display: grid; grid-template-columns: 240px auto; height: 180px; overflow: auto">
|
||||
<div style="display: grid; grid-template-columns: 6.25rem auto;">
|
||||
|
||||
<div class="control-wrapper">
|
||||
<div class="control-btn control-top" @mousedown="ptzCamera('up')" @mouseup="ptzCamera('stop')">
|
||||
<i class="el-icon-caret-top"></i>
|
||||
<div class="control-inner-btn control-inner"></div>
|
||||
</div>
|
||||
<div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')">
|
||||
<i class="el-icon-caret-left"></i>
|
||||
<div class="control-inner-btn control-inner"></div>
|
||||
</div>
|
||||
<div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')">
|
||||
<i class="el-icon-caret-bottom"></i>
|
||||
<div class="control-inner-btn control-inner"></div>
|
||||
</div>
|
||||
<div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')">
|
||||
<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 class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 6.25rem;">
|
||||
<el-slider v-model="controSpeed" :max="100"></el-slider>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-btn control-left" @mousedown="ptzCamera('left')" @mouseup="ptzCamera('stop')">
|
||||
<i class="el-icon-caret-left"></i>
|
||||
<div class="control-inner-btn control-inner"></div>
|
||||
</div>
|
||||
<div class="control-btn control-bottom" @mousedown="ptzCamera('down')" @mouseup="ptzCamera('stop')">
|
||||
<i class="el-icon-caret-bottom"></i>
|
||||
<div class="control-inner-btn control-inner"></div>
|
||||
</div>
|
||||
<div class="control-btn control-right" @mousedown="ptzCamera('right')" @mouseup="ptzCamera('stop')">
|
||||
<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('zoomin')"
|
||||
@mouseup="ptzCamera('stop')"><i class="el-icon-zoom-in control-zoom-btn"
|
||||
style="font-size: 1.875rem;"></i></div>
|
||||
<div style="position: absolute; left: 7.25rem; top: 3.25rem; font-size: 1.875rem;"
|
||||
@mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')"><i
|
||||
class="el-icon-zoom-out control-zoom-btn"></i></div>
|
||||
<div class="contro-speed" style="position: absolute; left: 4px; top: 7rem; width: 9rem;">
|
||||
<el-slider v-model="controSpeed" :max="255"></el-slider>
|
||||
<div>
|
||||
<div class="ptz-btn-box">
|
||||
<div style="" @mousedown="ptzCamera('zoomin')" @mouseup="ptzCamera('stop')" title="变倍+">
|
||||
<i class="el-icon-zoom-in control-zoom-btn" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div style="" @mousedown="ptzCamera('zoomout')" @mouseup="ptzCamera('stop')" title="变倍-">
|
||||
<i class="el-icon-zoom-out control-zoom-btn" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ptz-btn-box">
|
||||
<div @mousedown="focusCamera('near')" @mouseup="focusCamera('stop')" title="聚焦+">
|
||||
<i class="iconfont icon-bianjiao-fangda control-zoom-btn" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div @mousedown="focusCamera('far')" @mouseup="focusCamera('stop')" title="聚焦-">
|
||||
<i class="iconfont icon-bianjiao-suoxiao control-zoom-btn" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ptz-btn-box">
|
||||
<div @mousedown="irisCamera('in')" @mouseup="irisCamera('stop')" title="光圈+">
|
||||
<i class="iconfont icon-guangquan control-zoom-btn" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
<div @mousedown="pirisCamera('out')" @mouseup="irisCamera('stop')" title="光圈-">
|
||||
<i class="iconfont icon-guangquan- control-zoom-btn" style="font-size: 1.5rem;"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="text-align: left" >
|
||||
<el-select
|
||||
v-model="ptzMethod"
|
||||
style="width: 100%"
|
||||
size="mini"
|
||||
placeholder="请选择云台功能"
|
||||
>
|
||||
<el-option label="预置点" value="preset"></el-option>
|
||||
<el-option label="巡航组" value="cruise"></el-option>
|
||||
<el-option label="自动扫描" value="scan"></el-option>
|
||||
<el-option label="雨刷" value="wiper"></el-option>
|
||||
<el-option label="辅助开关" value="switch"></el-option>
|
||||
</el-select>
|
||||
|
||||
<div class="control-panel">
|
||||
<el-button-group>
|
||||
<el-tag style="position :absolute; left: 0rem; top: 0rem; width: 5rem; text-align: center"
|
||||
size="medium">预置位编号
|
||||
</el-tag>
|
||||
<el-input-number style="position: absolute; left: 5rem; top: 0rem; width: 6rem" size="mini"
|
||||
v-model="presetPos" controls-position="right" :precision="0" :step="1" :min="1"
|
||||
:max="255"></el-input-number>
|
||||
<el-button style="position: absolute; left: 11rem; top: 0rem; width: 5rem" size="mini"
|
||||
icon="el-icon-add-location" @click="presetPosition(129, presetPos)">设置
|
||||
</el-button>
|
||||
<el-button style="position: absolute; left: 27rem; top: 0rem; width: 5rem" size="mini" type="primary"
|
||||
icon="el-icon-place" @click="presetPosition(130, presetPos)">调用
|
||||
</el-button>
|
||||
<el-button style="position: absolute; left: 16rem; top: 0rem; width: 5rem" size="mini"
|
||||
icon="el-icon-delete-location" @click="presetPosition(131, presetPos)">删除
|
||||
</el-button>
|
||||
<el-tag style="position :absolute; left: 0rem; top: 2.5rem; width: 5rem; text-align: center"
|
||||
size="medium">巡航速度
|
||||
</el-tag>
|
||||
<el-input-number style="position: absolute; left: 5rem; top: 2.5rem; width: 6rem" size="mini"
|
||||
v-model="cruisingSpeed" controls-position="right" :precision="0" :min="1"
|
||||
:max="4095"></el-input-number>
|
||||
<el-button style="position: absolute; left: 11rem; top: 2.5rem; width: 5rem" size="mini"
|
||||
icon="el-icon-loading" @click="setSpeedOrTime(134, cruisingGroup, cruisingSpeed)">设置
|
||||
</el-button>
|
||||
<el-tag style="position :absolute; left: 16rem; top: 2.5rem; width: 5rem; text-align: center"
|
||||
size="medium">停留时间
|
||||
</el-tag>
|
||||
<el-input-number style="position: absolute; left: 21rem; top: 2.5rem; width: 6rem" size="mini"
|
||||
v-model="cruisingTime" controls-position="right" :precision="0" :min="1"
|
||||
:max="4095"></el-input-number>
|
||||
<el-button style="position: absolute; left: 27rem; top: 2.5rem; width: 5rem" size="mini"
|
||||
icon="el-icon-timer" @click="setSpeedOrTime(135, cruisingGroup, cruisingTime)">设置
|
||||
</el-button>
|
||||
<el-tag style="position :absolute; left: 0rem; top: 4.5rem; width: 5rem; text-align: center"
|
||||
size="medium">巡航组编号
|
||||
</el-tag>
|
||||
<el-input-number style="position: absolute; left: 5rem; top: 4.5rem; width: 6rem" size="mini"
|
||||
v-model="cruisingGroup" controls-position="right" :precision="0" :min="0"
|
||||
:max="255"></el-input-number>
|
||||
<el-button style="position: absolute; left: 11rem; top: 4.5rem; width: 5rem" size="mini"
|
||||
icon="el-icon-add-location" @click="setCommand(132, cruisingGroup, presetPos)">添加点
|
||||
</el-button>
|
||||
<el-button style="position: absolute; left: 16rem; top: 4.5rem; width: 5rem" size="mini"
|
||||
icon="el-icon-delete-location" @click="setCommand(133, cruisingGroup, presetPos)">删除点
|
||||
</el-button>
|
||||
<el-button style="position: absolute; left: 21rem; top: 4.5rem; width: 5rem" size="mini"
|
||||
icon="el-icon-delete" @click="setCommand(133, cruisingGroup, 0)">删除组
|
||||
</el-button>
|
||||
<el-button style="position: absolute; left: 27rem; top: 5rem; width: 5rem" size="mini" type="primary"
|
||||
icon="el-icon-video-camera-solid" @click="setCommand(136, cruisingGroup, 0)">巡航
|
||||
</el-button>
|
||||
<el-tag style="position :absolute; left: 0rem; top: 7rem; width: 5rem; text-align: center"
|
||||
size="medium">扫描速度
|
||||
</el-tag>
|
||||
<el-input-number style="position: absolute; left: 5rem; top: 7rem; width: 6rem" size="mini"
|
||||
v-model="scanSpeed" controls-position="right" :precision="0" :min="1"
|
||||
:max="4095"></el-input-number>
|
||||
<el-button style="position: absolute; left: 11rem; top: 7rem; width: 5rem" size="mini"
|
||||
icon="el-icon-loading" @click="setSpeedOrTime(138, scanGroup, scanSpeed)">设置
|
||||
</el-button>
|
||||
<el-tag style="position :absolute; left: 0rem; top: 9rem; width: 5rem; text-align: center"
|
||||
size="medium">扫描组编号
|
||||
</el-tag>
|
||||
<el-input-number style="position: absolute; left: 5rem; top: 9rem; width: 6rem" size="mini"
|
||||
v-model="scanGroup" controls-position="right" :precision="0" :step="1" :min="0"
|
||||
:max="255"></el-input-number>
|
||||
<el-button style="position: absolute; left: 11rem; top: 9rem; width: 5rem" size="mini"
|
||||
icon="el-icon-d-arrow-left" @click="setCommand(137, scanGroup, 1)">左边界
|
||||
</el-button>
|
||||
<el-button style="position: absolute; left: 16rem; top: 9rem; width: 5rem" size="mini"
|
||||
icon="el-icon-d-arrow-right" @click="setCommand(137, scanGroup, 2)">右边界
|
||||
</el-button>
|
||||
<el-button style="position: absolute; left: 27rem; top: 7rem; width: 5rem" size="mini" type="primary"
|
||||
icon="el-icon-video-camera-solid" @click="setCommand(137, scanGroup, 0)">扫描
|
||||
</el-button>
|
||||
<el-button style="position: absolute; left: 27rem; top: 9rem; width: 5rem" size="mini" type="danger"
|
||||
icon="el-icon-switch-button" @click="ptzCamera('stop')">停止
|
||||
</el-button>
|
||||
</el-button-group>
|
||||
<ptzPreset :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'preset'" style="margin-top: 1rem"></ptzPreset>
|
||||
<ptzCruising :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'cruise'" style="margin-top: 1rem"></ptzCruising>
|
||||
<ptzScan :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'scan'" style="margin-top: 1rem"></ptzScan>
|
||||
<ptzWiper :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'wiper'" style="margin-top: 1rem"></ptzWiper>
|
||||
<ptzSwitch :channelDeviceId="channelId" :deviceId="deviceId" v-if="ptzMethod === 'switch'" style="margin-top: 1rem"></ptzSwitch>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="编码信息" name="codec" v-loading="tracksLoading">
|
||||
<p>
|
||||
无法播放或者没有声音?   试一试 
|
||||
<el-button size="mini" type="primary" v-if="!coverPlaying" @click="coverPlay">转码播放</el-button>
|
||||
<el-button size="mini" type="danger" v-if="coverPlaying" @click="convertStopClick">停止转码</el-button>
|
||||
</p>
|
||||
<div class="trank">
|
||||
<p v-if="tracksNotLoaded" style="text-align: center;padding-top: 3rem;">暂无数据</p>
|
||||
<div v-for="(item, index) in tracks" style="width: 50%; float: left" loading>
|
||||
<span>流 {{ index }}</span>
|
||||
<div class="trankInfo" v-if="item.codec_type == 0">
|
||||
<p>格式: {{ item.codec_id_name }}</p>
|
||||
<p>类型: 视频</p>
|
||||
<p>分辨率: {{ item.width }} x {{ item.height }}</p>
|
||||
<p>帧率: {{ item.fps }}</p>
|
||||
</div>
|
||||
<div class="trankInfo" v-if="item.codec_type == 1">
|
||||
<p>格式: {{ item.codec_id_name }}</p>
|
||||
<p>类型: 音频</p>
|
||||
<p>采样位数: {{ item.sample_bit }}</p>
|
||||
<p>采样率: {{ item.sample_rate }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<mediaInfo :app="app" :stream="streamId" :mediaServerId="mediaServerId"></mediaInfo>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="语音对讲" name="broadcast">
|
||||
<div style="padding: 0 10px">
|
||||
@ -327,11 +264,18 @@ import rtcPlayer from '../dialog/rtcPlayer.vue'
|
||||
import LivePlayer from '@liveqing/liveplayer'
|
||||
import crypto from 'crypto'
|
||||
import jessibucaPlayer from '../common/jessibuca.vue'
|
||||
import PtzPreset from "../common/ptzPreset.vue";
|
||||
import PtzCruising from "../common/ptzCruising.vue";
|
||||
import ptzScan from "../common/ptzScan.vue";
|
||||
import ptzWiper from "../common/ptzWiper.vue";
|
||||
import ptzSwitch from "../common/ptzSwitch.vue";
|
||||
import mediaInfo from "../common/mediaInfo.vue";
|
||||
|
||||
export default {
|
||||
name: 'devicePlayer',
|
||||
props: {},
|
||||
components: {
|
||||
PtzPreset,PtzCruising,ptzScan,ptzWiper,ptzSwitch,mediaInfo,
|
||||
LivePlayer, jessibucaPlayer, rtcPlayer,
|
||||
},
|
||||
computed: {
|
||||
@ -363,9 +307,10 @@ export default {
|
||||
},
|
||||
showVideoDialog: false,
|
||||
streamId: '',
|
||||
ptzMethod: 'preset',
|
||||
ptzPresetId: '',
|
||||
app: '',
|
||||
mediaServerId: '',
|
||||
convertKey: '',
|
||||
deviceId: '',
|
||||
channelId: '',
|
||||
tabActiveName: 'media',
|
||||
@ -384,7 +329,6 @@ export default {
|
||||
scanSpeed: 100,
|
||||
scanGroup: 0,
|
||||
tracks: [],
|
||||
coverPlaying: false,
|
||||
tracksLoading: false,
|
||||
showPtz: true,
|
||||
showRrecord: true,
|
||||
@ -484,63 +428,6 @@ export default {
|
||||
}
|
||||
return this.videoUrl;
|
||||
|
||||
},
|
||||
coverPlay: function () {
|
||||
var that = this;
|
||||
this.coverPlaying = true;
|
||||
this.$refs[this.activePlayer].pause()
|
||||
that.$axios({
|
||||
method: 'post',
|
||||
url: '/api/play/convert/' + that.streamId
|
||||
}).then(function (res) {
|
||||
if (res.data.code === 0) {
|
||||
that.convertKey = res.data.key;
|
||||
setTimeout(() => {
|
||||
that.isLoging = false;
|
||||
that.playFromStreamInfo(false, res.data.data);
|
||||
}, 2000)
|
||||
} else {
|
||||
that.isLoging = false;
|
||||
that.coverPlaying = false;
|
||||
that.$message({
|
||||
showClose: true,
|
||||
message: '转码失败',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch(function (e) {
|
||||
console.log(e)
|
||||
that.coverPlaying = false;
|
||||
that.$message({
|
||||
showClose: true,
|
||||
message: '播放错误',
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
},
|
||||
convertStopClick: function () {
|
||||
this.convertStop(() => {
|
||||
this.$refs[this.activePlayer].play(this.videoUrl)
|
||||
});
|
||||
},
|
||||
convertStop: function (callback) {
|
||||
var that = this;
|
||||
that.$refs.videoPlayer.pause()
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: '/api/play/convertStop/' + this.convertKey
|
||||
}).then(function (res) {
|
||||
if (res.data.code == 0) {
|
||||
console.log(res.data.msg)
|
||||
} else {
|
||||
console.error(res.data.msg)
|
||||
}
|
||||
if (callback) callback();
|
||||
}).catch(function (e) {
|
||||
});
|
||||
that.coverPlaying = false;
|
||||
that.convertKey = "";
|
||||
// if (callback )callback();
|
||||
},
|
||||
|
||||
playFromStreamInfo: function (realHasAudio, streamInfo) {
|
||||
@ -562,10 +449,6 @@ export default {
|
||||
this.videoUrl = '';
|
||||
this.coverPlaying = false;
|
||||
this.showVideoDialog = false;
|
||||
if (this.convertKey != '') {
|
||||
this.convertStop();
|
||||
}
|
||||
this.convertKey = ''
|
||||
this.stopBroadcast()
|
||||
},
|
||||
|
||||
@ -595,8 +478,22 @@ export default {
|
||||
console.log('云台控制:' + command);
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed
|
||||
method: 'get',
|
||||
url: '/api/front-end/ptz/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + parseInt(this.controSpeed * 255/100) + '&verticalSpeed=' + parseInt(this.controSpeed * 255/100) + '&zoomSpeed=' + parseInt(this.controSpeed * 16/100)
|
||||
}).then(function (res) {
|
||||
});
|
||||
},
|
||||
irisCamera: function (command) {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: '/api/front-end/fi/iris/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&speed=' + parseInt(this.controSpeed * 255/100)
|
||||
}).then(function (res) {
|
||||
});
|
||||
},
|
||||
focusCamera: function (command) {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: '/api/front-end/fi/focus/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&speed=' + parseInt(this.controSpeed * 255/100)
|
||||
}).then(function (res) {
|
||||
});
|
||||
},
|
||||
@ -1001,4 +898,14 @@ export default {
|
||||
width: 80%;
|
||||
padding: 0 10%;
|
||||
}
|
||||
.el-dialog__body{
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.ptz-btn-box {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
padding: 0 2rem;
|
||||
height: 3rem;
|
||||
line-height: 4rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
width="65rem"
|
||||
top="2rem"
|
||||
center
|
||||
:append-to-body="true"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="showVideoDialog"
|
||||
:destroy-on-close="false"
|
||||
|
||||
@ -1,115 +1,106 @@
|
||||
<template>
|
||||
<div id="shareChannelAdd" style="width: 100%; background-color: #FFFFFF">
|
||||
<div class="page-header">
|
||||
<div class="page-header-btn">
|
||||
<div style="display: inline;">
|
||||
搜索:
|
||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
||||
<div id="shareChannelAdd" style="width: 100%; background-color: #FFFFFF; display: grid; grid-template-columns: 200px auto;">
|
||||
<el-tabs tab-position="left" style="" v-model="hasShare" @tab-click="search">
|
||||
<el-tab-pane label="未共享" name="false"></el-tab-pane>
|
||||
<el-tab-pane label="已共享" name="true"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<div>
|
||||
<div class="page-header">
|
||||
<div class="page-header-btn" style="width: 100%;">
|
||||
<div style="display: inline;">
|
||||
搜索:
|
||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
||||
|
||||
在线状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="在线" value="true"></el-option>
|
||||
<el-option label="离线" value="false"></el-option>
|
||||
</el-select>
|
||||
类型:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="channelType" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="国标设备" :value="0"></el-option>
|
||||
<el-option label="推流设备" :value="1"></el-option>
|
||||
<el-option label="拉流代理" :value="2"></el-option>
|
||||
</el-select>
|
||||
添加状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="hasShare" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="已共享" value="true"></el-option>
|
||||
<el-option label="未共享" value="false"></el-option>
|
||||
</el-select>
|
||||
<el-button v-if="hasShare !=='true'" size="mini" type="primary" @click="add()">
|
||||
添加
|
||||
</el-button>
|
||||
<el-button v-if="hasShare ==='true'" size="mini" type="danger" @click="remove()">
|
||||
移除
|
||||
</el-button>
|
||||
<el-button size="mini" @click="addByDevice()">按设备添加</el-button>
|
||||
<el-button size="mini" @click="removeByDevice()">按设备移除</el-button>
|
||||
<el-button size="mini" @click="addAll()">全部添加</el-button>
|
||||
<el-button size="mini" @click="removeAll()">全部移除</el-button>
|
||||
<el-button size="mini" @click="getChannelList()">刷新</el-button>
|
||||
在线状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="在线" value="true"></el-option>
|
||||
<el-option label="离线" value="false"></el-option>
|
||||
</el-select>
|
||||
类型:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="channelType" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="国标设备" :value="0"></el-option>
|
||||
<el-option label="推流设备" :value="1"></el-option>
|
||||
<el-option label="拉流代理" :value="2"></el-option>
|
||||
</el-select>
|
||||
<el-button v-if="hasShare !=='true'" size="mini" type="primary" @click="add()">
|
||||
添加
|
||||
</el-button>
|
||||
<el-button v-if="hasShare ==='true'" size="mini" type="danger" @click="remove()">
|
||||
移除
|
||||
</el-button>
|
||||
<el-button size="mini" v-if="hasShare !=='true'" @click="addByDevice()">按设备添加</el-button>
|
||||
<el-button size="mini" v-if="hasShare ==='true'" @click="removeByDevice()">按设备移除</el-button>
|
||||
<el-button size="mini" v-if="hasShare !=='true'" @click="addAll()">全部添加</el-button>
|
||||
<el-button size="mini" v-if="hasShare ==='true'" @click="removeAll()">全部移除</el-button>
|
||||
<el-button size="mini" @click="getChannelList()">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
|
||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
|
||||
<el-table-column type="selection" width="55" :selectable="selectable">
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column v-if="hasShare ==='true'" label="自定义名称" min-width="180">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="—" class="name-wrapper">
|
||||
<el-input size="mini" placeholder="不填按原名称" v-model:value="scope.row.customName"></el-input>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="hasShare ==='true'" label="自定义编号" min-width="180">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="—" class="name-wrapper">
|
||||
<el-input size="mini" placeholder="不填按原编号" v-model:value="scope.row.customDeviceId"></el-input>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="hasShare ==='true'" label="" min-width="80">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="mini" type="primary" @click="saveCustom(scope.row)">保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
|
||||
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
|
||||
<el-tag size="medium" effect="plain" type="warning" v-if="scope.row.streamProxyId">拉流代理</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="text-align: right"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="currentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="count"
|
||||
:page-sizes="[15, 25, 35, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
|
||||
</div>
|
||||
<el-table size="small" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%;"
|
||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" >
|
||||
<el-table-column type="selection" width="55" :selectable="selectable">
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbDeviceId" label="编号" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column v-if="hasShare ==='true'" label="自定义名称" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<div slot="—" class="name-wrapper">
|
||||
<el-input size="mini" placeholder="不填按原名称" v-model:value="scope.row.customName"></el-input>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="hasShare ==='true'" label="自定义编号" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<div slot="—" class="name-wrapper">
|
||||
<el-input size="mini" placeholder="不填按原编号" v-model:value="scope.row.customDeviceId"></el-input>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="hasShare ==='true'" label="" min-width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="primary" @click="saveCustom(scope.row)">保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
|
||||
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
|
||||
<el-tag size="medium" effect="plain" type="warning" v-if="scope.row.streamProxyId">拉流代理</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="共享状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" :title="scope.row.platformId" v-if="scope.row.platformId">已共享</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.platformId">未共享</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="text-align: right"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="currentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="count"
|
||||
:page-sizes="[15, 25, 35, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
<gbDeviceSelect ref="gbDeviceSelect"></gbDeviceSelect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@ -1,45 +1,54 @@
|
||||
<template>
|
||||
<div id="region" style="width: 100%">
|
||||
<el-container v-loading="loading" >
|
||||
<el-aside width="400px" >
|
||||
<GroupTree ref="groupTree" :show-header="true" :edit="true" :clickEvent="treeNodeClickEvent" :chooseIdChange="chooseIdChange" :onChannelChange="getChannelList"></GroupTree>
|
||||
<el-container v-loading="loading">
|
||||
<el-aside width="400px">
|
||||
<GroupTree ref="groupTree" :show-header="true" :edit="true" :clickEvent="treeNodeClickEvent"
|
||||
:onChannelChange="onChannelChange" :enableAddChannel="true" :addChannelToGroup="addChannelToGroup"></GroupTree>
|
||||
</el-aside>
|
||||
<el-main style="padding: 5px;">
|
||||
<div class="page-header">
|
||||
<div class="page-title">通道列表</div>
|
||||
<div class="page-title">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item v-for="key in regionParents" key="key">{{ key }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div class="page-header-btn">
|
||||
<div style="display: inline;">
|
||||
<div style="display: inline;">
|
||||
搜索:
|
||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
||||
|
||||
在线状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online"
|
||||
placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="在线" value="true"></el-option>
|
||||
<el-option label="离线" value="false"></el-option>
|
||||
</el-select>
|
||||
添加状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="hasGroup" placeholder="请选择"
|
||||
类型:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList"
|
||||
v-model="channelType" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="已添加" value="true"></el-option>
|
||||
<el-option label="未添加" value="false"></el-option>
|
||||
<el-option label="国标设备" :value="0"></el-option>
|
||||
<el-option label="推流设备" :value="1"></el-option>
|
||||
<el-option label="拉流代理" :value="2"></el-option>
|
||||
</el-select>
|
||||
<el-button v-if="hasGroup !=='true'" size="mini" type="primary" @click="add()">
|
||||
添加
|
||||
<el-button size="mini" type="primary" @click="add()">
|
||||
添加通道
|
||||
</el-button>
|
||||
<el-button v-if="hasGroup ==='true'" size="mini" type="danger" @click="remove()">
|
||||
移除
|
||||
<el-button v-bind:disabled="multipleSelection.length === 0" size="mini" type="danger" @click="remove()">
|
||||
移除通道
|
||||
</el-button>
|
||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="getChannelList()"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-table size="medium" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%"
|
||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" @row-dblclick="rowDblclick">
|
||||
<el-table-column type="selection" width="55" :selectable="selectable">
|
||||
<el-table size="medium" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%"
|
||||
header-row-class-name="table-header" @selection-change="handleSelectionChange"
|
||||
@row-dblclick="rowDblclick">
|
||||
<el-table-column type="selection" width="55" >
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
||||
</el-table-column>
|
||||
@ -48,7 +57,7 @@
|
||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
|
||||
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
|
||||
@ -57,21 +66,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="添加状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" :title="scope.row.gbParentId" v-if="scope.row.gbParentId">已添加</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.gbParentId">未添加</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="text-align: right"
|
||||
@ -85,7 +86,7 @@
|
||||
</el-pagination>
|
||||
</el-main>
|
||||
</el-container>
|
||||
|
||||
<GbChannelSelect ref="gbChannelSelect" dataType="group"></GbChannelSelect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -93,10 +94,14 @@
|
||||
import uiHeader from '../layout/UiHeader.vue'
|
||||
import DeviceService from "./service/DeviceService";
|
||||
import GroupTree from "./common/GroupTree.vue";
|
||||
import GbChannelSelect from "./dialog/GbChannelSelect.vue";
|
||||
import RegionTree from "./common/RegionTree.vue";
|
||||
|
||||
export default {
|
||||
name: 'channelList',
|
||||
components: {
|
||||
RegionTree,
|
||||
GbChannelSelect,
|
||||
uiHeader,
|
||||
GroupTree,
|
||||
},
|
||||
@ -116,6 +121,7 @@ export default {
|
||||
groupDeviceId: "",
|
||||
groupId: "",
|
||||
businessGroup: "",
|
||||
regionParents: ["请选择虚拟组织"],
|
||||
multipleSelection: []
|
||||
};
|
||||
},
|
||||
@ -123,7 +129,8 @@ export default {
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
destroyed() {},
|
||||
destroyed() {
|
||||
},
|
||||
methods: {
|
||||
initData: function () {
|
||||
this.getChannelList();
|
||||
@ -139,15 +146,16 @@ export default {
|
||||
getChannelList: function () {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/common/channel/list`,
|
||||
url: `/api/common/channel/parent/list`,
|
||||
params: {
|
||||
page: this.currentPage,
|
||||
count: this.count,
|
||||
query: this.searchSrt,
|
||||
online: this.online,
|
||||
hasGroup: this.hasGroup
|
||||
channelType: this.channelType,
|
||||
groupDeviceId: this.groupDeviceId
|
||||
}
|
||||
}).then((res)=> {
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.total = res.data.data.total;
|
||||
this.channelList = res.data.data.list;
|
||||
@ -157,77 +165,67 @@ export default {
|
||||
})
|
||||
}
|
||||
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
handleSelectionChange: function (val){
|
||||
handleSelectionChange: function (val) {
|
||||
this.multipleSelection = val;
|
||||
},
|
||||
selectable: function (row, rowIndex) {
|
||||
if (this.hasGroup === "") {
|
||||
if (row.gbParentId) {
|
||||
return false
|
||||
}else {
|
||||
return true
|
||||
}
|
||||
}else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
rowDblclick: function (row, rowIndex) {
|
||||
|
||||
},
|
||||
add: function (row) {
|
||||
if (!this.groupDeviceId) {
|
||||
if (this.regionDeviceId === "") {
|
||||
this.$message.info({
|
||||
showClose: true,
|
||||
message: "请选择左侧行政区划节点"
|
||||
})
|
||||
return;
|
||||
}
|
||||
let channels = []
|
||||
for (let i = 0; i < this.multipleSelection.length; i++) {
|
||||
channels.push(this.multipleSelection[i].gbId)
|
||||
}
|
||||
if (channels.length === 0) {
|
||||
this.$message.info({
|
||||
showClose: true,
|
||||
message: "请选择右侧通道"
|
||||
message: "请选择左侧虚拟组织节点"
|
||||
})
|
||||
return;
|
||||
}
|
||||
this.$refs.gbChannelSelect.openDialog((data) => {
|
||||
console.log("选择的数据")
|
||||
console.log(data)
|
||||
this.addChannelToGroup(this.groupDeviceId, this.businessGroup, data)
|
||||
})
|
||||
},
|
||||
addChannelToGroup: function (groupDeviceId, businessGroup, data) {
|
||||
if (data.length === 0) {
|
||||
return;
|
||||
}
|
||||
let channels = []
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
channels.push(data[i].gbId)
|
||||
}
|
||||
this.loading = true
|
||||
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: `/api/common/channel/group/add`,
|
||||
data: {
|
||||
parentId: this.groupDeviceId,
|
||||
businessGroup: this.businessGroup,
|
||||
parentId: groupDeviceId,
|
||||
businessGroup: businessGroup,
|
||||
channelIds: channels
|
||||
}
|
||||
}).then((res)=> {
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.$message.success({
|
||||
showClose: true,
|
||||
message: "保存成功"
|
||||
})
|
||||
this.getChannelList()
|
||||
// 刷新树节点
|
||||
this.$refs.groupTree.refresh(this.groupId)
|
||||
}else {
|
||||
} else {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: error
|
||||
})
|
||||
showClose: true,
|
||||
message: error
|
||||
})
|
||||
this.loading = false
|
||||
});
|
||||
},
|
||||
@ -240,7 +238,7 @@ export default {
|
||||
if (channels.length === 0) {
|
||||
this.$message.info({
|
||||
showClose: true,
|
||||
message: "请选择右侧通道"
|
||||
message: "请选择通道"
|
||||
})
|
||||
return;
|
||||
}
|
||||
@ -252,7 +250,7 @@ export default {
|
||||
data: {
|
||||
channelIds: channels
|
||||
}
|
||||
}).then((res)=> {
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.$message.success({
|
||||
showClose: true,
|
||||
@ -261,18 +259,18 @@ export default {
|
||||
this.getChannelList()
|
||||
// 刷新树节点
|
||||
this.$refs.groupTree.refresh(this.groupDeviceId)
|
||||
}else {
|
||||
} else {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: error
|
||||
})
|
||||
showClose: true,
|
||||
message: error
|
||||
})
|
||||
this.loading = false
|
||||
});
|
||||
},
|
||||
@ -288,13 +286,38 @@ export default {
|
||||
refresh: function () {
|
||||
this.initData();
|
||||
},
|
||||
treeNodeClickEvent: function (device, data, isCatalog) {
|
||||
treeNodeClickEvent: function (group) {
|
||||
if (group.deviceId === "" || group.deviceId === group.businessGroup) {
|
||||
this.channelList = []
|
||||
this.regionParents = ["请选择虚拟组织"];
|
||||
return
|
||||
}
|
||||
this.groupDeviceId = group.deviceId;
|
||||
this.businessGroup = group.businessGroup;
|
||||
this.initData();
|
||||
// 获取regionDeviceId对应的节点信息
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/group/path`,
|
||||
params: {
|
||||
deviceId: this.groupDeviceId,
|
||||
businessGroup: this.businessGroup,
|
||||
}
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
let path = []
|
||||
for (let i = 0; i < res.data.data.length; i++) {
|
||||
path.push(res.data.data[i].name)
|
||||
}
|
||||
this.regionParents = path;
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
chooseIdChange: function (id, deviceId, businessGroup) {
|
||||
this.groupId = id;
|
||||
this.groupDeviceId = deviceId;
|
||||
this.businessGroup = businessGroup;
|
||||
onChannelChange: function (deviceId) {
|
||||
//
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@ -41,22 +41,22 @@
|
||||
<el-table-column prop="fileName" label="文件名">
|
||||
</el-table-column>
|
||||
<el-table-column prop="fileSize" label="文件大小">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
{{formatFileSize(scope.row.fileSize)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="开始时间">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
{{formatTimeStamp(scope.row.startTime)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
{{formatTimeStamp(scope.row.endTime)}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<el-button size="medium" icon="el-icon-document" type="text" @click="showLogView(scope.row)">查看
|
||||
</el-button>
|
||||
<el-button size="medium" icon="el-icon-download" type="text" @click="downloadFile(scope.row)">下载
|
||||
|
||||
@ -1,45 +1,53 @@
|
||||
<template>
|
||||
<div id="region" style="width: 100%">
|
||||
<el-container v-loading="loading" >
|
||||
<el-aside width="400px" >
|
||||
<RegionTree ref="regionTree" :showHeader=true :edit="true" :clickEvent="treeNodeClickEvent" :chooseIdChange="chooseIdChange" :onChannelChange="getChannelList"></RegionTree>
|
||||
<el-container v-loading="loading">
|
||||
<el-aside width="400px">
|
||||
<RegionTree ref="regionTree" :showHeader=true :edit="true" :clickEvent="treeNodeClickEvent"
|
||||
:onChannelChange="onChannelChange" :enableAddChannel="true" :addChannelToCivilCode="addChannelToCivilCode"></RegionTree>
|
||||
</el-aside>
|
||||
<el-main style="padding: 5px;">
|
||||
<div class="page-header">
|
||||
<div class="page-title">通道列表</div>
|
||||
<div class="page-title">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item v-for="key in regionParents" key="key">{{ key }}</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div class="page-header-btn">
|
||||
<div style="display: inline;">
|
||||
<div style="display: inline;">
|
||||
搜索:
|
||||
<el-input @input="search" style="margin-right: 1rem; width: auto;" size="mini" placeholder="关键字"
|
||||
prefix-icon="el-icon-search" v-model="searchSrt" clearable></el-input>
|
||||
|
||||
在线状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online" placeholder="请选择"
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="online"
|
||||
placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="在线" value="true"></el-option>
|
||||
<el-option label="离线" value="false"></el-option>
|
||||
</el-select>
|
||||
添加状态:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="search" v-model="hasCivilCode" placeholder="请选择"
|
||||
类型:
|
||||
<el-select size="mini" style="width: 8rem; margin-right: 1rem;" @change="getChannelList" v-model="channelType" placeholder="请选择"
|
||||
default-first-option>
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="已添加" value="true"></el-option>
|
||||
<el-option label="未添加" value="false"></el-option>
|
||||
<el-option label="国标设备" :value="0"></el-option>
|
||||
<el-option label="推流设备" :value="1"></el-option>
|
||||
<el-option label="拉流代理" :value="2"></el-option>
|
||||
</el-select>
|
||||
<el-button v-if="hasCivilCode !=='true'" size="mini" type="primary" @click="add()">
|
||||
添加
|
||||
<el-button size="mini" type="primary" @click="add()">
|
||||
添加通道
|
||||
</el-button>
|
||||
<el-button v-if="hasCivilCode ==='true'" size="mini" type="danger" @click="remove()">
|
||||
移除
|
||||
<el-button v-bind:disabled="multipleSelection.length === 0" size="mini" type="danger" @click="remove()">
|
||||
移除通道
|
||||
</el-button>
|
||||
<el-button icon="el-icon-refresh-right" circle size="mini" @click="getChannelList()"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-table size="medium" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%"
|
||||
header-row-class-name="table-header" @selection-change="handleSelectionChange" @row-dblclick="rowDblclick">
|
||||
<el-table-column type="selection" width="55" :selectable="selectable">
|
||||
<el-table size="medium" ref="channelListTable" :data="channelList" :height="winHeight" style="width: 100%"
|
||||
header-row-class-name="table-header" @selection-change="handleSelectionChange"
|
||||
@row-dblclick="rowDblclick">
|
||||
<el-table-column type="selection" width="55">
|
||||
</el-table-column>
|
||||
<el-table-column prop="gbName" label="名称" min-width="180">
|
||||
</el-table-column>
|
||||
@ -48,7 +56,7 @@
|
||||
<el-table-column prop="gbManufacturer" label="厂家" min-width="100">
|
||||
</el-table-column>
|
||||
<el-table-column label="类型" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" effect="plain" v-if="scope.row.gbDeviceDbId">国标设备</el-tag>
|
||||
<el-tag size="medium" effect="plain" type="success" v-if="scope.row.streamPushId">推流设备</el-tag>
|
||||
@ -57,21 +65,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<template v-slot:default="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" v-if="scope.row.gbStatus === 'ON'">在线</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="scope.row.gbStatus !== 'ON'">离线</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="添加状态" min-width="100">
|
||||
<template slot-scope="scope">
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium" :title="scope.row.gbCivilCode" v-if="scope.row.gbCivilCode">已添加</el-tag>
|
||||
<el-tag size="medium" type="info" v-if="!scope.row.gbCivilCode">未添加</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
style="text-align: right"
|
||||
@ -85,7 +85,7 @@
|
||||
</el-pagination>
|
||||
</el-main>
|
||||
</el-container>
|
||||
|
||||
<GbChannelSelect ref="gbChannelSelect" dataType="civilCode"></GbChannelSelect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -93,10 +93,12 @@
|
||||
import uiHeader from '../layout/UiHeader.vue'
|
||||
import DeviceService from "./service/DeviceService";
|
||||
import RegionTree from "./common/RegionTree.vue";
|
||||
import GbChannelSelect from "./dialog/GbChannelSelect.vue";
|
||||
|
||||
export default {
|
||||
name: 'channelList',
|
||||
components: {
|
||||
GbChannelSelect,
|
||||
uiHeader,
|
||||
RegionTree,
|
||||
},
|
||||
@ -106,7 +108,6 @@ export default {
|
||||
searchSrt: "",
|
||||
channelType: "",
|
||||
online: "",
|
||||
hasCivilCode: "false",
|
||||
winHeight: window.innerHeight - 180,
|
||||
currentPage: 1,
|
||||
count: 15,
|
||||
@ -115,6 +116,7 @@ export default {
|
||||
loadSnap: {},
|
||||
regionId: "",
|
||||
regionDeviceId: "",
|
||||
regionParents: ["请选择行政区划"],
|
||||
multipleSelection: []
|
||||
};
|
||||
},
|
||||
@ -122,7 +124,8 @@ export default {
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
destroyed() {},
|
||||
destroyed() {
|
||||
},
|
||||
methods: {
|
||||
initData: function () {
|
||||
this.getChannelList();
|
||||
@ -138,15 +141,16 @@ export default {
|
||||
getChannelList: function () {
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/common/channel/list`,
|
||||
url: `/api/common/channel/civilcode/list`,
|
||||
params: {
|
||||
page: this.currentPage,
|
||||
count: this.count,
|
||||
query: this.searchSrt,
|
||||
online: this.online,
|
||||
hasCivilCode: this.hasCivilCode
|
||||
channelType: this.channelType,
|
||||
civilCode: this.regionDeviceId
|
||||
}
|
||||
}).then((res)=> {
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.total = res.data.data.total;
|
||||
this.channelList = res.data.data.list;
|
||||
@ -156,48 +160,39 @@ export default {
|
||||
})
|
||||
}
|
||||
|
||||
}).catch((error)=> {
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
handleSelectionChange: function (val){
|
||||
handleSelectionChange: function (val) {
|
||||
this.multipleSelection = val;
|
||||
},
|
||||
selectable: function (row, rowIndex) {
|
||||
if (this.hasCivilCode === "") {
|
||||
if (row.gbCivilCode) {
|
||||
return false
|
||||
}else {
|
||||
return true
|
||||
}
|
||||
}else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
rowDblclick: function (row, rowIndex) {
|
||||
// if (row.gbCivilCode) {
|
||||
// this.$refs.regionTree.refresh(row.gbCivilCode)
|
||||
// }
|
||||
},
|
||||
add: function (row) {
|
||||
if (!this.regionDeviceId) {
|
||||
if (this.regionDeviceId === "") {
|
||||
this.$message.info({
|
||||
showClose: true,
|
||||
message: "请选择左侧行政区划节点"
|
||||
message: "请选择左侧行政区划"
|
||||
})
|
||||
return;
|
||||
}
|
||||
this.$refs.gbChannelSelect.openDialog((data) => {
|
||||
console.log("选择的数据")
|
||||
console.log(data)
|
||||
this.addChannelToCivilCode(this.regionDeviceId, data)
|
||||
})
|
||||
},
|
||||
addChannelToCivilCode: function (regionDeviceId, data) {
|
||||
if (data.length === 0) {
|
||||
return;
|
||||
}
|
||||
let channels = []
|
||||
for (let i = 0; i < this.multipleSelection.length; i++) {
|
||||
channels.push(this.multipleSelection[i].gbId)
|
||||
}
|
||||
if (channels.length === 0) {
|
||||
this.$message.info({
|
||||
showClose: true,
|
||||
message: "请选择右侧通道"
|
||||
})
|
||||
return;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
channels.push(data[i].gbId)
|
||||
}
|
||||
this.loading = true
|
||||
|
||||
@ -205,30 +200,28 @@ export default {
|
||||
method: 'post',
|
||||
url: `/api/common/channel/region/add`,
|
||||
data: {
|
||||
civilCode: this.regionDeviceId,
|
||||
civilCode: regionDeviceId,
|
||||
channelIds: channels
|
||||
}
|
||||
}).then((res)=> {
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.$message.success({
|
||||
showClose: true,
|
||||
message: "保存成功"
|
||||
})
|
||||
this.getChannelList()
|
||||
// 刷新树节点
|
||||
this.$refs.regionTree.refresh(this.regionId)
|
||||
}else {
|
||||
} else {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: error
|
||||
})
|
||||
showClose: true,
|
||||
message: error
|
||||
})
|
||||
this.loading = false
|
||||
});
|
||||
},
|
||||
@ -240,7 +233,7 @@ export default {
|
||||
if (channels.length === 0) {
|
||||
this.$message.info({
|
||||
showClose: true,
|
||||
message: "请选择右侧通道"
|
||||
message: "请选择通道"
|
||||
})
|
||||
return;
|
||||
}
|
||||
@ -252,7 +245,7 @@ export default {
|
||||
data: {
|
||||
channelIds: channels
|
||||
}
|
||||
}).then((res)=> {
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.$message.success({
|
||||
showClose: true,
|
||||
@ -261,18 +254,18 @@ export default {
|
||||
this.getChannelList()
|
||||
// 刷新树节点
|
||||
this.$refs.regionTree.refresh(this.regionId)
|
||||
}else {
|
||||
} else {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
showClose: true,
|
||||
message: res.data.msg
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
}).catch((error)=> {
|
||||
}).catch((error) => {
|
||||
this.$message.error({
|
||||
showClose: true,
|
||||
message: error
|
||||
})
|
||||
showClose: true,
|
||||
message: error
|
||||
})
|
||||
this.loading = false
|
||||
});
|
||||
},
|
||||
@ -288,67 +281,39 @@ export default {
|
||||
refresh: function () {
|
||||
this.initData();
|
||||
},
|
||||
treeNodeClickEvent: function (device, data, isCatalog) {
|
||||
treeNodeClickEvent: function (region) {
|
||||
this.regionDeviceId = region.deviceId;
|
||||
if (region.deviceId === "") {
|
||||
this.channelList = []
|
||||
this.regionParents = ["请选择行政区划"];
|
||||
}
|
||||
this.initData();
|
||||
// 获取regionDeviceId对应的节点信息
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/region/path`,
|
||||
params: {
|
||||
deviceId: this.regionDeviceId,
|
||||
}
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
let path = []
|
||||
for (let i = 0; i < res.data.data.length; i++) {
|
||||
path.push(res.data.data[i].name)
|
||||
}
|
||||
this.regionParents = path;
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
},
|
||||
chooseIdChange: function (id, deviceId) {
|
||||
this.regionDeviceId = deviceId;
|
||||
this.regionId = id;
|
||||
gbChannelSelectEnd: function (selectedData) {
|
||||
console.log(selectedData);
|
||||
},
|
||||
onChannelChange: function (deviceId) {
|
||||
//
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.videoList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.video-item {
|
||||
position: relative;
|
||||
width: 15rem;
|
||||
height: 10rem;
|
||||
margin-right: 1rem;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.video-item-img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.video-item-img:after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
background-image: url("../assets/loading.png");
|
||||
background-size: cover;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.video-item-title {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
color: #000000;
|
||||
background-color: #ffffff;
|
||||
line-height: 1.5rem;
|
||||
padding: 0.3rem;
|
||||
width: 14.4rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 1291092 */
|
||||
src: url('iconfont.woff2?t=1726109971995') format('woff2'),
|
||||
url('iconfont.woff?t=1726109971995') format('woff'),
|
||||
url('iconfont.ttf?t=1726109971995') format('truetype');
|
||||
src: url('iconfont.woff2?t=1731484250872') format('woff2'),
|
||||
url('iconfont.woff?t=1731484250872') format('woff'),
|
||||
url('iconfont.ttf?t=1731484250872') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
@ -13,6 +13,22 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-bianjiao-suoxiao:before {
|
||||
content: "\e8c8";
|
||||
}
|
||||
|
||||
.icon-bianjiao-fangda:before {
|
||||
content: "\e8c9";
|
||||
}
|
||||
|
||||
.icon-guangquan-:before {
|
||||
content: "\e7e9";
|
||||
}
|
||||
|
||||
.icon-guangquan:before {
|
||||
content: "\e7ea";
|
||||
}
|
||||
|
||||
.icon-a-mti-1fenpingshi:before {
|
||||
content: "\e7e5";
|
||||
}
|
||||
|
||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user