删除脚手架的demo类,实现区域摄像头接口相关接口

master
aosodo_4812 2026-09-02 16:09:28 +08:00
parent e96c28f729
commit c8882099b4
48 changed files with 813 additions and 702 deletions

View File

@ -1,23 +0,0 @@
<!doctype html><html lang="zh"><head data-built-info="@cqsjjb/scripts@2.0.0-alpha-1 Env/production (2025/10/17 11:07:53) App/risk"><meta charset="UTF-8"/><meta name="renderer" content="webkit"/><meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1"/><meta name="viewport" content="width=device-width,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover"><title>--</title><script>(function () {
const APP_ENV = {
antd: {
'ant-prefix': 'micro-temp',
fontFamily: 'PingFangSC-Regular',
colorPrimary: '#1677ff',
borderRadius: parseInt('2')
},
appKey: '',
basename: 'risk',
API_HOST: ''
};
APP_ENV.API_HOST = sessionStorage.API_HOST || APP_ENV.API_HOST || window.location.origin;
window.process = {
env: { app: APP_ENV },
NODE_ENV: 'production'
};
window.__JJB_ENVIRONMENT__ = {
API_HOST: APP_ENV.API_HOST,
redirect: '',
FRAMEWORK: APP_ENV.antd
};
})();</script><script defer="defer" src="/risk/static/js/295.21df88c875577274cecb.js"></script><script defer="defer" src="/risk/static/js/main.4c0885586ad9a06ab444.js"></script><link href="/risk/static/css/main.40fc518bb0818fe8b8ea.css" rel="stylesheet"></head><body style="overflow: hidden"><noscript>此网页需要开启JavaScript功能。</noscript><div id="root" style="width: 100%; height: 100%; position: relative"></div><script type="text/javascript">/* @cqsjjb/script 输出当前应用基本信息、构建时间 */console.log("%c@cqsjjb/scripts@2.0.0-alpha-1 Env/production (2025/10/17 11:07:53) App/risk Version/master Java/<branch-name>", "color: #1890ff; border-radius: 2px; padding: 0 4px; border: 1px solid #1890ff; background: #f9fcff")</script></body></html>

View File

@ -0,0 +1,54 @@
package com.zcloud.gbs.edgeguard.web;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.zcloud.gbs.edgeguard.api.RegionCameraServiceI;
import com.zcloud.gbs.edgeguard.dto.CameraLeaderUpdateCmd;
import com.zcloud.gbs.edgeguard.dto.RegionCameraBindCmd;
import com.zcloud.gbs.edgeguard.dto.RegionCameraPageQry;
import com.zcloud.gbs.edgeguard.dto.clientobject.RegionCameraCo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "边缘人脸区域安全-区域摄像头")
@RestController
@RequestMapping("/edgeguard")
@RequiredArgsConstructor
public class RegionCameraController {
private final RegionCameraServiceI regionCameraService;
@ApiOperation("查询区域已绑定摄像头")
@PostMapping("/region-cameras/page")
public PageResponse<RegionCameraCo> page(@Validated @RequestBody RegionCameraPageQry qry) {
return regionCameraService.page(qry);
}
@ApiOperation("保存区域摄像头选择结果")
@PutMapping("/regions/{regionId}/cameras")
public Response bind(@PathVariable("regionId") Long regionId,
@Validated @RequestBody RegionCameraBindCmd cmd) {
return regionCameraService.bind(regionId, cmd);
}
@ApiOperation("设置摄像头负责人")
@PutMapping("/region-cameras/{id}/leader")
public Response updateLeader(@PathVariable("id") Long id,
@Validated @RequestBody CameraLeaderUpdateCmd cmd) {
return regionCameraService.updateLeader(id, cmd);
}
@ApiOperation("解除摄像头绑定")
@DeleteMapping("/region-cameras/{id}")
public Response unbind(@PathVariable("id") Long id) {
return regionCameraService.unbind(id);
}
}

View File

@ -1,78 +0,0 @@
package com.zcloud.gbs.edgeguard.web;
import com.alibaba.cola.dto.MultiResponse;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse;
import com.zcloud.gbs.edgeguard.api.RiskPointServiceI;
import com.zcloud.gbs.edgeguard.dto.RiskPointAddCmd;
import com.zcloud.gbs.edgeguard.dto.RiskPointPageQry;
import com.zcloud.gbs.edgeguard.dto.RiskPointUpdateCmd;
import com.zcloud.gbs.edgeguard.dto.clientobject.RiskPointCo;
import com.jjb.saas.framework.auth.model.SSOUser;
import com.jjb.saas.framework.auth.utils.AuthContext;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
/**
* @author lin
*/
@Api(tags = "边缘人脸区域安全-风险点管理")
@RequestMapping("/edgeguard/riskPoint")
@RestController
@AllArgsConstructor
public class RiskPointController {
private final RiskPointServiceI riskPointService;
@ApiOperation("新增")
@PostMapping("/save")
public SingleResponse<RiskPointCo> add(@Validated @RequestBody RiskPointAddCmd cmd) {
SSOUser ssoUser = AuthContext.getCurrentUser();
return riskPointService.add(cmd);
}
@ApiOperation("分页")
@PostMapping("/list")
public PageResponse<RiskPointCo> page(@RequestBody RiskPointPageQry qry) {
return riskPointService.listPage(qry);
}
@ApiOperation("所有数据")
@GetMapping("/listAll")
public MultiResponse<RiskPointCo> listAll() {
return MultiResponse.of(new ArrayList<RiskPointCo>());
}
@ApiOperation("详情")
@GetMapping("/{id}")
public SingleResponse<RiskPointCo> getInfoById(@PathVariable("id") Long id) {
return SingleResponse.of(new RiskPointCo());
}
@ApiOperation("删除")
@DeleteMapping("/{id}")
public Response remove(@PathVariable("id") Long id) {
riskPointService.remove(id);
return SingleResponse.buildSuccess();
}
@ApiOperation("删除多个")
@DeleteMapping("/ids")
public Response removeBatch(@RequestParam Long[] ids) {
riskPointService.removeBatch(ids);
return SingleResponse.buildSuccess();
}
@ApiOperation("修改")
@PutMapping("/edit")
public SingleResponse edit(@Validated @RequestBody RiskPointUpdateCmd riskPointUpdateCmd) {
riskPointService.edit(riskPointUpdateCmd);
return SingleResponse.buildSuccess();
}
}

View File

@ -21,6 +21,12 @@
<groupId>com.zcloud.gbs.edgeguard</groupId> <groupId>com.zcloud.gbs.edgeguard</groupId>
<artifactId>web-infrastructure</artifactId> <artifactId>web-infrastructure</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,34 @@
package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.gateway.RegionCameraGateway;
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
import com.zcloud.gbs.edgeguard.dto.CameraLeaderUpdateCmd;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
@RequiredArgsConstructor
public class CameraLeaderUpdateExe {
private final RegionCameraGateway cameraGateway;
private final RegionAccessService accessService;
private final RegionCommandSupport support;
@Transactional(rollbackFor = Exception.class)
public void execute(Long id, CameraLeaderUpdateCmd cmd) {
RegionCameraE binding = cameraGateway.getById(id);
if (binding == null || !"BOUND".equals(binding.getBindStatus())) {
throw new BizException("有效摄像头绑定不存在");
}
accessService.requireAccessibleRegion(binding.getRegionId());
support.validateLeader(cmd.getLeaderUserId(), binding.getCorpId());
RegionCameraE changed = new RegionCameraE();
changed.setId(id);
changed.setVersion(binding.getVersion());
changed.setLeaderUserId(cmd.getLeaderUserId());
if (!cameraGateway.update(changed)) {
throw new BizException("设置摄像头负责人失败,请刷新后重试");
}
}
}

View File

@ -2,7 +2,9 @@ package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException; import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.gateway.CorpGateway; import com.zcloud.gbs.edgeguard.domain.gateway.CorpGateway;
import com.zcloud.gbs.edgeguard.domain.gateway.RegionGateway;
import com.zcloud.gbs.edgeguard.domain.model.CorpE; import com.zcloud.gbs.edgeguard.domain.model.CorpE;
import com.zcloud.gbs.edgeguard.domain.model.RegionE;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -12,6 +14,7 @@ import java.util.List;
@RequiredArgsConstructor @RequiredArgsConstructor
public class RegionAccessService { public class RegionAccessService {
private final CorpGateway corpGateway; private final CorpGateway corpGateway;
private final RegionGateway regionGateway;
public List<CorpE> accessibleCorps() { public List<CorpE> accessibleCorps() {
return corpGateway.listAccessibleCorps(); return corpGateway.listAccessibleCorps();
@ -28,4 +31,13 @@ public class RegionAccessService {
} }
throw new BizException("无权访问该企业数据"); throw new BizException("无权访问该企业数据");
} }
public RegionE requireAccessibleRegion(Long regionId) {
RegionE region = regionGateway.getById(regionId);
if (region == null) {
throw new BizException("区域不存在");
}
requireAccessibleCorp(region.getCorpId());
return region;
}
} }

View File

@ -0,0 +1,65 @@
package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.model.CameraKeyE;
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
import com.zcloud.gbs.edgeguard.domain.model.RegionE;
import com.zcloud.gbs.edgeguard.dto.CameraSelectionCmd;
import com.zcloud.gbs.edgeguard.dto.RegionCameraBindCmd;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Component
@RequiredArgsConstructor
public class RegionCameraBindExe {
private static final String CAMERA_SOURCE = "VIDEOPATROL";
private final RegionAccessService accessService;
private final RegionCameraBindTransaction transaction;
public void execute(Long regionId, RegionCameraBindCmd cmd) {
RegionE region = accessService.requireAccessibleRegion(regionId);
List<CameraKeyE> keys = new ArrayList<>();
List<RegionCameraE> snapshots = new ArrayList<>();
Set<String> identities = new HashSet<>();
for (CameraSelectionCmd camera : cmd.getCameras()) {
if (!region.getCorpId().equals(camera.getCorpinfoId())) {
throw new BizException("摄像头所属单位与区域所属企业不一致:" + camera.getVideoName());
}
String cameraId = camera.getFixedCameraId().trim();
CameraKeyE key = new CameraKeyE(CAMERA_SOURCE, cameraId);
if (!identities.add(key.identity())) {
throw new BizException("摄像头选择结果存在重复项");
}
keys.add(key);
snapshots.add(toSnapshot(camera));
}
transaction.execute(region, keys, snapshots);
}
private RegionCameraE toSnapshot(CameraSelectionCmd camera) {
RegionCameraE snapshot = new RegionCameraE();
snapshot.setCameraSource(CAMERA_SOURCE);
snapshot.setCameraId(camera.getFixedCameraId().trim());
snapshot.setCameraName(camera.getVideoName().trim());
snapshot.setVideoType(camera.getVideoType());
snapshot.setCameraUnitId(camera.getCorpinfoId());
snapshot.setCameraUnitName(camera.getCorpinfoName());
snapshot.setCameraDeptId(camera.getDepartmentId());
snapshot.setCameraDeptName(camera.getDepartmentName());
snapshot.setVideoLevel(camera.getVideoLevel());
snapshot.setVideoAddress(camera.getVideoAddress());
snapshot.setIsOnline(camera.getIsOnline());
snapshot.setDeviceModel(camera.getDeviceModel());
snapshot.setDeviceGbNumber(camera.getDeviceGbNumber());
snapshot.setCameraNumber(camera.getCameraNumber());
snapshot.setLongitude(camera.getLongitude());
snapshot.setLatitude(camera.getLatitude());
snapshot.setRemarks(camera.getRemarks());
return snapshot;
}
}

View File

@ -0,0 +1,93 @@
package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.gateway.RegionCameraGateway;
import com.zcloud.gbs.edgeguard.domain.model.CameraKeyE;
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
import com.zcloud.gbs.edgeguard.domain.model.RegionE;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
@RequiredArgsConstructor
public class RegionCameraBindTransaction {
private final RegionCameraGateway cameraGateway;
@Transactional(rollbackFor = Exception.class)
public void execute(RegionE region, List<CameraKeyE> keys, List<RegionCameraE> authoritative) {
Map<String, RegionCameraE> existingByIdentity = new HashMap<>();
for (RegionCameraE existing : cameraGateway.listByKeys(region.getCorpId(), keys)) {
existingByIdentity.put(identity(existing), existing);
if ("BOUND".equals(existing.getBindStatus()) && !region.getId().equals(existing.getRegionId())) {
throw new BizException("摄像头已绑定其他区域:" + existing.getCameraName());
}
}
Map<String, RegionCameraE> authoritativeByIdentity = new HashMap<>();
for (RegionCameraE camera : authoritative) {
authoritativeByIdentity.put(identity(camera), camera);
}
Set<String> selected = new HashSet<>(authoritativeByIdentity.keySet());
Date now = new Date();
for (RegionCameraE current : cameraGateway.listBoundByRegionId(region.getId())) {
if (!selected.contains(identity(current))) {
current.setBindStatus("UNBOUND");
current.setUnboundTime(now);
if (!cameraGateway.update(current)) {
throw new BizException("解除摄像头绑定失败");
}
}
}
for (Map.Entry<String, RegionCameraE> entry : authoritativeByIdentity.entrySet()) {
RegionCameraE authoritativeCamera = entry.getValue();
RegionCameraE existing = existingByIdentity.get(entry.getKey());
if (existing == null) {
RegionCameraE created = snapshot(authoritativeCamera, new RegionCameraE());
created.setRegionId(region.getId());
created.setCorpId(region.getCorpId());
created.setBindStatus("BOUND");
created.setBoundTime(now);
if (!cameraGateway.add(created)) {
throw new BizException("保存摄像头绑定失败");
}
} else {
Long leaderUserId = existing.getLeaderUserId();
Date boundTime = existing.getBoundTime();
boolean wasBound = "BOUND".equals(existing.getBindStatus());
snapshot(authoritativeCamera, existing);
existing.setRegionId(region.getId());
existing.setCorpId(region.getCorpId());
existing.setLeaderUserId(leaderUserId);
existing.setBindStatus("BOUND");
existing.setBoundTime(wasBound && boundTime != null ? boundTime : now);
existing.setUnboundTime(null);
if (!cameraGateway.update(existing)) {
throw new BizException("更新摄像头绑定失败");
}
}
}
}
private RegionCameraE snapshot(RegionCameraE source, RegionCameraE target) {
Long id = target.getId();
Integer version = target.getVersion();
BeanUtils.copyProperties(source, target, "id", "regionId", "corpId", "leaderUserId",
"bindStatus", "boundTime", "unboundTime", "version");
target.setId(id);
target.setVersion(version);
return target;
}
private String identity(RegionCameraE camera) {
return camera.getCameraSource() + ":" + camera.getCameraId();
}
}

View File

@ -0,0 +1,34 @@
package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.gateway.RegionCameraGateway;
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
@Component
@RequiredArgsConstructor
public class RegionCameraUnbindExe {
private final RegionCameraGateway cameraGateway;
private final RegionAccessService accessService;
@Transactional(rollbackFor = Exception.class)
public void execute(Long id) {
RegionCameraE binding = cameraGateway.getById(id);
if (binding == null || !"BOUND".equals(binding.getBindStatus())) {
throw new BizException("有效摄像头绑定不存在");
}
accessService.requireAccessibleRegion(binding.getRegionId());
RegionCameraE changed = new RegionCameraE();
changed.setId(id);
changed.setVersion(binding.getVersion());
changed.setBindStatus("UNBOUND");
changed.setUnboundTime(new Date());
if (!cameraGateway.update(changed)) {
throw new BizException("解除摄像头绑定失败,请刷新后重试");
}
}
}

View File

@ -1,37 +0,0 @@
package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.gateway.RiskPointGateway;
import com.zcloud.gbs.edgeguard.domain.model.RiskPointE;
import com.zcloud.gbs.edgeguard.dto.RiskPointAddCmd;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
*
*
* @author lin
*/
@Component
@AllArgsConstructor
public class RiskPointAddExe {
private final RiskPointGateway riskPointGateway;
@Transactional(rollbackFor = Exception.class)
public boolean execute(RiskPointAddCmd cmd) {
RiskPointE examTypeE = new RiskPointE();
BeanUtils.copyProperties(cmd, examTypeE);
boolean res = false;
try {
res = riskPointGateway.add(examTypeE);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (!res) {
throw new BizException("保存失败");
}
return true;
}
}

View File

@ -1,33 +0,0 @@
package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.gateway.RiskPointGateway;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
*
* @author lin
*/
@Component
@AllArgsConstructor
public class RiskPointRemoveExe {
private final RiskPointGateway riskPointGateway;
@Transactional(rollbackFor = Exception.class)
public boolean execute(Long id) {
boolean res = riskPointGateway.deletedRiskPointById(id);
if(!res){
throw new BizException("删除失败");
}
return true;
}
@Transactional(rollbackFor = Exception.class)
public boolean execute(Long[] ids) {
boolean res = riskPointGateway.deletedRiskPointByIds(ids);
if(!res){
throw new BizException("删除失败");
}
return true;
}
}

View File

@ -1,31 +0,0 @@
package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.gateway.RiskPointGateway;
import com.zcloud.gbs.edgeguard.domain.model.RiskPointE;
import com.zcloud.gbs.edgeguard.dto.RiskPointUpdateCmd;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
/**
*
*
* @author lin
*/
@Component
@AllArgsConstructor
public class RiskPointUpdateExe {
private final RiskPointGateway riskPointGateway;
@Transactional(rollbackFor = Exception.class)
public void execute(RiskPointUpdateCmd riskPointUpdateCmd) {
RiskPointE riskPointE = new RiskPointE();
BeanUtils.copyProperties(riskPointUpdateCmd, riskPointE);
boolean res = riskPointGateway.update(riskPointE);
if (!res) {
throw new BizException("修改失败");
}
}
}

View File

@ -1,16 +0,0 @@
package com.zcloud.gbs.edgeguard.command.convertor;
import com.zcloud.gbs.edgeguard.dto.clientobject.RiskPointCo;
import com.zcloud.gbs.edgeguard.persistence.dataobject.RiskPointDO;
import org.mapstruct.Mapper;
import java.util.List;
@Mapper(componentModel = "spring")
public interface RiskPointCoConvertor {
/**
* @param riskPointE
* @return
*/
List<RiskPointCo> converDOsToCOs(List<RiskPointDO> riskPointE);
}

View File

@ -0,0 +1,72 @@
package com.zcloud.gbs.edgeguard.command.query;
import com.alibaba.cola.dto.PageResponse;
import com.zcloud.gbs.edgeguard.command.RegionAccessService;
import com.zcloud.gbs.edgeguard.domain.gateway.RegionCameraGateway;
import com.zcloud.gbs.edgeguard.domain.gateway.UserGateway;
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
import com.zcloud.gbs.edgeguard.domain.model.RegionE;
import com.zcloud.gbs.edgeguard.domain.model.UserE;
import com.zcloud.gbs.edgeguard.dto.RegionCameraPageQry;
import com.zcloud.gbs.edgeguard.dto.clientobject.RegionCameraCo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
@RequiredArgsConstructor
public class RegionCameraQueryExe {
private final RegionCameraGateway cameraGateway;
private final UserGateway userGateway;
private final RegionAccessService accessService;
public PageResponse<RegionCameraCo> page(RegionCameraPageQry qry) {
RegionE region = accessService.requireAccessibleRegion(qry.getRegionId());
int pageIndex = safePageIndex(qry.getPageIndex());
int pageSize = safePageSize(qry.getPageSize());
List<RegionCameraE> rows = cameraGateway.pageBound(
region.getId(), qry.getName(), qry.getVideoLevel(), qry.getIsOnline(), pageIndex, pageSize);
long total = cameraGateway.countBound(
region.getId(), qry.getName(), qry.getVideoLevel(), qry.getIsOnline());
Set<Long> leaderIds = new HashSet<>();
for (RegionCameraE row : rows) {
if (row.getLeaderUserId() != null) leaderIds.add(row.getLeaderUserId());
}
Map<Long, String> leaderNames = new HashMap<>();
for (UserE user : userGateway.listByIds(leaderIds)) {
leaderNames.put(user.getId(), user.getName());
}
List<RegionCameraCo> result = new ArrayList<>();
for (RegionCameraE row : rows) {
RegionCameraCo co = new RegionCameraCo();
BeanUtils.copyProperties(row, co);
co.setFixedCameraId(row.getCameraId());
co.setVideoName(row.getCameraName());
co.setCorpinfoId(row.getCameraUnitId());
co.setCorpinfoName(row.getCameraUnitName());
co.setDepartmentId(row.getCameraDeptId());
co.setDepartmentName(row.getCameraDeptName());
co.setRegionName(region.getRegionName());
co.setLeaderUserName(leaderNames.get(row.getLeaderUserId()));
result.add(co);
}
return PageResponse.of(result, (int) total, pageSize, pageIndex);
}
private int safePageIndex(int pageIndex) {
return pageIndex <= 0 ? 1 : pageIndex;
}
private int safePageSize(int pageSize) {
return pageSize <= 0 ? 10 : Math.min(pageSize, 200);
}
}

View File

@ -1,36 +0,0 @@
package com.zcloud.gbs.edgeguard.command.query;
import com.alibaba.cola.dto.PageResponse;
import com.zcloud.gbs.edgeguard.command.convertor.RiskPointCoConvertor;
import com.zcloud.gbs.edgeguard.dto.RiskPointPageQry;
import com.zcloud.gbs.edgeguard.dto.clientobject.RiskPointCo;
import com.zcloud.gbs.edgeguard.persistence.dataobject.RiskPointDO;
import com.zcloud.gbs.edgeguard.persistence.repository.RiskPointRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.List;
/**
*
*
* @author lin
*/
@Component
@AllArgsConstructor
public class RiskPointQueryExe {
private final RiskPointRepository riskPointRepository;
private final RiskPointCoConvertor riskPointCoConvertor;
/**
*
*
* @param riskPointPageQry
* @return
*/
public PageResponse<RiskPointCo> execute(RiskPointPageQry riskPointPageQry) {
PageResponse<RiskPointDO> pageResponse = riskPointRepository.listRiskPointPage(riskPointPageQry.toHashMap());
List<RiskPointCo> examCenterCOS = riskPointCoConvertor.converDOsToCOs(pageResponse.getData());
return PageResponse.of(examCenterCOS, pageResponse.getTotalCount(), pageResponse.getPageSize(), pageResponse.getPageIndex());
}
}

View File

@ -0,0 +1,47 @@
package com.zcloud.gbs.edgeguard.service;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.zcloud.gbs.edgeguard.api.RegionCameraServiceI;
import com.zcloud.gbs.edgeguard.command.CameraLeaderUpdateExe;
import com.zcloud.gbs.edgeguard.command.RegionCameraBindExe;
import com.zcloud.gbs.edgeguard.command.RegionCameraUnbindExe;
import com.zcloud.gbs.edgeguard.command.query.RegionCameraQueryExe;
import com.zcloud.gbs.edgeguard.dto.CameraLeaderUpdateCmd;
import com.zcloud.gbs.edgeguard.dto.RegionCameraBindCmd;
import com.zcloud.gbs.edgeguard.dto.RegionCameraPageQry;
import com.zcloud.gbs.edgeguard.dto.clientobject.RegionCameraCo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class RegionCameraServiceImpl implements RegionCameraServiceI {
private final RegionCameraQueryExe queryExe;
private final RegionCameraBindExe bindExe;
private final CameraLeaderUpdateExe leaderUpdateExe;
private final RegionCameraUnbindExe unbindExe;
@Override
public PageResponse<RegionCameraCo> page(RegionCameraPageQry qry) {
return queryExe.page(qry);
}
@Override
public Response bind(Long regionId, RegionCameraBindCmd cmd) {
bindExe.execute(regionId, cmd);
return Response.buildSuccess();
}
@Override
public Response updateLeader(Long id, CameraLeaderUpdateCmd cmd) {
leaderUpdateExe.execute(id, cmd);
return Response.buildSuccess();
}
@Override
public Response unbind(Long id) {
unbindExe.execute(id);
return Response.buildSuccess();
}
}

View File

@ -1,56 +0,0 @@
package com.zcloud.gbs.edgeguard.service;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.SingleResponse;
import com.zcloud.gbs.edgeguard.api.RiskPointServiceI;
import com.zcloud.gbs.edgeguard.command.RiskPointAddExe;
import com.zcloud.gbs.edgeguard.command.RiskPointRemoveExe;
import com.zcloud.gbs.edgeguard.command.RiskPointUpdateExe;
import com.zcloud.gbs.edgeguard.command.query.RiskPointQueryExe;
import com.zcloud.gbs.edgeguard.dto.RiskPointAddCmd;
import com.zcloud.gbs.edgeguard.dto.RiskPointPageQry;
import com.zcloud.gbs.edgeguard.dto.RiskPointUpdateCmd;
import com.zcloud.gbs.edgeguard.dto.clientobject.RiskPointCo;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
/**
* @author lin
*/
@Service
@AllArgsConstructor
public class RiskPointServiceImpl implements RiskPointServiceI {
private final RiskPointAddExe riskPointAddExe;
private final RiskPointUpdateExe riskPointUpdateExe;
private final RiskPointRemoveExe riskPointRemoveExe;
private final RiskPointQueryExe riskPointQueryExe;
@Override
public PageResponse<RiskPointCo> listPage(RiskPointPageQry qry){
return riskPointQueryExe.execute(qry);
}
@Override
public SingleResponse add(RiskPointAddCmd cmd) {
riskPointAddExe.execute(cmd);
return SingleResponse.buildSuccess();
}
@Override
public void edit(RiskPointUpdateCmd riskPointUpdateCmd) {
riskPointUpdateExe.execute(riskPointUpdateCmd);
}
@Override
public void remove(Long id) {
riskPointRemoveExe.execute(id);
}
@Override
public void removeBatch(Long[] ids) {
riskPointRemoveExe.execute(ids);
}
}

View File

@ -0,0 +1,97 @@
package com.zcloud.gbs.edgeguard.command;
import com.alibaba.cola.exception.BizException;
import com.zcloud.gbs.edgeguard.domain.gateway.RegionCameraGateway;
import com.zcloud.gbs.edgeguard.domain.model.CameraKeyE;
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
import com.zcloud.gbs.edgeguard.domain.model.RegionE;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class RegionCameraBindTransactionTest {
@Test
public void shouldApplyAddAndUnbindDifference() {
FakeGateway gateway = new FakeGateway();
gateway.rows.add(binding(1L, 10L, "SOURCE", "A", "BOUND"));
RegionCameraBindTransaction transaction = new RegionCameraBindTransaction(gateway);
RegionE region = new RegionE();
region.setId(10L);
region.setCorpId(100L);
transaction.execute(region,
Collections.singletonList(new CameraKeyE("SOURCE", "B")),
Collections.singletonList(binding(null, null, "SOURCE", "B", null)));
Assert.assertEquals("UNBOUND", gateway.find("SOURCE:A", false).getBindStatus());
Assert.assertNotNull(gateway.find("SOURCE:B", false));
Assert.assertEquals("BOUND", gateway.find("SOURCE:B", false).getBindStatus());
Assert.assertEquals(Long.valueOf(10L), gateway.find("SOURCE:B", false).getRegionId());
}
@Test
public void shouldRejectCameraBoundToOtherRegion() {
FakeGateway gateway = new FakeGateway();
gateway.rows.add(binding(1L, 99L, "SOURCE", "A", "BOUND"));
RegionCameraBindTransaction transaction = new RegionCameraBindTransaction(gateway);
RegionE region = new RegionE();
region.setId(10L);
region.setCorpId(100L);
try {
transaction.execute(region,
Collections.singletonList(new CameraKeyE("SOURCE", "A")),
Collections.singletonList(binding(null, null, "SOURCE", "A", null)));
Assert.fail("绑定到其他区域的摄像头应被拒绝");
} catch (BizException expected) {
Assert.assertTrue(expected.getMessage().startsWith("摄像头已绑定其他区域"));
}
}
private static RegionCameraE binding(Long id, Long regionId, String source, String cameraId, String status) {
RegionCameraE camera = new RegionCameraE();
camera.setId(id);
camera.setRegionId(regionId);
camera.setCameraSource(source);
camera.setCameraId(cameraId);
camera.setCameraName(cameraId);
camera.setBindStatus(status);
return camera;
}
private static class FakeGateway implements RegionCameraGateway {
private final List<RegionCameraE> rows = new ArrayList<>();
private long sequence = 10;
@Override public Boolean add(RegionCameraE value) { value.setId(sequence++); rows.add(value); return true; }
@Override public Boolean update(RegionCameraE value) { return true; }
@Override public Boolean deleteById(Long id) { return false; }
@Override public RegionCameraE getById(Long id) { return null; }
@Override public boolean existsBoundByRegionId(Long regionId) { return false; }
@Override public List<RegionCameraE> pageBound(Long regionId, String name, String level, Integer online, int index, int size) { return Collections.emptyList(); }
@Override public long countBound(Long regionId, String name, String level, Integer online) { return 0; }
@Override public List<RegionCameraE> listBoundByRegionId(Long regionId) {
List<RegionCameraE> result = new ArrayList<>();
for (RegionCameraE row : rows) if (regionId.equals(row.getRegionId()) && "BOUND".equals(row.getBindStatus())) result.add(row);
return result;
}
@Override public List<RegionCameraE> listByKeys(Long corpId, Collection<CameraKeyE> keys) {
List<RegionCameraE> result = new ArrayList<>();
for (CameraKeyE key : keys) {
RegionCameraE value = find(key.identity(), false);
if (value != null) result.add(value);
}
return result;
}
private RegionCameraE find(String identity, boolean ignored) {
for (RegionCameraE row : rows) {
if ((row.getCameraSource() + ":" + row.getCameraId()).equals(identity)) return row;
}
return null;
}
}
}

View File

@ -0,0 +1,15 @@
package com.zcloud.gbs.edgeguard.api;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response;
import com.zcloud.gbs.edgeguard.dto.CameraLeaderUpdateCmd;
import com.zcloud.gbs.edgeguard.dto.RegionCameraBindCmd;
import com.zcloud.gbs.edgeguard.dto.RegionCameraPageQry;
import com.zcloud.gbs.edgeguard.dto.clientobject.RegionCameraCo;
public interface RegionCameraServiceI {
PageResponse<RegionCameraCo> page(RegionCameraPageQry qry);
Response bind(Long regionId, RegionCameraBindCmd cmd);
Response updateLeader(Long id, CameraLeaderUpdateCmd cmd);
Response unbind(Long id);
}

View File

@ -1,20 +0,0 @@
package com.zcloud.gbs.edgeguard.api;
import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.SingleResponse;
import com.zcloud.gbs.edgeguard.dto.RiskPointAddCmd;
import com.zcloud.gbs.edgeguard.dto.RiskPointPageQry;
import com.zcloud.gbs.edgeguard.dto.RiskPointUpdateCmd;
import com.zcloud.gbs.edgeguard.dto.clientobject.RiskPointCo;
public interface RiskPointServiceI {
PageResponse<RiskPointCo> listPage(RiskPointPageQry qry);
SingleResponse<RiskPointCo> add(RiskPointAddCmd cmd);
void edit(RiskPointUpdateCmd riskPointUpdateCmd);
void remove(Long id);
void removeBatch(Long[] ids);
}

View File

@ -0,0 +1,14 @@
package com.zcloud.gbs.edgeguard.dto;
import com.alibaba.cola.dto.Command;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
@Data
@EqualsAndHashCode(callSuper = true)
public class CameraLeaderUpdateCmd extends Command {
@NotNull(message = "摄像头负责人不能为空")
private Long leaderUserId;
}

View File

@ -0,0 +1,30 @@
package com.zcloud.gbs.edgeguard.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
@Data
public class CameraSelectionCmd implements Serializable {
@NotBlank(message = "固定摄像头业务ID不能为空")
private String fixedCameraId;
@NotBlank(message = "视频名称不能为空")
private String videoName;
private String videoType;
@NotNull(message = "所属单位ID不能为空")
private Long corpinfoId;
private String corpinfoName;
private Long departmentId;
private String departmentName;
private String videoLevel;
private String videoAddress;
private Integer isOnline;
private String deviceModel;
private String deviceGbNumber;
private String cameraNumber;
private String longitude;
private String latitude;
private String remarks;
}

View File

@ -0,0 +1,19 @@
package com.zcloud.gbs.edgeguard.dto;
import com.alibaba.cola.dto.Command;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
public class RegionCameraBindCmd extends Command {
/** 提交完整选中集合;空集合表示解除该区域全部绑定。 */
@Valid
@NotNull(message = "摄像头选择结果不能为空")
private List<CameraSelectionCmd> cameras = new ArrayList<>();
}

View File

@ -0,0 +1,19 @@
package com.zcloud.gbs.edgeguard.dto;
import com.alibaba.cola.dto.PageQuery;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
@Data
@EqualsAndHashCode(callSuper = true)
public class RegionCameraPageQry extends PageQuery {
@NotNull(message = "区域ID不能为空")
@ApiModelProperty(value = "区域ID", required = true)
private Long regionId;
private String name;
private String videoLevel;
private Integer isOnline;
}

View File

@ -1,30 +0,0 @@
package com.zcloud.gbs.edgeguard.dto;
import com.alibaba.cola.dto.Command;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
/**
*
* @author lin
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RiskPointAddCmd extends Command {
@ApiModelProperty(value = "风险点名字", name = "riskPointName", required = true)
@NotEmpty(message = "风险点名字不能为空")
private String riskPointName;
// @ApiModelProperty(value = "部门Id", name = "deptId", required = true)
// @NotEmpty
// private String deptId;
@NotEmpty(message = "部门名字不能为空")
@ApiModelProperty(value = "部门名字", name = "deptName", required = true)
private String deptName;
}

View File

@ -1,46 +0,0 @@
package com.zcloud.gbs.edgeguard.dto;
import com.alibaba.cola.dto.PageQuery;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
@Data
public class RiskPointPageQry extends PageQuery {
@ApiModelProperty(value = "风险点名称")
private String likeRiskPointName;
@ApiModelProperty(value = "部门名称")
private String eqDeptName;
public Map<String, Object> toHashMap() {
Map<String, Object> map = new HashMap<>();
Class<?> clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
map.put(field.getName(), field.get(this));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
Class<?> superClass = clazz.getSuperclass();
if (superClass != null) {
Field[] superFields = superClass.getDeclaredFields();
for (Field field : superFields) {
try {
field.setAccessible(true);
map.put(field.getName(), field.get(this));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return map;
}
}

View File

@ -1,31 +0,0 @@
package com.zcloud.gbs.edgeguard.dto;
import com.alibaba.cola.dto.Command;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotEmpty;
/**
*
* @author lin
*/
@EqualsAndHashCode(callSuper = true)
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RiskPointUpdateCmd extends Command {
@ApiModelProperty(value = "风险点id", name = "id", required = true)
@NotEmpty
private String id;
@ApiModelProperty(value = "风险点名字", name = "riskPointName", required = true)
@NotEmpty
private String riskPointName;
@NotEmpty
@ApiModelProperty(value = "部门名字", name = "deptName", required = true)
private String deptName;
}

View File

@ -0,0 +1,33 @@
package com.zcloud.gbs.edgeguard.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import lombok.Data;
import java.util.Date;
@Data
public class RegionCameraCo extends ClientObject {
private Long id;
private Long regionId;
private String regionName;
private String fixedCameraId;
private String videoName;
private String videoType;
private Long corpinfoId;
private String corpinfoName;
private Long departmentId;
private String departmentName;
private String videoLevel;
private String videoAddress;
private Integer isOnline;
private String deviceModel;
private String deviceGbNumber;
private String cameraNumber;
private String longitude;
private String latitude;
private Long leaderUserId;
private String leaderUserName;
private String bindStatus;
private Date boundTime;
private Date unboundTime;
}

View File

@ -1,17 +0,0 @@
package com.zcloud.gbs.edgeguard.dto.clientobject;
import com.alibaba.cola.dto.ClientObject;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class RiskPointCo extends ClientObject {
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "风险点名称")
private String riskPointName;
@ApiModelProperty(value = "部门名称")
private String deptName;
@ApiModelProperty(value = "创建人")
private String createName;
}

View File

@ -1,6 +1,10 @@
package com.zcloud.gbs.edgeguard.domain.gateway; package com.zcloud.gbs.edgeguard.domain.gateway;
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE; import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
import com.zcloud.gbs.edgeguard.domain.model.CameraKeyE;
import java.util.Collection;
import java.util.List;
public interface RegionCameraGateway { public interface RegionCameraGateway {
Boolean add(RegionCameraE regionCamera); Boolean add(RegionCameraE regionCamera);
@ -8,4 +12,9 @@ public interface RegionCameraGateway {
Boolean deleteById(Long id); Boolean deleteById(Long id);
RegionCameraE getById(Long id); RegionCameraE getById(Long id);
boolean existsBoundByRegionId(Long regionId); boolean existsBoundByRegionId(Long regionId);
List<RegionCameraE> pageBound(Long regionId, String cameraName, String videoLevel,
Integer isOnline, int pageIndex, int pageSize);
long countBound(Long regionId, String cameraName, String videoLevel, Integer isOnline);
List<RegionCameraE> listBoundByRegionId(Long regionId);
List<RegionCameraE> listByKeys(Long corpId, Collection<CameraKeyE> cameraKeys);
} }

View File

@ -11,6 +11,7 @@ public interface RegionGateway {
Boolean deleteById(Long id); Boolean deleteById(Long id);
RegionE getById(Long id); RegionE getById(Long id);
List<RegionE> listByCorpIds(Collection<Long> corpIds); List<RegionE> listByCorpIds(Collection<Long> corpIds);
List<RegionE> listByIds(Collection<Long> ids);
boolean existsSiblingName(Long corpId, Long parentId, String regionName, Long excludeId); boolean existsSiblingName(Long corpId, Long parentId, String regionName, Long excludeId);
boolean existsChild(Long parentId); boolean existsChild(Long parentId);
} }

View File

@ -1,33 +0,0 @@
package com.zcloud.gbs.edgeguard.domain.gateway;
import com.zcloud.gbs.edgeguard.domain.model.RiskPointE;
/**
* getway
* @author lin
*/
public interface RiskPointGateway {
/**
*
* @param riskPointE
* @return
*/
Boolean add(RiskPointE riskPointE) ;
/**
*
* @param riskPointE
* @return
*/
Boolean update(RiskPointE riskPointE);
/**
*
* @param id
* @return
*/
Boolean deletedRiskPointById(Long id);
Boolean deletedRiskPointByIds(Long[] id);
}

View File

@ -0,0 +1,17 @@
package com.zcloud.gbs.edgeguard.domain.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CameraKeyE {
private String cameraSource;
private String cameraId;
public String identity() {
return cameraSource + ":" + cameraId;
}
}

View File

@ -18,19 +18,23 @@ public class RegionCameraE extends BaseE {
private String cameraSource; private String cameraSource;
private String cameraId; private String cameraId;
private String cameraName; private String cameraName;
private String cameraUnitId; private String videoType;
private Long cameraUnitId;
private String cameraUnitName; private String cameraUnitName;
private String cameraTypeCode; private Long cameraDeptId;
private String cameraTypeName;
private String cameraLevelCode;
private String cameraLevelName;
private String cameraDeptId;
private String cameraDeptName; private String cameraDeptName;
private String onlineStatus; private String videoLevel;
private String cameraSnapshot; private String videoAddress;
private Date cameraSyncedAt; private Integer isOnline;
private String deviceModel;
private String deviceGbNumber;
private String cameraNumber;
private String longitude;
private String latitude;
private Long leaderUserId; private Long leaderUserId;
private String bindStatus; private String bindStatus;
private Date boundTime; private Date boundTime;
private Date unboundTime; private Date unboundTime;
private Integer version;
private String remarks;
} }

View File

@ -1,20 +0,0 @@
package com.zcloud.gbs.edgeguard.domain.model;
import com.alibaba.cola.domain.Entity;
import com.jjb.saas.framework.domain.model.BaseE;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
*
*
* @author lin
*/
@Data
@Entity
@EqualsAndHashCode(callSuper = true)
public class RiskPointE extends BaseE {
private Long id;
private String riskPointName;
private String deptName;
}

View File

@ -39,5 +39,6 @@
<groupId>com.jjb.saas</groupId> <groupId>com.jjb.saas</groupId>
<artifactId>jjb-saas-framework-facade</artifactId> <artifactId>jjb-saas-framework-facade</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -1,6 +1,7 @@
package com.zcloud.gbs.edgeguard.gatewayimpl; package com.zcloud.gbs.edgeguard.gatewayimpl;
import com.zcloud.gbs.edgeguard.domain.gateway.RegionCameraGateway; import com.zcloud.gbs.edgeguard.domain.gateway.RegionCameraGateway;
import com.zcloud.gbs.edgeguard.domain.model.CameraKeyE;
import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE; import com.zcloud.gbs.edgeguard.domain.model.RegionCameraE;
import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionCameraDO; import com.zcloud.gbs.edgeguard.persistence.dataobject.RegionCameraDO;
import com.zcloud.gbs.edgeguard.persistence.repository.RegionCameraRepository; import com.zcloud.gbs.edgeguard.persistence.repository.RegionCameraRepository;
@ -8,6 +9,13 @@ import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class RegionCameraGatewayImpl implements RegionCameraGateway { public class RegionCameraGatewayImpl implements RegionCameraGateway {
@ -41,6 +49,69 @@ public class RegionCameraGatewayImpl implements RegionCameraGateway {
.count() > 0; .count() > 0;
} }
@Override
public List<RegionCameraE> pageBound(Long regionId, String cameraName, String videoLevel,
Integer isOnline, int pageIndex, int pageSize) {
LambdaQueryWrapper<RegionCameraDO> wrapper = boundWrapper(regionId, cameraName, videoLevel, isOnline)
.orderByDesc(RegionCameraDO::getBoundTime).orderByDesc(RegionCameraDO::getId);
Page<RegionCameraDO> page = repository.page(new Page<>(pageIndex, pageSize), wrapper);
return toEntities(page.getRecords());
}
@Override
public long countBound(Long regionId, String cameraName, String videoLevel, Integer isOnline) {
return repository.count(boundWrapper(regionId, cameraName, videoLevel, isOnline));
}
@Override
public List<RegionCameraE> listBoundByRegionId(Long regionId) {
return toEntities(repository.lambdaQuery()
.eq(RegionCameraDO::getRegionId, regionId)
.eq(RegionCameraDO::getBindStatus, "BOUND")
.list());
}
@Override
public List<RegionCameraE> listByKeys(Long corpId, Collection<CameraKeyE> cameraKeys) {
if (cameraKeys == null || cameraKeys.isEmpty()) {
return Collections.emptyList();
}
LambdaQueryWrapper<RegionCameraDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RegionCameraDO::getCorpId, corpId);
wrapper.and(group -> {
boolean first = true;
for (CameraKeyE key : cameraKeys) {
if (first) {
group.eq(RegionCameraDO::getCameraSource, key.getCameraSource())
.eq(RegionCameraDO::getCameraId, key.getCameraId());
first = false;
} else {
group.or(nested -> nested.eq(RegionCameraDO::getCameraSource, key.getCameraSource())
.eq(RegionCameraDO::getCameraId, key.getCameraId()));
}
}
});
return toEntities(repository.list(wrapper));
}
private LambdaQueryWrapper<RegionCameraDO> boundWrapper(Long regionId, String cameraName,
String videoLevel, Integer isOnline) {
return new LambdaQueryWrapper<RegionCameraDO>()
.eq(RegionCameraDO::getRegionId, regionId)
.eq(RegionCameraDO::getBindStatus, "BOUND")
.like(cameraName != null && !cameraName.trim().isEmpty(), RegionCameraDO::getCameraName, cameraName)
.eq(videoLevel != null && !videoLevel.trim().isEmpty(), RegionCameraDO::getVideoLevel, videoLevel)
.eq(isOnline != null, RegionCameraDO::getIsOnline, isOnline);
}
private List<RegionCameraE> toEntities(List<RegionCameraDO> rows) {
List<RegionCameraE> result = new ArrayList<>();
for (RegionCameraDO row : rows) {
result.add(toEntity(row));
}
return result;
}
private RegionCameraDO toDO(RegionCameraE source) { private RegionCameraDO toDO(RegionCameraE source) {
RegionCameraDO target = new RegionCameraDO(); RegionCameraDO target = new RegionCameraDO();
BeanUtils.copyProperties(source, target); BeanUtils.copyProperties(source, target);

View File

@ -58,6 +58,19 @@ public class RegionGatewayImpl implements RegionGateway {
return result; return result;
} }
@Override
public List<RegionE> listByIds(Collection<Long> ids) {
if (ids == null || ids.isEmpty()) {
return Collections.emptyList();
}
List<RegionDO> rows = repository.lambdaQuery().in(RegionDO::getId, ids).list();
List<RegionE> result = new ArrayList<>();
for (RegionDO row : rows) {
result.add(toEntity(row));
}
return result;
}
@Override @Override
public boolean existsSiblingName(Long corpId, Long parentId, String regionName, Long excludeId) { public boolean existsSiblingName(Long corpId, Long parentId, String regionName, Long excludeId) {
return repository.lambdaQuery() return repository.lambdaQuery()

View File

@ -1,51 +0,0 @@
package com.zcloud.gbs.edgeguard.gatewayimpl;
import com.zcloud.gbs.edgeguard.domain.gateway.RiskPointGateway;
import com.zcloud.gbs.edgeguard.domain.model.RiskPointE;
import com.zcloud.gbs.edgeguard.persistence.dataobject.RiskPointDO;
import com.zcloud.gbs.edgeguard.persistence.repository.RiskPointRepository;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.Arrays;
/**
*
*
* @author lin
*/
@Service
@AllArgsConstructor
public class RiskPointGatewayImpl implements RiskPointGateway {
private final RiskPointRepository riskPointRepository;
@Override
public Boolean add(RiskPointE riskPointE) {
RiskPointDO d = new RiskPointDO();
BeanUtils.copyProperties(riskPointE, d);
riskPointRepository.save(d);
return true;
}
@Override
public Boolean update(RiskPointE riskPointE) {
RiskPointDO d = new RiskPointDO();
BeanUtils.copyProperties(riskPointE, d);
riskPointRepository.updateById(d);
return true;
}
@Override
public Boolean deletedRiskPointById(Long id) {
return riskPointRepository.removeById(id);
}
@Override
public Boolean deletedRiskPointByIds(Long[] ids) {
return riskPointRepository.removeByIds(Arrays.asList(ids));
}
}

View File

@ -16,17 +16,19 @@ public class RegionCameraDO extends BaseDO {
private String cameraSource; private String cameraSource;
private String cameraId; private String cameraId;
private String cameraName; private String cameraName;
private String cameraUnitId; private String videoType;
private Long cameraUnitId;
private String cameraUnitName; private String cameraUnitName;
private String cameraTypeCode; private Long cameraDeptId;
private String cameraTypeName;
private String cameraLevelCode;
private String cameraLevelName;
private String cameraDeptId;
private String cameraDeptName; private String cameraDeptName;
private String onlineStatus; private String videoLevel;
private String cameraSnapshot; private String videoAddress;
private Date cameraSyncedAt; private Integer isOnline;
private String deviceModel;
private String deviceGbNumber;
private String cameraNumber;
private String longitude;
private String latitude;
private Long leaderUserId; private Long leaderUserId;
private String bindStatus; private String bindStatus;
private Date boundTime; private Date boundTime;

View File

@ -1,16 +0,0 @@
package com.zcloud.gbs.edgeguard.persistence.dataobject;
import com.baomidou.mybatisplus.annotation.TableName;
import com.jjb.saas.framework.repository.basedo.BaseDO;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("risk_point")
public class RiskPointDO extends BaseDO {
private String riskPointName;
private String deptName;
}

View File

@ -1,16 +0,0 @@
package com.zcloud.gbs.edgeguard.persistence.domainobject;
import com.baomidou.mybatisplus.annotation.TableName;
import com.jjb.saas.framework.repository.basedo.BaseDO;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("risk_point")
public class RiskPointDO extends BaseDO {
private String riskPointName;
private String deptName;
}

View File

@ -1,9 +0,0 @@
package com.zcloud.gbs.edgeguard.persistence.mapper;
import com.zcloud.gbs.edgeguard.persistence.dataobject.RiskPointDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface RiskPointMapper extends BaseMapper<RiskPointDO> {
}

View File

@ -1,15 +0,0 @@
package com.zcloud.gbs.edgeguard.persistence.repository;
import com.alibaba.cola.dto.PageResponse;
import com.zcloud.gbs.edgeguard.persistence.dataobject.RiskPointDO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jjb.saas.framework.repository.repo.BaseRepository;
import java.util.Map;
/**
* @author lin
*/
public interface RiskPointRepository extends BaseRepository<RiskPointDO> {
PageResponse<RiskPointDO> listRiskPointPage(Map<String,Object> parmas);
}

View File

@ -1,35 +0,0 @@
package com.zcloud.gbs.edgeguard.persistence.repository.impl;
import com.alibaba.cola.dto.PageResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.jjb.saas.framework.repository.common.PageHelper;
import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl;
import com.zcloud.gbs.edgeguard.persistence.dataobject.RiskPointDO;
import com.zcloud.gbs.edgeguard.persistence.mapper.RiskPointMapper;
import com.zcloud.gbs.edgeguard.persistence.repository.RiskPointRepository;
import com.zcloud.gbs.edgeguard.utils.PageQueryHelper;
import com.zcloud.gbs.edgeguard.utils.Query;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* @author lin
*/
@Service
@RequiredArgsConstructor
public class RiskPointRepositoryImpl extends BaseRepositoryImpl<RiskPointMapper, RiskPointDO> implements RiskPointRepository {
private final RiskPointMapper riskPointMapper;
@Override
public PageResponse<RiskPointDO> listRiskPointPage(Map<String, Object> parmas) {
IPage<RiskPointDO> iPage = new Query<RiskPointDO>().getPage(parmas);
QueryWrapper<RiskPointDO> queryWrapper = new QueryWrapper<>();
queryWrapper = PageQueryHelper.createPageQueryWrapper(queryWrapper, parmas);
queryWrapper.orderByDesc("create_time");
IPage<RiskPointDO> result = riskPointMapper.selectPage(iPage, queryWrapper);
return PageHelper.pageToResponse(result, result.getRecords());
}
}

View File

@ -42,17 +42,19 @@ CREATE TABLE `edgeguard_region_camera` (
`camera_source` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '摄像头来源系统编码', `camera_source` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '摄像头来源系统编码',
`camera_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '第三方摄像头唯一标识', `camera_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '第三方摄像头唯一标识',
`camera_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '摄像头名称缓存,第三方为权威数据源', `camera_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '摄像头名称缓存,第三方为权威数据源',
`camera_unit_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头所属单位第三方标识缓存', `video_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '视频类型快照',
`camera_unit_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头所属单位名称缓存', `camera_unit_id` bigint DEFAULT NULL COMMENT '所属单位ID快照',
`camera_type_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头类型编码缓存', `camera_unit_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '所属单位名称快照',
`camera_type_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头类型名称缓存', `camera_dept_id` bigint DEFAULT NULL COMMENT '主管部门ID快照',
`camera_level_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头等级编码缓存', `camera_dept_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '主管部门名称快照',
`camera_level_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头等级名称缓存', `video_level` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '视频等级快照',
`camera_dept_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头主管部门第三方标识缓存', `video_address` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '视频地址快照',
`camera_dept_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头主管部门名称缓存', `is_online` int DEFAULT NULL COMMENT '在线状态0离线1在线',
`online_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '在线状态缓存ONLINE/OFFLINE/UNKNOWN', `device_model` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '规格型号快照',
`camera_snapshot` json DEFAULT NULL COMMENT '第三方摄像头扩展字段快照', `device_gb_number` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '设备国标编号快照',
`camera_synced_at` datetime DEFAULT NULL COMMENT '摄像头缓存最近同步时间', `camera_number` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '摄像头编号快照',
`longitude` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '经度快照',
`latitude` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '纬度快照',
`leader_user_id` bigint DEFAULT NULL COMMENT '摄像头负责人用户id', `leader_user_id` bigint DEFAULT NULL COMMENT '摄像头负责人用户id',
`bind_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'BOUND' COMMENT '绑定状态BOUND/UNBOUND', `bind_status` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT 'BOUND' COMMENT '绑定状态BOUND/UNBOUND',
`bound_time` datetime NOT NULL COMMENT '最近绑定时间', `bound_time` datetime NOT NULL COMMENT '最近绑定时间',
@ -70,10 +72,10 @@ CREATE TABLE `edgeguard_region_camera` (
`update_id` bigint DEFAULT NULL COMMENT '修改人id', `update_id` bigint DEFAULT NULL COMMENT '修改人id',
`env` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境标识', `env` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '环境标识',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uk_camera_source_id` (`camera_source`, `camera_id`), UNIQUE KEY `uk_camera_source_id` (`tenant_id`, `camera_source`, `camera_id`),
KEY `idx_region_camera` (`tenant_id`, `region_id`, `bind_status`, `delete_enum`), KEY `idx_region_camera` (`tenant_id`, `region_id`, `bind_status`, `delete_enum`),
KEY `idx_camera_corp` (`tenant_id`, `corp_id`, `delete_enum`), KEY `idx_camera_corp` (`tenant_id`, `corp_id`, `delete_enum`),
KEY `idx_camera_filter` (`tenant_id`, `region_id`, `camera_level_code`, `online_status`, `delete_enum`), KEY `idx_camera_filter` (`tenant_id`, `region_id`, `bind_status`, `video_level`, `is_online`, `delete_enum`),
KEY `idx_camera_name` (`camera_name`), KEY `idx_camera_name` (`camera_name`),
KEY `idx_camera_leader` (`leader_user_id`) KEY `idx_camera_leader` (`leader_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='区域与第三方摄像头绑定表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='区域与第三方摄像头绑定表';

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zcloud.gbs.edgeguard.persistence.mapper.RiskPointMapper">
</mapper>

View File

@ -157,13 +157,16 @@ nodeType = REGION 本地区域节点
| `camera_source` | `varchar(64)` | 摄像头来源系统编码 | | `camera_source` | `varchar(64)` | 摄像头来源系统编码 |
| `camera_id` | `varchar(128)` | 第三方摄像头唯一标识 | | `camera_id` | `varchar(128)` | 第三方摄像头唯一标识 |
| `camera_name` | `varchar(255)` | 摄像头名称缓存 | | `camera_name` | `varchar(255)` | 摄像头名称缓存 |
| `camera_unit_id/name` | `varchar` | 所属单位标识及名称缓存 | | `video_type` | `varchar(64)` | 视频类型快照 |
| `camera_type_code/name` | `varchar` | 类型编码及名称缓存 | | `camera_unit_id/name` | `bigint/varchar` | 所属单位及名称快照 |
| `camera_level_code/name` | `varchar` | 等级编码及名称缓存 | | `camera_dept_id/name` | `bigint/varchar` | 主管部门及名称快照 |
| `camera_dept_id/name` | `varchar` | 主管部门标识及名称缓存 | | `video_level` | `varchar(64)` | 视频等级快照 |
| `online_status` | `varchar(32)` | 在线状态缓存 | | `video_address` | `varchar(1000)` | 视频地址快照 |
| `camera_snapshot` | `json` | 第三方其他扩展字段快照 | | `is_online` | `int` | 在线状态快照 |
| `camera_synced_at` | `datetime` | 缓存最近同步时间 | | `device_model` | `varchar(255)` | 规格型号快照 |
| `device_gb_number` | `varchar(128)` | 设备国标编号快照 |
| `camera_number` | `varchar(128)` | 摄像头编号快照 |
| `longitude/latitude` | `varchar(64)` | 经纬度快照 |
| `leader_user_id` | `bigint` | 摄像头负责人用户 ID | | `leader_user_id` | `bigint` | 摄像头负责人用户 ID |
| `bind_status` | `varchar(32)` | `BOUND/UNBOUND`,若逻辑删除足够可不单设 | | `bind_status` | `varchar(32)` | `BOUND/UNBOUND`,若逻辑删除足够可不单设 |
| `bound_time` | `datetime` | 绑定时间 | | `bound_time` | `datetime` | 绑定时间 |
@ -174,7 +177,7 @@ nodeType = REGION 本地区域节点
- 区域列表索引:`tenant_id + region_id + delete_enum`。 - 区域列表索引:`tenant_id + region_id + delete_enum`。
- 摄像头负责人索引:`leader_user_id`,仅在需要按负责人查询时增加。 - 摄像头负责人索引:`leader_user_id`,仅在需要按负责人查询时增加。
当前只缓存已经绑定的摄像头,因此展示字段直接放在绑定表中即可。如果后续要求缓存全部第三方摄像头、未绑定摄像头也要离线搜索,或一个摄像头允许绑定多个区域,则应拆分为“摄像头缓存表 + 区域摄像头关系表”。 当前只缓存已绑定摄像头的 `FixedCameraCO` 业务展示字段,权威主数据仍由视频巡检服务维护。如果后续要求缓存全部摄像头或一个摄像头允许绑定多个区域,再拆分为“摄像头缓存表 + 区域摄像头关系表”。
## 5. 页面功能拆解 ## 5. 页面功能拆解
@ -432,14 +435,14 @@ OR
| 编号 | 方法与路径 | 用途 | 主要入参 | 主要返回 | 核心规则 | 优先级 | | 编号 | 方法与路径 | 用途 | 主要入参 | 主要返回 | 核心规则 | 优先级 |
| --- | --- | --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- | --- | --- |
| `CAMERA-01` | `POST /edgeguard/region-cameras/page` | 查询区域已绑定摄像头 | `RegionCameraPageQry` | `PageResponse<RegionCameraCo>` | 必须传 `regionId`;从本地快照分页;支持名称、等级、在线状态;负责人批量翻译 | P0 | | `CAMERA-01` | `POST /edgeguard/region-cameras/page` | 查询区域已绑定摄像头 | `RegionCameraPageQry` | `PageResponse<RegionCameraCo>` | 必须传 `regionId`;从本地快照分页;支持名称、等级和在线状态筛选;负责人批量翻译 | P0 |
| `CAMERA-02` | `POST /edgeguard/region-cameras/candidates/page` | 查询第三方可选摄像头 | `CameraCandidatePageQry` | `PageResponse<CameraCandidateCo>` | 通过 Infrastructure Gateway 调第三方;标记未绑定、已绑定当前区域、已绑定其他区域 | P0依赖第三方契约 | | `CAMERA-02` | `POST /videopatrol/fixedCamera/list` | 查询可选摄像头 | 视频巡检 `FixedCameraPageQry` | 视频巡检 `FixedCameraCO` 分页 | 前端直接调用视频巡检服务,本服务不重复提供接口;`pageSize` 不使用 1000 | P0外部前端依赖 |
| `CAMERA-03` | `PUT /edgeguard/regions/{regionId}/cameras` | 保存区域摄像头选择结果 | `regionId + RegionCameraBindCmd` | `Response` | 入参提交选中的 `cameraSource + cameraId`;服务端重新查询权威数据;计算新增和解绑差异并在本地事务保存;重复提交幂等 | P0依赖第三方契约 | | `CAMERA-03` | `PUT /edgeguard/regions/{regionId}/cameras` | 保存区域摄像头选择结果 | `regionId + RegionCameraBindCmd` | `Response` | 入参字段与 `FixedCameraCO` 对齐;校验所属企业;保存展示快照并计算绑定差异;重复提交幂等 | P0 |
| `CAMERA-04` | `PUT /edgeguard/region-cameras/{id}/leader` | 设置摄像头负责人 | `id + CameraLeaderUpdateCmd` | `Response` | 负责人必须为有效用户;只修改当前有效绑定 | P0 | | `CAMERA-04` | `PUT /edgeguard/region-cameras/{id}/leader` | 设置摄像头负责人 | `id + CameraLeaderUpdateCmd` | `Response` | 负责人必须为有效用户;只修改当前有效绑定 | P0 |
| `CAMERA-05` | `DELETE /edgeguard/region-cameras/{id}` | 解除摄像头绑定 | `id` | `Response` | 只解除本地关系,不删除第三方摄像头;写入 `UNBOUND/unboundTime` | P0 | | `CAMERA-05` | `DELETE /edgeguard/region-cameras/{id}` | 解除摄像头绑定 | `id` | `Response` | 只解除本地关系,不删除第三方摄像头;写入 `UNBOUND/unboundTime` | P0 |
| `CAMERA-06` | `GET /edgeguard/region-cameras/{id}` | 查看摄像头详情 | `id` | `SingleResponse<RegionCameraCo>` | 优先查询第三方实时详情;失败时返回本地快照并明确 `snapshot=true` | P1依赖第三方契约 | | `CAMERA-06` | `GET /edgeguard/region-cameras/{id}` | 查看摄像头详情 | `id` | `SingleResponse<RegionCameraCo>` | 优先查询第三方实时详情;失败时返回本地快照并明确 `snapshot=true` | P1依赖第三方契约 |
`RegionCameraPageQry` 至少包含 `regionId`,可选 `cameraName/cameraLevelCode/onlineStatus`。摄像头选择接口的分页字段和筛选能力最终以第三方接口能力为准。 `RegionCameraPageQry` 至少包含 `regionId`,可选 `name`。可选摄像头分页参数以视频巡检服务的 `FixedCameraPageQry` 为准。
### 11.4 第三方区域开放接口 ### 11.4 第三方区域开放接口
@ -465,7 +468,7 @@ OR
`AlarmReceiveCmd` 当前确认字段: `AlarmReceiveCmd` 当前确认字段:
- `sourceSystem`、`alarmNo`、`alarmTime`、`alarmAddress`。 - `sourceSystem`、`alarmNo`、`alarmTime`、`alarmAddress`。
- `cameraSource`、`cameraId`、`cameraName` - `fixedCameraId`、`videoName`、`videoType`、所属单位、主管部门、视频等级、在线状态和摄像头编号等 `FixedCameraCO` 字段
- `regionCode`(第三方可传,但最终以本地摄像头绑定匹配结果校验)。 - `regionCode`(第三方可传,但最终以本地摄像头绑定匹配结果校验)。
- `alarmImageUrl` - `alarmImageUrl`
@ -513,7 +516,7 @@ OR
| 依赖 | 使用接口 | 当前状态 | 开发前需要确认 | | 依赖 | 使用接口 | 当前状态 | 开发前需要确认 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| 企业/用户公共服务 | `REGION-01~04`、`CAMERA-04`、统计展示 | 已有公共能力 | 企业数据权限来源、负责人有效性校验和批量翻译字段 | | 企业/用户公共服务 | `REGION-01~04`、`CAMERA-04`、统计展示 | 已有公共能力 | 企业数据权限来源、负责人有效性校验和批量翻译字段 |
| 第三方摄像头服务 | `CAMERA-02/03/06` | 契约待提供 | 协议、分页报文、筛选字段、唯一 ID、详情接口、超时和错误码 | | 视频巡检固定摄像头分页 | `CAMERA-02` | 已确认 | 前端调用 `POST /videopatrol/fixedCamera/list`,普通分页时返回 `FixedCameraCO` |
| 第三方报警平台 | `ALARM-01` | 契约待联调 | JSON 报文、鉴权签名、重试策略、截图 URL 有效期、区域/摄像头无法匹配时的处理 | | 第三方报警平台 | `ALARM-01` | 契约待联调 | JSON 报文、鉴权签名、重试策略、截图 URL 有效期、区域/摄像头无法匹配时的处理 |
| 隐患服务 `ZcloudHiddenFacade` | `ALARM-04/05` | Common 已有能力 | `HiddenAddCmd` 必填字段、返回的隐患 ID、幂等行为、失败错误码 | | 隐患服务 `ZcloudHiddenFacade` | `ALARM-04/05` | Common 已有能力 | `HiddenAddCmd` 必填字段、返回的隐患 ID、幂等行为、失败错误码 |
@ -524,7 +527,7 @@ OR
| 开发批次 | 接口 | 当前状态 | 原因 | | 开发批次 | 接口 | 当前状态 | 原因 |
| --- | --- | --- | --- | | --- | --- | --- | --- |
| 第1批区域闭环 | `REGION-01~05` | `DOING` | 分层实现、校验、测试及编译已完成;待菜单资源分配真实权限编码后转 `DONE` | | 第1批区域闭环 | `REGION-01~05` | `DOING` | 分层实现、校验、测试及编译已完成;待菜单资源分配真实权限编码后转 `DONE` |
| 第2批摄像头绑定 | `CAMERA-01~05` | `TODO` | 本地绑定可开发;候选和保存快照依赖第三方摄像头契约 | | 第2批摄像头绑定 | `CAMERA-01~05` | `DOING` | 前端复用视频巡检固定摄像头分页;本服务已完成快照保存、负责人、解绑及绑定差异逻辑;待配置菜单权限编码 |
| 第3批报警与统计 | `ALARM-01~04`、`STAT-01~02` | `TODO` | 统计需求和下钻行为已由原型确认;与报警主流程同批开发、联调 | | 第3批报警与统计 | `ALARM-01~04`、`STAT-01~02` | `TODO` | 统计需求和下钻行为已由原型确认;与报警主流程同批开发、联调 |
| 第4批开放查询 | `OPEN-REGION-01~04` | `TODO` | 需先确认第三方实际需要和开放鉴权方案 | | 第4批开放查询 | `OPEN-REGION-01~04` | `TODO` | 需先确认第三方实际需要和开放鉴权方案 |
| 第5批增强能力 | `CAMERA-06`、`ALARM-05` | `TODO` | 实时详情降级和隐患失败重试 | | 第5批增强能力 | `CAMERA-06`、`ALARM-05` | `TODO` | 实时详情降级和隐患失败重试 |