Browse Source

Merge remote-tracking branch 'origin/master'

tags/24080901
niohe·erbao 1 year ago
parent
commit
4a307b3ca4
34 changed files with 1283 additions and 177 deletions
  1. +19
    -0
      pmapi/pom.xml
  2. +22
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/common/enumeration/CommonEnum.java
  3. +2
    -2
      pmapi/src/main/java/com/ningdatech/pmapi/expert/controller/ReviewTemplateSettingsController.java
  4. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java
  5. +5
    -5
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.xml
  6. +17
    -11
      pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java
  7. +7
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/DeclaredProjectManage.java
  8. +88
    -4
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/DefaultDeclaredProjectManage.java
  9. +11
    -69
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/PrequalificationDeclaredProjectManage.java
  10. +2
    -6
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/ReviewByDeptJointManage.java
  11. +17
    -3
      pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/ReviewByProvincialDeptManage.java
  12. +1
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/helper/ProjectHelper.java
  13. +3
    -4
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/AnnualPlanLibManage.java
  14. +3
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/dto/ProjectDTO.java
  15. +9
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/entity/Project.java
  16. +3
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/req/ProjectListReq.java
  17. +3
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/vo/ProjectDetailVO.java
  18. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/scheduler/task/ProjectStatusFlowTask.java
  19. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/staging/mapper/NdWorkNoticeStagingMapper.xml
  20. +1
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/staging/mapper/ProjectStagingMapper.xml
  21. +0
    -1
      pmapi/src/main/java/com/ningdatech/pmapi/staging/service/impl/NdWorkNoticeStagingServiceImpl.java
  22. +0
    -44
      pmapi/src/main/java/com/ningdatech/pmapi/staging/utils/WorkNoticeFlowMapUtil.java
  23. +15
    -20
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java
  24. +140
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/model/dto/PdfGenerateDTO.java
  25. +140
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/utils/PdfGenerateUtil.java
  26. +153
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/todocenter/utils/PdfUtils.java
  27. +10
    -0
      pmapi/src/main/java/com/ningdatech/pmapi/user/model/vo/ResUserDetailVO.java
  28. BIN
      pmapi/src/main/resources/template/fileout/c34f631755a04532a0116494fd5f99ac.pdf
  29. BIN
      pmapi/src/main/resources/template/simsun.ttc
  30. +254
    -0
      pmapi/src/main/resources/template/盖章文件.html
  31. +249
    -0
      pmapi/src/main/resources/template/预审申请单.html
  32. BIN
      pmapi/src/main/resources/template/预审申请单.pdf
  33. +82
    -4
      pmapi/src/test/java/com/ningdatech/pmapi/todocenter/TodoCenterTest.java
  34. +24
    -0
      pom.xml

+ 19
- 0
pmapi/pom.xml View File

@@ -229,6 +229,25 @@
<groupId>org.springframework.statemachine</groupId>
<artifactId>spring-statemachine-core</artifactId>
</dependency>

<!-- PDF生成 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
</dependency>

</dependencies>
<!-- 打包 -->
<!--配置环境的profile-->


+ 22
- 0
pmapi/src/main/java/com/ningdatech/pmapi/common/enumeration/CommonEnum.java View File

@@ -0,0 +1,22 @@
package com.ningdatech.pmapi.common.enumeration;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
* @author zpf
* @date 2023/3/12 上午9:21
*/
@AllArgsConstructor
@Getter
public enum CommonEnum {
/**
* 公共的一些枚举
*/
YES(1,"是"),
NO(0,"否");

private Integer code;
private String desc;

}

+ 2
- 2
pmapi/src/main/java/com/ningdatech/pmapi/expert/controller/ReviewTemplateSettingsController.java View File

@@ -45,14 +45,14 @@ public class ReviewTemplateSettingsController {
}

@GetMapping("/template")
@ApiModelProperty("根据模版ID获取评审模版")
@ApiOperation("根据模版ID获取评审模版")
@ApiImplicitParam(name = "templateId", defaultValue = "模版ID")
public ReviewTemplateVO getTemplateById(@RequestParam Long templateId) {
return reviewTemplateSettingsManage.getReviewTemplateSettings(templateId);
}

@GetMapping("/templates")
@ApiModelProperty("(批量)根据模版ID获取评审模版")
@ApiOperation("(批量)根据模版ID获取评审模版")
@ApiImplicitParam(name = "templateIds", defaultValue = "模版ID集合")
public List<ReviewTemplateVO> getTemplateById(@RequestParam List<Long> templateIds) {
return reviewTemplateSettingsManage.listReviewTemplateSettings(templateIds);


+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/meeting/manage/MeetingManage.java View File

@@ -209,7 +209,7 @@ public class MeetingManage {
Assert.isTrue(checkCount >= inviteCount, "可供抽取的专家数量不足");
}
expertInviteManage.expertInviteByMeetingCreate(meeting, randomRules, avoidInfo);
expertInviteTask.addInviteExpertTaskByMeetingCreate(meeting.getId(), 5);
expertInviteTask.addInviteTaskByMeetingCreate(meeting.getId(), 5);
LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class);
update.set(Meeting::getInviteStatus, false);
update.eq(Meeting::getId, meeting.getId());


+ 5
- 5
pmapi/src/main/java/com/ningdatech/pmapi/meeting/mapper/MeetingExpertMapper.xml View File

@@ -74,22 +74,22 @@

<sql id="reviewedByHeadman">
<if test="p.reviewed">
and exists(select 1 from nd_expert_review ner where ner.project_id = np.id and ner.create_by =
exists(select 1 from nd_expert_review ner where ner.project_id = np.id and ner.create_by =
me.expert_id and is_final = true)
</if>
<if test="!p.reviewed">
and not exists(select 1 from nd_expert_review ner where ner.project_id = np.id and ner.create_by =
not exists(select 1 from nd_expert_review ner where ner.project_id = np.id and ner.create_by =
me.expert_id and is_final = true)
</if>
</sql>

<sql id="reviewedByNotHeadman">
<if test="p.reviewed">
and exists(select 1 from nd_expert_review ner where ner.project_id = np.id and ner.create_by =
exists(select 1 from nd_expert_review ner where ner.project_id = np.id and ner.create_by =
me.expert_id)
</if>
<if test="!p.reviewed">
and not exists(select 1 from nd_expert_review ner where ner.project_id = np.id and ner.create_by =
not exists(select 1 from nd_expert_review ner where ner.project_id = np.id and ner.create_by =
me.expert_id)
</if>
</sql>
@@ -104,7 +104,7 @@
inner join meeting_expert me on m.id = me.meeting_id
where m.is_inner_project = true
<if test="p.reviewed != null">
if(me.is_headman,<include refid="reviewedByHeadman"/>,<include refid="reviewedByNotHeadman"/>)
and if(me.is_headman,<include refid="reviewedByHeadman"/>,<include refid="reviewedByNotHeadman"/>)
</if>
and me.expert_id = #{p.userId}
<if test="p.projectName != null and p.projectName.length > 0">


+ 17
- 11
pmapi/src/main/java/com/ningdatech/pmapi/meeting/task/ExpertInviteTask.java View File

@@ -78,9 +78,9 @@ public class ExpertInviteTask {
private final YxtCallOrSmsHelper yxtCallOrSmsHelper;

/**
* 用来存入线程执行情况, 方便于停止定时任务时使用
* 用来存入线程执行句柄, 停止定时任务时使用
*/
protected static final ConcurrentMap<Long, ScheduledFuture<?>> INVITE_MAP = new ConcurrentHashMap<>();
private static final ConcurrentMap<Long, ScheduledFuture<?>> INVITE_TASK_MAP = new ConcurrentHashMap<>();

public ExpertInviteTask currProxy() {
return (ExpertInviteTask) AopContext.currentProxy();
@@ -109,7 +109,7 @@ public class ExpertInviteTask {
return;
}
for (InviteCacheDTO cache : caches.values()) {
addInviteExpertTask(cache.getMeetingId(), true, properties.getInviteDelay(), cache.getInvitedRefused());
addInviteTask(cache.getMeetingId(), true, properties.getInviteDelay(), cache.getInvitedRefused());
}
}

@@ -155,8 +155,8 @@ public class ExpertInviteTask {
if (ArrayUtil.isNotEmpty(invitedRefused)) {
tmpInvitedRefused = invitedRefused[0];
}
if (!INVITE_MAP.containsKey(meetingId)) {
addInviteExpertTask(meetingId, false, properties.getInviteDelay(), tmpInvitedRefused);
if (!INVITE_TASK_MAP.containsKey(meetingId)) {
addInviteTask(meetingId, false, properties.getInviteDelay(), tmpInvitedRefused);
log.info("重置会议的随机抽取状态:{}", meetingId);
LambdaUpdateWrapper<Meeting> update = Wrappers.lambdaUpdate(Meeting.class);
update.set(Meeting::getInviteStatus, false);
@@ -176,7 +176,7 @@ public class ExpertInviteTask {
* @param invitedRefused 是否可以邀请被拒绝的专家
* @author WendyYang
**/
public void addInviteExpertTask(Long meetingId, boolean checked, int delayedMinutes, boolean invitedRefused) {
public void addInviteTask(Long meetingId, boolean checked, int delayedMinutes, boolean invitedRefused) {
if (checked && !inviteCountCheck(meetingId)) {
// 如果抽取数量满足直接返回
return;
@@ -190,7 +190,7 @@ public class ExpertInviteTask {
log.error("执行专家邀请任务异常:{}", meetingId, e);
}
}, startTime, Duration.ofMinutes(properties.getInviteFixedRate()));
INVITE_MAP.putIfAbsent(meetingId, future);
INVITE_TASK_MAP.putIfAbsent(meetingId, future);
log.info("添加专家抽取后台任务:{}", meetingId);
}

@@ -201,13 +201,19 @@ public class ExpertInviteTask {
* @param delayedMinutes 延迟时间
* @author WendyYang
**/
public void addInviteExpertTaskByMeetingCreate(Long meetingId, int delayedMinutes) {
public void addInviteTaskByMeetingCreate(Long meetingId, int delayedMinutes) {
Assert.isTrue(properties.getEnable(), "随机邀请已关闭");
addInviteExpertTask(meetingId, false, delayedMinutes, false);
addInviteTask(meetingId, false, delayedMinutes, false);
InviteCacheDTO cacheVal = InviteCacheDTO.of(meetingId, false);
cachePlusOps.hSet(getCacheKey(meetingId), cacheVal);
}

/**
* 抽取过程
*
* @param meetingId 会议ID
* @param invitedRefused 是否可以邀请已拒绝的专家
*/
@Transactional(rollbackFor = Exception.class)
public void invite(Long meetingId, Boolean invitedRefused) {
log.info("开始进行专家后台抽取:{}", meetingId);
@@ -269,9 +275,9 @@ public class ExpertInviteTask {
log.info("终止专家抽取:{}", meetingId);
meetingService.stopRandomInvite(meetingId);
cachePlusOps.hDel(getCacheKey(meetingId));
ScheduledFuture<?> future = INVITE_MAP.get(meetingId);
ScheduledFuture<?> future = INVITE_TASK_MAP.get(meetingId);
if (future != null) {
INVITE_MAP.remove(meetingId);
INVITE_TASK_MAP.remove(meetingId);
if (!future.isCancelled()) {
future.cancel(true);
}


+ 7
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/DeclaredProjectManage.java View File

@@ -12,6 +12,7 @@ import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.common.constant.CommonConst;
import com.ningdatech.pmapi.common.constant.RegionConst;
import com.ningdatech.pmapi.common.enumeration.CommonEnum;
import com.ningdatech.pmapi.common.enumeration.ProjectProcessStageEnum;
import com.ningdatech.pmapi.common.helper.RegionCacheHelper;
import com.ningdatech.pmapi.common.helper.UserInfoHelper;
@@ -115,6 +116,12 @@ public class DeclaredProjectManage {
projectInfo.setBuildOrgCode(userInfoDetails.getOrganizationCode());
projectInfo.setBuildOrgName(userInfoDetails.getOrganizationName());

//如果主管单位没有 那么主管单位就是自己
if(CommonEnum.NO.getCode().equals(projectInfo.getIsSuperOrg())){
projectInfo.setSuperOrgCode(userInfoDetails.getOrganizationCode());
projectInfo.setSuperOrg(userInfoDetails.getOrganizationName());
}

//如果是重新提交的话 判断下 项目是否存在
if(Objects.nonNull(projectInfo.getId())){
Project oldProject = projectService.getById(projectInfo.getId());


+ 88
- 4
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/DefaultDeclaredProjectManage.java View File

@@ -1,29 +1,41 @@
package com.ningdatech.pmapi.projectdeclared.manage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.pmapi.common.enumeration.ProjectProcessStageEnum;
import com.ningdatech.pmapi.common.helper.UserInfoHelper;
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils;
import com.ningdatech.pmapi.organization.model.entity.DingOrganization;
import com.ningdatech.pmapi.organization.service.IDingOrganizationService;
import com.ningdatech.pmapi.projectdeclared.model.dto.ProjectConditionDTO;
import com.ningdatech.pmapi.projectlib.model.dto.ProjectDTO;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.entity.ProjectInst;
import com.ningdatech.pmapi.projectlib.service.IProjectInstService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO;
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails;
import com.ningdatech.pmapi.user.util.LoginUserUtil;
import com.wflow.bean.entity.WflowModels;
import com.wflow.bean.entity.WflowOrgModels;
import com.wflow.enums.OrgTypeEnum;
import com.wflow.enums.ProcessDefTypeEnum;
import com.wflow.exception.BusinessException;
import com.wflow.service.OrgProcdefService;
import com.wflow.workflow.bean.dto.OrgInfoDTO;
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto;
import com.wflow.workflow.bean.vo.ProcessStartParamsVo;
import com.wflow.workflow.service.ProcessInstanceService;
import com.wflow.workflow.service.ProcessModelService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
@@ -45,6 +57,14 @@ public class DefaultDeclaredProjectManage {
private final IDingOrganizationService dingOrganizationService;
private final OrgProcdefService orgProcdefService;

private final ProcessModelService processModelService;

private final ProcessInstanceService processService;

private final IProjectInstService projectInstService;

private final StateMachineUtils stateMachineUtils;

//项目名称去重
public void checkDuplication(ProjectDTO project){
VUtils.isTrue(projectService.count(Wrappers.lambdaQuery(Project.class)
@@ -120,4 +140,68 @@ public class DefaultDeclaredProjectManage {
orgMap.put(OrgTypeEnum.TARGET_LABEL.name(),orgInfoDTO);
return orgMap;
}

//直接提交预审方法 提取 在省级联审通过的时候 也可以用
public String directStartProcess(Project projectInfo,Long userId){
VUtils.isTrue(Objects.isNull(userId))
.throwMessage("发起人Id 不能为空!");

ProcessStartParamsVo params = new ProcessStartParamsVo();
params.setUser(buildUser(userId));
params.setProcessUsers(Collections.emptyMap());
//放入条件判断的项目字段
ProjectConditionDTO conditionDto = new ProjectConditionDTO();
BeanUtils.copyProperties(projectInfo, conditionDto);
params.setFormData(JSON.parseObject(JSON.toJSONString(conditionDto), new TypeReference<Map<String, Object>>() {
}));

String regionCode = projectInfo.getAreaCode();

WflowModels model = processModelService.getOne(Wrappers.lambdaQuery(WflowModels.class)
.eq(WflowModels::getRegionCode, regionCode)
.eq(WflowModels::getProcessType, ProjectProcessStageEnum.PROJECT_PREQUALIFICATION_APPROVAL_PROCESS.getCode())
.last("limit 1"));

if (Objects.isNull(model)) {
log.error("此 【{}】区域找不到 预审流程配置", regionCode);
throw new BusinessException(String.format("此 【%s】区域找不到 预审流程配置", regionCode));
}

// 获取发起单位、发起单位主管单位、发起单位上级主管条线单位信息
Map<String, OrgInfoDTO> orgModelMap = getOrgModelInfo(userId,projectInfo);
String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap);
log.info("提交预审项目成功 【{}】", instanceId);

//保存预审项目
preModifyProject(projectInfo, instanceId);

return instanceId;
}

/**
* 提交预审项目 时 更新信息
*
* @param project
* @param instanceId
*/
private void preModifyProject(Project project, String instanceId) {
//流程启动之后 入库项目 重要业务信息 用于列表查询 展示
try {
project.setUpdateOn(LocalDateTime.now());
project.setInstCode(instanceId);
projectService.updateById(project);

//保存项目和实例的关系
ProjectInst projectInst = new ProjectInst();
projectInst.setProjectId(project.getId());
projectInst.setInstCode(instanceId);
projectInst.setCreatOn(LocalDateTime.now());
projectInst.setUpdateOn(LocalDateTime.now());
projectInst.setInstType(ProjectProcessStageEnum.PROJECT_PREQUALIFICATION_APPROVAL_PROCESS.getCode());
projectInstService.save(projectInst);
} catch (Exception e) {
log.error("提交预审 项目信息修改 错误 ", e);
throw new BusinessException("提交预审 项目信息修改 错误 :" + e.getMessage());
}
}
}

+ 11
- 69
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/PrequalificationDeclaredProjectManage.java View File

@@ -33,6 +33,7 @@ import com.ningdatech.pmapi.projectlib.service.IProjectInstService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.staging.service.IProjectStagingService;
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO;
import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails;
import com.ningdatech.pmapi.user.util.LoginUserUtil;
import com.wflow.bean.entity.WflowModels;
import com.wflow.exception.BusinessException;
@@ -70,12 +71,6 @@ public class PrequalificationDeclaredProjectManage {

private final StateMachineUtils stateMachineUtils;

private final ProcessInstanceService processService;

private final ProcessModelService processModelService;

private final IProjectInstService projectInstService;

private final IProjectStagingService projectStagingService;

private final ProjectLibManage projectLibManage;
@@ -94,7 +89,8 @@ public class PrequalificationDeclaredProjectManage {
*/
@Transactional(rollbackFor = Exception.class)
public String startTheProcess(DefaultDeclaredDTO dto) {
Long userId = LoginUserUtil.getUserId();
UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail();
Long userId = userInfoDetails.getUserId();
VUtils.isTrue(Objects.isNull(userId)).throwMessage("获取登录用户失败!");

ProjectDTO projectDto = dto.getProjectInfo();
@@ -102,17 +98,9 @@ public class PrequalificationDeclaredProjectManage {
Project projectInfo = projectService.getById(projectDto.getId());
VUtils.isTrue(Objects.isNull(projectInfo)).throwMessage("提交失败 此项目不存在!");

String regionCode = projectInfo.getAreaCode();

WflowModels model = processModelService.getOne(Wrappers.lambdaQuery(WflowModels.class)
.eq(WflowModels::getRegionCode, regionCode)
.eq(WflowModels::getProcessType, ProjectProcessStageEnum.PROJECT_PREQUALIFICATION_APPROVAL_PROCESS.getCode())
.last("limit 1"));

if (Objects.isNull(model)) {
log.error("此 【{}】区域找不到 预审流程配置", regionCode);
throw new BusinessException(String.format("此 【%s】区域找不到 预审流程配置", regionCode));
}
//要判断 当前操作人 是不是项目主管单位的人
VUtils.isTrue(!userInfoDetails.getOrganizationCode().equals(projectInfo.getSuperOrgCode()))
.throwMessage(String.format("只有主管单位 【%s】的人 才能够提交",projectInfo.getSuperOrg()));

//首先要判断 项目当前状态 是不是 待预审
VUtils.isTrue(!ProjectStatusEnum.PENDING_PREQUALIFICATION.getCode().equals(projectInfo.getStatus()) ||
@@ -128,6 +116,8 @@ public class PrequalificationDeclaredProjectManage {
.getCode().equals(projectInfo.getStatus())){
//入库暂存表 后续处理 对接外部接口
projectInfo.setUpdateOn(LocalDateTime.now());
//保存一下 当前的主管单位发起人
projectInfo.setPreStartUserId(userId);
if(projectStagingService.addByProject(projectInfo,"省级部门联审")
&& projectService.updateById(projectInfo)){
return "提交省级部门联审成功";
@@ -136,26 +126,7 @@ public class PrequalificationDeclaredProjectManage {
}else if(ProjectStatusEnum.PRE_APPLYING
.getCode().equals(projectInfo.getStatus())){
//如果是非省级联审的项目 直接提交 预审
ProcessStartParamsVo params = new ProcessStartParamsVo();
params.setUser(declaredProjectManage.buildUser(userId));
params.setProcessUsers(Collections.emptyMap());
//放入条件判断的项目字段
ProjectConditionDTO conditionDto = new ProjectConditionDTO();
BeanUtils.copyProperties(projectInfo, conditionDto);
dto.getFormData().putAll(
JSON.parseObject(JSON.toJSONString(conditionDto), new TypeReference<Map<String, Object>>() {
})
);
params.setFormData(dto.getFormData());

// 获取发起单位、发起单位主管单位、发起单位上级主管条线单位信息
Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId,projectInfo);
instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap);
log.info("提交预审项目成功 【{}】", instanceId);

//保存预审项目
modifyProject(projectInfo, instanceId);

instanceId = defaultDeclaredProjectManage.directStartProcess(projectInfo,userId);
}else{
throw new BusinessException("项目状态 错误 project :" + JSON.toJSONString(projectInfo));
}
@@ -164,35 +135,6 @@ public class PrequalificationDeclaredProjectManage {
}

/**
* 提交预审项目 时 更新信息
*
* @param project
* @param instanceId
*/
private void modifyProject(Project project, String instanceId) {
//流程启动之后 入库项目 重要业务信息 用于列表查询 展示
try {
project.setUpdateOn(LocalDateTime.now());
project.setInstCode(instanceId);
//调用状态机 进入下一个通过状态
stateMachineUtils.pass(project);
projectService.updateById(project);

//保存项目和实例的关系
ProjectInst projectInst = new ProjectInst();
projectInst.setProjectId(project.getId());
projectInst.setInstCode(instanceId);
projectInst.setCreatOn(LocalDateTime.now());
projectInst.setUpdateOn(LocalDateTime.now());
projectInst.setInstType(ProjectProcessStageEnum.PROJECT_PREQUALIFICATION_APPROVAL_PROCESS.getCode());
projectInstService.save(projectInst);
} catch (Exception e) {
log.error("提交预审 项目信息修改 错误 ", e);
throw new BusinessException("提交预审 项目信息修改 错误 :" + e.getMessage());
}
}

/**
* 查询项目库
* @param preReq
* @return
@@ -207,8 +149,8 @@ public class PrequalificationDeclaredProjectManage {
Long userId = LoginUserUtil.getUserId();
VUtils.isTrue(Objects.isNull(userId)).throwMessage("获取登录用户失败!");
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId);
//放入用户的单位
req.setBuildOrgCode(userFullInfo.getOrganizationCode());
//放入用户的主管单位
req.setSuperOrgCode(userFullInfo.getOrganizationCode());
return projectLibManage.projectLibList(req);
}



+ 2
- 6
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/ReviewByDeptJointManage.java View File

@@ -51,8 +51,6 @@ public class ReviewByDeptJointManage {
private final ProcessInstanceService processService;

private final IProjectInstService projectInstService;

private final UserInfoHelper userInfoHelper;
private final DefaultDeclaredProjectManage declaredProjectManage;
private final DefaultDeclaredProjectManage defaultDeclaredProjectManage;

@@ -63,8 +61,8 @@ public class ReviewByDeptJointManage {
*/
@Transactional(rollbackFor = Exception.class)
public Boolean startTheProcess(Project project) {
Long userId = LoginUserUtil.getUserId();
VUtils.isTrue(Objects.isNull(userId)).throwMessage("获取登录用户失败!");
//这里是任务发起的 所以用项目发起人
Long userId = project.getSponsor();

VUtils.isTrue(Objects.isNull(project.getId())).throwMessage("提交失败 缺少项目ID!");
Project projectInfo = projectService.getById(project.getId());
@@ -122,8 +120,6 @@ public class ReviewByDeptJointManage {
try {
project.setUpdateOn(LocalDateTime.now());
project.setInstCode(instanceId);
project.setStage(ProjectStatusEnum.NOT_APPROVED.getCode());
project.setStatus(ProjectStatusEnum.UNDER_INTERNAL_AUDIT.getCode());
projectService.updateById(project);
//保存项目和实例的关系
ProjectInst projectInst = new ProjectInst();


+ 17
- 3
pmapi/src/main/java/com/ningdatech/pmapi/projectdeclared/manage/ReviewByProvincialDeptManage.java View File

@@ -1,11 +1,15 @@
package com.ningdatech.pmapi.projectdeclared.manage;

import com.ningdatech.basic.function.VUtils;
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils;
import com.ningdatech.pmapi.projectdeclared.model.dto.DefaultDeclaredDTO;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.model.dto.ProjectDTO;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Objects;
@@ -23,6 +27,10 @@ public class ReviewByProvincialDeptManage {

private final IProjectService projectService;

private final StateMachineUtils stateMachineUtils;

private final DefaultDeclaredProjectManage defaultProjectManage;

/**
* 省级部门联审
* @param project
@@ -40,10 +48,16 @@ public class ReviewByProvincialDeptManage {
!ProjectStatusEnum.NOT_APPROVED.getCode().equals(projectInfo.getStage()))
.throwMessage("提交失败 该项目不是 省级部门联审状态状态或者未立项阶段");
// TODO 对接省级联审的接口
Boolean sucessProvince = Boolean.FALSE;
Boolean sucessProvince = Boolean.TRUE;
if(sucessProvince){
//成功了后

//测试先成功
stateMachineUtils.pass(project);
projectService.updateById(project);
//直接去预审
if(StringUtils.isNotBlank(defaultProjectManage
.directStartProcess(project,project.getPreStartUserId()))){
return Boolean.TRUE;
}
}

return Boolean.FALSE;


+ 1
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/helper/ProjectHelper.java View File

@@ -45,6 +45,7 @@ public class ProjectHelper {

.like(req.getBuildOrg() != null, Project::getBuildOrgName, req.getBuildOrg())
.eq(req.getBuildOrgCode() != null, Project::getBuildOrgCode, req.getBuildOrgCode())
.eq(req.getSuperOrgCode() != null, Project::getSuperOrgCode, req.getSuperOrgCode())
.eq(req.getIsTemporaryAugment() != null, Project::getIsTemporaryAugment, req.getIsTemporaryAugment())
//状态 阶段 list
.in(CollUtil.isNotEmpty(req.getStageList()),Project::getStage,req.getStageList())


+ 3
- 4
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/manage/AnnualPlanLibManage.java View File

@@ -222,15 +222,14 @@ public class AnnualPlanLibManage {
public void exportList(ProjectListReq param, HttpServletResponse response) {
param.setPageNumber(CommonConst.EXPORT_PAGE_NUMBER);
param.setPageSize(CommonConst.EXPORT_PAGE_SIZE);
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(param);
Integer isTemporaryAugment = param.getIsTemporaryAugment();
if (Objects.isNull(isTemporaryAugment)) {
throw new BizException("请传入是否临时增补标志!");
}
query.eq(Project::getIsTemporaryAugment, isTemporaryAugment);
query.eq(Project::getIsTemporaryAugment, 0);
param.setIsTemporaryAugment(isTemporaryAugment);
param.setStatusList(CollUtils.fieldList(ANNUAL_PLAN_LIST_STATUS, ProjectStatusEnum::getCode));
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(param);
query.orderByDesc(Project::getAnnualPlanAddTime);
query.in(Project::getStatus, CollUtils.fieldList(ANNUAL_PLAN_LIST_STATUS, ProjectStatusEnum::getCode));
List<Project> projects = projectService.list(query);

ExcelExportWriter excelExportWriter = new ExcelExportWriter();


+ 3
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/dto/ProjectDTO.java View File

@@ -282,6 +282,9 @@ public class ProjectDTO implements Serializable {
@ApiModelProperty("项目发起人")
private Long sponsor;

@ApiModelProperty("上级条线单位审核意见")
private String higherLineSuperOrgReviewComments;

private Map<String,Object> dynamicForm;

}

+ 9
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/entity/Project.java View File

@@ -297,10 +297,19 @@ public class Project implements Serializable {
@ApiModelProperty("项目发起人 用户id")
private Long sponsor;

@ApiModelProperty("预审发起人 用户id")
private Long preStartUserId;

@ApiModelProperty("上级条线单位审核意见")
private String higherLineSuperOrgReviewComments;

@TableField(fill = FieldFill.INSERT)
private Long createBy;

@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateBy;

@ApiModelProperty("项目预审申请单文件ID")
private Long pretrialFileId;

}

+ 3
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/req/ProjectListReq.java View File

@@ -39,6 +39,9 @@ public class ProjectListReq extends PagePo {
@ApiModelProperty("申报单位code")
private String buildOrgCode;

@ApiModelProperty("主管单位code")
private String superOrgCode;

@ApiModelProperty("项目类型")
private Integer projectType;



+ 3
- 0
pmapi/src/main/java/com/ningdatech/pmapi/projectlib/model/vo/ProjectDetailVO.java View File

@@ -289,6 +289,9 @@ public class ProjectDetailVO {
@ApiModelProperty("项目发起人id")
private Long sponsor;

@ApiModelProperty("上级条线单位审核意见")
private String higherLineSuperOrgReviewComments;

private String projectTypeName;

public String getProjectTypeName() {


+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/scheduler/task/ProjectStatusFlowTask.java View File

@@ -82,7 +82,7 @@ public class ProjectStatusFlowTask {
projectStagingService.removeById(projectStaging);
}
}catch (Exception e){
log.error("项目流转 异常 projectId:【" + projectStaging.getProjectId() + "】 异常内容:" + e);
log.error("项目流转 异常 projectId:【" + projectStaging.getProjectId() + "】 异常内容:" + e.getMessage());
}finally {
//增加重试的次数 和下次扫描时间
projectStagingService.addRetryTimes(projectStaging);


+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/staging/mapper/NdWorkNoticeStagingMapper.xml View File

@@ -7,6 +7,6 @@
set retry_times = #{retryTimes},
next_time = #{nextRetryTime},
dead = #{dead}
where id = #{id} and retry_times = #{retryTimes - 1}
where id = #{id} and retry_times = #{retryTimes} - 1
</update>
</mapper>

+ 1
- 1
pmapi/src/main/java/com/ningdatech/pmapi/staging/mapper/ProjectStagingMapper.xml View File

@@ -7,6 +7,6 @@
set retry_times = #{retryTimes},
next_time = #{nextRetryTime},
dead = #{dead}
where id = #{id} and retry_times = #{retryTimes - 1}
where id = #{id} and retry_times = #{retryTimes} - 1
</update>
</mapper>

+ 0
- 1
pmapi/src/main/java/com/ningdatech/pmapi/staging/service/impl/NdWorkNoticeStagingServiceImpl.java View File

@@ -2,7 +2,6 @@ package com.ningdatech.pmapi.staging.service.impl;

import com.ningdatech.pmapi.staging.contants.StagingContant;
import com.ningdatech.pmapi.staging.enums.MsgTypeEnum;
import com.ningdatech.pmapi.staging.model.entity.ProjectStaging;
import com.ningdatech.pmapi.staging.model.entity.WorkNoticeStaging;
import com.ningdatech.pmapi.staging.mapper.NdWorkNoticeStagingMapper;
import com.ningdatech.pmapi.staging.service.INdWorkNoticeStagingService;


+ 0
- 44
pmapi/src/main/java/com/ningdatech/pmapi/staging/utils/WorkNoticeFlowMapUtil.java View File

@@ -1,23 +1,9 @@
package com.ningdatech.pmapi.staging.utils;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

import javax.annotation.PostConstruct;

import com.ningdatech.pmapi.common.util.SendWorkNoticeUtil;
import com.ningdatech.pmapi.staging.enums.MsgTypeEnum;
import com.ningdatech.pmapi.staging.model.entity.WorkNoticeStaging;
import com.ningdatech.pmapi.todocenter.bean.entity.WorkNoticeInfo;
import org.springframework.stereotype.Component;

import com.google.common.collect.Maps;
import com.ningdatech.pmapi.projectdeclared.manage.ReviewByDeptJointManage;
import com.ningdatech.pmapi.projectdeclared.manage.ReviewByProvincialDeptManage;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.Project;

import lombok.RequiredArgsConstructor;

/**
@@ -29,41 +15,11 @@ import lombok.RequiredArgsConstructor;
@Component
@RequiredArgsConstructor
public class WorkNoticeFlowMapUtil {
//public Map<Integer, Function<WorkNoticeInfo,Boolean>> workNoticeFlowFunctionMap = Maps.newHashMap();
/**
* key 重试的次数 , value 是增加是描述
*/
public Map<Integer, Integer> intervalTimeMap = Maps.newHashMap();

///**
// * 初始化工作通知分派逻辑,代替了if-else部分
// * key: 枚举 消息类型
// * value: lambda表达式,最终会获取发送工作通知的函数
// */
//@PostConstruct
//public void workNoticeFlowFunctionInit(){
// // 待审核
// workNoticeFlowFunctionMap.put(MsgTypeEnum.AUDIT.getCode(),
// workNoticeInfos-> SendWorkNoticeUtil.sendWorkNotice(workNoticeInfos));
//
// // 审核通过
// workNoticeFlowFunctionMap.put(MsgTypeEnum.PASS.getCode(),
// workNoticeInfos-> SendWorkNoticeUtil.sendWorkNotice(workNoticeInfos));
//
// // 被驳回
// workNoticeFlowFunctionMap.put(MsgTypeEnum.REJECTED.getCode(),
// workNoticeInfos-> SendWorkNoticeUtil.sendWorkNotice(workNoticeInfos));
//
// // 被退回
// workNoticeFlowFunctionMap.put(MsgTypeEnum.BACKED.getCode(),
// workNoticeInfos-> SendWorkNoticeUtil.sendWorkNotice(workNoticeInfos));
//
// // 被驳回
// workNoticeFlowFunctionMap.put(MsgTypeEnum.REJECTED.getCode(),
// workNoticeInfos-> SendWorkNoticeUtil.sendWorkNotice(workNoticeInfos));
//
//}

/**
* 扫描的间隔越来越长 秒数
*/


+ 15
- 20
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/manage/TodoCenterManage.java View File

@@ -32,6 +32,7 @@ import com.ningdatech.pmapi.projectlib.service.IProjectApplicationService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.staging.enums.MsgTypeEnum;
import com.ningdatech.pmapi.staging.service.INdWorkNoticeStagingService;
import com.ningdatech.pmapi.staging.service.IProjectStagingService;
import com.ningdatech.pmapi.todocenter.bean.entity.WorkNoticeInfo;
import com.ningdatech.pmapi.todocenter.model.dto.AdjustHandleDTO;
import com.ningdatech.pmapi.todocenter.model.vo.ProcessProgressDetailVo;
@@ -105,6 +106,8 @@ public class TodoCenterManage {
private final UserInfoHelper userInfoHelper;
private final BuildUserUtils buildUserUtils;

private final IProjectStagingService projectStagingService;


/**
* 待办中心待我处理项目列表查询
@@ -229,8 +232,6 @@ public class TodoCenterManage {
Integer projectStatus = declaredProject.getStatus();
// 获取当前未处理流程详情
ProcessProgressVo currentInstanceDetail = processInstanceService.getProgressInstanceDetail(null, processInstanceId);
// 获取当前未处理流程状态
String currentProcessStatus = currentInstanceDetail.getStatus();

// 获取当前要处理的流程实例
HistoricProcessInstance instance = historyService.createHistoricProcessInstanceQuery()
@@ -256,7 +257,7 @@ public class TodoCenterManage {
// 获取流程通过后当前审核人信息,向其发送工作通知
List<ProgressNode> newProgressInfo = newInstanceDetail.getProgressInfo();
ProgressNode currentNode = newProgressInfo.get(newProgressInfo.size() - 1);
UserInfo auditUserInfo = null;
UserInfo auditUserInfo;
// 说明当前节点是子流程节点
if (currentNode.getNodeType().name().equals(NodeTypeEnum.SUB.name())) {
List<ProgressNode> children = currentNode.getChildren();
@@ -267,31 +268,25 @@ public class TodoCenterManage {
auditUserInfo = userInfoService.getById(Long.valueOf(currentNode.getUserId()));
}

// 如果流程状态是被退回状态,流程通过后,进入下一个审核人,
// 当前通过审核人一定不是最后一个审核人(下一个审核人至多是最后一个)
if (ProcessStatusEnum.BE_BACKED.getDesc().equals(currentProcessStatus)) {
// 获取发送浙政钉工作通知必要信息
WorkNoticeInfo passWorkNoticeInfo = getSendWorkNoticeInfo(auditUserInfo);
String passMsg = String.format(PASS_MSG_TEMPLATE, passWorkNoticeInfo.getOrganizationName(), projectName);
passWorkNoticeInfo.setMsg(passMsg);
// 放入工作通知暂存表中,通过扫表异步发送
workNoticeStagingService.addByWorkNotice(passWorkNoticeInfo, MsgTypeEnum.AUDIT);
return;
}
// 若不是被退回状态,流程通过后,判断当前登录用户是不是最后一个审核人
// 流程通过后,判断当前登录用户是不是最后一个审核人
// 若当前登录用户是最后一个审批人,需更新流程状态为审核完成,项目状态到下个状态
// 并向流程发起人发送浙政钉工作通知:【项目名称】已通过【流程名称】,请及时开始下一步操作。
if (HisProInsEndActId.END.equals(newInstance.getEndActivityId())) {
switch (Objects.requireNonNull(ProjectStatusEnum.getValue(projectStatus))) {
// 当前项目状态是预审中
case PRE_APPLYING:
//先修改项目状态
updatePassProjectStatus(userId, declaredProject);
//然后入库暂存库
projectStagingService.addByProject(declaredProject,"暂存入库 待提交部门联审");
break;
// 当前项目状态是单位内部审核中
case UNDER_INTERNAL_AUDIT:
// 当前项目状态是预审中
case PRE_APPLYING:
// 当前项目状态是部门联审中
// 当前项目状态是部门联审中
case DEPARTMENT_JOINT_REVIEW:
// 当前项目状态是方案评审中
// 当前项目状态是方案评审中
case SCHEME_UNDER_REVIEW:
// 当前项目状态是终验审核中
// 当前项目状态是终验审核中
case FINAL_ACCEPTANCE_IS_UNDER_REVIEW:
updatePassProjectStatus(userId, declaredProject);
break;


+ 140
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/model/dto/PdfGenerateDTO.java View File

@@ -0,0 +1,140 @@
package com.ningdatech.pmapi.todocenter.model.dto;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;

/**
* pdf生成实体
*
* @author CMM
* @since 2023/03/13 14:24
*/
@Data
public class PdfGenerateDTO {
@ApiModelProperty("应用ID")
private Long id;

@ApiModelProperty("项目名称")
private String projectName;

@ApiModelProperty("是否临时增补 0:否 1:是")
private String isTemporaryAugment;

@ApiModelProperty("项目负责人")
private String responsibleMan;

@ApiModelProperty("负责人手机号码")
private String responsibleManMobile;

@ApiModelProperty("项目联系人")
private String contactName;

@ApiModelProperty("项目联系人手机号码")
private String contactPhone;

@ApiModelProperty("建设单位名称")
private String buildOrgName;

@ApiModelProperty("建设单位统一社会信用代码")
private String orgCreditCode;

@ApiModelProperty("项目类型 1:建设 2:运维")
private String projectType;

@ApiModelProperty("是否首次新建 0:否 1:是")
private String isFirst;

@ApiModelProperty("项目预算年度")
private Integer projectYear;

@ApiModelProperty("项目建设起止时间")
private String beginAndEndTime;

@ApiModelProperty("四大体系 1:业务应用 2:应用支撑 3:数据资源 4:基础设施")
private String fourSystems;

@ApiModelProperty("是否数字化改革项目 0:否 1:是")
private String isDigitalReform;

@ApiModelProperty("综合业务领域")
private String bizDomain;

@ApiModelProperty("立项依据")
private String buildBasis;


@ApiModelProperty("是否上云 0:否 1:是")
private String isCloud;

private String cloudType;

@ApiModelProperty("等保级别 1:一级 2:二级 3:三级 4:四级 5:五级")
private Integer protectionLevel;

@ApiModelProperty("是否密评 0:否 1:是")
private Integer isSecretComments;

@ApiModelProperty("项目简介")
private String projectIntroduction;

@ApiModelProperty("资金申报情况-申报金额(万元)")
private BigDecimal declareAmount;

@ApiModelProperty("资金申报情况-自有金额(万元)")
private BigDecimal declareHaveAmount;

@ApiModelProperty("资金申报情况-政府投资-本级财政资金(万元)")
private BigDecimal declareGovOwnFinanceAmount;

@ApiModelProperty("资金申报情况-政府投资-上级补助资金(万元)")
private BigDecimal declareGovSuperiorFinanceAmount;

@ApiModelProperty("银行贷款(万元)")
private BigDecimal declareBankLendingAmount;

@ApiModelProperty("其它资金(万元)")
private BigDecimal declareOtherAmount;

@ApiModelProperty("资金分配情况-软件开发(万元)")
private BigDecimal softwareDevelopmentAmount;

@ApiModelProperty("资金分配情况-云资源、硬件购置(万元)")
private BigDecimal cloudHardwarePurchaseAmount;

@ApiModelProperty("资金分配情况-第三方服务(万元)")
private BigDecimal thirdPartyAmount;

@ApiModelProperty("年度支付计划-年度支付计划(万元)")
private BigDecimal annualPlanAmount;

@ApiModelProperty("年度支付计划-自有金额(万元)")
private BigDecimal annualPlanHaveAmount;

@ApiModelProperty("年度支付计划-政府投资-本级财政资金(万元)")
private BigDecimal annualPlanGovOwnFinanceAmount;

@ApiModelProperty("年度支付计划-政府投资-上级补助资金(万元)")
private BigDecimal annualPlanGovSuperiorFinanceAmount;

@ApiModelProperty("年度支付计划-银行贷款(万元)")
private BigDecimal annualPlanBankLendingAmount;

@ApiModelProperty("年度支付计划-其它资金(万元)")
private BigDecimal annualPlanOtherAmount;

@ApiModelProperty("备注")
private String projectRemarks;

@ApiModelProperty("附件-是否开启 false:关闭 true:开启")
private Boolean isAccessories;

@ApiModelProperty("备注-是否开启 false:关闭 true:开启")
private Boolean isRemarks;

@ApiModelProperty("年度支付计划-是否开启 false:关闭 true:开启")
private Boolean isAnnualPlanAmount;

@ApiModelProperty("一地创新全省共享项目-是否开启 false:关闭 true:开启")
private Boolean isInnovateWholeProvinceShare;
}

+ 140
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/utils/PdfGenerateUtil.java View File

@@ -0,0 +1,140 @@
package com.ningdatech.pmapi.todocenter.utils;

import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.*;

/**
* pdf 生成工具
*
* @author CMM
* @since 2023/03/13 13:41
*/
@Slf4j
public class PdfGenerateUtil {

private PdfGenerateUtil() {
}


/**
* 生成填充了模板参数的pdf
*
* @param templatePdfInputStream 模板pdf流
* @param paramsMap 填充参数
* @return
*/
public static byte[] generatePdf(InputStream templatePdfInputStream,Map<String, Object> paramsMap) throws IOException {
byte[] templatePdfByteArray = readBytes(templatePdfInputStream);
return generatePdf(templatePdfByteArray, paramsMap);
}

/**
* 生成填充了模板参数的pdf
*
* @param templatePdfByteArray 模板pdf字节数组
* @param paramsMap 填充参数
* @return
*/
public static byte[] generatePdf(byte[] templatePdfByteArray, Map<String, Object> paramsMap) {

PdfReader reader = null;
ByteArrayOutputStream bos = null;
try {
//创建书写器,用于往document中书写信息
// 通过本地文件路径获取资源
reader = new PdfReader(templatePdfByteArray);
bos = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, bos);

//使用中文字体
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<>();
fontList.add(baseFont);


AcroFields form = stamper.getAcroFields();
form.setSubstitutionFonts(fontList);

for (String fieldName : paramsMap.keySet()) {
if (paramsMap.get(fieldName) == null) {
continue;
}

if (fieldName.indexOf("Image") > 0) {
String imgPath = paramsMap.get(fieldName).toString();
int pageNo = form.getFieldPositions(fieldName).get(0).page;
Rectangle rectangle = form.getFieldPositions(fieldName).get(0).position;
float x = rectangle.getLeft();
float y = rectangle.getTop();
//根据路径读取图片
Image image = Image.getInstance(imgPath);
//获取图片页面
PdfContentByte under = stamper.getOverContent(pageNo);
//图片大小自适应
image.scaleToFit(rectangle.getWidth(), rectangle.getHeight());
//添加图片
image.setAbsolutePosition(x, y - rectangle.getHeight());
under.addImage(image);
} else {
// 设置占位字段
form.setField(fieldName, paramsMap.get(fieldName).toString());
}
}

stamper.setFormFlattening(false);
stamper.close();

} catch (Exception e) {
log.error("通过模板生成PDF失败", e.getMessage());
return null;
} finally {
try {
if (null != reader) {
reader.close();
}
if (null != bos) {
bos.close();
}

} catch (IOException e) {
log.error("close resource error", e.getMessage());
}
}

return bos.toByteArray();
}

/**
* 读取输入流到字节数组
*
* @param in
* @return
* @throws IOException
*/
private static byte[] readBytes(InputStream in) throws IOException {
//读取字节的缓冲
byte[] buffer = new byte[1024];
//最终的数据
byte[] result = new byte[0];
int size = 0;
while ((size = in.read(buffer)) != -1) {
int oldLen = result.length;
byte[] tmp = new byte[oldLen + size];
if (oldLen > 0) {//copy 旧字节
System.arraycopy(result, 0, tmp, 0, oldLen);
}
//copy 新字节
System.arraycopy(buffer, 0, tmp, oldLen, size);

result = tmp;
}
return result;
}
}



+ 153
- 0
pmapi/src/main/java/com/ningdatech/pmapi/todocenter/utils/PdfUtils.java View File

@@ -0,0 +1,153 @@
package com.ningdatech.pmapi.todocenter.utils;


import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.*;
import com.ningdatech.basic.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.UUID;

/**
* pdf生成工具类
*
* @author CMM
* @since 2023/03/13 17:01
*/
@Slf4j
@Component
public class PdfUtils {
/**
* 生成PDF文件
*
* @return int
* @author CMM
* @since 2023/03/13 17:07
*/
public byte[] generatePdf(InputStream templateHtmlInputStream, Map<String, Object> paramsMap){
FileInputStream inputStream = null;

try {
File directory = new File("");
//pdf输出路径
String absolutePath = directory.getAbsolutePath();
String linkPath = "\\src\\main\\resources";
String filePath = absolutePath + linkPath + "\\template\\fileout";
if(!new File(filePath).exists()){
new File(filePath).mkdir();
}
//字体格式
String FONT = absolutePath + linkPath + "\\template\\simsun.ttc";
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(templateHtmlInputStream, StandardCharsets.UTF_8));
String line;
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
String htmlInfo = stringBuilder.toString();

//替换参数、多个参数多次替换
for (String fieldName : paramsMap.keySet()) {
if (paramsMap.get(fieldName) == null) {
continue;
}
// 设置占位字段
htmlInfo = htmlInfo.replace("#" + fieldName + "#", paramsMap.get(fieldName).toString());
}


//生成临时文件
String htmlFileName = UUID.randomUUID().toString().replace("-","") + ".html";
String htmlFilePath = filePath + File.separator + htmlFileName;
File file = new File(htmlFilePath);
FileOutputStream fop = new FileOutputStream(file);
if (!file.exists()) {
file.createNewFile();
}
byte[] contentInBytes = htmlInfo.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();

//生成pdf
String fileName = UUID.randomUUID().toString().replace("-","") + ".pdf";
String pdfFilePath = filePath + File.separator + fileName;
String url = new File(htmlFilePath).toURI().toURL().toString();
OutputStream os = Files.newOutputStream(Paths.get(pdfFilePath));

ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
renderer.layout();
renderer.createPDF(os);
os.flush();
os.close();

inputStream = new FileInputStream(pdfFilePath);

//删除临时文件
File delFile = new File(pdfFilePath);
if(delFile.exists()){
delFile.delete();
}
File delHtmlFile = new File(htmlFilePath);
if(delHtmlFile.exists()){
delHtmlFile.delete();
}
// 返回生成的pdf文件字节数组
return readBytes(inputStream);
} catch (IOException e) {
throw new BizException("生成pdf文件失败!");
} catch (DocumentException e) {
throw new BizException("生成pdf文件失败!");
} finally {
try {
if (null != inputStream) {

inputStream.close();
}
} catch (IOException e) {
log.error("close resource error", e.getMessage());
}
}
}


/**
* 读取输入流到字节数组
*
* @param in
* @return
* @throws IOException
*/
private byte[] readBytes(InputStream in) throws IOException {
//读取字节的缓冲
byte[] buffer = new byte[1024];
//最终的数据
byte[] result = new byte[0];
int size = 0;
while ((size = in.read(buffer)) != -1) {
int oldLen = result.length;
byte[] tmp = new byte[oldLen + size];
if (oldLen > 0) {//copy 旧字节
System.arraycopy(result, 0, tmp, 0, oldLen);
}
//copy 新字节
System.arraycopy(buffer, 0, tmp, oldLen, size);

result = tmp;
}
return result;
}

}

+ 10
- 0
pmapi/src/main/java/com/ningdatech/pmapi/user/model/vo/ResUserDetailVO.java View File

@@ -1,5 +1,6 @@
package com.ningdatech.pmapi.user.model.vo;

import com.ningdatech.pmapi.common.constant.RegionConst;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -48,4 +49,13 @@ public class ResUserDetailVO {

@ApiModelProperty("更新时间")
private LocalDateTime updateTime;

//是否是市级单位
public Boolean getIsMunicipalOrg(){
//如果是丽水市本级的code 就是
if(RegionConst.RC_LS.equals(this.regionCode)){
return Boolean.TRUE;
}
return Boolean.FALSE;
}
}

BIN
pmapi/src/main/resources/template/fileout/c34f631755a04532a0116494fd5f99ac.pdf View File


BIN
pmapi/src/main/resources/template/simsun.ttc View File


+ 254
- 0
pmapi/src/main/resources/template/盖章文件.html View File

@@ -0,0 +1,254 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html,
body {
padding: 0;
margin: 0;
}
.pdf {
margin: 0 auto;
padding: 10px 0 30px;
text-align: center;
}
.title {
padding: 0 0 40px 0;
font-size: 34px;
margin: 40px 0 0 0;
}
.tab {
padding: 0 20px;
}
.projectId {
color: #999999;
text-align: left;
margin-bottom: 8px;
}
.projectId > .time {
float: right;
}

table {
width: 100%;
border-collapse: collapse;
font-size: 16px;
table-layout: fixed;
word-break: break-all;
text-align: left;
}
td {
padding: 15px 8px;
border: 1px solid;
}
.tabTit {
background-color: #eee;
}
.label {
width: 150px;
}
.sealTd {
height: 200px;
position: relative;
}
.seal {
position: absolute;
right: 20px;
bottom: 30px;
width: 150px;
}
.seal > .time {
text-align: right;
}
.content {
height: 150px;
}
.text {
min-height: 150px;
}
</style>
</head>
<body>
<div class="pdf">
<p class="title">
<span></span>
】预审申请单
</p>
<div class="tab">
<p class="projectId">
<span>
项目编号:
<span></span>
</span>
<span class="time"></span>
</p>
<table>
<tbody>
<tr>
<td class="tabTit" colspan="4">项目基本信息</td>
</tr>
<tr>
<td class="label">项目名称</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="label">是否临时增补</td>
<td></td>
<td class="label">是否一地创新全省共享项目</td>
<td></td>
</tr>
<tr>
<td class="label">项目负责人</td>
<td></td>
<td class="label">负责人手机号</td>
<td></td>
</tr>
<tr>
<td class="label">项目联系人</td>
<td></td>
<td class="label">项目联系人手机号</td>
<td></td>
</tr>
<tr>
<td class="label">建设单位</td>
<td></td>
<td class="label">建设单位统一社会信用代码</td>
<td></td>
</tr>
<tr>
<td class="label">项目类型</td>
<td></td>
<td class="label">是否首次新建</td>
<td></td>
</tr>
<tr>
<td class="label">预算年度</td>
<td></td>
<td class="label">建设起止时间</td>
<td></td>
</tr>
<tr>
<td class="label">四大体系</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="label">是否数字化改革项目</td>
<td></td>
<td class="label">综合业务领域</td>
<td></td>
</tr>
<tr>
<td class="label">立项依据</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="label">是否上云</td>
<td></td>
<td class="label">云类型</td>
<td></td>
</tr>
<tr>
<td class="label">项目简介</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="tabTit" colspan="4">资金申报情况</td>
</tr>
<tr>
<td class="label">申报金额</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="label">自有资金</td>
<td></td>
<td class="label">政府投资-本级财政资金</td>
<td></td>
</tr>
<tr>
<td class="label">政府投资-上级补助资金</td>
<td></td>
<td class="label">银行贷款</td>
<td></td>
</tr>
<tr>
<td class="label">自有资金</td>
<td></td>
<td class="label">政府投资-本级财政资金</td>
<td></td>
</tr>
<tr>
<td class="label">其他资金</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="label">2021年计划投资(万元)</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="tabTit" colspan="4">资金分配情况</td>
</tr>
<tr>
<td class="label">软件开发</td>
<td></td>
<td class="label">云资源、硬件购置</td>
<td></td>
</tr>
<tr>
<td class="label">第三方服务</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="tabTit" colspan="4">年度支付计划</td>
</tr>
<tr>
<td class="label">年度支付金额</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="label">自有资金</td>
<td></td>
<td class="label">政府投资-本级财政资金</td>
<td></td>
</tr>
<tr>
<td class="label">政府投资-上级补助资金</td>
<td></td>
<td class="label">银行贷款</td>
<td></td>
</tr>
<tr>
<td class="label">其他资金</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="tabTit" colspan="4">备注</td>
</tr>
<tr>
<td class="label">备注</td>
<td colspan="3"></td>
</tr>
<tr>
<td class="tabTit" colspan="4">单位意见</td>
</tr>
<tr>
<td class="label">本级主管单位意见(盖章)</td>
<td colspan="3" class="text content"></td>
</tr>
<tr>
<td class="label">上级主管单位意见(盖章)</td>
<td colspan="3" class="text content"></td>
</tr>
<tr>
<td class="label">{本地区大数据局的名称}意见(盖章)</td>
<td colspan="3" class="text content"></td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

+ 249
- 0
pmapi/src/main/resources/template/预审申请单.html View File

@@ -0,0 +1,249 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:font-family="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html,
body {
padding: 0;
margin: 0;
font-family:SimSun;
}
.pdf {
margin: 0 auto;
padding: 10px 0 30px;
text-align: center;
}
.title {
padding: 0 0 40px 0;
font-size: 34px;
margin: 40px 0 0 0;
font-family:SimSun;
}
.tab {
padding: 0 20px;
}
.projectId {
color: #999999;
text-align: left;
margin-bottom: 8px;
}
.projectId > .time {
float: right;
}

table {
width: 100%;
border-collapse: collapse;
font-size: 16px;
table-layout: fixed;
word-break: break-all;
word-wrap: break-word;
text-align: left;
}
td {
padding: 15px 8px;
border: 1px solid;
}
.tabTit {
background-color: #eee;
}
.label {
width: 150px;
}
.sealTd {
height: 200px;
position: relative;
}
.seal {
position: absolute;
right: 20px;
bottom: 30px;
width: 150px;
}
.seal > .time {
text-align: right;
}
.content {
height: 150px;
}
.text {
min-height: 150px;
}
</style>
</head>
<body>
<div class="pdf">
<p class="title">
预审申请单
</p>
<div class="tab">
<p class="projectId">
<span>
项目编号:
<span>#projectNo#</span>
</span>
<span class="time">#time#</span>
</p>
<table>
<tbody>
<tr>
<td class="tabTit" colspan="4">项目基本信息</td>
</tr>
<tr>
<td class="label">项目名称</td>
<td colspan="3" align="center">#projectName#</td>
</tr>
<tr>
<td class="label">是否临时增补</td>
<td align="center">#isTemporaryAugment#</td>
<td class="label">是否一地创新全省共享项目</td>
<td align="center">#isInnovateWholeProvinceShare#</td>
</tr>
<tr>
<td class="label">项目负责人</td>
<td align="center">#responsibleMan#</td>
<td class="label">负责人手机号</td>
<td align="center">#responsibleManMobile#</td>
</tr>
<tr>
<td class="label">项目联系人</td>
<td align="center">#contactName#</td>
<td class="label">项目联系人手机号</td>
<td align="center">#contactPhone#</td>
</tr>
<tr>
<td class="label">建设单位</td>
<td align="center">#buildOrgName#</td>
<td class="label">建设单位统一社会信用代码</td>
<td align="center">#orgCreditCode#</td>
</tr>
<tr>
<td class="label">项目类型</td>
<td align="center">#projectType#</td>
<td class="label">是否首次新建</td>
<td align="center">#isFirst#</td>
</tr>
<tr>
<td class="label">预算年度</td>
<td align="center">#projectYear#</td>
<td class="label">建设起止时间</td>
<td align="center">#beginAndEndTime#</td>
</tr>
<tr>
<td class="label">四大体系</td>
<td colspan="3" align="center">#fourSystems#</td>
</tr>
<tr>
<td class="label">是否数字化改革项目</td>
<td align="center">#isDigitalReform#</td>
<td class="label">综合业务领域</td>
<td align="center">#bizDomain#</td>
</tr>
<tr>
<td class="label">立项依据</td>
<td colspan="3" align="center">#buildBasis#</td>
</tr>
<tr>
<td class="label">是否上云</td>
<td align="center">#isCloud#</td>
<td class="label">云类型</td>
<td align="center">#cloudType#</td>
</tr>
<tr>
<td class="label">项目简介</td>
<td colspan="3" align="center">#projectIntroduction#</td>
</tr>
<tr>
<td class="tabTit" colspan="4">资金申报情况</td>
</tr>
<tr>
<td class="label">申报金额</td>
<td colspan="3" align="center">#declareAmount#</td>
</tr>
<tr>
<td class="label">自有资金</td>
<td align="center">#declareHaveAmount#</td>
<td class="label">政府投资-本级财政资金</td>
<td align="center">#declareGovOwnFinanceAmount#</td>
</tr>
<tr>
<td class="label">政府投资-上级补助资金</td>
<td align="center">#declareGovSuperiorFinanceAmount#</td>
<td class="label">银行贷款</td>
<td align="center">#declareBankLendingAmount#</td>
</tr>
<tr>
<td class="label">其他资金</td>
<td colspan="3" align="center">#declareOtherAmount#</td>
</tr>
<tr>
<td class="label">本年计划投资(万元)</td>
<td colspan="3" align="center">#yearPlanInvest#</td>
</tr>
<tr>
<td class="tabTit" colspan="4">资金分配情况</td>
</tr>
<tr>
<td class="label">软件开发</td>
<td align="center">#softwareDevelopmentAmount#</td>
<td class="label">云资源、硬件购置</td>
<td align="center">#cloudHardwarePurchaseAmount#</td>
</tr>
<tr>
<td class="label">第三方服务</td>
<td colspan="3" align="center">#thirdPartyAmount#</td>
</tr>
<tr>
<td class="tabTit" colspan="4">年度支付计划</td>
</tr>
<tr>
<td class="label">年度支付金额</td>
<td colspan="3" align="center">#annualPlanAmount#</td>
</tr>
<tr>
<td class="label">自有资金</td>
<td align="center">#annualPlanHaveAmount#</td>
<td class="label">政府投资-本级财政资金</td>
<td align="center">#annualPlanGovOwnFinanceAmount#</td>
</tr>
<tr>
<td class="label">政府投资-上级补助资金</td>
<td align="center">#annualPlanGovSuperiorFinanceAmount#</td>
<td class="label">银行贷款</td>
<td align="center">#annualPlanBankLendingAmount#</td>
</tr>
<tr>
<td class="label">其他资金</td>
<td colspan="3" align="center">#annualPlanOtherAmount#</td>
</tr>
<tr>
<td class="tabTit" colspan="4">备注</td>
</tr>
<tr>
<td class="label">备注</td>
<td colspan="3" align="center">#projectRemarks#</td>
</tr>
<tr>
<td class="tabTit" colspan="4">单位意见</td>
</tr>
<tr>
<td class="label">本级主管单位意见(盖章)</td>
<td colspan="3" class="text content"></td>
</tr>
<tr>
<td class="label">上级主管单位意见(盖章)</td>
<td colspan="3" class="text content"></td>
</tr>
<tr>
<td class="label">{本地区大数据局的名称}意见(盖章)</td>
<td colspan="3" class="text content"></td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>

BIN
pmapi/src/main/resources/template/预审申请单.pdf View File


+ 82
- 4
pmapi/src/test/java/com/ningdatech/pmapi/todocenter/TodoCenterTest.java View File

@@ -1,18 +1,38 @@
package com.ningdatech.pmapi.todocenter;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.ningdatech.basic.model.GenericResult;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.file.entity.vo.result.FileResultVO;
import com.ningdatech.file.service.FileService;
import com.ningdatech.pmapi.AppTests;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectTypeEnum;
import com.ningdatech.pmapi.projectlib.manage.ProjectLibManage;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.vo.ProjectDetailVO;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.staging.enums.MsgTypeEnum;
import com.ningdatech.pmapi.staging.service.INdWorkNoticeStagingService;
import com.ningdatech.pmapi.todocenter.bean.entity.WorkNoticeInfo;
import com.ningdatech.pmapi.todocenter.manage.TodoCenterManage;
import com.ningdatech.pmapi.todocenter.model.dto.PdfGenerateDTO;
import com.ningdatech.pmapi.todocenter.utils.PdfGenerateUtil;
import com.ningdatech.pmapi.todocenter.utils.PdfUtils;
import com.ningdatech.pmapi.user.entity.UserInfo;
import com.ningdatech.pmapi.user.service.IUserInfoService;
import com.ningdatech.zwdd.client.ZwddClient;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.concurrent.*;

import static com.ningdatech.pmapi.todocenter.constant.WorkNotice.PASS_MSG_TEMPLATE;
@@ -25,10 +45,6 @@ import static com.ningdatech.pmapi.todocenter.constant.WorkNotice.PASS_MSG_TEMPL
*/
@Slf4j
public class TodoCenterTest extends AppTests {

//@Autowired
//private TaskExecutor executor;

@Autowired
private TodoCenterManage todoCenterManage;
@Autowired
@@ -37,6 +53,14 @@ public class TodoCenterTest extends AppTests {
private ZwddClient zwddClient;
@Autowired
private INdWorkNoticeStagingService workNoticeStagingService;
@Autowired
private ProjectLibManage projectLibManage;
@Autowired
private FileService fileService;
@Autowired
private IProjectService projectService;
@Autowired
private PdfUtils pdfUtils;
@Test
public void sendWorkNoticeTest() throws ExecutionException, InterruptedException {
//String msg = String.format(PASS_MSG_TEMPLATE, "发改委", "0223-00-测试项目");
@@ -98,4 +122,58 @@ public class TodoCenterTest extends AppTests {
// 放入工作通知暂存表中,通过扫表异步发送
workNoticeStagingService.addByWorkNotice(passWorkNoticeInfo, MsgTypeEnum.AUDIT);
}

@Test
public void GeneratePdf(){
// 获取本地目录的pdf模板
String fileName = "预审申请单";
InputStream pdfInputStream =
this.getClass().getClassLoader().getResourceAsStream("template/" + fileName + ".html");
// 获取表单数据
ProjectDetailVO projectDetail = projectLibManage.getProjectDetail(44L);
PdfGenerateDTO pdfGenerateDTO = new PdfGenerateDTO();
BeanUtils.copyProperties(projectDetail, pdfGenerateDTO);
// 设置pdf模板参数
JSONObject paramsMap = JSONObject.parseObject(JSONObject.toJSONString(pdfGenerateDTO));
paramsMap.put("time", NdDateUtils.format(LocalDateTime.now(), "yyyy-MM-dd HH:mm"));
paramsMap.put("isTemporaryAugment", "否");
Integer projectType = projectDetail.getProjectType();
paramsMap.put("projectType", ProjectTypeEnum.getDesc(projectType));
Integer isFirst = projectDetail.getIsFirst();
paramsMap.put("isFirst", "是");
Boolean isInnovateWholeProvinceShare = projectDetail.getIsInnovateWholeProvinceShare();
paramsMap.put("isInnovateWholeProvinceShare", Boolean.TRUE.equals(isInnovateWholeProvinceShare) ? "是" : "否");
String beginTime = projectDetail.getBeginTime();
String endTime = projectDetail.getEndTime();
String beginAndEndTime = beginTime + StrUtil.DASHED + endTime;
paramsMap.put("beginAndEndTime", beginAndEndTime);
Integer fourSystems = projectDetail.getFourSystems();
paramsMap.put("fourSystems", "业务应用");
Integer isDigitalReform = projectDetail.getIsDigitalReform();
paramsMap.put("isDigitalReform", "否");
Integer isCloud = projectDetail.getIsCloud();
paramsMap.put("isCloud", "否");

// 生成pdf字节数组

byte[] pdf = pdfUtils.generatePdf(pdfInputStream, paramsMap);

// 转换成MultipartFile
MultipartFile multipartFile = new MockMultipartFile("file", fileName + ".pdf", "application/pdf", pdf);

// 上传OSS
FileResultVO resultVO = fileService.upload(multipartFile, "default");

// 将返回的文件ID保存到项目库中
Project project = projectService.getById(44L);
project.setPretrialFileId(resultVO.getId());

try {
if (null != pdfInputStream) {
pdfInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

+ 24
- 0
pom.xml View File

@@ -148,6 +148,28 @@
<artifactId>spring-statemachine-core</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>

<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.9</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.9</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.0.3</version>
</dependency>

</dependencies>
</dependencyManagement>

@@ -165,6 +187,8 @@
</snapshots>
</repository>
</repositories>


<pluginRepositories>
<!--阿里云代理Spring 插件仓库-->
<pluginRepository>


Loading…
Cancel
Save