Merge remote-tracking branch 'refs/remotes/origin/main' into dev_human_push

# Conflicts:
#	web-adapter/src/main/java/com/zcloud/basic/info/facade/ZcloudDepartmentFacadeImpl.java
#	web-adapter/src/main/java/com/zcloud/basic/info/facade/ZcloudUserFacadeImpl.java
#	web-app/src/main/java/com/zcloud/basic/info/service/DepartmentServiceImpl.java
#	web-client/src/main/java/com/zcloud/basic/info/api/DepartmentServiceI.java
dev_human_push
zhaokai 2026-06-15 16:52:54 +08:00
commit 54277f8d61
19 changed files with 507 additions and 29 deletions

1
.gitignore vendored
View File

@ -37,3 +37,4 @@ build/
/.idea/ /.idea/
.idea .idea
/start/src/main/resources/templates/

View File

@ -1,10 +1,10 @@
spring: spring:
config: config:
import: import:
- classpath:nacos.yml # - classpath:nacos.yml
- classpath:sdk.yml # - classpath:sdk.yml
# - classpath:nacos-prod.yml - classpath:nacos-prod.yml
# - classpath:sdk-prod.yml - classpath:sdk-prod.yml
# - classpath:nacos-prod2.yml # - classpath:nacos-prod2.yml
# - classpath:sdk-prod2.yml # - classpath:sdk-prod2.yml
- classpath:swagger.yml - classpath:swagger.yml

View File

@ -108,4 +108,9 @@ public class ZcloudDepartmentFacadeImpl implements ZcloudDepartmentFacade {
Long deptId = departmentService.addHumanUserDept(addCmd); Long deptId = departmentService.addHumanUserDept(addCmd);
return SingleResponse.of(deptId); return SingleResponse.of(deptId);
} }
@Override
public SingleResponse<Long> addHumanUserDept(ZcloudDepartmentAddCmd zcloudDepartmentAddCmd) {
return null;
}
} }

View File

@ -106,4 +106,9 @@ public class ZcloudUserFacadeImpl implements ZcloudUserFacade {
return userServiceI.addHumanUser(userAddCmd); return userServiceI.addHumanUser(userAddCmd);
} }
@Override
public SingleResponse addHumanUser(ZcloudUserAddCmd zcloudUserAddCmd) {
return null;
}
} }

View File

@ -85,6 +85,13 @@ public class DepartmentController {
public MultiResponse<DepartmentTreeInfoCO> listTree(@Validated @RequestBody DepartmentTreeQry qry) { public MultiResponse<DepartmentTreeInfoCO> listTree(@Validated @RequestBody DepartmentTreeQry qry) {
return MultiResponse.of(departmentService.listTree(qry)); return MultiResponse.of(departmentService.listTree(qry));
} }
@ApiOperation("企业下部门树状所有数据,免token")
@PostMapping("/listTreeNopermission")
public MultiResponse<DepartmentTreeInfoCO> listTreeNopermission(@Validated @RequestBody DepartmentTreeQry qry) {
return MultiResponse.of(departmentService.listTreeNopermission(qry));
}
@ApiOperation("所有企业下部门树状所有数据") @ApiOperation("所有企业下部门树状所有数据")
@PostMapping("/listAllTree") @PostMapping("/listAllTree")
public MultiResponse<DepartmentTreeInfoCO> listAllTree() { public MultiResponse<DepartmentTreeInfoCO> listAllTree() {

View File

@ -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);
List<ImgFilesDO> resultImgFilesDOList = imgFilesDOList;
if (cmd.getType() == 14 && cmd.getForeignKey() != null && !cmd.getForeignKey().trim().isEmpty()) {
resultImgFilesDOList = syncIdCardFiles(cmd.getForeignKey(), imgFilesDOList);
} else {
imgFilesRepository.saveBatch(imgFilesDOList); imgFilesRepository.saveBatch(imgFilesDOList);
List<ImgFilesCO> imgFilesCOList = imgFilesCoConvertor.converDOsToCOs(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;
}
} }

View File

@ -110,7 +110,8 @@ public class UserUpdateExe {
boolean res = userGateway.update(userE); boolean res = userGateway.update(userE);
if(!Objects.equals(userE.getPhone(), userDO.getPhone()) if(!Objects.equals(userE.getPhone(), userDO.getPhone())
|| !Objects.equals(userE.getEmail(), userDO.getEmail()) || !Objects.equals(userE.getEmail(), userDO.getEmail())
|| !Objects.equals(userE.getName(), userDO.getName())){ || !Objects.equals(userE.getName(), userDO.getName())
|| !Objects.equals(userE.getDepartmentId(), userDO.getDepartmentId())){
// 判断底座是否有该用户信息,如果没有则不调用底座 // 判断底座是否有该用户信息,如果没有则不调用底座
SingleResponse<UserDetailCO> detail = null; SingleResponse<UserDetailCO> detail = null;
try { try {
@ -147,7 +148,8 @@ public class UserUpdateExe {
if(!Objects.equals(userE.getPhone(), userDO.getPhone()) if(!Objects.equals(userE.getPhone(), userDO.getPhone())
|| !Objects.equals(userE.getEmail(), userDO.getEmail()) || !Objects.equals(userE.getEmail(), userDO.getEmail())
|| !Objects.equals(userE.getName(), userDO.getName()) || !Objects.equals(userE.getName(), userDO.getName())
|| !Objects.equals(userE.getRoleId(), userDO.getRoleId())){ || !Objects.equals(userE.getRoleId(), userDO.getRoleId())
|| !Objects.equals(userE.getDepartmentId(), userDO.getDepartmentId())){
// 判断底座是否有该用户信息,如果没有则不调用底座 // 判断底座是否有该用户信息,如果没有则不调用底座
SingleResponse<UserDetailCO> detail = null; SingleResponse<UserDetailCO> detail = null;
try { try {

View File

@ -202,5 +202,37 @@ public class DepartmentQueryExe {
} }
public Collection<DepartmentTreeInfoCO> listTreeNopermission(DepartmentTreeQry departmentQry) {
if (Objects.isNull(departmentQry.getEqCorpinfoId())) {
throw new RuntimeException("请选择企业");
}
Map<String, Object> parmas = PageQueryHelper.toHashMap(departmentQry);
List<DepartmentDO> pageResponse = departmentRepository.listTree(parmas);
if (CollUtil.isEmpty(pageResponse)) {
return Collections.emptyList();
}
List<DepartmentTreeInfoCO> examCenterCOS = departmentCoConvertor.converDOsToInfoCOs(pageResponse);
//补充企业信息
//补充企业名称
Map<Long, String> corpinfoMap = corpInfoRepository.getCorpinfoNameByCorpinfoId(examCenterCOS.stream().map(DepartmentTreeInfoCO::getCorpinfoId).collect(Collectors.toList()));
if (CollUtil.isNotEmpty(corpinfoMap)) {
List<Long> departmentIds = examCenterCOS.stream().peek(examCenterCO -> {
examCenterCO.setCorpinfoName(corpinfoMap.getOrDefault(examCenterCO.getCorpinfoId(), StringUtils.EMPTY));
}).map(DepartmentTreeInfoCO :: getId).collect(Collectors.toList());
Map<Long, String> deptMap = zcloudDepartmentFacade.listFullName(departmentIds);
examCenterCOS.forEach(examCenterCO -> {
examCenterCO.setFullName(deptMap.getOrDefault(examCenterCO.getId(), StringUtils.EMPTY));
});
}
//GBS部门根节点父部门是tenantId
if(departmentQry.getEqParentId()!=null){
return Tools.buildEntityTree(examCenterCOS, "id", "parentId", "childrenList",departmentQry.getEqParentId());
}else{
return Tools.buildEntityTree(examCenterCOS, "id", "parentId", "childrenList",0L);
}
}
} }

View File

@ -106,5 +106,10 @@ public class DepartmentServiceImpl implements DepartmentServiceI {
public Long addHumanUserDept(DepartmentAddCmd cmd) { public Long addHumanUserDept(DepartmentAddCmd cmd) {
return departmentAddExe.executeHumanUserDept(cmd); return departmentAddExe.executeHumanUserDept(cmd);
} }
@Override
public Collection<DepartmentTreeInfoCO> listTreeNopermission(DepartmentTreeQry qry) {
return departmentQueryExe.listTreeNopermission(qry);
}
} }

View File

@ -46,5 +46,7 @@ public interface DepartmentServiceI {
Collection<DepartmentTreeInfoCO> listAllTreeByCorpType(DepartmentTreeQry qry); Collection<DepartmentTreeInfoCO> listAllTreeByCorpType(DepartmentTreeQry qry);
Long addHumanUserDept(DepartmentAddCmd cmd); Long addHumanUserDept(DepartmentAddCmd cmd);
Collection<DepartmentTreeInfoCO> listTreeNopermission(DepartmentTreeQry qry);
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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);

View File

@ -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) {

View File

@ -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;
} }

View File

@ -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);
} }

View File

@ -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;
/** /**
@ -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);
}
} }

View File

@ -35,7 +35,7 @@
left join department d on d.id = u.department_id left join department d on d.id = u.department_id
left join post p on p.id = u.post_id left join post p on p.id = u.post_id
<where> <where>
and u.id != u.corpinfo_id (and u.id != u.corpinfo_id
and u.delete_enum = 'FALSE' and u.delete_enum = 'FALSE'
and u.employment_flag in (1, 2) and u.employment_flag in (1, 2)
and u.corpinfo_id = #{params.corpinfoId} and u.corpinfo_id = #{params.corpinfoId}
@ -56,8 +56,8 @@
</if> </if>
<if test="params.userIdCard != null and params.userIdCard != ''"> <if test="params.userIdCard != null and params.userIdCard != ''">
and u.user_id_card = TO_BASE64(#{params.userIdCard}) and u.user_id_card = TO_BASE64(#{params.userIdCard})
</if> </if>)
or u.id = 2034204588722098176
</where> </where>
order by u.sort , order by u.sort ,
u.create_time desc u.create_time desc