diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/AdminApplication.java b/sz-service/sz-service-admin/src/main/java/com/sz/AdminApplication.java index 8b44e30..1a6e1d3 100644 --- a/sz-service/sz-service-admin/src/main/java/com/sz/AdminApplication.java +++ b/sz-service/sz-service-admin/src/main/java/com/sz/AdminApplication.java @@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.scheduling.annotation.EnableScheduling; diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/listener/event/CameraDeleteEventListener.java b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/listener/event/CameraDeleteEventListener.java new file mode 100644 index 0000000..82ee331 --- /dev/null +++ b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/listener/event/CameraDeleteEventListener.java @@ -0,0 +1,105 @@ +package com.sz.admin.monitor.listener.event; + +import com.sz.admin.monitor.listener.mode.CameraDeleteEvent; +import com.sz.admin.monitor.mapper.EdgeBoxMapper; +import com.sz.admin.monitor.pojo.po.Camera; +import com.sz.admin.monitor.pojo.po.EdgeBox; +import com.sz.admin.monitor.pojo.vo.edgebox.AlgorithmTaskVO; +import com.sz.admin.monitor.service.AlgorithmTaskService; +import com.sz.admin.monitor.service.CameraService; +import com.sz.admin.monitor.service.impl.CameraServiceImpl; +import com.sz.admin.monitor.utils.AiBoxRequestUtil; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * ClassName: CameraDeleteEventListener + * Package: com.sz.admin.monitor.listener.event + * Description: + */ +@Component +@Slf4j +public class CameraDeleteEventListener { + @Resource + private CameraService cameraService; + @Resource + private AlgorithmTaskService algorithmTaskService; + @Resource + private EdgeBoxMapper edgeBoxMapper; + @Resource + private AiBoxRequestUtil aiBoxRequestUtil; + + @EventListener + @Async + public void handleCameraDelete(CameraDeleteEvent event) { + List ids = event.getCameraIds(); + try { + List cameraList = cameraService.listByIds(ids); + if (cameraList.isEmpty()) return; + List taskList = algorithmTaskService.listByCameraIds(ids); + // 一次性查询出这批摄像头管理的盒子 + Set boxIdset = cameraList + .stream() + .map(Camera::getBoxId) + .collect(Collectors.toSet()); + Map boxMap=new HashMap<>(); + if(!boxIdset.isEmpty()) + { + List edgeBoxList = edgeBoxMapper.selectListByIds(boxIdset); + boxMap = edgeBoxList.stream().collect(Collectors.toMap(EdgeBox::getId, edgeBox -> edgeBox)); + } + try { + // 批量删除本地数据 + cameraService.batchDeleteLocalData(ids, taskList); + } catch (Exception e) { + log.error("本地数据库删除失败,中止后续硬件清理逻辑以防数据割裂!", e); + return; + } + // 清理盒子的算法任务 + for (AlgorithmTaskVO task : taskList) { + if(task!=null && task.getAlgTaskSession()!=null) + { + Camera camera = cameraList.stream().filter(c -> c.getId().equals(task.getCameraId())) + .findFirst() + .orElse(null); + if(camera==null) continue; + EdgeBox edgeBox = boxMap.get(camera.getBoxId()); + if(edgeBox==null) continue; + try { + aiBoxRequestUtil.controlTask(edgeBox.getIp(), edgeBox.getPort(), task.getAlgTaskSession(), 0); + aiBoxRequestUtil.deleteTask(edgeBox.getIp(), edgeBox.getPort(), task.getAlgTaskSession()); + } catch (Exception e) { + log.error("清理 AI 盒子任务失败,摄像机ID: {}, 忽略该错误继续执行...", task.getCameraId(), e); + } + } + } + // 清理盒子的通道 + for (Camera camera : cameraList) { + Long boxId = camera.getBoxId(); + if (boxId == null) continue; + EdgeBox edgeBox = boxMap.get(boxId); + if (edgeBox == null) continue; + try { + aiBoxRequestUtil.deleteVideoChannel(edgeBox.getIp(), edgeBox.getPort(), camera.getId().toString()); + } catch (Exception e) { + log.error("清理 AI 盒子视频通道失败,摄像机ID: {}", camera.getId(), e); + } + } + + } + catch (Exception e) + { + e.printStackTrace(); + } + } + +} diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/listener/mode/CameraDeleteEvent.java b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/listener/mode/CameraDeleteEvent.java new file mode 100644 index 0000000..da07165 --- /dev/null +++ b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/listener/mode/CameraDeleteEvent.java @@ -0,0 +1,18 @@ +package com.sz.admin.monitor.listener.mode; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +/** + * ClassName: CameraDeleteEvent + * Package: com.sz.admin.monitor.listener.mode + * Description: + */ +@Data +@AllArgsConstructor +public class CameraDeleteEvent { + // 携带需要删除的摄像头 ID 集合 + private List cameraIds; +} diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/AlgorithmTask.java b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/AlgorithmTask.java index b941a71..c109e73 100644 --- a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/AlgorithmTask.java +++ b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/AlgorithmTask.java @@ -74,7 +74,7 @@ public class AlgorithmTask implements Serializable { /** * 逻辑删除标识:0-正常,1-已删除 */ - @Column(isLogicDelete = true) + // @Column(isLogicDelete = true) @Schema(description = "是否删除") private String isDeleted; diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/Camera.java b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/Camera.java index 0f0c7d6..314cfef 100644 --- a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/Camera.java +++ b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/Camera.java @@ -82,7 +82,7 @@ public class Camera implements Serializable { /** * 逻辑删除标识:0-正常,1-已删除 */ - @Column(isLogicDelete = true) + // @Column(isLogicDelete = true) @Schema(description = "是否删除") private String isDeleted; diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/CameraSnapshot.java b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/CameraSnapshot.java index 80e482c..a881565 100644 --- a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/CameraSnapshot.java +++ b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/CameraSnapshot.java @@ -48,7 +48,7 @@ public class CameraSnapshot implements Serializable { /** * 逻辑删除标识:0-正常,1-已删除 */ - @Column(isLogicDelete = true) + // @Column(isLogicDelete = true) @Schema(description = "是否删除") private String isDeleted; diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/Preset.java b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/Preset.java index 153e786..9fc230d 100644 --- a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/Preset.java +++ b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/pojo/po/Preset.java @@ -47,7 +47,7 @@ public class Preset { /** * 逻辑删除标识:0-正常,1-已删除 */ - @Column(isLogicDelete = true) + // @Column(isLogicDelete = true) @Schema(description = "是否删除") private String isDeleted; diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/service/impl/CameraServiceImpl.java b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/service/impl/CameraServiceImpl.java index 6ca3295..2e4517b 100644 --- a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/service/impl/CameraServiceImpl.java +++ b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/service/impl/CameraServiceImpl.java @@ -1,34 +1,23 @@ package com.sz.admin.monitor.service.impl; -import com.alibaba.fastjson.JSONObject; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import com.mybatisflex.core.logicdelete.LogicDeleteManager; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.spring.service.impl.ServiceImpl; -import com.sz.admin.monitor.enums.HKPTZPreEnum; +import com.sz.admin.monitor.listener.mode.CameraDeleteEvent; import com.sz.admin.monitor.mapper.*; import com.sz.admin.monitor.pojo.dto.camera.CameraListDTO; import com.sz.admin.monitor.pojo.dto.camera.CameraUpdateDTO; -import com.sz.admin.monitor.pojo.po.AlgorithmTask; import com.sz.admin.monitor.pojo.po.Camera; import com.sz.admin.monitor.pojo.po.EdgeBox; import com.sz.admin.monitor.pojo.po.Nvr; import com.sz.admin.monitor.pojo.po.table.CameraTableDef; import com.sz.admin.monitor.pojo.vo.camera.CameraVO; -import com.sz.admin.monitor.pojo.vo.camerasnapshot.CameraSnapshotVO; import com.sz.admin.monitor.pojo.vo.edgebox.AlgorithmTaskVO; -import com.sz.admin.monitor.pojo.vo.preset.PresetVO; -import com.sz.admin.monitor.sdk.ManageNVR; -import com.sz.admin.monitor.enums.HCPlayControlEnum; -import com.sz.admin.monitor.service.*; +import com.sz.admin.monitor.service.AlgorithmTaskService; +import com.sz.admin.monitor.service.CameraService; import com.sz.admin.monitor.utils.AiBoxRequestUtil; import com.sz.admin.monitor.utils.RtspUtil; -import com.sz.admin.monitor.utils.ZLMediaKitUtils; -import com.sz.admin.teacher.pojo.po.TeacherStatistics; -import com.sz.admin.teacher.pojo.vo.TeacherStatisticsVO; import com.sz.core.common.entity.PageResult; import com.sz.core.common.entity.SelectIdsDTO; import com.sz.core.common.enums.CommonResponseEnum; @@ -38,10 +27,10 @@ import com.sz.core.util.BeanCopyUtils; import com.sz.core.util.PageUtils; import com.sz.core.util.Utils; import com.sz.platform.enums.AdminResponseEnum; -import com.sz.security.core.util.LoginUtils; import jakarta.annotation.Resource; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -49,7 +38,6 @@ import org.springframework.transaction.annotation.Transactional; import java.io.Serializable; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import static com.sz.admin.monitor.pojo.po.table.NvrTableDef.NVR; @@ -75,6 +63,8 @@ public class CameraServiceImpl extends ServiceImpl impleme private AiBoxRequestUtil aiBoxRequestUtil; @Resource private EdgeBoxMapper edgeBoxMapper; + @Resource + private ApplicationEventPublisher applicationEventPublisher; // 自己注入自己 @Resource @Lazy @@ -136,37 +126,45 @@ public class CameraServiceImpl extends ServiceImpl impleme } } @Override + @Transactional(rollbackFor = Exception.class) public void remove(SelectIdsDTO dto) { CommonResponseEnum.INVALID_ID.assertTrue(dto.getIds().isEmpty()); List cameraList = listByIds(dto.getIds()); if (cameraList.isEmpty()) { return; } - List taskList = algorithmTaskService.listByCameraIds(dto.getIds()); - for (AlgorithmTaskVO task : taskList) { - if (task != null && task.getAlgTaskSession() != null) { - try { - Long cameraId = task.getCameraId(); - Camera camera = this.getById(cameraId); - Long boxId = camera.getBoxId(); - EdgeBox edgeBox = edgeBoxMapper.selectOneById(boxId); - // 删除任务 - aiBoxRequestUtil.controlTask(edgeBox.getIp(), edgeBox.getPort(), task.getAlgTaskSession(), 0); - aiBoxRequestUtil.deleteTask(edgeBox.getIp(), edgeBox.getPort(), task.getAlgTaskSession()); - } catch (Exception e) { - log.error("清理 AI 盒子任务失败,摄像机ID: {}, Session: {}", task.getCameraId(), task.getAlgTaskSession(), e); - throw new BusinessException(AdminResponseEnum.OPERATION_FAIL,null,"同步清理设备算法任务失败,请检查网络后重试"); - } - } - } - for (Camera camera : cameraList) { - // 删除通道 - Long boxId = camera.getBoxId(); - EdgeBox edgeBox = edgeBoxMapper.selectOneById(boxId); - aiBoxRequestUtil.deleteVideoChannel(edgeBox.getIp(), edgeBox.getPort(), camera.getId().toString()); - } - cameraService.batchDeleteLocalData(dto.getIds(), taskList); + // 直接删除摄像头 + cameraMapper.deleteBatchByIds(dto.getIds()); + // 发布事件 + applicationEventPublisher.publishEvent(new CameraDeleteEvent((List) dto.getIds())); +// List taskList = algorithmTaskService.listByCameraIds(dto.getIds()); +// for (AlgorithmTaskVO task : taskList) { +// if (task != null && task.getAlgTaskSession() != null) { +// try { +// Long cameraId = task.getCameraId(); +// Camera camera = this.getById(cameraId); +// Long boxId = camera.getBoxId(); +// EdgeBox edgeBox = edgeBoxMapper.selectOneById(boxId); +// // 删除任务 +// aiBoxRequestUtil.controlTask(edgeBox.getIp(), edgeBox.getPort(), task.getAlgTaskSession(), 0); +// aiBoxRequestUtil.deleteTask(edgeBox.getIp(), edgeBox.getPort(), task.getAlgTaskSession()); +// } catch (Exception e) { +// log.error("清理 AI 盒子任务失败,摄像机ID: {}, Session: {}", task.getCameraId(), task.getAlgTaskSession(), e); +// throw new BusinessException(AdminResponseEnum.OPERATION_FAIL,null,"同步清理设备算法任务失败,请检查网络后重试"); +// } +// } +// } +// for (Camera camera : cameraList) { +// // 删除通道 +// Long boxId = camera.getBoxId(); +// if (boxId == null) +// continue; +// EdgeBox edgeBox = edgeBoxMapper.selectOneById(boxId); +// aiBoxRequestUtil.deleteVideoChannel(edgeBox.getIp(), edgeBox.getPort(), camera.getId().toString()); +// } +// cameraService.batchDeleteLocalData(dto.getIds(), taskList); } + @Transactional(rollbackFor = Exception.class) public void batchDeleteLocalData(List cameraIds, List taskList) { // 1. 批量删除预置位 diff --git a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/utils/AiBoxRequestUtil.java b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/utils/AiBoxRequestUtil.java index 0db41ce..4c149f2 100644 --- a/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/utils/AiBoxRequestUtil.java +++ b/sz-service/sz-service-admin/src/main/java/com/sz/admin/monitor/utils/AiBoxRequestUtil.java @@ -96,7 +96,6 @@ public class AiBoxRequestUtil { JSONObject responseJSON = new JSONObject(); responseJSON.put("code", CommonResponseEnum.MEDIA_HTTP_FAIL.getCode()); responseJSON.put("msg", CommonResponseEnum.MEDIA_HTTP_FAIL.getMessage()); - MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8"); String jsonString = ""; if (param != null) {