@@ -191,6 +191,11 @@ | |||
<artifactId>nd-basic</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.ningdatech</groupId> | |||
<artifactId>nd-yxt-starter</artifactId> | |||
<version>1.0.0</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>easyexcel-core</artifactId> | |||
</dependency> | |||
@@ -229,6 +234,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--> | |||
@@ -44,9 +44,9 @@ public class GlobalResponseHandler implements ResponseBodyAdvice<Object> { | |||
// ConverterType是StringHttpMessageConverter这个类型转换, | |||
// 由于将结果封装成了自定义的ApiResponse类型,所以有ApiResponse转换成String报错 | |||
// 所以需要对String类型的返回值单独进行处理 | |||
if (o instanceof String) { | |||
return JSONUtil.toJsonStr(apiResponse); | |||
} | |||
// if (o instanceof String) { | |||
// return JSONUtil.toJsonStr(apiResponse); | |||
// } | |||
return ApiResponse.ofSuccess(o); | |||
// return o; | |||
} | |||
@@ -22,11 +22,16 @@ import com.ningdatech.pmapi.expert.service.ExpertInfoService; | |||
import com.ningdatech.pmapi.expert.service.IExpertUserFullInfoService; | |||
import com.ningdatech.pmapi.meta.constant.DictExpertInfoTypeEnum; | |||
import com.ningdatech.pmapi.meta.model.ExpertRegionInfo; | |||
import com.ningdatech.pmapi.user.constant.UserAvailableEnum; | |||
import com.ningdatech.pmapi.user.entity.UserInfo; | |||
import com.ningdatech.pmapi.user.service.IUserInfoService; | |||
import com.ningdatech.pmapi.user.util.LoginUserUtil; | |||
import lombok.RequiredArgsConstructor; | |||
import org.apache.commons.collections4.CollectionUtils; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import java.time.LocalDateTime; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.util.Objects; | |||
@@ -47,6 +52,7 @@ public class ExpertManage { | |||
private final ExpertInfoCommonHelper expertInfoCommonHelper; | |||
private final FileService fileService; | |||
private final ExpertUserInfoAssembler expertUserInfoAssembler; | |||
private final IUserInfoService iUserInfoService; | |||
/** | |||
@@ -56,8 +62,11 @@ public class ExpertManage { | |||
*/ | |||
public void expertBasicInfoSubmit(ExpertUserBasicInfoSubmitRequest request) { | |||
// 用户id | |||
Long userId = LoginUserUtil.getUserId(); | |||
// Long userId = LoginUserUtil.getUserId(); | |||
ExpertBasicInfo basicInfo = request.getBasicInfo(); | |||
Long userId = generateOrGetUserId(basicInfo); | |||
// 校验区域编码合法性 校验履职意向编码合法性 | |||
ExpertRegionInfo expertRegionInfo = basicInfo.getExpertRegionInfo(); | |||
expertManageHelper.expertRegionInfoCheck(expertRegionInfo); | |||
@@ -137,4 +146,25 @@ public class ExpertManage { | |||
List<AttachFileVo> attachFiles = fileService.getByIds(fileIdList); | |||
return expertUserInfoAssembler.buildExpertFullInfoVO(attachFiles, expertUserFullInfoAll); | |||
} | |||
@Transactional(rollbackFor = Exception.class) | |||
public Long generateOrGetUserId(ExpertBasicInfo basicInfo) { | |||
String phoneNo = basicInfo.getPhoneNo(); | |||
UserInfo userInfo = iUserInfoService.getUserInfoByPhoneNo(phoneNo); | |||
if (Objects.isNull(userInfo)) { | |||
userInfo = UserInfo.builder() | |||
// .accountId(dingEmployeeInfo.getAccountId()) | |||
.username(basicInfo.getName()) | |||
.realName(basicInfo.getName()) | |||
// .employeeCode(dingEmployeeInfo.getEmployeeCode()) | |||
.available(UserAvailableEnum.DISABLE.name()) | |||
.createBy(LoginUserUtil.getUserId()) | |||
.updateBy(LoginUserUtil.getUserId()) | |||
.createOn(LocalDateTime.now()) | |||
.updateOn(LocalDateTime.now()) | |||
.build(); | |||
iUserInfoService.save(userInfo); | |||
} | |||
return userInfo.getId(); | |||
} | |||
} |
@@ -1,20 +1,44 @@ | |||
package com.ningdatech.pmapi.organization.controller; | |||
import com.ningdatech.pmapi.organization.manage.GovBusinessStripManage; | |||
import com.ningdatech.pmapi.organization.model.vo.GovBusinessStripTreeVO; | |||
import io.swagger.annotations.Api; | |||
import io.swagger.annotations.ApiOperation; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.stereotype.Controller; | |||
import org.springframework.validation.annotation.Validated; | |||
import org.springframework.web.bind.annotation.GetMapping; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.web.bind.annotation.RequestParam; | |||
import org.springframework.web.bind.annotation.RestController; | |||
import org.springframework.stereotype.Controller; | |||
import java.util.List; | |||
/** | |||
* <p> | |||
* 前端控制器 | |||
* 前端控制器 | |||
* </p> | |||
* | |||
* @author Liuxinxin | |||
* @since 2023-03-08 | |||
*/ | |||
@Controller | |||
@RequestMapping("/pmapi.organization/gov-business-strip") | |||
@Slf4j | |||
@Validated | |||
@RestController | |||
@RequiredArgsConstructor | |||
@Api(value = "GovBusinessStripController", tags = "条线管理") | |||
@RequestMapping("/api/v1/gov-business-strip") | |||
public class GovBusinessStripController { | |||
private final GovBusinessStripManage govBusinessStripManage; | |||
@GetMapping("/get-child-list") | |||
@ApiOperation("获取条线标签的的树状结构") | |||
public List<GovBusinessStripTreeVO> getChildOrganizationList(@RequestParam(value = "parentCode", required = false) String parentCode) { | |||
return govBusinessStripManage.getChildOrganizationList(parentCode); | |||
} | |||
} |
@@ -5,7 +5,6 @@ import io.swagger.annotations.ApiModel; | |||
import lombok.Data; | |||
import java.io.Serializable; | |||
import java.time.LocalDateTime; | |||
/** | |||
* <p> | |||
@@ -24,14 +23,6 @@ public class GovBusinessStrip implements Serializable { | |||
private Long id; | |||
private LocalDateTime createOn; | |||
private LocalDateTime updateOn; | |||
private Long createBy; | |||
private Long updateBy; | |||
/** | |||
* 条线code | |||
*/ | |||
@@ -41,4 +32,14 @@ public class GovBusinessStrip implements Serializable { | |||
* 条线名称 | |||
*/ | |||
private String businessStripName; | |||
/** | |||
* 父级条线code | |||
*/ | |||
private String parentCode; | |||
/** | |||
* 父级条线名称 | |||
*/ | |||
private String parentName; | |||
} |
@@ -0,0 +1,42 @@ | |||
package com.ningdatech.pmapi.organization.manage; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.pmapi.organization.entity.GovBusinessStrip; | |||
import com.ningdatech.pmapi.organization.model.vo.GovBusinessStripTreeVO; | |||
import com.ningdatech.pmapi.organization.service.IGovBusinessStripService; | |||
import lombok.RequiredArgsConstructor; | |||
import org.springframework.stereotype.Component; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @author liuxinxin | |||
* @date 2023/3/14 下午4:48 | |||
*/ | |||
@Component | |||
@RequiredArgsConstructor | |||
public class GovBusinessStripManage { | |||
private final IGovBusinessStripService iGovBusinessStripService; | |||
public List<GovBusinessStripTreeVO> getChildOrganizationList(String parentCode) { | |||
if (Objects.isNull(parentCode)) { | |||
parentCode = "-1"; | |||
} | |||
List<GovBusinessStrip> govBusinessStripList = iGovBusinessStripService.list(Wrappers.lambdaQuery(GovBusinessStrip.class) | |||
.eq(GovBusinessStrip::getParentCode, parentCode)); | |||
return govBusinessStripList.stream().map(r -> { | |||
GovBusinessStripTreeVO govBusinessStripTreeVO = new GovBusinessStripTreeVO(); | |||
govBusinessStripTreeVO.setBusinessStripCode(r.getBusinessStripCode()); | |||
govBusinessStripTreeVO.setBusinessStripName(r.getBusinessStripName()); | |||
govBusinessStripTreeVO.setParentCode(r.getParentCode()); | |||
govBusinessStripTreeVO.setParentName(r.getParentName()); | |||
return govBusinessStripTreeVO; | |||
}).collect(Collectors.toList()); | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
package com.ningdatech.pmapi.organization.model.vo; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.Data; | |||
/** | |||
* @author Liuxinxin | |||
* @since 2023-03-08 | |||
*/ | |||
@Data | |||
@ApiModel(value = "条线树形 responseVO", description = "") | |||
public class GovBusinessStripTreeVO { | |||
private Long id; | |||
@ApiModelProperty("条线code") | |||
private String businessStripCode; | |||
@ApiModelProperty("条线名称") | |||
private String businessStripName; | |||
@ApiModelProperty("父级条线code") | |||
private String parentCode; | |||
@ApiModelProperty("父级条线名称") | |||
private String parentName; | |||
} |
@@ -0,0 +1,113 @@ | |||
package com.ningdatech.pmapi.projectdeclared.converter; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.projectlib.model.entity.ProjectApplication; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialApplicationDTO; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import org.assertj.core.util.Lists; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @Classname ApplicationConverter | |||
* @Description | |||
* @Date 2023/3/13 17:38 | |||
* @Author PoffyZhang | |||
*/ | |||
public class ApplicationConverter { | |||
public static ProvincialProjectDTO convertProject(Project projectInfo,List<ProjectApplication> applications) { | |||
return ProvincialProjectDTO.builder() | |||
.regionCode(projectInfo.getAreaCode()) | |||
.regionName(projectInfo.getArea()) | |||
.projectName(projectInfo.getProjectName()) | |||
.projectId(String.valueOf(projectInfo.getId())) | |||
.projectType(projectInfo.getProjectType()) | |||
.totalMoney(projectInfo.getDeclareAmount()) | |||
.yearBudget(projectInfo.getAnnualPlanAmount()) | |||
.budgetFrom(projectInfo.getDeclareHaveAmount() + "," + | |||
projectInfo.getDeclareGovOwnFinanceAmount() + "," | |||
+ projectInfo.getDeclareGovSuperiorFinanceAmount()) | |||
.year(String.valueOf(projectInfo.getProjectYear())) | |||
.financialCode(projectInfo.getFinancialCode()) | |||
.developCode(projectInfo.getDevelopCode()) | |||
.beginTime(projectInfo.getBeginTime()) | |||
.endTime(projectInfo.getEndTime()) | |||
.buildBasis("立项依据") | |||
.buildBasisFile(projectInfo.getBuildBasis()) | |||
.projectSummary(projectInfo.getProjectIntroduction()) | |||
.responsibleMan(projectInfo.getResponsibleMan()) | |||
.responsibleManPhone(projectInfo.getResponsibleManMobile()) | |||
.contactName(projectInfo.getContactName()) | |||
.contactPhone(projectInfo.getContactPhone()) | |||
.buildUnit(projectInfo.getBuildOrgName()) | |||
.buildUnitCode(projectInfo.getBuildOrgCode()) | |||
.superUnit(projectInfo.getSuperOrg()) | |||
.superUnitCode(projectInfo.getSuperOrgCode()) | |||
.projectApplyFile(projectInfo.getProjectPdf()) | |||
.projectEstimateFile(projectInfo.getCalculationTotalInvestmentFile()) | |||
.unitThreePlan(projectInfo.getMainResponsibilitiesApplicantFile()) | |||
.otherFile(projectInfo.getPreliminaryPlanFile()) | |||
.projectRemark(projectInfo.getProjectRemarks()) | |||
.includeApplication(projectInfo.getIncludeApplication()) | |||
.applicationInfo(convertApplications(applications)) | |||
.build(); | |||
} | |||
//放入项目 app | |||
private static List<ProvincialApplicationDTO> convertApplications(List<ProjectApplication> applications) { | |||
if(CollUtil.isEmpty(applications)){ | |||
Collections.emptyList(); | |||
} | |||
return applications.stream().map(ApplicationConverter::convertApp).collect(Collectors.toList()); | |||
} | |||
private static ProvincialApplicationDTO convertApp(ProjectApplication projectApplication) { | |||
return ProvincialApplicationDTO.builder() | |||
.clouds(convertCloud(projectApplication)) | |||
.isFirst(projectApplication.getIsFirst()) | |||
.applicationName(projectApplication.getApplicationName()) | |||
.applicationCode(projectApplication.getRelatedExistsApplicationCode()) | |||
.relatedExistsApplication(projectApplication.getRelatedExistsApplication()) | |||
.applicationType(2) | |||
.buildLevel(projectApplication.getBuildLevel()) | |||
.isUniteBuild(projectApplication.getIsUniteBuild()) | |||
.unionBuildKind(projectApplication.getUnionBuildKind()) | |||
.applicationSummary(projectApplication.getApplicationSummary()) | |||
.applicationRemark(projectApplication.getApplicationRemark()) | |||
.applicationEstimateFile(projectApplication.getApplicationEstimateFile()) | |||
.isFiveDomain(projectApplication.getIsDigitalModification()) | |||
.fiveDomain(projectApplication.getDigitalModification()) | |||
.bizDomain(projectApplication.getBizDomain()) | |||
.isBizCooperate(projectApplication.getIsBizCooperate()) | |||
.userRange(projectApplication.getUsesRangeRemark()) | |||
.useGovCloud(projectApplication.getUseGovCloud()) | |||
.nationalITSpec(projectApplication.getNationalItSpec()) | |||
.netEnv(String.valueOf(projectApplication.getNetEnv())) | |||
.secrecyGrade(projectApplication.getSecrecyGrade()) | |||
.passwordGrade(projectApplication.getPasswordGrade()) | |||
.accountAppName(projectApplication.getAccountAppName()) | |||
.brainAccountAppName(projectApplication.getDomainBrainAccount()) | |||
.useCommonData(projectApplication.getUseCommonData()) | |||
.dataName(projectApplication.getDataName()) | |||
.commonComponents(projectApplication.getCommonComponents()) | |||
.useCommonComponent(projectApplication.getUseCommonComponent()) | |||
.isProduceCommonComponent(projectApplication.getProduceCommonComponent()) | |||
.produceCommonComponent(projectApplication.getProduceCommonComponents()) | |||
.publishSide(projectApplication.getPublishSide()) | |||
.build(); | |||
} | |||
private static List<ProvincialApplicationDTO.Cloud> convertCloud(ProjectApplication projectApplication) { | |||
return Lists.newArrayList(ProvincialApplicationDTO.Cloud.builder() | |||
.cloudType(projectApplication.getCloudsType()) | |||
.cloudNums(projectApplication.getCloudsNumber()) | |||
.cloudBasicSpec(projectApplication.getCloudsFoundationSpecifications()) | |||
.cloudUseDescription(projectApplication.getCloudsDescription()) | |||
.build()); | |||
} | |||
} |
@@ -102,7 +102,7 @@ public class ConstructionPlanManage { | |||
VUtils.isTrue(Objects.isNull(projectDto.getId())).throwMessage("提交失败 缺少项目ID!"); | |||
Project projectInfo = projectService.getById(projectDto.getId()); | |||
VUtils.isTrue(Objects.isNull(projectInfo)).throwMessage("提交失败 此项目不存在!"); | |||
VUtils.isTrue(StringUtils.isBlank(projectInfo.getConstructionPlanFile())).throwMessage("提交失败 请提交建设方案!"); | |||
VUtils.isTrue(StringUtils.isBlank(projectDto.getConstructionPlanFile())).throwMessage("提交失败 请提交建设方案!"); | |||
String regionCode = projectInfo.getAreaCode(); | |||
@@ -64,6 +64,7 @@ import javax.servlet.http.HttpServletResponse; | |||
import java.io.IOException; | |||
import java.time.LocalDateTime; | |||
import java.util.*; | |||
import java.util.concurrent.atomic.AtomicInteger; | |||
import java.util.stream.Collectors; | |||
/** | |||
@@ -375,19 +376,15 @@ public class DeclaredProjectManage { | |||
} | |||
public void exportList(HttpServletResponse response, ProjectListReq param) { | |||
Long userId = LoginUserUtil.getUserId(); | |||
UserInfoDetails userInfoDetails = LoginUserUtil.loginUserDetail(); | |||
Long userId = userInfoDetails.getUserId(); | |||
VUtils.isTrue(Objects.isNull(userId)).throwMessage("获取登录用户失败!"); | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
//放入用户的单位 | |||
param.setBuildOrgCode(userFullInfo.getOrganizationCode()); | |||
param.setPageNumber(CommonConst.EXPORT_PAGE_NUMBER); | |||
param.setPageSize(CommonConst.EXPORT_PAGE_SIZE); | |||
param.setBuildOrgCode(userInfoDetails.getOrganizationCode()); | |||
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(param); | |||
Page<Project> page = projectService.page(param.page(), query); | |||
List<Project> records = page.getRecords(); | |||
List<Project> records = projectService.list(query); | |||
AtomicInteger serialNumber = new AtomicInteger(0); | |||
List<DeclaredProjectExportDTO> collect = records.stream().map(r -> { | |||
DeclaredProjectExportDTO exportDTO = new DeclaredProjectExportDTO(); | |||
BeanUtils.copyProperties(r, exportDTO); | |||
@@ -395,11 +392,9 @@ public class DeclaredProjectManage { | |||
exportDTO.setStatusName(ProjectStatusEnum.getDesc(r.getStatus())); | |||
String createOnStr = NdDateUtils.format(r.getCreateOn(), "yyyy-MM-dd HH:mm"); | |||
exportDTO.setCreateOn(createOnStr); | |||
exportDTO.setSerialNumber(serialNumber.incrementAndGet()); | |||
return exportDTO; | |||
}).collect(Collectors.toList()); | |||
for (int i = 0; i < collect.size(); i++) { | |||
collect.get(i).setSerialNumber(i + 1); | |||
} | |||
String fileName = "项目申报列表"; | |||
ExcelDownUtil.setFileName(fileName,response); | |||
//数据导出处理函数 | |||
@@ -43,6 +43,7 @@ import java.time.LocalDateTime; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.concurrent.atomic.AtomicInteger; | |||
import java.util.function.Function; | |||
import java.util.stream.Collectors; | |||
@@ -163,13 +164,9 @@ public class ProjectAdjustmentManage { | |||
req.setBuildOrgCode(userFullInfo.getOrganizationCode()); | |||
LambdaQueryWrapper<Project> query = ProjectHelper.projectQuery(req); | |||
Page<Project> page = projectService.page(req.page(), query); | |||
req.setPageNumber(CommonConst.EXPORT_PAGE_NUMBER); | |||
req.setPageSize(CommonConst.EXPORT_PAGE_SIZE); | |||
List<Project> records = page.getRecords(); | |||
List<Project> records = projectService.list(query); | |||
AtomicInteger serialNumber = new AtomicInteger(0); | |||
List<ProjectAdjustmentExportDTO> collect = records.stream().map(r -> { | |||
ProjectAdjustmentExportDTO exportDTO = new ProjectAdjustmentExportDTO(); | |||
BeanUtils.copyProperties(r, exportDTO); | |||
@@ -177,11 +174,9 @@ public class ProjectAdjustmentManage { | |||
exportDTO.setStatusName(ProjectStatusEnum.getDesc(r.getStatus())); | |||
String createOnStr = NdDateUtils.format(r.getCreateOn(), "yyyy-MM-dd HH:mm"); | |||
exportDTO.setCreateOn(createOnStr); | |||
exportDTO.setSerialNumber(serialNumber.incrementAndGet()); | |||
return exportDTO; | |||
}).collect(Collectors.toList()); | |||
for (int i = 0; i < collect.size(); i++) { | |||
collect.get(i).setSerialNumber(i + 1); | |||
} | |||
String fileName = "项目内容调整列表"; | |||
ExcelDownUtil.setFileName(fileName,response); | |||
//数据导出处理函数 | |||
@@ -1,18 +1,30 @@ | |||
package com.ningdatech.pmapi.projectdeclared.manage; | |||
import cn.hutool.core.collection.CollUtil; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.ningdatech.basic.function.VUtils; | |||
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils; | |||
import com.ningdatech.pmapi.projectdeclared.converter.ApplicationConverter; | |||
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.model.entity.ProjectApplication; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectApplicationService; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectService; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialApplicationDTO; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
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.Collections; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import java.util.stream.Collectors; | |||
/** | |||
* @Classname ReviewByProvincialDeptManage | |||
@@ -31,6 +43,10 @@ public class ReviewByProvincialDeptManage { | |||
private final DefaultDeclaredProjectManage defaultProjectManage; | |||
private final IJoinReviewProvincialBureauService joinReviewProvincialBureauService; | |||
private final IProjectApplicationService applicationService; | |||
/** | |||
* 省级部门联审 | |||
* @param project | |||
@@ -47,17 +63,21 @@ public class ReviewByProvincialDeptManage { | |||
VUtils.isTrue(!ProjectStatusEnum.JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS.getCode().equals(projectInfo.getStatus()) || | |||
!ProjectStatusEnum.NOT_APPROVED.getCode().equals(projectInfo.getStage())) | |||
.throwMessage("提交失败 该项目不是 省级部门联审状态状态或者未立项阶段"); | |||
// TODO 对接省级联审的接口 | |||
Boolean sucessProvince = Boolean.TRUE; | |||
if(sucessProvince){ | |||
//测试先成功 | |||
stateMachineUtils.pass(project); | |||
projectService.updateById(project); | |||
//直接去预审 | |||
if(StringUtils.isNotBlank(defaultProjectManage | |||
.directStartProcess(project,project.getPreStartUserId()))){ | |||
return Boolean.TRUE; | |||
} | |||
// 对接省级联审的接口 | |||
List<ProjectApplication> applications = applicationService.list(Wrappers.lambdaQuery(ProjectApplication.class) | |||
.eq(ProjectApplication::getProjectId, projectInfo.getId())); | |||
if(joinReviewProvincialBureauService.pushImportProject( | |||
ApplicationConverter.convertProject(projectInfo,applications))){ | |||
return Boolean.TRUE; | |||
// //测试先成功 | |||
// stateMachineUtils.pass(project); | |||
// projectService.updateById(project); | |||
// //直接去预审 | |||
// if(StringUtils.isNotBlank(defaultProjectManage | |||
// .directStartProcess(project,project.getPreStartUserId()))){ | |||
// return Boolean.TRUE; | |||
// } | |||
} | |||
return Boolean.FALSE; | |||
@@ -309,4 +309,7 @@ public class Project implements Serializable { | |||
@TableField(fill = FieldFill.INSERT_UPDATE) | |||
private Long updateBy; | |||
@ApiModelProperty("项目预审申请单文件ID") | |||
private Long pretrialFileId; | |||
} |
@@ -67,7 +67,7 @@ public class ProjectApplication implements Serializable { | |||
@ApiModelProperty("是否数改系统 0:否 1:是") | |||
private Integer isDigitalModification; | |||
@ApiModelProperty("数改系统") | |||
@ApiModelProperty("数改系统 1: '党政机关整体智治',2: '数字政府',3: '数字经济',4: '数字社会',7: '数字文化',5: '数字法治',6: '一体化智能化公共数据平台', 8: '基层智治' 多个用英文,分隔") | |||
private String digitalModification; | |||
@ApiModelProperty("业务领域") | |||
@@ -1,5 +1,7 @@ | |||
package com.ningdatech.pmapi.provincial.controller; | |||
import com.ningdatech.pmapi.projectdeclared.manage.ReviewByProvincialDeptManage; | |||
import com.ningdatech.pmapi.projectlib.model.entity.Project; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
import io.swagger.annotations.Api; | |||
@@ -24,14 +26,19 @@ public class TestController { | |||
@Autowired | |||
private IJoinReviewProvincialBureauService joinReviewProvincialBureauService; | |||
@PostMapping("/push") | |||
@Autowired | |||
private ReviewByProvincialDeptManage provincialDeptManage; | |||
@GetMapping("/push") | |||
@ApiOperation("测试推送") | |||
private String push(@Valid @RequestBody ProvincialProjectDTO project){ | |||
return joinReviewProvincialBureauService.pushImportProject(project); | |||
private Boolean push(@Valid @RequestParam Long projectId){ | |||
Project project = new Project(); | |||
project.setId(projectId); | |||
return provincialDeptManage.startTheProcess(project); | |||
} | |||
@GetMapping("/detail") | |||
@ApiOperation("测试推送") | |||
@ApiOperation("测试获取详情") | |||
private String detail(@RequestParam String projectId){ | |||
return joinReviewProvincialBureauService.processInfo(projectId); | |||
} | |||
@@ -1,11 +1,13 @@ | |||
package com.ningdatech.pmapi.provincial.model.dto; | |||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; | |||
import io.swagger.annotations.ApiModel; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
import java.util.List; | |||
/** | |||
@@ -17,7 +19,9 @@ import java.util.List; | |||
@Data | |||
@Builder | |||
@ApiModel(value = "ProvincialApplicationDTO", description = "") | |||
public class ProvincialApplicationDTO { | |||
public class ProvincialApplicationDTO implements Serializable { | |||
//云 信息 | |||
private List<Cloud> clouds; | |||
//是否初次建设 1是 2不是 | |||
@@ -85,7 +89,9 @@ public class ProvincialApplicationDTO { | |||
//发布端 '浙里办','浙政钉','数字化改革门户','支付宝','微信','网页','PC客户端','APP端' | |||
private String publishSide; | |||
public static class Cloud { | |||
@Builder | |||
@JsonIgnoreProperties(value = { "handler"}) | |||
public static class Cloud implements Serializable { | |||
//云资源台数 11 | |||
private Integer cloudNums; | |||
//云资源类型 云服务器(ECS) | |||
@@ -7,6 +7,7 @@ import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
import java.io.Serializable; | |||
import java.math.BigDecimal; | |||
import java.util.List; | |||
@@ -21,7 +22,7 @@ import java.util.List; | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@ApiModel(value = "ProvincialProjectDTO", description = "") | |||
public class ProvincialProjectDTO { | |||
public class ProvincialProjectDTO implements Serializable { | |||
@ApiModelProperty("区域code") | |||
private String regionCode; | |||
@@ -114,10 +115,10 @@ public class ProvincialProjectDTO { | |||
private String projectRemark; | |||
@ApiModelProperty("是否有效 1有效 2无效 3撤回") | |||
private String isEffective; | |||
private Integer isEffective; | |||
@ApiModelProperty("是否包含应用 1包含") | |||
private String includeApplication; | |||
private Integer includeApplication; | |||
@ApiModelProperty("app信息") | |||
private List<ProvincialApplicationDTO> applicationInfo; | |||
@@ -14,7 +14,7 @@ public interface IJoinReviewProvincialBureauService { | |||
* 推送/保存 重大接口到 省局联审 | |||
* @return | |||
*/ | |||
String pushImportProject(ProvincialProjectDTO project); | |||
Boolean pushImportProject(ProvincialProjectDTO project); | |||
/** | |||
@@ -2,6 +2,8 @@ package com.ningdatech.pmapi.provincial.service.impl; | |||
import cn.hutool.core.util.StrUtil; | |||
import cn.hutool.crypto.SecureUtil; | |||
import com.alibaba.fastjson.JSON; | |||
import com.ningdatech.basic.model.ApiResponse; | |||
import com.ningdatech.pmapi.common.config.ProvincialProperties; | |||
import com.ningdatech.pmapi.provincial.model.dto.ProvincialProjectDTO; | |||
import com.ningdatech.pmapi.provincial.service.IJoinReviewProvincialBureauService; | |||
@@ -35,12 +37,12 @@ public class JoinReviewProvincialBureauServiceImpl implements IJoinReviewProvinc | |||
* @return | |||
*/ | |||
@Override | |||
public String pushImportProject(ProvincialProjectDTO project){ | |||
public Boolean pushImportProject(ProvincialProjectDTO project){ | |||
Long timeStamp = System.currentTimeMillis()/1000; | |||
String url = provincialProperties.getHost() + provincialProperties.getPushUrl() | |||
+ "?timestamp=" + timeStamp; | |||
log.info("省局推送联审url {}",url); | |||
ResponseEntity<String> responseEntity = null; | |||
ResponseEntity<ApiResponse> responseEntity = null; | |||
String signature = getSha256(timeStamp,provincialProperties.getPushUrl(), | |||
HttpMethod.POST.name()); | |||
@@ -55,14 +57,19 @@ public class JoinReviewProvincialBureauServiceImpl implements IJoinReviewProvinc | |||
.accept(MediaType.APPLICATION_JSON) | |||
.body(project); | |||
log.info("省局联审 提交 :{}", requestEntity); | |||
log.info("省局联审 提交body :{}", JSON.toJSONString(requestEntity.getBody())); | |||
try { | |||
responseEntity = restTemplate.exchange(requestEntity,String.class); | |||
responseEntity = restTemplate.exchange(requestEntity, ApiResponse.class); | |||
log.info("省局联审 响应 :{}",responseEntity); | |||
if(responseEntity.getBody().getCode().equals(200)){ | |||
return Boolean.TRUE; | |||
} | |||
} catch (Exception e) { | |||
log.error("[省局联审] http request error", e); | |||
} | |||
return responseEntity.getBody(); | |||
return Boolean.FALSE; | |||
} | |||
/** | |||
@@ -35,7 +35,7 @@ public class VerificationCodeController { | |||
@ApiOperation(value = "发送验证码", notes = "发送验证码") | |||
@PostMapping(value = "/send") | |||
public void send(@Validated @RequestBody ReqVerificationCodePO request) { | |||
// smsManage.sendVerificationCode(request); | |||
smsManage.sendVerificationCode(request); | |||
} | |||
} |
@@ -11,6 +11,9 @@ import com.ningdatech.pmapi.sms.model.dto.VerifyCodeCacheDTO; | |||
import com.ningdatech.pmapi.sms.model.po.ReqVerificationCodePO; | |||
import com.ningdatech.pmapi.sms.utils.DateUtil; | |||
import com.ningdatech.pmapi.sms.utils.SmsRedisKeyUtils; | |||
import com.ningdatech.yxt.client.YxtClient; | |||
import com.ningdatech.yxt.constants.YxtSmsSignEnum; | |||
import com.ningdatech.yxt.model.cmd.SendSmsCmd; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.lang3.StringUtils; | |||
@@ -29,65 +32,65 @@ import java.util.Collections; | |||
@Component | |||
@RequiredArgsConstructor | |||
public class SmsManage { | |||
// | |||
// private final YxtClient yxtClient; | |||
// private final CachePlusOps cachePlusOps; | |||
// | |||
// public void sendVerificationCode(ReqVerificationCodePO request) { | |||
// Assert.isTrue(PhoneUtil.isMobile(request.getMobile()), "手机号码格式不正确"); | |||
// String verificationType = request.getVerificationType(); | |||
// VerificationCodeType verificationCodeTypeEnum = VerificationCodeType.of(verificationType); | |||
// | |||
// // 验证是否被锁定 | |||
// String lockKey = SmsRedisKeyUtils.smsSendLockKey(verificationCodeTypeEnum, request.getMobile()); | |||
// if (StringUtils.isNotBlank(cachePlusOps.get(lockKey))) { | |||
// throw BizException.wrap("今日" + verificationCodeTypeEnum.getDesc() + "的验证码发送次数过多,已被锁定"); | |||
// } | |||
// // 验证发送间隔 | |||
// String cacheKey = SmsRedisKeyUtils.smsCodeVerifyKey(verificationCodeTypeEnum, request.getMobile()); | |||
// VerifyCodeCacheDTO preCache = (VerifyCodeCacheDTO) cachePlusOps.get(cacheKey); | |||
// if (preCache != null) { | |||
// if (LocalDateTime.now().minusMinutes(verificationCodeTypeEnum.getSendInterval()) | |||
// .isBefore(preCache.getSendTime())) { | |||
// throw BizException.wrap(verificationCodeTypeEnum.getSendInterval() + "分钟之内已发送过验证码,请稍后重试"); | |||
// } | |||
// } | |||
// String code = RandomUtil.randomNumbers(6); | |||
// VerifyCodeCacheDTO cache = VerifyCodeCacheDTO.builder() | |||
// .code(code) | |||
// .sendTime(LocalDateTime.now()) | |||
// .mobile(request.getMobile()) | |||
// .build(); | |||
// | |||
// // 创建短信内容 | |||
// SendSmsCmd sendSmsCmd = new SendSmsCmd(); | |||
// switch (verificationCodeTypeEnum) { | |||
// case LOGIN: | |||
// SendSmsCmd.SendSmsContext sendSmsContext = new SendSmsCmd.SendSmsContext(); | |||
// sendSmsContext.setReceiveNumber(request.getMobile()); | |||
// sendSmsContext.setContent(String.format(YxtSmsTemplateConst.SMS_LOGIN_TEMPLATE, code, verificationCodeTypeEnum.getExpireTime())); | |||
// sendSmsCmd.setContextList(Collections.singletonList(sendSmsContext)); | |||
// sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB); | |||
// break; | |||
// default: | |||
// throw new IllegalArgumentException("非法的短信发送类型"); | |||
// } | |||
// // 发送 短信 | |||
// yxtClient.submitSmsTask(sendSmsCmd); | |||
// log.info("send verificationCode mobile = {},code = {}", request.getMobile(), code); | |||
// | |||
// cachePlusOps.set(new CacheKey(cacheKey, Duration.ofMinutes(verificationCodeTypeEnum.getExpireTime())), cache); | |||
// String limitKey = SmsRedisKeyUtils.smsSendLimitKey(verificationCodeTypeEnum, request.getMobile()); | |||
// if (StringUtils.isNotBlank(cachePlusOps.get(limitKey))) { | |||
// long limitCount = cachePlusOps.incr(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon()))); | |||
// // 超出单日发送次数之后直接锁定 | |||
// if (limitCount >= verificationCodeTypeEnum.getSendTimesByDay().longValue()) { | |||
// cachePlusOps.set(new CacheKey(lockKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), request.getMobile()); | |||
// } | |||
// } else { | |||
// cachePlusOps.set(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), 1); | |||
// } | |||
// } | |||
private final YxtClient yxtClient; | |||
private final CachePlusOps cachePlusOps; | |||
public void sendVerificationCode(ReqVerificationCodePO request) { | |||
Assert.isTrue(PhoneUtil.isMobile(request.getMobile()), "手机号码格式不正确"); | |||
String verificationType = request.getVerificationType(); | |||
VerificationCodeType verificationCodeTypeEnum = VerificationCodeType.of(verificationType); | |||
// 验证是否被锁定 | |||
String lockKey = SmsRedisKeyUtils.smsSendLockKey(verificationCodeTypeEnum, request.getMobile()); | |||
if (StringUtils.isNotBlank(cachePlusOps.get(lockKey))) { | |||
throw BizException.wrap("今日" + verificationCodeTypeEnum.getDesc() + "的验证码发送次数过多,已被锁定"); | |||
} | |||
// 验证发送间隔 | |||
String cacheKey = SmsRedisKeyUtils.smsCodeVerifyKey(verificationCodeTypeEnum, request.getMobile()); | |||
VerifyCodeCacheDTO preCache = (VerifyCodeCacheDTO) cachePlusOps.get(cacheKey); | |||
if (preCache != null) { | |||
if (LocalDateTime.now().minusMinutes(verificationCodeTypeEnum.getSendInterval()) | |||
.isBefore(preCache.getSendTime())) { | |||
throw BizException.wrap(verificationCodeTypeEnum.getSendInterval() + "分钟之内已发送过验证码,请稍后重试"); | |||
} | |||
} | |||
String code = RandomUtil.randomNumbers(6); | |||
VerifyCodeCacheDTO cache = VerifyCodeCacheDTO.builder() | |||
.code(code) | |||
.sendTime(LocalDateTime.now()) | |||
.mobile(request.getMobile()) | |||
.build(); | |||
// 创建短信内容 | |||
SendSmsCmd sendSmsCmd = new SendSmsCmd(); | |||
switch (verificationCodeTypeEnum) { | |||
case LOGIN: | |||
SendSmsCmd.SendSmsContext sendSmsContext = new SendSmsCmd.SendSmsContext(); | |||
sendSmsContext.setReceiveNumber(request.getMobile()); | |||
sendSmsContext.setContent(String.format(YxtSmsTemplateConst.SMS_LOGIN_TEMPLATE, code, verificationCodeTypeEnum.getExpireTime())); | |||
sendSmsCmd.setContextList(Collections.singletonList(sendSmsContext)); | |||
sendSmsCmd.setSmsSignEnum(YxtSmsSignEnum.ZJS_ELECTRONIC_EXPERT_LIB); | |||
break; | |||
default: | |||
throw new IllegalArgumentException("非法的短信发送类型"); | |||
} | |||
// 发送 短信 | |||
yxtClient.submitSmsTask(sendSmsCmd); | |||
log.info("send verificationCode mobile = {},code = {}", request.getMobile(), code); | |||
cachePlusOps.set(new CacheKey(cacheKey, Duration.ofMinutes(verificationCodeTypeEnum.getExpireTime())), cache); | |||
String limitKey = SmsRedisKeyUtils.smsSendLimitKey(verificationCodeTypeEnum, request.getMobile()); | |||
if (StringUtils.isNotBlank(cachePlusOps.get(limitKey))) { | |||
long limitCount = cachePlusOps.incr(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon()))); | |||
// 超出单日发送次数之后直接锁定 | |||
if (limitCount >= verificationCodeTypeEnum.getSendTimesByDay().longValue()) { | |||
cachePlusOps.set(new CacheKey(lockKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), request.getMobile()); | |||
} | |||
} else { | |||
cachePlusOps.set(new CacheKey(limitKey, Duration.ofSeconds(DateUtil.restSecondsFromNowToNoon())), 1); | |||
} | |||
} | |||
} |
@@ -1,8 +1,8 @@ | |||
package com.ningdatech.pmapi.sys.service; | |||
import com.baomidou.mybatisplus.extension.service.IService; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import com.ningdatech.pmapi.sys.model.dto.RegionDTO; | |||
import com.ningdatech.pmapi.sys.model.entity.Region; | |||
import java.util.List; | |||
@@ -52,9 +52,9 @@ public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> impleme | |||
@Override | |||
public Long getRegionIdByParentIdWithSameRegionCode(Long parentId, String regionCode) { | |||
return baseMapper.selectOne(Wrappers.lambdaQuery(Region.class) | |||
.eq(Region::getParentId, parentId) | |||
.eq(Region::getRegionCode, regionCode) | |||
.eq(Region::getDeleted, false)) | |||
.eq(Region::getParentId, parentId) | |||
.eq(Region::getRegionCode, regionCode) | |||
.eq(Region::getDeleted, false)) | |||
.getId(); | |||
} | |||
@@ -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; | |||
} |
@@ -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; | |||
} | |||
} | |||
@@ -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; | |||
} | |||
} |
@@ -1,7 +1,7 @@ | |||
package com.ningdatech.pmapi.user.service; | |||
import com.ningdatech.pmapi.user.entity.UserInfo; | |||
import com.baomidou.mybatisplus.extension.service.IService; | |||
import com.ningdatech.pmapi.user.entity.UserInfo; | |||
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto; | |||
import java.util.Map; | |||
@@ -9,7 +9,7 @@ import java.util.Set; | |||
/** | |||
* <p> | |||
* 服务类 | |||
* 服务类 | |||
* </p> | |||
* | |||
* @author Lierbao | |||
@@ -19,4 +19,7 @@ public interface IUserInfoService extends IService<UserInfo> { | |||
Map<String, ProcessInstanceUserDto> getUserMapByIds(Set<String> staterUsers); | |||
ProcessInstanceUserDto getUserInfo(String userId); | |||
UserInfo getUserInfoByPhoneNo(String phoneNo); | |||
} |
@@ -12,6 +12,7 @@ import com.ningdatech.pmapi.user.mapper.NdUserInfoMapper; | |||
import com.ningdatech.pmapi.user.service.IUserInfoService; | |||
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto; | |||
import lombok.RequiredArgsConstructor; | |||
import org.apache.commons.lang3.StringUtils; | |||
import org.springframework.stereotype.Service; | |||
import java.util.List; | |||
@@ -22,7 +23,7 @@ import java.util.stream.Collectors; | |||
/** | |||
* <p> | |||
* 服务实现类 | |||
* 服务实现类 | |||
* </p> | |||
* | |||
* @author Lierbao | |||
@@ -36,6 +37,7 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||
private final IDingEmployeeInfoService dingEmployeeInfoService; | |||
private final IDingOrganizationService dingOrganizationService; | |||
@Override | |||
public Map<String, ProcessInstanceUserDto> getUserMapByIds(Set<String> staterUsers) { | |||
List<UserInfo> userInfos = userInfoMapper.selectBatchIds(staterUsers); | |||
@@ -44,13 +46,13 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||
userInfo.setUserId(String.valueOf(u.getId())); | |||
userInfo.setUserName(u.getRealName()); | |||
Long accountId = u.getAccountId(); | |||
if (Objects.isNull(accountId)){ | |||
if (Objects.isNull(accountId)) { | |||
throw new BizException("该用户没有录入浙政钉用户信息!"); | |||
} | |||
// 根据浙政钉用户ID获取单位code | |||
DingEmployeeInfo employeeInfo = dingEmployeeInfoService.getOne(Wrappers.lambdaQuery(DingEmployeeInfo.class) | |||
.eq(DingEmployeeInfo::getAccountId, accountId) | |||
.eq(DingEmployeeInfo::getMainJob,String.valueOf(Boolean.TRUE)) | |||
.eq(DingEmployeeInfo::getMainJob, String.valueOf(Boolean.TRUE)) | |||
.last("limit 1")); | |||
String organizationCode = employeeInfo.getOrganizationCode(); | |||
// 根据 单位code获取单位名称 | |||
@@ -70,7 +72,7 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||
processInstanceUserDto.setUserId(String.valueOf(userInfo.getId())); | |||
processInstanceUserDto.setUserName(userInfo.getRealName()); | |||
Long accountId = userInfo.getAccountId(); | |||
if (Objects.isNull(accountId)){ | |||
if (Objects.isNull(accountId)) { | |||
throw new BizException("该用户没有录入浙政钉用户信息!"); | |||
} | |||
// 根据浙政钉用户ID获取部门code | |||
@@ -85,4 +87,15 @@ public class UserInfoServiceImpl extends ServiceImpl<NdUserInfoMapper, UserInfo> | |||
processInstanceUserDto.setOrgName(organizationName); | |||
return processInstanceUserDto; | |||
} | |||
@Override | |||
public UserInfo getUserInfoByPhoneNo(String phoneNo) { | |||
if (StringUtils.isEmpty(phoneNo)) { | |||
return null; | |||
} | |||
UserInfo userInfo = userInfoMapper | |||
.selectOne(Wrappers.lambdaQuery(UserInfo.class) | |||
.eq(UserInfo::getMobile, phoneNo)); | |||
return userInfo; | |||
} | |||
} |
@@ -21,6 +21,7 @@ security: | |||
- /oa/** | |||
- /wflow/** | |||
- /sys/** | |||
- /api/v1/verification/** | |||
ignore-csrf-urls: | |||
- /api/v1/user/auth/** | |||
- /v2/api-docs | |||
@@ -37,6 +38,7 @@ security: | |||
- /oa/** | |||
- /wflow/** | |||
- /sys/** | |||
- /api/v1/verification/** | |||
role-map: | |||
"engineer": | |||
"project_manager": | |||
@@ -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> |
@@ -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> |
@@ -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(); | |||
} | |||
} | |||
} |
@@ -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> | |||