feat(info): 添加经营范围字段并优化图片压缩和身份证附件同步功能
parent
31d925e7e7
commit
48a1fc8f15
|
|
@ -1,8 +1,10 @@
|
||||||
package com.zcloud.basic.info.command;
|
package com.zcloud.basic.info.command;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
import com.alibaba.cola.dto.SingleResponse;
|
import com.alibaba.cola.dto.SingleResponse;
|
||||||
import com.alibaba.cola.exception.BizException;
|
import com.alibaba.cola.exception.BizException;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.jjb.saas.framework.auth.model.SSOUser;
|
import com.jjb.saas.framework.auth.model.SSOUser;
|
||||||
import com.jjb.saas.framework.auth.utils.AuthContext;
|
import com.jjb.saas.framework.auth.utils.AuthContext;
|
||||||
import com.zcloud.basic.info.command.convertor.ImgFilesCoConvertor;
|
import com.zcloud.basic.info.command.convertor.ImgFilesCoConvertor;
|
||||||
|
|
@ -14,8 +16,12 @@ import com.zcloud.basic.info.dto.ImgFilesAddCmd;
|
||||||
import com.zcloud.basic.info.dto.clientobject.ImgFilesCO;
|
import com.zcloud.basic.info.dto.clientobject.ImgFilesCO;
|
||||||
import com.zcloud.basic.info.dto.clientobject.ImgFilesInfoCO;
|
import com.zcloud.basic.info.dto.clientobject.ImgFilesInfoCO;
|
||||||
import com.zcloud.basic.info.persistence.dataobject.ImgFilesDO;
|
import com.zcloud.basic.info.persistence.dataobject.ImgFilesDO;
|
||||||
|
import com.zcloud.basic.info.persistence.dataobject.UserDO;
|
||||||
import com.zcloud.basic.info.persistence.repository.ImgFilesRepository;
|
import com.zcloud.basic.info.persistence.repository.ImgFilesRepository;
|
||||||
|
import com.zcloud.basic.info.persistence.repository.UserRepository;
|
||||||
import com.zcloud.gbscommon.utils.FileUtil;
|
import com.zcloud.gbscommon.utils.FileUtil;
|
||||||
|
import com.zcloud.gbscommon.utils.PageQueryHelper;
|
||||||
|
import com.zcloud.gbscommon.utils.Tools;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
@ -27,6 +33,8 @@ import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -43,6 +51,9 @@ public class ImgFilesAddExe {
|
||||||
private final ImgFilesCoConvertor imgFilesCoConvertor;
|
private final ImgFilesCoConvertor imgFilesCoConvertor;
|
||||||
private final ImgFilesRepository imgFilesRepository;
|
private final ImgFilesRepository imgFilesRepository;
|
||||||
private final DaHuaConfig daHuaConfig;
|
private final DaHuaConfig daHuaConfig;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final ImgFilesRemoveExe imgFilesRemoveExe;
|
||||||
|
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public SingleResponse<ImgFilesCO> execute(ImgFilesAddCmd cmd) {
|
public SingleResponse<ImgFilesCO> execute(ImgFilesAddCmd cmd) {
|
||||||
if (daHuaConfig.getDockFlag() == 1 && (cmd.getType() == 608 || cmd.getType() == 13)){
|
if (daHuaConfig.getDockFlag() == 1 && (cmd.getType() == 608 || cmd.getType() == 13)){
|
||||||
|
|
@ -125,8 +136,13 @@ public class ImgFilesAddExe {
|
||||||
imgFilesEList = imgFilesE.initBatchAdd(tenantId, imgFilesE);
|
imgFilesEList = imgFilesE.initBatchAdd(tenantId, imgFilesE);
|
||||||
}
|
}
|
||||||
List<ImgFilesDO> imgFilesDOList = imgFilesCoConvertor.converEsToDOs(imgFilesEList);
|
List<ImgFilesDO> imgFilesDOList = imgFilesCoConvertor.converEsToDOs(imgFilesEList);
|
||||||
imgFilesRepository.saveBatch(imgFilesDOList);
|
List<ImgFilesDO> resultImgFilesDOList = imgFilesDOList;
|
||||||
List<ImgFilesCO> imgFilesCOList = imgFilesCoConvertor.converDOsToCOs(imgFilesDOList);
|
if (cmd.getType() == 14 && cmd.getForeignKey() != null && !cmd.getForeignKey().trim().isEmpty()) {
|
||||||
|
resultImgFilesDOList = syncIdCardFiles(cmd.getForeignKey(), imgFilesDOList);
|
||||||
|
} else {
|
||||||
|
imgFilesRepository.saveBatch(imgFilesDOList);
|
||||||
|
}
|
||||||
|
List<ImgFilesCO> imgFilesCOList = imgFilesCoConvertor.converDOsToCOs(resultImgFilesDOList);
|
||||||
imgFilesCO.setFileList(imgFilesCOList);
|
imgFilesCO.setFileList(imgFilesCOList);
|
||||||
imgFilesCO.setForeignKey(imgFilesE.getForeignKey());
|
imgFilesCO.setForeignKey(imgFilesE.getForeignKey());
|
||||||
res = true;
|
res = true;
|
||||||
|
|
@ -140,5 +156,172 @@ public class ImgFilesAddExe {
|
||||||
return SingleResponse.of(imgFilesCO);
|
return SingleResponse.of(imgFilesCO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步身份证附件:
|
||||||
|
* 1. 先保存当前用户本次上传的图片;
|
||||||
|
* 2. 再回查当前用户最新有效的身份证图片集;
|
||||||
|
* 3. 用当前用户的最新完整集覆盖同手机号的其他用户。
|
||||||
|
*/
|
||||||
|
private List<ImgFilesDO> syncIdCardFiles(String currentUserId, List<ImgFilesDO> currentImgFilesDOList) throws Exception {
|
||||||
|
// 先落库,再在同一事务内回查当前用户的完整身份证图片集。
|
||||||
|
imgFilesRepository.saveBatch(currentImgFilesDOList);
|
||||||
|
|
||||||
|
List<ImgFilesDO> currentAllIdCardFiles = listIdCardFilesByForeignKey(currentUserId);
|
||||||
|
List<ImgFilesDO> currentLatestIdCardFiles = getLatestIdCardFiles(currentAllIdCardFiles);
|
||||||
|
// 当前用户仍在使用的物理文件路径,后续清理旧记录时不能误删。
|
||||||
|
Set<String> protectedFilePathSet = currentLatestIdCardFiles.stream()
|
||||||
|
.map(ImgFilesDO::getFilePath)
|
||||||
|
.filter(filePath -> filePath != null && !filePath.trim().isEmpty())
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
// 当前用户如果因为多次编辑产生了更老的身份证记录,这里只清理多余记录。
|
||||||
|
List<ImgFilesDO> currentRedundantIdCardFiles = getRedundantIdCardFiles(currentAllIdCardFiles, currentLatestIdCardFiles);
|
||||||
|
removeIdCardFiles(currentRedundantIdCardFiles, protectedFilePathSet);
|
||||||
|
|
||||||
|
List<UserDO> userDOList = userRepository.getUserListByUserId(currentUserId);
|
||||||
|
if (CollUtil.isEmpty(userDOList)) {
|
||||||
|
return currentLatestIdCardFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> otherUserIdList = userDOList.stream()
|
||||||
|
.map(UserDO::getUserId)
|
||||||
|
.filter(userId -> userId != null && !userId.trim().isEmpty())
|
||||||
|
.filter(userId -> !currentUserId.equals(userId))
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (CollUtil.isEmpty(otherUserIdList)) {
|
||||||
|
return currentLatestIdCardFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先清理其他用户旧的身份证记录,再按当前用户的最新完整集重建。
|
||||||
|
removeOldIdCardFiles(otherUserIdList, protectedFilePathSet);
|
||||||
|
List<ImgFilesDO> syncImgFilesDOList = new ArrayList<>();
|
||||||
|
for (String userId : otherUserIdList) {
|
||||||
|
syncImgFilesDOList.addAll(copyImgFiles(currentLatestIdCardFiles, userId));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CollUtil.isNotEmpty(syncImgFilesDOList)) {
|
||||||
|
imgFilesRepository.saveBatch(syncImgFilesDOList);
|
||||||
|
}
|
||||||
|
return currentLatestIdCardFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询某个用户名下当前有效的身份证附件。
|
||||||
|
*/
|
||||||
|
private List<ImgFilesDO> listIdCardFilesByForeignKey(String foreignKey) {
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("eqForeignKey", foreignKey);
|
||||||
|
params.put("eqType", 14);
|
||||||
|
params.put("eqDeleteEnum", "FALSE");
|
||||||
|
return imgFilesRepository.listAll(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 现阶段前端不区分正反面,这里按最新两张作为当前有效身份证图片集。
|
||||||
|
*/
|
||||||
|
private List<ImgFilesDO> getLatestIdCardFiles(List<ImgFilesDO> idCardFiles) {
|
||||||
|
if (CollUtil.isEmpty(idCardFiles)) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
int keepCount = Math.min(idCardFiles.size(), 2);
|
||||||
|
return new ArrayList<>(idCardFiles.subList(0, keepCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 找出当前用户历史上多余的旧身份证记录,保留最新有效集,其余作为冗余记录处理。
|
||||||
|
*/
|
||||||
|
private List<ImgFilesDO> getRedundantIdCardFiles(List<ImgFilesDO> allIdCardFiles, List<ImgFilesDO> latestIdCardFiles) {
|
||||||
|
if (CollUtil.isEmpty(allIdCardFiles) || allIdCardFiles.size() <= latestIdCardFiles.size()) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
Set<Long> latestIdSet = latestIdCardFiles.stream()
|
||||||
|
.map(ImgFilesDO::getId)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
return allIdCardFiles.stream()
|
||||||
|
.filter(imgFilesDO -> !latestIdSet.contains(imgFilesDO.getId()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理其他同手机号用户旧的身份证记录。
|
||||||
|
* 这里只清理旧数据,当前用户仍在使用的物理文件路径会被保护,不会删除。
|
||||||
|
*/
|
||||||
|
private void removeOldIdCardFiles(List<String> userIdList, Set<String> protectedFilePathSet) throws Exception {
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("inForeignKey", userIdList.toArray(new String[0]));
|
||||||
|
params.put("eqType", 14);
|
||||||
|
params.put("eqDeleteEnum", "FALSE");
|
||||||
|
|
||||||
|
List<ImgFilesDO> oldImgFilesDOList = imgFilesRepository.listAll(params);
|
||||||
|
removeIdCardFiles(oldImgFilesDOList, protectedFilePathSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除身份证记录时分两步处理:
|
||||||
|
* 1. 数据记录一定删除;
|
||||||
|
* 2. 物理文件只有在没有其他有效记录引用时才删除。
|
||||||
|
*/
|
||||||
|
private void removeIdCardFiles(List<ImgFilesDO> imgFilesDOList, Set<String> protectedFilePathSet) throws Exception {
|
||||||
|
if (CollUtil.isEmpty(imgFilesDOList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Long> deleteIdList = imgFilesDOList.stream()
|
||||||
|
.map(ImgFilesDO::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
ImgFilesE imgFilesE = new ImgFilesE();
|
||||||
|
List<String> filePathList = imgFilesDOList.stream()
|
||||||
|
.map(ImgFilesDO::getFilePath)
|
||||||
|
.filter(filePath -> filePath != null && !filePath.trim().isEmpty())
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (String filePath : filePathList) {
|
||||||
|
// 当前有效集仍在使用的文件,直接跳过,避免单张编辑时把另一张误删。
|
||||||
|
if (protectedFilePathSet.contains(filePath)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 只有确认没有其他有效记录再引用该路径时,才删除物理文件。
|
||||||
|
if (canDeletePhysicalFile(filePath, deleteIdList)) {
|
||||||
|
imgFilesE.deleteFile(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Long[] ids = deleteIdList.toArray(new Long[0]);
|
||||||
|
imgFilesRepository.deleteList(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断物理文件是否还被其他有效记录引用。
|
||||||
|
* 如果还有其他记录在用,当前只删数据库记录,不删物理文件。
|
||||||
|
*/
|
||||||
|
private boolean canDeletePhysicalFile(String filePath, List<Long> deleteIdList) {
|
||||||
|
QueryWrapper<ImgFilesDO> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("file_path", filePath);
|
||||||
|
queryWrapper.eq("delete_enum", "FALSE");
|
||||||
|
if (CollUtil.isNotEmpty(deleteIdList)) {
|
||||||
|
queryWrapper.notIn("id", deleteIdList);
|
||||||
|
}
|
||||||
|
List<ImgFilesDO> otherReferencedImgFiles = imgFilesRepository.list(queryWrapper);
|
||||||
|
return CollUtil.isEmpty(otherReferencedImgFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制当前用户的最新身份证图片集到其他用户名下,生成新的主键和业务主键。
|
||||||
|
*/
|
||||||
|
private List<ImgFilesDO> copyImgFiles(List<ImgFilesDO> sourceList, String foreignKey) {
|
||||||
|
List<ImgFilesDO> targetList = new ArrayList<>();
|
||||||
|
for (ImgFilesDO source : sourceList) {
|
||||||
|
ImgFilesDO target = new ImgFilesDO();
|
||||||
|
BeanUtils.copyProperties(source, target);
|
||||||
|
target.setId(null);
|
||||||
|
target.setImgFilesId(Tools.get32UUID());
|
||||||
|
target.setForeignKey(foreignKey);
|
||||||
|
targetList.add(target);
|
||||||
|
}
|
||||||
|
return targetList;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ public class CorpInfoAddCmd extends Command {
|
||||||
private Integer whetherLiquidammoniaFlag;
|
private Integer whetherLiquidammoniaFlag;
|
||||||
@ApiModelProperty(value = "选取形式", name = "selectfromList")
|
@ApiModelProperty(value = "选取形式", name = "selectfromList")
|
||||||
private List<CorpInfoXgfItemCmd> selectfromList;
|
private List<CorpInfoXgfItemCmd> selectfromList;
|
||||||
|
@ApiModelProperty(value = "经营范围", name = "natureBusiness")
|
||||||
|
private String natureBusiness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -179,5 +179,7 @@ public class CorpInfoUpdateCmd extends Command {
|
||||||
private Integer whetherLiquidammoniaFlag;
|
private Integer whetherLiquidammoniaFlag;
|
||||||
@ApiModelProperty(value = "选取形式", name = "selectfromList")
|
@ApiModelProperty(value = "选取形式", name = "selectfromList")
|
||||||
private List<CorpInfoXgfItemCmd> selectfromList;
|
private List<CorpInfoXgfItemCmd> selectfromList;
|
||||||
|
@ApiModelProperty(value = "经营范围", name = "natureBusiness")
|
||||||
|
private String natureBusiness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -271,5 +271,7 @@ public class CorpInfoCO extends ClientObject {
|
||||||
@ApiModelProperty(value = "选取形式", name = "selectfromList", required = true)
|
@ApiModelProperty(value = "选取形式", name = "selectfromList", required = true)
|
||||||
private List<CorpInfoXgfItemCO> selectfromList;
|
private List<CorpInfoXgfItemCO> selectfromList;
|
||||||
private String selectfromString;
|
private String selectfromString;
|
||||||
|
@ApiModelProperty(value = "经营范围", name = "natureBusiness")
|
||||||
|
private String natureBusiness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,8 @@ public class CorpInfoE extends BaseE {
|
||||||
// private final String defaultPassword = "Aa@12345678";
|
// private final String defaultPassword = "Aa@12345678";
|
||||||
// 密码
|
// 密码
|
||||||
private String password;
|
private String password;
|
||||||
|
@ApiModelProperty(value = "经营范围", name = "natureBusiness")
|
||||||
|
private String natureBusiness;
|
||||||
|
|
||||||
public void initPassWord(Integer type) {
|
public void initPassWord(Integer type) {
|
||||||
String encrypt = Sm2Util.encryptHex(MD5.md5(CorpTypeEnum.getPasswordByCode(type)), publicKey);
|
String encrypt = Sm2Util.encryptHex(MD5.md5(CorpTypeEnum.getPasswordByCode(type)), publicKey);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import javax.imageio.ImageWriter;
|
||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import javax.imageio.stream.ImageOutputStream;
|
import javax.imageio.stream.ImageOutputStream;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
@ -29,6 +30,23 @@ public class ImageCompressUtil {
|
||||||
private static final float MAX_QUALITY = 1.0F;
|
private static final float MAX_QUALITY = 1.0F;
|
||||||
private static final int QUALITY_SEARCH_TIMES = 8;
|
private static final int QUALITY_SEARCH_TIMES = 8;
|
||||||
private static final double RESIZE_SCALE = 0.9D;
|
private static final double RESIZE_SCALE = 0.9D;
|
||||||
|
private static final int EXIF_ORIENTATION_NORMAL = 1;
|
||||||
|
private static final int EXIF_ORIENTATION_FLIP_HORIZONTAL = 2;
|
||||||
|
private static final int EXIF_ORIENTATION_ROTATE_180 = 3;
|
||||||
|
private static final int EXIF_ORIENTATION_FLIP_VERTICAL = 4;
|
||||||
|
private static final int EXIF_ORIENTATION_TRANSPOSE = 5;
|
||||||
|
private static final int EXIF_ORIENTATION_ROTATE_90 = 6;
|
||||||
|
private static final int EXIF_ORIENTATION_TRANSVERSE = 7;
|
||||||
|
private static final int EXIF_ORIENTATION_ROTATE_270 = 8;
|
||||||
|
private static final int JPEG_SOI_MARKER = 0xD8;
|
||||||
|
private static final int JPEG_EOI_MARKER = 0xD9;
|
||||||
|
private static final int JPEG_SOS_MARKER = 0xDA;
|
||||||
|
private static final int JPEG_APP1_MARKER = 0xE1;
|
||||||
|
private static final int TIFF_HEADER_LENGTH = 8;
|
||||||
|
private static final int IFD_ENTRY_LENGTH = 12;
|
||||||
|
private static final int EXIF_ORIENTATION_TAG = 0x0112;
|
||||||
|
private static final int TIFF_TYPE_SHORT = 3;
|
||||||
|
private static final byte[] EXIF_HEADER = new byte[]{'E', 'x', 'i', 'f', 0, 0};
|
||||||
|
|
||||||
private ImageCompressUtil() {
|
private ImageCompressUtil() {
|
||||||
}
|
}
|
||||||
|
|
@ -49,7 +67,8 @@ public class ImageCompressUtil {
|
||||||
long maxSizeBytes = maxSizeKb * 1024L;
|
long maxSizeBytes = maxSizeKb * 1024L;
|
||||||
byte[] sourceBytes = file.getBytes();
|
byte[] sourceBytes = file.getBytes();
|
||||||
String formatName = getFormatName(sourceBytes);
|
String formatName = getFormatName(sourceBytes);
|
||||||
if (isTargetJpg(file, formatName, maxSizeBytes)) {
|
int orientation = getOrientation(sourceBytes);
|
||||||
|
if (isTargetJpg(file, formatName, maxSizeBytes) && orientation == EXIF_ORIENTATION_NORMAL) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,7 +77,9 @@ public class ImageCompressUtil {
|
||||||
throw new IllegalArgumentException("file is not a supported image");
|
throw new IllegalArgumentException("file is not a supported image");
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedImage rgbImage = toRgbImage(bufferedImage);
|
// 手机拍照图片经常依赖 EXIF 方向信息展示,压缩前先转正,避免保存后变成横图。
|
||||||
|
BufferedImage orientedImage = applyOrientation(bufferedImage, orientation);
|
||||||
|
BufferedImage rgbImage = toRgbImage(orientedImage);
|
||||||
byte[] compressedBytes = compress(rgbImage, maxSizeBytes);
|
byte[] compressedBytes = compress(rgbImage, maxSizeBytes);
|
||||||
String targetFileName = toJpgFileName(file.getOriginalFilename(), file.getName());
|
String targetFileName = toJpgFileName(file.getOriginalFilename(), file.getName());
|
||||||
return new ByteArrayMultipartFile(file.getName(), targetFileName, JPG_CONTENT_TYPE, compressedBytes);
|
return new ByteArrayMultipartFile(file.getName(), targetFileName, JPG_CONTENT_TYPE, compressedBytes);
|
||||||
|
|
@ -109,6 +130,148 @@ public class ImageCompressUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int getOrientation(byte[] sourceBytes) {
|
||||||
|
try {
|
||||||
|
if (!isJpeg(sourceBytes)) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
return readJpegOrientation(sourceBytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isJpeg(byte[] sourceBytes) {
|
||||||
|
return sourceBytes != null
|
||||||
|
&& sourceBytes.length > 3
|
||||||
|
&& (sourceBytes[0] & 0xFF) == 0xFF
|
||||||
|
&& (sourceBytes[1] & 0xFF) == JPEG_SOI_MARKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readJpegOrientation(byte[] sourceBytes) {
|
||||||
|
int offset = 2;
|
||||||
|
while (offset + 4 <= sourceBytes.length) {
|
||||||
|
if ((sourceBytes[offset] & 0xFF) != 0xFF) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int marker = sourceBytes[offset + 1] & 0xFF;
|
||||||
|
offset += 2;
|
||||||
|
if (marker == JPEG_SOI_MARKER) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (marker == JPEG_EOI_MARKER || marker == JPEG_SOS_MARKER) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (offset + 2 > sourceBytes.length) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int segmentLength = readUnsignedShort(sourceBytes, offset, false);
|
||||||
|
if (segmentLength < 2 || offset + segmentLength > sourceBytes.length) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int segmentDataOffset = offset + 2;
|
||||||
|
int segmentDataLength = segmentLength - 2;
|
||||||
|
if (marker == JPEG_APP1_MARKER && hasExifHeader(sourceBytes, segmentDataOffset, segmentDataLength)) {
|
||||||
|
return readExifOrientation(sourceBytes, segmentDataOffset, segmentDataLength);
|
||||||
|
}
|
||||||
|
offset += segmentLength;
|
||||||
|
}
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasExifHeader(byte[] sourceBytes, int offset, int length) {
|
||||||
|
if (length < EXIF_HEADER.length || offset + EXIF_HEADER.length > sourceBytes.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < EXIF_HEADER.length; i++) {
|
||||||
|
if (sourceBytes[offset + i] != EXIF_HEADER[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readExifOrientation(byte[] sourceBytes, int exifOffset, int exifLength) {
|
||||||
|
int tiffOffset = exifOffset + EXIF_HEADER.length;
|
||||||
|
int tiffLimit = exifOffset + exifLength;
|
||||||
|
if (tiffOffset + TIFF_HEADER_LENGTH > tiffLimit) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean littleEndian = resolveByteOrder(sourceBytes, tiffOffset);
|
||||||
|
if (littleEndian == null) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstIfdOffset = readUnsignedInt(sourceBytes, tiffOffset + 4, littleEndian);
|
||||||
|
int ifdOffset = tiffOffset + firstIfdOffset;
|
||||||
|
if (ifdOffset + 2 > tiffLimit) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int entryCount = readUnsignedShort(sourceBytes, ifdOffset, littleEndian);
|
||||||
|
int entryOffset = ifdOffset + 2;
|
||||||
|
for (int i = 0; i < entryCount; i++) {
|
||||||
|
int currentEntryOffset = entryOffset + i * IFD_ENTRY_LENGTH;
|
||||||
|
if (currentEntryOffset + IFD_ENTRY_LENGTH > tiffLimit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tag = readUnsignedShort(sourceBytes, currentEntryOffset, littleEndian);
|
||||||
|
if (tag != EXIF_ORIENTATION_TAG) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int type = readUnsignedShort(sourceBytes, currentEntryOffset + 2, littleEndian);
|
||||||
|
int count = readUnsignedInt(sourceBytes, currentEntryOffset + 4, littleEndian);
|
||||||
|
if (type != TIFF_TYPE_SHORT || count < 1) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int orientation = readUnsignedShort(sourceBytes, currentEntryOffset + 8, littleEndian);
|
||||||
|
if (orientation < EXIF_ORIENTATION_NORMAL || orientation > EXIF_ORIENTATION_ROTATE_270) {
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
return EXIF_ORIENTATION_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Boolean resolveByteOrder(byte[] sourceBytes, int tiffOffset) {
|
||||||
|
int first = sourceBytes[tiffOffset] & 0xFF;
|
||||||
|
int second = sourceBytes[tiffOffset + 1] & 0xFF;
|
||||||
|
if (first == 'I' && second == 'I') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (first == 'M' && second == 'M') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readUnsignedShort(byte[] sourceBytes, int offset, boolean littleEndian) {
|
||||||
|
if (littleEndian) {
|
||||||
|
return (sourceBytes[offset] & 0xFF) | ((sourceBytes[offset + 1] & 0xFF) << 8);
|
||||||
|
}
|
||||||
|
return ((sourceBytes[offset] & 0xFF) << 8) | (sourceBytes[offset + 1] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readUnsignedInt(byte[] sourceBytes, int offset, boolean littleEndian) {
|
||||||
|
if (littleEndian) {
|
||||||
|
return (sourceBytes[offset] & 0xFF)
|
||||||
|
| ((sourceBytes[offset + 1] & 0xFF) << 8)
|
||||||
|
| ((sourceBytes[offset + 2] & 0xFF) << 16)
|
||||||
|
| ((sourceBytes[offset + 3] & 0xFF) << 24);
|
||||||
|
}
|
||||||
|
return ((sourceBytes[offset] & 0xFF) << 24)
|
||||||
|
| ((sourceBytes[offset + 1] & 0xFF) << 16)
|
||||||
|
| ((sourceBytes[offset + 2] & 0xFF) << 8)
|
||||||
|
| (sourceBytes[offset + 3] & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
private static BufferedImage toRgbImage(BufferedImage sourceImage) {
|
private static BufferedImage toRgbImage(BufferedImage sourceImage) {
|
||||||
if (sourceImage.getType() == BufferedImage.TYPE_INT_RGB) {
|
if (sourceImage.getType() == BufferedImage.TYPE_INT_RGB) {
|
||||||
return sourceImage;
|
return sourceImage;
|
||||||
|
|
@ -125,6 +288,55 @@ public class ImageCompressUtil {
|
||||||
return rgbImage;
|
return rgbImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static BufferedImage applyOrientation(BufferedImage sourceImage, int orientation) {
|
||||||
|
if (orientation <= EXIF_ORIENTATION_NORMAL || orientation > EXIF_ORIENTATION_ROTATE_270) {
|
||||||
|
return sourceImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sourceWidth = sourceImage.getWidth();
|
||||||
|
int sourceHeight = sourceImage.getHeight();
|
||||||
|
boolean swapSize = orientation == EXIF_ORIENTATION_TRANSPOSE
|
||||||
|
|| orientation == EXIF_ORIENTATION_ROTATE_90
|
||||||
|
|| orientation == EXIF_ORIENTATION_TRANSVERSE
|
||||||
|
|| orientation == EXIF_ORIENTATION_ROTATE_270;
|
||||||
|
int targetWidth = swapSize ? sourceHeight : sourceWidth;
|
||||||
|
int targetHeight = swapSize ? sourceWidth : sourceHeight;
|
||||||
|
BufferedImage targetImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
|
||||||
|
Graphics2D graphics = targetImage.createGraphics();
|
||||||
|
try {
|
||||||
|
graphics.setColor(Color.WHITE);
|
||||||
|
graphics.fillRect(0, 0, targetWidth, targetHeight);
|
||||||
|
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||||
|
graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||||
|
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
graphics.drawImage(sourceImage, buildOrientationTransform(orientation, sourceWidth, sourceHeight), null);
|
||||||
|
} finally {
|
||||||
|
graphics.dispose();
|
||||||
|
}
|
||||||
|
return targetImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AffineTransform buildOrientationTransform(int orientation, int sourceWidth, int sourceHeight) {
|
||||||
|
switch (orientation) {
|
||||||
|
case EXIF_ORIENTATION_FLIP_HORIZONTAL:
|
||||||
|
return new AffineTransform(-1, 0, 0, 1, sourceWidth, 0);
|
||||||
|
case EXIF_ORIENTATION_ROTATE_180:
|
||||||
|
return new AffineTransform(-1, 0, 0, -1, sourceWidth, sourceHeight);
|
||||||
|
case EXIF_ORIENTATION_FLIP_VERTICAL:
|
||||||
|
return new AffineTransform(1, 0, 0, -1, 0, sourceHeight);
|
||||||
|
case EXIF_ORIENTATION_TRANSPOSE:
|
||||||
|
return new AffineTransform(0, 1, 1, 0, 0, 0);
|
||||||
|
case EXIF_ORIENTATION_ROTATE_90:
|
||||||
|
return new AffineTransform(0, 1, -1, 0, sourceHeight, 0);
|
||||||
|
case EXIF_ORIENTATION_TRANSVERSE:
|
||||||
|
return new AffineTransform(0, -1, -1, 0, sourceHeight, sourceWidth);
|
||||||
|
case EXIF_ORIENTATION_ROTATE_270:
|
||||||
|
return new AffineTransform(0, -1, 1, 0, 0, sourceWidth);
|
||||||
|
default:
|
||||||
|
return new AffineTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static byte[] compress(BufferedImage image, long maxSizeBytes) throws IOException {
|
private static byte[] compress(BufferedImage image, long maxSizeBytes) throws IOException {
|
||||||
BufferedImage currentImage = image;
|
BufferedImage currentImage = image;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
|
||||||
|
|
@ -257,7 +257,8 @@ public class CorpInfoDO extends BaseDO {
|
||||||
// @ApiModelProperty(value = "选取形式")
|
// @ApiModelProperty(value = "选取形式")
|
||||||
// @TableField(exist = false)
|
// @TableField(exist = false)
|
||||||
// private String selectfromString;
|
// private String selectfromString;
|
||||||
|
@ApiModelProperty(value = "经营范围", name = "natureBusiness")
|
||||||
|
private String natureBusiness;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,5 +110,7 @@ public interface UserRepository extends BaseRepository<UserDO> {
|
||||||
|
|
||||||
|
|
||||||
List<UserImgDO> listBase64ByUrl(Map<String,Object> params);
|
List<UserImgDO> listBase64ByUrl(Map<String,Object> params);
|
||||||
|
|
||||||
|
List<UserDO> getUserListByUserId(String foreignKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,10 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -179,7 +176,7 @@ public class UserRepositoryImpl extends BaseRepositoryImpl<UserMapper, UserDO> i
|
||||||
// List<Long> ids = new ArrayList<>();
|
// List<Long> ids = new ArrayList<>();
|
||||||
// ids.add(1999009782763397120L);
|
// ids.add(1999009782763397120L);
|
||||||
// Map<Long, String> sd1 = zcloudDepartmentFacade.listFullName(ids);
|
// Map<Long, String> sd1 = zcloudDepartmentFacade.listFullName(ids);
|
||||||
if (!ObjectUtils.isEmpty(params.get("eqEmploymentFlag"))){
|
if (!ObjectUtils.isEmpty(params.get("eqEmploymentFlag"))) {
|
||||||
params.put("employmentFlag", params.get("eqEmploymentFlag"));
|
params.put("employmentFlag", params.get("eqEmploymentFlag"));
|
||||||
}
|
}
|
||||||
if (!ObjectUtils.isEmpty(params.get("isMyCorp"))) {
|
if (!ObjectUtils.isEmpty(params.get("isMyCorp"))) {
|
||||||
|
|
@ -484,7 +481,7 @@ public class UserRepositoryImpl extends BaseRepositoryImpl<UserMapper, UserDO> i
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("updateXgf,GBS获取用户信息失败: {}", e.getMessage());
|
log.error("updateXgf,GBS获取用户信息失败: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
if(detail.getData() != null){
|
if (detail.getData() != null) {
|
||||||
//更新gbs密码
|
//更新gbs密码
|
||||||
UserUpdatePasswordCmd userUpdatePasswordCmd = new UserUpdatePasswordCmd();
|
UserUpdatePasswordCmd userUpdatePasswordCmd = new UserUpdatePasswordCmd();
|
||||||
userUpdatePasswordCmd.setId(id);
|
userUpdatePasswordCmd.setId(id);
|
||||||
|
|
@ -556,7 +553,7 @@ public class UserRepositoryImpl extends BaseRepositoryImpl<UserMapper, UserDO> i
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("updateXgf,GBS获取用户信息失败: {}", e.getMessage());
|
log.error("updateXgf,GBS获取用户信息失败: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
if(detail.getData() != null){
|
if (detail.getData() != null) {
|
||||||
AccountPasswordCheckCmd accountPasswordCheckCmd = new AccountPasswordCheckCmd();
|
AccountPasswordCheckCmd accountPasswordCheckCmd = new AccountPasswordCheckCmd();
|
||||||
accountPasswordCheckCmd.setUserId(userDO.getId());
|
accountPasswordCheckCmd.setUserId(userDO.getId());
|
||||||
accountPasswordCheckCmd.setPassword(userDO.getPassword());
|
accountPasswordCheckCmd.setPassword(userDO.getPassword());
|
||||||
|
|
@ -566,16 +563,16 @@ public class UserRepositoryImpl extends BaseRepositoryImpl<UserMapper, UserDO> i
|
||||||
if (!response.isSuccess()) {
|
if (!response.isSuccess()) {
|
||||||
throw new BizException("原密码不正确");
|
throw new BizException("原密码不正确");
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
//验证本地密码
|
//验证本地密码
|
||||||
UserE userE = new UserE();
|
UserE userE = new UserE();
|
||||||
Boolean checkUserPassword = userE.checkUserEncryptionPassword(userDO.getPassword(), oldUserDO.getPassword());
|
Boolean checkUserPassword = userE.checkUserEncryptionPassword(userDO.getPassword(), oldUserDO.getPassword());
|
||||||
log.info("updateXgf,验证用户本地密码结果:{}",checkUserPassword);
|
log.info("updateXgf,验证用户本地密码结果:{}", checkUserPassword);
|
||||||
if(!checkUserPassword){
|
if (!checkUserPassword) {
|
||||||
throw new BizException("密码错误");
|
throw new BizException("密码错误");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
log.info("updateXgf,密码为空,不进行密码验证");
|
log.info("updateXgf,密码为空,不进行密码验证");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -731,13 +728,13 @@ public class UserRepositoryImpl extends BaseRepositoryImpl<UserMapper, UserDO> i
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UserDO getUserIdByPhone(String phone) {
|
public UserDO getUserIdByPhone(String phone) {
|
||||||
return userMapper.getUserIdByPhone(phone);
|
return userMapper.getUserIdByPhone(phone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateFaceByPhone(String userAvatarUrl, String phone) {
|
public void updateFaceByPhone(String userAvatarUrl, String phone) {
|
||||||
|
|
||||||
userMapper.updateFaceByPhone(userAvatarUrl, phone);
|
userMapper.updateFaceByPhone(userAvatarUrl, phone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -752,5 +749,23 @@ public class UserRepositoryImpl extends BaseRepositoryImpl<UserMapper, UserDO> i
|
||||||
public List<UserImgDO> listBase64ByUrl(Map<String, Object> params) {
|
public List<UserImgDO> listBase64ByUrl(Map<String, Object> params) {
|
||||||
return userMapper.listBase64ByUrl(params);
|
return userMapper.listBase64ByUrl(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UserDO> getUserListByUserId(String foreignKey) {
|
||||||
|
QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("user_id", foreignKey);
|
||||||
|
queryWrapper.eq("delete_enum", "FALSE");
|
||||||
|
UserDO one = getOne(queryWrapper);
|
||||||
|
|
||||||
|
if (one == null || StringUtils.isEmpty(one.getPhone())) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryWrapper<UserDO> queryWrapperList = new QueryWrapper<>();
|
||||||
|
queryWrapperList.eq("phone", one.getPhone());
|
||||||
|
queryWrapperList.eq("delete_enum", "FALSE");
|
||||||
|
queryWrapperList.orderByAsc("create_time");
|
||||||
|
return list(queryWrapperList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue