Parcourir la source

外部调用会议专家信息接口

tags/24080901
CMM il y a 4 mois
Parent
révision
6dd08edf39
14 fichiers modifiés avec 369 ajouts et 4 suppressions
  1. +2
    -1
      hz-pm-api/src/main/java/com/hz/pm/api/common/handler/GlobalResponseHandler.java
  2. +2
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/expert/model/dto/DictionaryVO.java
  3. +12
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java
  4. +45
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/open/controller/OpenApiMeetingExpertInfoController.java
  5. +184
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/open/manage/OpenApiMeetingExpertInfoManage.java
  6. +26
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/open/model/po/ReqMeetingExpertInfoPO.java
  7. +36
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/open/model/vo/ExpertInfoVO.java
  8. +49
    -0
      hz-pm-api/src/main/java/com/hz/pm/api/open/model/vo/MeetingExpertInfoVO.java
  9. +3
    -1
      hz-pm-api/src/main/resources/application-dev.yml
  10. +4
    -1
      hz-pm-api/src/main/resources/application-prod.yml
  11. +3
    -1
      hz-pm-api/src/main/resources/application-test.yml
  12. +1
    -0
      hz-pm-api/src/main/resources/security/auth-dev.yml
  13. +1
    -0
      hz-pm-api/src/main/resources/security/auth-prod.yml
  14. +1
    -0
      hz-pm-api/src/main/resources/security/auth-test.yml

+ 2
- 1
hz-pm-api/src/main/java/com/hz/pm/api/common/handler/GlobalResponseHandler.java Voir le fichier

@@ -41,7 +41,8 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
"com.hz.pm.api.dashboard.controller",
"com.hz.pm.api.wps.controller",
"com.hz.pm.api.external.controller",
"com.hz.pm.api.gov.controller"
"com.hz.pm.api.gov.controller",
"com.hz.pm.api.open.controller"
})
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {



+ 2
- 0
hz-pm-api/src/main/java/com/hz/pm/api/expert/model/dto/DictionaryVO.java Voir le fichier

@@ -2,6 +2,7 @@ package com.hz.pm.api.expert.model.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* <p>
@@ -13,6 +14,7 @@ import lombok.Data;
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DictionaryVO {

private String dictionaryCode;


+ 12
- 0
hz-pm-api/src/main/java/com/hz/pm/api/meeting/entity/domain/MeetingExpert.java Voir le fichier

@@ -80,4 +80,16 @@ public class MeetingExpert implements Serializable {
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateOn;

/**
* 20240511 新增字段
*/
@ApiModelProperty("专家签到状态")
private Boolean signStatus;

@ApiModelProperty("专家签到时间")
private LocalDateTime signTime;

@ApiModelProperty("专家签到地点")
private String signAddress;

}

+ 45
- 0
hz-pm-api/src/main/java/com/hz/pm/api/open/controller/OpenApiMeetingExpertInfoController.java Voir le fichier

@@ -0,0 +1,45 @@
package com.hz.pm.api.open.controller;


import java.util.List;

import javax.validation.Valid;

import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.hz.pm.api.open.manage.OpenApiMeetingExpertInfoManage;
import com.hz.pm.api.open.model.po.ReqMeetingExpertInfoPO;
import com.hz.pm.api.open.model.vo.MeetingExpertInfoVO;
import com.ningdatech.log.annotation.WebLog;

import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
* <p>
* 会议专家信息外部调用接口
* </p>
* @author CMM
*
*/
@Slf4j
@Validated
@RestController
@RequestMapping("/open/api/meeting-expert-info")
@RequiredArgsConstructor
public class OpenApiMeetingExpertInfoController {

private final OpenApiMeetingExpertInfoManage openMeetingExpertInfoManage;

@PostMapping("/list")
@ApiOperation("获取已抽取完成会议确定参加会议且未签到的专家信息列表")
@WebLog
public List<MeetingExpertInfoVO> infoList(@Valid @RequestBody ReqMeetingExpertInfoPO po) {
return openMeetingExpertInfoManage.infoList(po);
}
}

+ 184
- 0
hz-pm-api/src/main/java/com/hz/pm/api/open/manage/OpenApiMeetingExpertInfoManage.java Voir le fichier

@@ -0,0 +1,184 @@
package com.hz.pm.api.open.manage;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;

import com.hz.pm.api.expert.model.dto.DictionaryVO;
import com.hz.pm.api.meta.model.dto.DictionaryDTO;
import com.hz.pm.api.user.model.entity.UserInfo;
import com.hz.pm.api.user.security.model.UserFullInfoDTO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.hz.pm.api.common.helper.UserInfoHelper;
import com.hz.pm.api.meeting.entity.domain.Meeting;
import com.hz.pm.api.meeting.entity.domain.MeetingExpert;
import com.hz.pm.api.meeting.service.IMeetingExpertService;
import com.hz.pm.api.meeting.service.IMeetingService;
import com.hz.pm.api.meta.constant.ExpertDictTypeEnum;
import com.hz.pm.api.meta.helper.DictionaryCache;
import com.hz.pm.api.meta.model.entity.ExpertDictionary;
import com.hz.pm.api.meta.service.IExpertDictionaryService;
import com.hz.pm.api.open.model.po.ReqMeetingExpertInfoPO;
import com.hz.pm.api.open.model.vo.ExpertInfoVO;
import com.hz.pm.api.open.model.vo.MeetingExpertInfoVO;
import com.hz.pm.api.user.service.IUserInfoService;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.util.CollUtils;

import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
* @author CMM
* @since 2024/05/10 17:18
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class OpenApiMeetingExpertInfoManage {

@Value("${hz-pm.interfaceKey}")
private String meetingExpertInfoKey;

private final IMeetingService meetingService;
private final IMeetingExpertService meetingExpertService;
private final UserInfoHelper userInfoHelper;
private final IUserInfoService userInfoService;
private final IExpertDictionaryService iExpertDictionaryService;
private final DictionaryCache dictionaryCache;
public List<MeetingExpertInfoVO> infoList(ReqMeetingExpertInfoPO po) {
String key = po.getKey();
// 校验传入的签名
if (!checkSign(key)){
throw new BizException("签名错误!");
}
// 获取已经抽取完成 确认参加会议并且未签到的专家信息
List<Meeting> meetingList = meetingService.list(Wrappers.lambdaQuery(Meeting.class)
.eq(Meeting::getConfirmedRoster, true));
if(CollUtil.isEmpty(meetingList)){
return Collections.emptyList();
}
List<MeetingExpertInfoVO> result = Lists.newArrayList();
// 获取已抽取完成会议中未签到的专家信息
List<Long> meetingIds = meetingList.stream().map(Meeting::getId).collect(Collectors.toList());
Map<Long, List<MeetingExpert>> meetingExpertMap = meetingExpertService.list(Wrappers.lambdaQuery(MeetingExpert.class)
.in(MeetingExpert::getMeetingId, meetingIds)
.eq(MeetingExpert::getSignStatus, Boolean.FALSE))
.stream().collect(Collectors.groupingBy(MeetingExpert::getMeetingId));
Map<Long, Meeting> meetingMap = CollUtils.listToMap(meetingList, Meeting::getId);
List<MeetingExpert> experts = Lists.newArrayList();
for (Map.Entry<Long, List<MeetingExpert>> listEntry : meetingExpertMap.entrySet()) {
List<MeetingExpert> value = listEntry.getValue();
experts.addAll(value);
}

// 获取未签到的专家信息
List<MeetingExpert> expertList = experts.stream().filter(m -> Boolean.FALSE.equals(m.getSignStatus())).collect(Collectors.toList());
Set<Long> userIds = expertList.stream().map(MeetingExpert::getExpertId).collect(Collectors.toSet());
List<UserInfo> userInfoList = userInfoService.list(Wrappers.lambdaQuery(UserInfo.class).in(UserInfo::getId, userIds));
Set<String> employeeSet = Sets.newHashSet();
userInfoList = userInfoList.stream().filter(u -> employeeSet.add(u.getEmployeeCode())).collect(Collectors.toList());
List<UserFullInfoDTO> userFullInfos = userInfoHelper.getUserFullInfos(userInfoList);
Set<Long> userIdSet = Sets.newHashSet();
userFullInfos = userFullInfos.stream().filter(u -> userIdSet.add(u.getUserId())).collect(Collectors.toList());
Map<Long, UserFullInfoDTO> infoMap = userFullInfos.stream().collect(Collectors.toMap(UserFullInfoDTO::getUserId, v -> v));

List<ExpertDictionary> expertDictionaryList = iExpertDictionaryService.list(Wrappers.lambdaQuery(ExpertDictionary.class)
.eq(ExpertDictionary::getExpertInfoField, ExpertDictTypeEnum.EXPERT_TYPE.getKey())
.in(ExpertDictionary::getUserId, userIdSet));
Map<Long, List<ExpertDictionary>> dictMap = expertDictionaryList.stream().collect(Collectors.groupingBy(ExpertDictionary::getUserId));

for (Map.Entry<Long, List<MeetingExpert>> entry : meetingExpertMap.entrySet()) {
MeetingExpertInfoVO vo = new MeetingExpertInfoVO();
Long meetingId = entry.getKey();
Meeting meeting = meetingMap.get(meetingId);
if (Objects.nonNull(meeting)){
vo.setMeetingId(meeting.getId());
vo.setStartTime(meeting.getStartTime());
vo.setEndTime(meeting.getEndTime());
vo.setMeetingName(meeting.getName());
vo.setMeetingAddress(meeting.getMeetingAddress());
vo.setConnecter(meeting.getConnecter());
vo.setContact(meeting.getContact());
}
List<MeetingExpert> meetingExperts = entry.getValue();
if (CollUtil.isNotEmpty(meetingExperts)){
// 获取未签到的专家信息
List<MeetingExpert> expertUserList = meetingExperts.stream().filter(m -> Boolean.FALSE.equals(m.getSignStatus())).collect(Collectors.toList());
if (CollUtil.isNotEmpty(expertUserList)){
List<ExpertInfoVO> expertInfoVOList = expertUserList.stream().map(m -> {
ExpertInfoVO expertInfoVO = new ExpertInfoVO();
expertInfoVO.setUserId(m.getExpertId());
expertInfoVO.setName(m.getExpertName());
expertInfoVO.setPhoneNo(m.getMobile());
UserFullInfoDTO userFullInfoDTO = infoMap.get(m.getExpertId());
if (Objects.nonNull(userFullInfoDTO)){
expertInfoVO.setMhUnitId(userFullInfoDTO.getMhUnitId());
expertInfoVO.setMhUnitName(userFullInfoDTO.getMhUnitName());
}
List<ExpertDictionary> dictionaries = dictMap.get(m.getExpertId());
if (CollUtil.isNotEmpty(dictionaries)){
List<DictionaryVO> dictionaryFieldInfos = dictionaries.stream().map(r -> {
DictionaryVO dictionary = new DictionaryVO();
dictionary.setDictionaryType(r.getExpertInfoField());
dictionary.setDictionaryCode(r.getDictionaryCode());
Optional<DictionaryDTO> dictionaryDTO = dictionaryCache.getByCode(r.getDictionaryCode());
dictionaryDTO.ifPresent(dictDTO -> dictionary.setDictionaryName(dictDTO.getName()));
return dictionary;
}).collect(Collectors.toList());
expertInfoVO.setExpertType(dictionaryFieldInfos);
}
return expertInfoVO;
}).collect(Collectors.toList());
vo.setExpertInfoList(expertInfoVOList);
}
}
result.add(vo);
}
return result;
}

private Boolean checkSign(String key) {
StringBuilder sb = new StringBuilder();
sb.append("key=").append(meetingExpertInfoKey);
// 使用SHA-256进行加密
String sign = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] bytes = md.digest(sb.toString().getBytes());
sign = bytesToHexString(bytes);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
if (sign == null || sign.length() <= 8) {
return false;
}
String signStr = sign.substring(sign.length() - 8);
return signStr.equals(key);
}

/**
* 将字节数组转换为十六进制字符串
*
* @param bytes 字节数组
* @return 十六进制字符串
*/
private static String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
sb.append("0");
}
sb.append(hex);
}
return sb.toString();
}
}

+ 26
- 0
hz-pm-api/src/main/java/com/hz/pm/api/open/model/po/ReqMeetingExpertInfoPO.java Voir le fichier

@@ -0,0 +1,26 @@
package com.hz.pm.api.open.model.po;

import javax.validation.constraints.NotBlank;

import com.ningdatech.basic.model.PagePo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
* @author CMM
* @since 2024-05-10
*/
@ApiModel(description = "会议专家信息列表请求入参")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReqMeetingExpertInfoPO extends PagePo {

@ApiModelProperty("校验公钥")
@NotBlank(message = "秘钥不能为空")
private String key;
}

+ 36
- 0
hz-pm-api/src/main/java/com/hz/pm/api/open/model/vo/ExpertInfoVO.java Voir le fichier

@@ -0,0 +1,36 @@
package com.hz.pm.api.open.model.vo;

import java.util.List;

import com.hz.pm.api.expert.model.dto.DictionaryVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
* @author CMM
* @date 2024/5/11
*/
@Data
@ApiModel("专家信息")
public class ExpertInfoVO {

@ApiModelProperty("专家用户id")
private Long userId;

@ApiModelProperty(value = "专家类型")
private List<DictionaryVO> expertType;

@ApiModelProperty(value = "专家姓名")
private String name;

@ApiModelProperty(value = "手机号")
private String phoneNo;

@ApiModelProperty(value = "单位名称")
private String mhUnitName;

@ApiModelProperty(value = "单位id")
private Long mhUnitId;

}

+ 49
- 0
hz-pm-api/src/main/java/com/hz/pm/api/open/model/vo/MeetingExpertInfoVO.java Voir le fichier

@@ -0,0 +1,49 @@
package com.hz.pm.api.open.model.vo;

import java.time.LocalDateTime;
import java.util.List;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
* 外部调用接口会议专家信息实体
*
* @author CMM
* @since 2024/05/10 17:16
*/
@Data
public class MeetingExpertInfoVO {


/**
* 会议信息
*/

@ApiModelProperty("会议ID")
private Long meetingId;

@ApiModelProperty("会议开始时间")
private LocalDateTime startTime;

@ApiModelProperty("会议结束时间")
private LocalDateTime endTime;

@ApiModelProperty("会议名称")
private String meetingName;

@ApiModelProperty("会议地址")
private String meetingAddress;

@ApiModelProperty("联系人")
private String connecter;

@ApiModelProperty("联系方式")
private String contact;

/**
* 专家信息列表
*/
@ApiModelProperty("专家信息列表")
private List<ExpertInfoVO> expertInfoList;
}

+ 3
- 1
hz-pm-api/src/main/resources/application-dev.yml Voir le fichier

@@ -204,4 +204,6 @@ mobile-call:
reminder-task:
declared-record:
open: false
cron: 0 30 8 * * ?
cron: 0 30 8 * * ?
hz-pm:
interfaceKey: hz_meeting_expert_info

+ 4
- 1
hz-pm-api/src/main/resources/application-prod.yml Voir le fichier

@@ -220,4 +220,7 @@ reminder-task:
cron: 0 30 8 * * ?
# 电话服务调用地址
mobile-call:
host: http://10.54.21.185:18085/blue_esl_api
host: http://10.54.21.185:18085/blue_esl_api
hz-pm:
interfaceKey: hz_meeting_expert_info


+ 3
- 1
hz-pm-api/src/main/resources/application-test.yml Voir le fichier

@@ -264,4 +264,6 @@ auth-code:
secret-key: uqrvd2bani4fercnisua1cqxjwk1neym
agent-login:
proxy:
secret-key: tqkwiqojg5j4eiypr3rb8w7nb4noa8b2
secret-key: tqkwiqojg5j4eiypr3rb8w7nb4noa8b2
hz-pm:
interfaceKey: hz_meeting_expert_info

+ 1
- 0
hz-pm-api/src/main/resources/security/auth-dev.yml Voir le fichier

@@ -73,6 +73,7 @@ security:
- /api/v1/wps-convert/**
- /api/v1/belong-org/business-strip/list
- /expert/ephemeral/*/registration
- /open/api/**
role-map:
"engineer":
"project_manager":


+ 1
- 0
hz-pm-api/src/main/resources/security/auth-prod.yml Voir le fichier

@@ -73,6 +73,7 @@ security:
- /api/v1/wps-convert/**
- /api/v1/belong-org/business-strip/list
- /expert/ephemeral/*/registration
- /open/api/**
role-map:
"engineer":
"project_manager":


+ 1
- 0
hz-pm-api/src/main/resources/security/auth-test.yml Voir le fichier

@@ -72,6 +72,7 @@ security:
- /api/v1/wps-convert/**
- /api/v1/belong-org/business-strip/list
- /expert/ephemeral/*/registration
- /open/api/**
role-map:
"engineer":
"project_manager":


Chargement…
Annuler
Enregistrer