mirror of
https://gitee.com/pan648540858/wvp-GB28181-pro.git
synced 2026-06-15 16:17:48 +08:00
支持通用通道云台控制,支持地图位置编辑
This commit is contained in:
parent
602cd390e0
commit
c0ef35c3a0
@ -9,9 +9,9 @@ import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToGroupByGbDevicePar
|
|||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToGroupParam;
|
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToGroupParam;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToRegionByGbDeviceParam;
|
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToRegionByGbDeviceParam;
|
||||||
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToRegionParam;
|
import com.genersoft.iot.vmp.gb28181.controller.bean.ChannelToRegionParam;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelFrontEndService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelPlayService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||||
import com.genersoft.iot.vmp.media.service.IMediaServerService;
|
|
||||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
|
||||||
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
|
||||||
@ -24,6 +24,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
|||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
@ -31,7 +32,6 @@ import org.springframework.util.ObjectUtils;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.context.request.async.DeferredResult;
|
import org.springframework.web.context.request.async.DeferredResult;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -51,10 +51,10 @@ public class ChannelController {
|
|||||||
private IGbChannelService channelService;
|
private IGbChannelService channelService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IMediaServerService mediaServerService;
|
private IGbChannelPlayService channelPlayService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IGbChannelPlayService channelPlayService;
|
private IGbChannelFrontEndService channelFrontEndService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserSetting userSetting;
|
private UserSetting userSetting;
|
||||||
@ -464,4 +464,371 @@ public class ChannelController {
|
|||||||
Assert.notNull(channel, "通道不存在");
|
Assert.notNull(channel, "通道不存在");
|
||||||
channelPlayService.playbackSpeed(channel, stream, speed);
|
channelPlayService.playbackSpeed(channel, stream, speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Operation(summary = "云台控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "command", description = "控制指令,允许值: left, right, up, down, upleft, upright, downleft, downright, zoomin, zoomout, stop", required = true)
|
||||||
|
@Parameter(name = "horizonSpeed", description = "水平速度(0-255)", required = true)
|
||||||
|
@Parameter(name = "verticalSpeed", description = "垂直速度(0-255)", required = true)
|
||||||
|
@Parameter(name = "zoomSpeed", description = "缩放速度(0-15)", required = true)
|
||||||
|
@GetMapping("/ptz")
|
||||||
|
public void ptz(Integer channelId, String command, Integer horizonSpeed, Integer verticalSpeed, Integer zoomSpeed){
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug(String.format("设备云台控制 API调用,channelId:%s ,command:%s ,horizonSpeed:%d ,verticalSpeed:%d ,zoomSpeed:%d",channelId, command, horizonSpeed, verticalSpeed, zoomSpeed));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (horizonSpeed == null) {
|
||||||
|
horizonSpeed = 100;
|
||||||
|
}else if (horizonSpeed < 0 || horizonSpeed > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "horizonSpeed 为 0-255的数字");
|
||||||
|
}
|
||||||
|
if (verticalSpeed == null) {
|
||||||
|
verticalSpeed = 100;
|
||||||
|
}else if (verticalSpeed < 0 || verticalSpeed > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "verticalSpeed 为 0-255的数字");
|
||||||
|
}
|
||||||
|
if (zoomSpeed == null) {
|
||||||
|
zoomSpeed = 16;
|
||||||
|
}else if (zoomSpeed < 0 || zoomSpeed > 15) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "zoomSpeed 为 0-15的数字");
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.ptz(channel, command, horizonSpeed, verticalSpeed, zoomSpeed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Operation(summary = "光圈控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "command", description = "控制指令,允许值: in, out, stop", required = true)
|
||||||
|
@Parameter(name = "speed", description = "光圈速度(0-255)", required = true)
|
||||||
|
@GetMapping("/fi/iris")
|
||||||
|
public void iris(Integer channelId, String command, Integer speed){
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("设备光圈控制 API调用,channelId:{} ,command:{} ,speed:{} ",channelId, command, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (speed == null) {
|
||||||
|
speed = 100;
|
||||||
|
}else if (speed < 0 || speed > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "speed 为 0-255的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.iris(channel, command, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "聚焦控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "command", description = "控制指令,允许值: near, far, stop", required = true)
|
||||||
|
@Parameter(name = "speed", description = "聚焦速度(0-255)", required = true)
|
||||||
|
@GetMapping("/fi/focus")
|
||||||
|
public void focus(Integer channelId, String command, Integer speed){
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("设备聚焦控制 API调用,channelId:{} ,command:{} ,speed:{} ",channelId, command, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (speed == null) {
|
||||||
|
speed = 100;
|
||||||
|
}else if (speed < 0 || speed > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "speed 为 0-255的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.focus(channel, command, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@GetMapping("/preset/query")
|
||||||
|
public DeferredResult<WVPResult<Object>> queryPreset(Integer channelId) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("设备预置位查询API调用");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
DeferredResult<WVPResult<Object>> deferredResult = new DeferredResult<> (3 * 1000L);
|
||||||
|
channelFrontEndService.queryPreset(channel, (code, msg, data) -> {
|
||||||
|
deferredResult.setResult(new WVPResult<>(code, msg, data));
|
||||||
|
});
|
||||||
|
|
||||||
|
deferredResult.onTimeout(()->{
|
||||||
|
log.warn("[获取设备预置位] 超时, {}", channelId);
|
||||||
|
deferredResult.setResult(WVPResult.fail(ErrorCode.ERROR100.getCode(), "超时"));
|
||||||
|
});
|
||||||
|
return deferredResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "预置位指令-设置预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
|
||||||
|
@GetMapping("/preset/add")
|
||||||
|
public void addPreset(Integer channelId, Integer presetId) {
|
||||||
|
if (presetId == null || presetId < 1 || presetId > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.addPreset(channel, presetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "预置位指令-调用预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
|
||||||
|
@GetMapping("/preset/call")
|
||||||
|
public void callPreset(Integer channelId, Integer presetId) {
|
||||||
|
if (presetId == null || presetId < 1 || presetId > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.callPreset(channel, presetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "预置位指令-删除预置位", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
|
||||||
|
@GetMapping("/preset/delete")
|
||||||
|
public void deletePreset(Integer channelId, Integer presetId) {
|
||||||
|
if (presetId == null || presetId < 1 || presetId > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "预置位编号必须为1-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.deletePreset(channel, presetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "巡航指令-加入巡航点", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "cruiseId", description = "巡航组号(0-255)", required = true)
|
||||||
|
@Parameter(name = "presetId", description = "预置位编号(1-255)", required = true)
|
||||||
|
@GetMapping("/cruise/point/add")
|
||||||
|
public void addCruisePoint(Integer 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之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.addCruisePoint(channel, cruiseId, presetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "巡航指令-删除一个巡航点", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "cruiseId", description = "巡航组号(1-255)", required = true)
|
||||||
|
@Parameter(name = "presetId", description = "预置位编号(0-255, 为0时删除整个巡航)", required = true)
|
||||||
|
@GetMapping("/cruise/point/delete")
|
||||||
|
public void deleteCruisePoint(Integer 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之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.deleteCruisePoint(channel, cruiseId, presetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "巡航指令-设置巡航速度", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "cruiseId", description = "巡航组号(0-255)", required = true)
|
||||||
|
@Parameter(name = "speed", description = "巡航速度(1-4095)", required = true)
|
||||||
|
@GetMapping("/cruise/speed")
|
||||||
|
public void setCruiseSpeed(Integer 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之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.setCruiseSpeed(channel, cruiseId, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "巡航指令-设置巡航停留时间", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "cruiseId", description = "巡航组号", required = true)
|
||||||
|
@Parameter(name = "time", description = "巡航停留时间(1-4095)", required = true)
|
||||||
|
@GetMapping("/cruise/time")
|
||||||
|
public void setCruiseTime(Integer 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之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.setCruiseTime(channel, cruiseId, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "巡航指令-开始巡航", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "cruiseId", description = "巡航组号)", required = true)
|
||||||
|
@GetMapping("/cruise/start")
|
||||||
|
public void startCruise(Integer channelId, Integer cruiseId) {
|
||||||
|
if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.startCruise(channel, cruiseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "巡航指令-停止巡航", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "cruiseId", description = "巡航组号", required = true)
|
||||||
|
@GetMapping("/cruise/stop")
|
||||||
|
public void stopCruise(Integer channelId, Integer cruiseId) {
|
||||||
|
if (cruiseId == null || cruiseId < 0 || cruiseId > 255) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "巡航组号必须为0-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.stopCruise(channel, cruiseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "扫描指令-开始自动扫描", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||||
|
@GetMapping("/scan/start")
|
||||||
|
public void startScan(Integer channelId, Integer scanId) {
|
||||||
|
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.startScan(channel, scanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "扫描指令-停止自动扫描", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||||
|
@GetMapping("/scan/stop")
|
||||||
|
public void stopScan(Integer channelId, Integer scanId) {
|
||||||
|
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.stopScan(channel, scanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "扫描指令-设置自动扫描左边界", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||||
|
@GetMapping("/scan/set/left")
|
||||||
|
public void setScanLeft(Integer channelId, Integer scanId) {
|
||||||
|
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.setScanLeft(channel, scanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "扫描指令-设置自动扫描右边界", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||||
|
@GetMapping("/scan/set/right")
|
||||||
|
public void setScanRight(Integer channelId, Integer scanId) {
|
||||||
|
if (scanId == null || scanId < 0 || scanId > 255 ) {
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "扫描组号必须为0-255之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.setScanRight(channel, scanId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Operation(summary = "扫描指令-设置自动扫描速度", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "scanId", description = "扫描组号(0-255)", required = true)
|
||||||
|
@Parameter(name = "speed", description = "自动扫描速度(1-4095)", required = true)
|
||||||
|
@GetMapping("/scan/set/speed")
|
||||||
|
public void setScanSpeed(Integer 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之间的数字");
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.setScanSpeed(channel, scanId, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Operation(summary = "辅助开关控制指令-雨刷控制", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "command", description = "控制指令,允许值: on, off", required = true)
|
||||||
|
@GetMapping("/wiper")
|
||||||
|
public void wiper(Integer channelId, String command){
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("辅助开关控制指令-雨刷控制 API调用,channelId:{} ,command:{}",channelId, command);
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.wiper(channel, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "辅助开关控制指令", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "channelId", description = "通道ID", required = true)
|
||||||
|
@Parameter(name = "command", description = "控制指令,允许值: on, off", required = true)
|
||||||
|
@Parameter(name = "switchId", description = "开关编号", required = true)
|
||||||
|
@GetMapping("/auxiliary")
|
||||||
|
public void auxiliarySwitch(Integer channelId, String command, Integer switchId){
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("辅助开关控制指令-雨刷控制 API调用,channelId:{} ,command:{}, switchId: {}", channelId, command, switchId);
|
||||||
|
}
|
||||||
|
CommonGBChannel channel = channelService.getOne(channelId);
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
|
||||||
|
channelFrontEndService.auxiliarySwitch(channel, command, switchId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "为地图获取通道列表", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||||
|
@Parameter(name = "query", description = "查询内容")
|
||||||
|
@Parameter(name = "online", description = "是否在线")
|
||||||
|
@Parameter(name = "hasRecordPlan", description = "是否已设置录制计划")
|
||||||
|
@Parameter(name = "channelType", description = "通道类型, 0:国标设备,1:推流设备,2:拉流代理")
|
||||||
|
@Parameter(name = "geoCoordSys", description = "地理坐标系, WGS84/GCJ02")
|
||||||
|
@GetMapping("/map/list")
|
||||||
|
public List<CommonGBChannel> queryListForMap(
|
||||||
|
@RequestParam(required = false) String query,
|
||||||
|
@RequestParam(required = false) Boolean online,
|
||||||
|
@RequestParam(required = false) Boolean hasRecordPlan,
|
||||||
|
@RequestParam(required = false) Integer channelType){
|
||||||
|
if (ObjectUtils.isEmpty(query)){
|
||||||
|
query = null;
|
||||||
|
}
|
||||||
|
return channelService.queryListForMap(query, online, hasRecordPlan, channelType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,52 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.service;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.Preset;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface IGbChannelFrontEndService {
|
||||||
|
|
||||||
|
|
||||||
|
void ptz(CommonGBChannel channel, String command, Integer horizonSpeed, Integer verticalSpeed, Integer zoomSpeed);
|
||||||
|
|
||||||
|
void iris(CommonGBChannel channel, String command, Integer speed);
|
||||||
|
|
||||||
|
void focus(CommonGBChannel channel, String command, Integer speed);
|
||||||
|
|
||||||
|
void queryPreset(CommonGBChannel channel, ErrorCallback<List<Preset>> callback);
|
||||||
|
|
||||||
|
void addPreset(CommonGBChannel channel, Integer presetId);
|
||||||
|
|
||||||
|
void callPreset(CommonGBChannel channel, Integer presetId);
|
||||||
|
|
||||||
|
void deletePreset(CommonGBChannel channel, Integer presetId);
|
||||||
|
|
||||||
|
void addCruisePoint(CommonGBChannel channel, Integer cruiseId, Integer presetId);
|
||||||
|
|
||||||
|
void deleteCruisePoint(CommonGBChannel channel, Integer cruiseId, Integer presetId);
|
||||||
|
|
||||||
|
void setCruiseSpeed(CommonGBChannel channel, Integer cruiseId, Integer speed);
|
||||||
|
|
||||||
|
void setCruiseTime(CommonGBChannel channel, Integer cruiseId, Integer time);
|
||||||
|
|
||||||
|
void startCruise(CommonGBChannel channel, Integer cruiseId);
|
||||||
|
|
||||||
|
void stopCruise(CommonGBChannel channel, Integer cruiseId);
|
||||||
|
|
||||||
|
void startScan(CommonGBChannel channel, Integer scanId);
|
||||||
|
|
||||||
|
void stopScan(CommonGBChannel channel, Integer scanId);
|
||||||
|
|
||||||
|
void setScanLeft(CommonGBChannel channel, Integer scanId);
|
||||||
|
|
||||||
|
void setScanRight(CommonGBChannel channel, Integer scanId);
|
||||||
|
|
||||||
|
void setScanSpeed(CommonGBChannel channel, Integer scanId, Integer speed);
|
||||||
|
|
||||||
|
void wiper(CommonGBChannel channel, String command);
|
||||||
|
|
||||||
|
void auxiliarySwitch(CommonGBChannel channel, String command, Integer switchId);
|
||||||
|
|
||||||
|
}
|
||||||
@ -97,4 +97,6 @@ public interface IGbChannelService {
|
|||||||
void updateGPSFromGPSMsgInfo(List<GPSMsgInfo> gpsMsgInfoList);
|
void updateGPSFromGPSMsgInfo(List<GPSMsgInfo> gpsMsgInfoList);
|
||||||
|
|
||||||
void updateGPS(List<CommonGBChannel> channelList);
|
void updateGPS(List<CommonGBChannel> channelList);
|
||||||
|
|
||||||
|
List<CommonGBChannel> queryListForMap(String query, Boolean online, Boolean hasRecordPlan, Integer channelType);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,534 @@
|
|||||||
|
package com.genersoft.iot.vmp.gb28181.service.impl;
|
||||||
|
|
||||||
|
import com.genersoft.iot.vmp.common.enums.ChannelDataType;
|
||||||
|
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceService;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelFrontEndService;
|
||||||
|
import com.genersoft.iot.vmp.gb28181.service.IPTZService;
|
||||||
|
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
||||||
|
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 org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import javax.sip.message.Response;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class GbChannelFrontEndServiceImpl implements IGbChannelFrontEndService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IPTZService ptzService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IDeviceService deviceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private IDeviceChannelService deviceChannelService;
|
||||||
|
|
||||||
|
private void frontEndCommand(CommonGBChannel channel, Integer cmdCode, Integer parameter1, Integer parameter2, Integer combindCode2){
|
||||||
|
|
||||||
|
Assert.isTrue(channel.getDataType() == ChannelDataType.GB28181, "类型获取错误");
|
||||||
|
|
||||||
|
Device device = deviceService.getDevice(channel.getDataDeviceId());
|
||||||
|
Assert.notNull(device, "设备不存在");
|
||||||
|
|
||||||
|
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
|
||||||
|
Assert.notNull(device, "原始通道不存在");
|
||||||
|
|
||||||
|
ptzService.frontEndCommand(device, deviceChannel.getDeviceId(), cmdCode, parameter1, parameter2, combindCode2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ptz(CommonGBChannel channel, String command, Integer horizonSpeed, Integer verticalSpeed, Integer zoomSpeed) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
int cmdCode = 0;
|
||||||
|
switch (command){
|
||||||
|
case "left":
|
||||||
|
cmdCode = 2;
|
||||||
|
break;
|
||||||
|
case "right":
|
||||||
|
cmdCode = 1;
|
||||||
|
break;
|
||||||
|
case "up":
|
||||||
|
cmdCode = 8;
|
||||||
|
break;
|
||||||
|
case "down":
|
||||||
|
cmdCode = 4;
|
||||||
|
break;
|
||||||
|
case "upleft":
|
||||||
|
cmdCode = 10;
|
||||||
|
break;
|
||||||
|
case "upright":
|
||||||
|
cmdCode = 9;
|
||||||
|
break;
|
||||||
|
case "downleft":
|
||||||
|
cmdCode = 6;
|
||||||
|
break;
|
||||||
|
case "downright":
|
||||||
|
cmdCode = 5;
|
||||||
|
break;
|
||||||
|
case "zoomin":
|
||||||
|
cmdCode = 16;
|
||||||
|
break;
|
||||||
|
case "zoomout":
|
||||||
|
cmdCode = 32;
|
||||||
|
break;
|
||||||
|
case "stop":
|
||||||
|
horizonSpeed = 0;
|
||||||
|
verticalSpeed = 0;
|
||||||
|
zoomSpeed = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frontEndCommand(channel, cmdCode, horizonSpeed, verticalSpeed, zoomSpeed);
|
||||||
|
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void iris(CommonGBChannel channel, String command, Integer speed) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
int cmdCode = 0x40;
|
||||||
|
switch (command){
|
||||||
|
case "in":
|
||||||
|
cmdCode = 0x44;
|
||||||
|
break;
|
||||||
|
case "out":
|
||||||
|
cmdCode = 0x48;
|
||||||
|
break;
|
||||||
|
case "stop":
|
||||||
|
speed = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frontEndCommand(channel, cmdCode, 0, speed, 0);
|
||||||
|
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focus(CommonGBChannel channel, String command, Integer speed) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
int cmdCode = 0x40;
|
||||||
|
switch (command){
|
||||||
|
case "near":
|
||||||
|
cmdCode = 0x42;
|
||||||
|
break;
|
||||||
|
case "far":
|
||||||
|
cmdCode = 0x41;
|
||||||
|
break;
|
||||||
|
case "stop":
|
||||||
|
speed = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frontEndCommand(channel, cmdCode, speed, 0, 0);
|
||||||
|
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void queryPreset(CommonGBChannel channel, ErrorCallback<List<Preset>> callback) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
|
||||||
|
Device device = deviceService.getDevice(channel.getDataDeviceId());
|
||||||
|
Assert.notNull(device, "设备不存在");
|
||||||
|
|
||||||
|
DeviceChannel deviceChannel = deviceChannelService.getOneForSourceById(channel.getGbId());
|
||||||
|
Assert.notNull(device, "原始通道不存在");
|
||||||
|
|
||||||
|
deviceService.queryPreset(device, deviceChannel.getDeviceId(), callback);
|
||||||
|
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addPreset(CommonGBChannel channel, Integer presetId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x81, 1, presetId, 0);
|
||||||
|
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void callPreset(CommonGBChannel channel, Integer presetId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x82, 1, presetId, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deletePreset(CommonGBChannel channel, Integer presetId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x83, 1, presetId, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addCruisePoint(CommonGBChannel channel, Integer cruiseId, Integer presetId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x84, cruiseId, presetId, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteCruisePoint(CommonGBChannel channel, Integer cruiseId, Integer presetId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x85, cruiseId, presetId, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCruiseSpeed(CommonGBChannel channel, Integer cruiseId, Integer speed) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
int parameter2 = speed & 0xFF;
|
||||||
|
int combindCode2 = speed >> 8;
|
||||||
|
frontEndCommand(channel, 0x86, cruiseId, parameter2, combindCode2);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCruiseTime(CommonGBChannel channel, Integer cruiseId, Integer time) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
int parameter2 = time & 0xFF;
|
||||||
|
int combindCode2 = time >> 8;
|
||||||
|
frontEndCommand(channel, 0x87, cruiseId, parameter2, combindCode2);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startCruise(CommonGBChannel channel, Integer cruiseId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x88, cruiseId, 0, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopCruise(CommonGBChannel channel, Integer cruiseId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0, 0, 0, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startScan(CommonGBChannel channel, Integer scanId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x89, scanId, 0, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopScan(CommonGBChannel channel, Integer scanId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0, 0, 0, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScanLeft(CommonGBChannel channel, Integer scanId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x89, scanId, 1, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScanRight(CommonGBChannel channel, Integer scanId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
frontEndCommand(channel, 0x89, scanId, 2, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScanSpeed(CommonGBChannel channel, Integer scanId, Integer speed) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
int parameter2 = speed & 0xFF;
|
||||||
|
int combindCode2 = speed >> 8;
|
||||||
|
frontEndCommand(channel, 0x8A, scanId, parameter2, combindCode2);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wiper(CommonGBChannel channel, String command) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
int cmdCode = 0;
|
||||||
|
switch (command){
|
||||||
|
case "on":
|
||||||
|
cmdCode = 0x8c;
|
||||||
|
break;
|
||||||
|
case "off":
|
||||||
|
cmdCode = 0x8d;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frontEndCommand(channel, cmdCode, 1, 0, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void auxiliarySwitch(CommonGBChannel channel, String command, Integer switchId) {
|
||||||
|
Assert.notNull(channel, "通道不存在");
|
||||||
|
if (channel.getDataType() == ChannelDataType.GB28181) {
|
||||||
|
// 国标通道
|
||||||
|
int cmdCode = 0;
|
||||||
|
switch (command){
|
||||||
|
case "on":
|
||||||
|
cmdCode = 0x8c;
|
||||||
|
break;
|
||||||
|
case "off":
|
||||||
|
cmdCode = 0x8d;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
frontEndCommand(channel, cmdCode, switchId, 0, 0);
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PROXY) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else if (channel.getDataType() == ChannelDataType.STREAM_PUSH) {
|
||||||
|
// 拉流代理
|
||||||
|
throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持此操作");
|
||||||
|
} else {
|
||||||
|
// 通道数据异常
|
||||||
|
log.error("[通用通道] 通道数据异常,无法识别通道来源: {}({})", channel.getGbName(), channel.getGbDeviceId());
|
||||||
|
throw new PlayException(Response.SERVER_INTERNAL_ERROR, "server internal error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,7 +12,6 @@ import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
|
|||||||
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IGbChannelService;
|
||||||
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
import com.genersoft.iot.vmp.gb28181.service.IPlatformChannelService;
|
||||||
import com.genersoft.iot.vmp.service.bean.ErrorCallback;
|
|
||||||
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
|
||||||
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
import com.genersoft.iot.vmp.streamPush.bean.StreamPush;
|
||||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||||
@ -26,7 +25,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import javax.sip.message.Response;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -788,4 +786,9 @@ public class GbChannelServiceImpl implements IGbChannelService {
|
|||||||
commonGBChannelMapper.updateGps(commonGBChannels);
|
commonGBChannelMapper.updateGps(commonGBChannels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CommonGBChannel> queryListForMap(String query, Boolean online, Boolean hasRecordPlan, Integer channelType) {
|
||||||
|
return commonGBChannelMapper.queryList(query, online, hasRecordPlan, channelType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"echarts": "^4.9.0",
|
"echarts": "^4.9.0",
|
||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
|
"gcoord": "^1.0.7",
|
||||||
"js-cookie": "2.2.0",
|
"js-cookie": "2.2.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"moment-duration-format": "^2.3.2",
|
"moment-duration-format": "^2.3.2",
|
||||||
|
|||||||
BIN
web/public/static/images/gis/camera1-red.png
Normal file
BIN
web/public/static/images/gis/camera1-red.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
@ -586,3 +586,15 @@ export function speedPlayback({ channelId, stream, speed}) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function getAllForMap({ query, online, hasRecordPlan, channelType }) {
|
||||||
|
return request({
|
||||||
|
method: 'get',
|
||||||
|
url: '/api/common/channel/map/list',
|
||||||
|
params: {
|
||||||
|
query: query,
|
||||||
|
online: online,
|
||||||
|
hasRecordPlan: hasRecordPlan,
|
||||||
|
channelType: channelType
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
1
web/src/icons/svg/map.svg
Normal file
1
web/src/icons/svg/map.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1749698203079" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11388" xmlns:xlink="http://www.w3.org/1999/xlink" ><path d="M219.322182 774.144a46.545455 46.545455 0 0 1 18.990545 60.276364l-1.698909 3.234909L196.584727 907.636364H844.8l-44.264727-67.584a46.545455 46.545455 0 0 1 75.659636-54.109091l2.210909 3.095272 44.288 67.584a93.090909 93.090909 0 0 1-73.239273 143.988364l-4.654545 0.116364H196.608a93.090909 93.090909 0 0 1-83.153455-134.958546l2.327273-4.352 40.029091-69.981091a46.545455 46.545455 0 0 1 63.511273-17.291636zM523.636364 46.545455C722.897455 46.545455 884.363636 208.709818 884.363636 408.622545c0 128.930909-102.679273 269.521455-303.127272 427.380364a93.137455 93.137455 0 0 1-115.316364-0.093091l-10.216727-8.098909C262.120727 673.326545 162.909091 535.365818 162.909091 408.622545 162.909091 208.709818 324.375273 46.545455 523.636364 46.545455z m0 93.090909C375.854545 139.636364 256 260.026182 256 408.622545c0 87.389091 78.196364 199.354182 238.778182 331.031273l18.874182 15.290182 9.984 7.912727 9.728-7.703272C706.839273 616.727273 791.272727 499.432727 791.272727 408.622545 791.272727 260.026182 671.418182 139.636364 523.636364 139.636364z m0 162.909091a104.727273 104.727273 0 1 1 0 209.454545 104.727273 104.727273 0 0 1 0-209.454545z" p-id="11389"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@ -85,6 +85,17 @@ export const constantRoutes = [
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/map',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/map',
|
||||||
|
children: [{
|
||||||
|
path: '',
|
||||||
|
name: 'Map',
|
||||||
|
component: () => import('@/views/map/index'),
|
||||||
|
meta: { title: '电子地图', icon: 'map' }
|
||||||
|
}]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/device',
|
path: '/device',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
|
|||||||
@ -48,7 +48,7 @@ import {
|
|||||||
stopPlayback,
|
stopPlayback,
|
||||||
pausePlayback,
|
pausePlayback,
|
||||||
resumePlayback,
|
resumePlayback,
|
||||||
seekPlayback, speedPlayback
|
seekPlayback, speedPlayback, getAllForMap
|
||||||
} from '@/api/commonChannel'
|
} from '@/api/commonChannel'
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
@ -561,6 +561,16 @@ const actions = {
|
|||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
getAllForMap({ commit }, params) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
getAllForMap(params).then(response => {
|
||||||
|
const { data } = response
|
||||||
|
resolve(data)
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,9 @@
|
|||||||
ref="regionTree"
|
ref="regionTree"
|
||||||
:edit="false"
|
:edit="false"
|
||||||
:show-header="false"
|
:show-header="false"
|
||||||
|
:show-position="showPosition"
|
||||||
:has-channel="true"
|
:has-channel="true"
|
||||||
|
:contextmenu="contextmenu"
|
||||||
@clickEvent="treeNodeClickEvent"
|
@clickEvent="treeNodeClickEvent"
|
||||||
:default-expanded-keys="[]"
|
:default-expanded-keys="[]"
|
||||||
/>
|
/>
|
||||||
@ -28,7 +30,9 @@
|
|||||||
ref="groupTree"
|
ref="groupTree"
|
||||||
:edit="false"
|
:edit="false"
|
||||||
:show-header="false"
|
:show-header="false"
|
||||||
|
:show-position="showPosition"
|
||||||
:has-channel="true"
|
:has-channel="true"
|
||||||
|
:contextmenu="contextmenu"
|
||||||
@clickEvent="treeNodeClickEvent"
|
@clickEvent="treeNodeClickEvent"
|
||||||
:default-expanded-keys="[]"
|
:default-expanded-keys="[]"
|
||||||
/>
|
/>
|
||||||
@ -56,6 +60,14 @@ export default {
|
|||||||
contextMenuEvent: {
|
contextMenuEvent: {
|
||||||
type: Function,
|
type: Function,
|
||||||
default: null
|
default: null
|
||||||
|
},
|
||||||
|
showPosition: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
contextmenu: {
|
||||||
|
type: Array,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -135,6 +147,14 @@ export default {
|
|||||||
if (data.leaf) {
|
if (data.leaf) {
|
||||||
this.$emit('clickEvent', data.id)
|
this.$emit('clickEvent', data.id)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
refresh: function(id) {
|
||||||
|
console.log(id)
|
||||||
|
if (this.showRegion) {
|
||||||
|
this.$refs.regionTree.refresh(id)
|
||||||
|
}else {
|
||||||
|
this.$refs.groupTree.refresh(id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,6 +65,7 @@
|
|||||||
style=" padding-left: 1px"
|
style=" padding-left: 1px"
|
||||||
:title="node.data.deviceId"
|
:title="node.data.deviceId"
|
||||||
>{{ node.label }}</span>
|
>{{ node.label }}</span>
|
||||||
|
<span v-if="node.data.longitude && showPosition" class="iconfont icon-gps"></span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</vue-easy-tree>
|
</vue-easy-tree>
|
||||||
@ -130,7 +131,7 @@ export default {
|
|||||||
GbChannelSelect,
|
GbChannelSelect,
|
||||||
VueEasyTree, groupEdit, gbDeviceSelect
|
VueEasyTree, groupEdit, gbDeviceSelect
|
||||||
},
|
},
|
||||||
props: ['edit', 'enableAddChannel', 'showHeader', 'hasChannel', 'addChannelToGroup', 'treeHeight'],
|
props: ['edit', 'enableAddChannel', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToGroup', 'treeHeight', 'showPosition', 'contextmenu'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
@ -231,90 +232,111 @@ export default {
|
|||||||
this.$forceUpdate()
|
this.$forceUpdate()
|
||||||
},
|
},
|
||||||
contextmenuEventHandler: function(event, data, node, element) {
|
contextmenuEventHandler: function(event, data, node, element) {
|
||||||
if (!this.edit) {
|
if (!this.edit && !this.contextmenu) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const allMenuItem = []
|
||||||
if (node.data.type === 0) {
|
if (node.data.type === 0) {
|
||||||
const menuItem = [
|
if (this.edit) {
|
||||||
{
|
const menuItem = [
|
||||||
label: '刷新节点',
|
{
|
||||||
icon: 'el-icon-refresh',
|
label: '刷新节点',
|
||||||
disabled: false,
|
icon: 'el-icon-refresh',
|
||||||
onClick: () => {
|
disabled: false,
|
||||||
this.refreshNode(node)
|
onClick: () => {
|
||||||
}
|
this.refreshNode(node)
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
label: '新建节点',
|
{
|
||||||
icon: 'el-icon-plus',
|
label: '新建节点',
|
||||||
disabled: false,
|
icon: 'el-icon-plus',
|
||||||
onClick: () => {
|
disabled: false,
|
||||||
this.addGroup(data.id, node)
|
onClick: () => {
|
||||||
}
|
this.addGroup(data.id, node)
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
label: '编辑节点',
|
{
|
||||||
icon: 'el-icon-edit',
|
label: '编辑节点',
|
||||||
disabled: node.level === 1,
|
icon: 'el-icon-edit',
|
||||||
onClick: () => {
|
disabled: node.level === 1,
|
||||||
this.editGroup(data, node)
|
onClick: () => {
|
||||||
}
|
this.editGroup(data, node)
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
label: '删除节点',
|
{
|
||||||
icon: 'el-icon-delete',
|
label: '删除节点',
|
||||||
disabled: node.level === 1,
|
icon: 'el-icon-delete',
|
||||||
divided: true,
|
disabled: node.level === 1,
|
||||||
onClick: () => {
|
divided: true,
|
||||||
this.$confirm('确定删除?', '提示', {
|
onClick: () => {
|
||||||
confirmButtonText: '确定',
|
this.$confirm('确定删除?', '提示', {
|
||||||
cancelButtonText: '取消',
|
confirmButtonText: '确定',
|
||||||
type: 'warning'
|
cancelButtonText: '取消',
|
||||||
}).then(() => {
|
type: 'warning'
|
||||||
this.removeGroup(data.id, node)
|
}).then(() => {
|
||||||
}).catch(() => {
|
this.removeGroup(data.id, node)
|
||||||
|
}).catch(() => {
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
if (this.enableAddChannel) {
|
||||||
|
menuItem.push(
|
||||||
|
{
|
||||||
|
label: '添加设备',
|
||||||
|
icon: 'el-icon-plus',
|
||||||
|
disabled: node.level <= 2,
|
||||||
|
onClick: () => {
|
||||||
|
this.addChannelFormDevice(data.id, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
menuItem.push(
|
||||||
|
{
|
||||||
|
label: '移除设备',
|
||||||
|
icon: 'el-icon-delete',
|
||||||
|
disabled: node.level <= 2,
|
||||||
|
divided: true,
|
||||||
|
onClick: () => {
|
||||||
|
this.removeChannelFormDevice(data.id, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
menuItem.push(
|
||||||
|
{
|
||||||
|
label: '添加通道',
|
||||||
|
icon: 'el-icon-plus',
|
||||||
|
disabled: node.level <= 2,
|
||||||
|
onClick: () => {
|
||||||
|
this.addChannel(data.id, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
allMenuItem.push(...menuItem)
|
||||||
|
}
|
||||||
|
if (this.contextmenu) {
|
||||||
|
for (let i = 0; i < this.contextmenu.length; i++) {
|
||||||
|
let item = this.contextmenu[i]
|
||||||
|
if (item.type === node.data.type) {
|
||||||
|
allMenuItem.push({
|
||||||
|
label: item.label,
|
||||||
|
icon: item.icon,
|
||||||
|
onClick: () => {
|
||||||
|
item.onClick(event, data, node)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
|
if (allMenuItem.length === 0) {
|
||||||
if (this.enableAddChannel) {
|
return
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: '添加设备',
|
|
||||||
icon: 'el-icon-plus',
|
|
||||||
disabled: node.level <= 2,
|
|
||||||
onClick: () => {
|
|
||||||
this.addChannelFormDevice(data.id, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: '移除设备',
|
|
||||||
icon: 'el-icon-delete',
|
|
||||||
disabled: node.level <= 2,
|
|
||||||
divided: true,
|
|
||||||
onClick: () => {
|
|
||||||
this.removeChannelFormDevice(data.id, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
menuItem.push(
|
|
||||||
{
|
|
||||||
label: '添加通道',
|
|
||||||
icon: 'el-icon-plus',
|
|
||||||
disabled: node.level <= 2,
|
|
||||||
onClick: () => {
|
|
||||||
this.addChannel(data.id, node)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$contextmenu({
|
this.$contextmenu({
|
||||||
items: menuItem,
|
items: allMenuItem,
|
||||||
event, // 鼠标事件信息
|
event, // 鼠标事件信息
|
||||||
customClass: 'custom-class', // 自定义菜单 class
|
customClass: 'custom-class', // 自定义菜单 class
|
||||||
zIndex: 3000 // 菜单样式 z-index
|
zIndex: 3000 // 菜单样式 z-index
|
||||||
|
|||||||
@ -17,11 +17,16 @@ import View from 'ol/View'
|
|||||||
import Feature from 'ol/Feature'
|
import Feature from 'ol/Feature'
|
||||||
import Overlay from 'ol/Overlay'
|
import Overlay from 'ol/Overlay'
|
||||||
import { Point, LineString } from 'ol/geom'
|
import { Point, LineString } from 'ol/geom'
|
||||||
import { get as getProj, fromLonLat } from 'ol/proj'
|
import { get as getProj } from 'ol/proj'
|
||||||
import { ZoomSlider, Zoom } from 'ol/control'
|
|
||||||
import { containsCoordinate } from 'ol/extent'
|
import { containsCoordinate } from 'ol/extent'
|
||||||
|
import {
|
||||||
|
defaults as defaultInteractions
|
||||||
|
} from 'ol/interaction'
|
||||||
|
import DragInteraction from './map/DragInteraction'
|
||||||
|
import { fromLonLat, toLonLat } from './map/TransformLonLat'
|
||||||
|
|
||||||
import { v4 } from 'uuid'
|
import { v4 } from 'uuid'
|
||||||
|
import { getUid } from 'ol'
|
||||||
|
|
||||||
let olMap = null
|
let olMap = null
|
||||||
|
|
||||||
@ -30,7 +35,8 @@ export default {
|
|||||||
props: [],
|
props: [],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
overlayId: null,
|
||||||
|
dragInteraction: new DragInteraction()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -44,34 +50,28 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
destroyed() {
|
destroyed() {
|
||||||
// if (this.jessibuca) {
|
|
||||||
// this.jessibuca.destroy();
|
|
||||||
// }
|
|
||||||
// this.playing = false;
|
|
||||||
// this.loaded = false;
|
|
||||||
// this.performance = "";
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init() {
|
init() {
|
||||||
let center = fromLonLat([116.41020, 39.915119])
|
let center = fromLonLat([116.41020, 39.915119])
|
||||||
if (mapParam.center) {
|
if (window.mapParam.center) {
|
||||||
center = fromLonLat(mapParam.center)
|
center = fromLonLat(window.mapParam.center)
|
||||||
}
|
}
|
||||||
const view = new View({
|
const view = new View({
|
||||||
center: center,
|
center: center,
|
||||||
zoom: mapParam.zoom || 10,
|
zoom: window.mapParam.zoom || 10,
|
||||||
projection: this.projection,
|
projection: this.projection,
|
||||||
maxZoom: mapParam.maxZoom || 19,
|
maxZoom: window.mapParam.maxZoom || 19,
|
||||||
minZoom: mapParam.minZoom || 1
|
minZoom: window.mapParam.minZoom || 1
|
||||||
})
|
})
|
||||||
let tileLayer = null
|
let tileLayer = null
|
||||||
if (mapParam.tilesUrl) {
|
if (window.mapParam.tilesUrl) {
|
||||||
tileLayer = new Tile({
|
tileLayer = new Tile({
|
||||||
source: new XYZ({
|
source: new XYZ({
|
||||||
projection: getProj('EPSG:3857'),
|
projection: getProj('EPSG:3857'),
|
||||||
wrapX: false,
|
wrapX: false,
|
||||||
tileSize: 256 || mapParam.tileSize,
|
tileSize: 256 || window.mapParam.tileSize,
|
||||||
url: mapParam.tilesUrl
|
url: window.mapParam.tilesUrl
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -81,18 +81,48 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
olMap = new Map({
|
olMap = new Map({
|
||||||
|
interactions: defaultInteractions().extend([this.dragInteraction]),
|
||||||
target: this.$refs.mapContainer, // 容器ID
|
target: this.$refs.mapContainer, // 容器ID
|
||||||
layers: [tileLayer], // 默认图层
|
layers: [tileLayer], // 默认图层
|
||||||
view: view, // 视图
|
view: view, // 视图
|
||||||
controls: [ // 控件
|
controls: [ // 控件
|
||||||
// new ZoomSlider(),
|
|
||||||
new Zoom()
|
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
console.log(3222)
|
olMap.once('loadend', event => {
|
||||||
|
this.$emit('loaded')
|
||||||
|
})
|
||||||
|
olMap.on('click', event => {
|
||||||
|
let features = {}
|
||||||
|
let layers = {}
|
||||||
|
// 单个元素事件传递
|
||||||
|
olMap.forEachFeatureAtPixel(event.pixel, (featureAtPixel, layerAtPixel) => {
|
||||||
|
|
||||||
|
if (layerAtPixel) {
|
||||||
|
let ol_uid = 'key' + getUid(layerAtPixel)
|
||||||
|
layers[ol_uid] = layerAtPixel
|
||||||
|
if (Object.hasOwn(features, ol_uid)) {
|
||||||
|
features[ol_uid].push(featureAtPixel)
|
||||||
|
} else {
|
||||||
|
features[ol_uid] = new Array(featureAtPixel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 遍历图层,传递事件
|
||||||
|
for (const key in layers) {
|
||||||
|
if (Object.hasOwn(layers, key)) {
|
||||||
|
var layer = layers[key]
|
||||||
|
layer.dispatchEvent({ type: 'click', event: event, features: features[key], outParam: { layersCount: Object.keys(layers).length } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
features = {}
|
||||||
|
layer = {}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
setCenter(point) {
|
setCenter(point) {
|
||||||
|
|
||||||
|
},
|
||||||
|
getCenter() {
|
||||||
|
return toLonLat(olMap.getView().getCenter())
|
||||||
},
|
},
|
||||||
zoomIn(zoom) {
|
zoomIn(zoom) {
|
||||||
|
|
||||||
@ -110,23 +140,33 @@ export default {
|
|||||||
duration: duration
|
duration: duration
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
panTo(point, zoom) {
|
coordinateInView: function(point) {
|
||||||
const duration = 800
|
return containsCoordinate(olMap.getView().calculateExtent(), fromLonLat(point))
|
||||||
|
},
|
||||||
|
panTo(point, zoom, endCallback) {
|
||||||
|
const duration = 1500
|
||||||
|
var coordinate = fromLonLat(point)
|
||||||
|
if (containsCoordinate(olMap.getView().calculateExtent(), coordinate)) {
|
||||||
|
olMap.getView().setCenter(coordinate)
|
||||||
|
if (endCallback) {
|
||||||
|
endCallback()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
olMap.getView().cancelAnimations()
|
olMap.getView().cancelAnimations()
|
||||||
olMap.getView().animate({
|
olMap.getView().animate({
|
||||||
center: fromLonLat(point),
|
center: coordinate,
|
||||||
duration: duration
|
duration: duration
|
||||||
})
|
})
|
||||||
if (!containsCoordinate(olMap.getView().calculateExtent(), fromLonLat(point))) {
|
olMap.getView().animate({
|
||||||
olMap.getView().animate({
|
zoom: 12,
|
||||||
zoom: olMap.getView().getZoom() - 1,
|
duration: duration / 2
|
||||||
duration: duration / 2
|
}, {
|
||||||
}, {
|
zoom: zoom || olMap.getView().getZoom(),
|
||||||
zoom: zoom || olMap.getView().getZoom(),
|
duration: duration / 2
|
||||||
duration: duration / 2
|
})
|
||||||
})
|
setTimeout(endCallback, duration + 100)
|
||||||
}
|
|
||||||
},
|
},
|
||||||
fit(layer) {
|
fit(layer) {
|
||||||
const extent = layer.getSource().getExtent()
|
const extent = layer.getSource().getExtent()
|
||||||
@ -138,10 +178,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
openInfoBox(position, content, offset) {
|
openInfoBox(position, content, offset) {
|
||||||
|
if (this.overlayId !== null) {
|
||||||
|
console.log(this.overlayId)
|
||||||
|
this.closeInfoBox(this.overlayId)
|
||||||
|
this.overlayId = null
|
||||||
|
}
|
||||||
const id = v4()
|
const id = v4()
|
||||||
// let infoBox = document.createElement("div");
|
// let infoBox = document.createElement('div')
|
||||||
// infoBox.innerHTML = content ;
|
// infoBox.setAttribute('id', id)
|
||||||
// infoBox.setAttribute("infoBoxId", id)
|
// infoBox.innerHTML = content
|
||||||
const overlay = new Overlay({
|
const overlay = new Overlay({
|
||||||
id: id,
|
id: id,
|
||||||
autoPan: true,
|
autoPan: true,
|
||||||
@ -150,16 +195,23 @@ export default {
|
|||||||
},
|
},
|
||||||
element: content,
|
element: content,
|
||||||
positioning: 'bottom-center',
|
positioning: 'bottom-center',
|
||||||
offset: offset
|
offset: offset,
|
||||||
|
position: fromLonLat(position)
|
||||||
// className:overlayStyle.className
|
// className:overlayStyle.className
|
||||||
})
|
})
|
||||||
olMap.addOverlay(overlay)
|
olMap.addOverlay(overlay)
|
||||||
overlay.setPosition(fromLonLat(position))
|
this.overlayId = id
|
||||||
return id
|
return id
|
||||||
},
|
},
|
||||||
closeInfoBox(id) {
|
closeInfoBox(id) {
|
||||||
olMap.getOverlayById(id).setPosition(undefined)
|
let overlay = olMap.getOverlayById(id)
|
||||||
// olMap.removeOverlay(olMap.getOverlayById(id))
|
if (overlay) {
|
||||||
|
olMap.removeOverlay(overlay)
|
||||||
|
}
|
||||||
|
var element = document.getElementById(id)
|
||||||
|
if (element) {
|
||||||
|
element.remove()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* 添加图层
|
* 添加图层
|
||||||
@ -178,13 +230,13 @@ export default {
|
|||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
addLayer(data, clickEvent) {
|
addLayer(data, clickEvent) {
|
||||||
const style = new Style()
|
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
const features = []
|
const features = []
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
const feature = new Feature(new Point(fromLonLat(data[i].position)))
|
const feature = new Feature(new Point(fromLonLat(data[i].position)))
|
||||||
|
feature.setId(data[i].id)
|
||||||
feature.customData = data[i].data
|
feature.customData = data[i].data
|
||||||
const cloneStyle = style.clone()
|
const cloneStyle = new Style()
|
||||||
cloneStyle.setImage(new Icon({
|
cloneStyle.setImage(new Icon({
|
||||||
anchor: data[i].image.anchor,
|
anchor: data[i].image.anchor,
|
||||||
crossOrigin: 'Anonymous',
|
crossOrigin: 'Anonymous',
|
||||||
@ -197,31 +249,88 @@ export default {
|
|||||||
source.addFeatures(features)
|
source.addFeatures(features)
|
||||||
const vectorLayer = new VectorLayer({
|
const vectorLayer = new VectorLayer({
|
||||||
source: source,
|
source: source,
|
||||||
style: style,
|
|
||||||
renderMode: 'image',
|
renderMode: 'image',
|
||||||
declutter: false
|
declutter: false
|
||||||
})
|
})
|
||||||
olMap.addLayer(vectorLayer)
|
olMap.addLayer(vectorLayer)
|
||||||
if (typeof clickEvent === 'function') {
|
if (typeof clickEvent === 'function') {
|
||||||
olMap.on('click', (event) => {
|
vectorLayer.on('click', (event) => {
|
||||||
vectorLayer.getFeatures(event.pixel).then((features) => {
|
|
||||||
if (features.length > 0) {
|
if (event.features.length > 0) {
|
||||||
const items = []
|
const items = []
|
||||||
for (let i = 0; i < features.length; i++) {
|
for (let i = 0; i < event.features.length; i++) {
|
||||||
items.push(features[i].customData)
|
items.push(event.features[i].customData)
|
||||||
}
|
|
||||||
clickEvent(items)
|
|
||||||
}
|
}
|
||||||
})
|
clickEvent(items)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return vectorLayer
|
return vectorLayer
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateLayer(layer, data, postponement) {
|
||||||
|
console.log(layer)
|
||||||
|
layer.getSource().clear(true)
|
||||||
|
const features = []
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
const feature = new Feature(new Point(fromLonLat(data[i].position)))
|
||||||
|
feature.setId(data[i].id)
|
||||||
|
feature.customData = data[i].data
|
||||||
|
const cloneStyle = new Style()
|
||||||
|
cloneStyle.setImage(new Icon({
|
||||||
|
anchor: data[i].image.anchor,
|
||||||
|
crossOrigin: 'Anonymous',
|
||||||
|
src: data[i].image.src
|
||||||
|
}))
|
||||||
|
feature.setStyle(cloneStyle)
|
||||||
|
features.push(feature)
|
||||||
|
}
|
||||||
|
layer.getSource().addFeatures(features)
|
||||||
|
if (postponement) {
|
||||||
|
olMap.removeLayer(layer)
|
||||||
|
setTimeout(() => {
|
||||||
|
olMap.addLayer(layer)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
return layer
|
||||||
|
},
|
||||||
removeLayer(layer) {
|
removeLayer(layer) {
|
||||||
olMap.removeLayer(layer)
|
olMap.removeLayer(layer)
|
||||||
},
|
},
|
||||||
|
setFeatureImageById(layer, featureId, image) {
|
||||||
|
let feature = layer.getSource().getFeatureById(featureId)
|
||||||
|
if (!feature) {
|
||||||
|
console.error('更改feature的图标时未找到图标')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let style = feature.getStyle()
|
||||||
|
style.setImage(new Icon({
|
||||||
|
anchor: image.anchor,
|
||||||
|
crossOrigin: 'Anonymous',
|
||||||
|
src: image.src
|
||||||
|
}))
|
||||||
|
feature.setStyle(style)
|
||||||
|
olMap.render()
|
||||||
|
},
|
||||||
|
setFeaturePositionById(layer, featureId, data) {
|
||||||
|
let featureOld = layer.getSource().getFeatureById(featureId)
|
||||||
|
if (featureOld) {
|
||||||
|
layer.getSource().removeFeature(featureOld)
|
||||||
|
}
|
||||||
|
|
||||||
|
const feature = new Feature(new Point(fromLonLat(data.position)))
|
||||||
|
feature.setId(data.id)
|
||||||
|
feature.customData = data.data
|
||||||
|
const style = new Style()
|
||||||
|
style.setImage(new Icon({
|
||||||
|
anchor: data.image.anchor,
|
||||||
|
crossOrigin: 'Anonymous',
|
||||||
|
src: data.image.src
|
||||||
|
}))
|
||||||
|
feature.setStyle(style)
|
||||||
|
layer.getSource().addFeature(feature)
|
||||||
|
},
|
||||||
|
|
||||||
addLineLayer(positions) {
|
addLineLayer(positions) {
|
||||||
if (positions.length > 0) {
|
if (positions.length > 0) {
|
||||||
|
|||||||
@ -56,15 +56,11 @@
|
|||||||
class="iconfont icon-shexiangtou2"
|
class="iconfont icon-shexiangtou2"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
v-if="node.data.deviceId !=='' && showCode"
|
|
||||||
style=" padding-left: 1px"
|
|
||||||
:title="node.data.deviceId"
|
|
||||||
>{{ node.label }}(编号:{{ node.data.deviceId }})</span>
|
|
||||||
<span
|
|
||||||
v-if="node.data.deviceId ==='' || !showCode"
|
|
||||||
style=" padding-left: 1px"
|
style=" padding-left: 1px"
|
||||||
:title="node.data.deviceId"
|
:title="node.data.deviceId"
|
||||||
>{{ node.label }}</span>
|
>{{ node.label }}</span>
|
||||||
|
<span v-if="node.data.deviceId !=='' && showCode">(编号:{{ node.data.deviceId }})</span>
|
||||||
|
<span v-if="node.data.longitude && showPosition" class="iconfont icon-gps"></span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</vue-easy-tree>
|
</vue-easy-tree>
|
||||||
@ -131,7 +127,7 @@ export default {
|
|||||||
GbChannelSelect,
|
GbChannelSelect,
|
||||||
VueEasyTree, regionEdit, gbDeviceSelect
|
VueEasyTree, regionEdit, gbDeviceSelect
|
||||||
},
|
},
|
||||||
props: ['edit', 'enableAddChannel', 'showHeader', 'hasChannel', 'addChannelToCivilCode', 'treeHeight'],
|
props: ['edit', 'enableAddChannel', 'onChannelChange', 'showHeader', 'hasChannel', 'addChannelToCivilCode', 'treeHeight', 'showPosition', 'contextmenu'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
@ -236,95 +232,115 @@ export default {
|
|||||||
this.$forceUpdate()
|
this.$forceUpdate()
|
||||||
},
|
},
|
||||||
contextmenuEventHandler: function(event, data, node, element) {
|
contextmenuEventHandler: function(event, data, node, element) {
|
||||||
if (!this.edit) {
|
if (!this.edit && !this.contextmenu) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const allMenuItem = []
|
||||||
if (node.data.type === 0) {
|
if (node.data.type === 0) {
|
||||||
const menuItem = [
|
if (this.edit) {
|
||||||
{
|
|
||||||
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(() => {
|
|
||||||
|
|
||||||
})
|
const menuItem = [
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
if (this.enableAddChannel) {
|
|
||||||
menuItem.push(
|
|
||||||
{
|
{
|
||||||
label: '添加设备',
|
label: '刷新节点',
|
||||||
|
icon: 'el-icon-refresh',
|
||||||
|
disabled: false,
|
||||||
|
onClick: () => {
|
||||||
|
this.refreshNode(node)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '新建节点',
|
||||||
icon: 'el-icon-plus',
|
icon: 'el-icon-plus',
|
||||||
|
disabled: false,
|
||||||
|
onClick: () => {
|
||||||
|
this.addRegion(data.id, node)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '编辑节点',
|
||||||
|
icon: 'el-icon-edit',
|
||||||
disabled: node.level === 1,
|
disabled: node.level === 1,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
this.addChannelFormDevice(data.id, node)
|
this.editCatalog(data, node)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
|
||||||
menuItem.push(
|
|
||||||
{
|
{
|
||||||
label: '移除设备',
|
label: '删除节点',
|
||||||
icon: 'el-icon-delete',
|
icon: 'el-icon-delete',
|
||||||
disabled: node.level === 1,
|
disabled: node.level === 1,
|
||||||
divided: true,
|
divided: true,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
this.removeChannelFormDevice(data.id, node)
|
this.$confirm('确定删除?', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
this.removeRegion(data.id, node)
|
||||||
|
}).catch(() => {
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
]
|
||||||
menuItem.push(
|
if (this.enableAddChannel) {
|
||||||
{
|
menuItem.push(
|
||||||
label: '添加通道',
|
{
|
||||||
icon: 'el-icon-plus',
|
label: '添加设备',
|
||||||
disabled: node.level === 1,
|
icon: 'el-icon-plus',
|
||||||
onClick: () => {
|
disabled: node.level === 1,
|
||||||
this.addChannel(data.id, node)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
menuItem.push(
|
||||||
|
{
|
||||||
|
label: '添加通道',
|
||||||
|
icon: 'el-icon-plus',
|
||||||
|
disabled: node.level === 1,
|
||||||
|
onClick: () => {
|
||||||
|
this.addChannel(data.id, node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
allMenuItem.push(...menuItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$contextmenu({
|
|
||||||
items: menuItem,
|
|
||||||
event, // 鼠标事件信息
|
|
||||||
customClass: 'custom-class', // 自定义菜单 class
|
|
||||||
zIndex: 3000 // 菜单样式 z-index
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
if (this.contextmenu) {
|
||||||
|
for (let i = 0; i < this.contextmenu.length; i++) {
|
||||||
|
let item = this.contextmenu[i]
|
||||||
|
if (item.type === node.data.type) {
|
||||||
|
allMenuItem.push({
|
||||||
|
label: item.label,
|
||||||
|
icon: item.icon,
|
||||||
|
onClick: () => {
|
||||||
|
item.onClick(event, data, node)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allMenuItem.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$contextmenu({
|
||||||
|
items: allMenuItem,
|
||||||
|
event, // 鼠标事件信息
|
||||||
|
customClass: 'custom-class', // 自定义菜单 class
|
||||||
|
zIndex: 3000 // 菜单样式 z-index
|
||||||
|
})
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
removeRegion: function(id, node) {
|
removeRegion: function(id, node) {
|
||||||
@ -396,12 +412,16 @@ export default {
|
|||||||
node.expand()
|
node.expand()
|
||||||
},
|
},
|
||||||
refresh: function(id) {
|
refresh: function(id) {
|
||||||
console.log(id)
|
|
||||||
// 查询node
|
// 查询node
|
||||||
const node = this.$refs.veTree.getNode(id)
|
const node = this.$refs.veTree.getNode(id)
|
||||||
if (node) {
|
if (node) {
|
||||||
node.loaded = false
|
if (id.includes('channel') >= 0) {
|
||||||
node.expand()
|
node.parent.loaded = false
|
||||||
|
node.parent.expand()
|
||||||
|
}else {
|
||||||
|
node.loaded = false
|
||||||
|
node.expand()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addRegion: function(id, node) {
|
addRegion: function(id, node) {
|
||||||
|
|||||||
116
web/src/views/common/map/DragInteraction.js
Normal file
116
web/src/views/common/map/DragInteraction.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import PointerInteraction from 'ol/interaction/Pointer'
|
||||||
|
import { toLonLat } from './TransformLonLat'
|
||||||
|
|
||||||
|
class DragInteraction extends PointerInteraction {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
handleDownEvent: (evt) => {
|
||||||
|
const map = evt.map
|
||||||
|
|
||||||
|
const feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => {
|
||||||
|
if (this.featureIdMap_.has(feature.getId())) {
|
||||||
|
return feature
|
||||||
|
}else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (feature) {
|
||||||
|
this.coordinate_ = evt.coordinate
|
||||||
|
this.feature_ = feature
|
||||||
|
let eventCallback = this.featureIdMap_.get(this.feature_.getId())
|
||||||
|
if (eventCallback && eventCallback.startEvent) {
|
||||||
|
eventCallback.startEvent(evt)
|
||||||
|
}
|
||||||
|
return !!feature
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleDragEvent: (evt) => {
|
||||||
|
const deltaX = evt.coordinate[0] - this.coordinate_[0]
|
||||||
|
const deltaY = evt.coordinate[1] - this.coordinate_[1]
|
||||||
|
|
||||||
|
const geometry = this.feature_.getGeometry()
|
||||||
|
geometry.translate(deltaX, deltaY)
|
||||||
|
|
||||||
|
this.coordinate_[0] = evt.coordinate[0]
|
||||||
|
this.coordinate_[1] = evt.coordinate[1]
|
||||||
|
|
||||||
|
let eventCallback = this.featureIdMap_.get(this.feature_.getId())
|
||||||
|
if (eventCallback && eventCallback.moveEvent) {
|
||||||
|
eventCallback.moveEvent(evt)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
handleMoveEvent: (evt) => {
|
||||||
|
if (this.cursor_) {
|
||||||
|
const map = evt.map
|
||||||
|
const feature = map.forEachFeatureAtPixel(evt.pixel, function(feature) {
|
||||||
|
return feature
|
||||||
|
})
|
||||||
|
const element = evt.map.getTargetElement()
|
||||||
|
if (feature) {
|
||||||
|
if (element.style.cursor != this.cursor_) {
|
||||||
|
this.previousCursor_ = element.style.cursor
|
||||||
|
element.style.cursor = this.cursor_
|
||||||
|
}
|
||||||
|
} else if (this.previousCursor_ !== undefined) {
|
||||||
|
element.style.cursor = this.previousCursor_
|
||||||
|
this.previousCursor_ = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleUpEvent: (evt) => {
|
||||||
|
let eventCallback = this.featureIdMap_.get(this.feature_.getId())
|
||||||
|
if (eventCallback && eventCallback.endEvent) {
|
||||||
|
evt.lonLat = toLonLat(this.feature_.getGeometry().getCoordinates())
|
||||||
|
eventCallback.endEvent(evt)
|
||||||
|
}
|
||||||
|
this.coordinate_ = null
|
||||||
|
this.feature_ = null
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import('../src/ol/coordinate.js').Coordinate}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.coordinate_ = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.cursor_ = 'pointer'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Feature}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.feature_ = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {string|undefined}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.previousCursor_ = undefined
|
||||||
|
|
||||||
|
this.featureIdMap_ = new Map()
|
||||||
|
|
||||||
|
this.addFeatureId = (id, moveEndEvent) => {
|
||||||
|
if (this.featureIdMap_.has(id)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.featureIdMap_.set(id, moveEndEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeFeatureId= (id) => {
|
||||||
|
this.featureIdMap_.delete(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasFeatureId= (id) => {
|
||||||
|
this.featureIdMap_.has(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DragInteraction
|
||||||
9
web/src/views/common/map/TransformLonLat.js
Normal file
9
web/src/views/common/map/TransformLonLat.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { fromLonLat as projFromLonLat, toLonLat as projToLonLat } from 'ol/proj'
|
||||||
|
import gcoord from 'gcoord'
|
||||||
|
|
||||||
|
export function fromLonLat(coordinate) {
|
||||||
|
return projFromLonLat(gcoord.transform(coordinate, gcoord.WGS84, gcoord.GCJ02))
|
||||||
|
}
|
||||||
|
export function toLonLat(coordinate) {
|
||||||
|
return gcoord.transform(projToLonLat(coordinate), gcoord.GCJ02, gcoord.WGS84)
|
||||||
|
}
|
||||||
433
web/src/views/map/index.vue
Executable file
433
web/src/views/map/index.vue
Executable file
@ -0,0 +1,433 @@
|
|||||||
|
<template>
|
||||||
|
<div id="devicePosition" style="height: calc(100vh - 84px);width: 100%;">
|
||||||
|
<div style="height: 100%; display: grid; grid-template-columns: 360px auto">
|
||||||
|
<DeviceTree ref="deviceTree" @clickEvent="treeChannelClickEvent" :showPosition="true" :contextmenu="getContextmenu()"/>
|
||||||
|
<MapComponent ref="mapComponent" @loaded="initChannelLayer"></MapComponent>
|
||||||
|
</div>
|
||||||
|
<div class="map-tool-box">
|
||||||
|
<div class="map-tool-btn-group">
|
||||||
|
<div class="map-tool-btn" @click="initChannelLayer">
|
||||||
|
<i class="iconfont icon-shuaxin3"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="map-tool-btn-group">
|
||||||
|
<div class="map-tool-btn">
|
||||||
|
<i class="iconfont icon-plus1"></i>
|
||||||
|
</div>
|
||||||
|
<div class="map-tool-btn">
|
||||||
|
<i class="iconfont icon-minus1"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div ref="infobox">
|
||||||
|
<transition name="el-zoom-in-center">
|
||||||
|
<div class="infobox-content" v-if="channel">
|
||||||
|
<el-descriptions class="margin-top" :title="channel.gbName" :column="1" :colon="true" size="mini" :labelStyle="labelStyle" >
|
||||||
|
<el-descriptions-item label="编号" >{{channel.gbDeviceId}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="生产厂商">{{channel.gbManufacture}}</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="安装地址" >{{channel.gbAddress == null?'未知': channel.gbAddress}}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
<div style="padding-top: 10px; margin: 0 auto; width: fit-content;">
|
||||||
|
<el-button v-bind:disabled="channel.gbStatus !== 'ON'" type="primary" size="small" title="播放" icon="el-icon-video-play" @click="play(channel)">播放</el-button>
|
||||||
|
<el-button type="primary" size="small" title="编辑位置" icon="el-icon-edit" @click="edit(channel)">编辑</el-button>
|
||||||
|
<!-- <el-button type="primary" size="small" title="轨迹查询" icon="el-icon-map-location" @click="getTrace(channel)">轨迹</el-button>-->
|
||||||
|
</div>
|
||||||
|
<span class="infobox-close el-icon-close" @click="closeInfoBox"></span>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ref="infoboxForEdit">
|
||||||
|
<transition name="el-zoom-in-center">
|
||||||
|
<div class="infobox-edit-content" v-if="dragChannel">
|
||||||
|
<div style="width: 100%; height: 2rem; line-height: 1.5rem; font-size: 14px">{{dragChannel.gbName}} ({{dragChannel.gbDeviceId}})</div>
|
||||||
|
<span style="font-size: 14px">经度:</span> <el-input v-model="dragChannel.gbLongitude" placeholder="请输入经度" style="width: 7rem; margin-right: 10px"></el-input>
|
||||||
|
<span style="font-size: 14px">纬度: </span> <el-input v-model="dragChannel.gbLatitude" placeholder="请输入纬度" style="width: 7rem; "></el-input>
|
||||||
|
<el-button icon="el-icon-close" size="medium" type="text" @click="cancelEdit(dragChannel)" style="margin-left: 1rem; font-size: 18px; color: #2b2f3a"></el-button>
|
||||||
|
<el-button icon="el-icon-check" size="medium" type="text" @click="submitEdit(dragChannel)" style="font-size: 18px; color: #0842e2"></el-button>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
<devicePlayer ref="devicePlayer" ></devicePlayer>
|
||||||
|
<queryTrace ref="queryTrace" ></queryTrace>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import DeviceTree from '../common/DeviceTree.vue'
|
||||||
|
import queryTrace from './queryTrace.vue'
|
||||||
|
import MapComponent from '../common/MapComponent.vue'
|
||||||
|
import devicePlayer from '../common/channelPlayer/index.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Map',
|
||||||
|
components: {
|
||||||
|
DeviceTree,
|
||||||
|
devicePlayer,
|
||||||
|
queryTrace,
|
||||||
|
MapComponent
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
layer: null,
|
||||||
|
channel: null,
|
||||||
|
dragChannel: {},
|
||||||
|
feature: null,
|
||||||
|
device: null,
|
||||||
|
infoBoxId: null,
|
||||||
|
channelLayer: null,
|
||||||
|
labelStyle: {
|
||||||
|
width: '56px'
|
||||||
|
},
|
||||||
|
isLoging: false,
|
||||||
|
longitudeStr: 'longitude',
|
||||||
|
latitudeStr: 'latitude'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
treeChannelClickEvent: function (id) {
|
||||||
|
this.closeInfoBox()
|
||||||
|
this.$store.dispatch('commonChanel/queryOne', id)
|
||||||
|
.then(data => {
|
||||||
|
if (!data.gbLongitude || data.gbLongitude < 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.$refs.mapComponent.coordinateInView([data.gbLongitude, data.gbLatitude])) {
|
||||||
|
this.showChannelInfo(data)
|
||||||
|
}else {
|
||||||
|
this.$refs.mapComponent.panTo([data.gbLongitude, data.gbLatitude], 16, () => {
|
||||||
|
this.showChannelInfo(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getContextmenu: function (event) {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
label: '播放通道',
|
||||||
|
icon: 'el-icon-video-play',
|
||||||
|
type: 1,
|
||||||
|
onClick: (event, data, node) => {
|
||||||
|
this.$store.dispatch('commonChanel/queryOne', data.id)
|
||||||
|
.then(data => {
|
||||||
|
this.play(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '编辑位置',
|
||||||
|
icon: 'el-icon-edit',
|
||||||
|
type: 1,
|
||||||
|
onClick: (event, data, node) => {
|
||||||
|
this.$store.dispatch('commonChanel/queryOne', data.id)
|
||||||
|
.then(data => {
|
||||||
|
this.edit(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ,
|
||||||
|
// {
|
||||||
|
// label: '轨迹查询',
|
||||||
|
// icon: 'el-icon-map-location',
|
||||||
|
// type: 1,
|
||||||
|
// onClick: (event, data, node) => {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
showChannelInfo: function(data) {
|
||||||
|
this.channel = data
|
||||||
|
this.infoBoxId = this.$refs.mapComponent.openInfoBox([data.gbLongitude, data.gbLatitude], this.$refs.infobox, [0, -50])
|
||||||
|
},
|
||||||
|
|
||||||
|
initChannelLayer: function () {
|
||||||
|
// 获取所有有位置的通道
|
||||||
|
this.closeInfoBox()
|
||||||
|
this.$store.dispatch('commonChanel/getAllForMap', {
|
||||||
|
geoCoordSys: window.mapParam.coordinateSystem
|
||||||
|
}).then(data => {
|
||||||
|
let array = []
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
let item = data[i]
|
||||||
|
if (item.gbLongitude && item.gbLatitude) {
|
||||||
|
array.push({
|
||||||
|
id: item.gbId,
|
||||||
|
position: [item.gbLongitude, item.gbLatitude],
|
||||||
|
data: item,
|
||||||
|
image: {
|
||||||
|
anchor: [0.5, 1],
|
||||||
|
src: this.getImageByChannel(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.updateChannelLayer(array)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
updateChannelLayer: function(array) {
|
||||||
|
if (this.channelLayer) {
|
||||||
|
this.channelLayer = this.$refs.mapComponent.updateLayer(this.channelLayer, array, true)
|
||||||
|
}else {
|
||||||
|
this.channelLayer = this.$refs.mapComponent.addLayer(array, data => {
|
||||||
|
this.closeInfoBox()
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (data[0].edit) {
|
||||||
|
this.showEditInfo(data[0])
|
||||||
|
}else {
|
||||||
|
this.showChannelInfo(data[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getImageByChannel: function (channel) {
|
||||||
|
if (channel.gbStatus === 'ON') {
|
||||||
|
return 'static/images/gis/camera1.png'
|
||||||
|
} else {
|
||||||
|
return 'static/images/gis/camera1-offline.png'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeInfoBox: function () {
|
||||||
|
if (this.infoBoxId !== null) {
|
||||||
|
this.$refs.mapComponent.closeInfoBox(this.infoBoxId)
|
||||||
|
}
|
||||||
|
this.channel = null
|
||||||
|
this.dragChannel = null
|
||||||
|
},
|
||||||
|
play: function (channel) {
|
||||||
|
const loading = this.$loading({
|
||||||
|
lock: true,
|
||||||
|
text: '正在请求视频',
|
||||||
|
spinner: 'el-icon-loading',
|
||||||
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
|
})
|
||||||
|
this.$store.dispatch('commonChanel/playChannel', channel.gbId)
|
||||||
|
.then((data) => {
|
||||||
|
this.$refs.devicePlayer.openDialog('media', channel.gbId, {
|
||||||
|
streamInfo: data,
|
||||||
|
hasAudio: channel.hasAudio
|
||||||
|
})
|
||||||
|
}).finally(() => {
|
||||||
|
loading.close()
|
||||||
|
})
|
||||||
|
|
||||||
|
},
|
||||||
|
edit: function (channel) {
|
||||||
|
this.closeInfoBox()
|
||||||
|
// 开启图标可拖动
|
||||||
|
this.$refs.mapComponent.dragInteraction.addFeatureId(channel.gbId,
|
||||||
|
{
|
||||||
|
startEvent: event => {
|
||||||
|
this.closeInfoBox()
|
||||||
|
},
|
||||||
|
endEvent: event => {
|
||||||
|
channel.gbLongitude = event.lonLat[0]
|
||||||
|
channel.gbLatitude = event.lonLat[1]
|
||||||
|
this.showEditInfo(channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
let position = null
|
||||||
|
if (!!channel.gbLongitude && !!channel.gbLatitude && channel.gbLongitude > 0 && channel.gbLatitude > 0) {
|
||||||
|
position = [channel.gbLongitude, channel.gbLatitude]
|
||||||
|
channel['oldLongitude'] = channel.gbLongitude
|
||||||
|
channel['oldLatitude'] = channel.gbLatitude
|
||||||
|
}else {
|
||||||
|
position = this.$refs.mapComponent.getCenter()
|
||||||
|
channel['oldLongitude'] = channel.gbLongitude
|
||||||
|
channel['oldLatitude'] = channel.gbLatitude
|
||||||
|
channel.gbLongitude = position[0]
|
||||||
|
channel.gbLatitude = position[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
channel['edit'] = true
|
||||||
|
if (!this.$refs.mapComponent.coordinateInView(position)) {
|
||||||
|
this.$refs.mapComponent.panTo(position, 16, () => {
|
||||||
|
this.showEditInfo(channel)
|
||||||
|
})
|
||||||
|
}else {
|
||||||
|
this.showEditInfo(channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标记可编辑图标为红色
|
||||||
|
this.$refs.mapComponent.setFeaturePositionById(this.channelLayer, channel.gbId, {
|
||||||
|
id: channel.gbId,
|
||||||
|
position: position,
|
||||||
|
data: channel,
|
||||||
|
image: {
|
||||||
|
anchor: [0.5, 1],
|
||||||
|
src: 'static/images/gis/camera1-red.png'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
showEditInfo: function(data) {
|
||||||
|
this.dragChannel = data
|
||||||
|
this.infoBoxId = this.$refs.mapComponent.openInfoBox([data.gbLongitude, data.gbLatitude], this.$refs.infoboxForEdit, [0, -50])
|
||||||
|
},
|
||||||
|
cancelEdit: function(channel) {
|
||||||
|
this.closeInfoBox()
|
||||||
|
this.$refs.mapComponent.dragInteraction.removeFeatureId(channel.gbId)
|
||||||
|
channel.gbLongitude = channel.oldLongitude
|
||||||
|
channel.gbLatitude = channel.oldLatitude
|
||||||
|
channel['edit'] = false
|
||||||
|
this.$refs.mapComponent.setFeaturePositionById(this.channelLayer, channel.gbId, {
|
||||||
|
id: channel.gbId,
|
||||||
|
position: [channel.gbLongitude, channel.gbLatitude],
|
||||||
|
data: channel,
|
||||||
|
image: {
|
||||||
|
anchor: [0.5, 1],
|
||||||
|
src: this.getImageByChannel(channel)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
submitEdit: function(channel) {
|
||||||
|
this.$store.dispatch('commonChanel/update', channel)
|
||||||
|
.then(data => {
|
||||||
|
this.$message.success({
|
||||||
|
showClose: true,
|
||||||
|
message: '保存成功'
|
||||||
|
})
|
||||||
|
this.closeInfoBox()
|
||||||
|
channel['edit'] = false
|
||||||
|
this.$refs.mapComponent.dragInteraction.removeFeatureId(channel.gbId)
|
||||||
|
this.$refs.mapComponent.setFeaturePositionById(this.channelLayer, channel.gbId, {
|
||||||
|
id: channel.gbId,
|
||||||
|
position: [channel.gbLongitude, channel.gbLatitude],
|
||||||
|
data: channel,
|
||||||
|
image: {
|
||||||
|
anchor: [0.5, 1],
|
||||||
|
src: this.getImageByChannel(channel)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 刷星树菜单
|
||||||
|
this.$refs.deviceTree.refresh('channel' + channel.gbId)
|
||||||
|
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getTrace: function (data) {
|
||||||
|
this.clean()
|
||||||
|
this.$refs.queryTrace.openDialog(data, (channelPositions) => {
|
||||||
|
if (channelPositions.length === 0) {
|
||||||
|
this.$message.info({
|
||||||
|
showClose: true,
|
||||||
|
message: '未查询到轨迹信息'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let positions = []
|
||||||
|
for (let i = 0; i < channelPositions.length; i++) {
|
||||||
|
if (channelPositions[i][this.longitudeStr] * channelPositions[i][this.latitudeStr] > 0) {
|
||||||
|
positions.push([channelPositions[i][this.longitudeStr], channelPositions[i][this.latitudeStr]])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (positions.length === 0) {
|
||||||
|
this.$message.info({
|
||||||
|
showClose: true,
|
||||||
|
message: '未查询到轨迹信息'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
clean: function (){
|
||||||
|
if (this.infoBoxId !== null) {
|
||||||
|
this.$refs.mapComponent.closeInfoBox(this.infoBoxId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.map-tool-box {
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
bottom: 20px;
|
||||||
|
}
|
||||||
|
.map-tool-btn-group {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-radius: 3px;
|
||||||
|
user-select: none;
|
||||||
|
box-shadow: 0 2px 2px rgba(0, 0, 0, .15);
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.map-tool-btn {
|
||||||
|
border-bottom: 1px #dfdfdf solid;
|
||||||
|
width: 33px;
|
||||||
|
height: 36px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 36px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.map-tool-btn i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.map-tool-btn-group:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobox-content{
|
||||||
|
width: 270px;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #868686;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobox-content::after {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -11px;
|
||||||
|
left: calc(50% - 8px);
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background: url('/static/images/arrow.png') no-repeat center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobox-edit-content{
|
||||||
|
width: 400px;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #868686;
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobox-edit-content::after {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -11px;
|
||||||
|
left: calc(50% - 8px);
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
background: url('/static/images/arrow.png') no-repeat center;
|
||||||
|
}
|
||||||
|
.infobox-close {
|
||||||
|
position: absolute;
|
||||||
|
right: 1rem;
|
||||||
|
top: 1rem;
|
||||||
|
color: #000000;
|
||||||
|
cursor:pointer
|
||||||
|
}
|
||||||
|
.el-descriptions__title {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 20px 20px 0px 23px;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
105
web/src/views/map/queryTrace.vue
Executable file
105
web/src/views/map/queryTrace.vue
Executable file
@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<div id="queryTrace" >
|
||||||
|
<el-dialog
|
||||||
|
title="查询轨迹"
|
||||||
|
width="40%"
|
||||||
|
top="2rem"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:visible.sync="showDialog"
|
||||||
|
:destroy-on-close="true"
|
||||||
|
@close="close()"
|
||||||
|
>
|
||||||
|
<div v-loading="isLoging">
|
||||||
|
<el-date-picker v-model="searchFrom" type="datetime" placeholder="选择开始日期时间" default-time="00:00:00" value-format="yyyy-MM-dd HH:mm:ss" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
|
||||||
|
<el-date-picker v-model="searchTo" type="datetime" placeholder="选择结束日期时间" default-time="00:00:00" value-format="yyyy-MM-dd HH:mm:ss" size="mini" style="width: 11rem;" align="right" :picker-options="pickerOptions"></el-date-picker>
|
||||||
|
<el-button icon="el-icon-search" size="mini" type="primary" @click="onSubmit">查询</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'deviceEdit',
|
||||||
|
props: [],
|
||||||
|
computed: {},
|
||||||
|
created() {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pickerOptions: {
|
||||||
|
shortcuts: [{
|
||||||
|
text: '今天',
|
||||||
|
onClick(picker) {
|
||||||
|
picker.$emit('pick', new Date())
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: '昨天',
|
||||||
|
onClick(picker) {
|
||||||
|
const date = new Date()
|
||||||
|
date.setTime(date.getTime() - 3600 * 1000 * 24)
|
||||||
|
picker.$emit('pick', date)
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: '一周前',
|
||||||
|
onClick(picker) {
|
||||||
|
const date = new Date()
|
||||||
|
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
|
||||||
|
picker.$emit('pick', date)
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
searchFrom: null,
|
||||||
|
searchTo: null,
|
||||||
|
listChangeCallback: null,
|
||||||
|
showDialog: false,
|
||||||
|
isLoging: false,
|
||||||
|
channel: null,
|
||||||
|
callback: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
openDialog: function (channel, callback) {
|
||||||
|
console.log(channel)
|
||||||
|
this.showDialog = true
|
||||||
|
this.callback = callback
|
||||||
|
this.channel = channel
|
||||||
|
},
|
||||||
|
|
||||||
|
onSubmit: function () {
|
||||||
|
console.log('onSubmit')
|
||||||
|
this.isLoging = true
|
||||||
|
let url = `/api/position/history/${this.channel.deviceId}?start=${this.searchFrom}&end=${this.searchTo}`
|
||||||
|
if (this.channel.channelId) {
|
||||||
|
url+='&channelId=${this.channel.channelId}'
|
||||||
|
}
|
||||||
|
this.$axios.get(url, {
|
||||||
|
}).then((res) => {
|
||||||
|
this.isLoging = false
|
||||||
|
if (typeof this.callback === 'function') {
|
||||||
|
if (res.data.code == 0) {
|
||||||
|
this.callback(res.data.data)
|
||||||
|
this.close()
|
||||||
|
}else {
|
||||||
|
this.$message.error({
|
||||||
|
showClose: true,
|
||||||
|
message: res.data.msg
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}).catch(function (error) {
|
||||||
|
this.isLoging = false
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
close: function () {
|
||||||
|
this.showDialog = false
|
||||||
|
this.isLoging = false
|
||||||
|
this.callback = null
|
||||||
|
this.channel = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Loading…
Reference in New Issue
Block a user