package com.zhgd.xmgl.async; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.zhgd.jeecg.common.execption.OpenPromptException; import com.zhgd.jeecg.common.util.SpringContextUtils; import com.zhgd.jeecg.common.util.pass.HttpUtils; import com.zhgd.redis.lock.RedisRepository; import com.zhgd.xmgl.call.HikvisionCall; import com.zhgd.xmgl.constant.Cts; import com.zhgd.xmgl.modules.basicdata.entity.Notice; import com.zhgd.xmgl.modules.basicdata.service.INoticeService; import com.zhgd.xmgl.modules.car.entity.CarInfo; import com.zhgd.xmgl.modules.car.service.impl.CarInfoServiceImpl; import com.zhgd.xmgl.modules.project.entity.Project; import com.zhgd.xmgl.modules.project.entity.vo.ProjectInfoExtVo; import com.zhgd.xmgl.modules.project.mapper.ProjectMapper; import com.zhgd.xmgl.modules.project.service.IProjectUfaceConfigService; import com.zhgd.xmgl.modules.project.service.impl.ProjectServiceImpl; import com.zhgd.xmgl.modules.video.mapper.ProjectVideoHkVqdMapper; import com.zhgd.xmgl.modules.video.mapper.VideoItemMapper; import com.zhgd.xmgl.modules.worker.entity.*; import com.zhgd.xmgl.modules.worker.mapper.EnterpriseInfoMapper; import com.zhgd.xmgl.modules.worker.service.impl.WorkerInfoServiceImpl; import com.zhgd.xmgl.modules.xz.entity.XzHikvisionSync; import com.zhgd.xmgl.modules.xz.mapper.XzHikvisionCompareDataMapper; import com.zhgd.xmgl.modules.xz.mapper.XzHikvisionSyncMapper; import com.zhgd.xmgl.modules.xz.service.impl.XzHikvisionCompareDataServiceImpl; import com.zhgd.xmgl.security.entity.UserInfo; import com.zhgd.xmgl.util.*; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import java.util.*; import java.util.concurrent.Future; import java.util.function.Function; import java.util.stream.Collectors; /** * 异步海康 */ @Slf4j @Component public class AsyncHikvision { public static final String XZ_HIKVISION_SYNC_TIME = "xzHikvisionSyncTime"; public static final int MAX_PAGE_SIZE = 1000; @Lazy @Autowired public CarInfoServiceImpl carInfoService; @Autowired @Lazy public WorkerInfoServiceImpl workerInfoService; @Autowired @Lazy public IProjectUfaceConfigService projectUfaceConfigService; @Autowired @Lazy HikvisionCall hikvisionCall; @Lazy @Autowired ProjectMapper projectMapper; @Lazy @Autowired VideoItemMapper videoItemMapper; @Lazy @Autowired ProjectVideoHkVqdMapper projectVideoHkVqdMapper; @Lazy @Autowired EnterpriseInfoMapper enterpriseInfoMapper; @Lazy @Autowired ProjectServiceImpl projectService; @Lazy @Autowired private INoticeService noticeService; @Lazy @Autowired private AsyncHikvision asyncHikvision; @Lazy @Autowired private XzHikvisionSyncMapper xzHikvisionSyncMapper; @Lazy @Autowired private XzHikvisionCompareDataMapper xzHikvisionCompareDataMapper; @Lazy @Autowired private XzHikvisionCompareDataServiceImpl xzHikvisionCompareDataService; @Autowired private RedisRepository redisRepository; /** * 获取下发的时间,如果不存在就新建 * * @return */ public static Date getSyncTimeWithInitIfAbsent() { Date now = ThreadLocalUtil.getNotNull().getDate(XZ_HIKVISION_SYNC_TIME); if (now == null) { now = new Date(); ThreadLocalUtil.addInKey(XZ_HIKVISION_SYNC_TIME, now); } return now; } /** * 获取下发的时间,如果不存在就新建,并删除同步表中对应的数据 * * @param bigType 1人员2车辆 * @param tableId * @return */ public static Date getSyncTimeWithInitAndDeleteSyncIfAbsent(int bigType, Long tableId) { Date now = ThreadLocalUtil.getNotNull().getDate(XZ_HIKVISION_SYNC_TIME); if (now == null) { //首次执行,清空以前同步记录 now = new Date(); ThreadLocalUtil.addInKey(XZ_HIKVISION_SYNC_TIME, now); SpringContextUtils.getBean(XzHikvisionSyncMapper.class).delete(new LambdaQueryWrapper() .eq(XzHikvisionSync::getBigType, bigType) .eq(XzHikvisionSync::getWhoId, tableId) ); } return now; } /** * 获取同步时间 * * @return */ public static Date getSyncTime() { return ThreadLocalUtil.getNotNull().getDate(XZ_HIKVISION_SYNC_TIME); } /** * 异步添加人员和权限 * * @param workerInfo * @param isSaveWorker * @param isSaveWorkerFace * @return */ @Async("workerHkExecutor") public Future addWorkerAndAuthAsync(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) { this.addWorkerAsync(workerInfo, true, true); projectUfaceConfigService.addWorkerInfo(workerInfo); return null; } /** * 添加劳务人员-海康 * * @param workerInfo * @param isSaveWorker * @param isSaveWorkerFace */ @Async("workerHkExecutor") public void addWorkerAsync(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) { try { hikvisionCall.saveWorker(workerInfo, isSaveWorker, isSaveWorkerFace); } catch (Exception e) { log.error("海康:", e); sendNoticeForWorker(workerInfo, e, "添加"); } } /** * 添加人员 * * @param workerInfo * @param isSaveWorker * @param isSaveWorkerFace */ public void addWorker(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) { this.addWorkerAsync(workerInfo, isSaveWorker, isSaveWorkerFace); } /** * 编辑人员和权限 * * @param workerInfo * @param isSaveWorker * @param isSaveWorkerFace */ @Async("workerHkExecutor") public void editWorkerAndAuthAsync(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) { this.saveWorkerAsync(workerInfo, true, true); projectUfaceConfigService.updateWorkerInfo(workerInfo, workerInfo); } /** * 保存人员 * * @param workerInfo * @param isSaveWorker * @param isSaveWorkerFace */ public void saveWorker(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) { this.saveWorkerAsync(workerInfo, isSaveWorker, isSaveWorkerFace); } /** * 异步保存人员 * * @param workerInfo * @param isSaveWorker * @param isSaveWorkerFace */ @Async("workerHkExecutor") public void saveWorkerAsync(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) { try { hikvisionCall.saveWorker(workerInfo, isSaveWorker, isSaveWorkerFace); } catch (Exception e) { log.error("海康:", e); sendNoticeForWorker(workerInfo, e, "更新"); } } /** * 编辑人员 * * @param workerInfo * @param isSaveWorker * @param isSaveWorkerFace */ public void editWorker(WorkerInfo workerInfo, boolean isSaveWorker, boolean isSaveWorkerFace) { this.saveWorkerAsync(workerInfo, isSaveWorker, isSaveWorkerFace); } /** * 为人员发送通知和设置下发状态 * * @param workerInfo * @param e * @param action */ private void sendNoticeForWorker(WorkerInfo workerInfo, Exception e, String action) { String title = action + "人员到海康isc失败"; String type = "23"; String msg; if (HttpUtils.isTimeOut(e)) { msg = "同步失败,人员名称:" + workerInfo.getWorkerName() + ",身份证号:" + workerInfo.getIdCard() + "。失败原因:平台连接isc网络异常"; } else if (e instanceof OpenPromptException) { msg = "同步失败,人员名称:" + workerInfo.getWorkerName() + ",身份证号:" + workerInfo.getIdCard() + "。失败原因:" + e.getMessage(); } else { msg = "同步失败,人员名称:" + workerInfo.getWorkerName() + ",身份证号:" + workerInfo.getIdCard() + "。失败原因:下发异常"; } if (ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class) != null) { noticeService.addUserNotice(ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class).getUserId(), title, msg, type); } hikvisionCall.updateAllFailStatusIfNull(workerInfo.getProjectSn(), workerInfo.getId(), 1); } /** * 异步删除人员 * * @param uniqueId * @param workerInfo */ @Async("workerHkExecutor") public void deleteWorkerForHikvisionAsync(String uniqueId, WorkerInfo workerInfo) { try { hikvisionCall.deleteWorkerForHikvision(uniqueId, workerInfo, true); } catch (Exception e) { log.error("海康:", e); sendNoticeForWorker(workerInfo, e, "删除"); } } /** * 删除人员 * * @param uniqueId * @param workerInfo */ public void deleteWorkerForHikvision(String uniqueId, WorkerInfo workerInfo) { this.deleteWorkerForHikvisionAsync(uniqueId, workerInfo); } /** * 异步添加车辆 * * @param carInfo */ @Async("carInfoExecutor") public void addCarInfoForHikvisionAsync(CarInfo carInfo) { try { hikvisionCall.saveCarInfoFromHikvision(carInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForCar(carInfo, e, "添加"); } } /** * 添加车辆 * * @param carInfo */ public void addCarInfoForHikvision(CarInfo carInfo) { this.addCarInfoForHikvisionAsync(carInfo); } /** * 为车辆发送通知和设置下发状态 * * @param carInfo * @param e * @param action */ private void sendNoticeForCar(CarInfo carInfo, Exception e, String action) { String title = action + "车辆到海康isc失败"; String type = "24"; String msg = null; if (HttpUtils.isTimeOut(e)) { msg = "同步失败,车牌号:" + carInfo.getCarNumber() + "。失败原因:平台连接isc网络异常"; } else if (e instanceof OpenPromptException) { msg = "同步失败,车牌号:" + carInfo.getCarNumber() + "。失败原因:" + e.getMessage(); } else { msg = "同步失败,车牌号:" + carInfo.getCarNumber() + "。失败原因:下发异常"; } if (ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class) != null) { noticeService.addUserNotice(ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class).getUserId(), title, msg, type); } hikvisionCall.updateAllFailStatusIfNull(carInfo.getProjectSn(), carInfo.getId(), 2); } /** * 异步编辑车辆 * * @param carInfo * @param old */ @Async("carInfoExecutor") public void editCarInfoForHikvisionAsync(CarInfo carInfo, CarInfo old) { try { hikvisionCall.editCarInfoForHikvision(carInfo, old); } catch (Exception e) { log.error("海康:", e); sendNoticeForCar(carInfo, e, "编辑"); } } /** * 编辑车辆 * * @param carInfo * @param old */ public void editCarInfoForHikvision(CarInfo carInfo, CarInfo old) { this.editCarInfoForHikvisionAsync(carInfo, old); } /** * 异步删除车辆并设置车辆黑名单状态 * * @param carInfo * @param isSetBlack */ @Async("carInfoExecutor") public void deleteCarInfoAndSetBlackForHikvisionAsync(CarInfo carInfo, boolean isSetBlack) { try { hikvisionCall.deleteCarInfoForHikvision(carInfo, isSetBlack); } catch (Exception e) { log.error("海康:", e); sendNoticeForCar(carInfo, e, "删除"); } } /** * 删除车辆并设置车辆黑名单状态 * * @param carInfo * @param isSetBlack */ public void deleteCarInfoAndSetBlackForHikvision(CarInfo carInfo, boolean isSetBlack) { this.deleteCarInfoAndSetBlackForHikvisionAsync(carInfo, isSetBlack); } /** * 添加企业 * * @param enterpriseInfo */ @Async("carInfoExecutor") public void addEnterpriseInfoForHikvision(EnterpriseInfo enterpriseInfo) { try { hikvisionCall.addEnterpriseInfoForHikvision(enterpriseInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(enterpriseInfo.getEnterpriseName(), e, "新增"); } } /** * 为组织发送通知和设置下发状态 * * @param name * @param e * @param action */ private void sendNoticeForOrg(String name, Exception e, String action) { String title = action + "组织到海康isc失败"; String type = "23"; String msg; if (HttpUtils.isTimeOut(e)) { msg = "同步失败,组织名称:" + name + "。失败原因:平台连接isc网络异常"; } else if (e instanceof OpenPromptException) { msg = "同步失败,组织名称:" + name + "。失败原因:" + e.getMessage(); } else { msg = "同步失败,组织名称:" + name + "。失败原因:下发异常"; } if (ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class) != null) { noticeService.addUserNotice(ThreadLocalUtil.getByKey(Cts.TL_AUTH_USER, UserInfo.class).getUserId(), title, msg, type); } xzHikvisionCompareDataService.compareRetryFail(); } /** * 编辑企业 * * @param enterpriseInfo */ @Async("carInfoExecutor") public void editEnterpriseInfoForHikvision(EnterpriseInfo enterpriseInfo) { try { hikvisionCall.editEnterpriseInfoForHikvision(enterpriseInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(enterpriseInfo.getEnterpriseName(), e, "编辑"); } } /** * 删除企业 * * @param projectSn * @param enterpriseName */ @Async("carInfoExecutor") public void deleteEnterpriseInfoForHikvision(String projectSn, String enterpriseName) { try { hikvisionCall.deleteEnterpriseInfoForHikvision(projectSn, enterpriseName); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(enterpriseName, e, "删除"); } } /** * 异步编辑班组 * * @param teamInfo */ @Async("carInfoExecutor") public void editTeamInfoForHikvision(TeamInfo teamInfo) { try { hikvisionCall.editTeamInfoForHikvision(teamInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(teamInfo.getTeamName(), e, "编辑"); } } /** * 异步删除班组 * * @param id * @param teamInfo */ @Async("carInfoExecutor") public void deleteTeamInfoForHikvision(String id, TeamInfo teamInfo) { try { hikvisionCall.deleteTeamInfoForHikvision(id, teamInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(teamInfo.getTeamName(), e, "删除"); } } /** * 异步添加班组 * * @param teamInfo */ @Async("carInfoExecutor") public void addTeamInfoForHikvision(TeamInfo teamInfo) { try { hikvisionCall.addTeamInfoForHikvision(teamInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(teamInfo.getTeamName(), e, "新增"); } } /** * 异步编辑部门 * * @param teamInfo */ @Async("carInfoExecutor") public void editDepartmentInfoForHikvision(DepartmentInfo teamInfo) { try { hikvisionCall.editDepartmentInfoForHikvision(teamInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(teamInfo.getDepartmentName(), e, "编辑"); } } /** * 异步添加部门 * * @param teamInfo */ @Async("carInfoExecutor") public void addDepartmentInfoForHikvision(DepartmentInfo teamInfo) { try { hikvisionCall.addDepartmentInfoForHikvision(teamInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(teamInfo.getDepartmentName(), e, "新增"); } } /** * 异步删除部门 * * @param uniqueId * @param departmentInfo */ @Async("carInfoExecutor") public void deleteDepartmentInfoForHikvision(String uniqueId, DepartmentInfo departmentInfo) { try { hikvisionCall.deleteDepartmentInfoForHikvision(uniqueId, departmentInfo); } catch (Exception e) { log.error("海康:", e); sendNoticeForOrg(departmentInfo.getDepartmentName(), e, "删除"); } } /** * 异步编辑项目 * * @param project */ @Async("carInfoExecutor") public void editProjectForHikvision(Project project) { try { hikvisionCall.editProjectForHikvision(project); } catch (Exception e) { log.error("海康:", e); } } /** * 异步获取车辆通行数据 * * @param paramMap */ @Async("getRecordForHikvisionTask") public void getCrossRecordsAsync(HashMap paramMap) { hikvisionCall.getCrossRecords(paramMap); } /** * 异步获取人员通行数据 * * @param paramMap */ @Async("getRecordForHikvisionTask") public void getDoorEventsAsync(HashMap paramMap) { hikvisionCall.getDoorEvents(paramMap); } /** * 批量下发人员 * * @param allDevList * @param workerList 下发的人员 * @param workerAndDevSnList 构建的下发的人员和设备的关系 * @param userId 批量下发的通知的人 * @param checkEditWorkers * @param sendNotice * @param flowStartUser */ @Async("workerAuthHkExecutor") public void sendBatchWorkerInfoAsync(List allDevList, List workerList, List workerAndDevSnList, Long userId, String projectSn, boolean checkEditWorkers, boolean sendNotice, Long flowStartUser) { try { if (CollUtil.isNotEmpty(workerAndDevSnList)) { ProjectInfoExtVo project = projectService.getProjectInfoBySn(projectSn); //判断人员的图片存在isc Map workerIdMap = workerList.stream().collect(Collectors.toMap(workerInfo -> workerInfo.getId() + "", Function.identity())); ArrayList futures = new ArrayList<>(); if (checkEditWorkers) { ArrayList needEditWorkers = getNeedEditWorkers(workerList, project, workerIdMap); if (CollUtil.isNotEmpty(needEditWorkers)) { for (WorkerInfo workerInfo : needEditWorkers) { Future future = workerInfoService.editWorkerAsyncForSendBatchAuth(workerInfo); futures.add(future); } } for (Future future : futures) { future.get(); } } Map devSnMap = allDevList.stream().collect(Collectors.toMap(UfaceDev::getDevSn, Function.identity())); JSONObject gdvJo = HikvisionUtil.getDoorsV2(project, HikvisionUtil.addPageParamIfAbsent(new JSONObject())); JSONObject gdvDataJo = HikvisionUtil.getJsonObjectData(gdvJo); //门禁设备编号:parentIndexCode,门禁点编号:indexCode,门禁设备资源通道号:channelNo Map devSnToIscDevSnMap = gdvDataJo.getJSONArray("list").stream().collect(Collectors.toMap(o -> ((JSONObject) o).getString("indexCode"), o -> (JSONObject) o)); workerAndDevSnList = this.addNeedSimpleAuthProp(workerAndDevSnList, devSnToIscDevSnMap, project); Map> devSnToJoMap = workerAndDevSnList.stream().collect(Collectors.groupingBy(jsonObject -> jsonObject.getString("devSn"))); futures = new ArrayList<>(); for (Map.Entry> entry : devSnToJoMap.entrySet()) { JSONObject iscDevSnObj = devSnToIscDevSnMap.get(entry.getKey()); Future future = asyncHikvision.sendBatchWorkersForOneDevAsync(devSnMap.get(entry.getKey()), entry, workerIdMap, workerList, project, projectSn, sendNotice, flowStartUser, iscDevSnObj); futures.add(future); } for (Future future : futures) { future.get(); } } //下发完成 if (userId != null) { java.text.DateFormat format1 = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String redNotice = ""; List redNameList = workerList.stream().filter(w -> NumberUtils.lt(w.getSafeScore(), PropertiesUtil.getWorkerInfoRedScore())).map(WorkerInfo::getWorkerName).collect(Collectors.toList()); if (CollUtil.isNotEmpty(redNameList)) { redNotice = StrUtil.format(",{}是红码不下发", StrUtil.join(Cts.COMMA, redNameList)); } Notice notice = new Notice(); notice.setAccountId(userId); notice.setMsg(StrUtil.format("已经完成批量向设备下发{}个人{}", workerList.size() - redNameList.size(), redNotice)); notice.setTitle("人员批量下发设备提醒"); notice.setSendTime(format1.format(new Date())); notice.setType("1"); noticeService.addNotice(notice, true); } } catch (Exception e) { log.error("批量下发权限失败:", e); hikvisionCall.updateAllFailStatusIfNullForAuth(projectSn, workerList, 1, 1); hikvisionCall.updateAllFailStatusIfNullForAuth(projectSn, workerList, 1, 3); sendExcNotice(e, workerList, null, projectSn, flowStartUser, new ArrayList<>()); } } /** * 添加需要简单权限删除的标志 * * @param workerAndDevSnList * @param devSnToIscDevSnMap * @param project * @return */ private List addNeedSimpleAuthProp(List workerAndDevSnList, Map devSnToIscDevSnMap, Project project) throws Exception { JSONArray rtJa = new JSONArray(); List workerIds = workerAndDevSnList.stream().filter(o -> !o.getBoolean(Cts.IS_ADD_AUTH)).map(o -> o.getString("workerId")).distinct().collect(Collectors.toList()); Map iscDevMap = new HashMap<>(); if (CollUtil.isNotEmpty(workerIds)) { Set> iscDevEntries = devSnToIscDevSnMap.entrySet(); for (List splitList : CollUtil.splitList(workerIds, MAX_PAGE_SIZE)) { JSONObject qaiJo = getQueryAuthItemParam(splitList, iscDevEntries.stream().map(e -> { return new JoBuilder() .put("resourceIndexCode", e.getValue().getString("parentIndexCode")) .put("resourceType", "acsDevice") .put("channelNos", Collections.singletonList(e.getValue().getString("channelNo"))) .build(); }).collect(Collectors.toList())); JSONObject qaiRtJo = HikvisionUtil.getJsonObjectData(HikvisionUtil.queryAuthItem(project, qaiJo)); JSONArray qaiList = qaiRtJo.getJSONArray("list"); if (CollUtil.isNotEmpty(qaiList)) { rtJa.addAll(qaiList); } } List simpleDeleteAuths = rtJa.stream().filter(o -> { JSONArray ja = ((JSONObject) o).getJSONArray("templateConfigInfos"); if (CollUtil.isNotEmpty(ja)) { JSONObject jo = ja.getJSONObject(0); if (jo != null) { return Objects.equals(jo.getInteger("dimension"), 1); } } return false; }).map(o -> ((JSONObject) o)).collect(Collectors.toList()); iscDevMap = simpleDeleteAuths.stream().collect(Collectors.toMap(o -> o.getString("resourceIndexCode") + Cts.COMMA + o.getString("channelNo"), Function.identity())); } for (JSONObject jo : workerAndDevSnList) { String devSn = jo.getString("devSn"); JSONObject iscDevJo = devSnToIscDevSnMap.get(devSn); JSONObject have = iscDevMap.get(iscDevJo.get("parentIndexCode") + Cts.COMMA + iscDevJo.get("channelNo")); if (have != null) { jo.put(Cts.IS_SIMPLE_DELETE_AUTH, true); } else { jo.put(Cts.IS_SIMPLE_DELETE_AUTH, false); } } return workerAndDevSnList; } /** * 发送异常通知 * * @param e * @param workerList * @param dev * @param projectSn * @param flowStartUser */ private void sendExcNotice(Exception e, List workerList, UfaceDev dev, String projectSn, Long flowStartUser, List deleteAuthWorkerIds) { String exc; if (HttpUtils.isTimeOut(e)) { exc = ",连接ISC网络异常"; } else { exc = ",下发异常"; } if (CollUtil.isNotEmpty(workerList)) { List failWorkers = workerInfoService.list(Wrappers.lambdaQuery() .eq(WorkerInfo::getProjectSn, projectSn) .ne(WorkerInfo::getSendSuccessStatus, 1) .in(WorkerInfo::getId, workerList.stream().map(WorkerInfo::getId).collect(Collectors.toList())) ); for (WorkerInfo workerInfo : failWorkers) { Set noticeUserIds = hikvisionCall.getNoticeUserIds(flowStartUser, workerInfo.getProjectSn()); for (Long noticeUserId : noticeUserIds) { noticeService.addUserNotice(noticeUserId, "人员下发设备提醒", StrUtil.format("[{}]{}下发{}设备权限失败{}", workerInfo.getWorkerName(), deleteAuthWorkerIds.contains(workerInfo.getId() + "") ? "取消" : "", (dev != null ? "[" + dev.getDevName() + "]" : "有些"), exc), "1"); } } } } /** * 获取需要编辑的人员 * * @param workerList * @param project * @param workerIdMap * @return * @throws Exception */ private ArrayList getNeedEditWorkers(List workerList, ProjectInfoExtVo project, Map workerIdMap) throws Exception { ArrayList needEditWorkers = new ArrayList<>(); JSONArray plListJa = getPersonListByWorkerList(workerList, project); HashSet iscPersonIds = new HashSet<>(); for (int i = 0; i < plListJa.size(); i++) { JSONObject jo = plListJa.getJSONObject(i); JSONArray personPhotoJa = jo.getJSONArray("personPhoto"); WorkerInfo workerInfo = workerIdMap.get(jo.getString("personId")); if (CollUtil.isEmpty(personPhotoJa)) { //不存在就编辑人员 needEditWorkers.add(workerInfo); } iscPersonIds.add(String.valueOf(workerInfo.getId())); } for (WorkerInfo workerInfo : workerList) { if (!iscPersonIds.contains(workerInfo.getId() + "")) { needEditWorkers.add(workerInfo); } } return needEditWorkers; } /** * 根据人员列表获取isc人员列表 * * @param workerList * @param project * @return * @throws Exception */ private JSONArray getPersonListByWorkerList(List workerList, ProjectInfoExtVo project) throws Exception { JSONArray rtJa = new JSONArray(); for (List splitList : CollUtil.splitList(workerList, MAX_PAGE_SIZE)) { JSONObject plJo = HikvisionUtil.queryPersonList(project, new JoBuilder() .put("personIds", StrUtil.join(Cts.COMMA, splitList.stream().map(WorkerInfo::getId).collect(Collectors.toList()))) .put("pageNo", 1) .put("pageSize", MAX_PAGE_SIZE) .build()); JSONObject plDataJo = HikvisionUtil.getJsonObjectData(plJo); JSONArray plListJa = plDataJo.getJSONArray("list"); rtJa.addAll(plListJa); } return rtJa; } /** * 一个设备批量下发人员 * * @param dev * @param devSnToJoEntry * @param workerIdMap * @param workerList * @param project * @param sendNotice * @param flowStartUser * @param iscDevSnObj */ @Async("workerBeWaitHkExecutor") public Future sendBatchWorkersForOneDevAsync(UfaceDev dev, Map.Entry> devSnToJoEntry, Map workerIdMap, List workerList, ProjectInfoExtVo project, String projectSn, boolean sendNotice, Long flowStartUser, JSONObject iscDevSnObj) { String devSn = devSnToJoEntry.getKey(); List addAuthWorkerIds = devSnToJoEntry.getValue().stream().filter(jo -> jo.getBoolean(Cts.IS_ADD_AUTH)).map(jsonObject -> jsonObject.getString("workerId")).collect(Collectors.toList()); List deleteAuthWorkerIds = devSnToJoEntry.getValue().stream().filter(jo -> !jo.getBoolean(Cts.IS_ADD_AUTH) && !jo.getBoolean(Cts.IS_SIMPLE_DELETE_AUTH)).map(jsonObject -> jsonObject.getString("workerId")).collect(Collectors.toList()); List deleteSimpleAuthWorkerIds = devSnToJoEntry.getValue().stream().filter(jo -> !jo.getBoolean(Cts.IS_ADD_AUTH) && jo.getBoolean(Cts.IS_SIMPLE_DELETE_AUTH)).map(jsonObject -> jsonObject.getString("workerId")).collect(Collectors.toList()); try { if (CollUtil.isNotEmpty(deleteSimpleAuthWorkerIds)) { //需要简单删除权限方法 for (String workerId : deleteSimpleAuthWorkerIds) { Future future = asyncHikvision.simpleDeletePersonAuthAsync(workerId, dev, project, flowStartUser, workerIdMap, iscDevSnObj); future.get(); } } //【添加权限配置】(人员列表,设备列表),这个接口只要没报错,你就直接去下一步就行了。 if (CollUtil.isEmpty(addAuthWorkerIds) && CollUtil.isEmpty(deleteAuthWorkerIds)) { log.error("无权限添加或删除,跳过"); return null; } if (CollUtil.isNotEmpty(addAuthWorkerIds)) { addAuthByWorkerList(project, addAuthWorkerIds, iscDevSnObj); } if (CollUtil.isNotEmpty(deleteAuthWorkerIds)) { deleteAuthByWorkerList(project, deleteAuthWorkerIds, iscDevSnObj); } //然后调用【根据出入权限配置快捷下载】(设备列表)(【添加权限配置】+【快捷下发】这是一个流程,你添加了几个权限,下发成功之后,就清零了) JSONObject daJo = HikvisionUtil.downloadAuth(project, getQueryDownloadProgressParam(iscDevSnObj)); JSONObject daRtJo = HikvisionUtil.getJsonObjectData(daJo); //然后调用【查询下载任务进度】(上面那个的任务) int totalPercent = 0; do { JSONObject qdpJo = HikvisionUtil.queryDownloadProgress(project, new JoBuilder() .put("taskId", daRtJo.getString("taskId")) .build()); totalPercent = HikvisionUtil.getJsonObjectData(qdpJo).getInteger("totalPercent"); Thread.sleep(MAX_PAGE_SIZE); } while (totalPercent != 100); //权限下发后(进度100后),用【查询权限条目列表】(人员列表,设备列表)接口去查,返回参数有权限状态,返回已下载的就是有权限 List workerIds = devSnToJoEntry.getValue().stream().map(jsonObject -> jsonObject.getString("workerId")).collect(Collectors.toList()); JSONArray qaiList = queryAuthItemByWorkerList(project, workerIds, getDevRqParam(iscDevSnObj)); Set rtWorkerIdSet; if (CollUtil.isNotEmpty(qaiList)) { for (int i = 0; i < qaiList.size(); i++) { handlerBatchWorkersResult(workerIdMap, addAuthWorkerIds, sendNotice, dev, flowStartUser, qaiList.getJSONObject(i)); } rtWorkerIdSet = qaiList.stream().map(o -> ((JSONObject) o).getString("personId")).collect(Collectors.toSet()); } else { rtWorkerIdSet = new HashSet<>(); } //处理删除权限的结果的 //1. 删除权限配置,还没删除的时候,权限变成 2更新待删除 //2. 删除以后,删除的权限状态是 4未配置 //3. 这个人的权限都没了以后,你就查不到这个权限条目了 //handlerBatchWorkersResultForDeleteAuth(); if (sendNotice && CollUtil.isNotEmpty(deleteAuthWorkerIds)) { for (String workerId : deleteAuthWorkerIds) { if (rtWorkerIdSet.contains(workerId)) { //已经处理过了 continue; } hikvisionCall.updateSuccessStatus(projectSn, Long.valueOf(workerId), 3, 3, devSn); Set noticeUserIds = hikvisionCall.getNoticeUserIds(flowStartUser, projectSn); for (Long noticeUserId : noticeUserIds) { noticeService.addUserNotice(noticeUserId, "人员下发设备提醒", StrUtil.format("[{}]取消下发到[{}]{}", workerIdMap.get(workerId).getWorkerName(), dev.getDevName(), "成功"), "1"); } } } } catch (Exception e) { log.error("批量下发权限失败:", e); hikvisionCall.updateAllFailStatusIfNullForAuth(projectSn, new ArrayList<>(workerIdMap.values()), 1, 1); hikvisionCall.updateAllFailStatusIfNullForAuth(projectSn, new ArrayList<>(workerIdMap.values()), 1, 3); List dawis = BeanUtil.copyToList(deleteAuthWorkerIds, String.class); if (CollUtil.isNotEmpty(deleteSimpleAuthWorkerIds)) { dawis.addAll(deleteSimpleAuthWorkerIds); } sendExcNotice(e, workerList, dev, projectSn, flowStartUser, dawis); } return null; } @Async("hkSimpleAuthExecutor") public Future simpleDeletePersonAuthAsync(String workerId, UfaceDev dev, ProjectInfoExtVo project, Long flowStartUser, Map workerIdMap, JSONObject iscDevSnObj) throws Exception { hikvisionCall.simpleDeletePersonAuth(workerId, dev, project, flowStartUser, workerIdMap, iscDevSnObj); return null; } /** * 为人员列表查询权限列表 * * @param project * @param workerIds * @param devRqParam * @return * @throws Exception */ private JSONArray queryAuthItemByWorkerList(ProjectInfoExtVo project, List workerIds, @NotNull List devRqParam) throws Exception { JSONArray rtJa = new JSONArray(); for (List splitList : CollUtil.splitList(workerIds, MAX_PAGE_SIZE)) { JSONObject qaiJo = HikvisionUtil.queryAuthItem(project, getQueryAuthItemParam(splitList, devRqParam)); JSONObject qaiRtJo = HikvisionUtil.getJsonObjectData(qaiJo); JSONArray qaiList = qaiRtJo.getJSONArray("list"); if (CollUtil.isNotEmpty(qaiList)) { rtJa.addAll(qaiList); } } return rtJa; } /** * 为人员列表删除权限 * * @param project * @param deleteAuthWorkerIds * @param jsonObject * @throws Exception */ private void deleteAuthByWorkerList(ProjectInfoExtVo project, List deleteAuthWorkerIds, JSONObject jsonObject) throws Exception { for (List splitWorkerIds : CollUtil.splitList(deleteAuthWorkerIds, MAX_PAGE_SIZE)) { JSONObject jo = HikvisionUtil.deleteAuth(project, getAddOrDeleteAuthParam(splitWorkerIds, jsonObject)); HikvisionUtil.getJsonObjectData(jo); } } /** * 为人员列表添加权限 * * @param project * @param addAuthWorkerIds * @param jsonObject * @throws Exception */ private void addAuthByWorkerList(ProjectInfoExtVo project, List addAuthWorkerIds, JSONObject jsonObject) throws Exception { for (List splitWorkerIds : CollUtil.splitList(addAuthWorkerIds, MAX_PAGE_SIZE)) { JSONObject jo = HikvisionUtil.addAuth(project, getAddOrDeleteAuthParam(splitWorkerIds, jsonObject)); HikvisionUtil.getJsonObjectData(jo); } } /** * 处理结果:一个设备批量下发人员 * * @param workerIdMap * @param addAuthWorkerIds * @param sendNotice * @param dev * @param flowStartUser */ public void handlerBatchWorkersResult(Map workerIdMap, List addAuthWorkerIds, boolean sendNotice, UfaceDev dev, Long flowStartUser, JSONObject jo) { String projectSn = dev.getProjectSn(); String personId = jo.getString("personId"); //人脸状态 //0:已配置未下载 //1:更新待下载 //2:更新待删除 //3:已下载 //4:未配置 //1. 删除权限配置,还没删除的时候,权限变成 2更新待删除 //2. 删除以后,删除的权限状态是 4未配置 //3. 这个人的权限都没了以后,你就查不到这个权限条目了 Integer faceStatus = jo.getInteger("faceStatus"); if (sendNotice) { if (addAuthWorkerIds.contains(personId)) { //添加权限 int addAuth = 3; if (Objects.equals(faceStatus, addAuth)) { hikvisionCall.updateSuccessStatus(projectSn, Long.valueOf(personId), 3, 1, dev.getDevSn()); Long syncId = ThreadLocalUtil.getByKey(Cts.TL_HK_SYNC_ID, Long.class); if (syncId != null) { redisRepository.set(Cts.HK_SYNC_AUTH_SUCCESS_KEY + syncId, 1, 60L); } } else { hikvisionCall.updateFailStatus(projectSn, Long.valueOf(personId), 3, 1, dev.getDevSn()); } Set noticeUserIds = hikvisionCall.getNoticeUserIds(flowStartUser, projectSn); for (Long noticeUserId : noticeUserIds) { noticeService.addUserNotice(noticeUserId, "人员下发设备提醒", StrUtil.format("[{}]下发到[{}]{}", workerIdMap.get(personId).getWorkerName(), dev.getDevName(), Objects.equals(faceStatus, 3) ? "成功" : "失败,下发异常"), "1"); } } else { //删除权限 int deleteAuth = 4; if (Objects.equals(faceStatus, deleteAuth)) { hikvisionCall.updateSuccessStatus(projectSn, Long.valueOf(personId), 3, 3, dev.getDevSn()); } else { hikvisionCall.updateFailStatus(projectSn, Long.valueOf(personId), 3, 3, dev.getDevSn()); } Set noticeUserIds = hikvisionCall.getNoticeUserIds(flowStartUser, projectSn); for (Long noticeUserId : noticeUserIds) { noticeService.addUserNotice(noticeUserId, "人员下发设备提醒", StrUtil.format("[{}]取消下发到[{}]{}", workerIdMap.get(personId).getWorkerName(), dev.getDevName(), Objects.equals(faceStatus, deleteAuth) ? "成功" : "失败,下发异常"), "1"); } } } } /** * 获取添加或删除权限的参数 * * @param workerIds * @param jsonObject * @return */ @NotNull private JSONObject getAddOrDeleteAuthParam(List workerIds, JSONObject jsonObject) { JSONObject aaJo = new JSONObject(); aaJo.put("personDatas", Collections.singletonList(new MapBuilder() .put("indexCodes", workerIds) .put("personDataType", "person") .build())); aaJo.put("resourceInfos", getDevRqParam(jsonObject)); return aaJo; } /** * 获取《删除权限配置》接口的设备请求的参数 * * @param jsonObject * @return */ @NotNull private List getDevRqParam(JSONObject jsonObject) { return Collections.singletonList(new JoBuilder() .put("resourceIndexCode", jsonObject.getString("parentIndexCode")) .put("resourceType", "acsDevice") .put("channelNos", Collections.singletonList(jsonObject.getString("channelNo"))) .build()); } /** * 获取《根据出入权限配置快捷下载》接口的请求的参数 * * @param jsonObject * @return */ private JSONObject getQueryDownloadProgressParam(JSONObject jsonObject) { JSONObject aaJo = new JSONObject(); aaJo.put("taskType", 4); aaJo.put("resourceInfos", getDevRqParam(jsonObject)); return aaJo; } /** * 获取《查询权限条目列表》的请求参数 * * @param workerIds * @param devRqParam * @return */ private JSONObject getQueryAuthItemParam(List workerIds, @NotNull List devRqParam) { JSONObject aaJo = new JSONObject(); aaJo.put("personIds", workerIds); aaJo.put("resourceInfos", devRqParam); aaJo.put("queryType", "acsDevice"); aaJo.put("pageNo", 1); aaJo.put("pageSize", MAX_PAGE_SIZE); return aaJo; } }