package com.iden.bms.service; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import com.alibaba.excel.EasyExcel; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.face.monitor.FaceMonitor; import com.face.monitor.model.FaceModel; import com.iden.bms.tool.FaceIdenTool; import com.iden.common.cache.DictCache; import com.iden.common.cache.FaceMoniterCache; import com.iden.common.cache.RedisKeyConstant; import com.iden.common.cache.RedisUtil; import com.iden.common.constant.Constants; import com.iden.common.entity.*; import com.iden.common.enums.CredentialsTypeEnum; import com.iden.common.enums.GenderEnum; import com.iden.common.enums.PersonTypeEnum; import com.iden.common.enums.PopulationTypeEnum; import com.iden.common.exceltool.RowWriteHandler; import com.iden.common.exception.BDException; import com.iden.common.service.*; import com.iden.common.util.ByteUtil; import com.iden.common.util.DateUtils; import com.iden.common.util.ImgUtil; import com.iden.common.vo.*; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.*; import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FileOutputStream; import java.net.URL; import java.net.URLEncoder; import java.util.*; /** * * @author makejava * @since 2021-05-21 00:08:38 */ @Service public class PersonService { @Resource private IdenPersonService idenPersonService; @Resource private IdenPersonCrowdRefService idenPersonCrowdRefService; @Resource private IdenCrowdService idenCrowdService; @Resource private IdenCommunityService idenCommunityService; @Resource private IdenWarningPersonService idenWarningPersonService; @Resource private RedisUtil redisUtil; @Value("${iden.root:#{null}}") private String idenRoot; @Value("${file.url:#{null}}") private String fileUrl; private static final Logger logger = LogManager.getLogger(PersonService.class); public PersonStaVO getPersonStaVO(String type, String nameOrCred, String district, String subdistrict, Long communityId, Long crowdId, String address, String gender, String populationType, UserLoginedConvertVO loginUser) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().like(IdenPerson::getType,type) .like(StrUtil.isNotEmpty(address), IdenPerson::getAddress,address) .eq(StrUtil.isNotEmpty(gender),IdenPerson::getGender,gender) .eq(StrUtil.isNotEmpty(populationType),IdenPerson::getPopulationType,populationType) .eq(StrUtil.isNotEmpty(district),IdenPerson::getDistrict,district) .eq(StrUtil.isNotEmpty(subdistrict),IdenPerson::getSubdistrict,subdistrict) .eq(communityId != null,IdenPerson::getCommunityId,communityId) .and(StrUtil.isNotEmpty(nameOrCred),wrapper -> wrapper.like(IdenPerson::getName,nameOrCred) .or().like(IdenPerson::getCredentialsCode,nameOrCred)); Integer personCount = this.idenPersonService.count(queryWrapper); QueryWrapper queryWrapper1 = new QueryWrapper<>(); queryWrapper1.lambda().like(IdenPerson::getType,type) .like(StrUtil.isNotEmpty(address), IdenPerson::getAddress,address) .eq(StrUtil.isNotEmpty(gender),IdenPerson::getGender,gender) .eq(StrUtil.isNotEmpty(populationType),IdenPerson::getPopulationType,populationType) .eq(StrUtil.isNotEmpty(district),IdenPerson::getDistrict,district) .eq(StrUtil.isNotEmpty(subdistrict),IdenPerson::getSubdistrict,subdistrict) .eq(communityId != null,IdenPerson::getCommunityId,communityId) .and(StrUtil.isNotEmpty(nameOrCred),wrapper -> wrapper.like(IdenPerson::getName,nameOrCred) .or().like(IdenPerson::getCredentialsCode,nameOrCred)) .isNotNull(IdenPerson::getImage); Integer faceImageCount = this.idenPersonService.count(queryWrapper1); QueryWrapper queryWrapper2 = new QueryWrapper<>(); queryWrapper2.select("distinct community_id") .lambda().like(IdenPerson::getType,type) .like(StrUtil.isNotEmpty(address), IdenPerson::getAddress,address) .eq(StrUtil.isNotEmpty(gender),IdenPerson::getGender,gender) .eq(StrUtil.isNotEmpty(populationType),IdenPerson::getPopulationType,populationType) .eq(StrUtil.isNotEmpty(district),IdenPerson::getDistrict,district) .eq(StrUtil.isNotEmpty(subdistrict),IdenPerson::getSubdistrict,subdistrict) .eq(communityId != null,IdenPerson::getCommunityId,communityId) .and(StrUtil.isNotEmpty(nameOrCred),wrapper -> wrapper.like(IdenPerson::getName,nameOrCred) .or().like(IdenPerson::getCredentialsCode,nameOrCred)); Integer communityCount = this.idenPersonService.count(queryWrapper2); PersonStaVO vo = new PersonStaVO(); vo.setCommunityCount(communityCount); vo.setFaceImageCount(faceImageCount); vo.setPersonCount(personCount); return vo; } /** * 查询人员列表 * @return */ public IPage listPerson(String type, String nameOrCred, String district, String subdistrict, Long communityId, Long crowdId, String address, String gender, String populationType, UserLoginedConvertVO loginUser, PageReqVO pageReqVo) { IPage page = new Page<>(pageReqVo.getCurrent(), pageReqVo.getPageSize()); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().like(IdenPerson::getType,type) .like(StrUtil.isNotEmpty(address), IdenPerson::getAddress,address) .eq(StrUtil.isNotEmpty(gender),IdenPerson::getGender,gender) .eq(StrUtil.isNotEmpty(populationType),IdenPerson::getPopulationType,populationType) .eq(StrUtil.isNotEmpty(district),IdenPerson::getDistrict,district) .eq(StrUtil.isNotEmpty(subdistrict),IdenPerson::getSubdistrict,subdistrict) .eq(communityId != null,IdenPerson::getCommunityId,communityId) .and(StrUtil.isNotEmpty(nameOrCred),wrapper -> wrapper.like(IdenPerson::getName,nameOrCred) .or().like(IdenPerson::getCredentialsCode,nameOrCred)) .orderByDesc(IdenPerson::getModifyTime) .orderByDesc(IdenPerson::getCreateTime); if (crowdId != null) { queryWrapper.apply(" iden_person.id in ( select person_id from iden_person_crowd_ref ipcr where ipcr.crowd_id = "+ crowdId + ")"); } IPage pageRes = this.idenPersonService.page(page, queryWrapper); IPage results = new Page<>(pageRes.getCurrent(),pageRes.getSize(),pageRes.getTotal()); if(CollUtil.isNotEmpty(pageRes.getRecords())){ List list = new ArrayList<>(); pageRes.getRecords().forEach(item -> { PersonVO resVO = new PersonVO(); BeanUtils.copyProperties(item,resVO); resVO.setPopulationTypeName(PopulationTypeEnum.getValueToName(resVO.getPopulationType())); resVO.setTypeName(PersonTypeEnum.getValueToName(resVO.getType())); resVO.setGenderName(GenderEnum.getValueToName(resVO.getGender())); resVO.setCredentialsTypeName(CredentialsTypeEnum.getValueToName(resVO.getCredentialsType())); resVO.setMarriageName(DictCache.getNameByValue("marriage", resVO.getMarriage())); resVO.setPolicitalStatusName(DictCache.getNameByValue("policital_status", resVO.getPolicitalStatus())); Long communityId1 = resVO.getCommunityId(); if(communityId1 != null){ IdenCommunity idenCommunity = this.idenCommunityService.getById(communityId1); if(idenCommunity != null) { resVO.setCommunityName(idenCommunity.getName()); } } QueryWrapper queryWrapper1 = new QueryWrapper<>(); queryWrapper1.lambda().eq(IdenPersonCrowdRef::getPersonId,resVO.getId()); List listIdenPersonCrowdRef = idenPersonCrowdRefService.list(queryWrapper1); StringBuilder sb = new StringBuilder(); if (CollUtil.isNotEmpty(listIdenPersonCrowdRef)) { for(IdenPersonCrowdRef idenPersonCrowdRef : listIdenPersonCrowdRef){ IdenCrowd idenCrowd = idenCrowdService.getById(idenPersonCrowdRef.getCrowdId()); if(idenCrowd != null) { sb.append(idenCrowd.getName()).append(","); } } } String crowdName = sb.toString(); if(crowdName != null && crowdName.endsWith(",")) { crowdName = crowdName.substring(0, crowdName.length() - 1); } resVO.setCrowdName(crowdName); list.add(resVO); }); results.setRecords(list); } return results; } public void downloadFormwork(UserLoginedConvertVO loginUser, HttpServletResponse response) throws Exception { List records = new ArrayList<>(); try { response.reset(); // 非常重要 response.addHeader("Access-Control-Allow-Origin", "*"); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); final String fileName = URLEncoder.encode("Person", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + "_" + System.currentTimeMillis() + ".xlsx"); EasyExcel.write(response.getOutputStream(), PersonExcelVO.class).sheet("人员表").registerWriteHandler(new RowWriteHandler()).doWrite(records); } catch (Exception e) { e.printStackTrace(); } } public void exportToExcel(String type, String nameOrCred, String district, String subdistrict, Long communityId, Long crowdId, String address, String gender, String populationType, UserLoginedConvertVO loginUser, HttpServletResponse response) throws Exception { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().like(IdenPerson::getType,type) .like(StrUtil.isNotEmpty(address), IdenPerson::getAddress,address) .eq(StrUtil.isNotEmpty(gender),IdenPerson::getGender,gender) .eq(StrUtil.isNotEmpty(populationType),IdenPerson::getPopulationType,populationType) .eq(StrUtil.isNotEmpty(district),IdenPerson::getDistrict,district) .eq(StrUtil.isNotEmpty(subdistrict),IdenPerson::getSubdistrict,subdistrict) .eq(communityId != null,IdenPerson::getCommunityId,communityId) .and(StrUtil.isNotEmpty(nameOrCred),wrapper -> wrapper.like(IdenPerson::getName,nameOrCred) .or().like(IdenPerson::getCredentialsCode,nameOrCred)) .orderByDesc(IdenPerson::getModifyTime) .orderByDesc(IdenPerson::getCreateTime); if (crowdId != null) { queryWrapper.apply(" in ( select person_id from iden_person_crowd_ref ipcr where ipcr.crowd_id = "+ crowdId + ")"); } List list = this.idenPersonService.list(queryWrapper); List records = new ArrayList<>(); if (CollUtil.isNotEmpty(list)) { list.forEach(item->{ PersonExcelVO resVO = new PersonExcelVO(); BeanUtils.copyProperties(item,resVO); resVO.setPopulationTypeName(PopulationTypeEnum.getValueToName(item.getPopulationType())); resVO.setTypeName(PersonTypeEnum.getValueToName(item.getType())); resVO.setGenderName(GenderEnum.getValueToName(item.getGender())); resVO.setCredentialsTypeName(CredentialsTypeEnum.getValueToName(item.getCredentialsType())); resVO.setMarriageName(DictCache.getNameByValue("marriage", item.getMarriage())); resVO.setPolicitalStatusName(DictCache.getNameByValue("policital_status", item.getPolicitalStatus())); try { resVO.setImageUrl(new URL(item.getImage())); } catch (Exception e){ e.printStackTrace(); } Long communityId1 = item.getCommunityId(); if(communityId1 != null){ IdenCommunity idenCommunity = this.idenCommunityService.getById(communityId1); if(idenCommunity != null) { resVO.setCommunityName(idenCommunity.getName()); } } QueryWrapper queryWrapper1 = new QueryWrapper<>(); queryWrapper1.lambda().eq(IdenPersonCrowdRef::getPersonId,item.getId()); List listIdenPersonCrowdRef = idenPersonCrowdRefService.list(queryWrapper1); StringBuilder sb = new StringBuilder(); if (CollUtil.isNotEmpty(listIdenPersonCrowdRef)) { for(IdenPersonCrowdRef idenPersonCrowdRef : listIdenPersonCrowdRef){ IdenCrowd idenCrowd = idenCrowdService.getById(idenPersonCrowdRef.getCrowdId()); if(idenCrowd != null) { sb.append(idenCrowd.getName()).append(","); } } } String crowdName = sb.toString(); if(crowdName != null && crowdName.endsWith(",")) { crowdName = crowdName.substring(0, crowdName.length() - 1); } resVO.setCrowdName(crowdName); records.add(resVO); }); } try { response.reset(); // 非常重要 response.addHeader("Access-Control-Allow-Origin", "*"); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); final String fileName = URLEncoder.encode("Person", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + "_" + System.currentTimeMillis() + ".xlsx"); EasyExcel.write(response.getOutputStream(), PersonExcelVO.class).sheet("人员表").registerWriteHandler(new RowWriteHandler()).doWrite(records); } catch (Exception e) { e.printStackTrace(); } } /** * 导入 * @param file * @return * @throws Exception */ @Transactional(rollbackFor = Exception.class) public List importWithExcel(MultipartFile file) throws BDException { List personIdList = new ArrayList<>(); try { String excelFileName = file.getOriginalFilename(); logger.info("excelFileName ==" + excelFileName); if (!excelFileName.substring(excelFileName.length() - 4).equals("xlsx")) { throw new BDException("导入Excel只支持xlsx格式"); } XSSFWorkbook workBook = new XSSFWorkbook(file.getInputStream()); Sheet sheet = workBook.getSheetAt(0); if (sheet.getLastRowNum() == 0) { logger.error("表中无数据!"); throw new BDException("表中无数据"); } //图片对应的行和图片数据 Map picMap = new HashMap<>(); //读取sheet的图片放入Map for (POIXMLDocumentPart dr : ((XSSFSheet) sheet).getRelations()) { if (dr instanceof XSSFDrawing) { XSSFDrawing drawing = (XSSFDrawing) dr; List shapes = drawing.getShapes(); for (XSSFShape shape : shapes) { XSSFPicture pic = (XSSFPicture) shape; //获取图片格式 String ext = pic.getPictureData().suggestFileExtension(); logger.info("ext == " + ext); if(!"jpg".equalsIgnoreCase(ext) && !"jpeg".equalsIgnoreCase(ext) && !"png".equalsIgnoreCase(ext) ){ throw new BDException("Excel中只能放jpg或png格式图像"); } XSSFClientAnchor anchor = pic.getPreferredSize(); CTMarker ctMarker = anchor.getFrom(); int row = ctMarker.getRow(); picMap.put(row, pic.getPictureData()); } } } //定义数据集合存放excel所有数据 List personVOList = new ArrayList<>(); //遍历行 for (int i = 1; i <= sheet.getLastRowNum(); i++) { logger.info("sheet.getLastRowNum() ==" + sheet.getLastRowNum()); //错误提示消息 StringBuffer msg = new StringBuffer(); Row row = sheet.getRow(i); if (null == row) continue; PersonVO personVO = new PersonVO(); IdenCommunity idenCommunity = null; // 遍历列 for (int j = 0; j < 23; j++) { Cell cell = row.getCell(j); String value = null; if (null != cell) { //全部作为文本处理 //cell.setCellType(HSSFCell.CELL_TYPE_STRING); value = cell.getStringCellValue(); } if (0 == j) {//人员编码 if (StringUtils.isNotBlank(value)){ personVO.setCode(value); } } else if (1 == j) {//姓名 if (StringUtils.isNotBlank(value)){ personVO.setName(value); }else { msg.append("请填写姓名!\n"); } } else if (3 == j) {//性别 if (StringUtils.isNotBlank(value)) { personVO.setGender(GenderEnum.getNameToValue(value)); } } else if (4 == j) {//证件类型 if (StringUtils.isNotBlank(value)){ personVO.setCredentialsType(CredentialsTypeEnum.getNameToValue(value)); } } else if (5 == j) {//证件号码 if (StringUtils.isNotBlank(value)){ personVO.setCredentialsCode(value); } } else if (6 == j) {//手机号码 if (StringUtils.isNotBlank(value)){ personVO.setPhone(value); } } else if (7 == j) {//人口类型 if (StringUtils.isNotBlank(value)){ personVO.setPopulationType(PopulationTypeEnum.getNameToValue(value)); } } else if (8 == j) {//民族 if (StringUtils.isNotBlank(value)){ personVO.setNation(value); } } else if (9 == j) {//政治面貌 if (StringUtils.isNotBlank(value)){ personVO.setPolicitalStatus(DictCache.getValueByName("policital_status",value)); } } else if (10 == j) {//婚姻 if (StringUtils.isNotBlank(value)){ personVO.setMarriage(DictCache.getValueByName("marriage",value)); } } else if (11 == j) {//口音 if (StringUtils.isNotBlank(value)){ personVO.setVoice(value); } } else if (12 == j) {//所属区域 if (StringUtils.isNotBlank(value)){ personVO.setDistrict(value); } } else if (13 == j) {//所属街道 if (StringUtils.isNotBlank(value)){ personVO.setSubdistrict(value); } } else if (14== j) {//所属小区 if (StringUtils.isNotBlank(value)){ logger.info("小区名字==" + value); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(IdenCommunity::getName,value); idenCommunity = this.idenCommunityService.getOne(queryWrapper); logger.info("idenCommunity ==" + idenCommunity); if(idenCommunity != null){ personVO.setCommunityId(idenCommunity.getId()); } else { msg.append("填写所属小区名称不存在!\n"); } }else { msg.append("请填写所属小区!\n"); } } else if (15 == j) {//地址 if (StringUtils.isNotBlank(value)){ personVO.setAddress(value); } } else if (16 == j) {//工作单位 if (StringUtils.isNotBlank(value)){ personVO.setWorkPlace(value); } } else if (17 == j) {//单位地址 if (StringUtils.isNotBlank(value)){ personVO.setWorkAddress(value); } } else if (18 == j) {//类型 if (StringUtils.isNotBlank(value)){ logger.info("类型==" + value); String type = PersonTypeEnum.getNameToValue(value); logger.info("type==" + type); if(StringUtils.isEmpty(type)){ msg.append("请填写类型(重点人员或小区人员,多个用英文逗号分隔)!\n"); } else { personVO.setType(type); } } else { msg.append("请填写类型(重点人员或小区人员,多个用英文逗号分隔)!\n"); } } else if (19 == j) {//人群类型 if (StringUtils.isNotBlank(value)){ String[] crowdNames = value.split(","); List idenCrowdIds = new ArrayList<>(); for (String crowdName : crowdNames) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(IdenCrowd::getName,crowdName); IdenCrowd idenCrowd = this.idenCrowdService.getOne(queryWrapper); if(idenCrowd == null){ msg.append("填写人群类型错误(多个用英文逗号分隔)!\n"); idenCrowdIds.clear(); break; } else{ idenCrowdIds.add(idenCrowd.getId()); } } if(CollUtil.isNotEmpty(idenCrowdIds)){ personVO.setCrowdIds(idenCrowdIds); } } } else if (20 == j) {//备注 if (StringUtils.isNotBlank(value)){ personVO.setRemark(value); } } if (!StringUtils.isBlank(msg.toString())) { logger.error("第 " + i + " 行: " + msg.toString()); throw new BDException("第 " + i + " 行: " + msg.toString()); } } PictureData picData = picMap.get(i); if(picData != null){ //保存的文件名 String saveFileName = DateUtils.getCurrYyyyMMddHHmmssDate() + "_" + UUID.randomUUID().toString() + "." + picData.suggestFileExtension(); logger.info("saveFileName== " + saveFileName); String savePath = idenRoot + "data/final/person/image/" + idenCommunity.getCode() + "/" + saveFileName; // 保存图片 savePic(picData,savePath); personVO.setImage(fileUrl + "person/image/" + idenCommunity.getCode() +"/" + saveFileName); } String image = personVO.getImage(); if(StringUtils.isNotEmpty(image)) { String featPtr = idenFeatPtr(image,idenCommunity.getCode()); if(StringUtils.isNotEmpty(featPtr)) { personVO.setFeatPtr(featPtr); } else { throw new BDException("图像识别失败,请上传正确人脸图像"); } } personVOList.add(personVO); } if (CollUtil.isNotEmpty(personVOList)) { List idenPersonCrowdRefList = new ArrayList<>(); personVOList.forEach(item->{ IdenPerson idenPerson = new IdenPerson(); BeanUtil.copyProperties(item,idenPerson); idenPerson.setUid(UUID.randomUUID().toString()); idenPerson.setCreateTime(new Date()); idenPersonService.save(idenPerson); appendFaceDataset(idenPerson); personIdList.add(idenPerson.getId()); List crowdIds = item.getCrowdIds(); if(CollUtil.isNotEmpty(crowdIds)){ crowdIds.forEach(item1 ->{ IdenPersonCrowdRef idenPersonCrowdRef = new IdenPersonCrowdRef(); idenPersonCrowdRef.setCrowdId(item1); idenPersonCrowdRef.setPersonId(idenPerson.getId()); idenPersonCrowdRefList.add(idenPersonCrowdRef); }); } }); if(CollUtil.isNotEmpty(idenPersonCrowdRefList)){ //批量保存 this.idenPersonCrowdRefService.saveBatch(idenPersonCrowdRefList); } } } catch (Exception e) { logger.error("导入异常", e); e.printStackTrace(); throw new BDException("导入异常:" + e.getMessage()); } return personIdList; } private void savePic( PictureData picData,String savePath) throws Exception { byte[] data = picData.getData(); FileOutputStream out = new FileOutputStream(savePath); out.write(data); out.close(); } /** * 删除人员 * @param id * @return */ @Transactional(rollbackFor = Exception.class) public void deleteById(Long id) throws BDException { String key = RedisKeyConstant.PERSON_DELETE; String requestId = UUID.randomUUID().toString(); boolean result = redisUtil.tryLock(key,requestId,10 * 60); try { if (result) { QueryWrapper queryWrapper0 = new QueryWrapper<>(); queryWrapper0.lambda().eq(IdenWarningPerson::getPersonId,id); int cnt = this.idenWarningPersonService.count(queryWrapper0); if(cnt > 0){ throw new BDException("人员被引用,不能删除"); } IdenPerson idenPerson = this.idenPersonService.getById(id); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(IdenPersonCrowdRef::getPersonId,idenPerson.getId()); idenPersonCrowdRefService.remove(queryWrapper); String image = idenPerson.getImage(); IdenCommunity idenCommunity = this.idenCommunityService.getById(idenPerson.getCommunityId()); if (StringUtils.isNotEmpty(image) && idenCommunity != null) { File imageFile = new File(idenRoot + "data/final/person/image/" + idenCommunity.getCode() + "/" + image.substring(image.lastIndexOf("/"))); if(imageFile.exists()){ imageFile.delete(); } } this.idenPersonService.removeById(id); reloadFaceDataset(); } else { throw new BDException("不能多人同时删除,稍后再试"); } } catch (Exception e) { e.getMessage(); } finally { redisUtil.releaseLock(key,requestId); } } /** * 详情 * @param id * @return */ public PersonVO getPersonById(Long id){ IdenPerson idenPerson = this.idenPersonService.getById(id); if (idenPerson!=null){ PersonVO resVO = new PersonVO(); BeanUtil.copyProperties(idenPerson,resVO); resVO.setPopulationTypeName(PopulationTypeEnum.getValueToName(resVO.getPopulationType())); resVO.setTypeName(PersonTypeEnum.getValueToName(resVO.getType())); resVO.setMarriageName(DictCache.getNameByValue("marriage", resVO.getMarriage())); resVO.setPolicitalStatusName(DictCache.getNameByValue("policital_status", resVO.getPolicitalStatus())); QueryWrapper queryWrapper1 = new QueryWrapper<>(); queryWrapper1.lambda().eq(IdenPersonCrowdRef::getPersonId,resVO.getId()); List listIdenPersonCrowdRef = idenPersonCrowdRefService.list(queryWrapper1); StringBuilder sb = new StringBuilder(); if (CollUtil.isNotEmpty(listIdenPersonCrowdRef)) { for(IdenPersonCrowdRef idenPersonCrowdRef : listIdenPersonCrowdRef){ IdenCrowd idenCrowd = idenCrowdService.getById(idenPersonCrowdRef.getCrowdId()); if(idenCrowd != null) { sb.append(idenCrowd.getName()).append(","); } } } String crowdName = sb.toString(); if(crowdName != null && crowdName.endsWith(",")) { crowdName = crowdName.substring(0, crowdName.length() - 1); } resVO.setCrowdName(crowdName); return resVO; } return null; } /** * 上传图像 * @param file * @return 访问URL */ public String uploadImage(MultipartFile file,Long communityId) throws BDException { if(communityId == null ){ throw new BDException("必须选择小区"); } IdenCommunity idenCommunity = this.idenCommunityService.getById(communityId); if(idenCommunity == null ){ throw new BDException("小区不能为空"); } String image = null; try { if (file != null) { //获取文件名 String fileName = file.getOriginalFilename(); if (org.springframework.util.StringUtils.isEmpty(fileName) || file.getSize() == 0) { throw new BDException("图像文件不能为空!"); } //验证文件名是否合格 if (!ImgUtil.isImg(fileName)) { throw new BDException("图像文件必须是图片格式!"); } String saveFileName = DateUtils.getCurrYyyyMMddHHmmssDate() + "_" + UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf("."), fileName.length()); String uploadDir = idenRoot + "data/final/person/image/" + idenCommunity.getCode() + "/"; File uploadDirFile = new File(uploadDir); if (!uploadDirFile.exists()){ uploadDirFile.mkdirs(); } FileOutputStream fos = new FileOutputStream(uploadDir + saveFileName); fos.write(file.getBytes()); image = fileUrl + "person/image/" + idenCommunity.getCode() +"/"+ saveFileName; } else { throw new BDException("上传失败"); } } catch (Exception e) { e.printStackTrace(); throw new BDException("上传失败",e); } return image; } /** * 保存人员 * 一个人只属于一个小区,避免同一个自然人属于二个小区 * @param vo */ @Transactional(rollbackFor = Exception.class) public void createPerson(PersonVO vo, UserLoginedConvertVO loginUser) throws BDException { Long communityId = vo.getCommunityId(); if(communityId == null ){ throw new BDException("必须选择小区"); } IdenCommunity idenCommunity = this.idenCommunityService.getById(communityId); if(idenCommunity == null ){ throw new BDException("小区不能为空"); } //保存人员 IdenPerson idenPerson = new IdenPerson(); BeanUtil.copyProperties(vo,idenPerson); idenPerson.setUid(UUID.randomUUID().toString()); idenPerson.setCreateTime(new Date()); //识别 String image = idenPerson.getImage(); if(StringUtils.isNotEmpty(image)) { String featPtr = idenFeatPtr(image,idenCommunity.getCode()); if(StringUtils.isNotEmpty(featPtr)) { idenPerson.setFeatPtr(featPtr); } else { throw new BDException("图像识别失败,请上传正确人脸图像"); } } this.idenPersonService.save(idenPerson); appendFaceDataset(idenPerson); } private void appendFaceDataset(IdenPerson idenPerson){ //追加陌生人脸库缓存 FaceMonitor faceMonitorPerson = FaceMoniterCache.getFaceMonitor(Constants.FACE_CACHE_PERSON_KEY); FaceModel[] dataset = new FaceModel[1]; dataset[0] = new FaceModel(); dataset[0].setPersonId(idenPerson.getId().intValue()); dataset[0].setName(idenPerson.getUid()); dataset[0].setFeatValue(ByteUtil.hex2Byte(idenPerson.getFeatPtr())); faceMonitorPerson.appendFaceDataset(dataset); } private void reloadFaceDataset(){ //重新加载人脸库缓存 FaceMonitor faceMonitorPerson = FaceMoniterCache.getFaceMonitor(Constants.FACE_CACHE_PERSON_KEY); QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.select("id","name","feat_ptr"); queryWrapper.lambda().isNotNull(IdenPerson::getFeatPtr); List idenPersonList = idenPersonService.list(queryWrapper); if (CollUtil.isNotEmpty(idenPersonList)) { FaceModel[] dataset = new FaceModel[idenPersonList.size()]; for(int i = 0; i < idenPersonList.size(); i++){ IdenPerson idenPerson = idenPersonList.get(i); dataset[i] = new FaceModel(); dataset[i].setPersonId(idenPerson.getId().intValue()); dataset[i].setName(idenPerson.getUid()); dataset[i].setFeatValue(ByteUtil.hex2Byte(idenPerson.getFeatPtr())); } faceMonitorPerson.loadFaceDataset(dataset); } } /** * 修改人员 * @param vo */ @Transactional(rollbackFor = Exception.class) public void updatePerson(PersonVO vo) throws BDException { String key = RedisKeyConstant.PERSON_UPDATE; String requestId = UUID.randomUUID().toString(); boolean result = redisUtil.tryLock(key,requestId,10 * 60); try { if (result) { vo.setCommunityId(null);//不能修改小区 IdenPerson idenPerson = this.idenPersonService.getById(vo.getId()); Long communityId = idenPerson.getCommunityId(); IdenCommunity idenCommunity = this.idenCommunityService.getById(communityId); //保存人员 String oldImage = idenPerson.getImage(); BeanUtil.copyProperties(vo,idenPerson); String newImage = vo.getImage(); if (StringUtils.isNotEmpty(newImage) && !newImage.equals(oldImage)){ //识别 String fileNameNew = newImage.substring(newImage.lastIndexOf("/")); File imgFileNew = new File(idenRoot + "data/final/person/image/" + idenCommunity.getCode() + "/" + fileNameNew); String featPtr = FaceIdenTool.getFeatPtr(idenRoot,imgFileNew); if (FaceIdenTool.isBad(featPtr)){ File discardDir = new File(imgFileNew.getParentFile().getAbsolutePath().replace("final","discard")); if(!discardDir.exists()){ discardDir.mkdirs(); } File discardImgFile = new File(discardDir, fileNameNew); imgFileNew.renameTo(discardImgFile);//移动到废弃目录 throw new BDException("图像识别失败,请上传正确人脸图像"); } idenPerson.setFeatPtr(featPtr); // 删除老的文件 if(StringUtils.isNotEmpty(oldImage)){ String fileNameOld = oldImage.substring(oldImage.lastIndexOf("/")); File imgFileOld = new File(idenRoot + "data/final/person/image/" + idenCommunity.getCode() + "/" + fileNameOld); if(imgFileOld.exists()){ imgFileOld.delete(); } } } idenPerson.setModifyTime(new Date()); this.idenPersonService.updateById(idenPerson); reloadFaceDataset(); } else { throw new BDException("不能多人同时修改,稍后再试"); } } catch (Exception e) { e.getMessage(); } finally { redisUtil.releaseLock(key,requestId); } } /** * 修改人员 * @param vo */ @Transactional(rollbackFor = Exception.class) public void updateRemark(PersonVO vo) throws BDException { UpdateWrapper updateWrapper = new UpdateWrapper(); updateWrapper.lambda().set(IdenPerson::getRemark,vo.getRemark()) .eq(IdenPerson::getId,vo.getId()); this.idenPersonService.update(updateWrapper); } private String idenFeatPtr(String image,String communityCode) { String fileName = image.substring(image.lastIndexOf("/")); File imgFile = new File(idenRoot + "data/final/person/image/"+ communityCode + "/" + fileName); String featPtr = FaceIdenTool.getFeatPtr(idenRoot,imgFile); if (FaceIdenTool.isBad(featPtr)) { File discardDir = new File(imgFile.getParentFile().getAbsolutePath().replace("final","discard")); if(!discardDir.exists()){ discardDir.mkdirs(); } File discardImgFile = new File(discardDir, fileName); imgFile.renameTo(discardImgFile);//移动到废弃目录 featPtr = null; } return featPtr; } }