parent
92cc6154c3
commit
59748186c6
|
|
@ -0,0 +1,20 @@
|
|||
package com.zcloud.basic.info.config;
|
||||
|
||||
import com.jjb.saas.framework.auth.filter.AuthenticationFilter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
public class LocalDevFilterConfig {
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<AuthenticationFilter> disableAuthenticationFilter(AuthenticationFilter authenticationFilter) {
|
||||
log.info("========== 本地开发环境:禁用 AuthenticationFilter 过滤器 ==========");
|
||||
FilterRegistrationBean<AuthenticationFilter> registration = new FilterRegistrationBean<>(authenticationFilter);
|
||||
registration.setEnabled(false);
|
||||
return registration;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
common:
|
||||
mysql:
|
||||
host: nlb-kd2xz70qhllfet2koj.cn-beijing.nlb.aliyuncsslb.com
|
||||
port: 33068
|
||||
username: root
|
||||
password: 5tS3owZ7w8Uk1egv
|
||||
dahua:
|
||||
config:
|
||||
dockFlag: 1
|
||||
primeportUrl: https://gbs-gateway.qhdsafety.com
|
||||
primeportGateway: primeport
|
||||
|
|
@ -3,8 +3,8 @@ spring:
|
|||
import:
|
||||
# - classpath:nacos.yml
|
||||
# - classpath:sdk.yml
|
||||
# - classpath:nacos-prod.yml
|
||||
# - classpath:sdk-prod.yml
|
||||
- classpath:nacos-prod2.yml
|
||||
- classpath:sdk-prod2.yml
|
||||
- classpath:nacos-prod.yml
|
||||
- classpath:sdk-prod.yml
|
||||
# - classpath:nacos-prod2.yml
|
||||
# - classpath:sdk-prod2.yml
|
||||
- classpath:swagger.yml
|
||||
|
|
|
|||
|
|
@ -35,4 +35,4 @@ spring:
|
|||
- config-flyway.yml
|
||||
discovery:
|
||||
server-addr: ${spring.cloud.nacos.config.server-addr}
|
||||
namespace: ${spring.cloud.nacos.config.namespace}
|
||||
namespace: ${spring.cloud.nacos.config.namespace}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
common:
|
||||
mysql:
|
||||
host: 192.168.2.166
|
||||
port: 3306
|
||||
host: nlb-kd2xz70qhllfet2koj.cn-beijing.nlb.aliyuncsslb.com
|
||||
port: 33068
|
||||
username: root
|
||||
password: root
|
||||
password: 5tS3owZ7w8Uk1egv
|
||||
redis:
|
||||
host: 10.43.253.4
|
||||
password: jjb123456
|
||||
|
|
|
|||
|
|
@ -1,10 +1,15 @@
|
|||
package com.zcloud.basic.info.facade;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.bean.copier.CopyOptions;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.cola.dto.MultiResponse;
|
||||
import com.alibaba.cola.dto.SingleResponse;
|
||||
import com.alibaba.cola.exception.BizException;
|
||||
import com.zcloud.basic.info.api.UserServiceI;
|
||||
import com.zcloud.basic.info.command.convertor.UserCoConvertor;
|
||||
import com.zcloud.basic.info.dto.UserAddCmd;
|
||||
import com.zcloud.basic.info.dto.UserUpdateCmd;
|
||||
import com.zcloud.basic.info.dto.clientobject.UserCO;
|
||||
import com.zcloud.basic.info.persistence.dataobject.UserDO;
|
||||
import com.zcloud.basic.info.persistence.dataobject.UserImgDO;
|
||||
|
|
@ -14,7 +19,9 @@ import com.zcloud.gbscommon.zclouduser.facade.ZcloudUserFacade;
|
|||
import com.zcloud.gbscommon.zclouduser.request.*;
|
||||
import com.zcloud.gbscommon.zclouduser.response.ZcloudUserCo;
|
||||
import com.zcloud.gbscommon.zclouduser.response.ZcloudUserImgBase64Co;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.dubbo.config.annotation.DubboService;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -25,6 +32,7 @@ import java.util.Map;
|
|||
/**
|
||||
* @author lin
|
||||
*/
|
||||
@Slf4j
|
||||
@DubboService
|
||||
public class ZcloudUserFacadeImpl implements ZcloudUserFacade {
|
||||
@Resource
|
||||
|
|
@ -97,18 +105,97 @@ public class ZcloudUserFacadeImpl implements ZcloudUserFacade {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SingleResponse addHumanUser(ZcloudUserAddCmd zcloudUserAddCmd) {
|
||||
return null;
|
||||
public SingleResponse<Long> addHumanUser(ZcloudUserAddCmd cmd) {
|
||||
UserAddCmd userAddCmd = new UserAddCmd();
|
||||
BeanUtil.copyProperties(cmd, userAddCmd);
|
||||
return userServiceI.addHumanUser(userAddCmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 人资用户变更 Dubbo 入口。
|
||||
* 这里负责把外部系统的更新命令转换为本系统命令对象,
|
||||
* 并在查到原用户时先回填老数据,再将非空的新值覆盖进去,
|
||||
* 最终统一交给 humanUserUpdateExe 按新增、离职、跨企业变更、企业内修改四种场景处理。
|
||||
*/
|
||||
@Override
|
||||
public SingleResponse<Long> updateHumanUser(ZcloudUserUpdateCmd zcloudUserUpdateCmd) {
|
||||
return null;
|
||||
if (zcloudUserUpdateCmd == null) {
|
||||
throw new BizException("用户更新参数不能为空");
|
||||
}
|
||||
log.info("接收人资用户变更请求参数: {}", JSONUtil.toJsonStr(zcloudUserUpdateCmd));
|
||||
|
||||
UserUpdateCmd userUpdateCmd = new UserUpdateCmd();
|
||||
UserDO userDO = null;
|
||||
if (zcloudUserUpdateCmd.getId() != null) {
|
||||
userDO = userRepository.getInfoById(zcloudUserUpdateCmd.getId());
|
||||
if (userDO != null) {
|
||||
userUpdateCmd = BeanUtil.toBean(userDO, UserUpdateCmd.class);
|
||||
}
|
||||
}
|
||||
|
||||
BeanUtil.copyProperties(zcloudUserUpdateCmd, userUpdateCmd, CopyOptions.create().ignoreNullValue());
|
||||
fillHumanUserUpdateCmd(userUpdateCmd, userDO, zcloudUserUpdateCmd);
|
||||
return userServiceI.updateHumanUser(userUpdateCmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiResponse<ZcloudUserCo> listUserByInfo(ZcloudUserInfoQry zcloudUserInfoQry) {
|
||||
return null;
|
||||
Map<String, Object> parmas = PageQueryHelper.toHashMap(zcloudUserInfoQry);
|
||||
List<UserDO> userList = userRepository.listUserByInfo(parmas);
|
||||
List<ZcloudUserCo> zcloudUserCos = userCoConvertor.converDOsToDubboCOs(userList);
|
||||
return MultiResponse.of(zcloudUserCos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 补齐人资更新入口需要的关键字段。
|
||||
* 这样在外部系统做局部更新时,可以避免 userId、手机号、账号等关键值丢失。
|
||||
* 但如果企业、部门、岗位 id 已发生变化,则需要主动清空旧名称,
|
||||
* 让下游按变更后的 id 重新解析名称,避免跨企业变更时 after 名称仍然写成旧值。
|
||||
*/
|
||||
private void fillHumanUserUpdateCmd(UserUpdateCmd userUpdateCmd, UserDO userDO, ZcloudUserUpdateCmd zcloudUserUpdateCmd) {
|
||||
if (userDO != null && !StringUtils.hasText(userUpdateCmd.getUserId())) {
|
||||
userUpdateCmd.setUserId(userDO.getUserId());
|
||||
}
|
||||
if (userDO != null && !StringUtils.hasText(userUpdateCmd.getName())) {
|
||||
userUpdateCmd.setName(userDO.getName());
|
||||
}
|
||||
if (userDO != null && !StringUtils.hasText(userUpdateCmd.getPhone())) {
|
||||
userUpdateCmd.setPhone(userDO.getPhone());
|
||||
}
|
||||
if (!StringUtils.hasText(userUpdateCmd.getUsername())) {
|
||||
if (StringUtils.hasText(zcloudUserUpdateCmd.getPhone())
|
||||
&& (userDO == null || !StringUtils.hasText(userDO.getUsername()) || userDO.getUsername().equals(userDO.getPhone()))) {
|
||||
userUpdateCmd.setUsername(zcloudUserUpdateCmd.getPhone());
|
||||
} else if (userDO != null) {
|
||||
userUpdateCmd.setUsername(userDO.getUsername());
|
||||
}
|
||||
}
|
||||
if (userDO != null
|
||||
&& userUpdateCmd.getCorpinfoId() != null
|
||||
&& !userUpdateCmd.getCorpinfoId().equals(userDO.getCorpinfoId())) {
|
||||
userUpdateCmd.setCorpinfoName(null);
|
||||
}
|
||||
if (userDO != null
|
||||
&& userUpdateCmd.getDepartmentId() != null
|
||||
&& !userUpdateCmd.getDepartmentId().equals(userDO.getDepartmentId())) {
|
||||
userUpdateCmd.setDepartmentName(null);
|
||||
}
|
||||
if (userDO != null && !StringUtils.hasText(userUpdateCmd.getDepartmentName())) {
|
||||
userUpdateCmd.setDepartmentName(userDO.getDepartmentName());
|
||||
}
|
||||
if (userDO != null
|
||||
&& userUpdateCmd.getPostId() != null
|
||||
&& !userUpdateCmd.getPostId().equals(userDO.getPostId())) {
|
||||
userUpdateCmd.setPostName(null);
|
||||
}
|
||||
if (userDO != null && !StringUtils.hasText(userUpdateCmd.getPostName())) {
|
||||
userUpdateCmd.setPostName(userDO.getPostName());
|
||||
}
|
||||
}
|
||||
|
||||
//人员
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,18 +41,9 @@ 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;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -65,11 +56,6 @@ import java.util.Base64;
|
|||
@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;
|
||||
|
|
@ -97,56 +83,17 @@ 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) {
|
||||
Boolean b = corpInfoQueryExe.verifyCorpInfo();
|
||||
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());
|
||||
Boolean b = corpInfoQueryExe.verifyCorpInfo();
|
||||
if (!b) {
|
||||
throw new BizException("请先完善企业信息");
|
||||
}
|
||||
Long tenantId = null;
|
||||
SSOUser ssoUser = AuthContext.getCurrentUser();
|
||||
if (ssoUser != null) {
|
||||
tenantId = ssoUser.getTenantId();
|
||||
}
|
||||
Long 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);
|
||||
|
|
@ -162,13 +109,7 @@ 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);
|
||||
|
|
@ -184,331 +125,22 @@ 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;
|
||||
userEmploymentLogGateway.add(userEmploymentLogE);
|
||||
addUserChangeRecordForSave(userE, corpInfoDO);
|
||||
} 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());
|
||||
personMap.put("departmentId", 1L);
|
||||
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) {
|
||||
|
||||
|
|
@ -866,63 +498,19 @@ public class UserAddExe {
|
|||
sendParams.put("code", phoneCode);
|
||||
messageSendCmd.setParams(sendParams);
|
||||
SingleResponse<Boolean> d = messageFacade.send(messageSendCmd);
|
||||
log.info("短信发送结果: {}, phone: {}", d, phone);
|
||||
System.out.println( d.toString());
|
||||
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();
|
||||
if (ssoUser != null) {
|
||||
tenantId = ssoUser.getTenantId();
|
||||
}
|
||||
Long 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) {
|
||||
|
|
@ -995,54 +583,6 @@ 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
|
||||
/**
|
||||
|
|
@ -1181,4 +721,5 @@ public class UserAddExe {
|
|||
userChangeRecordE.initUserAdd(userE, corpName, departmentName);
|
||||
userChangeRecordGateway.add(userChangeRecordE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -415,9 +415,9 @@ public class UserImportExe {
|
|||
user.setPostId(postId);
|
||||
user.setCorpinfoId(corpinfoId);
|
||||
user.setName(importEntity.getName());
|
||||
user.setUserIdCard(encodeBase64IdCard(importEntity.getUserIdCard()));
|
||||
user.setUserIdCard(null);
|
||||
user.setPersonnelType(importEntity.getPersonnelType());
|
||||
user.setPersonnelTypeName(importEntity.getPersonnelTypeName());
|
||||
user.setPersonnelTypeName(importEntity.getPersonnelType());
|
||||
user.resetPassword(corpInfoDO.getType());
|
||||
userGateway.add(user);
|
||||
String corpName = null;
|
||||
|
|
@ -444,5 +444,4 @@ public class UserImportExe {
|
|||
return userIdCard.trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -80,6 +80,9 @@ public class UserAddCmd extends Command {
|
|||
@ApiModelProperty(value = "人脸头像url", name = "userAvatarUrl")
|
||||
private String userAvatarUrl;
|
||||
|
||||
@ApiModelProperty(value = "人脸图片文件(取thumbUrl字段作为base64传大华)")
|
||||
private Object faceFile;
|
||||
|
||||
@ApiModelProperty(value = "现住址", name = "currentAddress")
|
||||
private String currentAddress;
|
||||
|
||||
|
|
@ -159,5 +162,10 @@ public class UserAddCmd extends Command {
|
|||
@ApiModelProperty(value = "是否缴纳其他人身伤害保险")
|
||||
private Integer isBf;
|
||||
|
||||
}
|
||||
private Integer rzFlag;
|
||||
|
||||
@ApiModelProperty(value = "该人员在大华口门对应的id")
|
||||
private Integer dahuaId;
|
||||
@ApiModelProperty(value = "该人员在大华口门对应的code")
|
||||
private String dahuaCode;
|
||||
|
||||
|
|
|
|||
|
|
@ -194,6 +194,10 @@ public class UserCO extends ClientObject {
|
|||
@ApiModelProperty(value = "微信openid")
|
||||
private String openId;
|
||||
|
||||
@ApiModelProperty(value = "该人员在大华口门对应的id")
|
||||
private Integer dahuaId;
|
||||
@ApiModelProperty(value = "该人员在大华口门对应的code")
|
||||
private String dahuaCode;
|
||||
|
||||
@ApiModelProperty(value = "是否特殊工种")
|
||||
private Integer isSpecialJob;
|
||||
|
|
@ -221,5 +225,4 @@ public class UserCO extends ClientObject {
|
|||
|
||||
@ApiModelProperty(value = "是否九公司人员")
|
||||
private Boolean nineCompanyFlag;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -21,6 +21,7 @@ import com.zcloud.gbscommon.utils.Sm2Util;
|
|||
import com.zcloud.gbscommon.utils.Tools;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
|
@ -42,6 +43,7 @@ import java.util.stream.Collectors;
|
|||
* @Date 2025-11-04 14:07:34
|
||||
*/
|
||||
@Data
|
||||
@Slf4j
|
||||
public class UserE extends BaseE {
|
||||
//GBS用户id
|
||||
private Long id;
|
||||
|
|
@ -155,6 +157,12 @@ public class UserE extends BaseE {
|
|||
// 入职状态
|
||||
private Integer flowFlag;
|
||||
private Integer rzFlag;
|
||||
// 人脸图片文件
|
||||
private Object faceFile;
|
||||
// 该人员在大华口门对应的id
|
||||
private Integer dahuaId;
|
||||
// 该人员在大华口门对应的code
|
||||
private String dahuaCode;
|
||||
// 父级租户id
|
||||
private final Long parentTenantId = 1989259383784415232L;
|
||||
// 默认密码
|
||||
|
|
@ -358,10 +366,19 @@ public class UserE extends BaseE {
|
|||
if (CollUtil.isEmpty(userEList)) {
|
||||
return;
|
||||
}
|
||||
//判断AuthContext.gettenantId在userList中是否存在
|
||||
//优先用当前对象自身的 corpinfoId,否则回退到 AuthContext
|
||||
Long currentCorpId = this.getCorpinfoId();
|
||||
if (currentCorpId == null) {
|
||||
try {
|
||||
currentCorpId = AuthContext.getTenantId();
|
||||
} catch (Exception e) {
|
||||
log.warn("checkPhone: 从 AuthContext 获取 tenantId 失败,无法按企业维度校验手机号");
|
||||
}
|
||||
}
|
||||
if (CollUtil.isNotEmpty(userEList)) {
|
||||
//判断是否有当前企业
|
||||
boolean flag = userEList.stream().anyMatch(userE -> userE.getCorpinfoId().equals(AuthContext.getTenantId()));
|
||||
final Long finalCorpId = currentCorpId;
|
||||
boolean flag = finalCorpId != null && userEList.stream().anyMatch(userE -> finalCorpId.equals(userE.getCorpinfoId()));
|
||||
if (flag) {
|
||||
//需要修改,不是提示
|
||||
throw new BizException("当前手机号当前企业已存在,请联系管理员");
|
||||
|
|
@ -416,5 +433,4 @@ public class UserE extends BaseE {
|
|||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -164,7 +164,10 @@ public class UserDO extends BaseDO {
|
|||
@ApiModelProperty(value = "微信openid")
|
||||
private String openId;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "该人员在大华口门对应的id")
|
||||
private Integer dahuaId;
|
||||
@ApiModelProperty(value = "该人员在大华口门对应的code")
|
||||
private String dahuaCode;
|
||||
|
||||
|
||||
|
||||
|
|
@ -206,5 +209,4 @@ public class UserDO extends BaseDO {
|
|||
this.userId = userId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue