|
@@ -0,0 +1,454 @@
|
|
|
+package com.fourdage.dingding.util;
|
|
|
+
|
|
|
+import java.io.BufferedReader;
|
|
|
+import java.io.ByteArrayInputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.FileWriter;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStreamReader;
|
|
|
+import java.io.OutputStreamWriter;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.nio.charset.Charset;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.apache.shiro.SecurityUtils;
|
|
|
+import org.apache.shiro.subject.Subject;
|
|
|
+import org.joda.time.DateTime;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Repository;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.fourdage.base.common.HttpHelper;
|
|
|
+import com.fourdage.dingding.entity.PdfVO;
|
|
|
+import com.fourdage.system.entity.DataDictionary;
|
|
|
+import com.fourdage.system.entity.User;
|
|
|
+import com.fourdage.system.service.IDataDictionaryService;
|
|
|
+import com.itextpdf.text.Document;
|
|
|
+import com.itextpdf.text.PageSize;
|
|
|
+import com.itextpdf.text.pdf.PdfWriter;
|
|
|
+import com.itextpdf.tool.xml.XMLWorkerFontProvider;
|
|
|
+import com.itextpdf.tool.xml.XMLWorkerHelper;
|
|
|
+
|
|
|
+import freemarker.template.Configuration;
|
|
|
+import freemarker.template.Template;
|
|
|
+
|
|
|
+
|
|
|
+@Repository
|
|
|
+public class HtmlPdfUtil {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IDataDictionaryService dataDictionaryService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private DingDingUtil dingdingUtil;
|
|
|
+
|
|
|
+ @Value("${web.pdf.file.path}")
|
|
|
+ private String path;
|
|
|
+
|
|
|
+ private Logger logger = LoggerFactory.getLogger(HtmlPdfUtil.class);
|
|
|
+
|
|
|
+ private String blankCode = " ";
|
|
|
+
|
|
|
+ public void generateHTMLFile(String accessToken, String processInstanceId, String fileName) {
|
|
|
+// FileWriter out = null;
|
|
|
+ OutputStreamWriter out = null;
|
|
|
+ try {
|
|
|
+ String title = "";
|
|
|
+ String businessId = "";
|
|
|
+ JSONObject jsonResult = dingdingUtil.getDingDingJSONResult(processInstanceId, accessToken);
|
|
|
+ logger.info("钉钉返回数据: {}", jsonResult);
|
|
|
+ if (jsonResult.getBoolean("success")){
|
|
|
+ DataDictionary corp = dataDictionaryService.findByCodeAndDataKey("corp_code", dingdingUtil.getRegion());
|
|
|
+
|
|
|
+ JSONObject result = jsonResult.getJSONObject("process_instance");
|
|
|
+ //企业名称
|
|
|
+// String corpName = corp.getDataValue();
|
|
|
+ String corpName = "四维时代 & 中德人工智能研究院";
|
|
|
+ //申请日期
|
|
|
+ String applyDate = result.getString("create_time");
|
|
|
+ //审批编码
|
|
|
+ businessId = result.getString("business_id");
|
|
|
+ String[] titlesArr = null;
|
|
|
+ if(result.getString("title").contains("的")){
|
|
|
+ titlesArr = result.getString("title").split("的");
|
|
|
+ }
|
|
|
+ if(result.getString("title").contains("'s")){
|
|
|
+ titlesArr = result.getString("title").split("'s");
|
|
|
+ }
|
|
|
+ String applyUserName = titlesArr[0];
|
|
|
+ //申请人
|
|
|
+ //模板名称
|
|
|
+ title = titlesArr[1];
|
|
|
+ //申请人部门
|
|
|
+ String org = result.getString("originator_dept_name");
|
|
|
+
|
|
|
+ PdfVO vo = new PdfVO();
|
|
|
+ vo.setCorpName(corpName);
|
|
|
+ vo.setApplyDate(applyDate);
|
|
|
+ vo.setBusinessId(businessId);
|
|
|
+ vo.setApplyUserName(applyUserName);
|
|
|
+ vo.setTitle(title);
|
|
|
+ vo.setOrg(org);
|
|
|
+ vo.setStatus(dingdingUtil.getStatus(result.getString("status")));
|
|
|
+ vo.setForm(generateForm(result).toString());
|
|
|
+ vo.setOperations(generateOperators(accessToken, result).toString());
|
|
|
+ vo.setPrintDate(new DateTime().toString("yyyy-MM-dd HH:mm"));
|
|
|
+
|
|
|
+ Subject subject = SecurityUtils.getSubject();
|
|
|
+ Object principal = subject.getPrincipal();
|
|
|
+ String userName = "";
|
|
|
+ if (principal != null) {
|
|
|
+ userName = ((User) principal).getNickName();
|
|
|
+ }
|
|
|
+ vo.setPrinter(userName);
|
|
|
+
|
|
|
+ Configuration configuration = new Configuration();
|
|
|
+ configuration.setDirectoryForTemplateLoading(new File(path));
|
|
|
+ configuration.setDefaultEncoding("UTF-8");
|
|
|
+ // 获取或创建一个模版。
|
|
|
+ Template template = configuration.getTemplate("pdf.ftl");
|
|
|
+ //设置输出流
|
|
|
+ File file = new File(path + fileName + ".html");
|
|
|
+// out = new FileWriter(file);
|
|
|
+ //设置文件输入流编码,不然生成的html文件会中文乱码
|
|
|
+ out = new OutputStreamWriter(new FileOutputStream(file),"UTF-8");
|
|
|
+ //模板输出静态文件
|
|
|
+ template.process(vo, out);
|
|
|
+ }
|
|
|
+ }catch (Exception e) {
|
|
|
+ logger.error("系统异常:", e);
|
|
|
+ } finally {
|
|
|
+ if(null != out) {
|
|
|
+ try {
|
|
|
+ out.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public String generateHtmlAndPDF(String accessToken, String processInstanceId, String processCodeName) {
|
|
|
+ String fileName = "";
|
|
|
+ try {
|
|
|
+ //从钉钉接口获取结果
|
|
|
+ JSONObject jsonResult = dingdingUtil.getDingDingJSONResult(processInstanceId, accessToken);
|
|
|
+ if (!jsonResult.getBoolean("success")) {
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+ //生成文件目录
|
|
|
+ File dirFile = new File(path + processCodeName);
|
|
|
+ if(!dirFile.exists()){
|
|
|
+ dirFile.mkdir();
|
|
|
+ }
|
|
|
+ JSONObject result = jsonResult.getJSONObject("process_instance");
|
|
|
+ fileName = result.getString("title") + result.getString("business_id");
|
|
|
+ String filePathName = path + processCodeName + "/" + fileName;
|
|
|
+ //生成HTML文件
|
|
|
+ generateHTMLFile(accessToken, processInstanceId, processCodeName + "/" + fileName);
|
|
|
+ //生成pdf文件
|
|
|
+ generatePdfFile(filePathName);
|
|
|
+
|
|
|
+ FileUtil.deleteFile(filePathName + ".html");
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("系统异常:", e);
|
|
|
+ } finally {
|
|
|
+ }
|
|
|
+ return fileName;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void generatePdfFile(String filePathName) {
|
|
|
+ Document document = null;
|
|
|
+ FileInputStream fis = null;
|
|
|
+ BufferedReader br = null;
|
|
|
+ InputStreamReader reader = null;
|
|
|
+ try {
|
|
|
+// fis = new FileInputStream(filePathName + ".html");
|
|
|
+// byte[] buf = new byte[1024];
|
|
|
+// int length = 0;
|
|
|
+// //循环读取文件内容,输入流中将最多buf.length个字节的数据读入一个buf数组中,返回类型是读取到的字节数。
|
|
|
+// //当文件读取到结尾时返回 -1,循环结束。
|
|
|
+// String content = null;
|
|
|
+// while((length = fis.read(buf)) != -1){
|
|
|
+// content = new String(buf,0,length);
|
|
|
+// System.out.print(content);
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
+ fis = new FileInputStream(filePathName + ".html");
|
|
|
+ reader = new InputStreamReader(fis, "UTF-8");
|
|
|
+ br = new BufferedReader(reader);
|
|
|
+ String content;
|
|
|
+ String ba = null;
|
|
|
+ while ((content = br.readLine()) != null) {
|
|
|
+ System.out.println(content);
|
|
|
+ ba += content;
|
|
|
+ }
|
|
|
+ byte b[] = ba.getBytes("utf-8"); //这里是必须要设置编码的,不然导出中文就会乱码。
|
|
|
+ ByteArrayInputStream bais = new ByteArrayInputStream(b);//将字节数组包装到流中
|
|
|
+
|
|
|
+ // step 1
|
|
|
+ document = new Document(PageSize.A4);
|
|
|
+ // step 2
|
|
|
+ PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filePathName + ".pdf"));
|
|
|
+ // step 3
|
|
|
+ document.open();
|
|
|
+ // step 4
|
|
|
+ XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
|
|
|
+ fontImp.register("/font/simhei.ttf");
|
|
|
+ XMLWorkerHelper.getInstance().parseXHtml(writer, document, bais, null, Charset.forName("UTF-8"), fontImp);
|
|
|
+ document.close();
|
|
|
+ br.close();
|
|
|
+ reader.close();
|
|
|
+ fis.close();
|
|
|
+ } catch (Exception e) {
|
|
|
+ logger.error("系统异常:", e);
|
|
|
+ } finally {
|
|
|
+ if (document != null) {
|
|
|
+ document.close();
|
|
|
+ }
|
|
|
+ if (fis != null){
|
|
|
+ try {
|
|
|
+ fis.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (br != null){
|
|
|
+ try {
|
|
|
+ br.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (reader != null){
|
|
|
+ try {
|
|
|
+ reader.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ // TODO Auto-generated catch block
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private StringBuffer generateOperators(String accessToken, JSONObject result) {
|
|
|
+ JSONArray userArray = result.getJSONObject("operation_records").getJSONArray("operation_records_vo");
|
|
|
+ StringBuffer userSB = null;
|
|
|
+ if (userArray != null && userArray.size() > 0){
|
|
|
+ userSB = new StringBuffer("<tr><td rowspan=\"").append(userArray.size()-1).append("\">审批人</td>");
|
|
|
+ for (int i = 0; i < userArray.size(); i++){
|
|
|
+ JSONObject ob = (JSONObject) userArray.get(i);
|
|
|
+ if ("START_PROCESS_INSTANCE".equals(ob.getString("operation_type"))){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (i == 1){
|
|
|
+ userSB.append("<td>");
|
|
|
+ }else{
|
|
|
+ userSB.append("<tr><td>");
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取用户信息
|
|
|
+ Map<String, Object> tokenMap = new HashMap<String, Object>();
|
|
|
+ tokenMap.put("access_token", accessToken);
|
|
|
+ tokenMap.put("userid", ob.getString("userid"));
|
|
|
+ String userStr = HttpHelper.sendGetByHttpUrlConnection("https://oapi.dingtalk.com/user/get", tokenMap, "UTF-8");
|
|
|
+ JSONObject userObject = JSON.parseObject(userStr);
|
|
|
+ userSB.append(userObject.getString("name")).append(blankCode);
|
|
|
+ //获取操作结果
|
|
|
+ if ("EXECUTE_TASK_NORMAL".equals(ob.getString("operation_type"))){
|
|
|
+ userSB.append(dingdingUtil.getTaskResult(ob.getString("operation_result")));
|
|
|
+ if (StringUtils.isNotEmpty(ob.getString("remark"))){
|
|
|
+ userSB.append("(").append(ob.getString("remark")).append(")").append(blankCode);
|
|
|
+ }
|
|
|
+ userSB.append(blankCode);
|
|
|
+ }else if ("ADD_REMARK".equals(ob.getString("operation_type"))){
|
|
|
+ userSB.append("添加评论(").append(ob.getString("remark")).append(")").append(blankCode);
|
|
|
+ }else {
|
|
|
+ userSB.append(dingdingUtil.getTaskResult(ob.getString("operation_result"))).append(blankCode);
|
|
|
+ }
|
|
|
+ userSB.append(ob.getString("date") == null ? "" : ob.getString("date")).append("</td></tr>");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return userSB;
|
|
|
+ }
|
|
|
+
|
|
|
+ private StringBuffer generateForm(JSONObject result) {
|
|
|
+ JSONArray formArray = result.getJSONObject("form_component_values").getJSONArray("form_component_value_vo");
|
|
|
+ StringBuffer formSB = null;
|
|
|
+ if (formArray != null && formArray.size() > 0){
|
|
|
+ formSB = new StringBuffer();
|
|
|
+ for (Object o : formArray){
|
|
|
+ JSONObject ob = (JSONObject) o;
|
|
|
+ // 图片、附件、说明的行不显示
|
|
|
+ if ("图片".equals(ob.getString("name"))
|
|
|
+ || "附件".equals(ob.getString("name"))
|
|
|
+ || "说明".equals(ob.getString("name"))
|
|
|
+ || "null".equals(ob.getString("name"))
|
|
|
+ || null == ob.getString("name")){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 处理表单中表单名是否是json对象,如[开始时间、结束时间]
|
|
|
+ if (dingdingUtil.isJSONValid(ob.getString("name"))){
|
|
|
+ JSONArray array = JSON.parseArray(ob.getString("name"));
|
|
|
+ if (array != null){
|
|
|
+ formSB.append("<tr><td>");
|
|
|
+ for (int i = 0; i < array.size(); i++){
|
|
|
+ formSB.append(array.get(i)).append(i == array.size() - 1 ? "" : "/");
|
|
|
+ }
|
|
|
+ formSB.append("</td><td>");
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ formSB.append("<tr><td>").append(ob.getString("name")).append("</td><td>");
|
|
|
+ }
|
|
|
+ //处理表单中表单名对应的表单值,空值不显示
|
|
|
+ String value = ob.getString("value");
|
|
|
+ if ("null".equals(value)){
|
|
|
+ formSB.append("");
|
|
|
+ //处理表单值是否是json对象
|
|
|
+ }else if (dingdingUtil.isJSONValid(value)){
|
|
|
+ JSONArray array = JSON.parseArray(ob.getString("value"));
|
|
|
+ for (int i = 0; i < array.size(); i++){
|
|
|
+ if (array.get(i) instanceof String || array.get(i) instanceof Integer || array.get(i) instanceof BigDecimal){
|
|
|
+ formSB.append(array.get(i)).append(i == array.size() - 1 ? "" : blankCode);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ JSONObject objecte = (JSONObject)array.get(i);
|
|
|
+ JSONArray rowValue = objecte.getJSONArray("rowValue");
|
|
|
+ if (rowValue != null){
|
|
|
+ for (Object rowObj : rowValue){
|
|
|
+ JSONObject row = (JSONObject)rowObj;
|
|
|
+ formSB.append("<p>");
|
|
|
+ if (dingdingUtil.isJSONValid(row.getString("label"))){
|
|
|
+ JSONArray labelArray = JSON.parseArray(row.getString("label"));
|
|
|
+ if (labelArray != null){
|
|
|
+ for (int j = 0; j < labelArray.size(); j++){
|
|
|
+ formSB.append(labelArray.get(j)).append(j == labelArray.size() - 1 ? "" : "/");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else if ("说明".equals(row.getString("label"))
|
|
|
+ || "null".equals(row.getString("label"))
|
|
|
+ || null == row.getString("label")){
|
|
|
+ formSB.append("</p>");
|
|
|
+ continue;
|
|
|
+ }else{
|
|
|
+ formSB.append(row.getString("label"));
|
|
|
+ }
|
|
|
+ formSB.append(":");
|
|
|
+ if (dingdingUtil.isJSONValid(row.getString("value"))){
|
|
|
+ JSONArray valueArray = JSON.parseArray(row.getString("value"));
|
|
|
+ if (valueArray != null){
|
|
|
+ for (int j = 0; j < valueArray.size(); j++){
|
|
|
+ formSB.append(valueArray.get(j)).append(j == valueArray.size() - 1 ? "" : "/");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ formSB.append(row.getString("value")).append(blankCode);
|
|
|
+ }
|
|
|
+ formSB.append("</p>");
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+// formSB.append("<td><tr>");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (i != array.size() - 1){
|
|
|
+ formSB.append("<p> </p>");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2022-2-23 by owen 钉钉返回的数据会导致解析异常
|
|
|
+// if (ob.getString("ext_value") != null){
|
|
|
+//
|
|
|
+// JSONArray objArr = JSON.parseObject(ob.getString("ext_value")).getJSONArray("statValue");
|
|
|
+//
|
|
|
+// if (objArr.size() > 0){
|
|
|
+// formSB.append("<p> </p>");
|
|
|
+// for (int i = 0; i < objArr.size(); i++){
|
|
|
+// JSONObject objecte = (JSONObject)objArr.get(i);
|
|
|
+// formSB.append(objecte.getString("label")).append(":").append(objecte.getString("num")).append("(").append(objecte.getString("upper")).append(")");
|
|
|
+// if (i != objArr.size() - 1){
|
|
|
+// formSB.append("<p> </p>");
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+ }else{
|
|
|
+ formSB.append(value);
|
|
|
+ }
|
|
|
+ formSB.append("</td></tr>");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return formSB;
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getDetailHtml(String accessToken, JSONObject jsonResult, String type) {
|
|
|
+ StringBuffer sb = new StringBuffer();
|
|
|
+ JSONObject result = jsonResult.getJSONObject("process_instance");
|
|
|
+ if (result != null){
|
|
|
+
|
|
|
+ DataDictionary corp = dataDictionaryService.findByCodeAndDataKey("corp_code", dingdingUtil.getRegion());
|
|
|
+
|
|
|
+ //企业名称
|
|
|
+ String corpName = corp.getDataValue();
|
|
|
+ //申请日期
|
|
|
+ String applyDate = result.getString("create_time");
|
|
|
+ //审批编码
|
|
|
+ String businessId = result.getString("business_id");
|
|
|
+ String[] titles = result.getString("title").split("的");
|
|
|
+ //申请人
|
|
|
+ String applyUserName = titles[0];
|
|
|
+ //模板名称
|
|
|
+ String title = titles[1];
|
|
|
+ //申请人部门
|
|
|
+ String org = result.getString("originator_dept_name");
|
|
|
+
|
|
|
+ sb.append("<!DOCTYPE html> ")
|
|
|
+ .append("<html lang=\"en\">").append("<head>")
|
|
|
+ .append("<meta charset=\"UTF-8\" />")
|
|
|
+ .append("<style> ").append("body{font-family:SimHei;} .content{width: 100%; margin: 0 auto; margin-top: 30px;} h2{text-align:center;} .mgrl-10{margin-left:30px;} table tr{height: 30px;} table td {word-wrap:break-word;word-break:break-all;}").append("</style>")
|
|
|
+ .append("</head>").append("<body>")
|
|
|
+ .append("<div class=\"content\">")
|
|
|
+ .append("<h2>").append(title).append("</h2>")
|
|
|
+ .append("<span>").append(corpName).append("</span>").append(" ").append("<span class=\"mgrl-10\">申请日期:").append(applyDate).append("</span>")
|
|
|
+ .append(" ").append("<span class=\"mgrl-10\" style=\"color: red;\">审批状态:").append(dingdingUtil.getStatus(result.getString("status"))).append("</span>")
|
|
|
+ .append("<table border=\"1\" cellspacing=\"0\" width=100% >")
|
|
|
+ .append("<tr><td style=\"width:20%\">审批编码</td><td>").append(businessId).append("</td></tr>")
|
|
|
+ .append("<tr><td>申请人</td><td>").append(applyUserName).append("</td></tr>")
|
|
|
+ .append("<tr><td>申请人部门</td><td>").append(org).append("</td></tr>");
|
|
|
+
|
|
|
+ //表单内容,循环生成表单内容
|
|
|
+ StringBuffer formSB = generateForm(result);
|
|
|
+ sb.append(formSB);
|
|
|
+
|
|
|
+ //审批人
|
|
|
+ StringBuffer userSB = generateOperators(accessToken, result);
|
|
|
+ sb.append(userSB).append("</table>");
|
|
|
+
|
|
|
+ if ("download".equals(type)){
|
|
|
+ Subject subject = SecurityUtils.getSubject();
|
|
|
+ Object principal = subject.getPrincipal();
|
|
|
+ String userName = "";
|
|
|
+ if (principal != null) {
|
|
|
+ userName = ((User) principal).getNickName();
|
|
|
+ }
|
|
|
+ sb.append("<span>打印时间:").append(new DateTime().toString("yyyy-MM-dd HH:mm")).append("</span> <span class=\"mgrl-10\">打印人:").append(userName).append("</span></div>");
|
|
|
+ }
|
|
|
+ sb.append("</body></html>");
|
|
|
+ }
|
|
|
+ return sb.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+}
|