From 051905a6f2b180582f16617454994710327563b9 Mon Sep 17 00:00:00 2001 From: PengJ <2413927716@qq.com> Date: Thu, 30 Oct 2025 10:14:51 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E7=99=BB=E5=BD=95=E3=80=91=E5=AE=89?= =?UTF-8?q?=E7=9C=BC=E7=BB=9F=E4=B8=80=E8=AE=A4=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/renkang/anyan/client/AnYanClient.java | 34 +- .../anyan/client/AnYanClientExecutor.java | 142 +++++-- .../anyan/config/AnYanRestTemplateConfig.java | 28 +- .../anyan/config/RestTemplateUtil.java | 60 ++- .../com/renkang/anyan/enums/AnYanApiEnum.java | 49 +-- .../anyan/model/dto/AuthByPasswordParam.java | 32 ++ .../anyan/model/vo/AnYanUserInfoResult.java | 149 ++++++++ .../renkang/anyan/model/vo/AuthResult.java | 8 + .../org/jeecg/config/shiro/ShiroConfig.java | 2 + jeecg-system/jeecg-system-biz/pom.xml | 4 + .../HealthUserEmployeeExController.java | 224 +++++------ .../system/controller/LoginController.java | 203 +++------- .../service/IHealthUserEmployeeExService.java | 4 +- .../system/service/ILoginAnYanService.java | 29 ++ .../modules/system/service/LoginService.java | 210 +++++++++++ .../impl/HealthUserEmployeeExServiceImpl.java | 202 +++++++--- .../service/impl/LoginAnYanServiceImpl.java | 353 ++++++++++++++++++ 17 files changed, 1301 insertions(+), 432 deletions(-) create mode 100644 functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/dto/AuthByPasswordParam.java create mode 100644 functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/vo/AnYanUserInfoResult.java create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/ILoginAnYanService.java create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/LoginService.java create mode 100644 jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/LoginAnYanServiceImpl.java diff --git a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/client/AnYanClient.java b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/client/AnYanClient.java index 361023a..9c48db6 100644 --- a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/client/AnYanClient.java +++ b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/client/AnYanClient.java @@ -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 @@ -43,21 +53,24 @@ public interface AnYanClient { HealthSignStatVO healthCheckStatistics(Date beginDate, Date endDate); /** - *健康打卡异常数据详细查询(血压) + * 健康打卡异常数据详细查询(血压) + * * @param healthSignListParam * @return */ IPage bloodPressureList(HealthSignListParam healthSignListParam); /** - *健康打卡异常数据详细查询(减重) + * 健康打卡异常数据详细查询(减重) + * * @param healthSignListParam * @return */ IPage weightPressureList(HealthSignListParam healthSignListParam); /** - *健康打卡异常数据详细查询(血糖) + * 健康打卡异常数据详细查询(血糖) + * * @param healthSignListParam * @return */ @@ -65,18 +78,21 @@ public interface AnYanClient { /** * 油田医院数据查询 + * * @return */ List hospitalList(); /** * 健康小屋基础数据查询 + * * @return */ List 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); } diff --git a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/client/AnYanClientExecutor.java b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/client/AnYanClientExecutor.java index 76c21ec..3bb3b85 100644 --- a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/client/AnYanClientExecutor.java +++ b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/client/AnYanClientExecutor.java @@ -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 @@ -54,43 +61,79 @@ public class AnYanClientExecutor implements AnYanClient { @Override public String getAuthToken() { - String token = redisClientUtil.get(new RedisKeyPrefix(AnYanConstants.AN_YAN_API_TOKEN_PREFIX) ,"token",String.class); - if(StrUtil.isEmpty(token)){ + String token = redisClientUtil.get(new RedisKeyPrefix(AnYanConstants.AN_YAN_API_TOKEN_PREFIX), "token", String.class); + if (StrUtil.isEmpty(token)) { AuthResult authResult = getAuthTokenExecutor(); - if(ObjectUtil.isNotEmpty(authResult) && StrUtil.isNotEmpty(authResult.getAccess_token())){ + if (ObjectUtil.isNotEmpty(authResult) && StrUtil.isNotEmpty(authResult.getAccess_token())) { token = authResult.getAccess_token(); - int expireSeconds = ObjectUtil.isNotEmpty(authResult.getExpires_in())? authResult.getExpires_in() : 7200; - redisClientUtil.set(new RedisKeyPrefix(expireSeconds,AnYanConstants.AN_YAN_API_TOKEN_PREFIX),"token", token); + int expireSeconds = ObjectUtil.isNotEmpty(authResult.getExpires_in()) ? authResult.getExpires_in() : 7200; + redisClientUtil.set(new RedisKeyPrefix(expireSeconds, AnYanConstants.AN_YAN_API_TOKEN_PREFIX), "token", token); } } return token; } - private AuthResult getAuthTokenExecutor(){ + private AuthResult getAuthTokenExecutor() { AuthParam authParam = new AuthParam(); authParam.setClient_id(anYanProperties.getClientId()); authParam.setClient_secret(anYanProperties.getClientSecret()); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); - ResponseEntity responseEntity = RestTemplateUtil.postExchange(AnYanApiEnum.QUERY_AUTH_TOKEN,headers,authParam,AuthResult.class); - if(HttpStatus.OK.equals(responseEntity.getStatusCode()) && ObjectUtils.isNotEmpty(responseEntity.getBody())){ + ResponseEntity responseEntity = RestTemplateUtil.postExchange(AnYanApiEnum.QUERY_AUTH_TOKEN, headers, authParam, AuthResult.class); + if (HttpStatus.OK.equals(responseEntity.getStatusCode()) && ObjectUtils.isNotEmpty(responseEntity.getBody())) { return responseEntity.getBody(); - }else { + } else { ExceptionAssertsUtil.fail("------安眼系统获取token失败------" + responseEntity.getBody()); } 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 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 = 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(); - if(ObjectUtil.isNotEmpty(authResult) && StrUtil.isNotEmpty(authResult.getAccess_token())){ - int expireSeconds = ObjectUtil.isNotEmpty(authResult.getExpires_in())? authResult.getExpires_in() : 7200; - redisClientUtil.set(new RedisKeyPrefix(expireSeconds,AnYanConstants.AN_YAN_API_TOKEN_PREFIX),"token", authResult.getAccess_token()); + if (ObjectUtil.isNotEmpty(authResult) && StrUtil.isNotEmpty(authResult.getAccess_token())) { + int expireSeconds = ObjectUtil.isNotEmpty(authResult.getExpires_in()) ? authResult.getExpires_in() : 7200; + redisClientUtil.set(new RedisKeyPrefix(expireSeconds, AnYanConstants.AN_YAN_API_TOKEN_PREFIX), "token", authResult.getAccess_token()); } } - private HttpHeaders buildTokenHeader(){ + private HttpHeaders buildTokenHeader() { HttpHeaders headers = new HttpHeaders(); headers.add(AnYanConstants.AUTHORIZATION, AnYanConstants.TOKEN_TYPE + getAuthToken()); return headers; @@ -99,9 +142,11 @@ public class AnYanClientExecutor implements AnYanClient { @Override @Retryable(maxAttempts = 2) public List 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)); + param.put("medicalYear", String.valueOf(medicalYear)); AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.HEALTH_EXAMINATION_STATISTICS, buildTokenHeader(), param); List listMaps = (List) result.getData(); return listMaps.stream().map(lMap -> BeanUtil.toBean(lMap, MedicalPeopleNumStatisticsVO.class)).collect(Collectors.toList()); @@ -111,31 +156,31 @@ public class AnYanClientExecutor implements AnYanClient { @Retryable(maxAttempts = 2) public HealthSignStatVO healthCheckStatistics(Date beginDate, Date endDate) { JSONObject param = new JSONObject(); - param.put("inputDateBegin",ObjectUtil.isEmpty(beginDate)? DateUtil.today() : DateUtil.formatDate(beginDate)); - param.put("inputDateEnd",ObjectUtil.isEmpty(endDate)? DateUtil.today() : DateUtil.formatDate(endDate)); + param.put("inputDateBegin", ObjectUtil.isEmpty(beginDate) ? DateUtil.today() : DateUtil.formatDate(beginDate)); + param.put("inputDateEnd", ObjectUtil.isEmpty(endDate) ? DateUtil.today() : DateUtil.formatDate(endDate)); AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.HEALTH_CHECK_STATISTICS, buildTokenHeader(), param); - return BeanUtil.toBean(result.getData(),HealthSignStatVO.class); + return BeanUtil.toBean(result.getData(), HealthSignStatVO.class); } @Override @Retryable(maxAttempts = 2) public IPage bloodPressureList(HealthSignListParam healthSignListParam) { AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.BLOOD_PRESSURE_LIST, buildTokenHeader(), healthSignListParam); - return new PageResultToBeanUtil().transform(result,BloodPressureList.class); + return new PageResultToBeanUtil().transform(result, BloodPressureList.class); } @Override @Retryable(maxAttempts = 2) public IPage weightPressureList(HealthSignListParam healthSignListParam) { AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.WEIGHT_PRESSURE_LIST, buildTokenHeader(), healthSignListParam); - return new PageResultToBeanUtil().transform(result,WeightPressureList.class); + return new PageResultToBeanUtil().transform(result, WeightPressureList.class); } @Override @Retryable(maxAttempts = 2) public IPage bloodSugarClockSList(HealthSignListParam healthSignListParam) { AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.BLOOD_SUGAR_CLOCKS_LIST, buildTokenHeader(), healthSignListParam); - return new PageResultToBeanUtil().transform(result,BloodSugarClockSList.class); + return new PageResultToBeanUtil().transform(result, BloodSugarClockSList.class); } @Override @@ -149,7 +194,7 @@ public class AnYanClientExecutor implements AnYanClient { @Override @Retryable(maxAttempts = 2) public List healthPlaceHomList() { - AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.HEALTH_PLACE_ROOM_LIST, buildTokenHeader(),null); + AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.HEALTH_PLACE_ROOM_LIST, buildTokenHeader(), null); List listMaps = (List) result.getData(); return listMaps.stream().map(lMap -> BeanUtil.toBean(lMap, HealthRoomBaseVO.class)).collect(Collectors.toList()); } @@ -158,61 +203,63 @@ public class AnYanClientExecutor implements AnYanClient { @Retryable(maxAttempts = 2) public IPage healthPlaceHomDetailList(HealthRoomDTO healthRoomDTO) { AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.HEALTH_PLACE_ROOM_INFO_LIST, buildTokenHeader(), healthRoomDTO); - return new PageResultToBeanUtil().transform(result,HealthPlaceHomDetailsVO.class); + return new PageResultToBeanUtil().transform(result, HealthPlaceHomDetailsVO.class); } @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); + param.put("medicalYear", medicalYear); AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.MEDICAL_ABNORMAL_STATISTICS, buildTokenHeader(), param); - return BeanUtil.toBean(result.getData(),MedicalAbnormalStatisticsVO.class); + return BeanUtil.toBean(result.getData(), MedicalAbnormalStatisticsVO.class); } @Override @Retryable(maxAttempts = 2) public IPage medicalAbnormalList(MedicalAbnormalDTO param) { AnYanResult result = RestTemplateUtil.postExchange(AnYanApiEnum.MEDICAL_ABNORMAL_LIST, buildTokenHeader(), param); - return new PageResultToBeanUtil().transform(result,MedicalAbnormalVO.class); + return new PageResultToBeanUtil().transform(result, MedicalAbnormalVO.class); } @Override - public String publicNetworkToken(){ - String token = redisClientUtil.get(new RedisKeyPrefix(AnYanConstants.AN_YAN_API_TOKEN_PREFIX) ,"publicToken",String.class); - if(StrUtil.isEmpty(token)){ + public String publicNetworkToken() { + String token = redisClientUtil.get(new RedisKeyPrefix(AnYanConstants.AN_YAN_API_TOKEN_PREFIX), "publicToken", String.class); + if (StrUtil.isEmpty(token)) { AuthResult authResult = publicNetworkTokenNoCache(); - if(null != authResult){ + if (null != authResult) { token = authResult.getAccess_token(); - int expireSeconds = ObjectUtil.isNotEmpty(authResult.getExpires_in())? authResult.getExpires_in() : 7200; - redisClientUtil.set(new RedisKeyPrefix(expireSeconds,AnYanConstants.AN_YAN_API_TOKEN_PREFIX),"publicToken", token); + int expireSeconds = ObjectUtil.isNotEmpty(authResult.getExpires_in()) ? authResult.getExpires_in() : 7200; + redisClientUtil.set(new RedisKeyPrefix(expireSeconds, AnYanConstants.AN_YAN_API_TOKEN_PREFIX), "publicToken", token); } } return token; } @Override - public AuthResult publicNetworkTokenNoCache(){ + public AuthResult publicNetworkTokenNoCache() { JSONObject param = new JSONObject(); String password = anYanProperties.getPublicPassWrod(); String userName = anYanProperties.getPublicUserNmae(); try { String sm4Password = SM4Utils.encryptSM4(password); String encryptPassword = StringUtils.encryptByPublicKey(publicKey, password); - param.put("password",encryptPassword); - param.put("selfPassword",sm4Password); - param.put("loginName",userName); + param.put("password", encryptPassword); + param.put("selfPassword", sm4Password); + param.put("loginName", userName); param.put("timeStamp", UUID.randomUUID().toString()); - ResponseEntity responseEntity = RestTemplateUtil.postExchangeForGetToken(AnYanApiEnum.PUBLIC_NETWORK_AUTH_TOKEN, param,AnYanResult.class); + ResponseEntity responseEntity = RestTemplateUtil.postExchangeForGetToken(AnYanApiEnum.PUBLIC_NETWORK_AUTH_TOKEN, param, AnYanResult.class); //安眼提供的接口包过深 ,先从AnYanResult对象中取出加密的密文,后在解密密文拿出 AuthResult对象 , 再从AuthResult对象中拿出 access_token AnYanResult anYanResult = responseEntity.getBody(); - if(ObjectUtil.isNotEmpty(anYanResult) && ObjectUtil.isNotEmpty(anYanResult.getData())){ + if (ObjectUtil.isNotEmpty(anYanResult) && ObjectUtil.isNotEmpty(anYanResult.getData())) { String decryptAuthResult = SM4Utils.decryptSM4((String) anYanResult.getData()); AuthResult authResult = JSON.parseObject(decryptAuthResult).toJavaObject(AuthResult.class); - if(null != authResult && null != authResult.getAccess_token()){ + if (null != authResult && null != authResult.getAccess_token()) { return authResult; - }else { + } else { ExceptionAssertsUtil.fail("获取安眼系统token失败"); } } @@ -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 exchange = RestTemplateUtil.getExchange(AnYanApiEnum.USER_INFO_UNIT_V2, headers, AnYanUserInfoResult.class); + return BeanUtil.toBean(exchange.getBody(), AnYanUserInfoResult.class); + } + } diff --git a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/config/AnYanRestTemplateConfig.java b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/config/AnYanRestTemplateConfig.java index 8436e55..8b5c37e 100644 --- a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/config/AnYanRestTemplateConfig.java +++ b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/config/AnYanRestTemplateConfig.java @@ -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(); } @@ -47,17 +54,28 @@ public class AnYanRestTemplateConfig { /** * 自定义拦截器处理接口鉴权失败, 配合spring retry使用从而避免因token失效导致的接口调用失败 */ - public ClientHttpRequestInterceptor authInterceptor(){ + 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); - HttpStatus httpStatus =execute.getStatusCode(); - if (Arrays.asList(HttpStatus.UNAUTHORIZED,HttpStatus.FORBIDDEN).contains(httpStatus)) { + if (shouldSkip) { + return execute; + } + HttpStatus httpStatus = execute.getStatusCode(); + if (Arrays.asList(HttpStatus.UNAUTHORIZED, HttpStatus.FORBIDDEN).contains(httpStatus) + && retryCount.getAndIncrement() < maxRetries) { SpringContextUtils.getBean("anYanClientExecutor", AnYanClient.class).refreshToken(); } } catch (Exception e) { - log.error("---------安眼平台API调用异常-------e{}",e.getMessage(),e); + log.error("---------安眼平台API调用异常-------e{}", e.getMessage(), e); ExceptionAssertsUtil.fail("安眼平台API调用失败"); throw e; } diff --git a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/config/RestTemplateUtil.java b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/config/RestTemplateUtil.java index 6d098d8..c07d8bc 100644 --- a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/config/RestTemplateUtil.java +++ b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/config/RestTemplateUtil.java @@ -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,50 +41,83 @@ public class RestTemplateUtil { /** * 请求接口访问 token - * @param api 接口 + * + * @param api 接口 * @param requestBody 参数 * @return ResponseEntity */ - public static ResponseEntity postExchange(AnYanApiEnum api, HttpHeaders headers ,Object requestBody,Class responseType) { - String url = getProperties().getHost() + api.getMethodPath() + api.getMethodParam(); + public static ResponseEntity postExchange(AnYanApiEnum api, HttpHeaders headers, Object requestBody, Class responseType) { + String url = getProperties().getHost() + api.getMethodPath() + api.getMethodParam(); HttpEntity requestEntity = new HttpEntity<>(requestBody); return getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType); } + /** + * 公网请求接口访问 token(密码模式) + * + * @param api 接口 + * @param formData 参数 + * @return ResponseEntity + */ + public static ResponseEntity postExchangeForGetTokenByPassword(AnYanApiEnum api, MultiValueMap formData, HttpHeaders headers, Class responseType) { + String url = getProperties().getPublicHost() + api.getMethodPath(); + HttpEntity> requestEntity = new HttpEntity<>(formData, headers); + log.info("开始发送请求到: {}", url); + ResponseEntity response = getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType); + log.info("收到响应: {}", response); + return response; + } + /** * 公网请求接口访问 token - * @param api 接口 + * + * @param api 接口 * @param requestBody 参数 * @return ResponseEntity */ - public static ResponseEntity postExchangeForGetToken(AnYanApiEnum api,Object requestBody,Class responseType) { - String url = getProperties().getPublicHost() + api.getMethodPath() + api.getMethodParam(); + public static ResponseEntity postExchangeForGetToken(AnYanApiEnum api, Object requestBody, Class responseType) { + String url = getProperties().getPublicHost() + api.getMethodPath() + api.getMethodParam(); HttpEntity requestEntity = new HttpEntity<>(requestBody); return getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType); } /** * 通用调用方法 - * @param api 请求接口 - * @param headers 请求头 + * + * @param api 请求接口 + * @param headers 请求头 * @param requestBody body参数 - * @return Result对象 + * @return Result对象 */ public static AnYanResult postExchange(AnYanApiEnum api, HttpHeaders headers, Object requestBody) { - String url = getProperties().getHost() + api.getMethodPath() +api.getMethodParam(); - HttpEntity requestEntity = new HttpEntity<>(requestBody,headers); + String url = getProperties().getHost() + api.getMethodPath() + api.getMethodParam(); + HttpEntity requestEntity = new HttpEntity<>(requestBody, headers); return responseHandler(getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, AnYanResult.class)); } + /** + * 通用调用方法 + * + * @param api 请求接口 + * @param headers 请求头 + * @return Result对象 + */ + public static ResponseEntity getExchange(AnYanApiEnum api, HttpHeaders headers, Class responseType) { + String url = getProperties().getHost() + api.getMethodPath() + api.getMethodParam(); + HttpEntity requestEntity = new HttpEntity<>(headers); + return getRestTemplate().exchange(url, api.getHttpMethod(), requestEntity, responseType); + } + /** * ResponseEntity 转 Result + * * @param entity * @return */ private static > AnYanResult responseHandler(ResponseEntity entity) { - if(HttpStatus.OK.equals(entity.getStatusCode()) && ObjectUtils.isNotEmpty(entity.getBody())){ + if (HttpStatus.OK.equals(entity.getStatusCode()) && ObjectUtils.isNotEmpty(entity.getBody())) { return entity.getBody(); - }else{ + } else { return AnYanResult.error("天眼系统API调用失败"); } } diff --git a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/enums/AnYanApiEnum.java b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/enums/AnYanApiEnum.java index 123fb13..3dbf30a 100644 --- a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/enums/AnYanApiEnum.java +++ b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/enums/AnYanApiEnum.java @@ -2,6 +2,7 @@ package com.renkang.anyan.enums; import lombok.Getter; import org.springframework.http.HttpMethod; + /** * @Description: AnYanApiEnum xj安眼系统接口枚举类 * @Author: feng @@ -13,62 +14,68 @@ public enum AnYanApiEnum { /** * 1.获取token接口 */ - QUERY_AUTH_TOKEN("/oauth/oauth/token","", HttpMethod.POST), + QUERY_AUTH_TOKEN("/oauth/oauth/token", "", HttpMethod.POST), /** * 2.体检人数统计查询 */ - HEALTH_EXAMINATION_STATISTICS("/aygc-znhpt-sys/0/aystatistics/peopleHealthExaminationStatistics","", HttpMethod.POST), + HEALTH_EXAMINATION_STATISTICS("/aygc-znhpt-sys/0/aystatistics/peopleHealthExaminationStatistics", "", HttpMethod.POST), /** - *3.健康打卡数据统计查询(血压,减重,血糖) + * 3.健康打卡数据统计查询(血压,减重,血糖) */ - HEALTH_CHECK_STATISTICS("/aygc-znhpt-sys/0/aystatistics/healthCheckStatistics","", HttpMethod.POST), + HEALTH_CHECK_STATISTICS("/aygc-znhpt-sys/0/aystatistics/healthCheckStatistics", "", HttpMethod.POST), /** - *4.健康打卡异常数据详细查询(血压) + * 4.健康打卡异常数据详细查询(血压) */ - BLOOD_PRESSURE_LIST("/aygc-znhpt-sys/0/aystatistics/bloodPressureList","", HttpMethod.POST), + BLOOD_PRESSURE_LIST("/aygc-znhpt-sys/0/aystatistics/bloodPressureList", "", HttpMethod.POST), /** - *5.健康打卡异常数据详细查询(减重) + * 5.健康打卡异常数据详细查询(减重) */ - WEIGHT_PRESSURE_LIST("/aygc-znhpt-sys/0/aystatistics/weightPressureList","", HttpMethod.POST), + WEIGHT_PRESSURE_LIST("/aygc-znhpt-sys/0/aystatistics/weightPressureList", "", HttpMethod.POST), /** - *6.健康打卡异常数据详细查询(血糖) + * 6.健康打卡异常数据详细查询(血糖) */ - BLOOD_SUGAR_CLOCKS_LIST("/aygc-znhpt-sys/0/aystatistics/bloodSugarClockSList","", HttpMethod.POST), + BLOOD_SUGAR_CLOCKS_LIST("/aygc-znhpt-sys/0/aystatistics/bloodSugarClockSList", "", HttpMethod.POST), /** - *7.体检异常数据统计查询(暂定) + * 7.体检异常数据统计查询(暂定) */ - MEDICAL_ABNORMAL_STATISTICS("/aygc-znhpt-sys/0/aystatistics/checkstatistics","", HttpMethod.POST), + MEDICAL_ABNORMAL_STATISTICS("/aygc-znhpt-sys/0/aystatistics/checkstatistics", "", HttpMethod.POST), /** - *8.体检异常数据清单(暂定) + * 8.体检异常数据清单(暂定) */ - MEDICAL_ABNORMAL_LIST("/aygc-znhpt-sys/0/aystatistics/checkList","", HttpMethod.POST), + MEDICAL_ABNORMAL_LIST("/aygc-znhpt-sys/0/aystatistics/checkList", "", HttpMethod.POST), /** - *9.油田医院数据查询 + * 9.油田医院数据查询 */ - HOSPITAL_LIST("/aygc-znhpt-sys/0/aystatistics/HospitalList","", HttpMethod.POST), + HOSPITAL_LIST("/aygc-znhpt-sys/0/aystatistics/HospitalList", "", HttpMethod.POST), /** - *10.健康小屋基础数据查询 + * 10.健康小屋基础数据查询 */ - HEALTH_PLACE_ROOM_LIST("/aygc-znhpt-sys/0/aystatistics/HealthPlaceHomList","", HttpMethod.POST), + HEALTH_PLACE_ROOM_LIST("/aygc-znhpt-sys/0/aystatistics/HealthPlaceHomList", "", HttpMethod.POST), /** - *11.健康小屋详细数据查询 + * 11.健康小屋详细数据查询 */ - HEALTH_PLACE_ROOM_INFO_LIST("/aygc-znhpt-sys/0/aystatistics/initEmpHealthRoomCheckinInfoPages","", HttpMethod.POST), + HEALTH_PLACE_ROOM_INFO_LIST("/aygc-znhpt-sys/0/aystatistics/initEmpHealthRoomCheckinInfoPages", "", HttpMethod.POST), /** * 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), + ; /** * 接口路径 diff --git a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/dto/AuthByPasswordParam.java b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/dto/AuthByPasswordParam.java new file mode 100644 index 0000000..80dd1f4 --- /dev/null +++ b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/dto/AuthByPasswordParam.java @@ -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; +} diff --git a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/vo/AnYanUserInfoResult.java b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/vo/AnYanUserInfoResult.java new file mode 100644 index 0000000..8ff828c --- /dev/null +++ b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/vo/AnYanUserInfoResult.java @@ -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; + } +} diff --git a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/vo/AuthResult.java b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/vo/AuthResult.java index 5115ca0..711f6f1 100644 --- a/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/vo/AuthResult.java +++ b/functional-modules/xj-anyan-api/src/main/java/com/renkang/anyan/model/vo/AuthResult.java @@ -28,4 +28,12 @@ public class AuthResult { * satoken */ private String satoken; + /** + * message + */ + private String message; + /** + * success + */ + private boolean success; } diff --git a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java b/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java index b2d1a75..dbfc138 100644 --- a/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java +++ b/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java @@ -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置换 diff --git a/jeecg-system/jeecg-system-biz/pom.xml b/jeecg-system/jeecg-system-biz/pom.xml index dcafb2f..7e81c39 100644 --- a/jeecg-system/jeecg-system-biz/pom.xml +++ b/jeecg-system/jeecg-system-biz/pom.xml @@ -80,6 +80,10 @@ com.renkang health-watch-api + + com.renkang + xj-anyan-api + diff --git a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/HealthUserEmployeeExController.java b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/HealthUserEmployeeExController.java index 1d2c671..233c875 100644 --- a/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/HealthUserEmployeeExController.java +++ b/jeecg-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/HealthUserEmployeeExController.java @@ -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; @@ -101,7 +101,7 @@ public class HealthUserEmployeeExController extends JeecgController page = new Page<>(pageNo, pageSize); - IPage pageList = healthUserEmployeeExService.selectHealthUserEmployeeExList(page, userFilter,idStatus); + IPage pageList = healthUserEmployeeExService.selectHealthUserEmployeeExList(page, userFilter, idStatus); return Result.OK(pageList); } @@ -154,18 +154,19 @@ public class HealthUserEmployeeExController extends JeecgController