@@ -17,11 +17,13 @@ public interface UserInfoHelper { | |||
/** | |||
* 根据用户id 获取 用户所属组织code organizationCode | |||
* | |||
* @param userId | |||
* @return | |||
* @param userId \ | |||
* @return \ | |||
*/ | |||
String getOrganizationCode(Long userId); | |||
UserFullInfoDTO getUserFullInfoByMhUserIdOrOpenId(String mhUserId); | |||
UserFullInfoDTO getUserFullInfo(Long userId); | |||
UserFullInfoDTO getUserFullInfo(UserInfo userInfo); | |||
@@ -31,9 +33,9 @@ public interface UserInfoHelper { | |||
String getUserName(Long userId); | |||
/** | |||
* 判断该用户是否是区管或者超管 | |||
* 判断该用户是否是区管或者超管 \ | |||
* | |||
* @return | |||
* @return \ | |||
*/ | |||
boolean isSuperOrRegionAdmin(Long userId); | |||
@@ -42,9 +44,9 @@ public interface UserInfoHelper { | |||
List<UserFullInfoDTO> getUserFullInfoByEmployeeCodes(Collection<String> employeeCodes); | |||
/** | |||
* 获取用户任职所在单位code | |||
* 获取用户任职所在单位code \ | |||
* | |||
* @return | |||
* @return \ | |||
*/ | |||
String getUserEmpPosUnitCode(Long userId); | |||
@@ -2,6 +2,7 @@ package com.hz.pm.api.common.helper.impl; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.core.collection.CollectionUtil; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.StringUtils; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.hz.pm.api.common.constant.BizConst; | |||
@@ -48,6 +49,19 @@ public class UserInfoHelperImpl implements UserInfoHelper { | |||
} | |||
@Override | |||
public UserFullInfoDTO getUserFullInfoByMhUserIdOrOpenId(String mhUserId) { | |||
LambdaQueryWrapper<UserInfo> query = Wrappers.lambdaQuery(UserInfo.class) | |||
.eq(UserInfo::getMhUserId, mhUserId) | |||
.or(q1 -> q1.eq(UserInfo::getWechatOpenId,mhUserId)); | |||
UserInfo userInfo = userInfoService.getOne(query); | |||
if (Objects.isNull(userInfo)) { | |||
return null; | |||
} | |||
// 返回用户全量信息 | |||
return getUserFullInfo(userInfo); | |||
} | |||
@Override | |||
public UserFullInfoDTO getUserFullInfo(Long userId) { | |||
UserInfo userInfo = userInfoService.getById(userId); | |||
if (Objects.isNull(userInfo)) { | |||
@@ -74,12 +74,12 @@ public class EmployeeBatchGetTask { | |||
// 获取所有的组织列表用户获取组织下的 用户信息(暂时 只查 单位的类型) | |||
List<DingOrganization> dingOrganizationList = iDingOrganizationService.list(Wrappers.lambdaQuery(DingOrganization.class) | |||
.eq(DingOrganization::getTypeCode, DingOrganizationContant.UNIT_TYPE)); | |||
log.info("所有待更新员工的单位数:{}",dingOrganizationList.size()); | |||
log.info("所有待更新员工的单位数:{}", dingOrganizationList.size()); | |||
if (CollUtil.isNotEmpty(dingOrganizationList)) { | |||
//记录任务 单位数 | |||
Integer index = 0; | |||
for (DingOrganization dingOrganization : dingOrganizationList) { | |||
log.info("当前单位:{},下标数,{}",dingOrganization.getOrganizationName(),index); | |||
log.info("当前单位:{},下标数,{}", dingOrganization.getOrganizationName(), index); | |||
index++; | |||
List<OrganizationEmployeePosition> allOrganizationEmployeePositionList = new ArrayList<>(); | |||
String organizationCode = dingOrganization.getOrganizationCode(); | |||
@@ -95,8 +95,8 @@ public class EmployeeBatchGetTask { | |||
// 查询组织下 用户信息 | |||
GenericResult<Page<OrganizationEmployeePosition>> firstPageGenericResult = zwddClient.pageOrganizationEmployeePositions(query); | |||
Page<OrganizationEmployeePosition> data = firstPageGenericResult.getData(); | |||
if (Objects.isNull(data)){ | |||
log.info("响应为空:{}",organizationCode); | |||
if (Objects.isNull(data)) { | |||
log.info("响应为空:{}", organizationCode); | |||
continue; | |||
} | |||
if (CollUtil.isNotEmpty(data.getData())) { | |||
@@ -106,7 +106,7 @@ public class EmployeeBatchGetTask { | |||
log.info("dingOrganization :{}", JSON.toJSONString(dingOrganization)); | |||
log.info("totalSize :{},{}", totalSize,dingOrganization.getOrganizationName()); | |||
log.info("totalSize :{},{}", totalSize, dingOrganization.getOrganizationName()); | |||
if (totalSize > PAGE_SIZE) { | |||
if (totalSize > MAX_SIZE) { | |||
//超过1万 按1万的处理 | |||
@@ -119,9 +119,9 @@ public class EmployeeBatchGetTask { | |||
query.setPageNo(pageNo); | |||
GenericResult<Page<OrganizationEmployeePosition>> pageGenericResult = zwddClient.pageOrganizationEmployeePositions(query); | |||
// log.info("pageGenericResult :{}", JSON.toJSONString(pageGenericResult)); | |||
if(pageGenericResult.isSuccess()){ | |||
if (pageGenericResult.isSuccess()) { | |||
allOrganizationEmployeePositionList.addAll(pageGenericResult.getData().getData()); | |||
}else{ | |||
} else { | |||
log.error(pageGenericResult.getMsg()); | |||
} | |||
} | |||
@@ -231,38 +231,37 @@ public class EmployeeBatchGetTask { | |||
dingEmployeeInfo.setId(employeeInfo.getId()); | |||
iDingEmployeeInfoService.saveOrUpdate(dingEmployeeInfo); | |||
} | |||
generateOrUpdateUserInfo(dingEmployeeInfo,organizationMap); | |||
generateOrUpdateUserInfo(dingEmployeeInfo, organizationMap); | |||
} | |||
} | |||
public void generateOrUpdateUserInfo(DingEmployeeInfo dingEmployeeInfo,Map<String, DingOrganization> organizationMap) { | |||
public void generateOrUpdateUserInfo(DingEmployeeInfo dingEmployeeInfo, Map<String, DingOrganization> organizationMap) { | |||
String employeeCode = dingEmployeeInfo.getEmployeeCode(); | |||
UserInfo userInfo = iUserInfoService.getOne(Wrappers.lambdaQuery(UserInfo.class) | |||
.eq(UserInfo::getEmployeeCode, employeeCode)); | |||
if (Objects.isNull(userInfo)) { | |||
userInfo = UserInfo.builder() | |||
.accountId(dingEmployeeInfo.getAccountId()) | |||
.username(dingEmployeeInfo.getEmployeeName()) | |||
.realName(dingEmployeeInfo.getEmployeeName()) | |||
.employeeCode(dingEmployeeInfo.getEmployeeCode()) | |||
.available(UserAvailableEnum.DISABLE.name()) | |||
.createBy(-1L) | |||
.updateBy(-1L) | |||
.createOn(LocalDateTime.now()) | |||
.updateOn(LocalDateTime.now()) | |||
.empPosUnitCode(dingEmployeeInfo.getEmpPosUnitCode()) | |||
.avatar(dingEmployeeInfo.getAvatar()) | |||
.build(); | |||
if(StringUtils.isNotBlank(userInfo.getEmpPosUnitCode()) && organizationMap.containsKey(userInfo.getEmpPosUnitCode())){ | |||
userInfo = new UserInfo(); | |||
userInfo.setAccountId(dingEmployeeInfo.getAccountId()); | |||
userInfo.setUsername(dingEmployeeInfo.getEmployeeName()); | |||
userInfo.setRealName(dingEmployeeInfo.getEmployeeName()); | |||
userInfo.setEmployeeCode(dingEmployeeInfo.getEmployeeCode()); | |||
userInfo.setAvailable(UserAvailableEnum.DISABLE.name()); | |||
userInfo.setCreateBy(-1L); | |||
userInfo.setUpdateBy(-1L); | |||
userInfo.setCreateOn(LocalDateTime.now()); | |||
userInfo.setUpdateOn(LocalDateTime.now()); | |||
userInfo.setEmpPosUnitCode(dingEmployeeInfo.getEmpPosUnitCode()); | |||
userInfo.setAvatar(dingEmployeeInfo.getAvatar()); | |||
if (StringUtils.isNotBlank(userInfo.getEmpPosUnitCode()) && organizationMap.containsKey(userInfo.getEmpPosUnitCode())) { | |||
DingOrganization dingOrganization = organizationMap.get(userInfo.getEmpPosUnitCode()); | |||
userInfo.setEmpPosUnitName(dingOrganization.getOrganizationName()); | |||
userInfo.setRegionCode(dingOrganization.getDivisionCode()); | |||
} | |||
iUserInfoService.save(userInfo); | |||
}else{ | |||
} else { | |||
userInfo.setAvatar(dingEmployeeInfo.getAvatar()); | |||
userInfo.setEmpPosUnitCode(dingEmployeeInfo.getEmpPosUnitCode()); | |||
if(StringUtils.isNotBlank(userInfo.getEmpPosUnitCode()) && organizationMap.containsKey(userInfo.getEmpPosUnitCode())){ | |||
if (StringUtils.isNotBlank(userInfo.getEmpPosUnitCode()) && organizationMap.containsKey(userInfo.getEmpPosUnitCode())) { | |||
DingOrganization dingOrganization = organizationMap.get(userInfo.getEmpPosUnitCode()); | |||
userInfo.setEmpPosUnitName(dingOrganization.getOrganizationName()); | |||
userInfo.setRegionCode(dingOrganization.getDivisionCode()); | |||
@@ -273,6 +272,7 @@ public class EmployeeBatchGetTask { | |||
/** | |||
* 按区域 来更新员工 | |||
* | |||
* @param regionCode | |||
*/ | |||
public void batchGetEmployeeTaskByRegionCode(String regionCode) { | |||
@@ -281,12 +281,12 @@ public class EmployeeBatchGetTask { | |||
.eq(DingOrganization::getDivisionCode, regionCode)); | |||
log.info("所有地区 {} 待更新员工的单位数:{}",regionCode,units.size()); | |||
log.info("所有地区 {} 待更新员工的单位数:{}", regionCode, units.size()); | |||
if (CollUtil.isNotEmpty(units)) { | |||
//记录任务 单位数 | |||
Integer index = 0; | |||
for (DingOrganization dingOrganization : units) { | |||
log.info("当前单位:{},下标数,{}",dingOrganization.getOrganizationName(),index); | |||
log.info("当前单位:{},下标数,{}", dingOrganization.getOrganizationName(), index); | |||
index++; | |||
List<OrganizationEmployeePosition> allOrganizationEmployeePositionList = new ArrayList<>(); | |||
String organizationCode = dingOrganization.getOrganizationCode(); | |||
@@ -302,8 +302,8 @@ public class EmployeeBatchGetTask { | |||
// 查询组织下 用户信息 | |||
GenericResult<Page<OrganizationEmployeePosition>> firstPageGenericResult = zwddClient.pageOrganizationEmployeePositions(query); | |||
Page<OrganizationEmployeePosition> data = firstPageGenericResult.getData(); | |||
if (Objects.isNull(data)){ | |||
log.info("响应为空:{}",organizationCode); | |||
if (Objects.isNull(data)) { | |||
log.info("响应为空:{}", organizationCode); | |||
continue; | |||
} | |||
if (CollUtil.isNotEmpty(data.getData())) { | |||
@@ -313,7 +313,7 @@ public class EmployeeBatchGetTask { | |||
log.info("dingOrganization :{}", JSON.toJSONString(dingOrganization)); | |||
log.info("totalSize :{},{}", totalSize,dingOrganization.getOrganizationName()); | |||
log.info("totalSize :{},{}", totalSize, dingOrganization.getOrganizationName()); | |||
if (totalSize > PAGE_SIZE) { | |||
if (totalSize > MAX_SIZE) { | |||
//超过1万 按1万的处理 | |||
@@ -326,9 +326,9 @@ public class EmployeeBatchGetTask { | |||
query.setPageNo(pageNo); | |||
GenericResult<Page<OrganizationEmployeePosition>> pageGenericResult = zwddClient.pageOrganizationEmployeePositions(query); | |||
// log.info("pageGenericResult :{}", JSON.toJSONString(pageGenericResult)); | |||
if(pageGenericResult.isSuccess()){ | |||
if (pageGenericResult.isSuccess()) { | |||
allOrganizationEmployeePositionList.addAll(pageGenericResult.getData().getData()); | |||
}else{ | |||
} else { | |||
log.error(pageGenericResult.getMsg()); | |||
} | |||
} | |||
@@ -358,7 +358,7 @@ public class EmployeeBatchGetTask { | |||
.eq(DingOrganization::getOrganizationCode, orgCode) | |||
.last(BizConst.LIMIT_1)); | |||
VUtils.isTrue(Objects.isNull(org)).throwMessage("单位不存在"); | |||
log.info("所属单位 {} 要更新员工信息了",org.getOrganizationName()); | |||
log.info("所属单位 {} 要更新员工信息了", org.getOrganizationName()); | |||
List<OrganizationEmployeePosition> allOrganizationEmployeePositionList = new ArrayList<>(); | |||
String organizationCode = orgCode; | |||
@@ -374,8 +374,8 @@ public class EmployeeBatchGetTask { | |||
// 查询组织下 用户信息 | |||
GenericResult<Page<OrganizationEmployeePosition>> firstPageGenericResult = zwddClient.pageOrganizationEmployeePositions(query); | |||
Page<OrganizationEmployeePosition> data = firstPageGenericResult.getData(); | |||
if (Objects.isNull(data)){ | |||
log.info("响应为空:{}",organizationCode); | |||
if (Objects.isNull(data)) { | |||
log.info("响应为空:{}", organizationCode); | |||
return; | |||
} | |||
if (CollUtil.isNotEmpty(data.getData())) { | |||
@@ -385,7 +385,7 @@ public class EmployeeBatchGetTask { | |||
log.info("dingOrganization :{}", JSON.toJSONString(org)); | |||
log.info("totalSize :{},{}", totalSize,org.getOrganizationName()); | |||
log.info("totalSize :{},{}", totalSize, org.getOrganizationName()); | |||
if (totalSize > PAGE_SIZE) { | |||
if (totalSize > MAX_SIZE) { | |||
//超过1万 按1万的处理 | |||
@@ -398,9 +398,9 @@ public class EmployeeBatchGetTask { | |||
query.setPageNo(pageNo); | |||
GenericResult<Page<OrganizationEmployeePosition>> pageGenericResult = zwddClient.pageOrganizationEmployeePositions(query); | |||
// log.info("pageGenericResult :{}", JSON.toJSONString(pageGenericResult)); | |||
if(pageGenericResult.isSuccess()){ | |||
if (pageGenericResult.isSuccess()) { | |||
allOrganizationEmployeePositionList.addAll(pageGenericResult.getData().getData()); | |||
}else{ | |||
} else { | |||
log.error(pageGenericResult.getMsg()); | |||
} | |||
} | |||
@@ -427,18 +427,19 @@ public class EmployeeBatchGetTask { | |||
/** | |||
* 更新员工信息 主要是头像 | |||
* | |||
* @param empCode | |||
*/ | |||
public void getEmployeeByCode(String empCode) { | |||
GenericResult<EmployeeInfoDTO> result = zwddClient.getEmployeeByCode(empCode); | |||
log.error("请求员工信息 result:{}",JSON.toJSONString(result)); | |||
if(!result.isSuccess()){ | |||
log.error("请求员工信息失败 :{},mesg:{}",empCode,result.getMsg()); | |||
log.error("请求员工信息 result:{}", JSON.toJSONString(result)); | |||
if (!result.isSuccess()) { | |||
log.error("请求员工信息失败 :{},mesg:{}", empCode, result.getMsg()); | |||
return; | |||
} | |||
EmployeeInfoDTO data = result.getData(); | |||
if(Objects.isNull(data)){ | |||
if (Objects.isNull(data)) { | |||
log.error("请求员工信息失败 返回为空"); | |||
return; | |||
} | |||
@@ -447,7 +448,7 @@ public class EmployeeBatchGetTask { | |||
.eq(DingEmployeeInfo::getEmployeeCode, empCode) | |||
.last(BizConst.LIMIT_1)); | |||
if(Objects.nonNull(emp)){ | |||
if (Objects.nonNull(emp)) { | |||
emp.setAvatar(data.getGovEmpAvatar()); | |||
iDingEmployeeInfoService.updateById(emp); | |||
} | |||
@@ -456,7 +457,7 @@ public class EmployeeBatchGetTask { | |||
.eq(UserInfo::getEmployeeCode, empCode) | |||
.last(BizConst.LIMIT_1)); | |||
if(Objects.nonNull(user)){ | |||
if (Objects.nonNull(user)) { | |||
user.setAvatar(data.getGovEmpAvatar()); | |||
iUserInfoService.updateById(user); | |||
} | |||
@@ -464,6 +465,7 @@ public class EmployeeBatchGetTask { | |||
/** | |||
* 更新一整个单位的 | |||
* | |||
* @param orgCode | |||
*/ | |||
public void getBatchEmployeeByCode(String orgCode) { | |||
@@ -471,7 +473,7 @@ public class EmployeeBatchGetTask { | |||
List<DingEmployeeInfo> employees = iDingEmployeeInfoService.list(Wrappers.lambdaQuery(DingEmployeeInfo.class) | |||
.eq(DingEmployeeInfo::getEmpPosUnitCode, orgCode)); | |||
for(DingEmployeeInfo employee : employees){ | |||
for (DingEmployeeInfo employee : employees) { | |||
getEmployeeByCode(employee.getEmployeeCode()); | |||
} | |||
} | |||
@@ -42,7 +42,7 @@ public class ExpertUserInfoAssembler { | |||
private final DictionaryCache dictionaryCache; | |||
private final RegionCacheHelper regionCacheHelper; | |||
public ExpertFullInfoVO buildExpertFullInfo(List<AttachFileVo> attachFiles, ExpertFullInfoAllDTO expertFullInfoAll) { | |||
public ExpertFullInfoVO buildExpertDetail(List<AttachFileVo> attachFiles, ExpertFullInfoAllDTO expertFullInfoAll) { | |||
ExpertUserFullInfoDTO expertUserInfo = expertFullInfoAll.getExpertUserInfoDTO(); | |||
// 字典字典段map | |||
Map<String, List<DictionaryFieldInfo>> dictMap = buildDictInfoMap(expertFullInfoAll.getExpertDictionaryList()); | |||
@@ -9,6 +9,7 @@ import com.hz.pm.api.expert.model.req.ExpertRegistrationRequest; | |||
import com.hz.pm.api.expert.model.req.ExpertUserBasicInfoSubmitRequest; | |||
import com.hz.pm.api.expert.model.req.GetZzdInfoRequest; | |||
import com.hz.pm.api.expert.model.vo.*; | |||
import com.hz.pm.api.user.util.LoginUserUtil; | |||
import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.log.annotation.WebLog; | |||
import io.swagger.annotations.Api; | |||
@@ -39,23 +40,6 @@ public class ExpertController { | |||
private final ExpertManage expertManage; | |||
private final ExpertAdminManage expertAdminManage; | |||
/** | |||
* 生成专家报名临时地址 | |||
* | |||
* @return 生成专家报名临时地址 | |||
*/ | |||
@GetMapping("/getRegistrationUrl") | |||
public String getRegistrationUrl() { | |||
return expertManage.getRegistrationUrl(); | |||
} | |||
@ApiIgnore | |||
@GetMapping("/ephemeral/{uniqueId}/registration") | |||
public void getRegistrationUrl(@PathVariable String uniqueId, HttpServletResponse response) throws IOException { | |||
expertManage.redirectToRegistrationUrl(uniqueId, response); | |||
} | |||
@PostMapping("/registration") | |||
@ApiOperation("社会专家报名") | |||
@WebLog("社会专家报名") | |||
@@ -84,14 +68,14 @@ public class ExpertController { | |||
@GetMapping("/detail") | |||
@ApiOperation("专家获取专家详细信息") | |||
public ExpertFullInfoVO getExpertFullInfoDetail() { | |||
return expertManage.getExpertFullInfoDetail(null); | |||
public ExpertDetailVO getExpertDetail() { | |||
return expertManage.getExpertDetail(LoginUserUtil.getUserId()); | |||
} | |||
@GetMapping("/admin/detail") | |||
@ApiOperation("专家管理员获取专家详细信息") | |||
public ExpertFullInfoVO getExpertFullInfoDetail(@RequestParam(value = "expertUserId") @NotNull Long expertUserId) { | |||
return expertManage.getExpertFullInfoDetail(expertUserId); | |||
public ExpertDetailVO getExpertDetail(@RequestParam(value = "expertUserId") @NotNull Long userId) { | |||
return expertManage.getExpertDetail(userId); | |||
} | |||
@PostMapping("/expert-library/list") | |||
@@ -73,8 +73,13 @@ public class ExpertUserFullInfo implements Serializable { | |||
*/ | |||
private String avatarFile; | |||
/** | |||
* 身份证号 | |||
*/ | |||
private String idCard; | |||
/** | |||
* 身份证号 | |||
*/ | |||
private String idCardFile; | |||
private String officePhone; | |||
@@ -117,6 +122,11 @@ public class ExpertUserFullInfo implements Serializable { | |||
private Integer star; | |||
/** | |||
* 学历 | |||
*/ | |||
private String education; | |||
/** | |||
* 学校及专业 | |||
*/ | |||
private String schoolMajor; | |||
@@ -199,11 +209,6 @@ public class ExpertUserFullInfo implements Serializable { | |||
private String itaicCredentials; | |||
/** | |||
* 专家来源 | |||
*/ | |||
private String expertSource; | |||
/** | |||
* 其他附件 | |||
*/ | |||
private String otherFile; | |||
@@ -218,11 +223,20 @@ public class ExpertUserFullInfo implements Serializable { | |||
*/ | |||
private String socialInsureFile; | |||
// TODO 重新处理单位 | |||
/** | |||
* 职务 | |||
*/ | |||
private String duties; | |||
/** | |||
* TODO:重新处理单位 | |||
*/ | |||
@TableField(exist = false) | |||
private String companyUniqCode; | |||
// TODO 重新处理单位 | |||
/** | |||
* TODO:重新处理单位 | |||
*/ | |||
@TableField(exist = false) | |||
private String company; | |||
@@ -28,28 +28,11 @@ public class ExpertManageHelper { | |||
private final TagCache tagCache; | |||
private final DictionaryCache dictionaryCache; | |||
/** | |||
* 校验区域code | |||
* | |||
* @param expertRegionInfo | |||
*/ | |||
public void expertRegionInfoCheck(ExpertRegionInfo expertRegionInfo) { | |||
// // todo 必须为叶子节点编码 | |||
// String regionCode = expertRegionInfo.getRegionCode(); | |||
// Integer regionLevel = expertRegionInfo.getRegionLevel(); | |||
// RegionDTO regionDTO = regionCache.getByCodeAndLevel(regionCode, regionLevel); | |||
// if (Objects.isNull(regionDTO)) { | |||
// throw new BadRequestException("illegal regionInfo"); | |||
// } | |||
} | |||
/** | |||
* 校验标签code是否合法 | |||
* | |||
* @param expertProfessionalInfo | |||
* @param expertBasicInfo | |||
* @param expertProfessionalInfo \ | |||
* @param expertBasicInfo \ | |||
*/ | |||
public void tagFieldCheck(ExpertProfessionalInfo expertProfessionalInfo, ExpertBasicInfo expertBasicInfo) { | |||
List<TagFieldInfo> goodAt = expertProfessionalInfo.getGoodAt(); | |||
@@ -1,29 +1,22 @@ | |||
package com.hz.pm.api.expert.manage; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.core.bean.BeanUtil; | |||
import cn.hutool.core.util.StrUtil; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.hz.pm.api.common.constant.BizConst; | |||
import com.hz.pm.api.common.model.FileBasicInfo; | |||
import com.hz.pm.api.common.model.entity.KeyValDTO; | |||
import com.hz.pm.api.common.util.BizUtils; | |||
import com.hz.pm.api.expert.assembler.ExpertInfoCmdAssembler; | |||
import com.hz.pm.api.expert.assembler.ExpertUserInfoAssembler; | |||
import com.hz.pm.api.expert.entity.ExpertUserFullInfo; | |||
import com.hz.pm.api.expert.helper.ExpertInfoCommonHelper; | |||
import com.hz.pm.api.expert.helper.ExpertManageHelper; | |||
import com.hz.pm.api.expert.model.*; | |||
import com.hz.pm.api.expert.model.cmd.ExpertFullInfoSaveCmd; | |||
import com.hz.pm.api.expert.model.cmd.ExpertRecommendProofSaveCmd; | |||
import com.hz.pm.api.expert.model.dto.ExpertDictionaryDTO; | |||
import com.hz.pm.api.expert.model.dto.ExpertFullInfoAllDTO; | |||
import com.hz.pm.api.expert.model.dto.DictionaryVO; | |||
import com.hz.pm.api.expert.model.req.ExpertRegistrationRequest; | |||
import com.hz.pm.api.expert.model.req.ExpertUserBasicInfoSubmitRequest; | |||
import com.hz.pm.api.expert.model.vo.ExpertFullInfoVO; | |||
import com.hz.pm.api.expert.model.vo.ExpertDetailVO; | |||
import com.hz.pm.api.expert.model.vo.ExpertPortraitVO; | |||
import com.hz.pm.api.expert.service.ExpertInfoService; | |||
import com.hz.pm.api.expert.service.IExpertUserFullInfoService; | |||
import com.hz.pm.api.meeting.entity.config.WebProperties; | |||
import com.hz.pm.api.meeting.entity.domain.MeetingExpertJudge; | |||
import com.hz.pm.api.meeting.entity.dto.ExpertInvitedRecordDTO; | |||
import com.hz.pm.api.meeting.entity.enumeration.ExpertAttendStatusEnum; | |||
@@ -32,7 +25,10 @@ import com.hz.pm.api.meeting.entity.enumeration.ExpertJudgeEnum.Performance; | |||
import com.hz.pm.api.meeting.service.IMeetingExpertJudgeService; | |||
import com.hz.pm.api.meeting.service.IMeetingExpertService; | |||
import com.hz.pm.api.meta.constant.ExpertDictTypeEnum; | |||
import com.hz.pm.api.meta.model.ExpertRegionInfo; | |||
import com.hz.pm.api.meta.helper.DictionaryCache; | |||
import com.hz.pm.api.meta.model.dto.DictDTO; | |||
import com.hz.pm.api.meta.model.entity.ExpertDictionary; | |||
import com.hz.pm.api.meta.service.IExpertDictionaryService; | |||
import com.hz.pm.api.sms.constant.VerificationCodeType; | |||
import com.hz.pm.api.sms.helper.VerifyCodeCheckHelper; | |||
import com.hz.pm.api.sys.model.entity.Role; | |||
@@ -47,29 +43,17 @@ import com.hz.pm.api.user.util.LoginUserUtil; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.basic.model.GenericResult; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.cache.model.cache.CacheKey; | |||
import com.ningdatech.cache.repository.CachePlusOps; | |||
import com.ningdatech.file.entity.vo.result.AttachFileVo; | |||
import com.ningdatech.file.service.FileService; | |||
import com.ningdatech.zwdd.client.ZwddClient; | |||
import com.ningdatech.zwdd.model.dto.DingInfoByMobileDTO; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.collections4.CollectionUtils; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.http.MediaType; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import javax.servlet.http.HttpServletResponse; | |||
import java.io.IOException; | |||
import java.nio.charset.StandardCharsets; | |||
import java.time.*; | |||
import java.time.temporal.TemporalAdjusters; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import java.util.*; | |||
import java.util.concurrent.atomic.AtomicInteger; | |||
import java.util.stream.Collectors; | |||
@@ -85,60 +69,34 @@ public class ExpertManage { | |||
private final ExpertManageHelper expertManageHelper; | |||
private final IExpertUserFullInfoService expertUserFullInfoService; | |||
private final ExpertInfoService expertInfoService; | |||
private final ExpertInfoCommonHelper expertInfoCommonHelper; | |||
private final FileService fileService; | |||
private final ExpertUserInfoAssembler expertUserInfoAssembler; | |||
private final IUserInfoService userInfoService; | |||
private final ExpertMetaApplyManage expertMetaApplyManage; | |||
private final IUserRoleService userRoleService; | |||
private final IRoleService roleService; | |||
private final VerifyCodeCheckHelper verifyCodeCheckHelper; | |||
private final CachePlusOps cachePlusOps; | |||
private final ZwddClient zwddClient; | |||
private final IMeetingExpertService meetingExpertService; | |||
private final IMeetingExpertJudgeService expertJudgeService; | |||
private final IExpertDictionaryService expertDictionaryService; | |||
private final DictionaryCache dictionaryCache; | |||
@Value("${expert-registration.verify-code.check:true}") | |||
private Boolean expertRegistrationVerifyCodeCheck; | |||
private static final Duration REGISTER_EXPIRED_DURATION = Duration.ofDays(3); | |||
private static final Duration REGISTER_GEN_DURATION = Duration.ofMinutes(30); | |||
private static final String RK_REGISTER_UNIQUE_ID = "expert_registration_id:"; | |||
private static final String RK_REGISTER_UNIQUE_ID_LAST = RK_REGISTER_UNIQUE_ID + "last"; | |||
public synchronized String getRegistrationUrl() { | |||
CacheKey lastKey = new CacheKey(RK_REGISTER_UNIQUE_ID_LAST, REGISTER_GEN_DURATION); | |||
String lastUniqueId = cachePlusOps.get(lastKey); | |||
if (StrUtil.isBlank(lastUniqueId)) { | |||
lastUniqueId = BizUtils.uuid32(); | |||
CacheKey key = new CacheKey(); | |||
key.setKey(RK_REGISTER_UNIQUE_ID + lastUniqueId); | |||
key.setExpire(REGISTER_EXPIRED_DURATION); | |||
cachePlusOps.set(lastKey, lastUniqueId); | |||
String gmtUserTime = LoginUserUtil.getUserId() + "#" + System.currentTimeMillis(); | |||
cachePlusOps.set(key, gmtUserTime); | |||
} | |||
return WebProperties.webUrl + "/pm/expert/ephemeral/" + lastUniqueId + "/registration"; | |||
} | |||
public void redirectToRegistrationUrl(String uniqueId, HttpServletResponse response) throws IOException { | |||
CacheKey cacheKey = new CacheKey(RK_REGISTER_UNIQUE_ID + uniqueId); | |||
response.setContentType(MediaType.TEXT_PLAIN_VALUE); | |||
response.setCharacterEncoding(StandardCharsets.UTF_8.name()); | |||
try { | |||
if (Boolean.TRUE.equals(cachePlusOps.exists(cacheKey))) { | |||
response.sendRedirect(WebProperties.webUrl + WebProperties.expertRegistrationUrl); | |||
private Map<String, List<DictionaryVO>> listExpertDictionary(Long userId) { | |||
List<ExpertDictionary> dicts = expertDictionaryService.listByUserId(Collections.singleton(userId)); | |||
return dicts.stream().map(w -> { | |||
Optional<DictDTO> dict = dictionaryCache.getByCode(w.getDictionaryCode()); | |||
if (dict.isPresent()) { | |||
DictDTO dto = dict.get(); | |||
return new DictionaryVO(dto.getDictionaryCode(), dto.getName(), dto.getDictionaryType()); | |||
} else { | |||
response.getWriter().write("专家报名链接已失效"); | |||
return null; | |||
} | |||
} catch (Exception e) { | |||
log.error("专家报名链接重定向异常:", e); | |||
response.getWriter().write("专家报名链接访问异常"); | |||
} | |||
}).filter(Objects::nonNull).collect(Collectors.groupingBy(DictionaryVO::getDictionaryType)); | |||
} | |||
/** | |||
* 专家管理员新增专家 | |||
* | |||
@@ -163,38 +121,20 @@ public class ExpertManage { | |||
} | |||
} | |||
private void expertRecommendProofSubmit(List<DictionaryFieldInfo> recommendedWay, List<FileBasicInfo> recommendProofFile, Long expertUserId) { | |||
// 证明材料提交 | |||
ExpertRecommendProofSaveCmd expertRecommendProofSaveCmd = new ExpertRecommendProofSaveCmd(); | |||
if (CollectionUtils.isNotEmpty(recommendProofFile)) { | |||
expertRecommendProofSaveCmd.setRecommendationProofFileIdList(recommendProofFile.stream().map(FileBasicInfo::getFileId).collect(Collectors.toList())); | |||
public ExpertDetailVO getExpertDetail(Long userId) { | |||
ExpertUserFullInfo eui = expertUserFullInfoService.getByUserId(userId); | |||
if (eui == null) { | |||
throw BizException.wrap("专家信息不存在"); | |||
} | |||
List<ExpertDictionaryDTO> recommendedWayDictionaryDTOList = new ArrayList<>(); | |||
if (CollUtil.isNotEmpty(recommendedWay)) { | |||
recommendedWay.forEach(r -> { | |||
ExpertDictionaryDTO expertDictionaryDTO = new ExpertDictionaryDTO(); | |||
expertDictionaryDTO.setDictionaryCode(r.getDictionaryCode()); | |||
expertDictionaryDTO.setExpertInfoField(ExpertDictTypeEnum.RECOMMENDED_WAY.getKey()); | |||
recommendedWayDictionaryDTOList.add(expertDictionaryDTO); | |||
}); | |||
ExpertDetailVO expertDetail = BeanUtil.copyProperties(eui, ExpertDetailVO.class); | |||
expertDetail.setDictionaries(listExpertDictionary(userId)); | |||
boolean isTechExpert = false; | |||
List<DictionaryVO> expertType = expertDetail.getDictionaries().get(ExpertDictTypeEnum.EXPERT_TYPE.getKey()); | |||
if (expertType != null) { | |||
isTechExpert = expertType.get(0).getDictionaryName().contains("技术"); | |||
} | |||
expertRecommendProofSaveCmd.setRecommendedWay(recommendedWayDictionaryDTOList); | |||
expertRecommendProofSaveCmd.setUserId(expertUserId); | |||
expertInfoService.expertRecommendProofSave(expertRecommendProofSaveCmd); | |||
} | |||
public ExpertFullInfoVO getExpertFullInfoDetail(Long expertUserId) { | |||
Long currentUserId = LoginUserUtil.getUserId(); | |||
if (Objects.isNull(expertUserId)) { | |||
expertUserId = currentUserId; | |||
} | |||
ExpertFullInfoAllDTO expertUserFullInfoAll = expertInfoService.getExpertUserFullInfoAll(expertUserId); | |||
if (Objects.isNull(expertUserFullInfoAll)) { | |||
return null; | |||
} | |||
List<Long> fileIdList = expertInfoCommonHelper.getExpertFileIdList(expertUserFullInfoAll); | |||
List<AttachFileVo> attachFiles = fileService.getByIds(fileIdList); | |||
return expertUserInfoAssembler.buildExpertFullInfo(attachFiles, expertUserFullInfoAll); | |||
expertDetail.setIsTechExpert(isTechExpert); | |||
return expertDetail; | |||
} | |||
public Long generateOrGetUserId(ExpertBasicInfo basicInfo, Long operatorId) { | |||
@@ -260,12 +200,6 @@ public class ExpertManage { | |||
Long userId = generateOrGetUserId(basicInfo, operatorId); | |||
// 校验区域编码合法性 校验履职意向编码合法性 | |||
ExpertRegionInfo expertRegionInfo = basicInfo.getExpertRegionInfo(); | |||
expertManageHelper.expertRegionInfoCheck(expertRegionInfo); | |||
List<ExpertRegionInfo> expertIntentionWorkRegions = basicInfo.getExpertIntentionWorkRegions(); | |||
for (ExpertRegionInfo expertIntentionWorkRegion : expertIntentionWorkRegions) { | |||
expertManageHelper.expertRegionInfoCheck(expertIntentionWorkRegion); | |||
} | |||
ExpertEduInfo eduInfo = req.getEduInfo(); | |||
ExpertJobInfo jobInfo = req.getJobInfo(); | |||
ExpertProfessionalInfo professionalInfo = req.getProfessionalInfo(); | |||
@@ -283,13 +217,6 @@ public class ExpertManage { | |||
.buildExpertFullInfoSaveCmd(userId, basicInfo, eduInfo, jobInfo, professionalInfo); | |||
expertInfoService.saveExpertInfo(expertFullInfoSaveCmd); | |||
} | |||
ExpertRecommendInfo recommendInfo = req.getRecommendInfo(); | |||
// 推荐证明材料 | |||
List<DictionaryFieldInfo> recommendedWay = recommendInfo.getRecommendedWay(); | |||
// 推荐方式 | |||
// List<FileBasicInfo> recommendProofFile = recommendInfo.getRecommendationProofFile(); | |||
// expertRecommendProofSubmit(recommendedWay, recommendProofFile, userId); | |||
return userId; | |||
} | |||
@@ -0,0 +1,24 @@ | |||
package com.hz.pm.api.expert.model.dto; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Data; | |||
/** | |||
* <p> | |||
* DictionaryVO | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 14:29 2023/12/26 | |||
*/ | |||
@Data | |||
@AllArgsConstructor | |||
public class DictionaryVO { | |||
private String dictionaryCode; | |||
private String dictionaryName; | |||
private String dictionaryType; | |||
} |
@@ -0,0 +1,180 @@ | |||
package com.hz.pm.api.expert.model.vo; | |||
import com.hz.pm.api.expert.model.dto.DictionaryVO; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
import java.time.LocalDate; | |||
import java.time.LocalDateTime; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* <p> | |||
* ExpertDetailVO | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 10:19 2023/12/26 | |||
*/ | |||
@Data | |||
public class ExpertDetailVO { | |||
@ApiModelProperty("是否是技术专家") | |||
private Boolean isTechExpert; | |||
@ApiModelProperty(value = "用户ID") | |||
private Long userId; | |||
@ApiModelProperty(value = "信创用户ID") | |||
private String mhUserId; | |||
@ApiModelProperty(value = "专家编号") | |||
private String mhExpertNo; | |||
@ApiModelProperty(value = "是否是浙政钉用户") | |||
private String isDingUser; | |||
@ApiModelProperty(value = "手机号") | |||
private String phoneNo; | |||
@ApiModelProperty(value = "性别") | |||
private String gender; | |||
@ApiModelProperty(value = "专家姓名") | |||
private String expertName; | |||
@ApiModelProperty(value = "头像文件路径") | |||
private String avatarFile; | |||
@ApiModelProperty(value = "身份证号") | |||
private String idCard; | |||
@ApiModelProperty(value = "身份证文件路径") | |||
private String idCardFile; | |||
@ApiModelProperty(value = "办公电话") | |||
private String officePhone; | |||
@ApiModelProperty(value = "微信OpenID") | |||
private String wechatOpenId; | |||
@ApiModelProperty(value = "银行账号") | |||
private String bankNo; | |||
@ApiModelProperty(value = "银行") | |||
private String bank; | |||
@ApiModelProperty(value = "电子邮箱") | |||
private String email; | |||
@ApiModelProperty(value = "区域代码") | |||
private String regionCode; | |||
@ApiModelProperty(value = "区域级别") | |||
private Integer regionLevel; | |||
@ApiModelProperty(value = "企业ID") | |||
private String mhCompanyId; | |||
@ApiModelProperty(value = "所在单位") | |||
private String unit; | |||
@ApiModelProperty(value = "单位性质") | |||
private String unitType; | |||
@ApiModelProperty(value = "通讯地址") | |||
private String address; | |||
@ApiModelProperty(value = "码值(1:绿码 2:黄码 3:红码)") | |||
private Integer star; | |||
@ApiModelProperty(value = "学历") | |||
private String education; | |||
@ApiModelProperty(value = "学校及专业") | |||
private String schoolMajor; | |||
@ApiModelProperty(value = "毕业时间") | |||
private LocalDate graduatedAt; | |||
@ApiModelProperty(value = "技术职称及评定时间") | |||
private String academicTitle; | |||
@ApiModelProperty(value = "毕业证书文件路径") | |||
private String graduationCertFile; | |||
@ApiModelProperty(value = "学位证书文件路径") | |||
private String degreeCertFile; | |||
@ApiModelProperty(value = "开始工作时间") | |||
private LocalDate startWorkAt; | |||
@ApiModelProperty(value = "经历") | |||
private String experience; | |||
@ApiModelProperty(value = "政治面貌") | |||
private String political; | |||
@ApiModelProperty(value = "籍贯") | |||
private String hometown; | |||
@ApiModelProperty(value = "民族") | |||
private String nationality; | |||
@ApiModelProperty(value = "出生日期") | |||
private LocalDate birthday; | |||
@ApiModelProperty(value = "入库时间") | |||
private LocalDateTime inPutTime; | |||
@ApiModelProperty(value = "是否入库") | |||
private String isPut; | |||
@ApiModelProperty(value = "发证日期") | |||
private LocalDateTime awardCertDate; | |||
@ApiModelProperty(value = "信创创建人") | |||
private String mhCreateBy; | |||
@ApiModelProperty(value = "信创创建时间") | |||
private LocalDateTime mhCreateOn; | |||
@ApiModelProperty(value = "专业技术资格") | |||
private String majorCredentials; | |||
@ApiModelProperty(value = "信创技术资格") | |||
private String itaicCredentials; | |||
@ApiModelProperty(value = "其他附件") | |||
private String otherFile; | |||
@ApiModelProperty(value = "专家推荐表文件路径") | |||
private String recommendFile; | |||
@ApiModelProperty(value = "社保记录文件路径") | |||
private String socialInsureFile; | |||
@ApiModelProperty(value = "职务") | |||
private String duties; | |||
@ApiModelProperty("专家字典信息") | |||
private Map<String, List<DictionaryVO>> dictionaries; | |||
} |
@@ -1,11 +1,7 @@ | |||
package com.hz.pm.api.external; | |||
import cn.hutool.core.codec.Base64; | |||
import cn.hutool.core.codec.Base64Encoder; | |||
import cn.hutool.core.date.DatePattern; | |||
import cn.hutool.core.date.LocalDateTimeUtil; | |||
import cn.hutool.core.lang.TypeReference; | |||
import cn.hutool.core.map.MapUtil; | |||
import cn.hutool.http.HttpUtil; | |||
import cn.hutool.json.JSONUtil; | |||
import com.hz.pm.api.external.model.dto.MhExpertDTO; | |||
@@ -13,16 +9,10 @@ import com.hz.pm.api.external.model.dto.MhOrgDTO; | |||
import com.hz.pm.api.external.model.dto.MhRetDTO; | |||
import com.hz.pm.api.external.model.dto.MhUserDTO; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.lang.NonNull; | |||
import org.springframework.stereotype.Component; | |||
import java.io.UnsupportedEncodingException; | |||
import java.net.URL; | |||
import java.net.URLEncoder; | |||
import java.time.LocalDateTime; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; | |||
@@ -37,22 +27,22 @@ import static cn.hutool.core.date.DatePattern.NORM_DATETIME_FORMATTER; | |||
@Component | |||
public class MhUserOrgClient { | |||
@Value("${xc.api-host:}") | |||
private String xcApiHost; | |||
@Value("${mh.api-host:}") | |||
private String mhApiHost; | |||
public static final String UNIT_URL = "/sync/unit"; | |||
public static final String USER_URL = "/sync/user"; | |||
public static final String EXPERT_URL = "/sync/expert"; | |||
public MhRetDTO<List<MhOrgDTO>> queryOrges() { | |||
String requestUrl = xcApiHost + UNIT_URL; | |||
public MhRetDTO<List<MhOrgDTO>> queryUnits() { | |||
String requestUrl = mhApiHost + UNIT_URL; | |||
String retBody = HttpUtil.get(requestUrl); | |||
return JSONUtil.toBean(retBody, new TypeReference<MhRetDTO<List<MhOrgDTO>>>() { | |||
}, false); | |||
} | |||
public MhRetDTO<List<MhUserDTO>> queryUsers(LocalDateTime syncDateTime) { | |||
String requestUrl = xcApiHost + USER_URL; | |||
String requestUrl = mhApiHost + USER_URL; | |||
if (syncDateTime != null) { | |||
String timeString = LocalDateTimeUtil.format(syncDateTime, NORM_DATETIME_FORMATTER); | |||
requestUrl = "?syncDateTime=" + timeString; | |||
@@ -63,7 +53,7 @@ public class MhUserOrgClient { | |||
} | |||
public MhRetDTO<MhExpertDTO> queryExperts(LocalDateTime syncDateTime) { | |||
String requestUrl = xcApiHost + EXPERT_URL; | |||
String requestUrl = mhApiHost + EXPERT_URL; | |||
if (syncDateTime != null) { | |||
String timeString = LocalDateTimeUtil.format(syncDateTime, NORM_DATETIME_FORMATTER); | |||
requestUrl = "?syncDateTime=" + timeString; | |||
@@ -1,6 +1,7 @@ | |||
package com.hz.pm.api.external.controller; | |||
import com.hz.pm.api.external.MhUserOrgClient; | |||
import com.hz.pm.api.user.manage.SyncMhUserOrgManage; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.format.annotation.DateTimeFormat; | |||
import org.springframework.web.bind.annotation.GetMapping; | |||
@@ -23,17 +24,18 @@ import java.time.LocalDateTime; | |||
@RequestMapping("/api/v1/mh/sync") | |||
public class MhSyncController { | |||
private final SyncMhUserOrgManage syncMhUserOrgManage; | |||
private final MhUserOrgClient mhUserOrgClient; | |||
@GetMapping("/users") | |||
public Object getUsers(@RequestParam(value = "syncTime", required = false) | |||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime syncTime) { | |||
return mhUserOrgClient.queryUsers(syncTime); | |||
public void getUsers(@RequestParam(value = "syncTime", required = false) | |||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime syncTime) { | |||
syncMhUserOrgManage.syncUsers(syncTime); | |||
} | |||
@GetMapping("/orges") | |||
public Object getOrges() { | |||
return mhUserOrgClient.queryOrges(); | |||
@GetMapping("/units") | |||
public void getUnits() { | |||
syncMhUserOrgManage.syncUnits(); | |||
} | |||
@GetMapping("/experts") | |||
@@ -30,7 +30,7 @@ public class MhUserDTO { | |||
*/ | |||
private Long mhUnitId; | |||
/** | |||
* 用户状态 | |||
* 用户状态:1 有效、0 无效 | |||
*/ | |||
private Integer status; | |||
/** | |||
@@ -45,6 +45,10 @@ public enum ExpertDictTypeEnum { | |||
*/ | |||
EXPERT_TYPE("expert_type"), | |||
/** | |||
* 专家来源 | |||
*/ | |||
EXPERT_SOURCE("expert_source"), | |||
/** | |||
* 专家领域 | |||
*/ | |||
EXPERT_AREA("expert_area"), | |||
@@ -18,7 +18,7 @@ import lombok.Data; | |||
*/ | |||
@Data | |||
@TableName("expert_dictionary") | |||
@ApiModel(value = "ExpertDictionary对象", description = "") | |||
@ApiModel(value = "ExpertDictionary对象") | |||
public class ExpertDictionary implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
@@ -29,6 +29,8 @@ public interface IExpertDictionaryService extends IService<ExpertDictionary> { | |||
**/ | |||
List<ExpertDictionary> listByUserId(Collection<Long> userIds, ExpertDictTypeEnum dictType); | |||
List<ExpertDictionary> listByUserId(Collection<Long> userIds); | |||
default void removeByUserId(Long userId) { | |||
this.remove(Wrappers.lambdaQuery(ExpertDictionary.class).eq(ExpertDictionary::getUserId, userId)); | |||
} | |||
@@ -14,7 +14,7 @@ import java.util.List; | |||
/** | |||
* <p> | |||
* 服务实现类 | |||
* 服务实现类 | |||
* </p> | |||
* | |||
* @author Liuxinxin | |||
@@ -32,4 +32,10 @@ public class ExpertDictionaryServiceImpl extends ServiceImpl<ExpertDictionaryMap | |||
return list(query); | |||
} | |||
@Override | |||
public List<ExpertDictionary> listByUserId(Collection<Long> userIds) { | |||
LambdaQueryWrapper<ExpertDictionary> query = Wrappers.lambdaQuery(ExpertDictionary.class) | |||
.in(ExpertDictionary::getUserId, userIds); | |||
return list(query); | |||
} | |||
} |
@@ -15,4 +15,5 @@ public enum UserAvailableEnum { | |||
* 禁用 | |||
*/ | |||
DISABLE | |||
} |
@@ -0,0 +1,18 @@ | |||
package com.hz.pm.api.user.controller; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.stereotype.Controller; | |||
/** | |||
* <p> | |||
* 组织表 前端控制器 | |||
* </p> | |||
* | |||
* @author CMM | |||
* @since 2023-12-25 | |||
*/ | |||
@Controller | |||
@RequestMapping("/api.user/mhUnit") | |||
public class MhUnitController { | |||
} |
@@ -85,7 +85,14 @@ public class UserAuthController { | |||
@ApiOperation(value = "代登陆") | |||
@ApiImplicitParams({ | |||
@ApiImplicitParam(name = "userId", value = "账号", required = true, paramType = "form", dataType = "String")}) | |||
public void agentLogin(@RequestParam(value = "userId", required = true) String userId) { | |||
public void agentLogin(@RequestParam(value = "userId") String userId) { | |||
// 不实现任何内容,只是为了出api文档 | |||
} | |||
@PostMapping(value = "/mh-login", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) | |||
@ApiOperation(value = "代登陆") | |||
@ApiImplicitParam(name = "code", value = "账号", paramType = "form") | |||
public void mhLogin(@RequestParam(value = "code") String code) { | |||
// 不实现任何内容,只是为了出api文档 | |||
} | |||
@@ -95,8 +102,8 @@ public class UserAuthController { | |||
@ApiImplicitParam(name = "credential", value = "凭证", required = true, paramType = "form", dataType = "String"), | |||
@ApiImplicitParam(name = "platform", value = "平台 PROVINCIAL_BUREAU,省局", required = true, paramType = "form", dataType = "String") | |||
}) | |||
public void commonLogin(@RequestParam(value = "credential", required = true) String credential | |||
, @RequestParam(value = "platform", required = true) String platform) { | |||
public void commonLogin(@RequestParam(value = "credential") String credential | |||
, @RequestParam(value = "platform") String platform) { | |||
// 不实现任何内容,只是为了出api文档 | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
package com.hz.pm.api.user.entity; | |||
import com.baomidou.mybatisplus.annotation.IdType; | |||
import com.baomidou.mybatisplus.annotation.TableId; | |||
import com.baomidou.mybatisplus.annotation.TableName; | |||
import java.io.Serializable; | |||
import java.time.LocalDateTime; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
/** | |||
* <p> | |||
* 组织表 | |||
* </p> | |||
* | |||
* @author CMM | |||
* @since 2023-12-25 | |||
*/ | |||
@Data | |||
@TableName("MH_UNIT") | |||
@ApiModel(value = "MhUnit对象", description = "组织表") | |||
public class MhUnit implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
@TableId(type = IdType.INPUT) | |||
private Long id; | |||
private String name; | |||
private Long parentId; | |||
private Short sort; | |||
private LocalDateTime createOn; | |||
private LocalDateTime updateOn; | |||
} |
@@ -11,6 +11,9 @@ import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
import java.time.LocalDateTime; | |||
/** | |||
* <p> | |||
* | |||
@@ -19,12 +22,12 @@ import java.time.LocalDateTime; | |||
* @author Lierbao | |||
* @since 2023-02-01 | |||
*/ | |||
@TableName("nd_user_info") | |||
@Builder | |||
@Data | |||
@AllArgsConstructor | |||
@Builder | |||
@NoArgsConstructor | |||
@ApiModel(value = "NdUserInfo对象") | |||
@AllArgsConstructor | |||
@TableName("nd_user_info") | |||
@ApiModel(value = "UserInfo对象") | |||
public class UserInfo implements Serializable { | |||
private static final long serialVersionUID = 1L; | |||
@@ -32,6 +35,11 @@ public class UserInfo implements Serializable { | |||
@TableId(type = IdType.AUTO) | |||
private Long id; | |||
/** | |||
* 信创系统用户ID | |||
*/ | |||
private String mhUserId; | |||
private String username; | |||
private String mobile; | |||
@@ -40,12 +48,19 @@ public class UserInfo implements Serializable { | |||
private Long accountId; | |||
private String wechatOpenId; | |||
/** | |||
* 账号状态 | |||
*/ | |||
private String available; | |||
private String employeeCode; | |||
private String regionCode; | |||
private Long mhUnitId; | |||
private String empPosUnitCode; | |||
private String empPosUnitName; | |||
@@ -0,0 +1,329 @@ | |||
package com.hz.pm.api.user.manage; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.core.collection.ListUtil; | |||
import cn.hutool.core.date.DateUtil; | |||
import cn.hutool.core.date.LocalDateTimeUtil; | |||
import cn.hutool.core.util.StrUtil; | |||
import cn.hutool.json.JSONUtil; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.hz.pm.api.common.util.BizUtils; | |||
import com.hz.pm.api.expert.entity.ExpertUserFullInfo; | |||
import com.hz.pm.api.expert.service.IExpertUserFullInfoService; | |||
import com.hz.pm.api.external.MhUserOrgClient; | |||
import com.hz.pm.api.external.model.dto.*; | |||
import com.hz.pm.api.meta.constant.ExpertDictTypeEnum; | |||
import com.hz.pm.api.meta.helper.DictionaryCache; | |||
import com.hz.pm.api.meta.model.dto.DictDTO; | |||
import com.hz.pm.api.meta.model.entity.ExpertDictionary; | |||
import com.hz.pm.api.meta.service.IExpertDictionaryService; | |||
import com.hz.pm.api.user.constant.UserAvailableEnum; | |||
import com.hz.pm.api.user.entity.MhUnit; | |||
import com.hz.pm.api.user.entity.UserInfo; | |||
import com.hz.pm.api.user.service.IMhUnitService; | |||
import com.hz.pm.api.user.service.IUserInfoService; | |||
import com.hz.pm.api.user.task.SyncMhUserProperties; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.collections4.SetUtils; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import java.time.LocalDate; | |||
import java.time.LocalDateTime; | |||
import java.time.format.DateTimeFormatter; | |||
import java.util.*; | |||
import static com.hz.pm.api.meta.constant.ExpertDictTypeEnum.*; | |||
/** | |||
* <p> | |||
* SyncMhUserManage | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:54 2023/12/25 | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
public class SyncMhUserOrgManage { | |||
private final IExpertUserFullInfoService expertUserFullInfoService; | |||
private final IUserInfoService userInfoService; | |||
private final MhUserOrgClient mhUserOrgClient; | |||
private final SyncMhUserProperties syncMhUserProperties; | |||
private final IMhUnitService mhUnitService; | |||
private final DictionaryCache dictionaryCache; | |||
private final IExpertDictionaryService expertDictionaryService; | |||
public void syncUsers(LocalDateTime syncDateTime) { | |||
MhRetDTO<List<MhUserDTO>> mhRet = mhUserOrgClient.queryUsers(syncDateTime); | |||
if (mhRet.isOk()) { | |||
List<MhUserDTO> mhUsers = mhRet.getData(); | |||
if (CollUtil.isEmpty(mhUsers)) { | |||
return; | |||
} | |||
Integer batchSize = syncMhUserProperties.getBatchSize(); | |||
List<List<MhUserDTO>> mhUserParts = ListUtil.partition(mhUsers, batchSize); | |||
for (List<MhUserDTO> part : mhUserParts) { | |||
List<String> mhUserIds = CollUtils.fieldList(part, MhUserDTO::getUserId); | |||
Map<String, Long> userIdMap = userInfoService.listUserIdByMhUserIds(mhUserIds); | |||
List<UserInfo> savedList = new ArrayList<>(); | |||
for (MhUserDTO mhUser : part) { | |||
if (StrUtil.isBlank(mhUser.getUserId())) { | |||
continue; | |||
} | |||
UserInfo userInfo = new UserInfo(); | |||
userInfo.setMhUserId(mhUser.getUserId()); | |||
if (Boolean.TRUE.equals(mhUser.getIsZzdAccount())) { | |||
userInfo.setAccountId(Long.parseLong(mhUser.getAccountId())); | |||
} | |||
UserAvailableEnum userStatus = getUserAvailable(mhUser.getStatus()); | |||
userInfo.setAvailable(userStatus.name()); | |||
userInfo.setRealName(mhUser.getUserName()); | |||
userInfo.setUsername(mhUser.getAccount()); | |||
userInfo.setId(userIdMap.get(mhUser.getUserId())); | |||
userInfo.setRegionCode("330100"); | |||
userInfo.setMhUnitId(mhUser.getMhUnitId()); | |||
savedList.add(userInfo); | |||
} | |||
if (!savedList.isEmpty()) { | |||
log.info("同步用户数量:{}", savedList.size()); | |||
userInfoService.saveOrUpdateBatch(savedList); | |||
} | |||
} | |||
} else { | |||
log.error("同步用户信息失败:{}", JSONUtil.toJsonStr(mhRet)); | |||
} | |||
} | |||
private UserAvailableEnum getUserAvailable(Integer status) { | |||
return status == null || status == 0 ? UserAvailableEnum.DISABLE : UserAvailableEnum.ENABLE; | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public void syncUnits() { | |||
MhRetDTO<List<MhOrgDTO>> mhRet = mhUserOrgClient.queryUnits(); | |||
if (mhRet.isOk()) { | |||
List<MhOrgDTO> mhUnits = mhRet.getData(); | |||
if (mhUnits == null || mhUnits.isEmpty()) { | |||
log.info("未获取到组织信息"); | |||
return; | |||
} | |||
List<Long> unitIds = CollUtils.fieldList(mhUnits, MhOrgDTO::getUnitId); | |||
List<Long> existsUnitIds = mhUnitService.listUnitIds(unitIds); | |||
List<MhUnit> saveList = new ArrayList<>(); | |||
List<MhUnit> updateList = new ArrayList<>(); | |||
for (MhOrgDTO org : mhUnits) { | |||
MhUnit unit = new MhUnit(); | |||
unit.setSort(Short.parseShort(org.getSortNum())); | |||
unit.setName(org.getUnitName()); | |||
unit.setParentId(org.getUnitPid()); | |||
unit.setId(org.getUnitId()); | |||
if (existsUnitIds.contains(unit.getId())) { | |||
updateList.add(unit); | |||
} else { | |||
saveList.add(unit); | |||
} | |||
} | |||
mhUnitService.saveBatch(saveList); | |||
mhUnitService.updateBatchById(updateList); | |||
} else { | |||
log.error("同步组织信息失败:{}", JSONUtil.toJsonStr(mhRet)); | |||
} | |||
} | |||
public void syncExperts(LocalDateTime syncDateTime) { | |||
MhRetDTO<MhExpertDTO> mhRet = mhUserOrgClient.queryExperts(syncDateTime); | |||
if (mhRet.isOk()) { | |||
MhExpertDTO data = mhRet.getData(); | |||
if (data == null) { | |||
return; | |||
} | |||
List<MhReviewExpertDTO> reviewExperts = data.getReviewExpertVOList(); | |||
if (CollUtil.isNotEmpty(reviewExperts)) { | |||
saveReviewExperts(reviewExperts); | |||
} | |||
List<MhTechExpertDTO> techExperts = data.getTechnicalExpertVOList(); | |||
if (CollUtil.isNotEmpty(techExperts)) { | |||
saveTechExperts(techExperts); | |||
} | |||
} else { | |||
log.error("同步专家信息失败:{}", JSONUtil.toJsonStr(mhRet)); | |||
} | |||
} | |||
private void saveReviewExperts(List<MhReviewExpertDTO> reviewExperts) { | |||
List<String> expertNos = CollUtils.fieldList(reviewExperts, MhReviewExpertDTO::getExpertNo); | |||
Map<String, ExpertUserFullInfo> expertMap = getExpertsMapMhExpertNo(expertNos); | |||
for (MhReviewExpertDTO expert : reviewExperts) { | |||
ExpertUserFullInfo eui = new ExpertUserFullInfo(); | |||
eui.setWechatOpenId(expert.getOpenId()); | |||
eui.setAvatarFile(expert.getFilePhoto()); | |||
BizUtils.notNull(expert.getBirthday(), w -> eui.setBirthday(DateUtil.date(w).toLocalDateTime().toLocalDate())); | |||
eui.setExpertName(expert.getName()); | |||
eui.setMhExpertNo(expert.getExpertNo()); | |||
eui.setEmail(expert.getEmail()); | |||
eui.setExperience(expert.getExperience()); | |||
eui.setGender(expert.getGender()); | |||
eui.setStar(expert.getStar()); | |||
eui.setSchoolMajor(expert.getSchool()); | |||
LocalDateTime inputTime = DateUtil.parse(expert.getInPutTime()).toLocalDateTime(); | |||
eui.setInPutTime(inputTime); | |||
eui.setEducation(expert.getEducation()); | |||
eui.setNationality(expert.getNation()); | |||
eui.setHometown(expert.getNativePlace()); | |||
eui.setIsPut(expert.getIsPut()); | |||
eui.setPhoneNo(expert.getPhone()); | |||
eui.setUnit(expert.getUnit()); | |||
eui.setUnitType(expert.getNature()); | |||
eui.setOfficePhone(expert.getTel()); | |||
eui.setAcademicTitle(expert.getTitle()); | |||
eui.setPolitical(expert.getPolitical()); | |||
eui.setDuties(expert.getDuties()); | |||
eui.setAddress(expert.getPlace()); | |||
ExpertUserFullInfo oldEui = expertMap.get(eui.getMhExpertNo()); | |||
if (oldEui == null) { | |||
UserInfo expertUser = new UserInfo(); | |||
expertUser.setUsername(expert.getName()); | |||
expertUser.setMobile(expert.getPhone()); | |||
expertUser.setRealName(expert.getName()); | |||
userInfoService.save(expertUser); | |||
eui.setUserId(expertUser.getId()); | |||
} else { | |||
eui.setUserId(oldEui.getUserId()); | |||
eui.setId(oldEui.getId()); | |||
} | |||
expertUserFullInfoService.saveOrUpdate(eui); | |||
String expertLevel = expert.getExpertLevel(); | |||
List<ExpertDictionary> dicts = new ArrayList<>(); | |||
Optional<DictDTO> levelDict = dictionaryCache.getByDictTypeAndName(EXPERT_LEVEL.getKey(), expertLevel); | |||
levelDict.ifPresent(dict -> dicts.add(getExpertDictionary(eui.getUserId(), dict))); | |||
String grade = expert.getGrade(); | |||
Optional<DictDTO> gradeDict = dictionaryCache.getByDictTypeAndName(EXPERT_LIBRARY.getKey(), grade); | |||
gradeDict.ifPresent(dict -> dicts.add(getExpertDictionary(eui.getUserId(), dict))); | |||
String area = expert.getArea(); | |||
Optional<DictDTO> areaDict = dictionaryCache.getByDictTypeAndName(EXPERT_AREA.getKey(), area); | |||
areaDict.ifPresent(dict -> dicts.add(getExpertDictionary(eui.getUserId(), dict))); | |||
String skills = expert.getSkills(); | |||
if (StrUtil.isNotBlank(skills)) { | |||
List<ExpertDictionary> skillsDicts = getSkillsDicts(skills, eui.getUserId()); | |||
if (!skillsDicts.isEmpty()) { | |||
dicts.addAll(skillsDicts); | |||
} | |||
} | |||
expertDictionaryService.removeByUserId(eui.getUserId()); | |||
expertDictionaryService.saveBatch(dicts); | |||
} | |||
} | |||
private void saveTechExperts(List<MhTechExpertDTO> techExperts) { | |||
List<String> expertNos = CollUtils.fieldList(techExperts, MhTechExpertDTO::getExpertNo); | |||
Map<String, ExpertUserFullInfo> expertMap = getExpertsMapMhExpertNo(expertNos); | |||
for (MhTechExpertDTO expert : techExperts) { | |||
ExpertUserFullInfo eui = new ExpertUserFullInfo(); | |||
eui.setWechatOpenId(expert.getOpenId()); | |||
eui.setAvatarFile(expert.getFilePhoto()); | |||
BizUtils.notNull(expert.getBirthday(), w -> eui.setBirthday(DateUtil.date(w).toLocalDateTime().toLocalDate())); | |||
eui.setExpertName(expert.getName()); | |||
eui.setMhExpertNo(expert.getExpertNo()); | |||
eui.setExperience(expert.getTextExperience()); | |||
eui.setGender(expert.getGender()); | |||
eui.setStar(expert.getStar()); | |||
eui.setIdCard(expert.getIdCard()); | |||
eui.setIdCardFile(expert.getFileIdCard()); | |||
eui.setRecommendFile(expert.getFileRecommend()); | |||
eui.setSocialInsureFile(expert.getFileSocial()); | |||
eui.setGraduationCertFile(expert.getFileDiploma()); | |||
eui.setDegreeCertFile(expert.getFileDegree()); | |||
eui.setMhCreateOn(LocalDateTimeUtil.of(expert.getCreateTime())); | |||
eui.setMhCreateBy(expert.getCreateUser()); | |||
LocalDateTime inputTime = DateUtil.parse(expert.getInPutTime()).toLocalDateTime(); | |||
eui.setInPutTime(inputTime); | |||
eui.setEducation(expert.getEducation()); | |||
eui.setIsPut(expert.getIsPut()); | |||
eui.setPhoneNo(expert.getPhone()); | |||
eui.setMhCompanyId(expert.getCompanyId()); | |||
eui.setPolitical(expert.getPolitical()); | |||
eui.setItaicCredentials(expert.getCredentialsSpeciality()); | |||
eui.setMajorCredentials(expert.getCredentialsTechnology()); | |||
eui.setOtherFile(expert.getFileOther()); | |||
BizUtils.notBlank(expert.getCartDate(),w -> { | |||
LocalDateTime certDate = DateUtil.parseDate(w).toLocalDateTime(); | |||
eui.setAwardCertDate(certDate); | |||
}); | |||
ExpertUserFullInfo oldEui = expertMap.get(eui.getMhExpertNo()); | |||
if (oldEui == null) { | |||
UserInfo expertUser = new UserInfo(); | |||
expertUser.setUsername(expert.getName()); | |||
expertUser.setMobile(expert.getPhone()); | |||
expertUser.setRealName(expert.getName()); | |||
userInfoService.save(expertUser); | |||
eui.setUserId(expertUser.getId()); | |||
} else { | |||
eui.setUserId(oldEui.getUserId()); | |||
eui.setId(oldEui.getId()); | |||
} | |||
expertUserFullInfoService.saveOrUpdate(eui); | |||
List<ExpertDictionary> dicts = new ArrayList<>(); | |||
// 专家级别 | |||
String expertLevel = expert.getExpertLevel(); | |||
Optional<DictDTO> levelDict = dictionaryCache.getByDictTypeAndName(EXPERT_LEVEL.getKey(), expertLevel); | |||
levelDict.ifPresent(dict -> dicts.add(getExpertDictionary(eui.getUserId(), dict))); | |||
// 专家来源 | |||
String expertCate = expert.getExpertCate(); | |||
Optional<DictDTO> sourceDict = dictionaryCache.getByDictTypeAndName(EXPERT_SOURCE.getKey(), expertCate); | |||
sourceDict.ifPresent(dict -> dicts.add(getExpertDictionary(eui.getUserId(), dict))); | |||
String skills = expert.getSkills(); | |||
if (StrUtil.isNotBlank(skills)) { | |||
List<ExpertDictionary> skillsDicts = getSkillsDicts(skills, eui.getUserId()); | |||
if (!skillsDicts.isEmpty()) { | |||
dicts.addAll(skillsDicts); | |||
} | |||
} | |||
expertDictionaryService.removeByUserId(eui.getUserId()); | |||
expertDictionaryService.saveBatch(dicts); | |||
} | |||
} | |||
private List<ExpertDictionary> getSkillsDicts(String skills, Long userId) { | |||
List<ExpertDictionary> dicts = new ArrayList<>(); | |||
List<DictDTO> skillsDict = dictionaryCache.listDictByDictType(EXPERT_SPECIALTY.getKey()); | |||
if (StrUtil.isNotBlank(skills)) { | |||
for (String skill : CollUtil.newHashSet(skills.split("[,、,]"))) { | |||
Optional<DictDTO> first = skillsDict.stream() | |||
.filter(dict -> dict.getName().equals(skill.trim())) | |||
.findFirst(); | |||
first.ifPresent(dict -> dicts.add(getExpertDictionary(userId, dict))); | |||
} | |||
} | |||
return dicts; | |||
} | |||
private ExpertDictionary getExpertDictionary(Long userId, DictDTO dict) { | |||
ExpertDictionary dictionary = new ExpertDictionary(); | |||
dictionary.setUserId(userId); | |||
dictionary.setDictionaryCode(dict.getDictionaryCode()); | |||
dictionary.setExpertInfoField(dict.getDictionaryType()); | |||
return dictionary; | |||
} | |||
private Map<String, ExpertUserFullInfo> getExpertsMapMhExpertNo(List<String> expertNos) { | |||
LambdaQueryWrapper<ExpertUserFullInfo> euiQuery = Wrappers.lambdaQuery(ExpertUserFullInfo.class) | |||
.select(ExpertUserFullInfo::getMhExpertNo, ExpertUserFullInfo::getUserId, ExpertUserFullInfo::getId) | |||
.in(ExpertUserFullInfo::getMhExpertNo, expertNos); | |||
List<ExpertUserFullInfo> experts = expertUserFullInfoService.list(euiQuery); | |||
return CollUtils.listToMap(experts, ExpertUserFullInfo::getMhExpertNo); | |||
} | |||
} |
@@ -0,0 +1,16 @@ | |||
package com.hz.pm.api.user.mapper; | |||
import com.hz.pm.api.user.entity.MhUnit; | |||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |||
/** | |||
* <p> | |||
* 组织表 Mapper 接口 | |||
* </p> | |||
* | |||
* @author CMM | |||
* @since 2023-12-25 | |||
*/ | |||
public interface MhUnitMapper extends BaseMapper<MhUnit> { | |||
} |
@@ -0,0 +1,5 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |||
<mapper namespace="com.hz.pm.api.user.mapper.MhUnitMapper"> | |||
</mapper> |
@@ -34,6 +34,8 @@ public class AuthProperties { | |||
*/ | |||
private String agentLoginUrl; | |||
private String mhLoginUrl; | |||
/** | |||
* 跳转登陆接口(目前只有省局跳转) | |||
*/ | |||
@@ -1,5 +1,6 @@ | |||
package com.hz.pm.api.user.security.auth; | |||
import com.hz.pm.api.user.security.auth.mh.MhAuthSecurityConfig; | |||
import com.ningdatech.basic.util.NdJsonUtil; | |||
import com.ningdatech.basic.util.StrPool; | |||
import com.hz.pm.api.common.constant.BizConst; | |||
@@ -37,6 +38,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||
private final DefaultLogoutSuccessHandler logoutSuccessHandler; | |||
private final DefaultExpiredSessionStrategy defaultExpiredSessionStrategy; | |||
private final AgentAuthSecurityConfig agentAuthSecurityConfig; | |||
private final MhAuthSecurityConfig mhAuthSecurityConfig; | |||
private final CommonAuthSecurityConfig commonAuthSecurityConfig; | |||
@Override | |||
@@ -47,6 +49,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { | |||
.and().apply(credentialAuthSecurityConfig) | |||
.and().apply(agentAuthSecurityConfig) | |||
.and().apply(commonAuthSecurityConfig) | |||
.and().apply(mhAuthSecurityConfig) | |||
.and() | |||
.authorizeRequests() | |||
.antMatchers(authProperties.getIgnoreAuthUrlsArray()) | |||
@@ -0,0 +1,66 @@ | |||
package com.hz.pm.api.user.security.auth.mh; | |||
import com.hz.pm.api.user.security.auth.model.WebRequestDetails; | |||
import com.ningdatech.basic.exception.BizException; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.springframework.http.HttpMethod; | |||
import org.springframework.security.authentication.AuthenticationServiceException; | |||
import org.springframework.security.authentication.BadCredentialsException; | |||
import org.springframework.security.authentication.InternalAuthenticationServiceException; | |||
import org.springframework.security.core.Authentication; | |||
import org.springframework.security.core.AuthenticationException; | |||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; | |||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; | |||
import javax.servlet.http.HttpServletRequest; | |||
import javax.servlet.http.HttpServletResponse; | |||
/** | |||
* <p> | |||
* AgentAuthFilter | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:20 2023/12/26 | |||
*/ | |||
public class MhAuthFilter extends AbstractAuthenticationProcessingFilter { | |||
private boolean postOnly = true; | |||
private static final String AUTH_CODE = "code"; | |||
// ~ Constructors | |||
// =================================================================================================== | |||
public MhAuthFilter(String processingUrl) { | |||
super(new AntPathRequestMatcher(processingUrl, HttpMethod.POST.name())); | |||
} | |||
// ======================================================================================================== | |||
@Override | |||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) | |||
throws AuthenticationException { | |||
if (postOnly && !request.getMethod().equals(HttpMethod.POST.name())) { | |||
throw new AuthenticationServiceException("请求方法错误"); | |||
} | |||
String authCode = request.getParameter(AUTH_CODE); | |||
if (StringUtils.isBlank(authCode)) { | |||
throw new BadCredentialsException("授权码不能为空"); | |||
} | |||
// 获取临时授权码对应的mhUserId或者openId | |||
String mhUserIdOrOpenId = "952795279527"; | |||
try { | |||
MhAuthToken authRequest = new MhAuthToken(mhUserIdOrOpenId, mhUserIdOrOpenId); | |||
authRequest.setDetails(new WebRequestDetails(request)); | |||
return this.getAuthenticationManager().authenticate(authRequest); | |||
} catch (AuthenticationException e) { | |||
throw new BadCredentialsException("用户id 不能为空"); | |||
} catch (BizException e) { | |||
throw new BadCredentialsException(e.getMessage()); | |||
} catch (Exception e) { | |||
throw new InternalAuthenticationServiceException("授权失败:", e); | |||
} | |||
} | |||
} |
@@ -0,0 +1,38 @@ | |||
package com.hz.pm.api.user.security.auth.mh; | |||
import lombok.Setter; | |||
import org.springframework.security.authentication.AuthenticationProvider; | |||
import org.springframework.security.core.Authentication; | |||
import org.springframework.security.core.AuthenticationException; | |||
import org.springframework.security.core.userdetails.UserDetails; | |||
import org.springframework.security.core.userdetails.UserDetailsService; | |||
/** | |||
* <p> | |||
* AgentAuthProvider | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 20:41 2023/12/15 | |||
*/ | |||
@Setter | |||
public class MhAuthProvider implements AuthenticationProvider { | |||
private UserDetailsService userDetailsService; | |||
@Override | |||
public Authentication authenticate(Authentication authentication) throws AuthenticationException { | |||
MhAuthToken authenticationToken = (MhAuthToken) authentication; | |||
String principal = (String) authenticationToken.getPrincipal(); | |||
UserDetails user = userDetailsService.loadUserByUsername(principal); | |||
// 将用户定义的user放入token中,这样可以在session中查询到所有自定义的用户信息 | |||
return new MhAuthToken(user, user.getPassword(), user.getAuthorities()); | |||
} | |||
@Override | |||
public boolean supports(Class<?> authentication) { | |||
return MhAuthToken.class.isAssignableFrom(authentication); | |||
} | |||
} |
@@ -0,0 +1,58 @@ | |||
package com.hz.pm.api.user.security.auth.mh; | |||
import com.hz.pm.api.user.security.auth.AuthProperties; | |||
import org.springframework.beans.factory.annotation.Qualifier; | |||
import org.springframework.security.authentication.AuthenticationManager; | |||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter; | |||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |||
import org.springframework.security.core.userdetails.UserDetailsService; | |||
import org.springframework.security.web.DefaultSecurityFilterChain; | |||
import org.springframework.security.web.authentication.AuthenticationFailureHandler; | |||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; | |||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* <p> | |||
* MhAuthSecurityConfig | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 14:24 2023/12/16 | |||
*/ | |||
@Component | |||
public class MhAuthSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { | |||
protected final AuthenticationSuccessHandler defaultLoginSuccessHandler; | |||
protected final AuthenticationFailureHandler defaultLoginFailureHandler; | |||
private final UserDetailsService mhLoginUserDetailService; | |||
private final AuthProperties authProperties; | |||
public MhAuthSecurityConfig(@Qualifier(value = "defaultLoginSuccessHandler") AuthenticationSuccessHandler loginSuccessHandler, | |||
@Qualifier(value = "defaultLoginFailureHandler") AuthenticationFailureHandler loginFailureHandler, | |||
@Qualifier(value = "mhLoginUserDetailService") UserDetailsService userDetailsService, | |||
AuthProperties authProperties) { | |||
this.defaultLoginSuccessHandler = loginSuccessHandler; | |||
this.defaultLoginFailureHandler = loginFailureHandler; | |||
this.mhLoginUserDetailService = userDetailsService; | |||
this.authProperties = authProperties; | |||
} | |||
@Override | |||
public void configure(HttpSecurity http) { | |||
MhAuthFilter agentAuthFilter = | |||
new MhAuthFilter(authProperties.getMhLoginUrl()); | |||
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class); | |||
agentAuthFilter.setAuthenticationManager(authenticationManager); | |||
agentAuthFilter.setAuthenticationSuccessHandler(defaultLoginSuccessHandler); | |||
agentAuthFilter.setAuthenticationFailureHandler(defaultLoginFailureHandler); | |||
MhAuthProvider authenticationProvider = new MhAuthProvider(); | |||
authenticationProvider.setUserDetailsService(mhLoginUserDetailService); | |||
http.authenticationProvider(authenticationProvider) | |||
.addFilterAfter(agentAuthFilter, UsernamePasswordAuthenticationFilter.class); | |||
} | |||
} |
@@ -0,0 +1,78 @@ | |||
package com.hz.pm.api.user.security.auth.mh; | |||
import org.springframework.security.authentication.AbstractAuthenticationToken; | |||
import org.springframework.security.core.GrantedAuthority; | |||
import org.springframework.security.core.SpringSecurityCoreVersion; | |||
import java.util.Collection; | |||
/** | |||
* <p> | |||
* MhAuthToken | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:21 2023/12/26 | |||
*/ | |||
public class MhAuthToken extends AbstractAuthenticationToken { | |||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | |||
private final Object principal; | |||
private final Object credentials; | |||
/** | |||
* This constructor can be safely used by any code that wishes to create a | |||
* <code>UsernamePasswordAuthenticationToken</code>, as the {@link #isAuthenticated()} will return | |||
* <code>false</code>. | |||
*/ | |||
public MhAuthToken(String principal, String credentials) { | |||
super(null); | |||
this.principal = principal; | |||
this.credentials = credentials; | |||
setAuthenticated(false); | |||
} | |||
/** | |||
* This constructor should only be used by <code>AuthenticationManager</code> or <code>AuthenticationProvider</code> | |||
* implementations that are satisfied with producing a trusted (i.e. {@link #isAuthenticated()} = <code>true</code>) | |||
* authentication token. | |||
* | |||
* @param principal \ | |||
* @param authorities \ | |||
*/ | |||
public MhAuthToken(Object principal, Object credentials, | |||
Collection<? extends GrantedAuthority> authorities) { | |||
super(authorities); | |||
this.principal = principal; | |||
this.credentials = credentials; | |||
// must use super, as we override | |||
super.setAuthenticated(true); | |||
} | |||
@Override | |||
public Object getCredentials() { | |||
return this.credentials; | |||
} | |||
@Override | |||
public Object getPrincipal() { | |||
return this.principal; | |||
} | |||
@Override | |||
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { | |||
if (isAuthenticated) { | |||
throw new IllegalArgumentException( | |||
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); | |||
} | |||
super.setAuthenticated(false); | |||
} | |||
@Override | |||
public void eraseCredentials() { | |||
super.eraseCredentials(); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
package com.hz.pm.api.user.security.auth.mh; | |||
import com.hz.pm.api.common.helper.UserInfoHelper; | |||
import com.hz.pm.api.user.constant.UserAvailableEnum; | |||
import com.hz.pm.api.user.security.auth.model.UserFullInfoDTO; | |||
import com.hz.pm.api.user.security.auth.model.UserInfoDetails; | |||
import com.hz.pm.api.user.security.auth.validate.CommonLoginException; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.security.core.userdetails.UserDetailsService; | |||
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |||
import org.springframework.stereotype.Service; | |||
import java.util.Objects; | |||
import static com.hz.pm.api.user.constant.UserAvailableEnum.DISABLE; | |||
/** | |||
* <p> | |||
* AgentLoginUserDetailService | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:22 2023/12/26 | |||
*/ | |||
@Service("mhLoginUserDetailService") | |||
@RequiredArgsConstructor | |||
public class MhLoginUserDetailService implements UserDetailsService { | |||
private final UserInfoHelper userInfoHelper; | |||
@Override | |||
public UserInfoDetails loadUserByUsername(String username) throws UsernameNotFoundException { | |||
UserFullInfoDTO userInfo = userInfoHelper.getUserFullInfoByMhUserIdOrOpenId(username); | |||
if (userInfo == null || DISABLE.equals(userInfo.getAvailable())) { | |||
throw new UsernameNotFoundException("用户不存在或已被禁用"); | |||
} | |||
UserInfoDetails userDetails = new UserInfoDetails(); | |||
userDetails.setUserId(userInfo.getUserId()); | |||
userDetails.setUsername(userInfo.getUsername()); | |||
userDetails.setRealName(userInfo.getRealName()); | |||
userDetails.setUserRoleList(userInfo.getUserRoleList()); | |||
userDetails.setRegionCode(userInfo.getRegionCode()); | |||
userDetails.setRegionLevel(userInfo.getRegionLevel()); | |||
userDetails.setIdentifier(userInfo.getIdentifier()); | |||
userDetails.setPassword(userInfo.getCredential()); | |||
userDetails.setEmployeeCode(userInfo.getEmployeeCode()); | |||
userDetails.setOrganizationCode(userInfo.getOrganizationCode()); | |||
userDetails.setOrganizationName(userInfo.getOrganizationName()); | |||
userDetails.setEmpPosUnitCode(userInfo.getEmpPosUnitCode()); | |||
userDetails.setEmpPosUnitName(userInfo.getOrganizationName()); | |||
return userDetails; | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
package com.hz.pm.api.user.service; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.hz.pm.api.user.entity.MhUnit; | |||
import com.baomidou.mybatisplus.extension.service.IService; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import java.util.Collection; | |||
import java.util.List; | |||
/** | |||
* <p> | |||
* 组织表 服务类 | |||
* </p> | |||
* | |||
* @author CMM | |||
* @since 2023-12-25 | |||
*/ | |||
public interface IMhUnitService extends IService<MhUnit> { | |||
default List<Long> listUnitIds(Collection<Long> unitIds){ | |||
LambdaQueryWrapper<MhUnit> query = Wrappers.lambdaQuery(MhUnit.class) | |||
.select(MhUnit::getId) | |||
.in(MhUnit::getId,unitIds); | |||
return CollUtils.fieldList(list(query), MhUnit::getId); | |||
} | |||
} |
@@ -1,10 +1,14 @@ | |||
package com.hz.pm.api.user.service; | |||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.baomidou.mybatisplus.extension.service.IService; | |||
import com.hz.pm.api.user.entity.UserInfo; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Map; | |||
/** | |||
* <p> | |||
@@ -23,4 +27,12 @@ public interface IUserInfoService extends IService<UserInfo> { | |||
UserInfo getUserInfoByAccountId(Long accountId); | |||
List<UserInfo> getUserInfoByEmployeeCodes(Collection<String> employeeCodes); | |||
default Map<String, Long> listUserIdByMhUserIds(Collection<String> mhUserIds) { | |||
LambdaQueryWrapper<UserInfo> query = Wrappers.lambdaQuery(UserInfo.class) | |||
.select(UserInfo::getMhUserId, UserInfo::getId) | |||
.in(UserInfo::getMhUserId, mhUserIds); | |||
return CollUtils.listToMap(list(query), UserInfo::getMhUserId, UserInfo::getId); | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
package com.hz.pm.api.user.service.impl; | |||
import com.hz.pm.api.user.entity.MhUnit; | |||
import com.hz.pm.api.user.mapper.MhUnitMapper; | |||
import com.hz.pm.api.user.service.IMhUnitService; | |||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; | |||
import org.springframework.stereotype.Service; | |||
/** | |||
* <p> | |||
* 组织表 服务实现类 | |||
* </p> | |||
* | |||
* @author CMM | |||
* @since 2023-12-25 | |||
*/ | |||
@Service | |||
public class MhUnitServiceImpl extends ServiceImpl<MhUnitMapper, MhUnit> implements IMhUnitService { | |||
} |
@@ -0,0 +1,31 @@ | |||
package com.hz.pm.api.user.task; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* <p> | |||
* SyncMhUnitProperties | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:49 2023/12/25 | |||
*/ | |||
@Data | |||
@Component | |||
@ConfigurationProperties(prefix = SyncMhExpertProperties.PREFIX) | |||
public class SyncMhExpertProperties { | |||
public static final String PREFIX = "sync-mh-expert"; | |||
/** | |||
* 单位:分钟 | |||
*/ | |||
private Integer fixedRate = 5; | |||
private Boolean open = true; | |||
private Integer batchSize = 2000; | |||
} |
@@ -0,0 +1,38 @@ | |||
package com.hz.pm.api.user.task; | |||
import com.hz.pm.api.user.manage.SyncMhUserOrgManage; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |||
import org.springframework.scheduling.annotation.Scheduled; | |||
import org.springframework.stereotype.Component; | |||
import java.time.LocalDateTime; | |||
import java.util.concurrent.TimeUnit; | |||
/** | |||
* <p> | |||
* SyncMhUserTask | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:02 2023/12/25 | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
@ConditionalOnProperty(prefix = SyncMhExpertProperties.PREFIX, value = "open", matchIfMissing = true) | |||
public class SyncMhExpertTask { | |||
private final SyncMhUserOrgManage syncMhUserOrgManage; | |||
private final SyncMhExpertProperties syncMhExpertProperties; | |||
@Scheduled(fixedRateString = "#{syncMhExpertProperties.getFixedRate()}", timeUnit = TimeUnit.MINUTES) | |||
public void execute() { | |||
Integer fixedRate = syncMhExpertProperties.getFixedRate(); | |||
LocalDateTime syncDateTime = LocalDateTime.now().minusMinutes(fixedRate + 1L); | |||
syncMhUserOrgManage.syncExperts(syncDateTime); | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
package com.hz.pm.api.user.task; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* <p> | |||
* SyncMhUnitProperties | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:49 2023/12/25 | |||
*/ | |||
@Data | |||
@Component | |||
@ConfigurationProperties(prefix = SyncMhUnitProperties.PREFIX) | |||
public class SyncMhUnitProperties { | |||
public static final String PREFIX = "sync-mh-unit"; | |||
private Integer fixedRate = 2; | |||
private Boolean open = true; | |||
private Integer batchSize = 2000; | |||
} |
@@ -0,0 +1,34 @@ | |||
package com.hz.pm.api.user.task; | |||
import com.hz.pm.api.user.manage.SyncMhUserOrgManage; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |||
import org.springframework.scheduling.annotation.Scheduled; | |||
import org.springframework.stereotype.Component; | |||
import java.util.concurrent.TimeUnit; | |||
/** | |||
* <p> | |||
* SyncMhUserTask | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:02 2023/12/25 | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
@ConditionalOnProperty(prefix = SyncMhUnitProperties.PREFIX, value = "open", matchIfMissing = true) | |||
public class SyncMhUnitTask { | |||
private final SyncMhUserOrgManage syncMhUserOrgManage; | |||
@Scheduled(fixedRateString = "#{syncMhUnitProperties.getFixedRate()}", timeUnit = TimeUnit.HOURS) | |||
public void execute() { | |||
syncMhUserOrgManage.syncUnits(); | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
package com.hz.pm.api.user.task; | |||
import lombok.Data; | |||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||
import org.springframework.stereotype.Component; | |||
/** | |||
* <p> | |||
* SyncMhUserProperties | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:49 2023/12/25 | |||
*/ | |||
@Data | |||
@Component | |||
@ConfigurationProperties(prefix = SyncMhUserProperties.PREFIX) | |||
public class SyncMhUserProperties { | |||
public static final String PREFIX = "sync-mh-user"; | |||
private Integer fixedRate = 30; | |||
private Boolean open = true; | |||
private Integer batchSize = 2000; | |||
} |
@@ -0,0 +1,38 @@ | |||
package com.hz.pm.api.user.task; | |||
import com.hz.pm.api.user.manage.SyncMhUserOrgManage; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |||
import org.springframework.scheduling.annotation.Scheduled; | |||
import org.springframework.stereotype.Component; | |||
import java.time.LocalDateTime; | |||
import java.util.concurrent.TimeUnit; | |||
/** | |||
* <p> | |||
* SyncMhUserTask | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 11:02 2023/12/25 | |||
*/ | |||
@Slf4j | |||
@Component | |||
@RequiredArgsConstructor | |||
@ConditionalOnProperty(prefix = SyncMhUserProperties.PREFIX, value = "open", matchIfMissing = true) | |||
public class SyncMhUserTask { | |||
private final SyncMhUserProperties syncMhUserProperties; | |||
private final SyncMhUserOrgManage syncMhUserOrgManage; | |||
@Scheduled(fixedRateString = "#{syncMhUserProperties.getFixedRate()}", timeUnit = TimeUnit.MINUTES) | |||
public void execute() { | |||
Integer fixedRate = syncMhUserProperties.getFixedRate(); | |||
LocalDateTime syncDateTime = LocalDateTime.now().minusMinutes(fixedRate + 1L); | |||
syncMhUserOrgManage.syncUsers(syncDateTime); | |||
} | |||
} |
@@ -245,5 +245,9 @@ web: | |||
expert-registration: | |||
verify-code: | |||
check: false | |||
sync-mh-expert: | |||
open: false | |||
sync-mh-unit: | |||
open: false | |||
sync-mh-user: | |||
open: false |
@@ -1,248 +0,0 @@ | |||
server: | |||
port: 38888 | |||
servlet: | |||
context-path: /hzpm | |||
#最大并发数,默认200 | |||
tomcat: | |||
threads: | |||
max: 600 | |||
spring: | |||
mvc: | |||
pathmatch: | |||
matching-strategy: ant_path_matcher | |||
session: | |||
store-type: redis | |||
redis: | |||
namespace: "spring:session" | |||
redis: | |||
timeout: 5000 | |||
host: localhost | |||
port: 6379 | |||
database: 0 | |||
password: Ndkj1234 | |||
jedis: | |||
pool: | |||
max-active: 200 | |||
max-idle: 500 | |||
min-idle: 8 | |||
max-wait: 10000 | |||
application: | |||
name: pm | |||
jackson: | |||
default-property-inclusion: non_null | |||
time-zone: GMT+8 | |||
date-format: yyyy-MM-dd HH:mm:ss | |||
jpa: | |||
properties: | |||
hibernate: | |||
default_schema: PUBLIC | |||
hbm2ddl: | |||
auto: update | |||
show_sql: true | |||
show-sql: true | |||
hibernate: | |||
ddl-auto: update | |||
datasource: | |||
type: com.zaxxer.hikari.HikariDataSource | |||
driverClassName: com.kingbase8.Driver | |||
url: jdbc:kingbase8://10.53.168.41:54321/nd_project_management?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8&nullCatalogMeansCurrent=true | |||
username: SYSTEM | |||
password: Ndkj1234 | |||
# 数据源 | |||
hikari: | |||
# 是客户端等待连接池连接的最大毫秒数 | |||
connection-timeout: 30000 | |||
# 是允许连接在连接池中空闲的最长时间 | |||
minimum-idle: 10 | |||
# 配置最大池大小 | |||
maximum-pool-size: 300 | |||
# 是允许连接在连接池中空闲的最长时间(以毫秒为单位) | |||
idle-timeout: 60000 | |||
# 池中连接关闭后的最长生命周期(以毫秒为单位) | |||
max-lifetime: 600000 | |||
# 配置从池返回的连接的默认自动提交行为。默认值为true。 | |||
auto-commit: true | |||
# 开启连接监测泄露 | |||
leak-detection-threshold: 5000 | |||
# 测试连接数据库 | |||
connection-test-query: SELECT 1 | |||
#设置上传 单个文件的大小 | |||
servlet: | |||
multipart: | |||
max-file-size: 100MB | |||
max-request-size: 150MB | |||
mybatis-plus: | |||
configuration: | |||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl | |||
global-config: | |||
db-config: | |||
logic-delete-value: true | |||
logic-not-delete-value: false | |||
logging: | |||
config: classpath:logback-spring.xml | |||
#日志配置 | |||
level: | |||
root: info | |||
file: | |||
path: logs | |||
nd: | |||
cache: | |||
type: REDIS | |||
serializerType: ProtoStuff | |||
cacheNullVal: true | |||
def: | |||
keyPrefix: pm | |||
log: | |||
enabled: true | |||
type: DB | |||
# 文件存储 | |||
file: | |||
storage-type: ALI_OSS | |||
ali: | |||
protocol: http:// | |||
bucket: projectmangmentoss | |||
urlPrefix: oss-cn-lishui-gov-d01-a.ops.lsdx-zw.gov.cn | |||
endpoint: oss-cn-lishui-gov-d01-a.ops.lsdx-zw.gov.cn | |||
accessKeyId: XS3kNLtfW5i41SaC | |||
accessKeySecret: 2cywvSZWANml7pZXxRAeAiHfisIhqm | |||
# 日志文件配置 | |||
log: | |||
path: ./logs | |||
info: | |||
file-size: 50MB | |||
max-size: 5 | |||
total-size: 200MB | |||
error: | |||
file-size: 10MB | |||
max-size: 5 | |||
total-size: 50MB | |||
swagger: | |||
enabled: true | |||
flowable: | |||
async-executor-activate: true | |||
#关闭一些不需要的功能服务 | |||
rest-api-enabled: false | |||
# database-schema-update: false | |||
idm: | |||
enabled: false | |||
common: | |||
enabled: false | |||
dmn: | |||
enabled: false | |||
form: | |||
enabled: false | |||
app: | |||
enabled: false | |||
wflow: | |||
file: | |||
max-size: 20 #最大文件上传大小,MB | |||
sa-token: | |||
# token 名称 (同时也是cookie名称) | |||
token-name: wflowToken | |||
# token 有效期,单位s 默认30天, -1代表永不过期 | |||
timeout: 172800 | |||
# token 临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 | |||
activity-timeout: -1 | |||
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) | |||
is-concurrent: true | |||
# 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) | |||
is-share: false | |||
# token风格 | |||
token-style: uuid | |||
# 是否输出操作日志 | |||
is-log: false | |||
#浙政钉公司顶级organizationCode | |||
organization: | |||
dept-visible-scopes: | |||
- GO_c1a6f8d5338e4a468337b08da76e2e31 | |||
yxt: | |||
wsdl-url: classpath:wsdl-prod.xml | |||
#账号 | |||
user-code: Lssdsjj | |||
#密码 | |||
password: Lssdsjj@2021 | |||
#音信通开关 | |||
sms-enable: true | |||
tel-enable: true | |||
#省局联审 请求信息 | |||
provincial: | |||
host: https://pms.zj.gov.cn/prometheus-zhejiang_foreign | |||
pushUrl: /api/v1/foreign/importantPro | |||
detailUrl: /api/v1/foreign/importantProView | |||
domainUrl: /api/v1/foreign/dominantUnit | |||
key: b5b2096953534a53991be4ea95f8cffa | |||
secret: 1bec9b77134d4962ac466fbe9696b897 | |||
# host: http://223.4.72.75/prometheus-zhejiang_foreign | |||
# pushUrl: /api/v1/foreign/importantPro | |||
# detailUrl: /api/v1/foreign/importantProView | |||
# key: b5b2096953534a53991be4ea95f8cffa | |||
# secret: 1bec9b77134d4962ac466fbe9696b897 | |||
#天印服务器接口信息 | |||
irs: | |||
is-search-app: true | |||
digital-resource-indicators: | |||
url: https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003001029/dataSharing/99E2bic31KdXzaa7.htm | |||
interfaceName: 99E2bic31KdXzaa7 | |||
app-key: A331101453557202109017383 | |||
app-secret: 496f0f2a19994f76b4fd9dae087366c7 | |||
seal-platform: | |||
project-id: 330001110 | |||
project-secret: 70e512d40c8f440484db4acab181570a | |||
access-key: 42bcb49bea174986a3bfdfba7d005566 | |||
secret-key: bebff29877d4443abd67fc4f8fb335d8 | |||
api-url: https://bcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220309000004/seal-platform/seal/v1/rest/sign/signPdf | |||
app-report: | |||
url: https://bcdsg.zj.gov.cn:8443/restapi/prod/IC33000020230427000001/irs-res-bill/report/pdfUrl | |||
appScret: BCDSGS_4ab4235d26a9a357170a39f3a13fd68c | |||
appKey: BCDSGA_d874c8e46b541eb4e8aac6510fd3351b | |||
push-app: | |||
url: https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003001029/dataSharing/94wbaL1I1Pbz0648.htm | |||
appScret: 496f0f2a19994f76b4fd9dae087366c7 | |||
appKey: A331101453557202109017383 | |||
search-app: | |||
url: https://interface.zjzwfw.gov.cn/gateway/api/001003001029/dataSharing/XS8daav3bcemZ3Ra.htm | |||
appScret: 496f0f2a19994f76b4fd9dae087366c7 | |||
appKey: A331101453557202109017383 | |||
province-gov: | |||
can-search: true | |||
url: https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003001029/dataSharing/62vd5jAdM0b7Gr00.htm | |||
interfaceName: 62vd5jAdM0b7Gr00 | |||
appSecret: 496f0f2a19994f76b4fd9dae087366c7 | |||
appKey: A331101453557202109017383 | |||
push-project-detail: | |||
url: https://interface.zjzwfw.gov.cn/gateway/api/proxy/001003001029/dataSharing/3XN9R93Pva6db7sf.htm | |||
interfaceName: 3XN9R93Pva6db7sf | |||
appSecret: 496f0f2a19994f76b4fd9dae087366c7 | |||
appKey: A331101453557202109017383 | |||
core-biz: | |||
url: https://interface.zjzwfw.gov.cn/gateway/api/001008012012001/dataSharing/Fc3re2cq7r64Qfa7.htm | |||
interfaceName: Fc3re2cq7r64Qfa7 | |||
appSecret: 496f0f2a19994f76b4fd9dae087366c7 | |||
appKey: A331101453557202109017383 | |||
interface-refresh: | |||
method: POST | |||
request-token-url: http://interface.zjzwfw.gov.cn/gateway/app/refreshTokenByKey.htm | |||
refresh-token-url: http://interface.zjzwfw.gov.cn/gateway/app/refreshTokenBySec.htm | |||
interface-local-refresh: | |||
method: GET | |||
request-token-url: https://interface.ls.local/a/api/requestTokenKey?appKey={appKey}&requestTime={requestTime}&sign={sign} | |||
refresh-token-url: https://interface.ls.local/a/api/refreshTokenKey?appKey={appKey}&requestTime={requestTime}&sign={sign} | |||
hostname: iZ6mx01asxnsmennpzoxooZ | |||
project: | |||
push-url: http://10.53.168.41:38088/open/api/v1/project-receive/save | |||
no-effective-url: http://10.53.168.41:38088/open/api/v1/project-receive/not-effective | |||
delete-all-url: http://10.53.168.41:38088/open/api/v1/project-receive/delete-all | |||
login: | |||
phone-verify-code: | |||
skip: true | |||
url: http://60.188.225.145:8080/login | |||
web: | |||
url: http://60.188.225.145:8080 |
@@ -1,12 +0,0 @@ | |||
#浙政钉 | |||
integration: | |||
zwdd: | |||
#扫码 | |||
app-auth-key: ls_project_managment_din-b1Y3I1g7Rr94yX76KfFkpp18Uy4WHtU0b6rINJ3 | |||
app-auth-secret: 75e8PMHv984KYF0Mcy6v4pxt480y73dbD7kB65dD | |||
#免登/获取信息 | |||
app-key: ls_project-c32LNu87v60UiANZVja | |||
app-secret: R14QgbBr21751LTGml3Vt8oX9doPl4Lk1ROzZNfG | |||
#专有钉钉在开发管理工作台,右键查看网页源码realmId: '31141',浙政钉固定196729 | |||
tenantId: 196729 | |||
domain: openplatform-pro.ding.zj.gov.cn |
@@ -4,6 +4,7 @@ security: | |||
invalid-session-url: /api/v1/user/auth/invalid-session | |||
password-login-url: /api/v1/user/auth/login | |||
agent-login-url: /api/v1/user/auth/agent-login | |||
mh-login-url: /api/v1/user/auth/mh-login | |||
logout-url: /api/v1/user/auth/logout | |||
common-login-url: /api/v1/user/auth/common-login | |||
ignore-auth-urls: | |||
@@ -1,84 +0,0 @@ | |||
security: | |||
auth: | |||
auth-require-url: /api/v1/user/auth/auth-require | |||
invalid-session-url: /api/v1/user/auth/invalid-session | |||
password-login-url: /api/v1/user/auth/login | |||
agent-login-url: /api/v1/user/auth/agent-login | |||
logout-url: /api/v1/user/auth/logout | |||
common-login-url: /api/v1/user/auth/common-login | |||
ignore-auth-urls: | |||
- /v2/api-docs | |||
- /swagger-ui.html | |||
- /webjars/** | |||
- /swagger-resources/** | |||
- /webjars/ | |||
- /api/v1/user/auth/register | |||
- /api/v1/user/auth/auth-require | |||
- /api/v1/user/auth/invalid-session | |||
- /api/v1/user/auth/login/password | |||
- /api/v1/user/auth/forget-password | |||
- /api/v1/user/auth/common-login | |||
- /doc.html | |||
- /ok.html | |||
- /open/api/** | |||
- /oa/** | |||
- /wflow/** | |||
- /sys/** | |||
- /api/v1/verification/** | |||
- /api/v1/expert/registration | |||
- /api/v1/meta/dictionary/list | |||
- /api/v1/meta/tag | |||
- /api/v1/organization/tree-list | |||
- /api/v1/organization/get-child-list | |||
- /api/v1/region/tree | |||
- /api/v1/expert/get-zzd-info | |||
- /file/upload | |||
- /file/download | |||
- /api/v1/zwdd/pull/** | |||
- /api/v1/irs/** | |||
- /api/v1/wps-convert/** | |||
- /api/v1/belong-org/business-strip/list | |||
- /expert/ephemeral/*/registration | |||
ignore-csrf-urls: | |||
- /api/v1/user/auth/** | |||
- /v2/api-docs | |||
- /swagger-ui.html | |||
- /webjars/** | |||
- /swagger-resources/** | |||
- /webjars/ | |||
- /doc.html | |||
- /ok.html | |||
- /api/v1/** | |||
- /file/** | |||
- /optLog/** | |||
- /dict/** | |||
- /oa/** | |||
- /wflow/** | |||
- /sys/** | |||
- /api/v1/verification/** | |||
- /api/v1/expert/registration | |||
- /api/v1/meta/dictionary/list | |||
- /api/v1/meta/tag | |||
- /api/v1/organization/tree-list | |||
- /api/v1/organization/get-child-list | |||
- /api/v1/region/tree | |||
- /api/v1/expert/get-zzd-info | |||
- /file/upload | |||
- /file/download | |||
- /api/v1/zwdd/pull/** | |||
- /api/v1/irs/** | |||
- /api/v1/wps-convert/** | |||
- /api/v1/belong-org/business-strip/list | |||
- /expert/ephemeral/*/registration | |||
role-map: | |||
"engineer": | |||
"project_manager": | |||
- /api/v1/user-info/kick-off/** | |||
"enterprise_admin": | |||
"regional_general_manager": | |||
"driver": | |||
"super_admin": | |||
- /api/v1/user-info/save | |||
- /api/v1/user-info/del | |||
- /api/v1/user-info/kick-off/** | |||
- /api/v1/user-info/password/mod |
@@ -4,6 +4,7 @@ security: | |||
invalid-session-url: /api/v1/user/auth/invalid-session | |||
password-login-url: /api/v1/user/auth/login | |||
agent-login-url: /api/v1/user/auth/agent-login | |||
mh-login-url: /api/v1/user/auth/mh-login | |||
logout-url: /api/v1/user/auth/logout | |||
common-login-url: /api/v1/user/auth/common-login | |||
ignore-auth-urls: | |||
@@ -15,11 +15,12 @@ | |||
<dependency> | |||
<groupId>com.baomidou</groupId> | |||
<artifactId>mybatis-plus-boot-starter</artifactId> | |||
<version>3.5.3.1</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.baomidou</groupId> | |||
<artifactId>mybatis-plus-generator</artifactId> | |||
<version>3.5.3.2</version> | |||
<version>3.5.3.1</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.freemarker</groupId> | |||
@@ -7,21 +7,20 @@ import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; | |||
import java.util.Collections; | |||
/** | |||
* @description: 自动生成code代码 | |||
* @author: zpf | |||
* @date: 2023/01/03 09:20 | |||
* <p> | |||
* CodeGen | |||
* </p> | |||
* | |||
* @author WendyYang | |||
* @since 13:27 2023/12/25 | |||
*/ | |||
public class GeneratorCodeKingbaseConfig { | |||
public class CodeGen { | |||
private static final String PATH_LXX = "/Users/liuxinxin/IdeaProjects/project-management/pmapi/src/main/java"; | |||
private static final String PATH_YYD = "/Users/wendy/code project/java/project-management/pmapi/src/main/java"; | |||
private static final String PATH_LS = ""; | |||
private static final String PATH_ZPF = "D:\\ningda\\project-management\\pmapi\\src\\main\\java"; | |||
private static final String PATH_CMM = "D:\\work\\project-management\\project-management\\pmapi\\src\\main\\java"; | |||
private static final String PATH_YYD = "/Users/wendy/coding/java/hz-project-management/hz-pm-api/src/main/java"; | |||
private static final String URL = "jdbc:kingbase8://120.26.44.207:54321/nd_project_management?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8"; | |||
private static final String USER_NAME = "SYSTEM"; | |||
private static final String PASSWORD = "Ndkj1234"; | |||
private static final String URL = "jdbc:dm://47.98.125.47:5236/HZ_PROJECT_MANAGEMENT?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8"; | |||
private static final String USER_NAME = "SYSDBA"; | |||
private static final String PASSWORD = "SYSDBA"; | |||
private static void generate(String author, String packageName, String path, String... tableNames) { | |||
FastAutoGenerator.create(URL, USER_NAME, PASSWORD) | |||
@@ -37,13 +36,13 @@ public class GeneratorCodeKingbaseConfig { | |||
}) | |||
.packageConfig(builder -> { | |||
// 设置父包名 | |||
builder.parent("com.ningdatech") | |||
builder.parent("com.hz.pm") | |||
// 设置父包模块名 | |||
.moduleName("pmapi." + packageName) | |||
.moduleName("api." + packageName) | |||
// 设置mapperXml生成路径 | |||
.pathInfo(Collections.singletonMap(OutputFile.xml, | |||
//设置自己的生成路径 | |||
path + "/com/ningdatech/pmapi/" + packageName + "/mapper")); | |||
path + "/com/hz/pm/api/" + packageName + "/mapper")); | |||
}) | |||
.strategyConfig(builder -> { | |||
builder.addTablePrefix(""); | |||
@@ -56,8 +55,7 @@ public class GeneratorCodeKingbaseConfig { | |||
} | |||
public static void main(String[] args) { | |||
//generate("Liuxinxin", "expert", PATH_LXX, "expert_gov_business_strip"); | |||
generate("CMM", "test", PATH_CMM, "nd_performance_appraisal_app_score_info"); | |||
generate("CMM", "user", PATH_YYD, "mh_unit"); | |||
} | |||
} |