Merge branch 'master' of http://47.109.37.87:3000/by2025/SmartParks
This commit is contained in:
@@ -18,6 +18,15 @@ public interface RemoteAttendanceService {
|
||||
* @param date 查询时间
|
||||
* @return 返回排班人员信息
|
||||
*/
|
||||
public List<RemoteAttendanceUserGroupVo> queryAttendPersonInfo(Date date);
|
||||
List<RemoteAttendanceUserGroupVo> queryAttendPersonInfo(Date date);
|
||||
|
||||
/**
|
||||
* 根据时间和设备ip查询当前设备所处区域的排班人员信息
|
||||
*
|
||||
* @param date 查询时间
|
||||
* @param deviceIp 设备ip
|
||||
* @return 返回排班人员信息
|
||||
*/
|
||||
List<RemoteAttendanceUserGroupVo> queryAttendByCurrDateAndDeviceIp(Date date, String deviceIp);
|
||||
|
||||
}
|
||||
|
@@ -49,5 +49,4 @@ public class RemoteAttendanceUserGroupVo implements Serializable {
|
||||
*/
|
||||
private LocalDate endDate;
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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<TbMeterInfoVo> 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<List<TreeNode<Long>>> queryMeterInfoTree(@PathVariable("meterType") Long meterType) {
|
||||
return R.ok(tbMeterInfoService.queryMeterInfoTree(meterType));
|
||||
@GetMapping("/tree")
|
||||
public R<List<TreeNode<Long>>> queryMeterInfoTree(@RequestParam Long meterType, @RequestParam Boolean isMeter) {
|
||||
return R.ok(tbMeterInfoService.queryMeterInfoTree(meterType, isMeter));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取水/电/气表当前读数/状态
|
||||
*
|
||||
* @param meterType 水电气类型
|
||||
* @param floorId 楼栋id
|
||||
*/
|
||||
@GetMapping("/currentReading")
|
||||
public R<Void> currentReading(@RequestParam Long meterType, @RequestParam Long floorId) {
|
||||
tbMeterInfoService.getMeterStatus(meterType, floorId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -41,6 +41,10 @@ public class ServiceWorkOrdersType extends TenantEntity {
|
||||
* 运作模式(0派单+抢单,1派单,2自动派单)
|
||||
*/
|
||||
private String operationMode;
|
||||
/**
|
||||
*部门id
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 排序值
|
||||
|
@@ -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;
|
||||
/**
|
||||
* 运作模式
|
||||
*/
|
||||
|
@@ -44,6 +44,14 @@ public class ServiceWorkOrdersTypeVo implements Serializable {
|
||||
*/
|
||||
@ExcelProperty(value = "工单类型名称")
|
||||
private String orderTypeName;
|
||||
/**
|
||||
*部门id
|
||||
*/
|
||||
private Long deptId;
|
||||
/**
|
||||
*部门名称
|
||||
*/
|
||||
private String deptName;
|
||||
|
||||
/**
|
||||
* 运作模式
|
||||
|
@@ -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<RemoteAttendanceUserGroupVo> queryAttendPersonInfo(Date date) {
|
||||
@@ -33,4 +36,12 @@ public class RemoteAttendanceServiceImpl implements RemoteAttendanceService {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RemoteAttendanceUserGroupVo> queryAttendByCurrDateAndDeviceIp(Date date, String deviceIp) {
|
||||
List<AttendanceUserGroupVo> ls = attendanceUserGroupService.queryAttendByCurrDateAndDeviceIp(date, deviceIp);
|
||||
if (CollUtil.isNotEmpty(ls)) {
|
||||
return BeanUtil.copyToList(ls, RemoteAttendanceUserGroupVo.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -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<AttendanceUserGroup, AttendanceUserGroupVo> {
|
||||
|
||||
/**
|
||||
* 根据日期和设备ip 查询当前设备所在区域的排班人员信息
|
||||
*
|
||||
* @param date 查询日期
|
||||
* @param deviceIp 设备ip
|
||||
* @return 返回排班人员列表
|
||||
*/
|
||||
List<AttendanceUserGroupVo> queryAttendByCurrDateAndDeviceIp(@Param("currDate") Date currDate, @Param("deviceIp") String deviceIp);
|
||||
}
|
||||
|
@@ -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<Long> ids, Boolean isValid);
|
||||
|
||||
}
|
||||
|
@@ -75,6 +75,15 @@ public interface IAttendanceUserGroupService {
|
||||
*/
|
||||
List<AttendanceUserGroupVo> queryAttendPersonInfo(Date date);
|
||||
|
||||
|
||||
TableDataInfo<AttendanceUserGroupVo> queryScheduleView(AttendanceUserGroupBo bo, PageQuery pageQuery);
|
||||
|
||||
/**
|
||||
* 根据日期和设备ip 查询当前设备所在区域的排班人员信息
|
||||
*
|
||||
* @param date 查询日期
|
||||
* @param deviceIp 设备ip
|
||||
* @return 返回排班人员列表
|
||||
*/
|
||||
List<AttendanceUserGroupVo> queryAttendByCurrDateAndDeviceIp(Date date, String deviceIp);
|
||||
}
|
||||
|
@@ -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<AttendanceUserGroup> attendanceUserGroups = RedisUtils.getCacheList(DateUtil.today());
|
||||
if (CollUtil.isEmpty(attendanceUserGroups)) {
|
||||
attendanceUserGroups = attendanceUserGroupMapper.selectList(
|
||||
new LambdaQueryWrapper<AttendanceUserGroup>()
|
||||
.le(AttendanceUserGroup::getStartDate, today)
|
||||
.ge(AttendanceUserGroup::getEndDate, today)
|
||||
.orderByAsc(AttendanceUserGroup::getCreateTime)
|
||||
);
|
||||
List<AttendanceUserGroup> attendanceUserGroupList = attendanceUserGroupMapper.selectList(
|
||||
new LambdaQueryWrapper<AttendanceUserGroup>()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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<ServiceWorkOrdersTypeVo> queryPageList(ServiceWorkOrdersTypeBo bo, PageQuery pageQuery) {
|
||||
LambdaQueryWrapper<ServiceWorkOrdersType> lqw = buildQueryWrapper(bo);
|
||||
Page<ServiceWorkOrdersTypeVo> 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<ServiceWorkOrdersTypeVo> queryList(ServiceWorkOrdersTypeBo bo) {
|
||||
LambdaQueryWrapper<ServiceWorkOrdersType> lqw = buildQueryWrapper(bo);
|
||||
return baseMapper.selectVoList(lqw);
|
||||
List<ServiceWorkOrdersTypeVo> 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<ServiceWorkOrdersType> buildQueryWrapper(ServiceWorkOrdersTypeBo bo) {
|
||||
|
@@ -299,4 +299,9 @@ public class AttendanceUserGroupServiceImpl implements IAttendanceUserGroupServi
|
||||
return TableDataInfo.build(attendanceArrangementVoPage);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AttendanceUserGroupVo> queryAttendByCurrDateAndDeviceIp(Date date, String deviceIp) {
|
||||
return this.baseMapper.queryAttendByCurrDateAndDeviceIp(date, deviceIp);
|
||||
}
|
||||
}
|
||||
|
@@ -118,10 +118,11 @@ public class CleanOrderServiceImpl implements ICleanOrderService {
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<CleanOrder> buildQueryWrapper(CleanOrderBo bo) {
|
||||
private LambdaQueryWrapper<CleanOrder>buildQueryWrapper(CleanOrderBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<CleanOrder> 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());
|
||||
|
||||
|
@@ -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<TbMeterInfo> 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<TreeNode<Long>> queryMeterInfoTree(Long meterType) {
|
||||
public List<TreeNode<Long>> queryMeterInfoTree(Long meterType, Boolean isMeter) {
|
||||
// 默认加载社区树
|
||||
List<TreeNode<Long>> treeList = new ArrayList<>();
|
||||
List<TbCommunityVo> tbCommunityVos = communityService.queryAll();
|
||||
@@ -223,20 +235,159 @@ public class TbMeterInfoServiceImpl implements ITbMeterInfoService {
|
||||
}).toList();
|
||||
treeList.addAll(l3);
|
||||
|
||||
TbMeterInfoBo bo = new TbMeterInfoBo();
|
||||
bo.setMeterType(meterType);
|
||||
List<TbMeterInfoVo> meterInfoVos = this.queryList(bo);
|
||||
if (meterInfoVos != null && !meterInfoVos.isEmpty()) {
|
||||
List<TreeNode<Long>> l4 = meterInfoVos.stream().map(item -> {
|
||||
TreeNode<Long> 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<TbMeterInfoVo> meterInfoVos = this.queryList(bo);
|
||||
if (meterInfoVos != null && !meterInfoVos.isEmpty()) {
|
||||
List<TreeNode<Long>> l4 = meterInfoVos.stream().map(item -> {
|
||||
TreeNode<Long> 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<TbMeterInfoVo> 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<String, Long> ipCountMap = new HashMap<>();
|
||||
for (String ip : hostIpArr) {
|
||||
ipCountMap.put(ip, baseMapper.selectCount(new LambdaQueryWrapper<TbMeterInfo>()
|
||||
.eq(TbMeterInfo::getHostIp, ip)));
|
||||
}
|
||||
|
||||
// 启动定时任务
|
||||
heartbeatTasks.startHeartbeatTask("Meter_Status_Reading", () -> {
|
||||
jsonObject.put("readingTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
List<MeterResult> 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<TbMeterInfoVo> 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<MeterResult> meterResults, List<TbMeterInfoVo> meterInfoVoList, WebSocketMessageDto webSocketMessage) {
|
||||
// 创建IP到结果的映射,提高查找效率
|
||||
Map<String, MeterResult> 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<Float> 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);
|
||||
}
|
||||
}
|
||||
|
@@ -238,50 +238,74 @@ public class TbMeterRecordServiceImpl implements ITbMeterRecordService {
|
||||
public Map<String, Object> getEnergyTrend(String floorId, String meterId, Long meterType, String day, String month, String year) {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
|
||||
// hour
|
||||
List<Map<String, Object>> 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<String, Object> todayMap = trendHourData(floorId, meterId, meterType, day);
|
||||
// yesterdayHour
|
||||
Map<String, Object> yesterdayMap = trendHourData(floorId, meterId, meterType, yesterday);
|
||||
|
||||
Map<String, Object> 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<Map<String, Object>> 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<String, Object> nowMonthMap = trendDayData(floorId, meterId, meterType, monthArr[0], monthArr[1]);
|
||||
// lastMonth
|
||||
Map<String, Object> lastMonthMap = trendDayData(floorId, meterId, meterType, monthArr[0], lastMonth);
|
||||
|
||||
Map<String, Object> 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<String, Object> nowYearMap = trendMonthData(floorId, meterId, meterType, year);
|
||||
// lastYear
|
||||
Map<String, Object> lastYearMap = trendMonthData(floorId, meterId, meterType, lastYear);
|
||||
|
||||
// month
|
||||
List<Map<String, Object>> monthList = baseMapper.getMonthTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, year);
|
||||
Map<String, Object> 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<String, Object> trendHourData(String floorId, String meterId, Long meterType, String day) {
|
||||
Map<String, Object> hourMap = new HashMap<>();
|
||||
List<Map<String, Object>> hourList = baseMapper.getHourTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, day);
|
||||
List<String[]> 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<String, Object> trendDayData(String floorId, String meterId, Long meterType, String year, String month) {
|
||||
Map<String, Object> dayMap = new HashMap<>();
|
||||
List<Map<String, Object>> dayList = baseMapper.getDayTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, year, month);
|
||||
List<String[]> 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<String, Object> trendMonthData(String floorId, String meterId, Long meterType, String year) {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
List<Map<String, Object>> monthList = baseMapper.getMonthTrend(StrUtil.isBlank(floorId) ? null : Long.parseLong(floorId), StrUtil.isBlank(meterId) ? null : Long.parseLong(meterId), meterType, year);
|
||||
List<String[]> 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;
|
||||
}
|
||||
}
|
||||
|
@@ -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<TreeNode<Long>> queryMeterInfoTree(Long meterType);
|
||||
List<TreeNode<Long>> queryMeterInfoTree(Long meterType, Boolean isMeter);
|
||||
|
||||
/**
|
||||
* 获取水/电/气表当前读数/状态
|
||||
*
|
||||
* @param meterType 水电气类型
|
||||
* @param floorId 楼栋id
|
||||
*/
|
||||
void getMeterStatus(Long meterType, Long floorId);
|
||||
}
|
||||
|
@@ -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<String, ScheduledFuture<?>> 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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<T> {
|
||||
private Integer code;
|
||||
private T data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取水/电/气表当前读数
|
||||
*/
|
||||
public List<MeterResult> getMeterStatus(Map<String, Long> 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<List<MeterResult>> result = JSONUtil.toBean(post, new TypeReference<Result<List<MeterResult>>>() {}, true);
|
||||
return result.getData();
|
||||
}
|
||||
|
||||
}
|
@@ -4,4 +4,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.dromara.property.mapper.attendanceMapper.AttendanceUserGroupMapper">
|
||||
|
||||
<select id="queryAttendByCurrDateAndDeviceIp"
|
||||
resultType="org.dromara.property.domain.vo.attendanceVo.AttendanceUserGroupVo">
|
||||
|
||||
SELECT
|
||||
a.*
|
||||
FROM
|
||||
attendance_user_group a
|
||||
LEFT JOIN attendance_arrangement_area b ON a.schedule_id = b.shcedule_id
|
||||
LEFT JOIN attendance_area_device c ON b.area_id = c.area_id
|
||||
LEFT JOIN sis_device_manage d ON c.device_manage_id = d.id
|
||||
WHERE
|
||||
d.device_ip = #{deviceIp}
|
||||
AND a.start_date <= #{currDate}
|
||||
AND a.end_date > #{currDate}
|
||||
|
||||
</select>
|
||||
</mapper>
|
||||
|
@@ -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, "用户登录异常"),
|
||||
|
@@ -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";
|
||||
}
|
||||
|
@@ -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<MessageExt> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
@@ -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<MessageExt> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -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<MessageExt> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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);
|
||||
|
||||
}
|
@@ -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<byte[]> imgs);
|
||||
|
||||
/**
|
||||
* 任务分配操作
|
||||
|
@@ -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);
|
||||
|
||||
}
|
@@ -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<SisDeviceBindRefVo> bindRefList = deviceBindRefService.queryByDeviceIp(deviceIp);
|
||||
List<SisDeviceBindRefVo> 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<SisElevatorFloorChannelRefVo> 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<byte[]> 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<RemoteAttendanceUserGroupVo> 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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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<byte[]> 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<SisAlarmEventAttachments> 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) {
|
||||
|
@@ -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<SisDeviceChannel> insertChannels = new ArrayList<>(channelInfo.getChannelInfo().size());
|
||||
List<SisDeviceChannel> updateChannels = new ArrayList<>(channelInfo.getChannelInfo().size());
|
||||
|
@@ -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<SysOssUploadVo> codeUpload(@RequestPart("file") MultipartFile file,String code) {
|
||||
public R<SysOssUploadVo> 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对象存储
|
||||
*
|
||||
|
@@ -109,4 +109,5 @@ public interface ISysOssService {
|
||||
* @return byte[] 返回下载的字节数组
|
||||
*/
|
||||
byte[] downloadToByteArray(Long ossId) throws IOException;
|
||||
|
||||
}
|
||||
|
@@ -306,5 +306,4 @@ public class SysOssServiceImpl implements ISysOssService {
|
||||
}
|
||||
return oss;
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user