| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.system.domain.SysVisitorRecord; |
| | | import com.ruoyi.system.mapper.SysVisitorRecordMapper; |
| | | import com.ruoyi.web.integration.dahua.DahuaVisitorAccessService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.transaction.support.TransactionSynchronization; |
| | | import org.springframework.transaction.support.TransactionSynchronizationManager; |
| | | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | |
| | | @Autowired |
| | | private RedisTemplate<String, String> redisTemplate; |
| | | |
| | | @Autowired |
| | | private DahuaVisitorAccessService dahuaVisitorAccessService; |
| | | |
| | | private static final String REDIS_KEY_PREFIX = "visitor:expire:"; |
| | | |
| | | /** |
| | | * 登记访客时设置 Redis 过期 Key |
| | | */ |
| | | public void registerVisitor(SysVisitorRecord record) { |
| | | if (record.getValidEndTime() == null) { |
| | | throw new IllegalArgumentException("访客有效期结束时间不能为空"); |
| | | } |
| | | if (!record.getValidEndTime().after(new Date())) { |
| | | log.warn("访客记录 {} 登记时已超期,不下发门禁权限", record.getRecordId()); |
| | | autoSignOut(record); |
| | | return; |
| | | } |
| | | |
| | | // 2. 设置 Redis 过期 Key |
| | | // 下发门禁权限后设置过期监听,确保登记与到期撤权使用同一条业务链路。 |
| | | DahuaVisitorAccessService.OperationResult accessResult = dahuaVisitorAccessService.grant(record); |
| | | registerGrantRollbackCompensation(record, accessResult); |
| | | setRedisExpireKey(record); |
| | | |
| | | log.info("访客 {} 登记成功,有效期至:{}", record.getRecordId(), record.getValidEndTime()); |
| | |
| | | private void setRedisExpireKey(SysVisitorRecord record) { |
| | | Date now = new Date(); |
| | | Date validEndTime = record.getValidEndTime(); |
| | | |
| | | if (validEndTime == null) { |
| | | throw new IllegalArgumentException("访客有效期结束时间不能为空"); |
| | | } |
| | | |
| | | // 如果有效期结束时间小于当前时间,直接签离 |
| | | if (validEndTime.before(now)) { |
| | |
| | | */ |
| | | private void autoSignOut(SysVisitorRecord record) { |
| | | Date now = new Date(); |
| | | revokeAccess(record); |
| | | record.setStatus("PENDING_CONFIRM"); |
| | | record.setSignTime(now); |
| | | record.setRemark("逾期滞留,等待确认"); |
| | | record.setUpdateTime(now); |
| | | this.updateById(record); |
| | | } |
| | | |
| | | /** |
| | | * 撤销访客在大华门禁设备上的人脸及人员权限。 |
| | | */ |
| | | public void revokeAccess(SysVisitorRecord record) { |
| | | dahuaVisitorAccessService.revoke(record); |
| | | } |
| | | |
| | | private void registerGrantRollbackCompensation(SysVisitorRecord record, |
| | | DahuaVisitorAccessService.OperationResult accessResult) { |
| | | if (accessResult.getSuccessCount() <= 0 || !TransactionSynchronizationManager.isSynchronizationActive()) { |
| | | return; |
| | | } |
| | | TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { |
| | | @Override |
| | | public void afterCompletion(int status) { |
| | | if (status != TransactionSynchronization.STATUS_ROLLED_BACK) { |
| | | return; |
| | | } |
| | | redisTemplate.delete(REDIS_KEY_PREFIX + record.getRecordId()); |
| | | try { |
| | | dahuaVisitorAccessService.revoke(record); |
| | | log.info("访客登记事务回滚,大华门禁权限补偿撤销完成,recordId={}", record.getRecordId()); |
| | | } catch (Exception e) { |
| | | log.error("访客登记事务回滚,大华门禁权限补偿撤销失败,recordId={}", |
| | | record.getRecordId(), e); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | |
| | | int count = 0; |
| | | for (SysVisitorRecord record : overdueRecords) { |
| | | try { |
| | | revokeAccess(record); |
| | | record.setStatus("OVERDUE_AUTO_SIGNED_OUT"); |
| | | record.setSignTime(now); |
| | | record.setRemark("系统自动签离(启动时检查)"); |