大华口门部门id修改
parent
8ff5a19654
commit
f5d06a08c7
|
|
@ -21,6 +21,8 @@ import com.zcloud.basic.info.command.convertor.UserCoConvertor;
|
|||
import com.zcloud.basic.info.command.query.CorpInfoQueryExe;
|
||||
import com.zcloud.basic.info.constant.RedisConstant;
|
||||
import com.zcloud.basic.info.domain.config.CodeConfig;
|
||||
import com.zcloud.basic.info.domain.config.DaHuaConfig;
|
||||
import com.zcloud.basic.info.domain.enums.CommonFlagEnum;
|
||||
import com.zcloud.basic.info.domain.enums.CorpTypeEnum;
|
||||
import com.zcloud.basic.info.domain.enums.UserEmploymentFlagEnum;
|
||||
import com.zcloud.basic.info.domain.enums.UserFlowFlagEnum;
|
||||
|
|
@ -31,6 +33,7 @@ import com.zcloud.basic.info.persistence.dataobject.*;
|
|||
import com.zcloud.basic.info.persistence.repository.*;
|
||||
import com.zcloud.gbscommon.utils.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
|
|
@ -38,9 +41,18 @@ import org.springframework.core.env.Environment;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.Period;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Base64;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -53,6 +65,11 @@ import java.util.stream.Collectors;
|
|||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class UserAddExe {
|
||||
@Data
|
||||
public static class DaHuaSyncResult {
|
||||
private Integer dahuaId;
|
||||
private String dahuaCode;
|
||||
}
|
||||
private final UserGateway userGateway;
|
||||
private final UserExpandInfoGateway userExpandInfoGateway;
|
||||
private UserCoConvertor userCoConvertor;
|
||||
|
|
@ -80,6 +97,7 @@ public class UserAddExe {
|
|||
private final CodeConfig codeConfig;
|
||||
private final UserExpandInfoRepository userExpandInfoRepository;
|
||||
private final ImgFilesRepository imgFilesRepository;
|
||||
private final DaHuaConfig daHuaConfig;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean execute(UserAddCmd cmd) {
|
||||
|
|
@ -87,10 +105,48 @@ public class UserAddExe {
|
|||
if (!b) {
|
||||
throw new BizException("请先完善企业信息");
|
||||
}
|
||||
log.info("开始新增用户,name: {}, corpinfoId: {}, phone: {}", cmd.getName(), cmd.getCorpinfoId(), cmd.getPhone());
|
||||
try {
|
||||
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attrs != null) {
|
||||
HttpServletRequest req = attrs.getRequest();
|
||||
String orgidHeader = req.getHeader("orgid");
|
||||
if (orgidHeader != null && cmd.getCorpinfoId() == null) {
|
||||
try {
|
||||
cmd.setCorpinfoId(Long.parseLong(orgidHeader.trim()));
|
||||
} catch (Exception e) {
|
||||
log.warn("orgid 转 Long 失败: {}", orgidHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取请求头异常: {}", e.getMessage());
|
||||
}
|
||||
Long tenantId = null;
|
||||
SSOUser ssoUser = AuthContext.getCurrentUser();
|
||||
Long tenantId = ssoUser.getTenantId();
|
||||
if (ssoUser != null) {
|
||||
tenantId = ssoUser.getTenantId();
|
||||
}
|
||||
UserE userE = new UserE();
|
||||
BeanUtils.copyProperties(cmd, userE);
|
||||
// tenantId 优先级:cmd 传值 -> AuthContext 上下文 -> ssoUser
|
||||
if (!ObjectUtils.isEmpty(userE.getTenantId())) {
|
||||
tenantId = userE.getTenantId();
|
||||
} else if (!ObjectUtils.isEmpty(userE.getCorpinfoId())) {
|
||||
tenantId = userE.getCorpinfoId();
|
||||
} else {
|
||||
try {
|
||||
Long ctxTenantId = AuthContext.getTenantId();
|
||||
if (ctxTenantId != null) {
|
||||
tenantId = ctxTenantId;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("从 AuthContext 获取 tenantId 失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
if (tenantId == null && ObjectUtils.isEmpty(userE.getCorpinfoId())) {
|
||||
throw new BizException("无法获取租户信息,请登录后重试或在请求中指定 corpinfoId");
|
||||
}
|
||||
userE.initAdd(tenantId, userE);
|
||||
//校验身份证是否存在
|
||||
List<UserDO> userDOList = userRepository.getByIdCard(userE.getUserIdCard(), null);
|
||||
|
|
@ -106,7 +162,13 @@ public class UserAddExe {
|
|||
userE.checkPhone(userEList);
|
||||
}
|
||||
|
||||
if (userE.getCorpinfoId() == null) {
|
||||
throw new BizException("企业ID不能为空");
|
||||
}
|
||||
CorpInfoDO corpInfoDO = corpInfoRepository.getById(userE.getCorpinfoId());
|
||||
if (corpInfoDO == null) {
|
||||
throw new BizException("企业信息不存在,corpinfoId=" + userE.getCorpinfoId());
|
||||
}
|
||||
String corpName = null;
|
||||
UserEmploymentLogE userEmploymentLogE = new UserEmploymentLogE();
|
||||
BeanUtils.copyProperties(userE, userEmploymentLogE);
|
||||
|
|
@ -122,21 +184,332 @@ public class UserAddExe {
|
|||
userE.setUserType(CorpTypeEnum.getUserTypeByCode(corpInfoDO.getType()));
|
||||
|
||||
userE.resetPassword(corpInfoDO.getType());
|
||||
// ① 先本地落库 + 底座GBS新增。GBS失败抛 RuntimeException,整个事务回滚
|
||||
res = userGateway.add(userE);
|
||||
if (corpInfoDO != null && !ObjectUtils.isEmpty(corpInfoDO.getCorpName())) {
|
||||
corpName = corpInfoDO.getCorpName();
|
||||
}
|
||||
userEmploymentLogE.initAdd(userEmploymentLogE, corpName, userE.getId());
|
||||
try {
|
||||
userEmploymentLogGateway.add(userEmploymentLogE);
|
||||
} catch (Exception e) {
|
||||
log.error("用户就业日志保存失败(不影响用户主体), userId: {}, error: {}", userE.getId(), e.getMessage(), e);
|
||||
}
|
||||
try {
|
||||
addUserChangeRecordForSave(userE, corpInfoDO);
|
||||
} catch (Exception e) {
|
||||
log.error("用户变更记录保存失败(不影响用户主体), userId: {}, error: {}", userE.getId(), e.getMessage(), e);
|
||||
}
|
||||
// ② 本地和底座都成功后,最后才同步大华。失败→抛异常→回滚本地+GBS(避免留下"大华人成功但本地没数据")
|
||||
DaHuaSyncResult syncResult = syncDaHuaPerson(userE);
|
||||
if (syncResult.dahuaId != null || (syncResult.dahuaCode != null && !syncResult.dahuaCode.trim().isEmpty())) {
|
||||
try {
|
||||
UserE updateDahua = new UserE();
|
||||
updateDahua.setId(userE.getId());
|
||||
updateDahua.setDahuaId(syncResult.dahuaId);
|
||||
updateDahua.setDahuaCode(syncResult.dahuaCode);
|
||||
userRepository.updateDahuaInfo(updateDahua.getId(), updateDahua.getDahuaId(), updateDahua.getDahuaCode());
|
||||
log.info("写回dahuaId/dahuaCode成功, userId={}, dahuaId={}, dahuaCode={}",
|
||||
userE.getId(), syncResult.dahuaId, syncResult.dahuaCode);
|
||||
} catch (Exception e) {
|
||||
log.error("写回dahuaId/dahuaCode失败, userId={}, dahuaId={}, dahuaCode={}",
|
||||
userE.getId(), syncResult.dahuaId, syncResult.dahuaCode, e);
|
||||
throw new BizException("写回大华信息到本地失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (BizException e) {
|
||||
log.error("新增用户业务异常: {}", e.getMessage(), e);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("新增用户系统异常: {}", e.getMessage(), e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (!res) {
|
||||
throw new BizException("保存失败");
|
||||
}
|
||||
cmd.setId(userE.getId());
|
||||
cmd.setUsername(userE.getUsername());
|
||||
log.info("新增用户完成, userId: {}, username: {}", userE.getId(), userE.getUsername());
|
||||
return true;
|
||||
}
|
||||
|
||||
private DaHuaSyncResult syncDaHuaPerson(UserE userE) {
|
||||
return syncDaHuaPerson(userE, userE.getFaceFile(), true);
|
||||
}
|
||||
|
||||
private DaHuaSyncResult syncDaHuaPerson(UserE userE, Object avatarSource, boolean throwOnFail) {
|
||||
Map<String, Object> personMap = new HashMap<>();
|
||||
personMap.put("name", userE.getName());
|
||||
String idCard = userE.getUserIdCard();
|
||||
String plainIdCard = idCard;
|
||||
if (idCard != null && !idCard.trim().isEmpty()) {
|
||||
try {
|
||||
byte[] decodedBytes = Base64.getDecoder().decode(idCard.trim());
|
||||
plainIdCard = new String(decodedBytes, StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
log.warn("身份证号非Base64格式,按原值处理: {}", idCard);
|
||||
}
|
||||
}
|
||||
personMap.put("code", plainIdCard);
|
||||
personMap.put("paperType", 111);
|
||||
personMap.put("paperNumber", plainIdCard);
|
||||
personMap.put("phone", userE.getPhone());
|
||||
Long realCorpId = userE.getCorpinfoId() != null ? userE.getCorpinfoId() : 1L;
|
||||
personMap.put("departmentId", realCorpId);
|
||||
personMap.put("departmentType", 2);
|
||||
personMap.put("type", 3);
|
||||
if (userE.getNation() != null && !userE.getNation().trim().isEmpty()) {
|
||||
try {
|
||||
personMap.put("nation", Integer.valueOf(userE.getNation().trim()));
|
||||
} catch (Exception e) {
|
||||
log.warn("用户民族编码转Integer失败,用默认值1,nation={}", userE.getNation());
|
||||
personMap.put("nation", 1);
|
||||
}
|
||||
} else {
|
||||
personMap.put("nation", 1);
|
||||
}
|
||||
personMap.put("nationName", (userE.getNationName() != null && !userE.getNationName().trim().isEmpty()) ? userE.getNationName().trim() : "汉族");
|
||||
personMap.put("service", "evo-thirdParty");
|
||||
|
||||
Object faceFile = avatarSource != null ? avatarSource : userE.getFaceFile();
|
||||
|
||||
java.util.function.Function<Object, String> extractThumbFromSingle = (singleObj) -> {
|
||||
if (singleObj == null) {
|
||||
return null;
|
||||
}
|
||||
if (singleObj instanceof String) {
|
||||
return singleObj.toString();
|
||||
}
|
||||
if (singleObj instanceof Map) {
|
||||
Map<String, Object> faceFileMap = (Map<String, Object>) singleObj;
|
||||
Object thumbUrlObj = faceFileMap.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} else if (singleObj instanceof cn.hutool.json.JSONObject) {
|
||||
cn.hutool.json.JSONObject faceJson = (cn.hutool.json.JSONObject) singleObj;
|
||||
Object thumbUrlObj = faceJson.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
cn.hutool.json.JSONObject faceJson = cn.hutool.json.JSONUtil.parseObj(singleObj);
|
||||
Object thumbUrlObj = faceJson.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析单个图片对象为JSON失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
String thumbUrl = null;
|
||||
if (faceFile != null) {
|
||||
boolean isArray = false;
|
||||
Object firstElement = null;
|
||||
if (faceFile instanceof java.util.Collection) {
|
||||
isArray = true;
|
||||
java.util.Collection<?> coll = (java.util.Collection<?>) faceFile;
|
||||
if (!coll.isEmpty()) {
|
||||
firstElement = coll.iterator().next();
|
||||
}
|
||||
} else if (faceFile.getClass().isArray()) {
|
||||
isArray = true;
|
||||
Object[] arr = (Object[]) faceFile;
|
||||
if (arr.length > 0) {
|
||||
firstElement = arr[0];
|
||||
}
|
||||
} else if (faceFile instanceof cn.hutool.json.JSONArray) {
|
||||
isArray = true;
|
||||
cn.hutool.json.JSONArray jsonArr = (cn.hutool.json.JSONArray) faceFile;
|
||||
if (!jsonArr.isEmpty()) {
|
||||
firstElement = jsonArr.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
if (firstElement != null) {
|
||||
thumbUrl = extractThumbFromSingle.apply(firstElement);
|
||||
}
|
||||
} else {
|
||||
thumbUrl = extractThumbFromSingle.apply(faceFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (thumbUrl != null && !thumbUrl.trim().isEmpty()) {
|
||||
String trimmedThumb = thumbUrl.trim();
|
||||
boolean startsWithHttp = trimmedThumb.startsWith("http://") || trimmedThumb.startsWith("https://");
|
||||
boolean containsComma = trimmedThumb.contains(",");
|
||||
boolean startsWithDataImage = trimmedThumb.startsWith("data:image");
|
||||
|
||||
String cleanBase64;
|
||||
if (containsComma && startsWithDataImage) {
|
||||
String prefixPart = trimmedThumb.substring(0, trimmedThumb.indexOf(",") + 1);
|
||||
String bodyPart = trimmedThumb.substring(trimmedThumb.indexOf(",") + 1);
|
||||
String cleanBody = bodyPart.replaceAll("\\s+", "");
|
||||
cleanBase64 = prefixPart + cleanBody;
|
||||
} else {
|
||||
String pureBody = trimmedThumb.replaceAll("\\s+", "");
|
||||
cleanBase64 = "data:image/jpeg;base64," + pureBody;
|
||||
}
|
||||
int commaIdx = cleanBase64.indexOf(",");
|
||||
String base64BodyOnly = commaIdx >= 0 ? cleanBase64.substring(commaIdx + 1) : cleanBase64;
|
||||
boolean isLikelyBase64 = base64BodyOnly.matches("^[A-Za-z0-9+/=]+$");
|
||||
int bodyLen = base64BodyOnly.length();
|
||||
boolean finalHasPrefix = cleanBase64.startsWith("data:image");
|
||||
|
||||
if (startsWithHttp) {
|
||||
log.error("同步大华人员失败:人脸图片传的是HTTP/HTTPS URL,要求必须传带data:image前缀的base64图片");
|
||||
} else if (!finalHasPrefix) {
|
||||
log.error("同步大华人员失败:人脸图片最终无data:image前缀,代码补齐逻辑失效");
|
||||
} else if (!isLikelyBase64) {
|
||||
log.error("同步大华人员失败:人脸图片base64主体含非base64非法字符");
|
||||
} else if (bodyLen < 1000) {
|
||||
log.error("同步大华人员失败:人脸图片base64主体长度过短({}),缩略图可能损坏", bodyLen);
|
||||
}
|
||||
|
||||
List<Map<String, Object>> personBiosignatures = new ArrayList<>();
|
||||
Map<String, Object> biosignature = new java.util.LinkedHashMap<>();
|
||||
biosignature.put("type", 3);
|
||||
biosignature.put("index", 1);
|
||||
biosignature.put("base64Data", cleanBase64);
|
||||
personBiosignatures.add(biosignature);
|
||||
personMap.put("personBiosignatures", personBiosignatures);
|
||||
} else {
|
||||
log.warn("未获取到人脸图片thumbUrl,personBiosignatures将不传递");
|
||||
}
|
||||
|
||||
Integer age = null;
|
||||
Integer sex = null;
|
||||
if (plainIdCard != null && plainIdCard.length() == 18) {
|
||||
try {
|
||||
String birthStr = plainIdCard.substring(6, 14);
|
||||
LocalDate birthDate = LocalDate.parse(birthStr, DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
age = Period.between(birthDate, LocalDate.now()).getYears();
|
||||
char sexChar = plainIdCard.charAt(16);
|
||||
int sexNum = Integer.parseInt(String.valueOf(sexChar));
|
||||
sex = (sexNum % 2 == 1) ? 1 : 2;
|
||||
} catch (Exception e) {
|
||||
log.warn("解析身份证号获取年龄性别失败: {}, error={}", plainIdCard, e.getMessage());
|
||||
}
|
||||
}
|
||||
if (age == null) {
|
||||
if (userE.getBirthday() != null && !userE.getBirthday().trim().isEmpty()) {
|
||||
try {
|
||||
String birthdayStr = userE.getBirthday().trim();
|
||||
LocalDate birthDate = null;
|
||||
if (birthdayStr.length() == 8 && birthdayStr.matches("\\d{8}")) {
|
||||
birthDate = LocalDate.parse(birthdayStr, DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
} else if (birthdayStr.contains("-")) {
|
||||
birthDate = LocalDate.parse(birthdayStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||
} else if (birthdayStr.contains("/")) {
|
||||
birthDate = LocalDate.parse(birthdayStr, DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
||||
}
|
||||
if (birthDate != null) {
|
||||
age = Period.between(birthDate, LocalDate.now()).getYears();
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
if (age == null) {
|
||||
age = 23;
|
||||
}
|
||||
if (sex == null) {
|
||||
if ("1".equals(userE.getSex()) || "男".equals(userE.getSex())) {
|
||||
sex = 1;
|
||||
} else if ("2".equals(userE.getSex()) || "女".equals(userE.getSex())) {
|
||||
sex = 2;
|
||||
} else {
|
||||
sex = 1;
|
||||
}
|
||||
}
|
||||
personMap.put("age", age);
|
||||
personMap.put("sex", sex);
|
||||
Map<String, String> extraHeaders = new HashMap<>();
|
||||
try {
|
||||
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attrs != null) {
|
||||
HttpServletRequest req = attrs.getRequest();
|
||||
String token = req.getHeader("token");
|
||||
String orgid = req.getHeader("orgid");
|
||||
String tenantId = req.getHeader("tenantId");
|
||||
if (token != null && !token.trim().isEmpty()) {
|
||||
extraHeaders.put("token", token);
|
||||
}
|
||||
if (orgid != null && !orgid.trim().isEmpty()) {
|
||||
extraHeaders.put("orgid", orgid);
|
||||
}
|
||||
if (tenantId != null && !tenantId.trim().isEmpty()) {
|
||||
extraHeaders.put("tenantId", tenantId);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取当前请求头异常: {}", e.getMessage());
|
||||
}
|
||||
Map<String, Object> syncResult = daHuaConfig.syncPerson(personMap, extraHeaders);
|
||||
Boolean success = (Boolean) syncResult.get("success");
|
||||
Boolean skipped = (Boolean) syncResult.get("skipped");
|
||||
DaHuaSyncResult result = new DaHuaSyncResult();
|
||||
result.setDahuaCode(plainIdCard);
|
||||
if (skipped != null && skipped) {
|
||||
return result;
|
||||
}
|
||||
String maskedIdCard = plainIdCard;
|
||||
if (plainIdCard != null && plainIdCard.length() >= 14) {
|
||||
maskedIdCard = plainIdCard.substring(0, 6) + "********" + plainIdCard.substring(plainIdCard.length() - 4);
|
||||
}
|
||||
result.setDahuaCode(plainIdCard);
|
||||
userE.setDahuaCode(plainIdCard);
|
||||
if (success == null || !success) {
|
||||
String errCode = (String) syncResult.getOrDefault("errCode", "");
|
||||
String errMessage = (String) syncResult.getOrDefault("errMessage", "大华人员同步失败");
|
||||
if (throwOnFail) {
|
||||
throw new BizException("同步大华平台失败:" + errMessage);
|
||||
} else {
|
||||
log.warn("同步大华平台未成功(重复信息或其他原因,不影响本地数据保存): errCode={}, errMessage={}, userId={}, idCardMask={}",
|
||||
errCode, errMessage, userE.getId(), maskedIdCard);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Object data = syncResult.get("data");
|
||||
if (data != null) {
|
||||
if (data instanceof Map) {
|
||||
Map<String, Object> dataMap = (Map<String, Object>) data;
|
||||
Object idObj = dataMap.get("id");
|
||||
if (idObj != null) {
|
||||
try {
|
||||
Integer dahuaId = Integer.valueOf(idObj.toString());
|
||||
result.setDahuaId(dahuaId);
|
||||
userE.setDahuaId(dahuaId);
|
||||
log.info("设置大华dahuaId成功, dahuaId={}", dahuaId);
|
||||
} catch (Exception e) {
|
||||
log.warn("转换大华返回id为Integer失败, idObj={}", idObj);
|
||||
}
|
||||
}
|
||||
} else if (data instanceof cn.hutool.json.JSONObject) {
|
||||
cn.hutool.json.JSONObject dataJson = (cn.hutool.json.JSONObject) data;
|
||||
Object idObj = dataJson.get("id");
|
||||
if (idObj != null) {
|
||||
try {
|
||||
Integer dahuaId = Integer.valueOf(idObj.toString());
|
||||
result.setDahuaId(dahuaId);
|
||||
userE.setDahuaId(dahuaId);
|
||||
log.info("设置大华dahuaId成功, dahuaId={}", dahuaId);
|
||||
} catch (Exception e) {
|
||||
log.warn("转换大华返回id为Integer失败, idObj={}", idObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
userE.setDahuaCode(plainIdCard);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean executeRegister(AppUserRegisterCmd cmd) {
|
||||
|
||||
|
|
@ -494,19 +867,63 @@ public class UserAddExe {
|
|||
sendParams.put("code", phoneCode);
|
||||
messageSendCmd.setParams(sendParams);
|
||||
SingleResponse<Boolean> d = messageFacade.send(messageSendCmd);
|
||||
System.out.println( d.toString());
|
||||
log.info("短信发送结果: {}, phone: {}", d, phone);
|
||||
return d == null ? false : d.getData();
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean executeXgf(UserXgfAddCmd cmd) {
|
||||
log.info("开始新增相关方用户,name: {}, corpinfoId: {}, phone: {}", cmd.getName(), cmd.getCorpinfoId(), cmd.getPhone());
|
||||
try {
|
||||
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attrs != null) {
|
||||
HttpServletRequest req = attrs.getRequest();
|
||||
String orgidHeader = req.getHeader("orgid");
|
||||
if (orgidHeader != null && cmd.getCorpinfoId() == null) {
|
||||
try {
|
||||
cmd.setCorpinfoId(Long.parseLong(orgidHeader.trim()));
|
||||
} catch (Exception e) {
|
||||
log.warn("orgid 转 Long 失败: {}", orgidHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取请求头异常: {}", e.getMessage());
|
||||
}
|
||||
Long tenantId = null;
|
||||
SSOUser ssoUser = AuthContext.getCurrentUser();
|
||||
Long tenantId = ssoUser.getTenantId();
|
||||
if (ssoUser != null) {
|
||||
tenantId = ssoUser.getTenantId();
|
||||
}
|
||||
UserE userE = new UserE();
|
||||
BeanUtils.copyProperties(cmd, userE);
|
||||
// tenantId 优先级:cmd 传值 -> AuthContext 上下文 -> ssoUser
|
||||
if (!ObjectUtils.isEmpty(userE.getTenantId())) {
|
||||
tenantId = userE.getTenantId();
|
||||
} else if (!ObjectUtils.isEmpty(userE.getCorpinfoId())) {
|
||||
tenantId = userE.getCorpinfoId();
|
||||
} else {
|
||||
try {
|
||||
Long ctxTenantId = AuthContext.getTenantId();
|
||||
if (ctxTenantId != null) {
|
||||
tenantId = ctxTenantId;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("从 AuthContext 获取 tenantId 失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
if (tenantId == null && ObjectUtils.isEmpty(userE.getCorpinfoId())) {
|
||||
throw new BizException("无法获取租户信息,请登录后重试或在请求中指定 corpinfoId");
|
||||
}
|
||||
if (ObjectUtils.isEmpty(userE.getCorpinfoId())) {
|
||||
userE.setCorpinfoId(tenantId);
|
||||
}
|
||||
userE.initAdd(tenantId, userE);
|
||||
CorpInfoDO corpInfoDO = corpInfoRepository.getById(userE.getCorpinfoId());
|
||||
if (corpInfoDO == null) {
|
||||
throw new BizException("企业信息不存在,corpinfoId=" + userE.getCorpinfoId());
|
||||
}
|
||||
userE.setUserType(CorpTypeEnum.getUserTypeByCode(corpInfoDO.getType()));
|
||||
Long roleId = userRepository.getDefaultRoleId();
|
||||
if (roleId == null) {
|
||||
|
|
@ -579,6 +996,54 @@ public class UserAddExe {
|
|||
userExpandInfoRepository.updateByPhone(userE.getPhone(),userE.getFlowFlag());
|
||||
}
|
||||
|
||||
// ========== 相关方用户同步大华(统一用 /person/sync;重复信息返回false直接跳过不影响本地)==========
|
||||
Long xgfUserId = addFlag ? userE.getId() : userDOUpdate.getId();
|
||||
if (xgfUserId == null) {
|
||||
log.warn("相关方用户保存后未获取到userId,跳过大华同步及dahua信息写回, addFlag={}", addFlag);
|
||||
} else {
|
||||
Object xgfAvatarSource = cmd.getUserImg();
|
||||
if (xgfAvatarSource == null) {
|
||||
xgfAvatarSource = cmd.getUserAvatarUrl();
|
||||
}
|
||||
DaHuaSyncResult xgfSyncResult = null;
|
||||
try {
|
||||
xgfSyncResult = syncDaHuaPerson(userE, xgfAvatarSource, false);
|
||||
} catch (Exception e) {
|
||||
log.error("相关方用户同步大华异常(不影响本地保存,继续执行写回身份证号为dahuaCode), userId={}, addFlag={}, error={}",
|
||||
xgfUserId, addFlag, e.getMessage(), e);
|
||||
}
|
||||
// 无论大华同步成功/失败/返回false/抛异常,都尝试写回dahuaId/dahuaCode:
|
||||
// dahuaId = 大华返回的id(成功时才有,失败/异常/重复时为null)
|
||||
// dahuaCode = 前端传的身份证号(经过Base64解码的明文,syncDaHuaPerson里即使失败也已经set到result了)
|
||||
Integer xgfDahuaId = xgfSyncResult != null ? xgfSyncResult.dahuaId : null;
|
||||
String xgfDahuaCode = xgfSyncResult != null ? xgfSyncResult.dahuaCode : null;
|
||||
// 如果xgfSyncResult异常或dahuaCode为空兜底:直接把userE.getUserIdCard()做一次Base64解码写入dahuaCode,保证100%写回
|
||||
if ((xgfDahuaCode == null || xgfDahuaCode.trim().isEmpty()) && userE.getUserIdCard() != null && !userE.getUserIdCard().trim().isEmpty()) {
|
||||
String idCardRaw = userE.getUserIdCard().trim();
|
||||
try {
|
||||
xgfDahuaCode = new String(java.util.Base64.getDecoder().decode(idCardRaw), java.nio.charset.StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
xgfDahuaCode = idCardRaw;
|
||||
}
|
||||
}
|
||||
if (xgfDahuaId != null || (xgfDahuaCode != null && !xgfDahuaCode.trim().isEmpty())) {
|
||||
try {
|
||||
UserE updateDahua = new UserE();
|
||||
updateDahua.setId(xgfUserId);
|
||||
updateDahua.setDahuaId(xgfDahuaId);
|
||||
updateDahua.setDahuaCode(xgfDahuaCode);
|
||||
userRepository.updateDahuaInfo(updateDahua.getId(), updateDahua.getDahuaId(), updateDahua.getDahuaCode());
|
||||
log.info("相关方用户写回dahuaId/dahuaCode成功, userId={}, addFlag={}, dahuaId={}, dahuaCode={}",
|
||||
xgfUserId, addFlag, xgfDahuaId, xgfDahuaCode);
|
||||
} catch (Exception e) {
|
||||
log.error("相关方用户写回dahuaId/dahuaCode失败, userId={}, addFlag={}, dahuaId={}, dahuaCode={}",
|
||||
xgfUserId, addFlag, xgfDahuaId, xgfDahuaCode, e);
|
||||
}
|
||||
} else {
|
||||
log.warn("相关方用户既无dahuaId也无dahuaCode可写回,跳过update, userId={}, addFlag={}", xgfUserId, addFlag);
|
||||
}
|
||||
}
|
||||
// =========================================================================
|
||||
|
||||
//页面相关保存user_corp
|
||||
/**
|
||||
|
|
@ -635,5 +1100,86 @@ public class UserAddExe {
|
|||
imgFilesRepository.saveBatch(newImgFiles);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long executeHumanUser(UserAddCmd cmd) {
|
||||
UserE userE = new UserE();
|
||||
BeanUtils.copyProperties(cmd, userE);
|
||||
userE.setTenantId(cmd.getCorpinfoId());
|
||||
//校验手机号
|
||||
List<Integer> employmentFlagList = Arrays.asList(UserEmploymentFlagEnum.ON.getCode(), UserEmploymentFlagEnum.ENTRY_AUDIT.getCode(), UserEmploymentFlagEnum.RESIGNATION_AUDIT.getCode());
|
||||
List<UserDO> userList = userRepository.getListByPhone(userE.getPhone(), employmentFlagList);
|
||||
if (CollUtil.isNotEmpty(userList)) {
|
||||
List<UserE> userEList = userCoConvertor.convertDOsToEs(userList);
|
||||
// userE.checkPhone(userEList);
|
||||
if (CollUtil.isNotEmpty(userEList)) {
|
||||
//判断是否有当前企业
|
||||
boolean existInCurrentCorp = userEList.stream()
|
||||
.anyMatch(userE1 -> userE1.getCorpinfoId().equals(cmd.getCorpinfoId()));
|
||||
|
||||
//判断是否在其他企业存在且为在职状态(employment_flag=1)
|
||||
boolean existInOtherCorpAndOnJob = userEList.stream()
|
||||
.filter(userE1 -> !userE1.getCorpinfoId().equals(cmd.getCorpinfoId()))
|
||||
.anyMatch(userE1 -> UserEmploymentFlagEnum.ON.getCode().equals(userE1.getEmploymentFlag()));
|
||||
|
||||
if (existInCurrentCorp) {
|
||||
throw new BizException("当前手机号在当前企业已存在,请联系管理员");
|
||||
} else if (existInOtherCorpAndOnJob) {
|
||||
throw new BizException("当前手机号已在其他企业存在且为在职状态,请联系管理员");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CorpInfoDO corpInfoDO = corpInfoRepository.getById(userE.getCorpinfoId());
|
||||
String corpName = null;
|
||||
UserEmploymentLogE userEmploymentLogE = new UserEmploymentLogE();
|
||||
BeanUtils.copyProperties(userE, userEmploymentLogE);
|
||||
boolean res = false;
|
||||
try {
|
||||
userE.setUserType(CorpTypeEnum.getUserTypeByCode(corpInfoDO.getType()));
|
||||
userE.resetPassword(corpInfoDO.getType());
|
||||
userE.setDepartmentLeaderFlag(0);
|
||||
userE.setUserId(Tools.get32UUID());
|
||||
userE.setRzFlag(CommonFlagEnum.YES.getCode());
|
||||
res = userGateway.add(userE);
|
||||
if (corpInfoDO != null && !ObjectUtils.isEmpty(corpInfoDO.getCorpName())) {
|
||||
corpName = corpInfoDO.getCorpName();
|
||||
}
|
||||
userEmploymentLogE.initAdd(userEmploymentLogE, corpName, userE.getId());
|
||||
userEmploymentLogGateway.add(userEmploymentLogE);
|
||||
// addUserChangeRecordForSave(userE, corpInfoDO);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (!res) {
|
||||
throw new BizException("保存失败");
|
||||
}
|
||||
return userE.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通保存企业用户时补充一条用户变更记录。
|
||||
* 该场景只记录变更后的企业、部门、岗位和姓名信息,变更前信息保持为空。
|
||||
*/
|
||||
private void addUserChangeRecordForSave(UserE userE, CorpInfoDO corpInfoDO) {
|
||||
String corpName = corpInfoDO == null ? null : corpInfoDO.getCorpName();
|
||||
String departmentName = null;
|
||||
String postName = userE.getPostName();
|
||||
if (userE.getDepartmentId() != null) {
|
||||
DepartmentDO departmentDO = departmentRepository.getById(userE.getDepartmentId());
|
||||
if (departmentDO != null) {
|
||||
departmentName = departmentDO.getName();
|
||||
}
|
||||
}
|
||||
if (userE.getPostId() != null && StringUtils.isEmpty(postName)) {
|
||||
PostDO postDO = postRepository.getById(userE.getPostId());
|
||||
if (postDO != null) {
|
||||
postName = postDO.getPostName();
|
||||
}
|
||||
}
|
||||
userE.setPostName(postName);
|
||||
UserChangeRecordE userChangeRecordE = new UserChangeRecordE();
|
||||
userChangeRecordE.initUserAdd(userE, corpName, departmentName);
|
||||
userChangeRecordGateway.add(userChangeRecordE);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,7 @@ import com.jjb.saas.system.client.user.request.UserUpdateQuitCmd;
|
|||
import com.jjb.saas.system.client.user.response.UserDetailCO;
|
||||
import com.sun.xml.bind.v2.TODO;
|
||||
import com.zcloud.basic.info.constant.RedisConstant;
|
||||
import com.zcloud.basic.info.domain.config.DaHuaConfig;
|
||||
import com.zcloud.basic.info.domain.enums.*;
|
||||
import com.zcloud.basic.info.domain.gateway.*;
|
||||
import com.zcloud.basic.info.domain.model.*;
|
||||
|
|
@ -34,13 +35,19 @@ import org.springframework.beans.BeanUtils;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Period;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.Base64;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dm.jdbc.util.DriverUtil.log;
|
||||
|
||||
|
||||
/**
|
||||
* web-app
|
||||
|
|
@ -70,21 +77,32 @@ public class UserUpdateExe {
|
|||
private ZcloudHiddenFacade zcloudHiddenFacade;
|
||||
@DubboReference
|
||||
private ZcloudRiskFacade zcloudRiskFacade;
|
||||
private final DaHuaConfig daHuaConfig;
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void execute(UserUpdateCmd userUpdateCmd) {
|
||||
//pc端不允许修改固定和流动状态
|
||||
log.info("【用户编辑execute入口】开始执行, id={}, name={}, phone={}",
|
||||
userUpdateCmd.getId(), userUpdateCmd.getName(), userUpdateCmd.getPhone());
|
||||
userUpdateCmd.setFlowFlag(null);
|
||||
|
||||
UserE userE = new UserE();
|
||||
BeanUtils.copyProperties(userUpdateCmd, userE);
|
||||
// 对比用户老数据与要修改数据,查看是否涉及调岗及入职
|
||||
UserDO userDO = userRepository.getInfoById(userUpdateCmd.getId());
|
||||
if (userDO == null) {
|
||||
throw new BizException("用户不存在,用户id:" + userUpdateCmd.getId());
|
||||
}
|
||||
userE.setDahuaId(userDO.getDahuaId());
|
||||
userE.setDahuaCode(userDO.getDahuaCode());
|
||||
log.info("【getInfoById查询结果】dahuaId={}, dahuaCode={}, name={}, userIdCard={}",
|
||||
userDO.getDahuaId(), userDO.getDahuaCode(), userDO.getName(), userDO.getUserIdCard());
|
||||
syncDaHuaPersonUpdate(userUpdateCmd, userDO);
|
||||
|
||||
UserE oldUserE = new UserE();
|
||||
BeanUtils.copyProperties(userDO, oldUserE);
|
||||
// boolean transferPositionFlag = userE.verifyTransferPosition(oldUserE, userE);
|
||||
boolean transferFlowFlag = userE.verifyTransferFlow(oldUserE, userE);
|
||||
boolean nameChanged = userUpdateCmd.getName() != null && !Objects.equals(userDO.getName(), userUpdateCmd.getName());
|
||||
if (transferFlowFlag) {
|
||||
List<UserCorpRecordDO> userCorpRecordDOList = userCorpRecordRepository.getInfoListByUserId(userDO.getId());
|
||||
if (CollUtil.isNotEmpty(userCorpRecordDOList)) {
|
||||
|
|
@ -179,6 +197,9 @@ public class UserUpdateExe {
|
|||
}else {
|
||||
throw new BizException("未找到该用户所属企业");
|
||||
}
|
||||
if (nameChanged) {
|
||||
addUserChangeRecordForNameUpdate(userDO);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -207,6 +228,270 @@ public class UserUpdateExe {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通编辑场景下姓名发生变化时,补充一条用户变更记录。
|
||||
* 该记录只在姓名实际变更后新增,避免影响其他普通修改逻辑。
|
||||
*/
|
||||
private void addUserChangeRecordForNameUpdate(UserDO oldUserDO) {
|
||||
UserDO newUserDO = userRepository.getInfoById(oldUserDO.getId());
|
||||
if (newUserDO == null) {
|
||||
log.warn("用户编辑后未查询到最新用户信息,跳过姓名变更记录,用户id:{}", oldUserDO.getId());
|
||||
return;
|
||||
}
|
||||
|
||||
UserE oldUserE = new UserE();
|
||||
BeanUtils.copyProperties(oldUserDO, oldUserE);
|
||||
UserE newUserE = new UserE();
|
||||
BeanUtils.copyProperties(newUserDO, newUserE);
|
||||
|
||||
UserChangeRecordE userChangeRecordE = new UserChangeRecordE();
|
||||
userChangeRecordE.initUserUpdate(newUserE, oldUserE, newUserDO.getCorpinfoName(), newUserDO.getDepartmentName(),UserChangeRecordStatusEnum.APPROVED.getCode());
|
||||
userChangeRecordGateway.add(userChangeRecordE);
|
||||
}
|
||||
|
||||
private void syncDaHuaPersonUpdate(UserUpdateCmd userUpdateCmd, UserDO userDO) {
|
||||
log.info("========== 大华人员(更新)检查开始 ==========");
|
||||
log.info("用户主键userDO.id={}, name={}, userIdCard={}, dahuaId={}, dahuaCode={}",
|
||||
userDO.getId(), userDO.getName(), userDO.getUserIdCard(), userDO.getDahuaId(), userDO.getDahuaCode());
|
||||
Integer dahuaId = userDO.getDahuaId();
|
||||
String dahuaCode = userDO.getDahuaCode();
|
||||
if (dahuaId == null && (dahuaCode == null || dahuaCode.trim().isEmpty())) {
|
||||
log.info("【跳过同步大华】该用户user表中dahuaId和dahuaCode都为空,说明从未同步过大华,本次跳过不调更新接口");
|
||||
return;
|
||||
}
|
||||
|
||||
String newName = userUpdateCmd.getName() != null ? userUpdateCmd.getName() : userDO.getName();
|
||||
String newIdCard = userUpdateCmd.getUserIdCard() != null ? userUpdateCmd.getUserIdCard() : userDO.getUserIdCard();
|
||||
String newPhone = userUpdateCmd.getPhone() != null ? userUpdateCmd.getPhone() : userDO.getPhone();
|
||||
String newNation = userUpdateCmd.getNation() != null ? userUpdateCmd.getNation() : userDO.getNation();
|
||||
String newNationName = userUpdateCmd.getNationName() != null ? userUpdateCmd.getNationName() : userDO.getNationName();
|
||||
Object newFaceFile = userUpdateCmd.getUserImg() != null ? userUpdateCmd.getUserImg() : userUpdateCmd.getFaceFile();
|
||||
Long newCorpId = userUpdateCmd.getCorpinfoId() != null ? userUpdateCmd.getCorpinfoId() : userDO.getCorpinfoId();
|
||||
log.info("【本次请求入参】name是否传={}, phone是否传={}, userIdCard是否传={}, nation是否传={}, nationName是否传={}, userImg是否传={}, faceFile是否传={}, corpinfoId是否传={}",
|
||||
userUpdateCmd.getName() != null, userUpdateCmd.getPhone() != null, userUpdateCmd.getUserIdCard() != null,
|
||||
userUpdateCmd.getNation() != null, userUpdateCmd.getNationName() != null,
|
||||
userUpdateCmd.getUserImg() != null, userUpdateCmd.getFaceFile() != null,
|
||||
userUpdateCmd.getCorpinfoId() != null);
|
||||
|
||||
boolean nameChanged = !Objects.equals(newName, userDO.getName());
|
||||
boolean idCardChanged = !Objects.equals(newIdCard, userDO.getUserIdCard());
|
||||
boolean phoneChanged = !Objects.equals(newPhone, userDO.getPhone());
|
||||
boolean nationChanged = !Objects.equals(newNation, userDO.getNation()) || !Objects.equals(newNationName, userDO.getNationName());
|
||||
boolean faceChanged = newFaceFile != null;
|
||||
boolean corpChanged = !Objects.equals(newCorpId, userDO.getCorpinfoId());
|
||||
log.info("【变化检测】nameChanged={}({}→{}), idCardChanged={}, phoneChanged={}, nationChanged={}({}/{}→{}/{}), faceChanged={}, corpChanged={}({}→{})",
|
||||
nameChanged, userDO.getName(), newName,
|
||||
idCardChanged, phoneChanged,
|
||||
nationChanged, userDO.getNation(), userDO.getNationName(), newNation, newNationName,
|
||||
faceChanged, corpChanged, userDO.getCorpinfoId(), newCorpId);
|
||||
if (!nameChanged && !idCardChanged && !phoneChanged && !nationChanged && !faceChanged && !corpChanged) {
|
||||
log.info("【跳过同步大华】姓名/身份证/手机号/民族/人脸图/企业 6项都没变化,按优化逻辑不调更新接口");
|
||||
return;
|
||||
}
|
||||
|
||||
String plainIdCard = newIdCard;
|
||||
if (newIdCard != null && !newIdCard.trim().isEmpty()) {
|
||||
try {
|
||||
byte[] decodedBytes = Base64.getDecoder().decode(newIdCard.trim());
|
||||
plainIdCard = new String(decodedBytes, StandardCharsets.UTF_8);
|
||||
log.info("身份证号Base64解密成功, 密文前20={}, 明文前10={}",
|
||||
newIdCard.substring(0, Math.min(20, newIdCard.length())) + (newIdCard.length() > 20 ? "..." : ""),
|
||||
plainIdCard.substring(0, Math.min(10, plainIdCard.length())) + (plainIdCard.length() > 10 ? "..." : ""));
|
||||
} catch (Exception e) {
|
||||
log.warn("身份证号非Base64格式,按原值处理: {}", newIdCard);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> personMap = new HashMap<>();
|
||||
if (dahuaId != null) {
|
||||
personMap.put("id", dahuaId);
|
||||
}
|
||||
personMap.put("name", newName);
|
||||
personMap.put("code", dahuaCode != null ? dahuaCode : plainIdCard);
|
||||
personMap.put("paperType", 111);
|
||||
personMap.put("paperNumber", plainIdCard);
|
||||
personMap.put("phone", newPhone);
|
||||
Long realCorpId = newCorpId != null ? newCorpId : 1L;
|
||||
personMap.put("departmentId", realCorpId);
|
||||
personMap.put("nationName", newNationName != null && !newNationName.trim().isEmpty() ? newNationName : "汉族");
|
||||
try {
|
||||
if (newNation != null && !newNation.trim().isEmpty()) {
|
||||
personMap.put("nation", Integer.parseInt(newNation.trim()));
|
||||
} else {
|
||||
personMap.put("nation", 1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("民族编码转Integer失败: {}, 用默认值1(汉族)", newNation);
|
||||
personMap.put("nation", 1);
|
||||
}
|
||||
personMap.put("service", "evo-thirdParty");
|
||||
|
||||
Integer age = null;
|
||||
Integer sex = null;
|
||||
if (plainIdCard != null && plainIdCard.length() == 18) {
|
||||
try {
|
||||
String birthStr = plainIdCard.substring(6, 14);
|
||||
LocalDate birthDate = LocalDate.parse(birthStr, DateTimeFormatter.ofPattern("yyyyMMdd"));
|
||||
age = Period.between(birthDate, LocalDate.now()).getYears();
|
||||
String sexChar = plainIdCard.substring(16, 17);
|
||||
int sexNum = Integer.parseInt(sexChar);
|
||||
sex = sexNum % 2 == 0 ? 2 : 1;
|
||||
} catch (Exception e) {
|
||||
log.warn("从身份证号解析年龄/性别失败, idCard={}", plainIdCard);
|
||||
}
|
||||
}
|
||||
personMap.put("age", age);
|
||||
personMap.put("sex", sex);
|
||||
|
||||
Object faceFile = newFaceFile;
|
||||
java.util.function.Function<Object, String> extractThumbFromSingle = (singleObj) -> {
|
||||
if (singleObj == null) {
|
||||
return null;
|
||||
}
|
||||
if (singleObj instanceof Map) {
|
||||
Map<String, Object> faceFileMap = (Map<String, Object>) singleObj;
|
||||
Object thumbUrlObj = faceFileMap.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} else if (singleObj instanceof cn.hutool.json.JSONObject) {
|
||||
cn.hutool.json.JSONObject faceJson = (cn.hutool.json.JSONObject) singleObj;
|
||||
Object thumbUrlObj = faceJson.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
cn.hutool.json.JSONObject faceJson = cn.hutool.json.JSONUtil.parseObj(singleObj);
|
||||
Object thumbUrlObj = faceJson.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析单个图片对象为JSON失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
String thumbUrl = null;
|
||||
if (faceFile != null) {
|
||||
boolean isArray = false;
|
||||
Object firstElement = null;
|
||||
if (faceFile instanceof java.util.Collection) {
|
||||
isArray = true;
|
||||
java.util.Collection<?> coll = (java.util.Collection<?>) faceFile;
|
||||
if (!coll.isEmpty()) {
|
||||
firstElement = coll.iterator().next();
|
||||
}
|
||||
} else if (faceFile.getClass().isArray()) {
|
||||
isArray = true;
|
||||
Object[] arr = (Object[]) faceFile;
|
||||
if (arr.length > 0) {
|
||||
firstElement = arr[0];
|
||||
}
|
||||
} else if (faceFile instanceof cn.hutool.json.JSONArray) {
|
||||
isArray = true;
|
||||
cn.hutool.json.JSONArray jsonArr = (cn.hutool.json.JSONArray) faceFile;
|
||||
if (!jsonArr.isEmpty()) {
|
||||
firstElement = jsonArr.get(0);
|
||||
}
|
||||
}
|
||||
if (isArray) {
|
||||
if (firstElement != null) {
|
||||
thumbUrl = extractThumbFromSingle.apply(firstElement);
|
||||
}
|
||||
} else {
|
||||
thumbUrl = extractThumbFromSingle.apply(faceFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (thumbUrl != null && !thumbUrl.trim().isEmpty()) {
|
||||
String trimmedThumb = thumbUrl.trim();
|
||||
boolean startsWithHttp = trimmedThumb.startsWith("http://") || trimmedThumb.startsWith("https://");
|
||||
boolean containsComma = trimmedThumb.contains(",");
|
||||
boolean startsWithDataImage = trimmedThumb.startsWith("data:image");
|
||||
|
||||
String cleanBase64;
|
||||
if (containsComma && startsWithDataImage) {
|
||||
String prefixPart = trimmedThumb.substring(0, trimmedThumb.indexOf(",") + 1);
|
||||
String bodyPart = trimmedThumb.substring(trimmedThumb.indexOf(",") + 1);
|
||||
String cleanBody = bodyPart.replaceAll("\\s+", "");
|
||||
cleanBase64 = prefixPart + cleanBody;
|
||||
} else {
|
||||
String pureBody = trimmedThumb.replaceAll("\\s+", "");
|
||||
cleanBase64 = "data:image/jpeg;base64," + pureBody;
|
||||
}
|
||||
int commaIdx = cleanBase64.indexOf(",");
|
||||
String base64BodyOnly = commaIdx >= 0 ? cleanBase64.substring(commaIdx + 1) : cleanBase64;
|
||||
boolean isLikelyBase64 = base64BodyOnly.matches("^[A-Za-z0-9+/=]+$");
|
||||
int bodyLen = base64BodyOnly.length();
|
||||
boolean finalHasPrefix = cleanBase64.startsWith("data:image");
|
||||
|
||||
if (startsWithHttp) {
|
||||
log.error("同步大华人员(更新)失败:人脸图片传的是HTTP/HTTPS URL,要求必须传带data:image前缀的base64图片");
|
||||
throw new BizException("同步大华平台失败:人脸图片不支持URL格式,请上传图片文件");
|
||||
} else if (!finalHasPrefix) {
|
||||
log.error("同步大华人员(更新)失败:人脸图片最终无data:image前缀,代码补齐逻辑失效");
|
||||
throw new BizException("同步大华平台失败:人脸图片格式异常");
|
||||
} else if (!isLikelyBase64) {
|
||||
log.error("同步大华人员(更新)失败:人脸图片base64主体含非base64非法字符");
|
||||
throw new BizException("同步大华平台失败:人脸图片格式错误");
|
||||
} else if (bodyLen < 1000) {
|
||||
log.error("同步大华人员(更新)失败:人脸图片base64主体长度过短({}),缩略图可能损坏", bodyLen);
|
||||
throw new BizException("同步大华平台失败:人脸图片不完整");
|
||||
}
|
||||
|
||||
List<Map<String, Object>> personBiosignatures = new ArrayList<>();
|
||||
Map<String, Object> biosignature = new java.util.LinkedHashMap<>();
|
||||
biosignature.put("type", 3);
|
||||
biosignature.put("index", 1);
|
||||
biosignature.put("base64Data", cleanBase64);
|
||||
personBiosignatures.add(biosignature);
|
||||
personMap.put("personBiosignatures", personBiosignatures);
|
||||
}
|
||||
|
||||
Map<String, String> extraHeaders = new HashMap<>();
|
||||
try {
|
||||
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attrs != null) {
|
||||
HttpServletRequest req = attrs.getRequest();
|
||||
String token = req.getHeader("token");
|
||||
String orgid = req.getHeader("orgid");
|
||||
String tenantId = req.getHeader("tenantId");
|
||||
if (token != null && !token.trim().isEmpty()) {
|
||||
extraHeaders.put("token", token);
|
||||
}
|
||||
if (orgid != null && !orgid.trim().isEmpty()) {
|
||||
extraHeaders.put("orgid", orgid);
|
||||
}
|
||||
if (tenantId != null && !tenantId.trim().isEmpty()) {
|
||||
extraHeaders.put("tenantId", tenantId);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取当前请求头异常: {}", e.getMessage());
|
||||
}
|
||||
|
||||
Map<String, Object> syncResult = daHuaConfig.updatePerson(personMap, extraHeaders);
|
||||
Boolean success = (Boolean) syncResult.get("success");
|
||||
Boolean skipped = (Boolean) syncResult.get("skipped");
|
||||
if (skipped != null && skipped) {
|
||||
return;
|
||||
}
|
||||
String maskedIdCard = plainIdCard;
|
||||
if (plainIdCard != null && plainIdCard.length() >= 14) {
|
||||
maskedIdCard = plainIdCard.substring(0, 6) + "********" + plainIdCard.substring(plainIdCard.length() - 4);
|
||||
}
|
||||
if (success == null || !success) {
|
||||
String errCode = (String) syncResult.getOrDefault("errCode", "");
|
||||
String errMessage = (String) syncResult.getOrDefault("errMessage", "大华人员更新失败");
|
||||
log.error("同步大华人员(更新)失败, errCode={}, errMessage={}, name={}, idCard={}", errCode, errMessage, newName, maskedIdCard);
|
||||
throw new BizException("同步大华平台失败:" + errMessage);
|
||||
}
|
||||
log.info("同步大华人员(更新)成功, name={}, idCard={}", newName, maskedIdCard);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void editData(UserQryCmd userUpdateCmd) {
|
||||
List<UserDO> userDOList = new ArrayList<>();
|
||||
|
|
@ -395,16 +680,9 @@ public class UserUpdateExe {
|
|||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updatePasswordFromApp(AppUserUpdatePassWordCmd cmd) {
|
||||
//新密码和旧密码不能相同
|
||||
if (cmd.getPassword().equals(cmd.getNewPassword())) {
|
||||
throw new BizException("新密码不能与旧密码相同");
|
||||
}
|
||||
UserE userE = new UserE();
|
||||
userE.checkPassword(cmd.getNewPassword(), cmd.getConfirmPassword());
|
||||
|
||||
BeanUtils.copyProperties(cmd, userE);
|
||||
userE.encryptionPassword();
|
||||
userGateway.updatePassword(userE);
|
||||
UserUpdatePassWordCmd userUpdatePassWordCmd = new UserUpdatePassWordCmd();
|
||||
BeanUtils.copyProperties(cmd, userUpdatePassWordCmd);
|
||||
executeUpdatePassword(userUpdatePassWordCmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -422,6 +700,10 @@ public class UserUpdateExe {
|
|||
@Transactional(rollbackFor = Exception.class)
|
||||
public Response executeUpdatePassword(UserUpdatePassWordCmd userUpdatePassWordCmd) {
|
||||
UserE userE = new UserE();
|
||||
if (userUpdatePassWordCmd.getPassword().equals(userUpdatePassWordCmd.getNewPassword())) {
|
||||
throw new BizException("新密码不能与旧密码相同");
|
||||
}
|
||||
userE.checkPassword(userUpdatePassWordCmd.getNewPassword(), userUpdatePassWordCmd.getConfirmPassword());
|
||||
BeanUtils.copyProperties(userUpdatePassWordCmd, userE);
|
||||
userE.encryptionPassword();
|
||||
return userGateway.updatePassword(userE);
|
||||
|
|
@ -490,6 +772,43 @@ public class UserUpdateExe {
|
|||
throw new IllegalArgumentException("GBS离职处理失败,用户id:"+userDO.getId()+",错误信息:"+quit.getErrMessage());
|
||||
}
|
||||
log.info("GBS离职处理结束,用户id:{},结果:{}", userDO.getId(), JSONUtil.toJsonStr(quit));
|
||||
|
||||
Integer dahuaId = userDO.getDahuaId();
|
||||
if (dahuaId != null) {
|
||||
log.info("【离职-同步删除大华人员】userId={}, name={}, dahuaId={}", userDO.getId(), userDO.getName(), dahuaId);
|
||||
Map<String, String> extraHeaders = new HashMap<>();
|
||||
try {
|
||||
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attrs != null) {
|
||||
HttpServletRequest req = attrs.getRequest();
|
||||
String token = req.getHeader("token");
|
||||
String orgid = req.getHeader("orgid");
|
||||
String tenantId = req.getHeader("tenantId");
|
||||
if (token != null && !token.trim().isEmpty()) extraHeaders.put("token", token);
|
||||
if (orgid != null && !orgid.trim().isEmpty()) extraHeaders.put("orgid", orgid);
|
||||
if (tenantId != null && !tenantId.trim().isEmpty()) extraHeaders.put("tenantId", tenantId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("【离职-获取大华透传请求头异常】: {}", e.getMessage());
|
||||
}
|
||||
Map<String, Object> deleteResult = daHuaConfig.deletePerson(Collections.singletonList(dahuaId), extraHeaders);
|
||||
Boolean skipped = (Boolean) deleteResult.get("skipped");
|
||||
if (skipped == null || !skipped) {
|
||||
Boolean success = (Boolean) deleteResult.get("success");
|
||||
String errCode = (String) deleteResult.getOrDefault("errCode", "");
|
||||
String errMessage = (String) deleteResult.getOrDefault("errMessage", "");
|
||||
if (success == null || !success) {
|
||||
log.error("【离职-大华删除失败→触发本地回滚】userId={}, dahuaId={}, errCode={}, errMessage={}",
|
||||
userDO.getId(), dahuaId, errCode, errMessage);
|
||||
throw new BizException("同步大华平台删除离职人员失败:" + errMessage);
|
||||
}
|
||||
log.info("【离职-大华删除成功】userId={}, dahuaId={}", userDO.getId(), dahuaId);
|
||||
} else {
|
||||
log.info("【离职-大华删除跳过】dockFlag未开启, userId={}", userDO.getId());
|
||||
}
|
||||
} else {
|
||||
log.info("【离职-跳过同步大华】用户dahuaId为空,未同步过大华平台, userId={}, name={}", userDO.getId(), userDO.getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue