From 54b7e9a5552a4d8be800261e4d28aa4d58069aac Mon Sep 17 00:00:00 2001 From: "ran.shang" <> Date: Wed, 9 Sep 2026 10:05:23 +0800 Subject: [PATCH] fix user --- .../sfile/dto/TransferMetadataDTO.java | 10 ++- .../impl/TransferFileMonitorServiceImpl.java | 73 ++++++++++++++++++- .../impl/TransferUserFileServiceImpl.java | 17 ++++- .../usercenter/user/dao/UserMapper.java | 9 +++ .../usercenter/user/mapper/UserMapper.xml | 11 +++ .../usercenter/user/service/UserService.java | 9 +++ .../user/service/impl/UserServiceImpl.java | 7 ++ 7 files changed, 129 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/senmesh/sfile/dto/TransferMetadataDTO.java b/src/main/java/com/senmesh/sfile/dto/TransferMetadataDTO.java index e35beab..ac592c1 100644 --- a/src/main/java/com/senmesh/sfile/dto/TransferMetadataDTO.java +++ b/src/main/java/com/senmesh/sfile/dto/TransferMetadataDTO.java @@ -24,5 +24,13 @@ public class TransferMetadataDTO implements Serializable { @ApiModelProperty("扩展用户文件DTO") private ExpandUserFileDTO expandUserFile; -} + @ApiModelProperty("源端用户ID,仅用于日志追踪") + private Long sourceUserId; + @ApiModelProperty("源端用户手机号") + private String sourceUserPhone; + + @ApiModelProperty("源端用户类型") + private Integer sourceUserType; + +} diff --git a/src/main/java/com/senmesh/sfile/service/impl/TransferFileMonitorServiceImpl.java b/src/main/java/com/senmesh/sfile/service/impl/TransferFileMonitorServiceImpl.java index ead668f..bc5cc91 100644 --- a/src/main/java/com/senmesh/sfile/service/impl/TransferFileMonitorServiceImpl.java +++ b/src/main/java/com/senmesh/sfile/service/impl/TransferFileMonitorServiceImpl.java @@ -7,17 +7,17 @@ import com.senmesh.component.file.config.FileProperties; import com.senmesh.component.file.service.FileService; import com.senmesh.sfile.constant.FileLocationEnum; import com.senmesh.sfile.constant.FileStatusEnum; -import com.senmesh.sfile.constant.FileTypeEnum; import com.senmesh.sfile.constant.RootTypeEnum; import com.senmesh.sfile.dto.ExpandUserFileDTO; import com.senmesh.sfile.dto.FileRiskDTO; import com.senmesh.sfile.dto.TransferMetadataDTO; -import com.senmesh.sfile.dto.UserFileCreateDTO; import com.senmesh.sfile.dto.UserFileDTO; import com.senmesh.sfile.dto.UserFileModifyStatusDTO; import com.senmesh.sfile.service.FileRiskService; import com.senmesh.sfile.service.TransferFileMonitorService; import com.senmesh.sfile.service.UserFileService; +import com.senmesh.usercenter.user.dto.UserDTO; +import com.senmesh.usercenter.user.service.UserService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +33,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.nio.file.attribute.FileTime; import java.util.Comparator; import java.util.Enumeration; @@ -63,6 +64,9 @@ public class TransferFileMonitorServiceImpl implements TransferFileMonitorServic @Autowired private FileRiskService fileRiskService; + @Autowired + private UserService userService; + @Override public void scanAndProcess() { String transferReceiveDir = fileProperties.getTransfer().getReceiveDir(); @@ -137,6 +141,10 @@ public class TransferFileMonitorServiceImpl implements TransferFileMonitorServic return; } + if (!resolveTargetUser(zipFile, metadata)) { + return; + } + log.info("文件大小校验通过,开始解包: {}", fileName); // 2. 解包并创建用户文件(传入已解析的元数据,直接创建为正常状态) @@ -154,6 +162,66 @@ public class TransferFileMonitorServiceImpl implements TransferFileMonitorServic } } + /** + * 根据源端用户手机号和用户类型映射目标端用户。映射失败时改名为 .error,避免定时任务重复解包。 + */ + private boolean resolveTargetUser(Path zipFile, TransferMetadataDTO metadata) { + String fileName = zipFile.getFileName().toString(); + String sourceUserPhone = StringUtils.trim(metadata.getSourceUserPhone()); + Integer sourceUserType = metadata.getSourceUserType(); + + if (StringUtils.isBlank(sourceUserPhone) || sourceUserType == null) { + renameToError(zipFile, "元数据缺少源端用户手机号或用户类型"); + return false; + } + + List users = userService.listUncanceledByExactPhoneAndType(sourceUserPhone, sourceUserType); + if (users.size() != 1) { + renameToError(zipFile, "目标端用户匹配数量异常: phone=" + maskPhone(sourceUserPhone) + + ", userType=" + sourceUserType + ", count=" + users.size()); + return false; + } + + Long targetUserId = users.get(0).getId(); + ExpandUserFileDTO expandUserFile = metadata.getExpandUserFile(); + if (expandUserFile == null || expandUserFile.getFolder() == null) { + renameToError(zipFile, "元数据缺少文件夹信息"); + return false; + } + + Long sourceUserId = metadata.getSourceUserId() == null + ? expandUserFile.getFolder().getUserId() + : metadata.getSourceUserId(); + expandUserFile.getFolder().setUserId(targetUserId); + if (expandUserFile.getFiles() != null) { + for (UserFileDTO file : expandUserFile.getFiles()) { + file.setUserId(targetUserId); + } + } + log.info("传输用户映射成功: file={}, sourceUserId={}, sourcePhone={}, sourceType={}, targetUserId={}", + fileName, sourceUserId, maskPhone(sourceUserPhone), sourceUserType, targetUserId); + return true; + } + + private void renameToError(Path zipFile, String reason) { + String fileName = zipFile.getFileName().toString(); + Path errorFile = zipFile.resolveSibling(fileName + ".error"); + try { + Files.move(zipFile, errorFile, StandardCopyOption.REPLACE_EXISTING); + log.error("传输文件停止解包并改名为 .error: file={}, errorFile={}, reason={}", + fileName, errorFile.getFileName(), reason); + } catch (Exception e) { + log.error("传输文件停止解包但改名 .error 失败: file={}, reason={}", fileName, reason, e); + } + } + + private String maskPhone(String phone) { + if (StringUtils.length(phone) < 7) { + return phone; + } + return phone.substring(0, 3) + "****" + phone.substring(phone.length() - 4); + } + /** @@ -507,4 +575,3 @@ public class TransferFileMonitorServiceImpl implements TransferFileMonitorServic } } } - diff --git a/src/main/java/com/senmesh/sfile/service/impl/TransferUserFileServiceImpl.java b/src/main/java/com/senmesh/sfile/service/impl/TransferUserFileServiceImpl.java index 01d742c..beaa9c4 100644 --- a/src/main/java/com/senmesh/sfile/service/impl/TransferUserFileServiceImpl.java +++ b/src/main/java/com/senmesh/sfile/service/impl/TransferUserFileServiceImpl.java @@ -1,5 +1,6 @@ package com.senmesh.sfile.service.impl; +import com.senmesh.common.exception.util.Assert; import com.senmesh.common.util.JsonUtils; import com.senmesh.common.util.UserContextHolder; import com.senmesh.component.file.config.FileProperties; @@ -14,6 +15,8 @@ import com.senmesh.sfile.dto.TransferUserFileCreateDTO; import com.senmesh.sfile.dto.UserFileDTO; import com.senmesh.sfile.service.TransferUserFileService; import com.senmesh.sfile.service.UserFileService; +import com.senmesh.usercenter.user.dto.UserDTO; +import com.senmesh.usercenter.user.service.UserService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -25,9 +28,7 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -47,6 +48,9 @@ public class TransferUserFileServiceImpl implements TransferUserFileService { @Autowired private FileService fileService; + @Autowired + private UserService userService; + @Override @Transactional public Long create(TransferUserFileCreateDTO createDTO) { @@ -92,6 +96,11 @@ public class TransferUserFileServiceImpl implements TransferUserFileService { private void packTransferFiles(ExpandUserFileDTO expandUserFileDTO) throws IOException { UserFileDTO folder = expandUserFileDTO.getFolder(); List files = expandUserFileDTO.getFiles(); + UserDTO sourceUser = userService.get(folder.getUserId()); + Assert.notNull(sourceUser, "源端用户不存在"); + Assert.notBlank(sourceUser.getPhone(), "源端用户手机号不能为空"); + Assert.notNull(sourceUser.getType(), "源端用户类型不能为空"); + String sourceUserPhone = sourceUser.getPhone().trim(); // 1. 创建传输发送目录 String transferSendDir = fileProperties.getTransfer().getSendDir(); @@ -133,6 +142,9 @@ public class TransferUserFileServiceImpl implements TransferUserFileService { // 2.2 添加元数据文件 TransferMetadataDTO metadata = TransferMetadataDTO.builder() .expandUserFile(expandUserFileDTO) + .sourceUserId(sourceUser.getId()) + .sourceUserPhone(sourceUserPhone) + .sourceUserType(sourceUser.getType()) .build(); String metadataJson = JsonUtils.toJsonString(metadata); @@ -145,4 +157,3 @@ public class TransferUserFileServiceImpl implements TransferUserFileService { log.info("传输文件打包完成: {}", finalFilePath); } } - diff --git a/src/main/java/com/senmesh/usercenter/user/dao/UserMapper.java b/src/main/java/com/senmesh/usercenter/user/dao/UserMapper.java index f186f6e..48a7d6c 100644 --- a/src/main/java/com/senmesh/usercenter/user/dao/UserMapper.java +++ b/src/main/java/com/senmesh/usercenter/user/dao/UserMapper.java @@ -181,4 +181,13 @@ public interface UserMapper extends MyMapper { List listPlatformUser(@Param("param") PlatformUserListQueryDTO queryDTO); List listByRealNameOrPhone(@Param("orgId") Long orgId, @Param("realNames") Set realNames, @Param("phones") Set phones); + + /** + * 根据手机号和用户类型精确查询未注销用户 + * + * @param phone 手机号 + * @param type 用户类型 + * @return 用户列表 + */ + List listUncanceledByExactPhoneAndType(@Param("phone") String phone, @Param("type") Integer type); } diff --git a/src/main/java/com/senmesh/usercenter/user/mapper/UserMapper.xml b/src/main/java/com/senmesh/usercenter/user/mapper/UserMapper.xml index 5c4df69..68168e2 100644 --- a/src/main/java/com/senmesh/usercenter/user/mapper/UserMapper.xml +++ b/src/main/java/com/senmesh/usercenter/user/mapper/UserMapper.xml @@ -90,6 +90,17 @@ ORDER BY uu.id DESC ) tab + + update diff --git a/src/main/java/com/senmesh/usercenter/user/service/UserService.java b/src/main/java/com/senmesh/usercenter/user/service/UserService.java index 197ac72..ba46db2 100644 --- a/src/main/java/com/senmesh/usercenter/user/service/UserService.java +++ b/src/main/java/com/senmesh/usercenter/user/service/UserService.java @@ -54,6 +54,15 @@ public interface UserService { * @author sr on 2021-05-24 */ List list(UserQueryDTO userQueryDTO); + + /** + * 根据手机号和用户类型精确查询未注销用户 + * + * @param phone 手机号 + * @param type 用户类型 + * @return 用户列表 + */ + List listUncanceledByExactPhoneAndType(String phone, Integer type); /** * 查询单个 diff --git a/src/main/java/com/senmesh/usercenter/user/service/impl/UserServiceImpl.java b/src/main/java/com/senmesh/usercenter/user/service/impl/UserServiceImpl.java index 8c65a1f..dbf5b6d 100644 --- a/src/main/java/com/senmesh/usercenter/user/service/impl/UserServiceImpl.java +++ b/src/main/java/com/senmesh/usercenter/user/service/impl/UserServiceImpl.java @@ -512,6 +512,13 @@ public class UserServiceImpl implements UserService { return userMapper.listUserDTO(userQueryDTO); } + @Override + public List listUncanceledByExactPhoneAndType(String phone, Integer type) { + Assert.notBlank(phone, "手机号不能为空"); + Assert.notNull(type, "用户类型不能为空"); + return userMapper.listUncanceledByExactPhoneAndType(phone.trim(), type); + } + @Override public UserDTO find(UserQueryDTO userQueryDTO) { List userDTOs = list(userQueryDTO);