package com.xjrsoft.module.personnel.controller; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.github.yulichang.toolkit.MPJWrappers; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.xjrsoft.common.enums.DeleteMark; import com.xjrsoft.common.model.result.RT; import com.xjrsoft.common.page.ConventPage; import com.xjrsoft.common.page.PageOutput; import com.xjrsoft.common.utils.FileZipUtil; import com.xjrsoft.common.utils.ImageUtil; import com.xjrsoft.common.utils.UploadUtil; import com.xjrsoft.common.utils.VoToColumnUtil; import com.xjrsoft.module.base.entity.BaseClass; import com.xjrsoft.module.base.service.IBaseClassService; import com.xjrsoft.module.base.vo.StudentClassVo; import com.xjrsoft.module.hikvision.mapper.HikvisionDataMapper; import com.xjrsoft.module.hikvision.util.ApiUtil; import com.xjrsoft.module.personnel.dto.AddFaceManagementDto; import com.xjrsoft.module.personnel.dto.AddStundentFaceProcessDto; import com.xjrsoft.module.personnel.dto.StundentFaceProcessPageDto; import com.xjrsoft.module.personnel.dto.UpdateStundentFaceProcessDto; import com.xjrsoft.module.personnel.entity.FaceManagement; import com.xjrsoft.module.personnel.entity.StundentFaceProcess; import com.xjrsoft.module.personnel.service.IFaceManagementService; import com.xjrsoft.module.personnel.service.IStundentFaceProcessService; import com.xjrsoft.module.personnel.vo.StundentFaceProcessPageVo; import com.xjrsoft.module.personnel.vo.StundentFaceProcessVo; import com.xjrsoft.module.student.entity.BaseStudent; import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll; import com.xjrsoft.module.student.entity.BaseStudentUser; import com.xjrsoft.module.student.service.IStudentManagerService; import com.xjrsoft.module.system.entity.DictionaryDetail; import com.xjrsoft.module.system.entity.File; import com.xjrsoft.module.system.service.IFileService; import com.xjrsoft.module.teacher.entity.XjrUser; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.validation.Valid; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.nio.file.Files; import java.time.LocalDateTime; import java.util.Base64; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * @title: 学生人脸信息审核 * @Author dzx * @Date: 2024-05-10 * @Version 1.0 */ @RestController @RequestMapping("/personnel" + "/stundentFaceProcess") @Api(value = "/personnel" + "/stundentFaceProcess",tags = "学生人脸信息审核代码") @AllArgsConstructor public class StundentFaceProcessController { private final IStundentFaceProcessService stundentFaceProcessService; private final IStudentManagerService studentManagerService; private final IFileService fileService; private final IFaceManagementService faceManagementService; private final IBaseClassService classService; private final HikvisionDataMapper hikvisionDataMapper; @GetMapping(value = "/page") @ApiOperation(value="学生人脸信息审核列表(分页)") @SaCheckPermission("stundentfaceprocess:detail") public RT> page(@Valid StundentFaceProcessPageDto dto){ if(ObjectUtil.isNull(dto.getStatus())){ dto.setStatus(1); } IPage page=stundentFaceProcessService.selectJoinListPage(ConventPage.getPage(dto),StundentFaceProcessPageVo.class, MPJWrappers.lambdaJoin() .orderByDesc(StundentFaceProcess::getId) .disableSubLogicDel() .like(StrUtil.isNotBlank(dto.getName()), XjrUser::getName,dto.getName()) .eq(StrUtil.isNotBlank(dto.getStduyStatus()),BaseStudentSchoolRoll::getStduyStatus,dto.getStduyStatus()) .like(StrUtil.isNotBlank(dto.getMobile()),XjrUser::getMobile,dto.getMobile()) .like(StrUtil.isNotBlank(dto.getStudentId()),BaseStudent::getStudentId,dto.getStudentId()) .eq(ObjectUtil.isNotNull(dto.getClassId())&&dto.getClassId()!=0,StundentFaceProcess::getClassId,dto.getClassId()) .eq(StundentFaceProcess::getExamStatus,dto.getStatus()) .select(StundentFaceProcess::getId,StundentFaceProcess::getUserId,StundentFaceProcess::getClassId,StundentFaceProcess::getFacePhoto) .innerJoin(XjrUser.class,XjrUser::getId, StundentFaceProcess::getUserId) .leftJoin(File.class,File::getFolderId,StundentFaceProcess::getFacePhoto) .leftJoin(FaceManagement.class,FaceManagement::getFileId, StundentFaceProcess::getFacePhoto) .leftJoin(DictionaryDetail.class,DictionaryDetail::getCode,StundentFaceProcess::getGender, ext->ext.selectAs(DictionaryDetail::getName, StundentFaceProcessPageVo::getGender)) .leftJoin(BaseStudentSchoolRoll.class,BaseStudentSchoolRoll::getUserId,StundentFaceProcess::getUserId) .leftJoin(DictionaryDetail.class,DictionaryDetail::getCode,BaseStudentSchoolRoll::getStduyStatus, ext->ext.selectAs(DictionaryDetail::getName, StundentFaceProcessPageVo::getStduyStatus)) .leftJoin(BaseClass.class,BaseClass::getId,StundentFaceProcess::getClassId,ext->ext.selectAs(BaseClass::getName,StundentFaceProcessPageVo::getClassCn)) .leftJoin(XjrUser.class,XjrUser::getId,StundentFaceProcess::getTeacherId, ext->ext.selectAs(XjrUser::getName, StundentFaceProcessPageVo::getTeacherCn)) .selectAs(XjrUser::getName,StundentFaceProcess::getName) .select("t2.file_url AS face_photo_url,t1.user_name AS user_name,t1.mobile") .leftJoin(BaseStudent.class,BaseStudent::getUserId,StundentFaceProcess::getUserId, ext->ext.selectAs(BaseStudent::getStudentId, StundentFaceProcessPageVo::getStudentId)) ); PageOutput pageOutput = ConventPage.getPageOutput(page, StundentFaceProcessPageVo.class); return RT.ok(pageOutput); } @GetMapping(value = "/info") @ApiOperation(value="根据id查询学生人脸信息审核信息") @SaCheckPermission("stundentfaceprocess:detail") public RT info(@RequestParam Long id){ StundentFaceProcess stundentFaceProcess = stundentFaceProcessService.getById(id); if (stundentFaceProcess == null) { return RT.error("找不到此数据!"); } return RT.ok(BeanUtil.toBean(stundentFaceProcess, StundentFaceProcessVo.class)); } @GetMapping(value = "/info-userId") @ApiOperation(value="根据用户id查询学生人脸信息审核信息") @SaCheckPermission("stundentfaceprocess:detail") public RT infoUserId(@RequestParam Long userId){ List stundentFaceProcess = stundentFaceProcessService.list( new QueryWrapper().lambda() .eq(StundentFaceProcess::getUserId, userId) .eq(StundentFaceProcess::getStatus, 1) .orderByDesc(StundentFaceProcess::getCreateDate) ); if (stundentFaceProcess == null || stundentFaceProcess.isEmpty()) { return RT.error("找不到此数据!"); } return RT.ok(BeanUtil.toBean(stundentFaceProcess.get(0), StundentFaceProcessVo.class)); } @PostMapping @ApiOperation(value = "新增学生人脸信息审核") @SaCheckPermission("stundentfaceprocess:add") public RT add(@Valid @RequestBody AddStundentFaceProcessDto dto){ StundentFaceProcess stundentFaceProcess = BeanUtil.toBean(dto, StundentFaceProcess.class); boolean isSuccess = stundentFaceProcessService.save(stundentFaceProcess); return RT.ok(isSuccess); } @PutMapping @ApiOperation(value = "修改学生人脸信息审核") @SaCheckPermission("stundentfaceprocess:edit") public RT update(@Valid @RequestBody UpdateStundentFaceProcessDto dto){ StundentFaceProcess stundentFaceProcess = BeanUtil.toBean(dto, StundentFaceProcess.class); return RT.ok(stundentFaceProcessService.updateById(stundentFaceProcess)); } @DeleteMapping @ApiOperation(value = "删除学生人脸信息审核") @SaCheckPermission("stundentfaceprocess:delete") public RT delete(@Valid @RequestBody List ids){ return RT.ok(stundentFaceProcessService.removeByIds(ids)); } @PostMapping(value = "/batch-import") @ApiOperation(value = "批量新增学生人脸") @SaCheckPermission("stundentfaceprocess:batch-upload") public RT batchUpload(@RequestParam("file") MultipartFile file) throws Exception { List list = studentManagerService.list( new MPJLambdaWrapper().distinct() .select(BaseStudentUser::getId) .select(BaseStudentUser.class, user -> !user.getColumn().equals("avatar")) .select(BaseStudentUser.class, x -> VoToColumnUtil.fieldsToColumns(BaseStudentUser.class).contains(x.getProperty())) .leftJoin(BaseStudent.class, BaseStudent::getUserId, BaseStudentUser::getId) .eq(BaseStudent::getDeleteMark, DeleteMark.NODELETE.getCode()) .eq(BaseStudentUser::getDeleteMark, DeleteMark.NODELETE.getCode()) ); Map studentMap = new HashMap<>(); for (BaseStudentUser baseStudentUser : list) { studentMap.put(baseStudentUser.getCredentialNumber(), baseStudentUser); } List studentClass = classService.getStudentClass(); Map studentClassMap = new HashMap<>(); for (StudentClassVo classVo : studentClass) { studentClassMap.put(classVo.getUserId(), classVo); } List faceList = stundentFaceProcessService.list( new QueryWrapper().lambda() .eq(StundentFaceProcess::getDeleteMark, DeleteMark.NODELETE.getCode()) ); Map faceMap = new HashMap<>(); for (StundentFaceProcess faceProcess : faceList) { faceMap.put(faceProcess.getUserId(), faceProcess); } List faceManagementList = faceManagementService.list( new QueryWrapper().lambda() .select(FaceManagement.class, face -> !face.getColumn().equals("registerBase64")) .select(FaceManagement.class, face -> !face.getColumn().equals("register_base64")) .eq(FaceManagement::getDeleteMark, DeleteMark.NODELETE.getCode()) .eq(FaceManagement::getUserType, 2) ); Map faceManagementMap = new HashMap<>(); for (FaceManagement management : faceManagementList) { faceManagementMap.put(management.getUserId(), management); } JsonParser parser = new JsonParser(); ApiUtil apiUtil = new ApiUtil(); ZipFile zipFile = FileZipUtil.convertToZipFile(file); Enumeration entries = zipFile.entries(); while (entries.hasMoreElements()){ ZipEntry entry = entries.nextElement(); String filename = entry.getName(); InputStream inputStream = zipFile.getInputStream(entry); //读取文件内容 String[] split = filename.split("\\."); String idNumber = split[0].substring(split[0].length() - 18); BaseStudentUser studentUser = studentMap.get(idNumber); if(studentUser == null){ continue; } //将照片转换成base64 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } byte[] imageBytes = outputStream.toByteArray(); //压缩到200k imageBytes = ImageUtil.compressUnderSize(imageBytes, 204800); //压缩之后,存入本地 String suffix = StringUtils.substringAfterLast(filename, StringPool.DOT); String tempFilePath = "/" + IdUtil.getSnowflakeNextId() + "." + suffix; FileOutputStream fos = new FileOutputStream(tempFilePath); fos.write(imageBytes); fos.close(); //再读取出来 java.io.File tempFile = new java.io.File(tempFilePath); imageBytes = Files.readAllBytes(tempFile.toPath()); //删除文件 if(tempFile.exists()){ tempFile.delete(); } String base64String = Base64.getEncoder().encodeToString(imageBytes); inputStream.close(); outputStream.close(); //保存到云服务器 String filePath = UploadUtil.uploadFileByte(filename, imageBytes); //存入数据库 long fileId = IdUtil.getSnowflakeNextId(); Long folderId = IdWorker.getId(); File fileEntity = new File(); fileEntity.setId(fileId); fileEntity.setFolderId(folderId); fileEntity.setFileName(filename); fileEntity.setCreateDate(LocalDateTime.now()); fileEntity.setCreateUserId(StpUtil.getLoginIdAsLong()); fileEntity.setDeleteMark(0); fileEntity.setFileUrl(filePath); fileEntity.setFileSize(file.getSize()); fileEntity.setFileSuffiex(StringPool.DOT + suffix); fileEntity.setFileType(suffix); fileService.save(fileEntity); StundentFaceProcess process = faceMap.get(studentUser.getId()); if(process == null){ StudentClassVo classVo = studentClassMap.get(studentUser.getId()); if(classVo == null){ continue; } long baseFaceId = IdUtil.getSnowflakeNextId(); FaceManagement baseFace = new FaceManagement(); baseFace.setId(baseFaceId); baseFace.setRegisterBase64(base64String); baseFace.setUserId(studentUser.getId()); baseFace.setSex(studentUser.getGender()); baseFace.setName(studentUser.getName()); baseFace.setIdno(studentUser.getCredentialNumber()); baseFace.setVerifyStatus(1); baseFace.setCreateDate(LocalDateTime.now()); baseFace.setCreateUserId(StpUtil.getLoginIdAsLong()); baseFace.setDeleteMark(0); baseFace.setStatus(1); baseFace.setFileId(folderId); baseFace.setUserType(2L); faceManagementService.save(baseFace); StundentFaceProcess studentFace = new StundentFaceProcess(); studentFace.setStatus(1); studentFace.setCreateDate(new Date()); studentFace.setCreateUserId(StpUtil.getLoginIdAsLong()); studentFace.setDeleteMark(0); studentFace.setGender(studentUser.getGender()); studentFace.setFacePhoto(folderId); studentFace.setName(studentUser.getName()); studentFace.setClassId(classVo.getId()); studentFace.setClassCn(classVo.getName()); studentFace.setTeacherId(classVo.getTeacherId()); studentFace.setIdentityCard(studentUser.getCredentialNumber()); studentFace.setStatus(1); studentFace.setUserId(studentUser.getId()); studentFace.setExamStatus(1); //将人脸上传海康 JsonObject paramJson = new JsonObject(); paramJson.addProperty("personId", hikvisionDataMapper.getStudentHikvisionId(studentUser.getId())); paramJson.addProperty("faceData", base64String); Map querys = new HashMap<>(); querys.put("tagId", "frs"); String apiPath = "/api/resource/v1/face/single/add"; String response = apiUtil.doPost(apiPath, String.valueOf(paramJson), querys); studentFace.setHikvisionResult(response); stundentFaceProcessService.save(studentFace); }else{ process.setStatus(1); process.setExamStatus(1); process.setModifyDate(new Date()); process.setModifyUserId(StpUtil.getLoginIdAsLong()); process.setDeleteMark(0); process.setFacePhoto(folderId); String faceId = null; if(process.getHikvisionResult() != null && process.getHikvisionResult().startsWith("{") && process.getHikvisionResult().endsWith("}")){ JsonObject object = parser.parse(process.getHikvisionResult()).getAsJsonObject(); if("0".equals(object.get("code").getAsString()) && "success".equals(object.get("msg").getAsString()) && !object.get("data").isJsonNull()){ faceId = object.get("data").getAsJsonObject().get("faceId").getAsString(); } } if(faceId == null){ String apiUrl = "/api/resource/v1/person/condition/personInfo"; JsonObject paramsJson = new JsonObject(); paramsJson.addProperty("paramName", "personId"); JsonArray array = new JsonArray(); array.add(studentUser.getId()); paramsJson.add("paramValue", array); String personInfoRes = apiUtil.doPost(apiUrl, paramsJson.toString(), null); JsonObject personInfoData = parser.parse(personInfoRes).getAsJsonObject(); if("0".equals(personInfoData.get("code").getAsString()) && "success".equals(personInfoData.get("msg").getAsString())){ JsonObject dataJson = personInfoData.get("data").getAsJsonObject(); if(dataJson.get("total").getAsInt() > 0){ JsonArray personPhoto = dataJson.get("list").getAsJsonArray().get(0) .getAsJsonObject().get("personPhoto").getAsJsonArray(); if(personPhoto.size() > 0){ faceId = personPhoto.get(0).getAsJsonObject().get("personPhotoIndexCode").getAsString(); } } } } //更新海康数据 JsonObject paramJson = new JsonObject(); String apiPath; if(faceId != null){ apiPath = "/api/resource/v1/face/single/update"; paramJson.addProperty("faceId", faceId); paramJson.addProperty("faceData", base64String); }else{ apiPath = "/api/resource/v1/face/single/add"; paramJson.addProperty("personId", studentUser.getId()); paramJson.addProperty("faceData", base64String); } String result = apiUtil.doPost(apiPath, paramJson.toString(), null); if(result.startsWith("{") && result.endsWith("}")){ JsonObject object = parser.parse(result).getAsJsonObject(); if("0".equals(object.get("code").getAsString()) && "success".equals(object.get("msg").getAsString())){ process.setHikvisionResult(result); } } stundentFaceProcessService.updateById(process); FaceManagement faceManagement = faceManagementMap.get(studentUser.getId()); faceManagement.setVerifyStatus(2); faceManagement.setRegisterBase64(base64String); faceManagement.setFileId(folderId); faceManagementService.update(faceManagement); } } return RT.ok(true); } @PostMapping(value = "/ns-upload-face") @ApiOperation(value = "新生账号激活上传人脸信息") @SaCheckPermission("stundentfaceprocess:add") public RT nsUploadFace(AddFaceManagementDto dto, @RequestParam("file") MultipartFile file) { Boolean isSuccess = stundentFaceProcessService.nsUploadFace(dto, file); return RT.ok(isSuccess); } }