@@ -252,6 +252,12 @@ | |||
<groupId>org.xhtmlrenderer</groupId> | |||
<artifactId>flying-saucer-pdf-itext5</artifactId> | |||
</dependency> | |||
<!--将html转换成pdf--> | |||
<dependency> | |||
<groupId>com.itextpdf</groupId> | |||
<artifactId>html2pdf</artifactId> | |||
</dependency> | |||
</dependencies> | |||
<!-- 打包 --> | |||
@@ -1,7 +1,8 @@ | |||
package com.ningdatech.pmapi.irs.sign; | |||
import com.alibaba.fastjson.JSON; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.ningdatech.pmapi.irs.config.IrsSealPlatformProperties; | |||
import com.ningdatech.pmapi.todocenter.model.dto.SignReqDTO; | |||
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; | |||
import org.apache.commons.lang3.tuple.Pair; | |||
import org.apache.http.HttpEntity; | |||
@@ -28,26 +29,10 @@ import java.text.SimpleDateFormat; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
public class IRSAPIRequest { | |||
//天印服务器接口信息 | |||
// private static String ProjectID = "XXX"; | |||
// private static String ProjectSecret = "XXXX"; | |||
// private static String accessKey = "XXXX"; | |||
// private static String secretKey = "XXXX"; | |||
// private static String apiUrl = "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220309000004/seal-platform/seal/v1/rest/sign/signPdf"; | |||
private static String ProjectID = "XXX"; | |||
private static String ProjectSecret = "XXXX"; | |||
private static String accessKey = "XXXX"; | |||
private static String secretKey = "XXXX"; | |||
private static String apiUrl = "https://ibcdsg.zj.gov.cn:8443/restapi/prod/IC33000020220309000004/seal-platform/seal/v1/rest/sign/signPdf"; | |||
public static void main(String[] args) throws Exception { | |||
createSignPdf(); | |||
} | |||
/** | |||
@@ -56,33 +41,36 @@ public class IRSAPIRequest { | |||
* | |||
* @return | |||
*/ | |||
public static JSONObject createSignPdf() { | |||
public static byte[] createSignPdf(SignReqDTO req) { | |||
String pdfEncode64 = req.getPdfEncode64(); | |||
Float posX = req.getPosX(); | |||
Float posY = req.getPosY(); | |||
String sealSn = req.getSealSn(); | |||
String fileName = req.getFileName(); | |||
JSONObject obj = null; | |||
String resp = null; | |||
try { | |||
JSONObject ReqData = new JSONObject(); | |||
String pathname = "D://001.pdf"; | |||
File file = new File(pathname); | |||
String fileByte1 = IRSAPIRequest.PDFToBase64(file); | |||
ReqData.put("fileBase64", fileByte1); | |||
ReqData.put("sealSn", "33012108041829053952"); | |||
ReqData.put("posX", "200"); | |||
ReqData.put("posY", "200"); | |||
ReqData.put("fileBase64", pdfEncode64); | |||
ReqData.put("sealSn", sealSn); | |||
ReqData.put("posX", posX); | |||
ReqData.put("posY", posY); | |||
ReqData.put("signType", "1"); | |||
// ReqData.put("key", "单位"); | |||
ReqData.put("posPage", "1"); | |||
ReqData.put("fileName", "01.pdf"); | |||
ReqData.put("fileName", fileName); | |||
resp = post(ReqData, "post"); | |||
JSONObject jsonObject = JSON.parseObject(resp); | |||
String data = jsonObject.getString("data"); | |||
JSONObject jsondata = JSON.parseObject(data); | |||
String signFileB64 = jsondata.getString("signFileB64"); | |||
IRSAPIRequest.base64StringToPdf(signFileB64, "D:\\test21.pdf"); | |||
//JSONObject jsonObject = JSON.parseObject(resp); | |||
//String data = jsonObject.getString("data"); | |||
//JSONObject jsondata = JSON.parseObject(data); | |||
//String signFileB64 = jsondata.getString("signFileB64"); | |||
//IRSAPIRequest.base64StringToPdf(signFileB64, "D:\\test21.pdf"); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
return obj; | |||
// return obj; | |||
return resp.getBytes(); | |||
} | |||
@@ -92,12 +80,12 @@ public class IRSAPIRequest { | |||
DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US); | |||
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); | |||
String date = dateFormat.format(new Date()); | |||
URL url = new URL(apiUrl); | |||
URL url = new URL(IrsSealPlatformProperties.apiUrl); | |||
URI uri = new URI(url.getProtocol(), url.getHost(), url.getPath(), url.getQuery(), null); | |||
String canonicalQueryString = getCanonicalQueryString(uri.getQuery()); | |||
String message = requestMethod.toUpperCase() + "\n" + uri.getPath() + "\n" + canonicalQueryString + "\n" + accessKey + "\n" + date + "\n"; | |||
String message = requestMethod.toUpperCase() + "\n" + uri.getPath() + "\n" + canonicalQueryString + "\n" + IrsSealPlatformProperties.accessKey + "\n" + date + "\n"; | |||
Mac hasher = Mac.getInstance("HmacSHA256"); | |||
hasher.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256")); | |||
hasher.init(new SecretKeySpec(IrsSealPlatformProperties.secretKey.getBytes(), "HmacSHA256")); | |||
byte[] hash = hasher.doFinal(message.getBytes()); | |||
DatatypeConverter.printHexBinary(hash); | |||
String sign = DatatypeConverter.printBase64Binary(hash); | |||
@@ -112,14 +100,14 @@ public class IRSAPIRequest { | |||
String signature = sign(stream); | |||
//System.out.println(signature); | |||
// 设置HTTP请求头 | |||
HttpEntityEnclosingRequestBase req = new HttpPost(apiUrl); | |||
HttpEntityEnclosingRequestBase req = new HttpPost(IrsSealPlatformProperties.apiUrl); | |||
// project-id为用户的projectId | |||
req.addHeader("appId", ProjectID); | |||
req.addHeader("appId", IrsSealPlatformProperties.projectId); | |||
// signature为之前生成的签名 | |||
req.addHeader("signature", signature); | |||
req.addHeader("X-BG-HMAC-SIGNATURE", sign); | |||
req.addHeader("X-BG-HMAC-ALGORITHM", "hmac-sha256"); | |||
req.addHeader("X-BG-HMAC-ACCESS-KEY", accessKey); | |||
req.addHeader("X-BG-HMAC-ACCESS-KEY", IrsSealPlatformProperties.accessKey); | |||
req.addHeader("X-BG-DATE-TIME", date); | |||
req.addHeader("Content-Type", "application/json"); | |||
@@ -151,7 +139,7 @@ public class IRSAPIRequest { | |||
Mac mac = Mac.getInstance("HmacSHA256"); | |||
// 获取安全密钥 | |||
Key secKey = new SecretKeySpec(ProjectSecret.getBytes("UTF-8"), mac.getAlgorithm()); | |||
Key secKey = new SecretKeySpec(IrsSealPlatformProperties.projectSecret.getBytes("UTF-8"), mac.getAlgorithm()); | |||
// 初始化 | |||
mac.init(secKey); | |||
@@ -169,7 +157,7 @@ public class IRSAPIRequest { | |||
Mac mac = Mac.getInstance("HmacSHA256"); | |||
// 获取安全密钥 | |||
Key secKey = new SecretKeySpec(secretKey.getBytes("UTF-8"), mac.getAlgorithm()); | |||
Key secKey = new SecretKeySpec(IrsSealPlatformProperties.secretKey.getBytes("UTF-8"), mac.getAlgorithm()); | |||
// 初始化 | |||
mac.init(secKey); | |||
@@ -275,7 +263,8 @@ public class IRSAPIRequest { | |||
BufferedOutputStream bos = null; | |||
try { | |||
byte[] bytes = decoder.decodeBuffer(base64Content);//base64编码内容转换为字节数组 | |||
// base64编码内容转换为字节数组 | |||
byte[] bytes = decoder.decodeBuffer(base64Content); | |||
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(bytes); | |||
bis = new BufferedInputStream(byteInputStream); | |||
File file = new File(filePath); | |||
@@ -86,16 +86,19 @@ public class DefaultDeclaredProjectManage { | |||
VUtils.isTrue(declareAmount.compareTo(totalAmount) != 0) | |||
.throwMessage(String.format("申报失败! 申报总金额【{}】 不等于其它申报金额 【{}】",declareAmount,totalAmount)); | |||
BigDecimal annualPlanAmount = projectInfo.getAnnualPlanAmount(); | |||
BigDecimal annualGovSuperAmount = projectInfo.getAnnualPlanGovSuperiorFinanceAmount(); | |||
BigDecimal annualOwnSuperAmount = projectInfo.getAnnualPlanGovOwnFinanceAmount(); | |||
BigDecimal annualBankLendingAmount = projectInfo.getAnnualPlanBankLendingAmount(); | |||
BigDecimal annualHaveAmount = projectInfo.getAnnualPlanHaveAmount(); | |||
BigDecimal anualOtherAmount = projectInfo.getAnnualPlanOtherAmount(); | |||
BigDecimal totalAnnual = annualGovSuperAmount | |||
.add(annualOwnSuperAmount).add(annualBankLendingAmount).add(annualHaveAmount).add(anualOtherAmount); | |||
VUtils.isTrue(annualPlanAmount.compareTo(totalAnnual) != 0) | |||
.throwMessage(String.format("申报失败! 年度支付总金额【{}】 不等于其它年度支付金额 【{}】",annualPlanAmount,totalAnnual)); | |||
//判断 年度计划金额 如果开着的话 | |||
if(projectInfo.getIsAnnualPlanAmount()){ | |||
BigDecimal annualPlanAmount = projectInfo.getAnnualPlanAmount(); | |||
BigDecimal annualGovSuperAmount = projectInfo.getAnnualPlanGovSuperiorFinanceAmount(); | |||
BigDecimal annualOwnSuperAmount = projectInfo.getAnnualPlanGovOwnFinanceAmount(); | |||
BigDecimal annualBankLendingAmount = projectInfo.getAnnualPlanBankLendingAmount(); | |||
BigDecimal annualHaveAmount = projectInfo.getAnnualPlanHaveAmount(); | |||
BigDecimal anualOtherAmount = projectInfo.getAnnualPlanOtherAmount(); | |||
BigDecimal totalAnnual = annualGovSuperAmount | |||
.add(annualOwnSuperAmount).add(annualBankLendingAmount).add(annualHaveAmount).add(anualOtherAmount); | |||
VUtils.isTrue(annualPlanAmount.compareTo(totalAnnual) != 0) | |||
.throwMessage(String.format("申报失败! 年度支付总金额【{}】 不等于其它年度支付金额 【{}】",annualPlanAmount,totalAnnual)); | |||
} | |||
} | |||
public ProcessInstanceUserDto buildUser(Long userId){ | |||
@@ -0,0 +1,44 @@ | |||
package com.ningdatech.pmapi.projectlib.enumeration; | |||
import java.util.Objects; | |||
import org.apache.commons.lang3.StringUtils; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Getter; | |||
import lombok.NoArgsConstructor; | |||
/** | |||
* 四大体系枚举 | |||
* | |||
* @return | |||
* @author CMM | |||
* @since 2023/03/16 16:27 | |||
*/ | |||
@Getter | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
public enum FourSystemEnum { | |||
/** | |||
* 项目类型 | |||
*/ | |||
BUSINESS_APPLICATION(1, "业务应用"), | |||
APPLICATION_SUPPORT(2, "应用支撑"), | |||
DATA_RESOURCES(3, "数据资源"), | |||
INFRASTRUCTURE(4, "基础设施"); | |||
private Integer code; | |||
private String desc; | |||
public static String getDescByCode(Integer code) { | |||
if (Objects.isNull(code)) { | |||
return StringUtils.EMPTY; | |||
} | |||
for (FourSystemEnum t : FourSystemEnum.values()) { | |||
if (code.equals(t.getCode())) { | |||
return t.desc; | |||
} | |||
} | |||
return StringUtils.EMPTY; | |||
} | |||
} |
@@ -47,7 +47,7 @@ public class PreliminaryPreviewHandle extends AbstractProcessBusinessHandle { | |||
// 根据项目ID查询项目预审流程的流程状态 | |||
ProjectInst projectInst = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class) | |||
.eq(ProjectInst::getProjectId, projectId) | |||
.eq(ProjectInst::getInstType, InstTypeEnum.DEPT_UNITED_REVIEW.getCode()) | |||
.eq(ProjectInst::getInstType, InstTypeEnum.PRELIMINARY_PREVIEW.getCode()) | |||
.orderByDesc(ProjectInst::getCreatOn) | |||
.last("limit 1")); | |||
if (Objects.isNull(projectInst)){ | |||
@@ -312,4 +312,7 @@ public class Project implements Serializable { | |||
@ApiModelProperty("项目预审申请单文件ID") | |||
private Long pretrialFileId; | |||
@ApiModelProperty("项目预审申请单文件名") | |||
private String pretrialFileName; | |||
} |
@@ -294,6 +294,12 @@ public class ProjectDetailVO { | |||
private String projectTypeName; | |||
@ApiModelProperty("项目预审申请单文件ID") | |||
private Long pretrialFileId; | |||
@ApiModelProperty("项目预审申请单文件名") | |||
private String pretrialFileName; | |||
public String getProjectTypeName() { | |||
if (Objects.nonNull(this.projectType)) { | |||
Optional.ofNullable(ProjectTypeEnum.getDesc(this.projectType)) | |||
@@ -2,8 +2,10 @@ package com.ningdatech.pmapi.provincial.model.res; | |||
import io.swagger.annotations.ApiModel; | |||
import io.swagger.annotations.ApiModelProperty; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Builder; | |||
import lombok.Data; | |||
import lombok.NoArgsConstructor; | |||
/** | |||
* @Classname ProcessCommentDTO | |||
@@ -14,6 +16,8 @@ import lombok.Data; | |||
@Data | |||
@Builder | |||
@ApiModel(value = "ProcessCommentRes", description = "省局返回流程审核详情") | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
public class ProcessCommentRes { | |||
@ApiModelProperty("任务id") | |||
@@ -2,8 +2,10 @@ package com.ningdatech.pmapi.provincial.model.res; | |||
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,6 +19,8 @@ import java.util.List; | |||
@Data | |||
@Builder | |||
@ApiModel(value = "ProvincialApplicationRes", description = "") | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
public class ProvincialApplicationRes implements Serializable { | |||
@@ -89,6 +93,8 @@ public class ProvincialApplicationRes implements Serializable { | |||
@Builder | |||
@JsonIgnoreProperties(value = { "handler"}) | |||
@NoArgsConstructor | |||
@AllArgsConstructor | |||
public static class Cloud implements Serializable { | |||
//云资源台数 11 | |||
private Integer cloudNums; | |||
@@ -39,14 +39,14 @@ public class CheckProvincialReviewResultTask { | |||
private final IProjectService projectService; | |||
private final StateMachineUtils stateMachineUtils; | |||
@Scheduled(cron = "0 */5 * * * ?") | |||
@Scheduled(cron = "0 */1 * * * ?") | |||
public void statusFlow() throws UnknownHostException { | |||
//测试暂时用自己电脑HOST | |||
if (TaskContant.Host.HOST_ZPF.equals(InetAddress.getLocalHost().getHostName())) { | |||
//1. 定时取 省级部门联审中的项目 去取项目 | |||
List<Project> projectList = projectService.list(Wrappers.lambdaQuery(Project.class) | |||
.eq(Project::getStage, ProjectStatusEnum.NOT_APPROVED) | |||
.eq(Project::getStatus, ProjectStatusEnum.JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS) | |||
.eq(Project::getStage, ProjectStatusEnum.NOT_APPROVED.getCode()) | |||
.eq(Project::getStatus, ProjectStatusEnum.JOINT_REVIEW_BY_PROVINCIAL_DEPARTMENTS.getCode()) | |||
.orderByAsc(Project::getCreateOn)); | |||
log.info("需要去查询省级联审结果的项目 size:{}",projectList.size()); | |||
@@ -6,6 +6,7 @@ import javax.validation.Valid; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.DefaultDeclaredDTO; | |||
import com.ningdatech.pmapi.todocenter.model.dto.AdjustHandleDTO; | |||
import com.ningdatech.pmapi.todocenter.model.dto.SealInfoDTO; | |||
import com.ningdatech.pmapi.todocenter.model.vo.ProcessProgressDetailVo; | |||
import com.ningdatech.pmapi.todocenter.model.req.ProcessDetailReq; | |||
import com.ningdatech.pmapi.todocenter.model.req.ToBeProcessedExportReq; | |||
@@ -169,4 +170,16 @@ public class TodoCenterController { | |||
String instanceId = todoCenterManage.adjustmentAndHandle(dto); | |||
return "退回项目内容调整并且重新通过 【" + instanceId + "】 成功"; | |||
} | |||
@ApiOperation("获取未签章的pdf文件") | |||
@PostMapping("/getNotSealedPdf/{projectId}") | |||
public Long getNotSealedPdf (@Valid @PathVariable("projectId") Long projectId){ | |||
return todoCenterManage.getNotSealedPdf(projectId); | |||
} | |||
@ApiOperation("获取签章后的pdf文件") | |||
@PostMapping("/getSealedPdf") | |||
public Long getSealedPdf(@Valid @RequestBody SealInfoDTO req){ | |||
return todoCenterManage.getSealedPdf(req); | |||
} | |||
} |
@@ -0,0 +1,71 @@ | |||
package com.ningdatech.pmapi.todocenter.enumeration; | |||
import java.util.Objects; | |||
import org.apache.commons.lang3.StringUtils; | |||
import io.swagger.annotations.ApiModel; | |||
import lombok.AllArgsConstructor; | |||
import lombok.Getter; | |||
import lombok.NoArgsConstructor; | |||
/** | |||
* 是否增补项目枚举 | |||
* | |||
* @author CMM | |||
*/ | |||
@Getter | |||
@AllArgsConstructor | |||
@NoArgsConstructor | |||
@ApiModel(value = "IsOrNotEnum", description = "是否-枚举") | |||
public enum IsOrNotEnum { | |||
/** | |||
* 否 | |||
*/ | |||
NOT(0, "否"), | |||
/** | |||
* 是 | |||
*/ | |||
IS(1, "是"); | |||
private Integer code; | |||
private String desc; | |||
public String getDesc() { | |||
return desc; | |||
} | |||
public void setDesc(String desc) { | |||
this.desc = desc; | |||
} | |||
public static String getDescByCode(Integer code) { | |||
if (Objects.isNull(code)) { | |||
return StringUtils.EMPTY; | |||
} | |||
for (IsOrNotEnum t : IsOrNotEnum.values()) { | |||
if (code.equals(t.getCode())) { | |||
return t.desc; | |||
} | |||
} | |||
return StringUtils.EMPTY; | |||
} | |||
public static IsOrNotEnum getEnumByValue(Integer code) { | |||
if (Objects.isNull(code)) { | |||
return null; | |||
} | |||
for (IsOrNotEnum t : IsOrNotEnum.values()) { | |||
if (code.equals(t.getCode())) { | |||
return t; | |||
} | |||
} | |||
return null; | |||
} | |||
public boolean eq(String val) { | |||
return this.name().equals(val); | |||
} | |||
} |
@@ -1,40 +1,54 @@ | |||
package com.ningdatech.pmapi.todocenter.manage; | |||
import cn.hutool.core.codec.Base64; | |||
import cn.hutool.core.collection.CollUtil; | |||
import cn.hutool.core.util.StrUtil; | |||
import com.alibaba.fastjson.JSONObject; | |||
import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |||
import com.google.common.collect.Sets; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.basic.function.VUtils; | |||
import com.ningdatech.basic.model.PageVo; | |||
import com.ningdatech.basic.util.CollUtils; | |||
import com.ningdatech.basic.util.NdDateUtils; | |||
import com.ningdatech.file.entity.File; | |||
import com.ningdatech.file.entity.vo.result.FileResultVO; | |||
import com.ningdatech.file.service.FileService; | |||
import com.ningdatech.pmapi.common.constant.CommonConst; | |||
import com.ningdatech.pmapi.common.helper.UserInfoHelper; | |||
import com.ningdatech.pmapi.common.model.entity.ExcelExportWriter; | |||
import com.ningdatech.pmapi.common.statemachine.event.ProjectStatusChangeEvent; | |||
import com.ningdatech.pmapi.common.statemachine.util.StateMachineUtils; | |||
import com.ningdatech.pmapi.common.util.ExcelDownUtil; | |||
import com.ningdatech.pmapi.irs.sign.IRSAPIRequest; | |||
import com.ningdatech.pmapi.organization.model.entity.DingEmployeeInfo; | |||
import com.ningdatech.pmapi.organization.model.entity.DingOrganization; | |||
import com.ningdatech.pmapi.organization.service.IDingEmployeeInfoService; | |||
import com.ningdatech.pmapi.organization.service.IDingOrganizationService; | |||
import com.ningdatech.pmapi.projectdeclared.manage.DefaultDeclaredProjectManage; | |||
import com.ningdatech.pmapi.projectdeclared.model.dto.DefaultDeclaredDTO; | |||
import com.ningdatech.pmapi.projectlib.enumeration.FourSystemEnum; | |||
import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum; | |||
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum; | |||
import com.ningdatech.pmapi.projectlib.enumeration.ProjectTypeEnum; | |||
import com.ningdatech.pmapi.projectlib.manage.ProjectLibManage; | |||
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.model.entity.ProjectInst; | |||
import com.ningdatech.pmapi.projectlib.model.req.ProjectListReq; | |||
import com.ningdatech.pmapi.projectlib.model.vo.ProjectLibListItemVO; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectApplicationService; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectInstService; | |||
import com.ningdatech.pmapi.projectlib.service.IProjectService; | |||
import com.ningdatech.pmapi.signature.entity.CompanySignature; | |||
import com.ningdatech.pmapi.signature.service.ICompanySignatureService; | |||
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.enumeration.IsOrNotEnum; | |||
import com.ningdatech.pmapi.todocenter.model.dto.AdjustHandleDTO; | |||
import com.ningdatech.pmapi.todocenter.model.dto.PdfGenerateDTO; | |||
import com.ningdatech.pmapi.todocenter.model.dto.SealInfoDTO; | |||
import com.ningdatech.pmapi.todocenter.model.dto.SignReqDTO; | |||
import com.ningdatech.pmapi.todocenter.model.vo.ProcessProgressDetailVo; | |||
import com.ningdatech.pmapi.todocenter.enumeration.IsAppendProjectEnum; | |||
import com.ningdatech.pmapi.todocenter.model.req.ProcessDetailReq; | |||
@@ -42,6 +56,7 @@ import com.ningdatech.pmapi.todocenter.model.req.ToBeProcessedExportReq; | |||
import com.ningdatech.pmapi.todocenter.model.req.ToBeProcessedReq; | |||
import com.ningdatech.pmapi.todocenter.model.vo.ResToBeProcessedVO; | |||
import com.ningdatech.pmapi.todocenter.utils.BuildUserUtils; | |||
import com.ningdatech.pmapi.todocenter.utils.PdfUtils; | |||
import com.ningdatech.pmapi.user.entity.UserInfo; | |||
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO; | |||
import com.ningdatech.pmapi.user.service.IUserInfoService; | |||
@@ -50,33 +65,35 @@ import com.wflow.contants.HisProInsEndActId; | |||
import com.wflow.exception.BusinessException; | |||
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto; | |||
import com.wflow.workflow.bean.dto.ReqProcessHandlerDTO; | |||
import com.wflow.workflow.bean.process.ProcessComment; | |||
import com.wflow.workflow.bean.process.ProgressNode; | |||
import com.wflow.workflow.bean.process.enums.NodeTypeEnum; | |||
import com.wflow.workflow.bean.vo.ProcessInstanceVo; | |||
import com.wflow.workflow.bean.vo.ProcessProgressVo; | |||
import com.wflow.workflow.bean.vo.ProcessTaskVo; | |||
import com.wflow.workflow.enums.ProcessHandlerEnum; | |||
import com.wflow.workflow.enums.ProcessStatusEnum; | |||
import com.wflow.workflow.service.ProcessInstanceService; | |||
import com.wflow.workflow.service.ProcessTaskService; | |||
import lombok.RequiredArgsConstructor; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.apache.commons.io.FileUtils; | |||
import org.assertj.core.util.Lists; | |||
import org.flowable.bpmn.model.*; | |||
import org.flowable.engine.HistoryService; | |||
import org.flowable.engine.history.HistoricProcessInstance; | |||
import org.flowable.engine.runtime.ActivityInstance; | |||
import org.mockito.internal.matchers.CompareTo; | |||
import org.springframework.beans.BeanUtils; | |||
import org.springframework.mock.web.MockMultipartFile; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Transactional; | |||
import org.springframework.web.multipart.MultipartFile; | |||
import javax.servlet.http.HttpServletResponse; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.math.BigDecimal; | |||
import java.net.URL; | |||
import java.time.LocalDateTime; | |||
import java.util.*; | |||
import java.util.stream.Collectors; | |||
import static com.ningdatech.pmapi.todocenter.constant.WorkNotice.*; | |||
import static com.wflow.workflow.task.TriggerServiceTask.runtimeService; | |||
@@ -93,10 +110,8 @@ public class TodoCenterManage { | |||
private final HistoryService historyService; | |||
private final IUserInfoService userInfoService; | |||
private final IProjectService projectService; | |||
private final ProjectLibManage projectLibManage; | |||
private final StateMachineUtils stateMachineUtils; | |||
private final IDingEmployeeInfoService dingEmployeeInfoService; | |||
private final IDingOrganizationService dingOrganizationService; | |||
private final ProcessInstanceService processInstanceService; | |||
@@ -105,8 +120,11 @@ public class TodoCenterManage { | |||
private final IProjectApplicationService projectApplicationService; | |||
private final UserInfoHelper userInfoHelper; | |||
private final BuildUserUtils buildUserUtils; | |||
private final IProjectStagingService projectStagingService; | |||
private final IProjectInstService projectInstService; | |||
private final PdfUtils pdfUtils; | |||
private final FileService fileService; | |||
private final ICompanySignatureService companySignatureService; | |||
/** | |||
@@ -246,6 +264,8 @@ public class TodoCenterManage { | |||
switch (param.getAction()) { | |||
// 通过 | |||
case PASS: | |||
// 盖章并通过 | |||
case SEAL_PASS: | |||
// 通过该任务,流程到下一审核人处 | |||
processTaskService.handleTask(param, userId); | |||
// 获取流程通过后的流程实例 | |||
@@ -313,12 +333,6 @@ public class TodoCenterManage { | |||
workNoticeStagingService.addByWorkNotice(sendWorkNoticeInfo, MsgTypeEnum.AUDIT); | |||
} | |||
break; | |||
// 盖章并通过 | |||
case SEAL_PASS: | |||
// TODO 调用盖章接口,返回盖章后的文件流 | |||
// 通过该任务,流程到下一审核人处 | |||
processTaskService.handleTask(param, userId); | |||
break; | |||
// 驳回 | |||
case REJECT: | |||
// 驳回该任务,中止流程并使项目进入对应状态,给项目创建人、流程发起人发送浙政钉工作通知: | |||
@@ -406,6 +420,62 @@ public class TodoCenterManage { | |||
} | |||
} | |||
/** | |||
* 调用IRS接口,获取盖章后的pdf文件,上传到OSS,并保存文件ID到项目库中 | |||
* @param req | |||
* @param declaredProject | |||
* @return void | |||
* @author CMM | |||
* @since 2023/03/16 21:34 | |||
*/ | |||
private Long getSealedPdf(SealInfoDTO req, Project declaredProject) { | |||
Long projectId = req.getProjectId(); | |||
// 设置pdf模板参数 | |||
JSONObject paramsMap = assemblyPdfParams(declaredProject); | |||
// TODO 根据当前盖章单位设置对应的盖章意见与盖章日期 | |||
paramsMap.put("superOrgOpinion",null); | |||
paramsMap.put("superOrgAuditDate",null); | |||
paramsMap.put("higherOrgOpinion",null); | |||
paramsMap.put("higherOrgAuditDate",null); | |||
paramsMap.put("bigDataBureauOpinion",null); | |||
paramsMap.put("bigDataBureauAuditDate",null); | |||
// 再次获取装配了盖章意见和盖章日期参数的未盖章pdf文件 | |||
Long pretrialFileId = generateNotSealedPdf(projectId,paramsMap); | |||
// 获取预审申请单文件,并转换为Base64 | |||
File pdfFile = fileService.getById(pretrialFileId); | |||
InputStream fileInputStream = fileService.getFileInputStream(pdfFile); | |||
String pdfEncode64 = Base64.encode(fileInputStream); | |||
// 装配盖章接口请求参数信息 | |||
SignReqDTO signReq = new SignReqDTO(); | |||
signReq.setPdfEncode64(pdfEncode64); | |||
String originalFileName = pdfFile.getOriginalFileName(); | |||
signReq.setFileName(originalFileName); | |||
Float posX = req.getPosX(); | |||
Float posY = req.getPosY(); | |||
signReq.setPosX(posX); | |||
signReq.setPosY(posY); | |||
// 获取当前登录签章用户信息 | |||
Long userId = LoginUserUtil.getUserId(); | |||
UserFullInfoDTO userFullInfo = userInfoHelper.getUserFullInfo(userId); | |||
// 获取印章编号 | |||
CompanySignature companySignature = companySignatureService.getOne(Wrappers.lambdaQuery(CompanySignature.class) | |||
.eq(CompanySignature::getOrganizationCode, userFullInfo.getOrganizationCode())); | |||
String sealSn = companySignature.getSealSn(); | |||
signReq.setSealSn(sealSn); | |||
// 调用盖章接口,获取盖章后返回的pdf文件字符数组 | |||
byte[] signPdf = IRSAPIRequest.createSignPdf(signReq); | |||
// 转换成MultipartFile | |||
MultipartFile multipartFile = new MockMultipartFile("file", originalFileName + ".pdf", "application/pdf", signPdf); | |||
// 上传OSS | |||
FileResultVO resultVo = fileService.upload(multipartFile, "default"); | |||
// 将返回的文件ID更新到项目库中对应的项目下 | |||
declaredProject.setPretrialFileId(resultVo.getId()); | |||
declaredProject.setPretrialFileName(resultVo.getOriginalFileName()); | |||
declaredProject.setUpdateOn(LocalDateTime.now()); | |||
projectService.updateById(declaredProject); | |||
return resultVo.getId(); | |||
} | |||
/** | |||
* 当为驳回操作时,更新项目表中的项目状态 | |||
@@ -938,4 +1008,136 @@ public class TodoCenterManage { | |||
} | |||
return Boolean.TRUE; | |||
} | |||
/** | |||
* 获取未盖章的预审申请单pdf文件 | |||
* @param projectId | |||
* @return java.lang.Long | |||
* @author CMM | |||
* @since 2023/03/16 22:46 | |||
*/ | |||
public Long getNotSealedPdf(Long projectId) { | |||
// 设置pdf模板参数 | |||
Project project = projectService.getById(projectId); | |||
JSONObject paramsMap = assemblyPdfParams(project); | |||
paramsMap.put("superOrgOpinion",null); | |||
paramsMap.put("superOrgAuditDate",null); | |||
paramsMap.put("higherOrgOpinion",null); | |||
paramsMap.put("higherOrgAuditDate",null); | |||
paramsMap.put("bigDataBureauOpinion",null); | |||
paramsMap.put("bigDataBureauAuditDate",null); | |||
return generateNotSealedPdf(projectId, paramsMap); | |||
} | |||
private Long generateNotSealedPdf(Long projectId, JSONObject paramsMap) { | |||
// 获取本地目录的pdf模板 | |||
String fileName = "预审申请单"; | |||
InputStream htmlInputStream = | |||
this.getClass().getClassLoader().getResourceAsStream("template/" + fileName + ".html"); | |||
// 生成pdf字节数组 | |||
byte[] pdf = pdfUtils.generatePdf(htmlInputStream, paramsMap); | |||
// 转换成MultipartFile | |||
MultipartFile multipartFile = new MockMultipartFile("file", fileName + ".pdf", "application/pdf", pdf); | |||
// 上传OSS | |||
FileResultVO resultVO = fileService.upload(multipartFile, "default"); | |||
// 将返回的文件ID保存到项目库中 | |||
Project project = projectService.getById(projectId); | |||
project.setPretrialFileId(resultVO.getId()); | |||
project.setPretrialFileName(resultVO.getOriginalFileName()); | |||
project.setUpdateOn(LocalDateTime.now()); | |||
projectService.updateById(project); | |||
try { | |||
if (null != htmlInputStream) { | |||
htmlInputStream.close(); | |||
} | |||
// 删除输出文件夹下的临时文件 | |||
java.io.File resourcesPath = new java.io.File("pmapi/src/main/resources"); | |||
String reportPath = resourcesPath.getCanonicalPath(); | |||
String path = reportPath + "/template/fileout"; | |||
java.io.File directory = new java.io.File(path); | |||
FileUtils.cleanDirectory(directory); | |||
} catch (IOException e) { | |||
log.error(e.getMessage()); | |||
} | |||
// 返回文件id供前端下载 | |||
return resultVO.getId(); | |||
} | |||
/** | |||
* 装配pdf模板参数 | |||
* @param project 申报项目ID | |||
* @return com.alibaba.fastjson.JSONObject | |||
* @author CMM | |||
* @since 2023/03/16 22:28 | |||
*/ | |||
private JSONObject assemblyPdfParams(Project project) { | |||
// 获取本地目录的pdf模板 | |||
String fileName = "预审申请单"; | |||
Long projectId = project.getId(); | |||
// 获取表单数据 | |||
PdfGenerateDTO pdfGenerateDTO = new PdfGenerateDTO(); | |||
BeanUtils.copyProperties(project, pdfGenerateDTO); | |||
JSONObject paramsMap = JSONObject.parseObject(JSONObject.toJSONString(pdfGenerateDTO)); | |||
// 设置title | |||
String title = "【" + project.getProjectName() + "】" + fileName; | |||
paramsMap.put("title",title); | |||
paramsMap.put("projectNo", projectId); | |||
// 获取预审申报的开始时间 | |||
ProjectInst projectInst = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class) | |||
.eq(ProjectInst::getProjectId, projectId) | |||
.eq(ProjectInst::getInstType, InstTypeEnum.PRELIMINARY_PREVIEW.getCode()) | |||
.orderByDesc(ProjectInst::getCreatOn) | |||
.last("limit 1")); | |||
LocalDateTime time = null; | |||
if (Objects.nonNull(projectInst)) { | |||
time = projectInst.getCreatOn(); | |||
paramsMap.put("time", NdDateUtils.format(time, "yyyy-MM-dd HH:mm")); | |||
}else { | |||
paramsMap.put("time", null); | |||
} | |||
// 获取是否临时增补项目 | |||
String isTemporaryAugment = IsOrNotEnum.getDescByCode(project.getIsTemporaryAugment()); | |||
paramsMap.put("isTemporaryAugment", isTemporaryAugment); | |||
// 获取项目类型 | |||
Integer projectType = project.getProjectType(); | |||
paramsMap.put("projectType", ProjectTypeEnum.getDesc(projectType)); | |||
// 获取是否首次新建 | |||
String isFirst = IsOrNotEnum.getDescByCode(project.getIsFirst()); | |||
paramsMap.put("isFirst", isFirst); | |||
// 获取是否一地创新全省共享项目 | |||
Boolean isInnovateWholeProvinceShare = project.getIsInnovateWholeProvinceShare(); | |||
paramsMap.put("isInnovateWholeProvinceShare", Boolean.TRUE.equals(isInnovateWholeProvinceShare) ? | |||
IsOrNotEnum.IS.getDesc() : IsOrNotEnum.NOT.getDesc()); | |||
// 获取项目建设起始时间 | |||
String beginTime = project.getBeginTime(); | |||
String endTime = project.getEndTime(); | |||
String beginAndEndTime = beginTime + StrUtil.DASHED + endTime; | |||
paramsMap.put("beginAndEndTime", beginAndEndTime); | |||
// 获取四大体系 | |||
String fourSystem = FourSystemEnum.getDescByCode(project.getFourSystems()); | |||
paramsMap.put("fourSystems", fourSystem); | |||
// 获取是否数字化改革项目 | |||
String isDigitalReform = IsOrNotEnum.getDescByCode(project.getIsDigitalReform()); | |||
paramsMap.put("isDigitalReform", isDigitalReform); | |||
// 获取是否上云 | |||
String isCloud = IsOrNotEnum.getDescByCode(project.getIsCloud()); | |||
paramsMap.put("isCloud", isCloud); | |||
// 获取本年计划投资金额 | |||
BigDecimal yearPlanInvest = project.getAnnualPlanAmount(); | |||
paramsMap.put("yearPlanInvest",yearPlanInvest); | |||
// TODO 根据地区编码获取当地大数据局(中心)的名称 | |||
paramsMap.put("bigDataBureauName",null); | |||
return paramsMap; | |||
} | |||
public Long getSealedPdf(SealInfoDTO req) { | |||
Long projectId = req.getProjectId(); | |||
Project declaredProject = projectService.getById(projectId); | |||
return getSealedPdf(req, declaredProject); | |||
} | |||
} |
@@ -137,4 +137,10 @@ public class PdfGenerateDTO { | |||
@ApiModelProperty("一地创新全省共享项目-是否开启 false:关闭 true:开启") | |||
private Boolean isInnovateWholeProvinceShare; | |||
@ApiModelProperty("本地区大数据局名称") | |||
private String bidDataBureauName; | |||
@ApiModelProperty("年度计划投资") | |||
private BigDecimal yearPlanInvest; | |||
} |
@@ -0,0 +1,37 @@ | |||
package com.ningdatech.pmapi.todocenter.model.dto; | |||
import lombok.Data; | |||
/** | |||
* 调用天印外部接口签章所需信息 | |||
* | |||
* @author CMM | |||
* @since 2023/03/16 17:01 | |||
*/ | |||
@Data | |||
public class SealInfoDTO { | |||
/** | |||
* 项目ID | |||
*/ | |||
private Long projectId; | |||
/** | |||
* 印章x坐标 | |||
*/ | |||
private Float posX; | |||
/** | |||
* 印章y坐标 | |||
*/ | |||
private Float posY; | |||
/** | |||
* 页码 | |||
*/ | |||
private String posPage; | |||
/** | |||
* 签署类型 | |||
*/ | |||
private Integer signType; | |||
} |
@@ -0,0 +1,24 @@ | |||
package com.ningdatech.pmapi.todocenter.model.dto; | |||
import lombok.Data; | |||
/** | |||
* 印章信息及位置坐标 | |||
* | |||
* @author CMM | |||
* @since 2023/03/16 11:56 | |||
*/ | |||
@Data | |||
public class SignReqDTO { | |||
private String pdfEncode64; | |||
private Float posX; | |||
private Float posY; | |||
private String sealSn; | |||
private String fileName; | |||
} |
@@ -1,140 +0,0 @@ | |||
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; | |||
} | |||
} | |||
@@ -1,9 +1,13 @@ | |||
package com.ningdatech.pmapi.todocenter.utils; | |||
import cn.hutool.core.util.StrUtil; | |||
import com.itextpdf.text.DocumentException; | |||
import com.itextpdf.text.Image; | |||
import com.itextpdf.text.Rectangle; | |||
import com.itextpdf.text.pdf.*; | |||
import com.ningdatech.basic.exception.BizException; | |||
import com.ningdatech.pmapi.common.util.StrUtils; | |||
import lombok.extern.slf4j.Slf4j; | |||
import org.springframework.stereotype.Component; | |||
import org.springframework.transaction.annotation.Propagation; | |||
@@ -40,7 +44,7 @@ public class PdfUtils { | |||
File directory = new File(""); | |||
//pdf输出路径 | |||
String absolutePath = directory.getAbsolutePath(); | |||
String linkPath = "\\src\\main\\resources"; | |||
String linkPath = "\\pmapi\\src\\main\\resources"; | |||
String filePath = absolutePath + linkPath + "\\template\\fileout"; | |||
if(!new File(filePath).exists()){ | |||
new File(filePath).mkdir(); | |||
@@ -58,13 +62,14 @@ public class PdfUtils { | |||
//替换参数、多个参数多次替换 | |||
for (String fieldName : paramsMap.keySet()) { | |||
if (paramsMap.get(fieldName) == null) { | |||
continue; | |||
// 没有值的字段使用-覆盖 | |||
htmlInfo = htmlInfo.replace("#" + fieldName + "#", ""); | |||
}else { | |||
// 设置占位字段 | |||
htmlInfo = htmlInfo.replace("#" + fieldName + "#", paramsMap.get(fieldName).toString()); | |||
} | |||
// 设置占位字段 | |||
htmlInfo = htmlInfo.replace("#" + fieldName + "#", paramsMap.get(fieldName).toString()); | |||
} | |||
//生成临时文件 | |||
String htmlFileName = UUID.randomUUID().toString().replace("-","") + ".html"; | |||
String htmlFilePath = filePath + File.separator + htmlFileName; | |||
@@ -95,15 +100,6 @@ public class PdfUtils { | |||
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) { | |||
@@ -96,7 +96,7 @@ mybatis-plus: | |||
logic-not-delete-value: false | |||
logging: | |||
config: classpath:logback-spring.xml | |||
#日志配置 | |||
#日志配置 | |||
level: | |||
root: info | |||
file: | |||
@@ -195,6 +195,7 @@ provincial: | |||
secret: 75152a97f20e4c4c854dc6301cf72ad4 | |||
#天印服务器接口信息 | |||
irs: | |||
seal-platform: | |||
project-id: 1 | |||
@@ -1,254 +0,0 @@ | |||
<!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> |
@@ -1,5 +1,8 @@ | |||
<!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"> | |||
<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" /> | |||
@@ -9,7 +12,7 @@ | |||
body { | |||
padding: 0; | |||
margin: 0; | |||
font-family:SimSun; | |||
font-family: SimSun; | |||
} | |||
.pdf { | |||
margin: 0 auto; | |||
@@ -20,7 +23,7 @@ | |||
padding: 0 0 40px 0; | |||
font-size: 34px; | |||
margin: 40px 0 0 0; | |||
font-family:SimSun; | |||
font-family: SimSun; | |||
} | |||
.tab { | |||
padding: 0 20px; | |||
@@ -72,12 +75,16 @@ | |||
.text { | |||
min-height: 150px; | |||
} | |||
.content > .right { | |||
float: right; | |||
margin-right: 10px; | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div class="pdf"> | |||
<p class="title"> | |||
预审申请单 | |||
<span>#title#</span> | |||
</p> | |||
<div class="tab"> | |||
<p class="projectId"> | |||
@@ -231,15 +238,45 @@ | |||
</tr> | |||
<tr> | |||
<td class="label">本级主管单位意见(盖章)</td> | |||
<td colspan="3" class="text content"></td> | |||
<td colspan="3" class="text content"> | |||
<div class="right"> | |||
<p> | |||
<span>#superOrgOpinion#</span> | |||
</p> | |||
<p> | |||
<span>#superOrgAuditDate#</span> | |||
</p> | |||
</div> | |||
</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> | |||
<td colspan="3" class="text content"> | |||
<div class="right"> | |||
<p> | |||
<span>#higherOrgOpinion#</span> | |||
</p> | |||
<p> | |||
<span>#higherOrgAuditDate#</span> | |||
</p> | |||
</div> | |||
</td> | |||
</tr> | |||
<tr> | |||
<td class="label"> | |||
<span>#bigDataBureauName#</span> | |||
意见(盖章) | |||
</td> | |||
<td colspan="3" class="text content"> | |||
<div class="right"> | |||
<p> | |||
<span>#bigDataBureauOpinion#</span> | |||
</p> | |||
<p> | |||
<span>#bigDataBureauAuditDate#</span> | |||
</p> | |||
</div> | |||
</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
@@ -17,7 +17,6 @@ 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; | |||
@@ -28,13 +27,10 @@ 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; | |||
/** | |||
@@ -127,7 +123,7 @@ public class TodoCenterTest extends AppTests { | |||
public void GeneratePdf(){ | |||
// 获取本地目录的pdf模板 | |||
String fileName = "预审申请单"; | |||
InputStream pdfInputStream = | |||
InputStream htmlInputStream = | |||
this.getClass().getClassLoader().getResourceAsStream("template/" + fileName + ".html"); | |||
// 获取表单数据 | |||
ProjectDetailVO projectDetail = projectLibManage.getProjectDetail(44L); | |||
@@ -153,10 +149,11 @@ public class TodoCenterTest extends AppTests { | |||
paramsMap.put("isDigitalReform", "否"); | |||
Integer isCloud = projectDetail.getIsCloud(); | |||
paramsMap.put("isCloud", "否"); | |||
paramsMap.put("yearPlanInvest",null); | |||
paramsMap.put("bigDataBureauName",null); | |||
// 生成pdf字节数组 | |||
byte[] pdf = pdfUtils.generatePdf(pdfInputStream, paramsMap); | |||
byte[] pdf = pdfUtils.generatePdf(htmlInputStream, paramsMap); | |||
// 转换成MultipartFile | |||
MultipartFile multipartFile = new MockMultipartFile("file", fileName + ".pdf", "application/pdf", pdf); | |||
@@ -169,8 +166,8 @@ public class TodoCenterTest extends AppTests { | |||
project.setPretrialFileId(resultVO.getId()); | |||
try { | |||
if (null != pdfInputStream) { | |||
pdfInputStream.close(); | |||
if (null != htmlInputStream) { | |||
htmlInputStream.close(); | |||
} | |||
} catch (IOException e) { | |||
e.printStackTrace(); | |||
@@ -169,6 +169,12 @@ | |||
<artifactId>flying-saucer-pdf-itext5</artifactId> | |||
<version>9.0.3</version> | |||
</dependency> | |||
<!--将html转换成pdf--> | |||
<dependency> | |||
<groupId>com.itextpdf</groupId> | |||
<artifactId>html2pdf</artifactId> | |||
<version>2.0.2</version> | |||
</dependency> | |||
</dependencies> | |||
</dependencyManagement> | |||