Merge branch 'master' of http://47.109.37.87:3000/by2025/SmartParks
Some checks are pending
Gitea Actions Demo / Explore-Gitea-Actions (push) Waiting to run

This commit is contained in:
15683799673
2025-08-07 23:13:53 +08:00
42 changed files with 566 additions and 120 deletions

View File

@@ -0,0 +1,49 @@
package org.dromara.sis.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.web.core.BaseController;
import org.dromara.sis.domain.bo.SisAuthRecordBo;
import org.dromara.sis.service.ISisDataSyncService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 主动推送的同步数据
* 前端访问路由地址为:/sis/dataSync
*
* @author lsm
* @since 2025-07-14
*/
@Validated
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/dataSync")
public class SisDataSyncController extends BaseController {
private final ISisDataSyncService sisDataSyncService;
@SaCheckPermission("sis:dataSync:add")
@Log(title = "人员库授权", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping("/add")
public R<Void> add(@Validated(AddGroup.class) @RequestBody SisAuthRecordBo bo, HttpServletRequest request) {
log.info("开始同步报警记录数据...");
// return toAjax();
return R.ok();
}
}

View File

@@ -83,4 +83,9 @@ public class SisPersonLibImg extends TenantEntity {
*/
private String imgMd5Value;
/**
* 人员标签
*/
private Integer rosterType;
}

View File

@@ -91,4 +91,9 @@ public class SisPersonLibImgBo extends BaseEntity {
*/
private String imgMd5Value;
/**
* 人员标签
*/
private Integer rosterType;
}

View File

@@ -0,0 +1,32 @@
package org.dromara.sis.domain.enums;
import lombok.Getter;
/**
* @author lsm
* @apiNote RosterTypeEnum
* @since 2025/8/7
*/
@Getter
public enum RosterTypeEnum {
/**
* 红名单
*/
RED_LIST(1),
/**
* 白名单
*/
WHITE_LIST(2),
/**
* 黑名单名单
*/
BLACK_LIST(3);
private final Integer code;
RosterTypeEnum(Integer code) {
this.code = code;
}
}

View File

@@ -62,5 +62,9 @@ public class SisAuthRecordVo implements Serializable {
@ExcelProperty(value = "结束时间")
private Date endDate;
/**
* 人员标签
*/
private Integer rosterType;
}

View File

@@ -102,4 +102,10 @@ public class SisPersonLibImgVo implements Serializable {
*/
@ExcelProperty(value = "图片MD5")
private String imgMd5Value;
/**
* 人员标签
*/
@ExcelProperty(value = "人员标签")
private Integer rosterType;
}

View File

@@ -85,15 +85,15 @@ public class RemoteSisAuthServiceImpl implements RemoteSisAuthService {
}
/**
* 通过MD5查询图片id
* 通过MD5查询华为盒子id
*
* @param imgMd5 图片MD5
* @return Long
*/
@Override
public Long queryImgIdByImgMd5(String imgMd5) {
public Long queryHuaweiBoxIdByImgMd5(String imgMd5) {
SisPersonLibImgVo vo = sisPersonLibImgService.queryByImgMd5(imgMd5);
return vo != null ? vo.getId() : null;
return vo != null ? vo.getRemoteImgId() : null;
}
/**
@@ -118,6 +118,7 @@ public class RemoteSisAuthServiceImpl implements RemoteSisAuthService {
pId = huaWeiBoxApi.addPerson(List.of(req));
} catch (Exception e) {
log.error("同步华为盒子失败:{}----{}", person.getName(), person.getId());
return null;
}
return pId;
@@ -152,7 +153,7 @@ public class RemoteSisAuthServiceImpl implements RemoteSisAuthService {
try {
log.info("e8平台上传照片");
String e8ImgUrl = e8PlatformApi.uploadFace(imgByte);
Assert.notNull(e8ImgUrl, "图片上传E8平台失败");
Assert.notNull(e8ImgUrl, "图片上传E8平台失败" + person.getName() + "----" + person.getId());
log.info("e8平台上传照片完成");
count++; // 图片上传完成步进器+1
@@ -161,7 +162,7 @@ public class RemoteSisAuthServiceImpl implements RemoteSisAuthService {
req.setName(person.getName());
req.setGender(person.getSex() != 1 ? 0 : 1);
e8Id = e8PlatformApi.addCustomer(req).getId();
Assert.notNull(e8Id, "e8同步新建人员失败");
Assert.notNull(e8Id, "e8同步新建人员失败" + person.getName() + "----" + person.getId());
log.info("e8同步新建人员完成");
count++; // 新增人员完成步进器+1
@@ -172,7 +173,7 @@ public class RemoteSisAuthServiceImpl implements RemoteSisAuthService {
voucherReq.setTxtData(e8ImgUrl);
voucherReq.setCardType(34);
Long voucherId = e8PlatformApi.issueVoucher(voucherReq);
Assert.notNull(voucherId, "e8平台发行凭证失败");
Assert.notNull(voucherId, "e8平台发行凭证失败" + person.getName() + "----" + person.getId());
log.info("e8平台发行凭证成功");
count++; // 发行凭证完成步进器+1
@@ -199,11 +200,12 @@ public class RemoteSisAuthServiceImpl implements RemoteSisAuthService {
log.info("e8平台开始授权");
Boolean flag = e8PlatformApi.addCustomerAuth(authReq);
Assert.isTrue(flag, "E8平台授权失败");
Assert.isTrue(flag, "E8平台授权失败" + person.getName() + "----" + person.getId());
log.info("E8平台授权完成!");
count++; // 授权完成步进器+1
}
} catch (Exception e) {
log.info(e.getMessage());
return null;
}

View File

@@ -0,0 +1,7 @@
package org.dromara.sis.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.dromara.sis.domain.SisAlarmEvents;
public interface SisDataSyncMapper extends BaseMapper<SisAlarmEvents> {
}

View File

@@ -1,5 +1,7 @@
package org.dromara.sis.sdk.hik.service;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sis.sdk.hik.HCNetSDK;
@@ -18,7 +20,7 @@ public class CamearService extends SdkBaseServer {
/**
* 获取设备通道信息
*
* @return
* @return DeviceInfo
*/
public static DeviceInfo getDeviceChannelInfo(int lUserID) {
HCNetSDK.NET_DVR_IPPARACFG_V40 lpOutBuffer = new HCNetSDK.NET_DVR_IPPARACFG_V40();
@@ -77,4 +79,78 @@ public class CamearService extends SdkBaseServer {
return deviceInfo;
}
public static void isAPI(int lUserID, String url) {
// 输入参数
HCNetSDK.NET_DVR_XML_CONFIG_INPUT strInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
strInput.dwSize = strInput.size(); // 初始化结构体内存
// 2. 构造URL - 必须包含 \r\n 结束符
// String url = "GET /ISAPI/Intelligent/capabilities\r\n";
byte[] urlBytes = url.getBytes();
Memory urlMemory = new Memory(urlBytes.length + 1); // +1 for null terminator
urlMemory.write(0, urlBytes, 0, urlBytes.length);
urlMemory.setByte(urlBytes.length, (byte) 0); // 添加NUL终止符
strInput.lpRequestUrl = urlMemory;
strInput.dwRequestUrlLen = urlBytes.length; // 不包括NUL终止符
// 3. 输入缓冲区设为空指针
strInput.lpInBuffer = Pointer.NULL;
strInput.dwInBufferSize = 0;
// 输出参数
HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT strOutput = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
strOutput.dwSize = strOutput.size();
// 5. 分配输出缓冲区 (8KB)
int outBufSize = 8 * 1024;
Memory outBuffer = new Memory(outBufSize);
outBuffer.clear(); // 清零缓冲区
// 6. 分配状态缓冲区 (1KB)
int statusSize = 1024;
Memory statusBuffer = new Memory(statusSize);
statusBuffer.clear(); // 清零缓冲区
strOutput.lpOutBuffer = outBuffer;
strOutput.dwOutBufferSize = outBufSize;
strOutput.lpStatusBuffer = statusBuffer;
strOutput.dwStatusSize = statusSize;
// 7. 调用前写入结构体
strOutput.write(); // 将Java结构体写入本地内存
strOutput.write(); // 将Java结构体写入本地内存
// 调用SDK方法
boolean success = hcNetSDK.NET_DVR_STDXMLConfig(lUserID, strInput, strOutput);
if (!success) {
int errorCode = hcNetSDK.NET_DVR_GetLastError();
System.err.println("NET_DVR_STDXMLConfig failed, error code: " + errorCode);
// 打印状态信息帮助调试
if (strOutput.dwReturnedXMLSize > 0) {
String status = statusBuffer.getString(0);
System.err.println("Status: " + status);
}
} else {
System.out.println("NET_DVR_STDXMLConfig successfully!");
// 9. 读取前同步结构体字段
strOutput.read(); // 从本地内存读取更新后的结构体
// 检查实际返回的数据大小
int returnedSize = strOutput.dwReturnedXMLSize;
if (returnedSize > 0) {
// 使用正确的长度读取字符串
String xmlResponse = outBuffer.getString(0);
System.out.println("Response size: " + returnedSize);
System.out.println(xmlResponse);
} else {
System.out.println("No data returned");
}
}
}
}

View File

@@ -0,0 +1,7 @@
package org.dromara.sis.service;
/**
* 告警数据同步Service接口
*/
public interface ISisDataSyncService {
}

View File

@@ -18,6 +18,7 @@ import org.dromara.sis.api.domain.RemotePersonAuth;
import org.dromara.sis.domain.bo.SisAccessControlBo;
import org.dromara.sis.domain.bo.SisElevatorInfoBo;
import org.dromara.sis.domain.bo.SisPersonLibImgBo;
import org.dromara.sis.domain.enums.RosterTypeEnum;
import org.dromara.sis.domain.vo.SisAccessControlVo;
import org.dromara.sis.domain.vo.SisElevatorInfoVo;
import org.dromara.sis.domain.vo.SisPersonLibImgVo;
@@ -115,30 +116,34 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService {
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean insertByPerson(RemotePersonAuth bo) {
SisAuthRecord add = new SisAuthRecord();
add.setTargetType(1L);
add.setTargetId(bo.getId());
add.setGroupId(bo.getAuthGroupId());
add.setBegDate(bo.getAuthBegDate());
add.setEndDate(bo.getAuthEndDate());
add.setTenantId("000000");
boolean flag = baseMapper.insert(add) > 0;
Assert.isTrue(flag, "新增授权记录失败");
// 黑名单不加授权记录
if (!Objects.equals(bo.getRosterType(), RosterTypeEnum.BLACK_LIST.getCode())) {
SisAuthRecord add = new SisAuthRecord();
add.setTargetType(1L);
add.setTargetId(bo.getId());
add.setGroupId(bo.getAuthGroupId());
add.setBegDate(bo.getAuthBegDate());
add.setEndDate(bo.getAuthEndDate());
add.setTenantId("000000");
boolean flag = baseMapper.insert(add) > 0;
Assert.isTrue(flag, "新增授权记录失败");
}
try {
// 记录图片md5值
byte[] imgByte = remoteFileService.downloadToByteArray(Long.parseLong(bo.getOssId()));
String md5 = calculateMD5(imgByte);
// 写入安防人像信息
this.syncPersonImg(bo, md5);
Boolean sync = this.syncPersonImg(bo, md5);
Assert.isTrue(sync, "写入安防人像信息失败");
} catch (Exception e) {
log.info("下载图片失败");
log.info(e.getMessage());
}
return flag;
return true;
}
private void syncPersonImg(RemotePersonAuth bo, String md5) {
private Boolean syncPersonImg(RemotePersonAuth bo, String md5) {
log.info("开始写入安防人像信息");
SisPersonLibImgBo personLibImg = new SisPersonLibImgBo();
personLibImg.setImgOssId(Long.parseLong(bo.getOssId()));
@@ -149,8 +154,10 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService {
personLibImg.setCertificateNo(bo.getIdCardNumber());
personLibImg.setResidentPersonId(bo.getId());
personLibImg.setImgMd5Value(md5);
sisPersonLibImgService.insertByBo(personLibImg);
log.info("写入安防人像信息完成");
personLibImg.setRosterType(bo.getRosterType());
Boolean flag = sisPersonLibImgService.insertByBo(personLibImg);
if (flag) log.info("写入安防人像信息完成");
return flag;
}
/**
@@ -352,28 +359,26 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService {
public Boolean deleteByPersonIds(Collection<Long> ids, Collection<Long> e8Ids) {
LambdaQueryWrapper<SisAuthRecord> lqw = new LambdaQueryWrapper<>();
lqw.in(SisAuthRecord::getTargetId, ids);
boolean flag = baseMapper.delete(lqw) > 0;
Assert.isTrue(flag, "删除授权记录失败");
baseMapper.delete(lqw);
if (flag) {
List<SisPersonLibImgVo> list = new ArrayList<>();
ids.forEach(id -> {
SisPersonLibImgVo imgVo = sisPersonLibImgService.queryByPersonId(id);
if (imgVo != null) {
list.add(imgVo);
}
});
Collection<Long> imgIds = list.stream().map(SisPersonLibImgVo::getId).toList();
if (CollUtil.isNotEmpty(imgIds)){
flag = sisPersonLibImgService.deleteWithValidByIds(imgIds, false);
Assert.isTrue(flag, "删除人像库图片失败");
}
if (CollUtil.isNotEmpty(e8Ids)){
e8Ids.forEach(e8PlatformApi::deleteCustomer);
List<SisPersonLibImgVo> list = new ArrayList<>();
ids.forEach(id -> {
SisPersonLibImgVo imgVo = sisPersonLibImgService.queryByPersonId(id);
if (imgVo != null) {
list.add(imgVo);
}
});
Collection<Long> imgIds = list.stream().map(SisPersonLibImgVo::getId).toList();
if (CollUtil.isNotEmpty(imgIds)) {
Boolean flag = sisPersonLibImgService.deleteWithValidByIds(imgIds, false);
Assert.isTrue(flag, "删除人像库图片失败");
}
return flag;
if (CollUtil.isNotEmpty(e8Ids)) {
e8Ids.forEach(e8PlatformApi::deleteCustomer);
}
return true;
}
/**
@@ -382,7 +387,7 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService {
* @param groupIds 权限组IDs
*/
@Override
public Boolean queryByGroupIds(Collection<Long> groupIds){
public Boolean queryByGroupIds(Collection<Long> groupIds) {
LambdaQueryWrapper<SisAuthRecord> lqw = Wrappers.lambdaQuery();
lqw.in(SisAuthRecord::getGroupId, groupIds);
List<SisAuthRecordVo> authVoList = baseMapper.selectVoList(lqw);

View File

@@ -0,0 +1,15 @@
package org.dromara.sis.service.impl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.sis.service.ISisDataSyncService;
import org.springframework.stereotype.Service;
/**
* 告警数据同步Service业务层处理
*/
@Slf4j
@RequiredArgsConstructor
@Service
public class SisDataSyncServiceImpl implements ISisDataSyncService {
}

View File

@@ -8,6 +8,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.property.api.RemoteFloorService;
import org.dromara.sis.domain.enums.RosterTypeEnum;
import org.dromara.sis.domain.vo.*;
import org.dromara.sis.producer.CleanLiftAuthRocketProducer;
import org.dromara.sis.sdk.e8.E8PlatformApi;
@@ -70,6 +71,12 @@ public class ZeroSensationPassageServiceImpl implements IZeroSensationPassageSer
// 不是内部人员 产生紧急的告警信息
alarmEventsService.createAlarmRecord(deviceIp, 1, 1, "陌生人员入内", smallImg, bigImg);
return;
}else {
if (Objects.equals(authRecord.getRosterType(), RosterTypeEnum.BLACK_LIST.getCode())) {
log.info("人员[{}]在黑名单中,暂不处理。", person);
alarmEventsService.createAlarmRecord(deviceIp, 3, 1, "黑名单人员入内", smallImg, bigImg);
return;
}
}
Date now = new Date();

View File

@@ -5,8 +5,11 @@ import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.property.api.RemoteFloorService;
import org.dromara.property.api.domain.vo.RemoteFloorVo;
import org.dromara.sis.domain.AlarmRecord;
import org.dromara.sis.domain.SisAlarmEvents;
import org.dromara.sis.domain.bo.SisAlarmEventsBo;
import org.dromara.sis.service.AlarmRecordService;
import org.dromara.sis.service.ApiService;
import org.dromara.sis.service.ISisAlarmEventsService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@@ -24,13 +27,15 @@ public class DataSyncTask {
private final ApiService apiService;
private final AlarmRecordService alarmRecordService;
private final ISisAlarmEventsService sisAlarmEventsService;
@Value("${sync.pageSize:100}")
private int pageSize;
public DataSyncTask(ApiService apiService, AlarmRecordService alarmRecordService) {
public DataSyncTask(ApiService apiService, AlarmRecordService alarmRecordService, ISisAlarmEventsService sisAlarmEventsService) {
this.apiService = apiService;
this.alarmRecordService = alarmRecordService;
this.sisAlarmEventsService = sisAlarmEventsService;
}
/**
@@ -72,11 +77,29 @@ public class DataSyncTask {
// 提取操作记录数据
Map<Long, List<Map<String, Object>>> operatorMap = new HashMap<>();
for (Map<String, Object> recordMap : recordList) {
Long recordId = Long.valueOf((Integer)recordMap.get("Id"));
Long recordId = Long.valueOf((Integer) recordMap.get("Id"));
List<Map<String, Object>> operators = (List<Map<String, Object>>) recordMap.get("TaskOperators");
if (operators != null && !operators.isEmpty()) {
operatorMap.put(recordId, operators);
}
//同步成功后将两张表的数据合并到alarmEvents表中
SisAlarmEventsBo sisAlarmEvents = new SisAlarmEventsBo();
sisAlarmEvents.setId(recordId);
sisAlarmEvents.setType(Long.valueOf((Integer) recordMap.get("Type")));
sisAlarmEvents.setLevel(Long.valueOf((Integer) recordMap.get("Level")));
sisAlarmEvents.setDeviceIp((String) recordMap.get("DeviceSipNum"));
sisAlarmEvents.setDeviceName(recordMap.get("DeviceName").toString());
sisAlarmEvents.setDeviceGroupId(Long.valueOf((Integer) recordMap.get("GroupId")));
sisAlarmEvents.setDeviceGroupName(recordMap.get("GroupName").toString());
sisAlarmEvents.setReportTime((Date) recordMap.get("StartTime"));
sisAlarmEvents.setState((Integer) recordMap.get("State"));
if ((Integer) recordMap.get("State") == 3) {
sisAlarmEvents.setWorkOrderId(Long.valueOf((Integer) recordMap.get("WorkOrderId")));
}
//保存报警事件
sisAlarmEventsService.insertByBo(sisAlarmEvents);
}
// 保存数据(包含操作记录)

View File

@@ -5,7 +5,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<mapper namespace="org.dromara.sis.mapper.SisAuthRecordMapper">
<select id="checkAuth" resultType="org.dromara.sis.domain.vo.SisAuthRecordVo">
SELECT c.target_id, c.group_id, c.beg_date, c.end_date
SELECT c.target_id, c.group_id, c.beg_date, c.end_date, a.roster_type
FROM sis_person_lib_img a
LEFT JOIN resident_person b ON a.resident_person_id = b.id and b.state = 1
LEFT JOIN sis_auth_record c