fix(sis): 优化人脸照片同步和授权记录更新逻辑

This commit is contained in:
2025-07-29 18:37:03 +08:00
parent 64c3355e05
commit 21985e48e7
15 changed files with 279 additions and 30 deletions

View File

@@ -25,6 +25,8 @@ public class RemoteResidentPersonVo implements Serializable {
private Long gender;
private String phone;
private String idCard;
private Long authGroupId;

View File

@@ -10,4 +10,6 @@ import org.dromara.sis.api.domain.RemotePersonAuth;
public interface RemoteSisAuth {
Boolean personAuth(RemotePersonAuth personAuth);
Boolean updatePersonAuth(RemotePersonAuth personAuth);
}

View File

@@ -27,6 +27,8 @@ public class RemotePersonAuth implements Serializable {
private String email;
private Long e8Id;
private Integer cardType = 1;
private String idCardNumber;

View File

@@ -1,6 +1,7 @@
package org.dromara.property.service.impl;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
@@ -159,15 +160,60 @@ public class ResidentPersonServiceImpl implements IResidentPersonService {
@Override
public Boolean updateByBo(ResidentPersonBo bo) {
ResidentPerson update = MapstructUtils.convert(bo, ResidentPerson.class);
validEntityBeforeUpdate(update);
return baseMapper.updateById(update) > 0;
assert update != null;
boolean flag;
// 人脸照片存在时,才同步修改授权
if (update.getAuthGroupId() != null && update.getAuthEndDate() != null && update.getImg() != null) {
ResidentPersonVo vo = queryById(update.getId());
Long e8Id = vo.getEEightId();
flag = baseMapper.updateById(update) > 0;
// 显式移除e8id
LambdaUpdateWrapper<ResidentPerson> lqw = new LambdaUpdateWrapper<>();
lqw.eq(ResidentPerson::getId, update.getId())
.set(ResidentPerson::getEEightId, "");
baseMapper.update(lqw);
if (flag) {
log.info("开始修改授权记录, {}", bo.getUserName());
RemotePersonAuth personAuth = new RemotePersonAuth();
personAuth.setId(update.getId());
personAuth.setName(update.getUserName());
personAuth.setSex(update.getGender().intValue());
personAuth.setPhone(update.getPhone());
personAuth.setEmail(update.getEmail());
personAuth.setIdCardNumber(update.getIdCard());
personAuth.setOssId(update.getImg());
personAuth.setCarNumber(update.getCarNumber());
personAuth.setE8Id(e8Id);
personAuth.setAuthGroupId(update.getAuthGroupId());
personAuth.setAuthBegDate(update.getAuthBegDate());
personAuth.setAuthEndDate(update.getAuthEndDate());
Boolean auth = remoteSisAuth.updatePersonAuth(personAuth);
Assert.isTrue(auth, "修改授权记录失败!");
}
} else {
flag = baseMapper.updateById(update) > 0;
}
Assert.isTrue(flag, "修改入驻员工失败!");
return flag;
}
/**
* 保存前的数据校验
*/
private void validEntityBeforeUpdate(ResidentPerson entity) {
//TODO 做一些数据校验,如唯一约束
LambdaQueryWrapper<ResidentPerson> lqw = Wrappers.lambdaQuery();
lqw.eq(ResidentPerson::getIdCard, entity.getIdCard())
.eq(ResidentPerson::getUnitId, entity.getUnitId());
boolean exists = baseMapper.exists(lqw);
Assert.isTrue(!exists, "当前单位,{}已存在!", entity.getUserName());
}
/**

View File

@@ -83,13 +83,13 @@ public class SisAuthRecordController extends BaseController {
/**
* 修改授权记录
*/
@SaCheckPermission("sis:authRecord:edit")
@Log(title = "授权记录", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody SisAuthRecordBo bo) {
return toAjax(sisAuthRecordService.updateByBo(bo));
}
// @SaCheckPermission("sis:authRecord:edit")
// @Log(title = "授权记录", businessType = BusinessType.UPDATE)
// @RepeatSubmit()
// @PutMapping()
// public R<Void> edit(@Validated(EditGroup.class) @RequestBody SisAuthRecordBo bo) {
// return toAjax(sisAuthRecordService.updateByBo(bo));
// }
/**
* 删除授权记录

View File

@@ -78,4 +78,9 @@ public class SisPersonLibImg extends TenantEntity {
*/
private Long residentPersonId;
/**
* 图片MD5
*/
private String imgMd5Value;
}

View File

@@ -86,4 +86,9 @@ public class SisPersonLibImgBo extends BaseEntity {
*/
private Long residentPersonId;
/**
* 图片MD5
*/
private String imgMd5Value;
}

View File

@@ -96,4 +96,10 @@ public class SisPersonLibImgVo implements Serializable {
*/
@ExcelProperty(value = "入驻员工id")
private Long residentPersonId;
/**
* 图片MD5
*/
@ExcelProperty(value = "图片MD5")
private String imgMd5Value;
}

View File

@@ -23,4 +23,9 @@ public class RemoteSisAuthImpl implements RemoteSisAuth {
public Boolean personAuth(RemotePersonAuth personAuth) {
return sisAuthRecordService.insertByPerson(personAuth);
}
@Override
public Boolean updatePersonAuth(RemotePersonAuth personAuth) {
return sisAuthRecordService.updateByBo(personAuth);
}
}

View File

@@ -52,12 +52,12 @@ public interface ISisAuthRecordService {
Boolean insertByPerson(RemotePersonAuth bo);
/**
* 修改授权记录
* 修改授权记录(单个)
*
* @param bo 授权记录
* @return 是否修改成功
*/
Boolean updateByBo(SisAuthRecordBo bo);
Boolean updateByBo(RemotePersonAuth bo);
/**
* 校验并批量删除授权记录信息

View File

@@ -79,7 +79,23 @@ public interface ISisPersonLibImgService {
*
* @param personId 入驻员工id
* @param huaweiBoxId 华为盒子图像id
* @param imgMd5 图片md5值
* @return Boolean
*/
Boolean updateByPersonId(Long personId, Long huaweiBoxId);
Boolean updateByPersonId(Long personId, Long huaweiBoxId, String imgMd5);
/**
* 根据图片MD5查询图片
*
* @param imgMd5 图片MD5
*/
SisPersonLibImgVo queryByImgMd5(String imgMd5);
/**
* 根据入驻员工id查询图片
*
* @param personId 入驻员工id
*/
SisPersonLibImgVo queryByPersonId(Long personId);
}

View File

@@ -13,12 +13,16 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.property.api.RemoteFloorService;
import org.dromara.property.api.domain.vo.RemoteFloorVo;
import org.dromara.resource.api.RemoteFileService;
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.vo.SisAccessControlVo;
import org.dromara.sis.domain.vo.SisElevatorInfoVo;
import org.dromara.sis.domain.vo.SisPersonLibImgVo;
import org.dromara.sis.sdk.e8.E8PlatformApi;
import org.dromara.sis.sdk.huawei.HuaWeiBoxApi;
import org.dromara.sis.service.*;
import org.springframework.stereotype.Service;
import org.dromara.sis.domain.bo.SisAuthRecordBo;
@@ -27,6 +31,7 @@ import org.dromara.sis.domain.SisAuthRecord;
import org.dromara.sis.mapper.SisAuthRecordMapper;
import org.springframework.transaction.annotation.Transactional;
import java.security.MessageDigest;
import java.util.*;
/**
@@ -40,6 +45,8 @@ import java.util.*;
@Service
public class SisAuthRecordServiceImpl implements ISisAuthRecordService {
private final E8PlatformApi e8PlatformApi;
private final SisAuthRecordMapper baseMapper;
private final ISisElevatorInfoService elevatorInfoService;
private final ISisPersonLibImgService sisPersonLibImgService;
@@ -48,6 +55,9 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService {
@DubboReference
private RemoteFloorService remoteFloorService;
@DubboReference
private RemoteFileService remoteFileService;
/**
* 查询授权记录
*
@@ -112,30 +122,69 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService {
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 (flag) {
try {
// 记录图片md5值
byte[] imgByte = remoteFileService.downloadToByteArray(Long.parseLong(bo.getOssId()));
String md5 = calculateMD5(imgByte);
// 写入安防人像信息
this.syncPersonImg(bo);
this.syncPersonImg(bo, md5);
} catch (Exception e) {
log.info("下载图片失败");
}
return flag;
}
private void syncPersonImg(RemotePersonAuth bo) {
private void syncPersonImg(RemotePersonAuth bo, String md5) {
log.info("开始写入安防人像信息");
SisPersonLibImgBo personLibImg = new SisPersonLibImgBo();
personLibImg.setImgOssId(Long.parseLong(bo.getOssId()));
personLibImg.setTel(bo.getPhone());
personLibImg.setImgName(bo.getName());
personLibImg.setSex(bo.getSex());
personLibImg.setCertificateType(1);
personLibImg.setCertificateNo(bo.getIdCardNumber());
personLibImg.setResidentPersonId(bo.getId());
personLibImg.setImgMd5Value(md5);
sisPersonLibImgService.insertByBo(personLibImg);
log.info("写入安防人像信息完成");
}
/**
* 直接计算字节数组的MD5值
*
* @param data 图片的字节数组
* @return 32位小写MD5字符串
*/
private String calculateMD5(byte[] data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("输入数据不能为null");
}
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(data);
return bytesToHex(md.digest());
}
/**
* 字节数组转十六进制字符串
*
* @param bytes 字节数组
* @return 32位十六进制字符串
*/
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
// %02x 表示两位小写十六进制不足两位补0
sb.append(String.format("%02x", b));
}
return sb.toString();
}
/**
* 修改授权记录
*
@@ -143,10 +192,24 @@ public class SisAuthRecordServiceImpl implements ISisAuthRecordService {
* @return 是否修改成功
*/
@Override
public Boolean updateByBo(SisAuthRecordBo bo) {
SisAuthRecord update = MapstructUtils.convert(bo, SisAuthRecord.class);
validEntityBeforeSave(update);
return baseMapper.updateById(update) > 0;
public Boolean updateByBo(RemotePersonAuth bo) {
LambdaQueryWrapper<SisAuthRecord> lqw = new LambdaQueryWrapper<>();
lqw.eq(SisAuthRecord::getTargetId, bo.getId());
boolean flag = baseMapper.delete(lqw) > 0;
Assert.isTrue(flag, "删除授权记录失败");
// 删除人像库图片
SisPersonLibImgVo imgVo = sisPersonLibImgService.queryByPersonId(bo.getId());
if (imgVo != null) {
flag = sisPersonLibImgService.deleteWithValidByIds(List.of(imgVo.getId()), false);
Assert.isTrue(flag, "删除人像库图片失败");
}
// 删除e8人员
flag = e8PlatformApi.deleteCustomer(bo.getE8Id());
Assert.isTrue(flag, "删除e8人员失败");
return flag;
}
/**

View File

@@ -118,6 +118,8 @@ public class SisPersonLibImgServiceImpl implements ISisPersonLibImgService {
@Transactional(rollbackFor = Exception.class)
public Boolean insertByBo(SisPersonLibImgBo bo) {
SisPersonLibImg add = MapstructUtils.convert(bo, SisPersonLibImg.class);
assert add != null;
add.setTenantId("000000");
Assert.notNull(add, "数据处理失败");
boolean flag = baseMapper.insert(add) > 0;
Assert.isTrue(flag, "新增数据失败");
@@ -165,7 +167,7 @@ public class SisPersonLibImgServiceImpl implements ISisPersonLibImgService {
boolean flag = baseMapper.deleteByIds(ids) > 0;
Assert.isTrue(flag, "删除失败");
return true;
return flag;
}
/**
@@ -184,14 +186,45 @@ public class SisPersonLibImgServiceImpl implements ISisPersonLibImgService {
*
* @param personId 入驻员工id
* @param huaweiBoxId 华为盒子图像id
* @param imgMd5 图片md5值
* @return Boolean
*/
@Override
public Boolean updateByPersonId(Long personId, Long huaweiBoxId){
public Boolean updateByPersonId(Long personId, Long huaweiBoxId, String imgMd5) {
LambdaQueryWrapper<SisPersonLibImg> lqw = new LambdaQueryWrapper<>();
lqw.eq(SisPersonLibImg::getResidentPersonId, personId);
SisPersonLibImg update = new SisPersonLibImg();
update.setRemoteImgId(huaweiBoxId);
update.setImgMd5Value(imgMd5);
return baseMapper.update(update, lqw) > 0;
}
/**
* 根据图片MD5查询图片
*
* @param imgMd5 图片MD5
*/
@Override
public SisPersonLibImgVo queryByImgMd5(String imgMd5) {
LambdaQueryWrapper<SisPersonLibImg> lqw = new LambdaQueryWrapper<>();
lqw.eq(SisPersonLibImg::getImgMd5Value, imgMd5);
List<SisPersonLibImgVo> list = baseMapper.selectVoList(lqw);
if (list.isEmpty()) {
return null;
} else {
return list.get(0);
}
}
/**
* 根据入驻员工id查询图片
*
* @param personId 入驻员工id
*/
@Override
public SisPersonLibImgVo queryByPersonId(Long personId) {
LambdaQueryWrapper<SisPersonLibImg> lqw = new LambdaQueryWrapper<>();
lqw.eq(SisPersonLibImg::getResidentPersonId, personId);
return baseMapper.selectVoOne(lqw);
}
}

View File

@@ -30,6 +30,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
@@ -68,7 +69,7 @@ public class AuthSyncTask {
// 需要先设置模拟上下文
SaTokenContextMockUtil.setMockContext(() -> {
// 模拟登录
StpUtil.login(1); // 模拟登录
StpUtil.login(1);
unAuthPersonRef.set(remoteResidentPersonService.queryUnAuthPerson());
List<RemoteResidentPersonVo> unAuthPerson = unAuthPersonRef.get();
@@ -89,12 +90,25 @@ public class AuthSyncTask {
byte[] imgByte = imgByteRef.get();
if (imgByte == null) continue;
String nowMd5 = this.calculateMD5(imgByte);
SisPersonLibImgVo imgVo = sisPersonLibImgService.queryByImgMd5(nowMd5);
Long huaweiId;
Boolean update;
if (ObjectUtil.isEmpty(imgVo)) {
// 写入华为盒子
Long huaweiId = syncHuaweiBox(person, imgByte);
huaweiId = syncHuaweiBox(person, imgByte);
} else {
if (imgVo.getRemoteImgId() == null) {
huaweiId = syncHuaweiBox(person, imgByte);
} else {
huaweiId = imgVo.getRemoteImgId();
}
}
if (huaweiId == null) continue;
// 更新人像信息huaweiBoxId
Boolean update = sisPersonLibImgService.updateByPersonId(person.getId(), huaweiId);
update = sisPersonLibImgService.updateByPersonId(person.getId(), huaweiId, nowMd5);
if (!update) continue;
// 同步E8平台
@@ -105,7 +119,6 @@ public class AuthSyncTask {
remoteResidentPersonService.updateE8Id(person.getId(), e8Id);
}
} else {
log.info("无待授权人员");
}
@@ -115,12 +128,18 @@ public class AuthSyncTask {
});
}
/**
* 补录授权记录
*
* @param person bean
*/
private void syncAuthRecord(RemoteResidentPersonVo person) {
log.info("开始补录授权记录、人像信息");
RemotePersonAuth personAuth = new RemotePersonAuth();
personAuth.setId(person.getId());
personAuth.setOssId(person.getOssId());
personAuth.setName(person.getName());
personAuth.setPhone(person.getPhone());
personAuth.setSex(person.getGender().intValue());
personAuth.setIdCardNumber(person.getIdCard());
personAuth.setAuthGroupId(person.getAuthGroupId());
@@ -130,6 +149,13 @@ public class AuthSyncTask {
log.info("补录授权记录、人像信息完成");
}
/**
* 同步华为盒子
*
* @param vo bean
* @param imgByte 图片字节
* @return Long
*/
private Long syncHuaweiBox(RemoteResidentPersonVo vo, byte[] imgByte) {
log.info("开始写入华为平台");
AddHWPersonReq req = new AddHWPersonReq();
@@ -149,6 +175,13 @@ public class AuthSyncTask {
return pId;
}
/**
* 同步E8平台
*
* @param vo bean
* @param imgByte 图片字节
* @return Long
*/
private Long syncE8Plat(RemoteResidentPersonVo vo, byte[] imgByte) {
log.info("e8平台上传照片");
@@ -205,4 +238,35 @@ public class AuthSyncTask {
}
return e8Id;
}
/**
* 直接计算字节数组的MD5值
*
* @param data 图片的字节数组
* @return 32位小写MD5字符串
*/
public String calculateMD5(byte[] data) throws Exception {
if (data == null) {
throw new IllegalArgumentException("输入数据不能为null");
}
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(data);
return bytesToHex(md.digest());
}
/**
* 字节数组转十六进制字符串
*
* @param bytes 字节数组
* @return 32位十六进制字符串
*/
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
// %02x 表示两位小写十六进制不足两位补0
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}

View File

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