【登录】安眼统一认证
This commit is contained in:
+28
@@ -18,10 +18,18 @@ import java.util.List;
|
||||
public interface AnYanClient {
|
||||
/**
|
||||
* 获取服务访问令牌
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String getAuthToken();
|
||||
|
||||
/**
|
||||
* 获取服务访问令牌(密码模式)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
AuthResult getAuthTokenByPassword(String username, String password);
|
||||
|
||||
/**
|
||||
* 刷新口令
|
||||
*/
|
||||
@@ -29,6 +37,7 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 体检医院人数统计查询
|
||||
*
|
||||
* @param medicalYear 体检年份
|
||||
* @return
|
||||
*/
|
||||
@@ -36,6 +45,7 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 健康打卡数据统计查询(血压,减重,血糖)
|
||||
*
|
||||
* @param beginDate
|
||||
* @param endDate
|
||||
* @return
|
||||
@@ -44,6 +54,7 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 健康打卡异常数据详细查询(血压)
|
||||
*
|
||||
* @param healthSignListParam
|
||||
* @return
|
||||
*/
|
||||
@@ -51,6 +62,7 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 健康打卡异常数据详细查询(减重)
|
||||
*
|
||||
* @param healthSignListParam
|
||||
* @return
|
||||
*/
|
||||
@@ -58,6 +70,7 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 健康打卡异常数据详细查询(血糖)
|
||||
*
|
||||
* @param healthSignListParam
|
||||
* @return
|
||||
*/
|
||||
@@ -65,18 +78,21 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 油田医院数据查询
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<HospitalListVO> hospitalList();
|
||||
|
||||
/**
|
||||
* 健康小屋基础数据查询
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<HealthRoomBaseVO> healthPlaceHomList();
|
||||
|
||||
/**
|
||||
* 健康小屋详细数据查询
|
||||
*
|
||||
* @param healthRoomDTO
|
||||
* @return
|
||||
*/
|
||||
@@ -84,6 +100,7 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 当年体检异常人数统计
|
||||
*
|
||||
* @param medicalYear 年份
|
||||
* @return
|
||||
*/
|
||||
@@ -91,6 +108,7 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 当年体检异常人员列表
|
||||
*
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
@@ -98,13 +116,23 @@ public interface AnYanClient {
|
||||
|
||||
/**
|
||||
* 公网环境获取服务访问token (目前仅用于访问安眼大屏)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String publicNetworkToken();
|
||||
|
||||
/**
|
||||
* 公网环境获取服务访问token (目前仅用于访问安眼大屏, 不走缓存, 每次用现取)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
AuthResult publicNetworkTokenNoCache();
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
AnYanUserInfoResult getAnYanUserInfo(String token);
|
||||
}
|
||||
|
||||
+62
-2
@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@@ -20,6 +21,7 @@ import com.renkang.anyan.utils.PageResultToBeanUtil;
|
||||
import com.renkang.anyan.utils.SM4Utils;
|
||||
import com.renkang.anyan.utils.StringUtils;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||
import org.jeecg.util.RedisClientUtil;
|
||||
@@ -31,9 +33,13 @@ import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.retry.annotation.EnableRetry;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.HttpClientErrorException;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -43,6 +49,7 @@ import java.util.stream.Collectors;
|
||||
* @Date: 2025-8-1
|
||||
* @Version: V1.0
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@EnableRetry
|
||||
@RequiredArgsConstructor
|
||||
@@ -81,6 +88,42 @@ public class AnYanClientExecutor implements AnYanClient {
|
||||
return new AuthResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 通过密码获取令牌
|
||||
* @author PengJ
|
||||
* @date 2025/10/24 11:15
|
||||
*/
|
||||
@Override
|
||||
public AuthResult getAuthTokenByPassword(String username, String password) {
|
||||
try {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
formData.add("grant_type", "password");
|
||||
formData.add("username", username);
|
||||
formData.add("password", password);
|
||||
formData.add("client_id", anYanProperties.getClientId());
|
||||
formData.add("client_secret", anYanProperties.getClientSecret());
|
||||
ResponseEntity<AuthResult> authResult = RestTemplateUtil.postExchangeForGetTokenByPassword(AnYanApiEnum.QUERY_AUTH_TOKEN, formData, headers, AuthResult.class);
|
||||
if (HttpStatus.OK.equals(authResult.getStatusCode())
|
||||
&& ObjectUtils.isNotEmpty(authResult.getBody())) {
|
||||
return authResult.getBody();
|
||||
} else {
|
||||
log.error("------安眼系统获取token失败(密码模式){}------", authResult.getBody());
|
||||
ExceptionAssertsUtil.fail("------安眼系统获取token失败------" + authResult.getBody());
|
||||
return null;
|
||||
}
|
||||
} catch (HttpClientErrorException e) {
|
||||
String replace = Objects.requireNonNull(e.getMessage()).replace("401 Unauthorized: ", "");
|
||||
replace = replace.replace("\"", "");
|
||||
AuthResult bean = JSONUtil.toBean(replace, AuthResult.class);
|
||||
ExceptionAssertsUtil.fail(bean.getMessage());
|
||||
} catch (Exception e) {
|
||||
ExceptionAssertsUtil.fail(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshToken() {
|
||||
AuthResult authResult = getAuthTokenExecutor();
|
||||
@@ -99,7 +142,9 @@ public class AnYanClientExecutor implements AnYanClient {
|
||||
@Override
|
||||
@Retryable(maxAttempts = 2)
|
||||
public List<MedicalPeopleNumStatisticsVO> examinationStatistics(Integer medicalYear) {
|
||||
if(null == medicalYear){ medicalYear = DateUtil.year(new Date()); }
|
||||
if (null == medicalYear) {
|
||||
medicalYear = DateUtil.year(new Date());
|
||||
}
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("medicalYear", String.valueOf(medicalYear));
|
||||
AnYanResult<Object> result = RestTemplateUtil.postExchange(AnYanApiEnum.HEALTH_EXAMINATION_STATISTICS, buildTokenHeader(), param);
|
||||
@@ -164,7 +209,9 @@ public class AnYanClientExecutor implements AnYanClient {
|
||||
@Override
|
||||
@Retryable(maxAttempts = 2)
|
||||
public MedicalAbnormalStatisticsVO medicalAbnormalStatistics(Integer medicalYear) {
|
||||
if(null == medicalYear){ medicalYear = DateUtil.year(new Date()); }
|
||||
if (null == medicalYear) {
|
||||
medicalYear = DateUtil.year(new Date());
|
||||
}
|
||||
JSONObject param = new JSONObject();
|
||||
param.put("medicalYear", medicalYear);
|
||||
AnYanResult<Object> result = RestTemplateUtil.postExchange(AnYanApiEnum.MEDICAL_ABNORMAL_STATISTICS, buildTokenHeader(), param);
|
||||
@@ -223,4 +270,17 @@ public class AnYanClientExecutor implements AnYanClient {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 根据token获取用户信息
|
||||
* @author PengJ
|
||||
* @date 2025/10/24 17:00
|
||||
*/
|
||||
@Override
|
||||
public AnYanUserInfoResult getAnYanUserInfo(String token) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(AnYanConstants.AUTHORIZATION, AnYanConstants.TOKEN_TYPE + token);
|
||||
ResponseEntity<AnYanUserInfoResult> exchange = RestTemplateUtil.getExchange(AnYanApiEnum.USER_INFO_UNIT_V2, headers, AnYanUserInfoResult.class);
|
||||
return BeanUtil.toBean(exchange.getBody(), AnYanUserInfoResult.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+20
-2
@@ -2,6 +2,7 @@ package com.renkang.restaurant.config;
|
||||
|
||||
import com.renkang.anyan.client.AnYanClient;
|
||||
import com.renkang.anyan.config.AnYanProperties;
|
||||
import com.renkang.anyan.enums.AnYanApiEnum;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||
@@ -12,6 +13,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.http.converter.FormHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
@@ -20,6 +22,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @Description: AnYanClient xj安眼系统接口调用客户端
|
||||
@@ -39,7 +42,11 @@ public class AnYanRestTemplateConfig {
|
||||
return new RestTemplateBuilder()
|
||||
.setConnectTimeout(Duration.of(properties.getTimeout(), ChronoUnit.MILLIS))
|
||||
.setReadTimeout(Duration.of(properties.getReadTimeout(), ChronoUnit.MILLIS))
|
||||
.additionalMessageConverters(new StringHttpMessageConverter(StandardCharsets.UTF_8), new MappingJackson2HttpMessageConverter())
|
||||
.additionalMessageConverters(
|
||||
new StringHttpMessageConverter(StandardCharsets.UTF_8),
|
||||
new MappingJackson2HttpMessageConverter(),
|
||||
new FormHttpMessageConverter()
|
||||
)
|
||||
.additionalInterceptors(authInterceptor)
|
||||
.build();
|
||||
}
|
||||
@@ -48,12 +55,23 @@ public class AnYanRestTemplateConfig {
|
||||
* 自定义拦截器处理接口鉴权失败, 配合spring retry使用从而避免因token失效导致的接口调用失败
|
||||
*/
|
||||
public ClientHttpRequestInterceptor authInterceptor() {
|
||||
// 添加重试次数限制
|
||||
AtomicInteger retryCount = new AtomicInteger(0);
|
||||
int maxRetries = 5;
|
||||
return (httpRequest, bytes, clientHttpRequestExecution) -> {
|
||||
ClientHttpResponse execute;
|
||||
try {
|
||||
// 获取请求URL
|
||||
String url = httpRequest.getURI().toString();
|
||||
// 排除特定接口不执行拦截逻辑
|
||||
boolean shouldSkip = url.contains(AnYanApiEnum.QUERY_AUTH_TOKEN.getMethodPath());
|
||||
execute = clientHttpRequestExecution.execute(httpRequest, bytes);
|
||||
if (shouldSkip) {
|
||||
return execute;
|
||||
}
|
||||
HttpStatus httpStatus = execute.getStatusCode();
|
||||
if (Arrays.asList(HttpStatus.UNAUTHORIZED,HttpStatus.FORBIDDEN).contains(httpStatus)) {
|
||||
if (Arrays.asList(HttpStatus.UNAUTHORIZED, HttpStatus.FORBIDDEN).contains(httpStatus)
|
||||
&& retryCount.getAndIncrement() < maxRetries) {
|
||||
SpringContextUtils.getBean("anYanClientExecutor", AnYanClient.class).refreshToken();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
+34
@@ -9,6 +9,7 @@ import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.Objects;
|
||||
@@ -40,6 +41,7 @@ public class RestTemplateUtil {
|
||||
|
||||
/**
|
||||
* 请求接口访问 token
|
||||
*
|
||||
* @param api 接口
|
||||
* @param requestBody 参数
|
||||
* @return ResponseEntity
|
||||
@@ -50,8 +52,25 @@ public class RestTemplateUtil {
|
||||
return getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 公网请求接口访问 token(密码模式)
|
||||
*
|
||||
* @param api 接口
|
||||
* @param formData 参数
|
||||
* @return ResponseEntity
|
||||
*/
|
||||
public static <T> ResponseEntity<T> postExchangeForGetTokenByPassword(AnYanApiEnum api, MultiValueMap<String, String> formData, HttpHeaders headers, Class<T> responseType) {
|
||||
String url = getProperties().getPublicHost() + api.getMethodPath();
|
||||
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
|
||||
log.info("开始发送请求到: {}", url);
|
||||
ResponseEntity<T> response = getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType);
|
||||
log.info("收到响应: {}", response);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公网请求接口访问 token
|
||||
*
|
||||
* @param api 接口
|
||||
* @param requestBody 参数
|
||||
* @return ResponseEntity
|
||||
@@ -64,6 +83,7 @@ public class RestTemplateUtil {
|
||||
|
||||
/**
|
||||
* 通用调用方法
|
||||
*
|
||||
* @param api 请求接口
|
||||
* @param headers 请求头
|
||||
* @param requestBody body参数
|
||||
@@ -75,8 +95,22 @@ public class RestTemplateUtil {
|
||||
return responseHandler(getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, AnYanResult.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用调用方法
|
||||
*
|
||||
* @param api 请求接口
|
||||
* @param headers 请求头
|
||||
* @return Result对象
|
||||
*/
|
||||
public static <T> ResponseEntity<T> getExchange(AnYanApiEnum api, HttpHeaders headers, Class<T> responseType) {
|
||||
String url = getProperties().getHost() + api.getMethodPath() + api.getMethodParam();
|
||||
HttpEntity<Object> requestEntity = new HttpEntity<>(headers);
|
||||
return getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType);
|
||||
}
|
||||
|
||||
/**
|
||||
* ResponseEntity 转 Result
|
||||
*
|
||||
* @param entity
|
||||
* @return
|
||||
*/
|
||||
|
||||
+8
-1
@@ -2,6 +2,7 @@ package com.renkang.anyan.enums;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
/**
|
||||
* @Description: AnYanApiEnum xj安眼系统接口枚举类
|
||||
* @Author: feng
|
||||
@@ -68,7 +69,13 @@ public enum AnYanApiEnum {
|
||||
/**
|
||||
* 12.从外网地址获取安眼token接口
|
||||
*/
|
||||
PUBLIC_NETWORK_AUTH_TOKEN("/aygc-service-sys/0/api/xj/outside/getToken","", HttpMethod.POST);
|
||||
PUBLIC_NETWORK_AUTH_TOKEN("/aygc-service-sys/0/api/xj/outside/getToken", "", HttpMethod.POST),
|
||||
|
||||
/**
|
||||
* 13.获取员工信息及单位-V2
|
||||
*/
|
||||
USER_INFO_UNIT_V2("/iosp-iam/v2/users/self", "?containsUnit=true", HttpMethod.GET),
|
||||
;
|
||||
|
||||
/**
|
||||
* 接口路径
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.renkang.anyan.model.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author PengJ
|
||||
* @description: 密码鉴权入参
|
||||
* @date 2025/10/24 11:04
|
||||
*/
|
||||
@Data
|
||||
public class AuthByPasswordParam {
|
||||
/**
|
||||
* grant_type
|
||||
*/
|
||||
private String grant_type = "password";
|
||||
/**
|
||||
* username
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* password
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* client_id
|
||||
*/
|
||||
private String client_id;
|
||||
/**
|
||||
* client_secret
|
||||
*/
|
||||
private String client_secret;
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
package com.renkang.anyan.model.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author Huawei
|
||||
* @version 1.0
|
||||
* @description: TODO
|
||||
* @date 2025/10/24 16:59
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public class AnYanUserInfoResult {
|
||||
@JsonProperty("id")
|
||||
private String id;
|
||||
@JsonProperty("loginName")
|
||||
private String loginName;
|
||||
@JsonProperty("email")
|
||||
private String email;
|
||||
@JsonProperty("organizationId")
|
||||
private Integer organizationId;
|
||||
@JsonProperty("realName")
|
||||
private String realName;
|
||||
@JsonProperty("phone")
|
||||
private String phone;
|
||||
@JsonProperty("gender")
|
||||
private Integer gender;
|
||||
@JsonProperty("tenantName")
|
||||
private String tenantName;
|
||||
@JsonProperty("tenantNum")
|
||||
private String tenantNum;
|
||||
@JsonProperty("roleMergeFlag")
|
||||
private Integer roleMergeFlag;
|
||||
@JsonProperty("tenantId")
|
||||
private Integer tenantId;
|
||||
@JsonProperty("currentRoleId")
|
||||
private String currentRoleId;
|
||||
@JsonProperty("currentRoleCode")
|
||||
private String currentRoleCode;
|
||||
@JsonProperty("currentRoleName")
|
||||
private String currentRoleName;
|
||||
@JsonProperty("currentRoleLevel")
|
||||
private String currentRoleLevel;
|
||||
@JsonProperty("employeeUnitDTO")
|
||||
private EmployeeUnitDTO employeeUnitDTO;
|
||||
|
||||
@NoArgsConstructor
|
||||
@Data
|
||||
public static class EmployeeUnitDTO {
|
||||
|
||||
/**
|
||||
* 职工编号
|
||||
*/
|
||||
@JsonProperty("employeeNum")
|
||||
private String employeeNum;
|
||||
|
||||
/**
|
||||
* 姓名
|
||||
*/
|
||||
@JsonProperty("name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
@JsonProperty("email")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 手机
|
||||
*/
|
||||
@JsonProperty("mobile")
|
||||
private String mobile;
|
||||
|
||||
/**
|
||||
* 性别
|
||||
*/
|
||||
@JsonProperty("gender")
|
||||
private Integer gender;
|
||||
@JsonProperty("status")
|
||||
private Object status;
|
||||
|
||||
/**
|
||||
* 启用状态
|
||||
*/
|
||||
@JsonProperty("enabledFlag")
|
||||
private String enabledFlag;
|
||||
@JsonProperty("unitName")
|
||||
private String unitName;
|
||||
|
||||
/**
|
||||
* 所属二级单位unitCode
|
||||
*/
|
||||
@JsonProperty("unitCode")
|
||||
private String unitCode;
|
||||
|
||||
/**
|
||||
* 科级单位名称
|
||||
*/
|
||||
@JsonProperty("sectionUnitName")
|
||||
private String sectionUnitName;
|
||||
|
||||
/**
|
||||
* 科级单位unitCode
|
||||
*/
|
||||
@JsonProperty("sectionUnitCode")
|
||||
private String sectionUnitCode;
|
||||
@JsonProperty("directDepartmentName")
|
||||
private String directDepartmentName;
|
||||
|
||||
/**
|
||||
* 直属部门unitCode
|
||||
*/
|
||||
@JsonProperty("directDepartmentCode")
|
||||
private String directDepartmentCode;
|
||||
|
||||
/**
|
||||
* 层级路径(unitCode拼接)
|
||||
*/
|
||||
@JsonProperty("levelPath")
|
||||
private String levelPath;
|
||||
|
||||
/**
|
||||
* 完整组织机构路径(unitName拼接)
|
||||
*/
|
||||
@JsonProperty("unitNamePath")
|
||||
private String unitNamePath;
|
||||
|
||||
/**
|
||||
* 固定电话
|
||||
*/
|
||||
@JsonProperty("attribute1")
|
||||
private String attribute1;
|
||||
|
||||
/**
|
||||
* 职务
|
||||
*/
|
||||
@JsonProperty("attribute2")
|
||||
private String attribute2;
|
||||
|
||||
/**
|
||||
* 生日或年龄
|
||||
*/
|
||||
@JsonProperty("attribute3")
|
||||
private Object attribute3;
|
||||
}
|
||||
}
|
||||
+8
@@ -28,4 +28,12 @@ public class AuthResult {
|
||||
* satoken
|
||||
*/
|
||||
private String satoken;
|
||||
/**
|
||||
* message
|
||||
*/
|
||||
private String message;
|
||||
/**
|
||||
* success
|
||||
*/
|
||||
private boolean success;
|
||||
}
|
||||
|
||||
@@ -87,9 +87,11 @@ public class ShiroConfig {
|
||||
filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
|
||||
filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
|
||||
filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
|
||||
filterChainDefinitionMap.put("/sys/loginAnYan", "anon"); //登录接口排除(三方授权)
|
||||
filterChainDefinitionMap.put("/sys/loginDoctor", "anon"); //登录接口排除
|
||||
filterChainDefinitionMap.put("/conDoctor/loginDoctor", "anon"); //登录接口排除
|
||||
filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
|
||||
filterChainDefinitionMap.put("/sys/mLoginAnYan", "anon"); //登录接口排除(三方授权)
|
||||
filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
|
||||
filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录
|
||||
filterChainDefinitionMap.put("/sys/exchangeToken", "anon"); // 食堂token置换
|
||||
|
||||
@@ -80,6 +80,10 @@
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>health-watch-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.renkang</groupId>
|
||||
<artifactId>xj-anyan-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
+17
-57
@@ -5,7 +5,6 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.xkcoding.http.util.StringUtil;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -40,15 +39,16 @@ import org.jeecg.modules.system.bean.request.QueryWeightMaxParam;
|
||||
import org.jeecg.modules.system.bean.request.QueryqueryGroupAParam;
|
||||
import org.jeecg.modules.system.bean.request.UserFilter;
|
||||
import org.jeecg.modules.system.entity.HealthUserEmployeeEx;
|
||||
import org.jeecg.modules.system.entity.SysDepart;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.entity.SysUserDepartChangeApply;
|
||||
import org.jeecg.modules.system.manager.DictCacheManager;
|
||||
import org.jeecg.modules.system.manager.UserCacheManager;
|
||||
import org.jeecg.modules.system.service.IHealthUserEmployeeExService;
|
||||
import org.jeecg.modules.system.service.ISysUserDepartChangeApplyService;
|
||||
import org.jeecg.modules.system.service.ISysUserService;
|
||||
import org.jeecg.modules.system.vo.*;
|
||||
import org.jeecg.modules.system.vo.ItemVo;
|
||||
import org.jeecg.modules.system.vo.NoSelfManagerUser;
|
||||
import org.jeecg.modules.system.vo.SysDepartVo;
|
||||
import org.jeecg.modules.system.vo.UserEmployeeImportVo;
|
||||
import org.jeecg.redis.RedisStreamKeyEnum;
|
||||
import org.jeecg.redis.RedisStreamUtil;
|
||||
import org.jeecg.util.AsyncUtils;
|
||||
@@ -154,6 +154,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
* 1.因feign调用无法接收IPage接口类修饰的数据此接口换成实现类Page
|
||||
* 2.更明确的传参方式声明,所有参数统一使用RequestParam传参(feign调用须指明传参方式)
|
||||
* 3.该接口不支持获取员工信息中的家庭成员数量
|
||||
*
|
||||
* @return 带分页的员工列表
|
||||
*/
|
||||
@Operation(summary = "feign服务间调用员工分页列表", description = "feign服务间调用员工分页列表", hidden = true)
|
||||
@@ -204,25 +205,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
@RequiresPermissions("system:health_user_employee_ex:add")
|
||||
@PostMapping(value = "/add")
|
||||
public Result<String> add(@RequestBody @Validated UserEmployee userEmployee) {
|
||||
// 密码解密
|
||||
String key = RSAEncryptUtils.decrypt1(userEmployee.getPassword(), CommonConstant.PRIVATE_KEY);
|
||||
String s = CheckPasswordUtil.checkPasswordRule(key);
|
||||
if (StrUtil.isNotBlank(s)) {
|
||||
return Result.error(s);
|
||||
}
|
||||
userEmployee.setPassword(key);
|
||||
boolean success = healthUserEmployeeExService.saveAndUser(userEmployee);
|
||||
if (success) {
|
||||
if (!GlobalUtils.isQh()) {
|
||||
redisStreamUtil.add(RedisStreamKeyEnum.EMPLOYEE_ASYNC_ADD, userEmployee);
|
||||
}
|
||||
// 添加缓存
|
||||
AsyncUtils.execute(asyncTaskExecutor, ClientSignThreadLocal.getClientSignThreadLocal(),
|
||||
() -> userCacheManager.addUser(empConvertUser(userEmployee)));
|
||||
return Result.ok("添加成功");
|
||||
} else {
|
||||
return Result.error("添加失败");
|
||||
}
|
||||
return healthUserEmployeeExService.addUserInfo(userEmployee);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,42 +244,9 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
@RequiresPermissions("system:health_user_employee_ex:edit")
|
||||
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})
|
||||
public Result<String> edit(@RequestBody UserEmployee userEmployee) {
|
||||
//通过userId获取用户修改前的部门信息
|
||||
SysUser sysUser = sysUserService.getUserById(userEmployee.getId());
|
||||
userEmployee.setPassword(null);
|
||||
//获取登录人信息
|
||||
LoginUser loginUser = GlobalUtils.getLoginUser();
|
||||
boolean success = healthUserEmployeeExService.updateByIdAndUser(userEmployee);
|
||||
if (success) {
|
||||
//编辑成功之后新增部门迁移列表
|
||||
//若原有的部门跟编辑不一样则新增迁移列表,反之不用
|
||||
if (Objects.nonNull(sysUser) && Objects.nonNull(sysUser.getDepart())
|
||||
&&!sysUser.getDepart().getOrgCode().equals(userEmployee.getOrgCode())){
|
||||
SysUserDepartChangeApply departChangeApply = healthUserEmployeeExService.addUserDepartChange(sysUser, loginUser);
|
||||
SysDepart sysDepart = sysCache.getDepartByOrgCode(userEmployee.getOrgCode());
|
||||
departChangeApply.setToDepartId(sysDepart.getId());//迁入部门id
|
||||
departChangeApply.setToDepartCode(userEmployee.getOrgCode());//迁入部门code
|
||||
departChangeApply.setMemo("用户编辑数据");
|
||||
sysUserDepartChangeApplyService.save(departChangeApply);
|
||||
}
|
||||
if (!GlobalUtils.isQh()) {
|
||||
redisStreamUtil.add(RedisStreamKeyEnum.EMPLOYEE_ASYNC_EDIT, userEmployee);
|
||||
}
|
||||
// 编辑缓存
|
||||
AsyncUtils.execute(asyncTaskExecutor, ClientSignThreadLocal.getClientSignThreadLocal(), () -> {
|
||||
userCacheManager.updateUser(empConvertUser(userEmployee));
|
||||
// 刷新用户缓存信息
|
||||
userCacheManager.updateUserCache(userEmployee.getId());
|
||||
});
|
||||
|
||||
String orgCode = userEmployee.getOrgCode();
|
||||
if(StringUtil.isNotEmpty(orgCode)){
|
||||
sendUpdateMsgToRedisStream(userEmployee.getId(),orgCode);
|
||||
}
|
||||
return Result.ok("编辑成功");
|
||||
} else {
|
||||
return Result.error("编辑失败");
|
||||
}
|
||||
return healthUserEmployeeExService.updateUserInfo(userEmployee, loginUser);
|
||||
}
|
||||
|
||||
private void sendUpdateMsgToRedisStream(String userId, String orgCode) {
|
||||
@@ -501,6 +451,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
mv.addObject(NormalExcelConstants.MAP_LIST, mapList);
|
||||
return mv;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过excel导入数据
|
||||
*
|
||||
@@ -564,8 +515,10 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
healthUserEmployeeExService.updateUserItem(infoId);
|
||||
return Result.OK("开始更新数据并导入数据");
|
||||
}
|
||||
|
||||
/**
|
||||
* 员工更新单位模版下载
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/departTemp")
|
||||
@@ -645,6 +598,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
healthUserEmployeeExService.updateUserDepart(infoId);
|
||||
return Result.OK("开始更新数据并导入数据");
|
||||
}
|
||||
|
||||
private void delCacheBatch(List<SysUser> users) {
|
||||
if (CollectionUtil.isEmpty(users)) {
|
||||
return;
|
||||
@@ -684,6 +638,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
|
||||
/**
|
||||
* 员工-分页列表查询 筛选用
|
||||
*
|
||||
* @param userFilter
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
@@ -705,6 +660,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
/**
|
||||
* 医疗点业务员工分页列表(目前用于服务间调用)
|
||||
* ps: 获取未分配医疗点的员工列表 , 调用方需处理数据权限的问题
|
||||
*
|
||||
* @return 带分页的员工列表
|
||||
*/
|
||||
@Operation(summary = "医疗点业务员工分页列表(目前用于服务间调用)", description = "医疗点业务员工分页列表(目前用于服务间调用)", hidden = true)
|
||||
@@ -715,6 +671,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
|
||||
/**
|
||||
* 通过ID获取员工常用的基本信息(适合业务服务种员工信息补全) 目前适用于业务服务种feign调用
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@@ -726,6 +683,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
|
||||
/**
|
||||
* 通过民族、政治面貌、岗位层级、婚姻状况、健康现状查询员工基本信息 (适合业务服务种员工信息补全) 目前适用于业务服务种feign调用
|
||||
*
|
||||
* @param healthUserEmployeeEx
|
||||
* @return
|
||||
*/
|
||||
@@ -738,6 +696,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
|
||||
/**
|
||||
* 通过ID获取员工常用的基本信息(适合业务服务种员工信息补全) 目前适用于业务服务种feign调用
|
||||
*
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@@ -755,6 +714,7 @@ public class HealthUserEmployeeExController extends JeecgController<HealthUserEm
|
||||
|
||||
/**
|
||||
* 移动端用户获取身高体重
|
||||
*
|
||||
* @param userFlag 不传从token中取ID, 传了就用用户标识,可传身份证和ID(适用于食堂接口的用户身高体重数据补全)
|
||||
* @return
|
||||
*/
|
||||
|
||||
+49
-154
@@ -1,6 +1,5 @@
|
||||
package org.jeecg.modules.system.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@@ -13,7 +12,6 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresRoles;
|
||||
import org.jeecg.base.UserBase;
|
||||
@@ -28,9 +26,10 @@ import org.jeecg.common.util.encryption.EncryptedString;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.global.GlobalUtils;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.manager.ISysCache;
|
||||
import org.jeecg.modules.system.entity.*;
|
||||
import org.jeecg.modules.system.mapper.SysUserRoleMapper;
|
||||
import org.jeecg.modules.system.entity.SysDepart;
|
||||
import org.jeecg.modules.system.entity.SysRoleIndex;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.entity.SysUserPost;
|
||||
import org.jeecg.modules.system.model.SysLoginModel;
|
||||
import org.jeecg.modules.system.service.*;
|
||||
import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
|
||||
@@ -49,7 +48,6 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author scott
|
||||
@@ -74,26 +72,24 @@ public class LoginController {
|
||||
@Autowired
|
||||
private ISysDepartService sysDepartService;
|
||||
@Autowired
|
||||
private ISysTenantService sysTenantService;
|
||||
@Autowired
|
||||
private ISysDictService sysDictService;
|
||||
@Resource
|
||||
private BaseCommonService baseCommonService;
|
||||
@Autowired
|
||||
private JeecgBaseConfig jeecgBaseConfig;
|
||||
@Autowired
|
||||
private SysUserRoleMapper sysUserRoleMapper;
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
@Autowired
|
||||
private ISysCache sysCache;
|
||||
@Autowired
|
||||
private ISysUserDeviceService sysUserDeviceService;
|
||||
@Autowired
|
||||
private ISysUserPostService sysUserPostService;
|
||||
@Autowired
|
||||
private TaskExecutor taskExecutor;
|
||||
|
||||
@Autowired
|
||||
private ILoginAnYanService iLoginService;
|
||||
|
||||
@Autowired
|
||||
private LoginService loginService;
|
||||
|
||||
@Operation(summary = "登录接口")
|
||||
@RequestMapping(value = "/login", method = RequestMethod.POST)
|
||||
public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel) {
|
||||
@@ -144,7 +140,7 @@ public class LoginController {
|
||||
boolean qh = GlobalUtils.isQh();
|
||||
SysUser sysUser = sysUserService.getUserByNameOrWorkNoOrMobile(username, password, null);
|
||||
if (sysUser == null) {
|
||||
addLoginFailOvertimes(username);
|
||||
loginService.addLoginFailOvertimes(username);
|
||||
result.error500("账号或密码错误");
|
||||
return result;
|
||||
}
|
||||
@@ -161,7 +157,7 @@ public class LoginController {
|
||||
}
|
||||
|
||||
// 用户角色信息
|
||||
handleUserRoles(sysUser);
|
||||
loginService.handleUserRoles(sysUser);
|
||||
// 用户岗位信息
|
||||
if (!qh) {
|
||||
SysUserPost sysUserPost = sysUserPostService.getById(sysUser.getId());
|
||||
@@ -170,7 +166,7 @@ public class LoginController {
|
||||
}
|
||||
}
|
||||
// 用户管理部门
|
||||
handleUserDepartCodes(sysUser);
|
||||
loginService.handleUserDepartCodes(sysUser);
|
||||
//用户登录信息
|
||||
userInfo(sysUser, result);
|
||||
//update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
|
||||
@@ -188,6 +184,27 @@ public class LoginController {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 安眼统一认证(pc端)
|
||||
* @author PengJ
|
||||
* @date 2025/10/24 13:39
|
||||
*/
|
||||
@Operation(summary = "安眼统一认证(pc端)")
|
||||
@RequestMapping(value = "/loginAnYan", method = RequestMethod.POST)
|
||||
public Result<JSONObject> loginAnYan(@RequestBody SysLoginModel sysLoginModel) {
|
||||
return iLoginService.loginAnYan(sysLoginModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 安眼统一认证(移动端)
|
||||
* @author PengJ
|
||||
* @date 2025/10/24 13:39
|
||||
*/
|
||||
@Operation(summary = "安眼统一认证(移动端)")
|
||||
@RequestMapping(value = "/mLoginAnYan", method = RequestMethod.POST)
|
||||
public Result<JSONObject> mLoginAnYan(@RequestBody SysLoginModel sysLoginModel) {
|
||||
return iLoginService.mLoginAnYan(sysLoginModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 医护人员登录接口
|
||||
@@ -198,7 +215,7 @@ public class LoginController {
|
||||
@PostMapping(value = "medicalStaffLogin")
|
||||
public Result<JSONObject> medicalStaffLogin(@RequestBody SysLoginModel sysLoginModel) {
|
||||
// 验证码校验
|
||||
boolean checkCode = checkVerificationCode(sysLoginModel.getCaptcha(), sysLoginModel.getCheckKey());
|
||||
boolean checkCode = loginService.checkVerificationCode(sysLoginModel.getCaptcha(), sysLoginModel.getCheckKey());
|
||||
if (!checkCode) {
|
||||
// 改成特殊的code 便于前端判断
|
||||
return Result.error(HttpStatus.PRECONDITION_FAILED.value(), "验证码错误");
|
||||
@@ -230,16 +247,16 @@ public class LoginController {
|
||||
}
|
||||
|
||||
// 角色信息
|
||||
handleUserRoles(sysUser);
|
||||
loginService.handleUserRoles(sysUser);
|
||||
// 管理部门
|
||||
handleUserDepartCodes(sysUser);
|
||||
loginService.handleUserDepartCodes(sysUser);
|
||||
|
||||
// 生成token
|
||||
String token = JwtUtil.sign(sysUser);
|
||||
// 缓存redis以及设置token过去时间
|
||||
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
|
||||
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
|
||||
cacheLoginUserInfo(username, sysUser, "登录成功[医护人员]!");
|
||||
loginService.cacheLoginUserInfo(username, sysUser, "登录成功[医护人员]!");
|
||||
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("token", token);
|
||||
@@ -247,53 +264,6 @@ public class LoginController {
|
||||
return Result.OK("登录成功", obj);
|
||||
}
|
||||
|
||||
private boolean checkVerificationCode(String captcha, String checkKey) {
|
||||
// 验证码校验
|
||||
if (StrUtil.isBlank(captcha) || StrUtil.isBlank(checkKey)) {
|
||||
return false;
|
||||
}
|
||||
String lowerCaseCaptcha = captcha.toLowerCase();
|
||||
String origin = lowerCaseCaptcha + checkKey + jeecgBaseConfig.getSignatureSecret();
|
||||
String realKey = Md5Util.md5Encode(origin, "utf-8");
|
||||
Object checkCode = redisUtil.get(realKey);
|
||||
if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {
|
||||
log.warn("验证码错误,key= {} , Ui checkCode= {}, Redis checkCode = {}", checkKey, lowerCaseCaptcha, checkCode);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void cacheLoginUserInfo(String username, SysUser sysUser, String loginSuccessTips) {
|
||||
if (StrUtil.isBlank(username) || sysUser == null) {
|
||||
return;
|
||||
}
|
||||
redisUtil.del(CommonConstant.LOGIN_FAIL + username);
|
||||
LoginUser loginUser = new LoginUser();
|
||||
sysUser.setClient(GlobalUtils.loginClient());
|
||||
BeanUtils.copyProperties(sysUser, loginUser);
|
||||
baseCommonService.addLog("用户名: " + username + "," + loginSuccessTips, CommonConstant.LOG_TYPE_1, null, loginUser);
|
||||
Cache cache = cacheManager.getCache(CacheConstant.SYS_USERS_CACHE);
|
||||
if (Objects.nonNull(cache)) {
|
||||
cache.put(sysUser.getId(), loginUser);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleUserRoles(SysUser user) {
|
||||
if (ObjectUtil.isNull(user)) {
|
||||
return;
|
||||
}
|
||||
List<SysRole> list = sysUserRoleMapper.getUserRolesByUserId(user.getId());
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String roleCodes = list.stream().map(SysRole::getRoleCode)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.joining(","));
|
||||
user.setRoleCodes(roleCodes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 【vue3专用】获取用户信息
|
||||
*/
|
||||
@@ -321,7 +291,7 @@ public class LoginController {
|
||||
//update-begin---author:liusq ---date:2022-06-29 for:接口返回值修改,同步修改这里的判断逻辑-----------
|
||||
//update-end---author:scott ---date::2022-06-20 for:vue3前端,支持自定义首页--------------
|
||||
// 用户角色
|
||||
handleUserRoles(sysUser);
|
||||
loginService.handleUserRoles(sysUser);
|
||||
sysUser.setClient(GlobalUtils.loginClient());
|
||||
obj.put("userInfo", sysUser);
|
||||
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
|
||||
@@ -578,7 +548,7 @@ public class LoginController {
|
||||
//update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
|
||||
if (!smscode.equals(code)) {
|
||||
//update-begin-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
addLoginFailOvertimes(phone);
|
||||
loginService.addLoginFailOvertimes(phone);
|
||||
//update-end-author:taoyan date:2022-11-7 for: issues/4109 平台用户登录失败锁定用户
|
||||
result.setMessage("手机验证码错误");
|
||||
return result;
|
||||
@@ -742,7 +712,7 @@ public class LoginController {
|
||||
// personType=1 员工
|
||||
SysUser sysUser = sysUserService.getUserByNameOrWorkNoOrMobile(username, password, null);
|
||||
if (sysUser == null) {
|
||||
addLoginFailOvertimes(username);
|
||||
loginService.addLoginFailOvertimes(username);
|
||||
result.error500("账号或密码错误");
|
||||
return result;
|
||||
}
|
||||
@@ -800,9 +770,9 @@ public class LoginController {
|
||||
//5. 设置登录用户信息
|
||||
obj.put("userInfo", sysUser);
|
||||
// 用户角色
|
||||
handleUserRoles(sysUser);
|
||||
loginService.handleUserRoles(sysUser);
|
||||
// 用户管理部门
|
||||
handleUserDepartCodes(sysUser);
|
||||
loginService.handleUserDepartCodes(sysUser);
|
||||
//6. 生成token
|
||||
String token = JwtUtil.sign(sysUser);
|
||||
// 设置超时时间
|
||||
@@ -824,52 +794,12 @@ public class LoginController {
|
||||
//录入登录用户的设备型号
|
||||
if (StringUtils.isNotBlank(sysLoginModel.getDeviceType()) && StringUtils.isNotBlank(sysLoginModel.getDeviceSystem())) {
|
||||
taskExecutor.execute(() ->
|
||||
insertUserDeviceType(sysUser.getId(), sysLoginModel.getDeviceType(), sysLoginModel.getDeviceSystem()));
|
||||
loginService.insertUserDeviceType(sysUser.getId(), sysLoginModel.getDeviceType(), sysLoginModel.getDeviceSystem()));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public void insertUserDeviceType(String userId, String deviceType, String deviceSystem) {
|
||||
LambdaQueryWrapper<SysUserDevice> wrapper = Wrappers.lambdaQuery(SysUserDevice.class)
|
||||
.eq(SysUserDevice::getUserId, userId)
|
||||
.eq(SysUserDevice::getDeviceType, deviceType)
|
||||
.eq(SysUserDevice::getDeviceSystem, deviceSystem);
|
||||
Optional<SysUserDevice> findOptional = sysUserDeviceService.getOneOpt(wrapper);
|
||||
Date now = new Date();
|
||||
if (findOptional.isPresent()) {
|
||||
SysUserDevice sysUserDevice = findOptional.get();
|
||||
sysUserDevice.setLastLoginTime(now);
|
||||
sysUserDeviceService.updateById(sysUserDevice);
|
||||
} else {
|
||||
SysUserDevice sysUserDevice = new SysUserDevice();
|
||||
sysUserDevice.setUserId(userId);
|
||||
sysUserDevice.setDeviceSystem(deviceSystem);
|
||||
sysUserDevice.setDeviceType(deviceType);
|
||||
sysUserDevice.setCreateTime(now);
|
||||
sysUserDevice.setLastLoginTime(now);
|
||||
sysUserDeviceService.save(sysUserDevice);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleUserDepartCodes(SysUser sysUser) {
|
||||
if (sysUser == null || StrUtil.isBlank(sysUser.getDepartIds())) {
|
||||
return;
|
||||
}
|
||||
String[] split = sysUser.getDepartIds().split(",");
|
||||
List<String> codes = new ArrayList<>();
|
||||
for (String departId : split) {
|
||||
SysDepart departById = sysCache.getDepartById(departId);
|
||||
if (departById != null) {
|
||||
codes.add(departById.getOrgCode());
|
||||
}
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(codes)) {
|
||||
sysUser.setDepartCodes(String.join(",", codes));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三方登录获取token
|
||||
*
|
||||
@@ -893,7 +823,7 @@ public class LoginController {
|
||||
// username 泛指账号 包含(username/工号/电话)
|
||||
SysUser sysUser = sysUserService.getUserByNameOrWorkNoOrMobile(username, password, null);
|
||||
if (sysUser == null) {
|
||||
addLoginFailOvertimes(username);
|
||||
loginService.addLoginFailOvertimes(username);
|
||||
result.error500("账号或密码错误");
|
||||
return result;
|
||||
}
|
||||
@@ -903,7 +833,7 @@ public class LoginController {
|
||||
}
|
||||
|
||||
// 用户角色
|
||||
handleUserRoles(sysUser);
|
||||
loginService.handleUserRoles(sysUser);
|
||||
//6. 生成token
|
||||
String token = JwtUtil.sign(sysUser);
|
||||
// 设置超时时间
|
||||
@@ -996,41 +926,6 @@ public class LoginController {
|
||||
return Result.OK(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录失败超出次数5 返回true
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
private boolean isLoginFailOvertimes(String username) {
|
||||
String key = CommonConstant.LOGIN_FAIL + username;
|
||||
Object failTime = redisUtil.get(key);
|
||||
if (failTime != null) {
|
||||
Integer val = Integer.parseInt(failTime.toString());
|
||||
if (val > 5) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录登录失败次数
|
||||
*
|
||||
* @param username
|
||||
*/
|
||||
private void addLoginFailOvertimes(String username) {
|
||||
String key = CommonConstant.LOGIN_FAIL + username;
|
||||
Object failTime = redisUtil.get(key);
|
||||
Integer val = 0;
|
||||
if (failTime != null) {
|
||||
val = Integer.parseInt(failTime.toString());
|
||||
}
|
||||
// 1小时
|
||||
redisUtil.set(key, ++val, 3600);
|
||||
}
|
||||
|
||||
|
||||
@Operation(summary = "登录接口专家端专用")
|
||||
@RequestMapping(value = "/loginDoctor", method = RequestMethod.POST)
|
||||
public Result<JSONObject> loginDoctor(@RequestBody SysLoginModel sysLoginModel) {
|
||||
@@ -1060,7 +955,7 @@ public class LoginController {
|
||||
break;
|
||||
}
|
||||
if (Objects.isNull(sysUser)) {
|
||||
addLoginFailOvertimes(username);
|
||||
loginService.addLoginFailOvertimes(username);
|
||||
result.error500("用户名或密码错误");
|
||||
return result;
|
||||
}
|
||||
@@ -1128,9 +1023,9 @@ public class LoginController {
|
||||
LoginUser cacheUser = cache.get(sysUser.getId(), LoginUser.class);
|
||||
if (cacheUser == null) {
|
||||
// 用户角色
|
||||
handleUserRoles(sysUser);
|
||||
loginService.handleUserRoles(sysUser);
|
||||
// 用户管理部门
|
||||
handleUserDepartCodes(sysUser);
|
||||
loginService.handleUserDepartCodes(sysUser);
|
||||
LoginUser loginUser = new LoginUser();
|
||||
BeanUtils.copyProperties(sysUser, loginUser);
|
||||
cache.put(sysUser.getId(), loginUser);
|
||||
|
||||
+3
-1
@@ -59,9 +59,11 @@ public interface IHealthUserEmployeeExService extends IService<HealthUserEmploye
|
||||
|
||||
UserEmployee selectArchivesById(String id);
|
||||
|
||||
Result<String> addUserInfo(UserEmployee userEmployee);
|
||||
|
||||
boolean saveAndUser(UserEmployee userEmployee);
|
||||
|
||||
boolean updateByIdAndUser(UserEmployee userEmployee);
|
||||
Result<String> updateUserInfo(UserEmployee userEmployee, LoginUser loginUser);
|
||||
|
||||
boolean saveAndUserDepartManager(UserEmployee userEmployee);
|
||||
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package org.jeecg.modules.system.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.modules.system.model.SysLoginModel;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
/**
|
||||
* @author PengJ
|
||||
* @description: 登录Service
|
||||
* @date 2025/10/24 18:10
|
||||
*/
|
||||
public interface ILoginAnYanService {
|
||||
|
||||
/**
|
||||
* @description: 安眼统一认证(pc端)
|
||||
* @author PengJ
|
||||
* @date 2025/10/24 18:11
|
||||
*/
|
||||
Result<JSONObject> loginAnYan(@RequestBody SysLoginModel sysLoginModel);
|
||||
|
||||
/**
|
||||
* @description: 安眼统一认证(移动端)
|
||||
* @author PengJ
|
||||
* @date 2025/10/24 18:11
|
||||
*/
|
||||
Result<JSONObject> mLoginAnYan(@RequestBody SysLoginModel sysLoginModel);
|
||||
|
||||
}
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
package org.jeecg.modules.system.service;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.jeecg.common.constant.CacheConstant;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.Md5Util;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.config.JeecgBaseConfig;
|
||||
import org.jeecg.global.GlobalUtils;
|
||||
import org.jeecg.modules.base.service.BaseCommonService;
|
||||
import org.jeecg.modules.manager.ISysCache;
|
||||
import org.jeecg.modules.system.entity.*;
|
||||
import org.jeecg.modules.system.mapper.SysUserRoleMapper;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Huawei
|
||||
* @version 1.0
|
||||
* @description: TODO
|
||||
* @date 2025/10/29 16:01
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class LoginService {
|
||||
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
@Autowired
|
||||
private ISysUserPostService sysUserPostService;
|
||||
@Autowired
|
||||
private ISysCache sysCache;
|
||||
@Autowired
|
||||
private SysUserRoleMapper sysUserRoleMapper;
|
||||
@Autowired
|
||||
private ISysUserDeviceService sysUserDeviceService;
|
||||
@Autowired
|
||||
private JeecgBaseConfig jeecgBaseConfig;
|
||||
@Resource
|
||||
private BaseCommonService baseCommonService;
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* 记录登录失败次数
|
||||
*
|
||||
* @param username
|
||||
*/
|
||||
public void addLoginFailOvertimes(String username) {
|
||||
String key = CommonConstant.LOGIN_FAIL + username;
|
||||
Object failTime = redisUtil.get(key);
|
||||
Integer val = 0;
|
||||
if (failTime != null) {
|
||||
val = Integer.parseInt(failTime.toString());
|
||||
}
|
||||
// 1小时
|
||||
redisUtil.set(key, ++val, 3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录失败超出次数5 返回true
|
||||
*
|
||||
* @param username
|
||||
* @return
|
||||
*/
|
||||
public boolean isLoginFailOvertimes(String username) {
|
||||
String key = CommonConstant.LOGIN_FAIL + username;
|
||||
Object failTime = redisUtil.get(key);
|
||||
if (failTime != null) {
|
||||
Integer val = Integer.parseInt(failTime.toString());
|
||||
if (val > 5) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理用户相关信息(角色、岗位、管理部门)
|
||||
*/
|
||||
public void processUserInfo(SysUser sysUser) {
|
||||
// 用户角色信息
|
||||
handleUserRoles(sysUser);
|
||||
// 用户岗位信息
|
||||
if (!GlobalUtils.isQh()) {
|
||||
SysUserPost sysUserPost = sysUserPostService.getById(sysUser.getId());
|
||||
if (ObjectUtil.isNotNull(sysUserPost)) {
|
||||
sysUser.setPostId(sysUserPost.getPostId());
|
||||
}
|
||||
}
|
||||
// 用户管理部门
|
||||
handleUserDepartCodes(sysUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验验证码
|
||||
*/
|
||||
public boolean checkVerificationCode(String captcha, String checkKey) {
|
||||
// 验证码校验
|
||||
if (StrUtil.isBlank(captcha) || StrUtil.isBlank(checkKey)) {
|
||||
return false;
|
||||
}
|
||||
String lowerCaseCaptcha = captcha.toLowerCase();
|
||||
String origin = lowerCaseCaptcha + checkKey + jeecgBaseConfig.getSignatureSecret();
|
||||
String realKey = Md5Util.md5Encode(origin, "utf-8");
|
||||
Object checkCode = redisUtil.get(realKey);
|
||||
if (checkCode == null || !checkCode.toString().equals(lowerCaseCaptcha)) {
|
||||
log.warn("验证码错误,key= {} , Ui checkCode= {}, Redis checkCode = {}", checkKey, lowerCaseCaptcha, checkCode);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存用户信息
|
||||
*/
|
||||
public void cacheLoginUserInfo(String username, SysUser sysUser, String loginSuccessTips) {
|
||||
if (StrUtil.isBlank(username) || sysUser == null) {
|
||||
return;
|
||||
}
|
||||
redisUtil.del(CommonConstant.LOGIN_FAIL + username);
|
||||
LoginUser loginUser = new LoginUser();
|
||||
sysUser.setClient(GlobalUtils.loginClient());
|
||||
BeanUtils.copyProperties(sysUser, loginUser);
|
||||
baseCommonService.addLog("用户名: " + username + "," + loginSuccessTips, CommonConstant.LOG_TYPE_1, null, loginUser);
|
||||
Cache cache = cacheManager.getCache(CacheConstant.SYS_USERS_CACHE);
|
||||
if (Objects.nonNull(cache)) {
|
||||
cache.put(sysUser.getId(), loginUser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 用户角色信息
|
||||
* @author PengJ
|
||||
* @date 2025/10/27 15:21
|
||||
*/
|
||||
public void handleUserRoles(SysUser user) {
|
||||
if (ObjectUtil.isNull(user)) {
|
||||
return;
|
||||
}
|
||||
List<SysRole> list = sysUserRoleMapper.getUserRolesByUserId(user.getId());
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String roleCodes = list.stream().map(SysRole::getRoleCode)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.joining(","));
|
||||
user.setRoleCodes(roleCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 用户部门信息处理
|
||||
*/
|
||||
public void handleUserDepartCodes(SysUser sysUser) {
|
||||
if (sysUser == null || StrUtil.isBlank(sysUser.getDepartIds())) {
|
||||
return;
|
||||
}
|
||||
String[] split = sysUser.getDepartIds().split(",");
|
||||
List<String> codes = new ArrayList<>();
|
||||
for (String departId : split) {
|
||||
SysDepart departById = sysCache.getDepartById(departId);
|
||||
if (departById != null) {
|
||||
codes.add(departById.getOrgCode());
|
||||
}
|
||||
}
|
||||
if (CollectionUtil.isNotEmpty(codes)) {
|
||||
sysUser.setDepartCodes(String.join(",", codes));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 插入用户设备信息
|
||||
*/
|
||||
public void insertUserDeviceType(String userId, String deviceType, String deviceSystem) {
|
||||
LambdaQueryWrapper<SysUserDevice> wrapper = Wrappers.lambdaQuery(SysUserDevice.class)
|
||||
.eq(SysUserDevice::getUserId, userId)
|
||||
.eq(SysUserDevice::getDeviceType, deviceType)
|
||||
.eq(SysUserDevice::getDeviceSystem, deviceSystem);
|
||||
Optional<SysUserDevice> findOptional = sysUserDeviceService.getOneOpt(wrapper);
|
||||
Date now = new Date();
|
||||
if (findOptional.isPresent()) {
|
||||
SysUserDevice sysUserDevice = findOptional.get();
|
||||
sysUserDevice.setLastLoginTime(now);
|
||||
sysUserDeviceService.updateById(sysUserDevice);
|
||||
} else {
|
||||
SysUserDevice sysUserDevice = new SysUserDevice();
|
||||
sysUserDevice.setUserId(userId);
|
||||
sysUserDevice.setDeviceSystem(deviceSystem);
|
||||
sysUserDevice.setDeviceType(deviceType);
|
||||
sysUserDevice.setCreateTime(now);
|
||||
sysUserDevice.setLastLoginTime(now);
|
||||
sysUserDeviceService.save(sysUserDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
+80
-2
@@ -32,7 +32,6 @@ import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||
import org.jeecg.common.export.PoiExportHandler;
|
||||
import org.jeecg.common.system.api.ISysBaseAPI;
|
||||
import org.jeecg.common.system.util.DictUtil;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.system.vo.SysUserModel;
|
||||
import org.jeecg.common.util.*;
|
||||
@@ -82,6 +81,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -164,6 +165,8 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl<HealthUserEmplo
|
||||
private UserDataRecordBloodAboMapper aboMapper;
|
||||
@Autowired
|
||||
RedisTemplate<String, Object> redisTemplate;
|
||||
@Autowired
|
||||
private AsyncTaskExecutor asyncTaskExecutor;
|
||||
|
||||
// 档案模块数据导出code
|
||||
private final String exportCode = "sysDataUserExportCode";
|
||||
@@ -430,6 +433,7 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl<HealthUserEmplo
|
||||
|
||||
/**
|
||||
* 脏数据处理
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
@@ -747,7 +751,8 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl<HealthUserEmplo
|
||||
bwhWrapper.isNotNull(UserDataRecordBWH::getWaist);
|
||||
value = Optional.ofNullable(recordBWHMapper.selectOne(bwhWrapper, false)).map(o -> String.valueOf(o.getWaist())).orElse(null);
|
||||
break;
|
||||
default:break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -824,6 +829,30 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl<HealthUserEmplo
|
||||
return userEmployee;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Result<String> addUserInfo(UserEmployee userEmployee) {
|
||||
// 密码解密
|
||||
String key = RSAEncryptUtils.decrypt1(userEmployee.getPassword(), CommonConstant.PRIVATE_KEY);
|
||||
String s = CheckPasswordUtil.checkPasswordRule(key);
|
||||
if (StrUtil.isNotBlank(s)) {
|
||||
return Result.error(s);
|
||||
}
|
||||
userEmployee.setPassword(key);
|
||||
boolean success = saveAndUser(userEmployee);
|
||||
if (success) {
|
||||
if (!GlobalUtils.isQh()) {
|
||||
redisStreamUtil.add(RedisStreamKeyEnum.EMPLOYEE_ASYNC_ADD, userEmployee);
|
||||
}
|
||||
// 添加缓存
|
||||
AsyncUtils.execute(asyncTaskExecutor, ClientSignThreadLocal.getClientSignThreadLocal(),
|
||||
() -> userCacheManager.addUser(empConvertUser(userEmployee)));
|
||||
return Result.ok("添加成功");
|
||||
} else {
|
||||
return Result.error("添加失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean saveAndUser(UserEmployee userEmployee) {
|
||||
@@ -883,6 +912,55 @@ public class HealthUserEmployeeExServiceImpl extends ServiceImpl<HealthUserEmplo
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Result<String> updateUserInfo(UserEmployee userEmployee, LoginUser loginUser) {
|
||||
//将原来编辑用户逻辑迁移到service层
|
||||
//通过userId获取用户修改前的部门信息
|
||||
SysUser sysUser = sysUserService.getUserById(userEmployee.getId());
|
||||
userEmployee.setPassword(null);
|
||||
boolean success = updateByIdAndUser(userEmployee);
|
||||
if (success) {
|
||||
//编辑成功之后新增部门迁移列表
|
||||
//若原有的部门跟编辑不一样则新增迁移列表,反之不用
|
||||
if (Objects.nonNull(sysUser) && Objects.nonNull(sysUser.getDepart())
|
||||
&& !sysUser.getDepart().getOrgCode().equals(userEmployee.getOrgCode())) {
|
||||
SysUserDepartChangeApply departChangeApply = addUserDepartChange(sysUser, loginUser);
|
||||
SysDepart sysDepart = sysCache.getDepartByOrgCode(userEmployee.getOrgCode());
|
||||
departChangeApply.setToDepartId(sysDepart.getId());//迁入部门id
|
||||
departChangeApply.setToDepartCode(userEmployee.getOrgCode());//迁入部门code
|
||||
departChangeApply.setMemo("用户编辑数据");
|
||||
sysUserDepartChangeApplyService.save(departChangeApply);
|
||||
}
|
||||
if (!GlobalUtils.isQh()) {
|
||||
redisStreamUtil.add(RedisStreamKeyEnum.EMPLOYEE_ASYNC_EDIT, userEmployee);
|
||||
}
|
||||
// 编辑缓存
|
||||
AsyncUtils.execute(asyncTaskExecutor, ClientSignThreadLocal.getClientSignThreadLocal(), () -> {
|
||||
userCacheManager.updateUser(empConvertUser(userEmployee));
|
||||
// 刷新用户缓存信息
|
||||
userCacheManager.updateUserCache(userEmployee.getId());
|
||||
});
|
||||
|
||||
String orgCode = userEmployee.getOrgCode();
|
||||
if (com.xkcoding.http.util.StringUtil.isNotEmpty(orgCode)) {
|
||||
sendUpdateMsgToRedisStream(userEmployee.getId(), orgCode);
|
||||
}
|
||||
return Result.ok("编辑成功");
|
||||
} else {
|
||||
return Result.error("编辑失败");
|
||||
}
|
||||
}
|
||||
|
||||
private void sendUpdateMsgToRedisStream(String userId, String orgCode) {
|
||||
if (sysCache.getDepartByOrgCode(orgCode) == null) {
|
||||
return;
|
||||
}
|
||||
SysUserModel userModel = new SysUserModel();
|
||||
userModel.setId(userId);
|
||||
userModel.setDepartIds(sysCache.getDepartByOrgCode(orgCode).getId());
|
||||
userModel.setOrgCode(orgCode);
|
||||
redisStreamUtil.add(RedisStreamKeyEnum.CHANGE_USER_DEPART, userModel);
|
||||
}
|
||||
|
||||
public boolean updateByIdAndUser(UserEmployee userEmployee) {
|
||||
// 添加账号 电话 身份证号校验
|
||||
/* List<String> checkExistUser = sysBaseAPI.checkExistUser(userEmployee.getId(), userEmployee.getUsername(), userEmployee.getPhone(), userEmployee.getIdCard());
|
||||
|
||||
+353
@@ -0,0 +1,353 @@
|
||||
package org.jeecg.modules.system.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.renkang.anyan.client.AnYanClient;
|
||||
import com.renkang.anyan.model.vo.AnYanUserInfoResult;
|
||||
import com.renkang.anyan.model.vo.AuthResult;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.constant.FillRuleConstant;
|
||||
import org.jeecg.common.exception.ExceptionAssertsUtil;
|
||||
import org.jeecg.common.system.util.JwtUtil;
|
||||
import org.jeecg.common.system.vo.LoginUser;
|
||||
import org.jeecg.common.util.CheckPasswordUtil;
|
||||
import org.jeecg.common.util.FillRuleUtil;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.jeecg.common.util.oConvertUtils;
|
||||
import org.jeecg.modules.system.bean.UserEmployee;
|
||||
import org.jeecg.modules.system.entity.HealthUserEmployeeEx;
|
||||
import org.jeecg.modules.system.entity.SysDepart;
|
||||
import org.jeecg.modules.system.entity.SysUser;
|
||||
import org.jeecg.modules.system.model.SysLoginModel;
|
||||
import org.jeecg.modules.system.service.*;
|
||||
import org.jeecg.util.RSAEncryptUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Huawei
|
||||
* @version 1.0
|
||||
* @description: TODO
|
||||
* @date 2025/10/24 18:06
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class LoginAnYanServiceImpl implements ILoginAnYanService {
|
||||
private final ISysUserService sysUserService;
|
||||
private final IHealthUserEmployeeExService healthUserEmployeeExService;
|
||||
private final ISysDepartService sysDepartService;
|
||||
private final ISysDictService sysDictService;
|
||||
private final AnYanClient anYanClient;
|
||||
private final RedisUtil redisUtil;
|
||||
private final TaskExecutor taskExecutor;
|
||||
private final LoginService loginService;
|
||||
|
||||
private static final String CLIENT_TYPE_PC = "pc";
|
||||
private static final String CLIENT_TYPE_APP = "app";
|
||||
|
||||
/**
|
||||
* @description: 安眼登录(pc)
|
||||
* @author PengJ
|
||||
* @date 2025/10/27 13:31
|
||||
*/
|
||||
@Override
|
||||
public Result<JSONObject> loginAnYan(SysLoginModel sysLoginModel) {
|
||||
Result<JSONObject> result;
|
||||
String username = sysLoginModel.getUsername();
|
||||
try {
|
||||
result = loginBusiness(sysLoginModel, username, CLIENT_TYPE_PC);
|
||||
} catch (Exception e) {
|
||||
log.error("安眼登录异常(pc): ", e);
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 安眼app登录
|
||||
* @author PengJ
|
||||
* @date 2025/10/27 15:35
|
||||
*/
|
||||
@Override
|
||||
public Result<JSONObject> mLoginAnYan(SysLoginModel sysLoginModel) {
|
||||
Result<JSONObject> result;
|
||||
String username = sysLoginModel.getUsername();
|
||||
try {
|
||||
result = loginBusiness(sysLoginModel, username, CLIENT_TYPE_APP);
|
||||
} catch (Exception e) {
|
||||
log.error("安眼登录异常(app): ", e);
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 登录业务处理
|
||||
* @author PengJ
|
||||
* @date 2025/10/27 13:31
|
||||
*/
|
||||
public Result<JSONObject> loginBusiness(SysLoginModel sysLoginModel, String username, String clientType) {
|
||||
// 密码解密
|
||||
String decryptedPassword = RSAEncryptUtils.decrypt1(sysLoginModel.getPassword(), CommonConstant.PRIVATE_KEY);
|
||||
if (StrUtil.isBlank(decryptedPassword)) {
|
||||
return Result.error("密码解密失败");
|
||||
}
|
||||
|
||||
// 获取安眼token
|
||||
AuthResult anYanAuthResult = anYanClient.getAuthTokenByPassword(username, decryptedPassword);
|
||||
if (anYanAuthResult == null || StringUtils.isBlank(anYanAuthResult.getAccess_token())) {
|
||||
return Result.error(anYanAuthResult != null ? anYanAuthResult.getMessage() : "认证服务器无响应");
|
||||
}
|
||||
|
||||
// 授权成功获取用户信息
|
||||
AnYanUserInfoResult anYanUserInfo = anYanClient.getAnYanUserInfo(anYanAuthResult.getAccess_token());
|
||||
if (anYanUserInfo == null) {
|
||||
return Result.error("无法获取用户信息");
|
||||
}
|
||||
|
||||
// 检查并更新用户信息
|
||||
checkUserAndUpdate(anYanUserInfo, decryptedPassword);
|
||||
|
||||
// 获取本地用户信息
|
||||
SysUser sysUser = sysUserService.getUserByNameOrWorkNoOrMobile(username, decryptedPassword, null);
|
||||
if (sysUser == null) {
|
||||
loginService.addLoginFailOvertimes(username);
|
||||
return Result.error("账号或密码错误");
|
||||
}
|
||||
// 校验用户有效性
|
||||
Result<JSONObject> result = sysUserService.checkUserIsEffective(sysUser);
|
||||
if (!result.isSuccess()) {
|
||||
return result;
|
||||
}
|
||||
// 弱密码校验
|
||||
String checkMsg = CheckPasswordUtil.checkPasswordRule(decryptedPassword);
|
||||
if (StrUtil.isNotBlank(checkMsg)) {
|
||||
return Result.error(checkMsg);
|
||||
}
|
||||
// 处理用户相关信息(角色、岗位、管理部门)
|
||||
loginService.processUserInfo(sysUser);
|
||||
// 用户登录信息处理
|
||||
userInfo(sysUser, result, clientType);
|
||||
// 清除登录失败记录
|
||||
redisUtil.del(CommonConstant.LOGIN_FAIL + username);
|
||||
// 缓存登录用户信息
|
||||
if (CLIENT_TYPE_PC.equals(clientType)) {
|
||||
loginService.cacheLoginUserInfo(username, sysUser, "登录成功!");
|
||||
} else if (CLIENT_TYPE_APP.equals(clientType)) {
|
||||
loginService.cacheLoginUserInfo(username, sysUser, "登录成功[移动端]!");
|
||||
}
|
||||
if (clientType.equals(CLIENT_TYPE_APP)) {
|
||||
//录入登录用户的设备型号
|
||||
if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(sysLoginModel.getDeviceType()) && com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotBlank(sysLoginModel.getDeviceSystem())) {
|
||||
taskExecutor.execute(() ->
|
||||
loginService.insertUserDeviceType(sysUser.getId(), sysLoginModel.getDeviceType(), sysLoginModel.getDeviceSystem()));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 检查并更新用户信息
|
||||
* @author PengJ
|
||||
* @date 2025/10/27 9:50
|
||||
*/
|
||||
private void checkUserAndUpdate(AnYanUserInfoResult anYanUserInfo, String password) {
|
||||
List<SysUser> list = sysUserService.list(new LambdaQueryWrapper<SysUser>()
|
||||
.eq(SysUser::getWorkNo, anYanUserInfo.getEmployeeUnitDTO().getEmployeeNum())
|
||||
);
|
||||
AnYanUserInfoResult.EmployeeUnitDTO employeeUnitDTO = anYanUserInfo.getEmployeeUnitDTO();
|
||||
String departId = checkDepartAndUpdate(employeeUnitDTO);
|
||||
if (list.isEmpty()) {
|
||||
UserEmployee user = getUserEmployee(anYanUserInfo, password, employeeUnitDTO);
|
||||
user.setPassword(password);
|
||||
user.setOrgCode(departId);
|
||||
user.setPersonType("1");
|
||||
user.setStatus(1);
|
||||
healthUserEmployeeExService.saveAndUser(user);
|
||||
} else if (list.size() == 1) {
|
||||
SysUser sysUser = list.get(0);
|
||||
UserEmployee user = getUserEmployee(anYanUserInfo, password, employeeUnitDTO);
|
||||
HealthUserEmployeeEx extension = user.getExtension();
|
||||
extension.setId(sysUser.getId());
|
||||
user.setExtension(extension);
|
||||
user.setId(sysUser.getId());
|
||||
user.setPassword(null);
|
||||
user.setOrgCode(departId);
|
||||
LoginUser loginUser = new LoginUser();
|
||||
BeanUtil.copyProperties(user, loginUser);
|
||||
healthUserEmployeeExService.updateUserInfo(user, loginUser);
|
||||
} else {
|
||||
ExceptionAssertsUtil.fail("用户工号重复");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 用户信息赋值
|
||||
* @author PengJ
|
||||
* @date 2025/10/27 11:29
|
||||
*/
|
||||
@NotNull
|
||||
private static UserEmployee getUserEmployee(AnYanUserInfoResult anYanUserInfo, String password, AnYanUserInfoResult.EmployeeUnitDTO employeeUnitDTO) {
|
||||
HealthUserEmployeeEx healthUserEmployeeEx = new HealthUserEmployeeEx();
|
||||
healthUserEmployeeEx.setEmpSysno(employeeUnitDTO.getEmployeeNum());
|
||||
UserEmployee user = new UserEmployee();
|
||||
user.setExtension(healthUserEmployeeEx);
|
||||
user.setWorkNo(employeeUnitDTO.getEmployeeNum());
|
||||
user.setUsername(anYanUserInfo.getLoginName());
|
||||
user.setRealname(employeeUnitDTO.getName());
|
||||
user.setEmail(employeeUnitDTO.getEmail());
|
||||
user.setPhone(employeeUnitDTO.getMobile());
|
||||
user.setSex(anYanUserInfo.getGender());
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 获取用户信息
|
||||
* @author PengJ
|
||||
* @date 2025/10/27 15:22
|
||||
*/
|
||||
private void userInfo(SysUser sysUser, Result<JSONObject> result, String clientType) {
|
||||
String userId = sysUser.getId();
|
||||
String username = sysUser.getUsername();
|
||||
// 获取用户部门信息
|
||||
JSONObject obj = new JSONObject(new LinkedHashMap<>());
|
||||
//1.生成token
|
||||
String token = JwtUtil.sign(sysUser);
|
||||
// 设置token缓存有效时间
|
||||
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
|
||||
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);
|
||||
obj.put("token", token);
|
||||
|
||||
//2.设置登录租户
|
||||
Result<JSONObject> loginTenantError = sysUserService.setLoginTenant(sysUser, obj, username, result);
|
||||
if (loginTenantError != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientType.equals(CLIENT_TYPE_PC)) {
|
||||
//设置登录部门
|
||||
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
|
||||
obj.put("departs", departs);
|
||||
if (departs == null || departs.isEmpty()) {
|
||||
obj.put("multi_depart", 0);
|
||||
} else if (departs.size() == 1) {
|
||||
sysUserService.updateUserDepart(userId, departs.get(0).getOrgCode(), null);
|
||||
obj.put("multi_depart", 1);
|
||||
} else {
|
||||
//查询当前是否有登录部门
|
||||
// update-begin--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
|
||||
SysUser sysUserById = sysUserService.getById(sysUser.getId());
|
||||
if (oConvertUtils.isEmpty(sysUserById.getOrgCode())) {
|
||||
sysUserService.updateUserDepart(userId, departs.get(0).getOrgCode(), null);
|
||||
}
|
||||
// update-end--Author:wangshuai Date:20200805 for:如果用戶为选择部门,数据库为存在上一次登录部门,则取一条存进去
|
||||
obj.put("multi_depart", 2);
|
||||
}
|
||||
//获取字典数据
|
||||
obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
|
||||
} else if (clientType.equals(CLIENT_TYPE_APP)) {
|
||||
String orgCode = sysUser.getOrgCode();
|
||||
if (oConvertUtils.isEmpty(orgCode)) {
|
||||
//如果当前用户无选择部门 查看部门关联信息
|
||||
List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
|
||||
if (!departs.isEmpty()) {
|
||||
orgCode = departs.get(0).getOrgCode();
|
||||
sysUser.setOrgCode(orgCode);
|
||||
this.sysUserService.updateUserDepart(sysUser.getId(), orgCode, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
//设置登录用户信息
|
||||
obj.put("userInfo", sysUser);
|
||||
result.setResult(obj);
|
||||
result.success("登录成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* @description: 检查并更新部门信息(返回所属orgId)
|
||||
* @author PengJ
|
||||
* @date 2025/10/29 9:37
|
||||
*/
|
||||
private String checkDepartAndUpdate(AnYanUserInfoResult.EmployeeUnitDTO employeeUnitDTO) {
|
||||
String levelPath = employeeUnitDTO.getLevelPath();
|
||||
String orgId = "";
|
||||
if (StringUtils.isNotBlank(levelPath)) {
|
||||
String parentId = "";
|
||||
String[] unitCodes = levelPath.split("\\|");
|
||||
for (String unitCode : unitCodes) {
|
||||
if (StringUtils.isBlank(unitCode) || "00000100".equals(unitCode)) {
|
||||
parentId = sysDepartService.getOne(new LambdaQueryWrapper<SysDepart>()
|
||||
.and(wrapper ->
|
||||
wrapper.isNull(SysDepart::getParentId)
|
||||
.or().eq(SysDepart::getParentId, "")
|
||||
).eq(SysDepart::getOrgCategory, "1")
|
||||
.eq(SysDepart::getOrgCode, "A01")
|
||||
).getId();
|
||||
continue;
|
||||
}
|
||||
SysDepart depart = sysDepartService.getOne(new LambdaQueryWrapper<SysDepart>()
|
||||
.eq(SysDepart::getId, unitCode)
|
||||
);
|
||||
String orgName = "";
|
||||
if (unitCode.equals(employeeUnitDTO.getUnitCode())) {
|
||||
orgName = employeeUnitDTO.getUnitName();
|
||||
} else if (unitCode.equals(employeeUnitDTO.getSectionUnitCode())) {
|
||||
orgName = employeeUnitDTO.getSectionUnitName();
|
||||
}
|
||||
boolean save;
|
||||
// 部门不存在
|
||||
if (depart == null) {
|
||||
depart = new SysDepart();
|
||||
depart.setId(unitCode);
|
||||
depart.setParentId(parentId);
|
||||
JSONObject formData = new JSONObject();
|
||||
formData.put("parentId", parentId);
|
||||
String[] codeArray = (String[]) FillRuleUtil.executeRule(FillRuleConstant.DEPART, formData);
|
||||
depart.setOrgCode(codeArray[0]);
|
||||
String orgType = codeArray[1];
|
||||
depart.setOrgType(String.valueOf(orgType));
|
||||
depart.setDepartName(orgName);
|
||||
depart.setCreateTime(new Date());
|
||||
depart.setStatus("1");
|
||||
depart.setDelFlag("0");
|
||||
depart.setOrgCategory("2");
|
||||
save = sysDepartService.save(depart);
|
||||
} else {
|
||||
save = sysDepartService.update(new LambdaUpdateWrapper<SysDepart>()
|
||||
.eq(SysDepart::getId, depart.getId())
|
||||
.set(SysDepart::getDepartName, orgName)
|
||||
.set(SysDepart::getUpdateTime, new Date())
|
||||
);
|
||||
}
|
||||
if (save) {
|
||||
// 仅在父节点为叶子节点时更新为非叶子节点
|
||||
SysDepart parentDepart = sysDepartService.getOne(new LambdaQueryWrapper<SysDepart>()
|
||||
.eq(SysDepart::getId, parentId)
|
||||
);
|
||||
if (parentDepart != null && !parentDepart.getIzLeaf().equals(1)) {
|
||||
sysDepartService.update(new LambdaUpdateWrapper<SysDepart>()
|
||||
.eq(SysDepart::getId, parentId)
|
||||
.set(SysDepart::getIzLeaf, "1")
|
||||
);
|
||||
}
|
||||
}
|
||||
parentId = depart.getId();
|
||||
orgId = depart.getId();
|
||||
}
|
||||
}
|
||||
return orgId;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user