diff --git a/ruoyi-api/property-api/src/main/java/org/dromara/property/api/RemoteAttendanceService.java b/ruoyi-api/property-api/src/main/java/org/dromara/property/api/RemoteAttendanceService.java index 94e6e2a8..fb1a0bbe 100644 --- a/ruoyi-api/property-api/src/main/java/org/dromara/property/api/RemoteAttendanceService.java +++ b/ruoyi-api/property-api/src/main/java/org/dromara/property/api/RemoteAttendanceService.java @@ -18,6 +18,15 @@ public interface RemoteAttendanceService { * @param date 查询时间 * @return 返回排班人员信息 */ - public List queryAttendPersonInfo(Date date); + List queryAttendPersonInfo(Date date); + + /** + * 根据时间和设备ip查询当前设备所处区域的排班人员信息 + * + * @param date 查询时间 + * @param deviceIp 设备ip + * @return 返回排班人员信息 + */ + List queryAttendByCurrDateAndDeviceIp(Date date, String deviceIp); } diff --git a/ruoyi-api/property-api/src/main/java/org/dromara/property/api/domain/vo/RemoteAttendanceUserGroupVo.java b/ruoyi-api/property-api/src/main/java/org/dromara/property/api/domain/vo/RemoteAttendanceUserGroupVo.java index 1146533a..1916b5d1 100644 --- a/ruoyi-api/property-api/src/main/java/org/dromara/property/api/domain/vo/RemoteAttendanceUserGroupVo.java +++ b/ruoyi-api/property-api/src/main/java/org/dromara/property/api/domain/vo/RemoteAttendanceUserGroupVo.java @@ -49,5 +49,4 @@ public class RemoteAttendanceUserGroupVo implements Serializable { */ private LocalDate endDate; - } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/smartDevicesController/TbMeterInfoController.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/smartDevicesController/TbMeterInfoController.java index df9b6d17..967996d2 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/smartDevicesController/TbMeterInfoController.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/controller/smartDevicesController/TbMeterInfoController.java @@ -28,7 +28,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; * 前端访问路由地址为:/property/meterInfo * * @author lsm - * @date 2025-07-19 + * @since 2025-07-19 */ @Validated @RequiredArgsConstructor @@ -66,7 +66,7 @@ public class TbMeterInfoController extends BaseController { @SaCheckPermission("property:meterInfo:query") @GetMapping("/{id}") public R getInfo(@NotNull(message = "主键不能为空") - @PathVariable("id") Long id) { + @PathVariable("id") Long id) { return R.ok(tbMeterInfoService.queryById(id)); } @@ -109,12 +109,24 @@ public class TbMeterInfoController extends BaseController { * 生成 社区/建组/单元/楼栋/(水电气表)树结构 * * @param meterType 水电气类型 - * + * @param isMeter 是否返回仪表 * @return (水电气表)树结构 */ - @GetMapping("/tree/{meterType}") - public R>> queryMeterInfoTree(@PathVariable("meterType") Long meterType) { - return R.ok(tbMeterInfoService.queryMeterInfoTree(meterType)); + @GetMapping("/tree") + public R>> queryMeterInfoTree(@RequestParam Long meterType, @RequestParam Boolean isMeter) { + return R.ok(tbMeterInfoService.queryMeterInfoTree(meterType, isMeter)); + } + + /** + * 获取水/电/气表当前读数/状态 + * + * @param meterType 水电气类型 + * @param floorId 楼栋id + */ + @GetMapping("/currentReading") + public R currentReading(@RequestParam Long meterType, @RequestParam Long floorId) { + tbMeterInfoService.getMeterStatus(meterType, floorId); + return R.ok(); } } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/ServiceWorkOrdersType.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/ServiceWorkOrdersType.java index 118998aa..7dd4c22c 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/ServiceWorkOrdersType.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/ServiceWorkOrdersType.java @@ -41,6 +41,10 @@ public class ServiceWorkOrdersType extends TenantEntity { * 运作模式(0派单+抢单,1派单,2自动派单) */ private String operationMode; + /** + *部门id + */ + private Long deptId; /** * 排序值 diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/bo/ServiceWorkOrdersTypeBo.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/bo/ServiceWorkOrdersTypeBo.java index a9a15f6c..5e97ec4b 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/bo/ServiceWorkOrdersTypeBo.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/bo/ServiceWorkOrdersTypeBo.java @@ -36,7 +36,11 @@ public class ServiceWorkOrdersTypeBo extends BaseEntity { */ @NotNull(message = "工单类型名称不能为空", groups = { AddGroup.class, EditGroup.class }) private String orderTypeName; - + /** + *部门id + */ + @NotNull(message = "部门id", groups = { EditGroup.class }) + private Long deptId; /** * 运作模式 */ diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/ServiceWorkOrdersTypeVo.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/ServiceWorkOrdersTypeVo.java index 9b44e8a4..ec128904 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/ServiceWorkOrdersTypeVo.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/domain/vo/ServiceWorkOrdersTypeVo.java @@ -44,6 +44,14 @@ public class ServiceWorkOrdersTypeVo implements Serializable { */ @ExcelProperty(value = "工单类型名称") private String orderTypeName; + /** + *部门id + */ + private Long deptId; + /** + *部门名称 + */ + private String deptName; /** * 运作模式 diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/dubbo/RemoteAttendanceServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/dubbo/RemoteAttendanceServiceImpl.java index 0acb754b..060749d7 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/dubbo/RemoteAttendanceServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/dubbo/RemoteAttendanceServiceImpl.java @@ -6,7 +6,9 @@ import lombok.RequiredArgsConstructor; import org.apache.dubbo.config.annotation.DubboService; import org.dromara.property.api.RemoteAttendanceService; import org.dromara.property.api.domain.vo.RemoteAttendanceUserGroupVo; +import org.dromara.property.domain.vo.attendanceVo.AttendanceAreaDeviceVo; import org.dromara.property.domain.vo.attendanceVo.AttendanceUserGroupVo; +import org.dromara.property.service.attendanceService.IAttendanceAreaDeviceService; import org.dromara.property.service.attendanceService.IAttendanceUserGroupService; import java.util.Date; @@ -23,6 +25,7 @@ public class RemoteAttendanceServiceImpl implements RemoteAttendanceService { private final IAttendanceUserGroupService attendanceUserGroupService; + private final IAttendanceAreaDeviceService attendanceAreaDeviceService; public List queryAttendPersonInfo(Date date) { @@ -33,4 +36,12 @@ public class RemoteAttendanceServiceImpl implements RemoteAttendanceService { return null; } + @Override + public List queryAttendByCurrDateAndDeviceIp(Date date, String deviceIp) { + List ls = attendanceUserGroupService.queryAttendByCurrDateAndDeviceIp(date, deviceIp); + if (CollUtil.isNotEmpty(ls)) { + return BeanUtil.copyToList(ls, RemoteAttendanceUserGroupVo.class); + } + return null; + } } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/mapper/attendanceMapper/AttendanceUserGroupMapper.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/mapper/attendanceMapper/AttendanceUserGroupMapper.java index 209320db..69076ad5 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/mapper/attendanceMapper/AttendanceUserGroupMapper.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/mapper/attendanceMapper/AttendanceUserGroupMapper.java @@ -1,8 +1,12 @@ package org.dromara.property.mapper.attendanceMapper; +import org.apache.ibatis.annotations.Param; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; import org.dromara.property.domain.AttendanceUserGroup; import org.dromara.property.domain.vo.attendanceVo.AttendanceUserGroupVo; -import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +import java.util.Date; +import java.util.List; /** * 排班明细Mapper接口 @@ -12,4 +16,12 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; */ public interface AttendanceUserGroupMapper extends BaseMapperPlus { + /** + * 根据日期和设备ip 查询当前设备所在区域的排班人员信息 + * + * @param date 查询日期 + * @param deviceIp 设备ip + * @return 返回排班人员列表 + */ + List queryAttendByCurrDateAndDeviceIp(@Param("currDate") Date currDate, @Param("deviceIp") String deviceIp); } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/attendanceService/IAttendanceAreaDeviceService.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/attendanceService/IAttendanceAreaDeviceService.java index e230c275..0889ce12 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/attendanceService/IAttendanceAreaDeviceService.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/attendanceService/IAttendanceAreaDeviceService.java @@ -6,6 +6,7 @@ import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.PageQuery; import java.util.Collection; +import java.util.Date; import java.util.List; /** @@ -65,4 +66,5 @@ public interface IAttendanceAreaDeviceService { * @return 是否删除成功 */ Boolean deleteWithValidByIds(Collection ids, Boolean isValid); + } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/attendanceService/IAttendanceUserGroupService.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/attendanceService/IAttendanceUserGroupService.java index b3855ffa..c32e340b 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/attendanceService/IAttendanceUserGroupService.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/attendanceService/IAttendanceUserGroupService.java @@ -75,6 +75,15 @@ public interface IAttendanceUserGroupService { */ List queryAttendPersonInfo(Date date); + TableDataInfo queryScheduleView(AttendanceUserGroupBo bo, PageQuery pageQuery); + /** + * 根据日期和设备ip 查询当前设备所在区域的排班人员信息 + * + * @param date 查询日期 + * @param deviceIp 设备ip + * @return 返回排班人员列表 + */ + List queryAttendByCurrDateAndDeviceIp(Date date, String deviceIp); } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersServiceImpl.java index 623e7b85..6870bbc0 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersServiceImpl.java @@ -227,7 +227,7 @@ public class ServiceWorkOrdersServiceImpl implements IServiceWorkOrdersService { boolean flags = workOrdersRecordMapper.insert(serviceWorkOrdersRecord) > 0; if (flags) { if (serviceWorkOrdersType.getOperationMode().equals(OrderTypeOperationEnum.AUTOMATE_DISPATCH.getValue())) { - handleServiceWorkOrder(add); + handleServiceWorkOrder(add,serviceWorkOrdersType); } } } @@ -235,17 +235,19 @@ public class ServiceWorkOrdersServiceImpl implements IServiceWorkOrdersService { } //自动派单 - private void handleServiceWorkOrder(ServiceWorkOrders serviceWorkOrders) { + private void handleServiceWorkOrder(ServiceWorkOrders serviceWorkOrders,ServiceWorkOrdersType serviceWorkOrdersType) { LocalDate today = LocalDate.now(); // 1. 获取今日排班人员(优先查缓存,未命中则查询数据库并缓存) List attendanceUserGroups = RedisUtils.getCacheList(DateUtil.today()); - if (CollUtil.isEmpty(attendanceUserGroups)) { - attendanceUserGroups = attendanceUserGroupMapper.selectList( - new LambdaQueryWrapper() - .le(AttendanceUserGroup::getStartDate, today) - .ge(AttendanceUserGroup::getEndDate, today) - .orderByAsc(AttendanceUserGroup::getCreateTime) - ); + List attendanceUserGroupList = attendanceUserGroupMapper.selectList( + new LambdaQueryWrapper() + .le(AttendanceUserGroup::getStartDate, today) + .ge(AttendanceUserGroup::getEndDate, today) + .eq(AttendanceUserGroup::getDeptId, serviceWorkOrdersType.getDeptId()) + .orderByAsc(AttendanceUserGroup::getStartDate) + ); + if (CollUtil.isEmpty(attendanceUserGroups)|| attendanceUserGroups.size() != attendanceUserGroupList.size()) { + attendanceUserGroups=attendanceUserGroupList; Assert.isTrue(CollUtil.isNotEmpty(attendanceUserGroups), "暂无排班人员"); // 缓存当天排班数据(假设当天不会变) RedisUtils.setCacheList(DateUtil.today(), attendanceUserGroups); @@ -589,7 +591,7 @@ public class ServiceWorkOrdersServiceImpl implements IServiceWorkOrdersService { boolean flags = workOrdersRecordMapper.insert(serviceWorkOrdersRecord) > 0; if (flags) { if (serviceWorkOrdersType.getOperationMode().equals(OrderTypeOperationEnum.AUTOMATE_DISPATCH.getValue())) { - handleServiceWorkOrder(add); + handleServiceWorkOrder(add,serviceWorkOrdersType); } } } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersTypeServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersTypeServiceImpl.java index 48912b8b..0e487feb 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersTypeServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/ServiceWorkOrdersTypeServiceImpl.java @@ -3,6 +3,7 @@ package org.dromara.property.service.impl; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import org.apache.dubbo.config.annotation.DubboReference; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; @@ -18,6 +19,8 @@ import org.dromara.property.domain.bo.ServiceWorkOrdersTypeBo; import org.dromara.property.domain.vo.ServiceWorkOrdersTypeVo; import org.dromara.property.mapper.ServiceWorkOrdersTypeMapper; import org.dromara.property.service.IServiceWorkOrdersTypeService; +import org.dromara.system.api.RemoteDeptService; +import org.dromara.system.api.domain.vo.RemoteDeptVo; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -39,6 +42,8 @@ public class ServiceWorkOrdersTypeServiceImpl implements IServiceWorkOrdersTypeS private final ServiceWorkOrdersTypeMapper baseMapper; + @DubboReference + private RemoteDeptService remoteDeptService; /** * 查询【工单类型】 * @@ -47,7 +52,11 @@ public class ServiceWorkOrdersTypeServiceImpl implements IServiceWorkOrdersTypeS */ @Override public ServiceWorkOrdersTypeVo queryById(Long id) { - return baseMapper.selectVoById(id); + ServiceWorkOrdersTypeVo serviceWorkOrdersTypeVo= baseMapper.selectVoById(id); + Long deptId = serviceWorkOrdersTypeVo.getDeptId(); + RemoteDeptVo remoteDeptVo = remoteDeptService.selectDeptVoById(deptId); + serviceWorkOrdersTypeVo.setDeptName(remoteDeptVo.getDeptName()); + return serviceWorkOrdersTypeVo; } /** @@ -61,6 +70,11 @@ public class ServiceWorkOrdersTypeServiceImpl implements IServiceWorkOrdersTypeS public TableDataInfo queryPageList(ServiceWorkOrdersTypeBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + result.getRecords().stream().forEach(vo -> { + Long deptId = vo.getDeptId(); + RemoteDeptVo remoteDeptVo = remoteDeptService.selectDeptVoById(deptId); + vo.setDeptName(remoteDeptVo.getDeptName()); + }); return TableDataInfo.build(result); } @@ -73,7 +87,13 @@ public class ServiceWorkOrdersTypeServiceImpl implements IServiceWorkOrdersTypeS @Override public List queryList(ServiceWorkOrdersTypeBo bo) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); - return baseMapper.selectVoList(lqw); + List serviceWorkOrdersTypeVoList= baseMapper.selectVoList(lqw); + serviceWorkOrdersTypeVoList.stream().forEach(vo -> { + Long deptId = vo.getDeptId(); + RemoteDeptVo remoteDeptVo = remoteDeptService.selectDeptVoById(deptId); + vo.setDeptName(remoteDeptVo.getDeptName()); + }); + return serviceWorkOrdersTypeVoList; } private LambdaQueryWrapper buildQueryWrapper(ServiceWorkOrdersTypeBo bo) { diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/attendanceImpl/AttendanceUserGroupServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/attendanceImpl/AttendanceUserGroupServiceImpl.java index 8221157f..6dd3a696 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/attendanceImpl/AttendanceUserGroupServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/attendanceImpl/AttendanceUserGroupServiceImpl.java @@ -299,4 +299,9 @@ public class AttendanceUserGroupServiceImpl implements IAttendanceUserGroupServi return TableDataInfo.build(attendanceArrangementVoPage); } + + @Override + public List queryAttendByCurrDateAndDeviceIp(Date date, String deviceIp) { + return this.baseMapper.queryAttendByCurrDateAndDeviceIp(date, deviceIp); + } } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/cleanOrderImpl/CleanOrderServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/cleanOrderImpl/CleanOrderServiceImpl.java index 6b7e2831..2a03af34 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/cleanOrderImpl/CleanOrderServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/cleanOrderImpl/CleanOrderServiceImpl.java @@ -118,10 +118,11 @@ public class CleanOrderServiceImpl implements ICleanOrderService { return baseMapper.selectVoList(lqw); } - private LambdaQueryWrapper buildQueryWrapper(CleanOrderBo bo) { + private LambdaQueryWrapperbuildQueryWrapper(CleanOrderBo bo) { Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); - lqw.orderByAsc(CleanOrder::getId); + lqw.orderByDesc(CleanOrder::getCreateTime) + .orderByDesc(CleanOrder::getUpdateTime); // lqw.eq(StringUtils.isNotBlank(bo.getLocation()), CleanOrder::getLocation, bo.getLocation()); // lqw.eq(StringUtils.isNotBlank(bo.getArea()), CleanOrder::getArea, bo.getArea()); diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterInfoServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterInfoServiceImpl.java index a5a71bec..3c7ea77b 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterInfoServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterInfoServiceImpl.java @@ -1,6 +1,8 @@ package org.dromara.property.service.impl.smartDevicesImpl; +import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; +import com.alibaba.fastjson.JSONObject; import org.dromara.common.core.domain.TreeNode; import org.dromara.common.core.utils.MapstructUtils; import org.dromara.common.core.utils.StringUtils; @@ -13,13 +15,18 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.satoken.utils.LoginHelper; +import org.dromara.common.websocket.dto.WebSocketMessageDto; +import org.dromara.common.websocket.utils.WebSocketUtils; import org.dromara.property.domain.bo.TbFloorBo; import org.dromara.property.domain.vo.TbBuildingVo; import org.dromara.property.domain.vo.TbCommunityVo; import org.dromara.property.domain.vo.TbFloorVo; +import org.dromara.property.rocketmq.domain.MeterResult; import org.dromara.property.service.ITbBuildingService; import org.dromara.property.service.ITbCommunityService; import org.dromara.property.service.ITbFloorService; +import org.dromara.property.tasks.HeartbeatTasks; +import org.dromara.property.utils.MeterRecordUtil; import org.dromara.system.api.model.LoginUser; import org.springframework.stereotype.Service; import org.dromara.property.domain.bo.smartDevicesBo.TbMeterInfoBo; @@ -29,10 +36,10 @@ import org.dromara.property.mapper.smartDevicesMapper.TbMeterInfoMapper; import org.dromara.property.service.smartDevicesService.ITbMeterInfoService; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Collection; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -51,6 +58,9 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService { private final ITbBuildingService buildingService; private final ITbCommunityService communityService; + private final MeterRecordUtil meterRecordUtil; + private final HeartbeatTasks heartbeatTasks; + /** * 查询水电气 * @@ -106,16 +116,17 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService { LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.orderByAsc(TbMeterInfo::getId); lqw.like(StringUtils.isNotBlank(bo.getHostIp()), TbMeterInfo::getHostIp, bo.getHostIp()); - lqw.like(StringUtils.isNotBlank(bo.getMeterName()), TbMeterInfo::getMeterName, bo.getMeterName()); lqw.eq(StringUtils.isNotBlank(bo.getMeterCode()), TbMeterInfo::getMeterCode, bo.getMeterCode()); lqw.eq(StringUtils.isNotBlank(bo.getFactoryNo()), TbMeterInfo::getFactoryNo, bo.getFactoryNo()); + lqw.like(StringUtils.isNotBlank(bo.getMeterName()), TbMeterInfo::getMeterName, bo.getMeterName()); + lqw.eq(StringUtils.isNotBlank(bo.getInstallLocation()), TbMeterInfo::getInstallLocation, bo.getInstallLocation()); + lqw.eq(bo.getFloorId() != null, TbMeterInfo::getFloorId, bo.getFloorId()); + lqw.eq(bo.getMaxRang() != null, TbMeterInfo::getMaxRang, bo.getMaxRang()); lqw.eq(bo.getMeterType() != null, TbMeterInfo::getMeterType, bo.getMeterType()); lqw.eq(bo.getMeterUnit() != null, TbMeterInfo::getMeterUnit, bo.getMeterUnit()); - lqw.eq(StringUtils.isNotBlank(bo.getInstallLocation()), TbMeterInfo::getInstallLocation, bo.getInstallLocation()); lqw.eq(bo.getInitReading() != null, TbMeterInfo::getInitReading, bo.getInitReading()); - lqw.eq(bo.getMaxRang() != null, TbMeterInfo::getMaxRang, bo.getMaxRang()); - lqw.eq(bo.getCommunicationState() != null, TbMeterInfo::getCommunicationState, bo.getCommunicationState()); lqw.eq(bo.getRunningState() != null, TbMeterInfo::getRunningState, bo.getRunningState()); + lqw.eq(bo.getCommunicationState() != null, TbMeterInfo::getCommunicationState, bo.getCommunicationState()); return lqw; } @@ -177,10 +188,11 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService { * 查询水电气树结构 * * @param meterType 水电气类型 + * @param isMeter 是否返回仪表 * @return 水电气树结构 */ @Override - public List> queryMeterInfoTree(Long meterType) { + public List> queryMeterInfoTree(Long meterType, Boolean isMeter) { // 默认加载社区树 List> treeList = new ArrayList<>(); List tbCommunityVos = communityService.queryAll(); @@ -223,20 +235,159 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService { }).toList(); treeList.addAll(l3); - TbMeterInfoBo bo = new TbMeterInfoBo(); - bo.setMeterType(meterType); - List meterInfoVos = this.queryList(bo); - if (meterInfoVos != null && !meterInfoVos.isEmpty()) { - List> l4 = meterInfoVos.stream().map(item -> { - TreeNode node = new TreeNode<>(); - node.setLevel(4); - node.setCode(item.getId()); - node.setParentCode(item.getFloorId()); - node.setLabel(item.getMeterName()); - return node; - }).toList(); - treeList.addAll(l4); + if (isMeter) { + TbMeterInfoBo bo = new TbMeterInfoBo(); + bo.setMeterType(meterType); + List meterInfoVos = this.queryList(bo); + if (meterInfoVos != null && !meterInfoVos.isEmpty()) { + List> l4 = meterInfoVos.stream().map(item -> { + TreeNode node = new TreeNode<>(); + node.setLevel(4); + node.setCode(item.getId()); + node.setParentCode(item.getFloorId()); + node.setLabel(item.getMeterName()); + return node; + }).toList(); + treeList.addAll(l4); + } } return TreeUtils.build(treeList, 0L); } + + /** + * 获取水/电/气表当前读数/状态 + * + * @param meterType 水电气类型 + * @param floorId 楼栋id + */ + @Override + public void getMeterStatus(Long meterType, Long floorId) { + // 参数校验 + if (meterType == 0L || floorId == 0L) { + heartbeatTasks.stopTask("Meter_Status_Reading"); + return; + } + + // 获取当前登录用户 + LoginUser user = LoginHelper.getLoginUser(); + if (user == null) { + heartbeatTasks.stopTask("Meter_Status_Reading"); + return; + } + + // 初始化WebSocket消息 + WebSocketMessageDto webSocketMessage = new WebSocketMessageDto(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("type", "meter"); + + // 查询仪表信息 + TbMeterInfoBo meterInfoBo = new TbMeterInfoBo(); + meterInfoBo.setFloorId(floorId); + meterInfoBo.setMeterType(meterType); + List meterInfoVoList = this.queryList(meterInfoBo); + + // 如果没有仪表信息,直接返回 + if (meterInfoVoList.isEmpty()) { + heartbeatTasks.stopTask("Meter_Status_Reading"); + jsonObject.put("readingTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); + jsonObject.put("data", new ArrayList<>()); + webSocketMessage.setMessage(jsonObject.toString()); + webSocketMessage.setSessionKeys(List.of(user.getUserId())); + WebSocketUtils.publishMessage(webSocketMessage); + return; + } + + // 获取唯一的主机IP列表 + String[] hostIpArr = meterInfoVoList.stream() + .map(TbMeterInfoVo::getHostIp) + .distinct() + .toArray(String[]::new); + + // 统计每个IP对应的仪表数量 + Map ipCountMap = new HashMap<>(); + for (String ip : hostIpArr) { + ipCountMap.put(ip, baseMapper.selectCount(new LambdaQueryWrapper() + .eq(TbMeterInfo::getHostIp, ip))); + } + + // 启动定时任务 + heartbeatTasks.startHeartbeatTask("Meter_Status_Reading", () -> { + jsonObject.put("readingTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); + + List meterResults; + try { + meterResults = meterRecordUtil.getMeterStatus(ipCountMap, hostIpArr); + } catch (Exception e) { + // 获取数据失败,设置所有仪表通信状态为0并发送消息 + handleMeterCommunicationFailure(user, jsonObject, meterInfoVoList, webSocketMessage); + return; + } + + // 处理仪表读数和状态 + processMeterResults(user, jsonObject, meterResults, meterInfoVoList, webSocketMessage); + }, 30000); + } + + /** + * 处理仪表通信失败的情况 + * + * @param meterInfoVoList 仪表列表 + * @param jsonObject 消息对象 + * @param webSocketMessage WebSocket消息 + * @param user 当前用户 + */ + private void handleMeterCommunicationFailure(LoginUser user, JSONObject jsonObject, List meterInfoVoList, WebSocketMessageDto webSocketMessage) { + meterInfoVoList.forEach(item -> item.setCommunicationState(0L)); + jsonObject.put("data", meterInfoVoList); + webSocketMessage.setMessage(jsonObject.toString()); + webSocketMessage.setSessionKeys(List.of(user.getUserId())); + WebSocketUtils.publishMessage(webSocketMessage); + } + + /** + * 处理仪表读数结果 + * + * @param meterInfoVoList 仪表列表 + * @param meterResults 读数结果 + * @param jsonObject 消息对象 + * @param webSocketMessage WebSocket消息 + * @param user 当前用户 + */ + private void processMeterResults(LoginUser user, JSONObject jsonObject, List meterResults, List meterInfoVoList, WebSocketMessageDto webSocketMessage) { + // 创建IP到结果的映射,提高查找效率 + Map meterResultMap = meterResults.stream() + .collect(Collectors.toMap(MeterResult::getIp, Function.identity(), (v1, v2) -> v1)); + + for (TbMeterInfoVo item : meterInfoVoList) { + MeterResult meterResult = meterResultMap.get(item.getHostIp()); + if (meterResult == null) { + // 如果没有找到对应的结果,设置通信状态为0 + item.setCommunicationState(0L); + continue; + } + + // 解析读数 + List collectionValue = meterResult.getCollectionValue(); + String meterCode = item.getMeterCode(); + + try { + int codeIndex = Integer.parseInt(meterCode); + if (codeIndex >= 0 && codeIndex < collectionValue.size()) { + BigDecimal initReading = BigDecimal.valueOf(collectionValue.get(codeIndex)) + .setScale(2, RoundingMode.HALF_UP); + item.setInitReading(initReading); + item.setCommunicationState(initReading.compareTo(BigDecimal.ZERO) == 0 ? 0L : 1L); + } else { + item.setCommunicationState(0L); + } + } catch (NumberFormatException e) { + item.setCommunicationState(0L); + } + } + + jsonObject.put("data", meterInfoVoList); + webSocketMessage.setMessage(jsonObject.toString()); + webSocketMessage.setSessionKeys(List.of(user.getUserId())); + WebSocketUtils.publishMessage(webSocketMessage); + } } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterRecordServiceImpl.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterRecordServiceImpl.java index 2c206a81..bf6a03b9 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterRecordServiceImpl.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/impl/smartDevicesImpl/TbMeterRecordServiceImpl.java @@ -238,50 +238,74 @@ public class TbMeterRecordServiceImpl implements ITbMeterRecordService { public Map getEnergyTrend(String floorId, String meterId, Long meterType, String day, String month, String year) { Map resultMap = new HashMap<>(); - // hour - List> hourList = baseMapper.getHourTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, day); + String yesterday = DateUtil.format(DateUtil.offsetDay(DateUtil.parse(day), -1), "yyyy-MM-dd"); + // todayHour + Map todayMap = trendHourData(floorId, meterId, meterType, day); + // yesterdayHour + Map yesterdayMap = trendHourData(floorId, meterId, meterType, yesterday); + Map hourMap = new HashMap<>(); - String[] hourCategories = hourList.stream() - .map(map -> map.get("hour").toString()) - .toArray(String[]::new); - BigDecimal[] hourData = hourList.stream() - .map(map -> new BigDecimal(map.get("total_consumption").toString())) - .toArray(BigDecimal[]::new); - hourMap.put("categories", hourCategories); - hourMap.put("data", hourData); - hourMap.put("total" , hourList.stream().map(map -> new BigDecimal(map.get("total_consumption").toString())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).floatValue()); + hourMap.put("today", todayMap); + hourMap.put("yesterday", yesterdayMap); + - // day String[] monthArr = month.split("-"); - List> dayList = baseMapper.getDayTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, monthArr[0], monthArr[1]); + String lastMonth = Integer.parseInt(monthArr[1]) - 1 + ""; + // nowMonth + Map nowMonthMap = trendDayData(floorId, meterId, meterType, monthArr[0], monthArr[1]); + // lastMonth + Map lastMonthMap = trendDayData(floorId, meterId, meterType, monthArr[0], lastMonth); + Map dayMap = new HashMap<>(); - String[] dayCategories = dayList.stream() - .map(map -> map.get("day").toString()) - .toArray(String[]::new); - BigDecimal[] dayData = dayList.stream() - .map(map -> new BigDecimal(map.get("total_consumption").toString())) - .toArray(BigDecimal[]::new); - dayMap.put("categories", dayCategories); - dayMap.put("data", dayData); - dayMap.put("total", dayList.stream().map(map -> new BigDecimal(map.get("total_consumption").toString())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).floatValue()); + dayMap.put("nowMonth", nowMonthMap); + dayMap.put("lastMonth", lastMonthMap); + + String lastYear = Integer.parseInt(year) - 1 + ""; + // nowYear + Map nowYearMap = trendMonthData(floorId, meterId, meterType, year); + // lastYear + Map lastYearMap = trendMonthData(floorId, meterId, meterType, lastYear); - // month - List> monthList = baseMapper.getMonthTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, year); Map monthMap = new HashMap<>(); - String[] monthCategories = monthList.stream() - .map(map -> map.get("month").toString()) - .toArray(String[]::new); - BigDecimal[] monthData = monthList.stream() - .map(map -> new BigDecimal(map.get("total_consumption").toString())) - .toArray(BigDecimal[]::new); - monthMap.put("categories", monthCategories); - monthMap.put("data", monthData); - monthMap.put("total", monthList.stream().map(map -> new BigDecimal(map.get("total_consumption").toString())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).floatValue()); - + monthMap.put("nowYear", nowYearMap); + monthMap.put("lastYear", lastYearMap); resultMap.put("hour", hourMap); resultMap.put("day", dayMap); resultMap.put("month", monthMap); return resultMap; } + + private Map trendHourData(String floorId, String meterId, Long meterType, String day) { + Map hourMap = new HashMap<>(); + List> hourList = baseMapper.getHourTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, day); + List hourData = new ArrayList<>(); + hourList.forEach(item -> hourData.add(new String[]{item.get("hour").toString(), item.get("total_consumption").toString()})); + Float total = hourList.stream().map(map -> new BigDecimal(map.get("total_consumption").toString())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).floatValue(); + hourMap.put("total", total); + hourMap.put("data", hourData); + return hourMap; + } + + private Map trendDayData(String floorId, String meterId, Long meterType, String year, String month) { + Map dayMap = new HashMap<>(); + List> dayList = baseMapper.getDayTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, year, month); + List dayData = new ArrayList<>(); + dayList.forEach(item -> dayData.add(new String[]{item.get("day").toString(), item.get("total_consumption").toString()})); + Float total = dayList.stream().map(map -> new BigDecimal(map.get("total_consumption").toString())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).floatValue(); + dayMap.put("total", total); + dayMap.put("data", dayData); + return dayMap; + } + + private Map trendMonthData(String floorId, String meterId, Long meterType, String year) { + Map resultMap = new HashMap<>(); + List> monthList = baseMapper.getMonthTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, year); + List monthData = new ArrayList<>(); + monthList.forEach(item -> monthData.add(new String[]{item.get("month").toString(), item.get("total_consumption").toString()})); + Float total = monthList.stream().map(map -> new BigDecimal(map.get("total_consumption").toString())).reduce(BigDecimal::add).orElse(BigDecimal.ZERO).floatValue(); + resultMap.put("total", total); + resultMap.put("data", monthData); + return resultMap; + } } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/smartDevicesService/ITbMeterInfoService.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/smartDevicesService/ITbMeterInfoService.java index 7695b8f2..7430854c 100644 --- a/ruoyi-modules/Property/src/main/java/org/dromara/property/service/smartDevicesService/ITbMeterInfoService.java +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/service/smartDevicesService/ITbMeterInfoService.java @@ -13,7 +13,7 @@ import java.util.List; * 水电气Service接口 * * @author lsm - * @date 2025-07-19 + * @since 2025-07-19 */ public interface ITbMeterInfoService { @@ -71,8 +71,16 @@ public interface ITbMeterInfoService { * 查询水电气树结构 * * @param meterType 水电气类型 - * + * @param isMeter 是否返回仪表 * @return 水电气树结构 */ - List> queryMeterInfoTree(Long meterType); + List> queryMeterInfoTree(Long meterType, Boolean isMeter); + + /** + * 获取水/电/气表当前读数/状态 + * + * @param meterType 水电气类型 + * @param floorId 楼栋id + */ + void getMeterStatus(Long meterType, Long floorId); } diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/tasks/HeartbeatTasks.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/tasks/HeartbeatTasks.java new file mode 100644 index 00000000..3ea0917e --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/tasks/HeartbeatTasks.java @@ -0,0 +1,42 @@ +package org.dromara.property.tasks; + +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.*; + +/** + * @author lsm + * @apiNote HeartbeatTasks + * @since 2025/9/1 + */ +@Component +public class HeartbeatTasks { + private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); + private final Map> tasks = new ConcurrentHashMap<>(); + + public void startHeartbeatTask(String taskId, Runnable task, long intervalMs) { + // 先停止同名任务(如果存在) + stopTask(taskId); + + // 创建新任务 + ScheduledFuture future = scheduler.scheduleAtFixedRate( + task, 0, intervalMs, TimeUnit.MILLISECONDS); + + tasks.put(taskId, future); + } + + public void stopHeartbeatTask() { + // 停止所有心跳任务 + tasks.values().forEach(future -> future.cancel(true)); + tasks.clear(); + } + + public void stopTask(String taskId) { + ScheduledFuture future = tasks.get(taskId); + if (future != null) { + future.cancel(true); + tasks.remove(taskId); + } + } +} diff --git a/ruoyi-modules/Property/src/main/java/org/dromara/property/utils/MeterRecordUtil.java b/ruoyi-modules/Property/src/main/java/org/dromara/property/utils/MeterRecordUtil.java new file mode 100644 index 00000000..aec441d0 --- /dev/null +++ b/ruoyi-modules/Property/src/main/java/org/dromara/property/utils/MeterRecordUtil.java @@ -0,0 +1,48 @@ +package org.dromara.property.utils; + +import cn.hutool.core.lang.TypeReference; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.dromara.property.rocketmq.domain.MeterResult; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; + +/** + * @author lsm + * @apiNote MeterRecordUtil + * @since 2025/8/30 + */ +@Slf4j +@Component +public class MeterRecordUtil { + + @Value("${eqp.config.meter.host}") + private String meterRecordUrl; + + private static final String READING_URL = "reading"; + + @Data + public static class Result { + private Integer code; + private T data; + } + + /** + * 获取水/电/气表当前读数 + */ + public List getMeterStatus(Map ipMap, String[] ipArr) { + JSONObject jsonObject = new JSONObject(); + jsonObject.putOnce("ipMap", ipMap); + jsonObject.putOnce("ipArr", ipArr); + String post = HttpUtil.post(meterRecordUrl + READING_URL, jsonObject.toString(), 3000); + Result> result = JSONUtil.toBean(post, new TypeReference>>() {}, true); + return result.getData(); + } + +} diff --git a/ruoyi-modules/Property/src/main/resources/mapper/Property/AttendanceUserGroupMapper.xml b/ruoyi-modules/Property/src/main/resources/mapper/Property/AttendanceUserGroupMapper.xml index b38100ed..dd6edb9b 100644 --- a/ruoyi-modules/Property/src/main/resources/mapper/Property/AttendanceUserGroupMapper.xml +++ b/ruoyi-modules/Property/src/main/resources/mapper/Property/AttendanceUserGroupMapper.xml @@ -4,4 +4,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/enums/EventSmallTypeEnum.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/enums/EventSmallTypeEnum.java index ee4720b0..8e794cf3 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/enums/EventSmallTypeEnum.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/domain/enums/EventSmallTypeEnum.java @@ -37,6 +37,7 @@ public enum EventSmallTypeEnum { EQP_REPORT_SBSB(1025, "报警设备上报"), BLACK_PERSON(1026, "黑名单人员"), AUTHORIZATION_EXPIRED(1027, "门禁授权已过期"), + ILLEGAL_PARKING(1028,"非法停车"), /* -----------------------系统报警相关-------------------------------------*/ SYS_REPORT_WLGZ(2001, "网络连接故障"), SYS_REPORT_DLYC(2002, "用户登录异常"), diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/RocketMqConstants.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/RocketMqConstants.java index 1cfafe7a..8d055e38 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/RocketMqConstants.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/RocketMqConstants.java @@ -9,10 +9,15 @@ public interface RocketMqConstants { // mq topic String TOPIC = "SmartParks"; + /*-----------------------------------消息group------------------------------------*/ // 人比比对消费者组 String COMPAREGROUP = "SmartParks-compare"; // 人脸抓拍消费者组 String CAPTUREGROUP = "SmartParks-capture"; + // 人员聚集消费组 + String HIGH_DENSITY_GROUP = "SmartParks-highDensity"; + // 停车消费组 + String PARKING_GROUP = "SmartParks-parking"; /*-----------------------------------消息tag------------------------------------*/ String HIKADD = "ADD_HIK_DEVICE_TAG"; @@ -20,5 +25,8 @@ public interface RocketMqConstants { String FACECAPTURE = "FACE_CAPTURE_REPORT"; // 人脸比对 String FACECOMPARE = "FACE_COMPARE_REPORT"; - + // 人员聚集上报 + String HIGH_DENSITY = "HIGH_DENSITY_REPORT"; + // 停车上报 + String PARKING_ALARM = "PARKING_ALARM_REPORT"; } diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/FaceCaptureConsumer.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/FaceCaptureConsumer.java index 6e25325c..0cd0c935 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/FaceCaptureConsumer.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/FaceCaptureConsumer.java @@ -8,7 +8,7 @@ import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQListener; import org.dromara.sis.rocketmq.RocketMqConstants; import org.dromara.sis.rocketmq.domain.FaceCapture; -import org.dromara.sis.service.IZeroSensationPassageService; +import org.dromara.sis.service.IEventAlarmReportService; import org.springframework.stereotype.Component; /** @@ -27,14 +27,14 @@ import org.springframework.stereotype.Component; ) public class FaceCaptureConsumer implements RocketMQListener { - private final IZeroSensationPassageService zeroSensationPassageService; + private final IEventAlarmReportService eventAlarmReportService; @Override public void onMessage(MessageExt ext) { log.info("消费人脸抓拍数据,数据长度={}", ext.getBody().length); try { FaceCapture capture = JSONObject.parseObject(ext.getBody(), FaceCapture.class); - zeroSensationPassageService.pass(capture.getDeviceIp(), capture.getSmallImg(), capture.getBigImg()); + eventAlarmReportService.handleCaptureImg(capture.getDeviceIp(), capture.getSmallImg(), capture.getBigImg()); } catch (Exception e) { log.error("消费人脸抓拍数据处理失败,", e); } diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/HighDensityConsumer.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/HighDensityConsumer.java new file mode 100644 index 00000000..677f876a --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/HighDensityConsumer.java @@ -0,0 +1,44 @@ +package org.dromara.sis.rocketmq.consumer; + +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.dromara.sis.rocketmq.RocketMqConstants; +import org.dromara.sis.rocketmq.domain.HighDensity; +import org.dromara.sis.service.IEventAlarmReportService; +import org.dromara.sis.service.IZeroSensationPassageService; +import org.springframework.stereotype.Component; + +/** + * 人员聚集消费者 + * + * @author lxj + */ + +@Slf4j +@Component +@RequiredArgsConstructor +@RocketMQMessageListener( + topic = RocketMqConstants.TOPIC, + consumerGroup = RocketMqConstants.HIGH_DENSITY, + selectorExpression = RocketMqConstants.HIGH_DENSITY +) +public class HighDensityConsumer implements RocketMQListener { + + private final IEventAlarmReportService eventAlarmReportService; + + @Override + public void onMessage(MessageExt ext) { + log.info("消费人员聚集数据,数据长度={}", ext.getBody().length); + try { + HighDensity f = JSONObject.parseObject(ext.getBody(), HighDensity.class); + eventAlarmReportService.handleHighDensity(f); + } catch (Exception e) { + log.error("消费人脸抓拍数据处理失败,", e); + } + + } +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/ParkingDelayConsumer.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/ParkingDelayConsumer.java new file mode 100644 index 00000000..718a505a --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/consumer/ParkingDelayConsumer.java @@ -0,0 +1,43 @@ +package org.dromara.sis.rocketmq.consumer; + +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.rocketmq.common.message.MessageExt; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.dromara.sis.rocketmq.RocketMqConstants; +import org.dromara.sis.rocketmq.domain.ParkingReport; +import org.dromara.sis.service.IEventAlarmReportService; +import org.springframework.stereotype.Component; + +/** + * 人员聚集消费者 + * + * @author lxj + */ + +@Slf4j +@Component +@RequiredArgsConstructor +@RocketMQMessageListener( + topic = RocketMqConstants.TOPIC, + consumerGroup = RocketMqConstants.PARKING_GROUP, + selectorExpression = RocketMqConstants.PARKING_ALARM +) +public class ParkingDelayConsumer implements RocketMQListener { + + private final IEventAlarmReportService eventAlarmReportService; + + @Override + public void onMessage(MessageExt ext) { + log.info("消费停车检测数据,数据长度={}", ext.getBody().length); + try { + ParkingReport report = JSONObject.parseObject(ext.getBody(), ParkingReport.class); + eventAlarmReportService.handleParking(report); + } catch (Exception e) { + log.error("消费人脸抓拍数据处理失败,", e); + } + + } +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/domain/HighDensity.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/domain/HighDensity.java new file mode 100644 index 00000000..14a5f119 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/domain/HighDensity.java @@ -0,0 +1,38 @@ +package org.dromara.sis.rocketmq.domain; + +import lombok.Data; + +/** + * 人员聚集报警 + * + * @author lxj + */ +@Data +public class HighDensity { + + /** + * 报警图片 + */ + private byte[] img; + + /** + * 设备ip + */ + private String deviceIp; + + /** + * 人员密度0.1-1.0 + */ + private Double density; + + /** + * 灵敏度参数,取值范围:[1,5] + */ + private Byte sensitivity; + + /** + * 触发人员聚集参数报警阈值,20~360s + */ + private Integer wDuration; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/domain/ParkingReport.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/domain/ParkingReport.java new file mode 100644 index 00000000..3930c7c3 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/rocketmq/domain/ParkingReport.java @@ -0,0 +1,28 @@ +package org.dromara.sis.rocketmq.domain; + + +import lombok.Data; + +/** + * 区域停车报警 + * @author lxj + */ +@Data +public class ParkingReport { + + /** + * 报警图片 + */ + private byte[] img; + + /** + * 设备ip + */ + private String deviceIp; + + /** + * 触发人员聚集参数报警阈值,20~360s + */ + private Integer pDuration; + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/IEventAlarmReportService.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/IEventAlarmReportService.java new file mode 100644 index 00000000..27185929 --- /dev/null +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/IEventAlarmReportService.java @@ -0,0 +1,36 @@ +package org.dromara.sis.service; + +import org.dromara.sis.rocketmq.domain.HighDensity; +import org.dromara.sis.rocketmq.domain.ParkingReport; + +/** + * 事件告警上报处理服务 + * + * @author lxj + */ +public interface IEventAlarmReportService { + + /** + * 处理停车滞留上报 + * + * @param report 上报信息 + */ + void handleParking(ParkingReport report); + + /** + * 处理人员聚集事件上报 + * + * @param density 上报信息 + */ + void handleHighDensity(HighDensity density); + + /** + * 处理人像抓拍 + * + * @param deviceIp 设备ip + * @param smallImg 小图 + * @param bigImg 大图 + */ + void handleCaptureImg(String deviceIp, byte[] smallImg, byte[] bigImg); + +} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisAlarmEventsService.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisAlarmEventsService.java index f65b1a29..ec33a236 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisAlarmEventsService.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/ISisAlarmEventsService.java @@ -2,6 +2,7 @@ package org.dromara.sis.service; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.sis.domain.SisAlarmEvents; import org.dromara.sis.domain.bo.SisAlarmEventsBo; import org.dromara.sis.domain.bo.alarm.AlarmAssignmentBo; import org.dromara.sis.domain.bo.alarm.AlarmCompleteBo; @@ -79,7 +80,7 @@ public interface ISisAlarmEventsService { /** * 异步生成告警记录 */ - void createAlarmRecord(String deviceIp, Integer level, EventSmallTypeEnum type, String msg, byte[] smallImg, byte[] bigImg); + SisAlarmEvents createAlarmRecord(String deviceIp, Integer level, EventSmallTypeEnum type, String msg, List imgs); /** * 任务分配操作 diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/IZeroSensationPassageService.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/IZeroSensationPassageService.java deleted file mode 100644 index d5c5e353..00000000 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/IZeroSensationPassageService.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.dromara.sis.service; - -import cn.hutool.core.date.TimeInterval; - -public interface IZeroSensationPassageService { - - /** - * 无感通行服务 - * - * @param deviceIp 设备ip - * @param smallImp 人脸小图 - * @param bigImg 背景图片 - */ - void pass(String deviceIp, byte[] smallImp, byte[] bigImg); - - /** - * 电梯外部按键触发 - * - * @param deviceIp 设备ip - */ - void handleEleOut(String deviceIp); - -} diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/ZeroSensationPassageServiceImpl.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/EventAlarmReportServiceImpl.java similarity index 66% rename from ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/ZeroSensationPassageServiceImpl.java rename to ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/EventAlarmReportServiceImpl.java index 5eb7e30f..1533f30a 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/ZeroSensationPassageServiceImpl.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/EventAlarmReportServiceImpl.java @@ -9,12 +9,18 @@ import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.DubboReference; +import org.dromara.property.api.RemoteAttendanceService; import org.dromara.property.api.RemoteFloorService; +import org.dromara.property.api.domain.vo.RemoteAttendanceUserGroupVo; import org.dromara.property.api.domain.vo.RemoteFloorVo; +import org.dromara.sis.domain.SisAlarmEvents; +import org.dromara.sis.domain.bo.alarm.AlarmAssignmentBo; import org.dromara.sis.domain.enums.ControlTypeEnum; import org.dromara.sis.domain.enums.EventSmallTypeEnum; import org.dromara.sis.domain.enums.RosterTypeEnum; import org.dromara.sis.domain.vo.*; +import org.dromara.sis.rocketmq.domain.HighDensity; +import org.dromara.sis.rocketmq.domain.ParkingReport; import org.dromara.sis.sdk.e8.E8PlatformApi; import org.dromara.sis.sdk.e8.domain.accessControl.req.RemoteOpenDoorReq; import org.dromara.sis.sdk.hik.HikApiService; @@ -22,24 +28,23 @@ import org.dromara.sis.sdk.huawei.HuaWeiBoxApi; import org.dromara.sis.sdk.huawei.domain.HWResult; import org.dromara.sis.sdk.smartDevices.utils.ElevatorControlTcpUtil; import org.dromara.sis.service.*; +import org.dromara.system.api.RemoteUserService; +import org.dromara.system.api.domain.vo.RemoteUserVo; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Objects; +import java.util.*; /** - * 无感通行业务服务实现 + * 处理设备告警上报服务 * - * @author lxj, lsm - * @since 2025-08-04 + * @author lxj */ @Slf4j @Service @RequiredArgsConstructor -public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageService { +public class EventAlarmReportServiceImpl implements IEventAlarmReportService { + private final ISisAlarmEventsService alarmEventsService; private final HuaWeiBoxApi huaWeiBoxApi; private final ISisAuthRecordService authRecordService; private final ISisElevatorInfoService elevatorInfoService; @@ -49,14 +54,27 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer private final ISisElevatorFloorRefService elevatorFloorRefService; private final ISisElevatorFloorChannelRefService elevatorFloorChannelRefService; private final E8PlatformApi e8PlatformApi; - private final ISisAlarmEventsService alarmEventsService; private final HikApiService hikApiService; @DubboReference private RemoteFloorService remoteFloorService; + @DubboReference + private RemoteAttendanceService remoteAttendanceService; + @DubboReference + private RemoteUserService remoteUserService; @Override - public void pass(String deviceIp, byte[] smallImg, byte[] bigImg) { + public void handleParking(ParkingReport report) { + handleAlarm(report.getDeviceIp(), report.getImg(), 2, EventSmallTypeEnum.ILLEGAL_PARKING, "非法停车报警"); + } + + @Override + public void handleHighDensity(HighDensity density) { + handleAlarm(density.getDeviceIp(), density.getImg(), 2, EventSmallTypeEnum.SMART_REPORT_RYJJ, "人员聚集报警"); + } + + @Override + public void handleCaptureImg(String deviceIp, byte[] smallImg, byte[] bigImg) { TimeInterval interval = new TimeInterval(); // 抓拍小图 String smallImgBase64Str = Base64Encoder.encode(smallImg); @@ -64,7 +82,7 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer if (result.getCode() != 200) { log.info("华为盒子比对失败,msg={}", result.getMessage()); // 产生告警数据 人脸比对失败,默认为 - alarmEventsService.createAlarmRecord(deviceIp, 2, EventSmallTypeEnum.SMART_REPORT_ZJCR, "人脸比对失败", smallImg, bigImg); + handleAlarm(deviceIp, smallImg, bigImg, 2, EventSmallTypeEnum.SMART_REPORT_ZJCR, "人脸比对失败"); return; } log.info("人脸比对执行完成,耗时:{}ms", interval.intervalMs()); @@ -75,20 +93,20 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer if (authRecord == null) { log.info("人员[{}]没有授权记录,判定为陌生人", person); // 不是内部人员 产生紧急的告警信息 - alarmEventsService.createAlarmRecord(deviceIp, 2, EventSmallTypeEnum.SMART_REPORT_ZJCR, "陌生人员入内", smallImg, bigImg); + handleAlarm(deviceIp, smallImg, bigImg, 2, EventSmallTypeEnum.SMART_REPORT_ZJCR, "陌生人员入内"); return; } else { if (Objects.equals(authRecord.getRosterType(), RosterTypeEnum.BLACK_LIST.getCode())) { - log.info("人员[{}]在黑名单中,暂不处理。", person); - alarmEventsService.createAlarmRecord(deviceIp, 3, EventSmallTypeEnum.BLACK_PERSON, "黑名单人员入内", smallImg, bigImg); + log.info("黑名单人员[{}]。", person); + handleAlarm(deviceIp, smallImg, bigImg, 3, EventSmallTypeEnum.BLACK_PERSON, "黑名单人员"); return; } } Date now = new Date(); if (DateUtil.compare(now, authRecord.getEndDate()) > 0) { - alarmEventsService.createAlarmRecord(deviceIp, 1, EventSmallTypeEnum.AUTHORIZATION_EXPIRED, "人员授权信息已过期", smallImg, bigImg); - log.info("当前人脸已过期,暂不处理。"); + handleAlarm(deviceIp, smallImg, bigImg, 1, EventSmallTypeEnum.AUTHORIZATION_EXPIRED, "人员授权信息已过期"); + log.info("当前人脸已过期。person={}", person); return; } // 获取当前设备的绑定设备信息 @@ -128,63 +146,6 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer log.info("权限下发执行完成,耗时:{}ms", interval.intervalMs()); } - /** - * 电梯外部按键触发 - * - * @param deviceIp 设备ip - */ - @Override - public void handleEleOut(String deviceIp) { - TimeInterval interval = new TimeInterval(); - // 获取当前设备的绑定设备信息 - List bindRefList = deviceBindRefService.queryByDeviceIp(deviceIp); - List outRefList = bindRefList.stream().filter(item -> Objects.equals(item.getControlType(), ControlTypeEnum.ELEVATOR_OUT_CONTROL.getCode())).toList(); - - outRefList.forEach(item -> { - // 获取当前电梯信息 - SisElevatorInfoVo ele = elevatorInfoService.queryById(item.getBindId()); - - List channelRef = elevatorFloorChannelRefService.queryByFloorIds(List.of(item.getDeviceFloorId())); - SisElevatorFloorChannelRefVo channelRefVo = channelRef.stream().filter(o -> Objects.equals(o.getElevatorId(), item.getBindId())).findFirst().orElse(null); - - if (channelRefVo != null) { - if (channelRefVo.getDownChannel() != null) { - hikApiService.controlGateway(ele.getControlIp(), channelRefVo.getDownChannel().intValue(), 2); - } - - if (channelRefVo.getUpChannel() != null) { - hikApiService.controlGateway(ele.getControlIp(), channelRefVo.getUpChannel().intValue(), 2); - } - } - }); - log.info("处理电梯外部按键完成,耗时:{}ms", interval.intervalMs()); - } - - /** - * 生成告警事件 - */ - public void createAlarmRecord(String deviceIp, Integer level, Integer type, String msg, byte[] smallImg, byte[] bigImg) { -// alarmEventsService.createAlarmRecord(deviceIp, level, type, msg, smallImg, bigImg); - } - - /** - * 处理门禁 - */ - public void handleAc(Long deviceId) { - if (deviceId != null) { - SisAccessControlVo ac = accessControlService.queryById(deviceId); - log.info("调用门禁服务远程开门,doorName:{}", ac.getAccessName()); - RemoteOpenDoorReq req = new RemoteOpenDoorReq(); - req.setType(0); - RemoteOpenDoorReq.ControlData data = new RemoteOpenDoorReq.ControlData(); - data.setDeviceId(Long.parseLong(ac.getOutCode())); - data.setDoorId(Long.parseLong(ac.getOutCode())); - req.setControlList(List.of(data)); - Boolean flag = e8PlatformApi.remoteOpenDoor(req); - log.info("远程开门结果,result={}", flag); - } - } - /** * 验证电梯权限 */ @@ -239,4 +200,86 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer } log.info("梯控下发权限完成"); } + + /** + * 处理门禁 + */ + public void handleAc(Long deviceId) { + if (deviceId != null) { + SisAccessControlVo ac = accessControlService.queryById(deviceId); + log.info("调用门禁服务远程开门,doorName:{}", ac.getAccessName()); + RemoteOpenDoorReq req = new RemoteOpenDoorReq(); + req.setType(0); + RemoteOpenDoorReq.ControlData data = new RemoteOpenDoorReq.ControlData(); + data.setDeviceId(Long.parseLong(ac.getOutCode())); + data.setDoorId(Long.parseLong(ac.getOutCode())); + req.setControlList(List.of(data)); + Boolean flag = e8PlatformApi.remoteOpenDoor(req); + log.info("远程开门结果,result={}", flag); + } + } + + /** + * 处理告警信息 + * + * @param deviceIp 设备ip + * @param smallImg 人脸小图 + * @param bigImg 人脸大图 + * @param smallType 事件类型 + */ + private void handleAlarm(String deviceIp, byte[] smallImg, byte[] bigImg, Integer level, EventSmallTypeEnum smallType, String desc) { + List ls = new ArrayList<>(2); + ls.add(smallImg); + ls.add(bigImg); + // 生成告警记录 + SisAlarmEvents alarmRecord = alarmEventsService.createAlarmRecord(deviceIp, level, smallType, desc, ls); + autoAssign(alarmRecord.getId(), deviceIp); + } + + /** + * 处理告警信息 + * + * @param deviceIp 设备ip + * @param img 图片 + * @param smallType 事件类型 + */ + private void handleAlarm(String deviceIp, byte[] img, Integer level, EventSmallTypeEnum smallType, String desc) { + // 生成告警记录 + SisAlarmEvents alarmRecord = alarmEventsService.createAlarmRecord(deviceIp, level, smallType, desc, List.of(img)); + autoAssign(alarmRecord.getId(), deviceIp); + } + + + private void autoAssign(Long alarmId, String deviceIp) { + SaTokenContextMockUtil.setMockContext(() -> { + // 如果当前设备区域存在排班人员,那么惊醒自动指派操作 + List userGroupVos = remoteAttendanceService.queryAttendByCurrDateAndDeviceIp(new Date(), deviceIp); + if (CollUtil.isEmpty(userGroupVos)) { + return; + } + // 进行自动指派操作 + RemoteAttendanceUserGroupVo currHandlePerson = null; + if (userGroupVos.size() == 1) { + currHandlePerson = userGroupVos.get(0); + } else { + // 生成一个排班人员课表的随机数 + Random random = new Random(); + int randomIndex = random.nextInt(userGroupVos.size()); + currHandlePerson = userGroupVos.get(randomIndex); + } + // 获取当前指派人员的详细信息 + RemoteUserVo userInfo = remoteUserService.getUserInfoById(currHandlePerson.getEmployeeId()); + // 任务指派操作 + AlarmAssignmentBo bo = new AlarmAssignmentBo(); + bo.setAlarmId(alarmId); + bo.setSolveId(userInfo.getUserId()); + bo.setSolveName(userInfo.getUserName()); + bo.setSolvePhone(userInfo.getPhonenumber()); + bo.setSolveEmail(userInfo.getEmail()); + bo.setRemark("系统自动指派"); + alarmEventsService.taskAssignment(bo); + }); + } + } + diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisAlarmEventsServiceImpl.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisAlarmEventsServiceImpl.java index efe5de5b..109f0c20 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisAlarmEventsServiceImpl.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisAlarmEventsServiceImpl.java @@ -37,7 +37,6 @@ import org.dromara.sis.service.ISisAlarmEventProcessService; import org.dromara.sis.service.ISisAlarmEventsService; import org.dromara.sis.service.ISisDeviceManageService; import org.dromara.system.api.model.LoginUser; -import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -179,15 +178,14 @@ public class SisAlarmEventsServiceImpl implements ISisAlarmEventsService { return baseMapper.deleteByIds(ids) > 0; } - @Async @Override @Transactional(rollbackFor = Exception.class) - public void createAlarmRecord(String deviceIp, Integer level, EventSmallTypeEnum type, String msg, byte[] smallImg, byte[] bigImg) { + public SisAlarmEvents createAlarmRecord(String deviceIp, Integer level, EventSmallTypeEnum type, String msg, List imgs) { // 校验设备信息 SisDeviceManage sisDeviceManage = deviceManageService.queryByDeviceIp(deviceIp); if (sisDeviceManage == null) { log.error("设备信息不存在,放弃此条告警记录。"); - return; + return null; } // 生成时间信息 Date now = new Date(); @@ -223,18 +221,14 @@ public class SisAlarmEventsServiceImpl implements ISisAlarmEventsService { alarmEventProcess.setReceiveTaskTag(0L); alarmEventProcess.setTenantId(""); - // 写入附件表 List ls = new ArrayList<>(); - if (smallImg != null && smallImg.length > 0) { - ls.add(createEventAttachments(smallImg, alarmEvents, sisDeviceManage)); - } - if (bigImg != null && bigImg.length > 0) { - ls.add(createEventAttachments(bigImg, alarmEvents, sisDeviceManage)); + for (byte[] img : imgs) { + ls.add(createEventAttachments(img, alarmEvents, sisDeviceManage)); } Boolean flag = alarmEventAttachmentsService.batchInsert(ls); log.info("写入告警事件附件表完成, reslut={}, size={}", flag, ls.size()); - + return alarmEvents; } public SisAlarmEventAttachments createEventAttachments(byte[] img, SisAlarmEvents alarmEvents, SisDeviceManage sisDeviceManage) { diff --git a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisDeviceChannelServiceImpl.java b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisDeviceChannelServiceImpl.java index 90f7783c..4b05153a 100644 --- a/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisDeviceChannelServiceImpl.java +++ b/ruoyi-modules/Sis/src/main/java/org/dromara/sis/service/impl/SisDeviceChannelServiceImpl.java @@ -47,7 +47,7 @@ public class SisDeviceChannelServiceImpl implements ISisDeviceChannelService { private final SisDeviceChannelMapper baseMapper; private final ISisDeviceGroupService deviceGroupService; - private HikApiService hikApiService; + private final HikApiService hikApiService; @@ -239,6 +239,7 @@ public class SisDeviceChannelServiceImpl implements ISisDeviceChannelService { } } else if (DeviceTypeEnum.NVR.getType().equals(bo.getDeviceType()) || DeviceTypeEnum.DVR.getType().equals(bo.getDeviceType())) { DeviceInfo channelInfo = hikApiService.getChannelInfo(bo.getDeviceIp()); + if (channelInfo != null && CollUtil.isNotEmpty(channelInfo.getChannelInfo())) { List insertChannels = new ArrayList<>(channelInfo.getChannelInfo().size()); List updateChannels = new ArrayList<>(channelInfo.getChannelInfo().size()); diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/SysOssController.java b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/SysOssController.java index 1a0beb8c..f02c6bc5 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/SysOssController.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/controller/SysOssController.java @@ -3,20 +3,18 @@ package org.dromara.resource.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.ObjectUtil; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotEmpty; import lombok.RequiredArgsConstructor; import org.apache.dubbo.config.annotation.DubboReference; -import org.apache.dubbo.config.annotation.DubboService; -import org.dromara.common.core.constant.GlobalConstants; import org.dromara.common.core.domain.R; import org.dromara.common.core.validate.QueryGroup; -import org.dromara.common.redis.utils.RedisUtils; -import org.dromara.common.web.core.BaseController; import org.dromara.common.log.annotation.Log; import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.web.core.BaseController; import org.dromara.property.api.RemoteVisitoreGetCodeInfoService; -import org.dromara.resource.domain.QrCodeInfo; import org.dromara.resource.domain.bo.SysOssBo; import org.dromara.resource.domain.vo.SysOssUploadVo; import org.dromara.resource.domain.vo.SysOssVo; @@ -26,8 +24,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.constraints.NotEmpty; import java.io.IOException; import java.util.Arrays; import java.util.List; @@ -46,6 +42,7 @@ public class SysOssController extends BaseController { private final ISysOssService iSysOssService; @DubboReference private RemoteVisitoreGetCodeInfoService remoteVisitoreGetCodeInfoService; + /** * 查询OSS对象存储列表 */ @@ -96,17 +93,17 @@ public class SysOssController extends BaseController { // @SaCheckPermission("system:oss:upload") @Log(title = "OSS对象存储", businessType = BusinessType.INSERT) @PostMapping(value = "/qrupload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public R codeUpload(@RequestPart("file") MultipartFile file,String code) { + public R codeUpload(@RequestPart("file") MultipartFile file, String code) { if (ObjectUtil.isNull(file)) { return R.fail("上传文件不能为空"); } String codeInfo = remoteVisitoreGetCodeInfoService.getCodeInfo(code); // QrCodeInfo info = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY+"Qrcode" + code); - if (codeInfo.isEmpty()){ + if (codeInfo.isEmpty()) { return R.fail("二维码已过期"); } - SysOssVo oss = iSysOssService.qrupload(file,codeInfo); + SysOssVo oss = iSysOssService.qrupload(file, codeInfo); SysOssUploadVo uploadVo = new SysOssUploadVo(); uploadVo.setUrl(oss.getUrl()); uploadVo.setFileName(oss.getOriginalName()); @@ -125,6 +122,16 @@ public class SysOssController extends BaseController { iSysOssService.download(ossId, response); } + /** + * 输出图片到浏览器 + * + * @param ossId OSS对象ID + */ + @GetMapping(value = "/preview/{ossId}", produces = {MediaType.IMAGE_JPEG_VALUE, MediaType.IMAGE_PNG_VALUE}) + public byte [] preview(@PathVariable Long ossId) throws IOException { + return iSysOssService.downloadToByteArray(ossId); + } + /** * 删除OSS对象存储 * diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/service/ISysOssService.java b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/service/ISysOssService.java index 1b2a2b9c..f0957feb 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/service/ISysOssService.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/service/ISysOssService.java @@ -109,4 +109,5 @@ public interface ISysOssService { * @return byte[] 返回下载的字节数组 */ byte[] downloadToByteArray(Long ossId) throws IOException; + } diff --git a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/service/impl/SysOssServiceImpl.java index 48ab3a39..dc8359bc 100644 --- a/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-resource/src/main/java/org/dromara/resource/service/impl/SysOssServiceImpl.java @@ -306,5 +306,4 @@ public class SysOssServiceImpl implements ISysOssService { } return oss; } - }