parent
20f9c5ebd2
commit
5d34e2ab40
|
|
@ -101,31 +101,22 @@ public class UserAddExe {
|
|||
// if (!b) {
|
||||
// throw new BizException("请先完善企业信息");
|
||||
// }
|
||||
log.info("========== 开始新增用户,请求参数 name: {}, corpinfoId: {}, phone: {}, 请求体 JSON: {}", cmd.getName(), cmd.getCorpinfoId(), cmd.getPhone(), JSONUtil.toJsonStr(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();
|
||||
Enumeration<String> headerNames = req.getHeaderNames();
|
||||
Map<String, String> headerMap = new HashMap<>();
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String h = headerNames.nextElement();
|
||||
headerMap.put(h, req.getHeader(h));
|
||||
}
|
||||
log.info("========== 请求头信息: {}", JSONUtil.toJsonStr(headerMap));
|
||||
String orgidHeader = req.getHeader("orgid");
|
||||
log.info("========== 从请求头获取 orgid: {}", orgidHeader);
|
||||
if (orgidHeader != null && cmd.getCorpinfoId() == null) {
|
||||
try {
|
||||
cmd.setCorpinfoId(Long.parseLong(orgidHeader.trim()));
|
||||
log.info("========== 用请求头 orgid 设置 cmd.corpinfoId: {}", cmd.getCorpinfoId());
|
||||
} catch (Exception e) {
|
||||
log.warn("========== orgid 转 Long 失败: {}", orgidHeader);
|
||||
log.warn("orgid 转 Long 失败: {}", orgidHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("========== 获取请求头异常: {}", e.getMessage());
|
||||
log.warn("获取请求头异常: {}", e.getMessage());
|
||||
}
|
||||
Long tenantId = null;
|
||||
SSOUser ssoUser = AuthContext.getCurrentUser();
|
||||
|
|
@ -186,34 +177,39 @@ public class UserAddExe {
|
|||
userE.setRoleId(roleId);
|
||||
}
|
||||
try {
|
||||
log.info("========== 企业类型 type: {}", corpInfoDO.getType());
|
||||
userE.setUserType(CorpTypeEnum.getUserTypeByCode(corpInfoDO.getType()));
|
||||
|
||||
userE.resetPassword(corpInfoDO.getType());
|
||||
//先同步大华人脸平台,成功后再保存本地
|
||||
log.info("========== 开始调用大华同步接口");
|
||||
syncDaHuaPerson(userE);
|
||||
log.info("========== 大华同步成功,开始保存本地用户");
|
||||
res = userGateway.add(userE);
|
||||
log.info("========== 本地保存结果: {}", res);
|
||||
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);
|
||||
log.info("========== 用户就业日志保存成功");
|
||||
} catch (Exception e) {
|
||||
log.error("用户变更记录保存失败(不影响用户主体), userId: {}, error: {}", userE.getId(), e.getMessage(), e);
|
||||
}
|
||||
} catch (BizException e) {
|
||||
log.error("========== 业务异常: {}", e.getMessage(), e);
|
||||
log.error("新增用户业务异常: {}", e.getMessage(), e);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("========== 系统异常: {}", e.getMessage(), e);
|
||||
log.error("新增用户系统异常: {}", e.getMessage(), e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (!res) {
|
||||
throw new BizException("保存失败");
|
||||
}
|
||||
log.info("========== 新增用户完成");
|
||||
cmd.setId(userE.getId());
|
||||
cmd.setUsername(userE.getUsername());
|
||||
log.info("新增用户完成, userId: {}, username: {}", userE.getId(), userE.getUsername());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -242,67 +238,34 @@ public class UserAddExe {
|
|||
personMap.put("service", "evo-thirdParty");
|
||||
|
||||
Object faceFile = userE.getFaceFile();
|
||||
log.info("========== 大华图片调试开始 ==========");
|
||||
log.info("faceFile原始类型: {}, faceFile原始值(截取前500字符): {}",
|
||||
faceFile == null ? "null" : faceFile.getClass().getName(),
|
||||
faceFile == null ? "null" : (faceFile.toString().length() > 500 ? faceFile.toString().substring(0, 500) + "..." : faceFile.toString()));
|
||||
log.info("userE.getUserAvatarUrl()值(截取前500字符): {}",
|
||||
userE.getUserAvatarUrl() == null ? "null" : (userE.getUserAvatarUrl().length() > 500 ? userE.getUserAvatarUrl().substring(0, 500) + "..." : userE.getUserAvatarUrl()));
|
||||
|
||||
java.util.function.Function<Object, String> extractThumbFromSingle = (singleObj) -> {
|
||||
if (singleObj == null) {
|
||||
log.debug("单个图片对象为null");
|
||||
return null;
|
||||
}
|
||||
log.info("从单个对象提取thumbUrl,对象类型: {}", singleObj.getClass().getName());
|
||||
if (singleObj instanceof Map) {
|
||||
Map<String, Object> faceFileMap = (Map<String, Object>) singleObj;
|
||||
log.info("单个对象是Map类型,所有key: {}", faceFileMap.keySet());
|
||||
for (Map.Entry<String, Object> entry : faceFileMap.entrySet()) {
|
||||
Object v = entry.getValue();
|
||||
String vStr = v == null ? "null" : (v.toString().length() > 200 ? v.toString().substring(0, 200) + "..." : v.toString());
|
||||
log.info("单个对象 key={}, value类型={}, value={}", entry.getKey(), v == null ? "null" : v.getClass().getName(), vStr);
|
||||
}
|
||||
Object thumbUrlObj = faceFileMap.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
String res = thumbUrlObj.toString();
|
||||
log.info("从Map提取到thumbUrl,长度={}", res.length());
|
||||
return res;
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} else if (singleObj instanceof cn.hutool.json.JSONObject) {
|
||||
cn.hutool.json.JSONObject faceJson = (cn.hutool.json.JSONObject) singleObj;
|
||||
log.info("单个对象是JSONObject类型,所有key: {}", faceJson.keySet());
|
||||
for (String key : faceJson.keySet()) {
|
||||
Object v = faceJson.get(key);
|
||||
String vStr = v == null ? "null" : (v.toString().length() > 200 ? v.toString().substring(0, 200) + "..." : v.toString());
|
||||
log.info("单个对象 key={}, value类型={}, value={}", key, v == null ? "null" : v.getClass().getName(), vStr);
|
||||
}
|
||||
Object thumbUrlObj = faceJson.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
String res = thumbUrlObj.toString();
|
||||
log.info("从JSONObject提取到thumbUrl,长度={}", res.length());
|
||||
return res;
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
cn.hutool.json.JSONObject faceJson = cn.hutool.json.JSONUtil.parseObj(singleObj);
|
||||
log.info("单个对象解析为JSONObject后,所有key: {}", faceJson.keySet());
|
||||
for (String key : faceJson.keySet()) {
|
||||
Object v = faceJson.get(key);
|
||||
String vStr = v == null ? "null" : (v.toString().length() > 200 ? v.toString().substring(0, 200) + "..." : v.toString());
|
||||
log.info("单个对象 key={}, value类型={}, value={}", key, v == null ? "null" : v.getClass().getName(), vStr);
|
||||
}
|
||||
Object thumbUrlObj = faceJson.get("thumbUrl");
|
||||
if (thumbUrlObj != null) {
|
||||
String res = thumbUrlObj.toString();
|
||||
log.info("从解析后的JSONObject提取到thumbUrl,长度={}", res.length());
|
||||
return res;
|
||||
return thumbUrlObj.toString();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("解析单个图片对象为JSON失败: {}, 错误: {}", singleObj, e.getMessage());
|
||||
log.warn("解析单个图片对象为JSON失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
log.warn("单个对象中未找到thumbUrl字段");
|
||||
return null;
|
||||
};
|
||||
|
||||
|
|
@ -313,56 +276,39 @@ public class UserAddExe {
|
|||
if (faceFile instanceof java.util.Collection) {
|
||||
isArray = true;
|
||||
java.util.Collection<?> coll = (java.util.Collection<?>) faceFile;
|
||||
log.info("faceFile是Collection/List类型,size={}", coll.size());
|
||||
if (!coll.isEmpty()) {
|
||||
firstElement = coll.iterator().next();
|
||||
log.info("取Collection第一个元素,类型: {}", firstElement == null ? "null" : firstElement.getClass().getName());
|
||||
} else {
|
||||
log.warn("faceFile是空数组,无元素可取");
|
||||
}
|
||||
} else if (faceFile.getClass().isArray()) {
|
||||
isArray = true;
|
||||
Object[] arr = (Object[]) faceFile;
|
||||
log.info("faceFile是原生数组类型,length={}", arr.length);
|
||||
if (arr.length > 0) {
|
||||
firstElement = arr[0];
|
||||
log.info("取数组第0个元素,类型: {}", firstElement == null ? "null" : firstElement.getClass().getName());
|
||||
} else {
|
||||
log.warn("faceFile是空原生数组,无元素可取");
|
||||
}
|
||||
} else if (faceFile instanceof cn.hutool.json.JSONArray) {
|
||||
isArray = true;
|
||||
cn.hutool.json.JSONArray jsonArr = (cn.hutool.json.JSONArray) faceFile;
|
||||
log.info("faceFile是JSONArray类型,size={}", jsonArr.size());
|
||||
if (!jsonArr.isEmpty()) {
|
||||
firstElement = jsonArr.get(0);
|
||||
log.info("取JSONArray第0个元素,类型: {}", firstElement == null ? "null" : firstElement.getClass().getName());
|
||||
} else {
|
||||
log.warn("faceFile是空JSONArray,无元素可取");
|
||||
}
|
||||
}
|
||||
|
||||
if (isArray) {
|
||||
log.info("faceFile是数组/集合类型,从第一个元素中提取thumbUrl");
|
||||
if (firstElement != null) {
|
||||
thumbUrl = extractThumbFromSingle.apply(firstElement);
|
||||
} else {
|
||||
log.warn("数组第一个元素是null,无法提取thumbUrl");
|
||||
}
|
||||
} else {
|
||||
log.info("faceFile是单个对象类型,直接提取thumbUrl");
|
||||
thumbUrl = extractThumbFromSingle.apply(faceFile);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("从faceFile提取thumbUrl结果(截取前500字符): {}",
|
||||
thumbUrl == null ? "null" : (thumbUrl.length() > 500 ? thumbUrl.substring(0, 500) + "..." : thumbUrl));
|
||||
|
||||
|
||||
if (thumbUrl != null && !thumbUrl.trim().isEmpty()) {
|
||||
String trimmedThumb = thumbUrl.trim();
|
||||
boolean startsWithDataImage = trimmedThumb.startsWith("data:image");
|
||||
boolean startsWithHttp = trimmedThumb.startsWith("http://") || trimmedThumb.startsWith("https://");
|
||||
boolean containsComma = trimmedThumb.contains(",");
|
||||
boolean startsWithDataImage = trimmedThumb.startsWith("data:image");
|
||||
|
||||
String cleanBase64;
|
||||
if (containsComma && startsWithDataImage) {
|
||||
|
|
@ -370,46 +316,25 @@ public class UserAddExe {
|
|||
String bodyPart = trimmedThumb.substring(trimmedThumb.indexOf(",") + 1);
|
||||
String cleanBody = bodyPart.replaceAll("\\s+", "");
|
||||
cleanBase64 = prefixPart + cleanBody;
|
||||
log.info("已保留data:image前缀(严格对齐大华文档示例), 前缀={}, 仅清洗主体中的空白字符", prefixPart.length() > 80 ? prefixPart.substring(0, 80) + "..." : prefixPart);
|
||||
} else {
|
||||
String pureBody = trimmedThumb.replaceAll("\\s+", "");
|
||||
cleanBase64 = "data:image/jpeg;base64," + pureBody;
|
||||
log.info("原始thumbUrl无标准data:image前缀,已自动补齐(data:image/jpeg;base64,)以对齐大华文档示例");
|
||||
}
|
||||
int commaIdx = cleanBase64.indexOf(",");
|
||||
String base64BodyOnly = commaIdx >= 0 ? cleanBase64.substring(commaIdx + 1) : cleanBase64;
|
||||
boolean isLikelyBase64 = base64BodyOnly.matches("^[A-Za-z0-9+/=]+$");
|
||||
int totalLen = cleanBase64.length();
|
||||
int bodyLen = base64BodyOnly.length();
|
||||
boolean finalHasPrefix = cleanBase64.startsWith("data:image");
|
||||
|
||||
log.info("========== 图片格式判断结果(严格对齐大华文档示例) ==========");
|
||||
log.info("原始thumbUrl总长度: {}", trimmedThumb.length());
|
||||
log.info("最终结果是否带data:image前缀(文档示例:true): {}", finalHasPrefix);
|
||||
log.info("是否是http/https URL(文档要求:false): {}", startsWithHttp);
|
||||
log.info("最终整体长度(含前缀): {}", totalLen);
|
||||
log.info("base64主体长度(去掉前缀逗号后): {}", bodyLen);
|
||||
log.info("base64主体是否匹配纯base64字符集(A-Za-z0-9+/=): {}", isLikelyBase64);
|
||||
if (startsWithHttp) {
|
||||
log.error("===== 严重错误:传的是HTTP/HTTPS URL(或文件路径)!大华文档personBiosignatures要求必须传【带data:image前缀的base64图片】,不是URL =====");
|
||||
System.out.println("===== 大华图片错误:HTTP URL无效, 前200: " + (trimmedThumb.length() > 200 ? trimmedThumb.substring(0, 200) : trimmedThumb));
|
||||
log.error("同步大华人员失败:人脸图片传的是HTTP/HTTPS URL,要求必须传带data:image前缀的base64图片");
|
||||
} else if (!finalHasPrefix) {
|
||||
log.error("===== 最终结果竟然没有data:image前缀(代码补齐逻辑失效) =====");
|
||||
System.out.println("===== 大华图片错误:无data:image前缀, 前100: " + (cleanBase64.length() > 100 ? cleanBase64.substring(0, 100) : cleanBase64));
|
||||
log.error("同步大华人员失败:人脸图片最终无data:image前缀,代码补齐逻辑失效");
|
||||
} else if (!isLikelyBase64) {
|
||||
log.error("===== base64主体部分含非base64非法字符!前200: {}", base64BodyOnly.length() > 200 ? base64BodyOnly.substring(0, 200) : base64BodyOnly);
|
||||
System.out.println("===== 大华图片错误:主体非base64字符, 前200: " + (base64BodyOnly.length() > 200 ? base64BodyOnly.substring(0, 200) : base64BodyOnly));
|
||||
log.error("同步大华人员失败:人脸图片base64主体含非base64非法字符");
|
||||
} else if (bodyLen < 1000) {
|
||||
log.error("===== base64主体长度过短({}),缩略图太小/损坏!正常300KB JPEG→主体约40万字符 =====", bodyLen);
|
||||
System.out.println("===== 大华图片错误:主体过短=" + bodyLen);
|
||||
} else {
|
||||
log.info("===== ✅ 完全符合大华文档personBiosignatures格式:带data:image前缀 + 纯base64主体 + 长度正常 =====");
|
||||
log.error("同步大华人员失败:人脸图片base64主体长度过短({}),缩略图可能损坏", bodyLen);
|
||||
}
|
||||
log.info("【最终传给大华base64Data(严格对齐文档)】前150字符: {}", cleanBase64.length() > 150 ? cleanBase64.substring(0, 150) : cleanBase64);
|
||||
log.info("【最终传给大华base64Data】后150字符: {}", cleanBase64.length() > 150 ? cleanBase64.substring(cleanBase64.length() - 150) : cleanBase64);
|
||||
System.out.println("===== 最终带前缀完整base64Data 前200: " + (cleanBase64.length() > 200 ? cleanBase64.substring(0, 200) : cleanBase64));
|
||||
System.out.println("===== 最终带前缀完整base64Data 后200: " + (cleanBase64.length() > 200 ? cleanBase64.substring(cleanBase64.length() - 200) : cleanBase64));
|
||||
System.out.println("===== 是否按文档带data:image前缀=" + finalHasPrefix + " / 最终总长度=" + totalLen + " / 主体长度=" + bodyLen);
|
||||
|
||||
List<Map<String, Object>> personBiosignatures = new ArrayList<>();
|
||||
Map<String, Object> biosignature = new java.util.LinkedHashMap<>();
|
||||
|
|
@ -418,15 +343,9 @@ public class UserAddExe {
|
|||
biosignature.put("base64Data", cleanBase64);
|
||||
personBiosignatures.add(biosignature);
|
||||
personMap.put("personBiosignatures", personBiosignatures);
|
||||
log.info("组装personBiosignatures成功(严格按文档顺序type→index→base64Data,LinkedHashMap有序)");
|
||||
String biosigJson = JSONUtil.toJsonStr(personBiosignatures);
|
||||
log.info("personBiosignatures JSON(截取前500字符): {}", biosigJson.length() > 500 ? biosigJson.substring(0, 500) + "..." : biosigJson);
|
||||
System.out.println("===== 传给大华personBiosignatures完整JSON前500字符: " + (biosigJson.length() > 500 ? biosigJson.substring(0, 500) + "..." : biosigJson));
|
||||
} else {
|
||||
log.warn("未获取到人脸图片thumbUrl,personBiosignatures将不传递");
|
||||
System.out.println("===== 警告:未从faceFile中获取到有效的thumbUrl,personBiosignatures不会传给大华!");
|
||||
}
|
||||
log.info("========== 大华图片调试结束 ==========");
|
||||
|
||||
Integer age = null;
|
||||
Integer sex = null;
|
||||
|
|
@ -491,7 +410,6 @@ public class UserAddExe {
|
|||
if (tenantId != null && !tenantId.trim().isEmpty()) {
|
||||
extraHeaders.put("tenantId", tenantId);
|
||||
}
|
||||
log.info("收集到需要透传的请求头: {}", extraHeaders);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("获取当前请求头异常: {}", e.getMessage());
|
||||
|
|
@ -502,14 +420,15 @@ public class UserAddExe {
|
|||
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, userE.getName(), plainIdCard);
|
||||
throw new BizException("同步大华平台失败:" + errMessage);
|
||||
}
|
||||
log.info("同步大华人员成功, name={}, idCard={}", userE.getName(), plainIdCard);
|
||||
System.out.println("同步大华人员成功, name=" + userE.getName() + ", idCard=" + plainIdCard);
|
||||
Object data = syncResult.get("data");
|
||||
if (data != null) {
|
||||
if (data instanceof Map) {
|
||||
|
|
@ -539,7 +458,6 @@ public class UserAddExe {
|
|||
}
|
||||
}
|
||||
userE.setDahuaCode(plainIdCard);
|
||||
log.info("设置大华dahuaCode成功, dahuaCode={}", plainIdCard);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
|
@ -899,7 +817,7 @@ 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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,8 +92,6 @@ public class UserUpdateExe {
|
|||
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);
|
||||
|
|
@ -263,26 +261,21 @@ public class UserUpdateExe {
|
|||
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();
|
||||
log.info("【本次请求入参】name是否传={}, phone是否传={}, userIdCard是否传={}, nation是否传={}, nationName是否传={}, userImg是否传={}, faceFile是否传={}",
|
||||
userUpdateCmd.getName() != null, userUpdateCmd.getPhone() != null, userUpdateCmd.getUserIdCard() != null,
|
||||
userUpdateCmd.getNation() != null, userUpdateCmd.getNationName() != null,
|
||||
userUpdateCmd.getUserImg() != null, userUpdateCmd.getFaceFile() != null);
|
||||
Object newFaceFile = userUpdateCmd.getFaceFile();
|
||||
log.info("【本次请求入参】name是否传={}, phone是否传={}, userIdCard是否传={}, faceFile是否传={}",
|
||||
userUpdateCmd.getName() != null, userUpdateCmd.getPhone() != null, userUpdateCmd.getUserIdCard() != null, newFaceFile != 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;
|
||||
log.info("【变化检测】nameChanged={}({}→{}), idCardChanged={}, phoneChanged={}, nationChanged={}({}/{}→{}/{}), faceChanged={}",
|
||||
log.info("【变化检测】nameChanged={}({}→{}), idCardChanged={}({}→{}), phoneChanged={}({}→{}), faceChanged={}",
|
||||
nameChanged, userDO.getName(), newName,
|
||||
idCardChanged, phoneChanged,
|
||||
nationChanged, userDO.getNation(), userDO.getNationName(), newNation, newNationName,
|
||||
idCardChanged, userDO.getUserIdCard(), newIdCard,
|
||||
phoneChanged, userDO.getPhone(), newPhone,
|
||||
faceChanged);
|
||||
if (!nameChanged && !idCardChanged && !phoneChanged && !nationChanged && !faceChanged) {
|
||||
log.info("【跳过同步大华】姓名/身份证/手机号/民族/人脸图 5项都没变化,按优化逻辑不调更新接口");
|
||||
if (!nameChanged && !idCardChanged && !phoneChanged && !faceChanged) {
|
||||
log.info("【跳过同步大华】姓名/身份证/手机号/人脸图 4项都没变化,按优化逻辑不调更新接口");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -309,17 +302,7 @@ public class UserUpdateExe {
|
|||
personMap.put("paperNumber", plainIdCard);
|
||||
personMap.put("phone", newPhone);
|
||||
personMap.put("departmentId", 1);
|
||||
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("nationName", "汉族");
|
||||
personMap.put("service", "evo-thirdParty");
|
||||
|
||||
Integer age = null;
|
||||
|
|
@ -676,9 +659,16 @@ public class UserUpdateExe {
|
|||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean updatePasswordFromApp(AppUserUpdatePassWordCmd cmd) {
|
||||
UserUpdatePassWordCmd userUpdatePassWordCmd = new UserUpdatePassWordCmd();
|
||||
BeanUtils.copyProperties(cmd, userUpdatePassWordCmd);
|
||||
executeUpdatePassword(userUpdatePassWordCmd);
|
||||
//新密码和旧密码不能相同
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -696,10 +686,6 @@ 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);
|
||||
|
|
@ -768,43 +754,6 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ import com.alibaba.cola.dto.PageResponse;
|
|||
import com.alibaba.cola.dto.Response;
|
||||
import com.alibaba.cola.dto.SingleResponse;
|
||||
import com.zcloud.basic.info.api.UserServiceI;
|
||||
import com.zcloud.basic.info.command.UserAddExe;
|
||||
import com.zcloud.basic.info.command.UserImportExe;
|
||||
import com.zcloud.basic.info.command.UserRemoveExe;
|
||||
import com.zcloud.basic.info.command.UserUpdateExe;
|
||||
import com.zcloud.basic.info.command.*;
|
||||
import com.zcloud.basic.info.command.query.UserQueryExe;
|
||||
import com.zcloud.basic.info.dto.*;
|
||||
import com.zcloud.basic.info.dto.clientobject.*;
|
||||
|
|
@ -36,7 +33,7 @@ public class UserServiceImpl implements UserServiceI {
|
|||
private final UserRemoveExe userRemoveExe;
|
||||
private final UserQueryExe userQueryExe;
|
||||
private final UserImportExe userImportExe;
|
||||
|
||||
private final HumanUserUpdateExe humanUserUpdateExe;
|
||||
@Override
|
||||
public PageResponse<UserCO> listPage(UserPageQry qry) {
|
||||
|
||||
|
|
@ -44,10 +41,15 @@ public class UserServiceImpl implements UserServiceI {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SingleResponse add(UserAddCmd cmd) {
|
||||
public SingleResponse<UserCO> add(UserAddCmd cmd) {
|
||||
|
||||
userAddExe.execute(cmd);
|
||||
return SingleResponse.buildSuccess();
|
||||
UserCO userCO = new UserCO();
|
||||
userCO.setId(cmd.getId());
|
||||
userCO.setUsername(cmd.getUsername());
|
||||
userCO.setName(cmd.getName());
|
||||
userCO.setPhone(cmd.getPhone());
|
||||
return SingleResponse.of(userCO);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -265,5 +267,20 @@ public class UserServiceImpl implements UserServiceI {
|
|||
public PageResponse<UserCO> pageByNopermission(UserPageQry qry) {
|
||||
return userQueryExe.pageByNopermission(qry);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleResponse<Long> addHumanUser(UserAddCmd cmd) {
|
||||
Long userId = userAddExe.executeHumanUser(cmd);
|
||||
return SingleResponse.of(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SingleResponse<Long> updateHumanUser(UserUpdateCmd userUpdateCmd) {
|
||||
return humanUserUpdateExe.updateHumanUser(userUpdateCmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResponse<UserCO> pageByNopermissionAll(UserPageQry qry) {
|
||||
return userQueryExe.pageByNopermissionAll(qry);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,9 @@ import java.time.LocalDate;
|
|||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserAddCmd extends Command {
|
||||
@ApiModelProperty(value = "主键id(新增时不传,保存成功后返回)", name = "id")
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "业务主键id老系统id", name = "userId")
|
||||
private String userId;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,8 +65,6 @@ public class UserUpdateCmd extends Command {
|
|||
private String userAvatarUrl;
|
||||
@ApiModelProperty(value = "人脸图片文件(取thumbUrl字段作为base64传大华)")
|
||||
private Object faceFile;
|
||||
@ApiModelProperty(value = "用户头像数组(相关方人员头像,取第一个元素的thumbUrl字段作为base64传大华,优先级高于faceFile)")
|
||||
private Object userImg;
|
||||
@ApiModelProperty(value = "现住址", name = "currentAddress")
|
||||
private String currentAddress;
|
||||
@ApiModelProperty(value = "户口所在地", name = "locationAddress")
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
|
@ -67,9 +68,7 @@ public class DaHuaConfig {
|
|||
String gw = (primeportGateway == null || primeportGateway.trim().isEmpty()) ? "basicInfo" : primeportGateway.trim();
|
||||
String url = baseUrl + "/" + gw + "/dahua/person/sync";
|
||||
String reqJson = JSONUtil.toJsonStr(personMap);
|
||||
log.info("调用大华人员同步接口, url={}, 请求参数={}", url, reqJson);
|
||||
System.out.println("调用大华人员同步接口, url=" + url);
|
||||
System.out.println("请求参数: " + reqJson);
|
||||
log.info("调用大华人员同步接口, url={}", url);
|
||||
try {
|
||||
HttpRequest request = HttpRequest.post(url)
|
||||
.header("Content-Type", "application/json;charset=UTF-8")
|
||||
|
|
@ -79,14 +78,12 @@ public class DaHuaConfig {
|
|||
extraHeaders.forEach((k, v) -> {
|
||||
if (k != null && v != null) {
|
||||
request.header(k, v);
|
||||
System.out.println("透传请求头: " + k + "=" + v);
|
||||
}
|
||||
});
|
||||
log.info("透传请求头: {}", extraHeaders);
|
||||
}
|
||||
String respBody = request.execute().body();
|
||||
log.info("大华人员同步接口返回: {}", respBody);
|
||||
System.out.println("大华人员同步接口返回: " + respBody);
|
||||
if (respBody == null || respBody.trim().isEmpty()) {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("errCode", "EMPTY_RESPONSE");
|
||||
|
|
@ -111,4 +108,84 @@ public class DaHuaConfig {
|
|||
return resultMap;
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Object> updatePerson(Map<String, Object> personMap) {
|
||||
return updatePerson(personMap, null);
|
||||
}
|
||||
|
||||
public Map<String, Object> updatePerson(Map<String, Object> personMap, Map<String, String> extraHeaders) {
|
||||
Map<String, Object> resultMap = new HashMap<>();
|
||||
log.info("========== 大华人员(更新)调用开始 ==========");
|
||||
log.info("dockFlag配置值={}, primeportUrl={}, primeportGateway={}", dockFlag, primeportUrl, primeportGateway);
|
||||
if (dockFlag == null || dockFlag != 1) {
|
||||
log.info("大华对接未开启(dockFlag={}), 跳过更新大华人员", dockFlag);
|
||||
resultMap.put("success", true);
|
||||
resultMap.put("skipped", true);
|
||||
return resultMap;
|
||||
}
|
||||
String baseUrl = primeportUrl;
|
||||
if (baseUrl == null || baseUrl.trim().isEmpty()) {
|
||||
throw new RuntimeException("大华对接网关地址未配置(dahua.config.primeportUrl)");
|
||||
}
|
||||
baseUrl = baseUrl.trim();
|
||||
if (baseUrl.endsWith("/")) {
|
||||
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
|
||||
}
|
||||
String gw = (primeportGateway == null || primeportGateway.trim().isEmpty()) ? "basicInfo" : primeportGateway.trim();
|
||||
|
||||
String url = baseUrl + "/" + gw + "/dahua/person/update";
|
||||
log.info("【实际请求URL】method=PUT, url={}", url);
|
||||
log.info("【对比-新增sync的URL】method=POST, {}/{}/dahua/person/sync", baseUrl, gw);
|
||||
|
||||
String reqJson = JSONUtil.toJsonStr(personMap);
|
||||
log.info("【传给大华的请求体(JSON)】{}", reqJson);
|
||||
log.info("【personMap关键字段】id={}, code={}, name={}, paperNumber={}, phone={}, departmentId={}, paperType={}, service={}, personBiosignatures是否有值={}",
|
||||
personMap.get("id"), personMap.get("code"), personMap.get("name"),
|
||||
personMap.get("paperNumber"), personMap.get("phone"),
|
||||
personMap.get("departmentId"), personMap.get("paperType"),
|
||||
personMap.get("service"),
|
||||
personMap.get("personBiosignatures") == null ? "null" :
|
||||
(personMap.get("personBiosignatures") instanceof List
|
||||
? "List-size=" + ((List<?>) personMap.get("personBiosignatures")).size()
|
||||
: personMap.get("personBiosignatures").getClass().getName()));
|
||||
try {
|
||||
HttpRequest request = HttpRequest.put(url)
|
||||
.header("Content-Type", "application/json;charset=UTF-8")
|
||||
.timeout(30000)
|
||||
.body(reqJson);
|
||||
if (extraHeaders != null && !extraHeaders.isEmpty()) {
|
||||
extraHeaders.forEach((k, v) -> {
|
||||
if (k != null && v != null) {
|
||||
request.header(k, v);
|
||||
}
|
||||
});
|
||||
log.info("【透传请求头】{}", extraHeaders);
|
||||
}
|
||||
String respBody = request.execute().body();
|
||||
log.info("【大华接口原始返回】{}", respBody);
|
||||
if (respBody == null || respBody.trim().isEmpty()) {
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("errCode", "EMPTY_RESPONSE");
|
||||
resultMap.put("errMessage", "大华人员更新接口返回为空");
|
||||
return resultMap;
|
||||
}
|
||||
JSONObject respJson = JSONUtil.parseObj(respBody);
|
||||
Boolean success = respJson.getBool("success", false);
|
||||
String errCode = respJson.getStr("errCode", "");
|
||||
String errMessage = respJson.getStr("errMessage", "");
|
||||
Object data = respJson.get("data");
|
||||
resultMap.put("success", success);
|
||||
resultMap.put("errCode", errCode);
|
||||
resultMap.put("errMessage", errMessage);
|
||||
resultMap.put("data", data);
|
||||
log.info("【解析后返回】success={}, errCode={}, errMessage={}, data={}", success, errCode, errMessage, data);
|
||||
return resultMap;
|
||||
} catch (Exception e) {
|
||||
log.error("调用大华人员更新接口异常: {}", e.getMessage(), e);
|
||||
resultMap.put("success", false);
|
||||
resultMap.put("errCode", "HTTP_EXCEPTION");
|
||||
resultMap.put("errMessage", "调用大华人员更新接口异常: " + e.getMessage());
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -39,6 +39,7 @@ public class UserGatewayImpl implements UserGateway {
|
|||
private UserFacade userFacade;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class, propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW)
|
||||
public Boolean add(UserE userE) {
|
||||
UserDO d = new UserDO();
|
||||
BeanUtils.copyProperties(userE, d);
|
||||
|
|
@ -48,6 +49,7 @@ public class UserGatewayImpl implements UserGateway {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class, propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW)
|
||||
public Boolean addYanshi(UserE userE) {
|
||||
UserDO d = new UserDO();
|
||||
BeanUtils.copyProperties(userE, d);
|
||||
|
|
@ -66,6 +68,7 @@ public class UserGatewayImpl implements UserGateway {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class, propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW)
|
||||
public boolean addXgf(UserE userE) {
|
||||
UserDO d = new UserDO();
|
||||
// 新增用户默认在职
|
||||
|
|
@ -264,4 +267,3 @@ public class UserGatewayImpl implements UserGateway {
|
|||
userRepository.deletedUserByPhone(phone);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,10 @@
|
|||
select
|
||||
c.corp_name as corpinfoName,
|
||||
d.name as department_name,
|
||||
p.post_name,
|
||||
CASE
|
||||
WHEN c.type IN (3,4, 5) THEN u.post_name
|
||||
ELSE p.post_name
|
||||
END AS post_name,
|
||||
u.id,
|
||||
u.user_id,
|
||||
u.username,
|
||||
|
|
@ -248,6 +251,7 @@
|
|||
u.political_affiliation_name,
|
||||
u.employment_flag,
|
||||
u.flow_flag,
|
||||
u.rz_flag,
|
||||
CASE
|
||||
WHEN LENGTH(FROM_BASE64(u.user_id_card)) > 0
|
||||
AND MOD(SUBSTRING(FROM_BASE64(u.user_id_card), 17, 1), 2) = 1 THEN
|
||||
|
|
@ -336,6 +340,8 @@
|
|||
u.is_injuries_pay_time,
|
||||
u.pay_number,
|
||||
u.is_bf,
|
||||
u.dahua_id,
|
||||
u.dahua_code,
|
||||
|
||||
CASE
|
||||
WHEN LENGTH(FROM_BASE64(u.user_id_card)) > 0
|
||||
|
|
@ -588,12 +594,93 @@
|
|||
<where>
|
||||
and ui.delete_enum = 'FALSE'
|
||||
<if test="params.urlList != null and params.urlList.size() > 0">
|
||||
and ui.user_avatar_url IN
|
||||
ui.user_avatar_url IN
|
||||
<foreach collection="params.urlList" item="url" open="(" close=")" separator=",">
|
||||
#{url}
|
||||
</foreach>
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
<update id="updateEmploymentFlagAndDeleteEnum">
|
||||
UPDATE user
|
||||
SET employment_flag = #{employmentFlag},
|
||||
delete_enum = #{deleteEnum}
|
||||
WHERE id = #{userId}
|
||||
</update>
|
||||
|
||||
<select id="pageByNopermissionAll" resultType="com.zcloud.basic.info.persistence.dataobject.UserDO">
|
||||
select
|
||||
d.name as department_name,
|
||||
CASE
|
||||
WHEN c.type IN (3,4, 5) THEN u.post_name
|
||||
ELSE p.post_name
|
||||
END AS post_name,
|
||||
c.corp_name as corpinfoName,
|
||||
u.id,
|
||||
u.user_id,
|
||||
u.username,
|
||||
u.name,
|
||||
u.corpinfo_id,
|
||||
u.main_corp_flag,
|
||||
u.user_type,
|
||||
u.department_id,
|
||||
u.post_id,
|
||||
u.role_id,
|
||||
u.email,
|
||||
u.phone,
|
||||
u.personnel_type,
|
||||
u.personnel_type_name,
|
||||
u.nation,
|
||||
u.nation_name,
|
||||
u.user_id_card,
|
||||
u.user_avatar_url,
|
||||
u.current_address,
|
||||
u.location_address,
|
||||
u.rank_level,
|
||||
u.rank_level_name,
|
||||
u.sort,
|
||||
u.version,
|
||||
u.create_id,
|
||||
u.create_name,
|
||||
u.create_time,
|
||||
u.update_id,
|
||||
u.update_name,
|
||||
u.update_time,
|
||||
u.remarks,
|
||||
u.delete_enum,
|
||||
u.tenant_id,
|
||||
u.org_id,
|
||||
u.env,
|
||||
u.department_leader_flag,
|
||||
u.deputy_leader_flag,
|
||||
u.cultural_level,
|
||||
u.cultural_level_name,
|
||||
u.marital_status,
|
||||
u.marital_status_name,
|
||||
u.political_affiliation,
|
||||
u.political_affiliation_name,
|
||||
u.employment_flag,
|
||||
u.flow_flag,
|
||||
u.rz_flag,
|
||||
CASE
|
||||
WHEN LENGTH(FROM_BASE64(u.user_id_card)) > 0
|
||||
AND MOD(SUBSTRING(FROM_BASE64(u.user_id_card), 17, 1), 2) = 1 THEN
|
||||
'男'
|
||||
WHEN LENGTH(FROM_BASE64(u.user_id_card)) > 0
|
||||
AND MOD(SUBSTRING(FROM_BASE64(u.user_id_card), 17, 1), 2) = 0 THEN
|
||||
'女'
|
||||
END AS sex,
|
||||
|
||||
CASE
|
||||
WHEN LENGTH(FROM_BASE64(u.user_id_card)) > 0 THEN
|
||||
(YEAR(NOW()) - SUBSTRING(FROM_BASE64(u.user_id_card), 7, 4)) ELSE NULL
|
||||
END AS age,
|
||||
|
||||
cast(substring(FROM_BASE64(u.user_id_card), 7, 8) AS DATE) AS birthday
|
||||
from user u
|
||||
left join corp_info c on c.id = u.corpinfo_id
|
||||
left join department d on d.id = u.department_id
|
||||
left join post p on p.id = u.post_id
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue