|
|
@@ -7,6 +7,7 @@ import cn.hutool.log.StaticLog;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.alibaba.nacos.shaded.com.google.common.util.concurrent.ThreadFactoryBuilder;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
|
@@ -95,6 +96,7 @@ import org.springframework.web.context.request.RequestContextHolder;
|
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
+
|
|
|
import javax.annotation.Resource;
|
|
|
import javax.imageio.ImageIO;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
@@ -115,9 +117,7 @@ import java.sql.SQLException;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.List;
|
|
|
import java.util.*;
|
|
|
-import java.util.concurrent.CompletableFuture;
|
|
|
-import java.util.concurrent.ConcurrentHashMap;
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
+import java.util.concurrent.*;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.regex.Matcher;
|
|
|
import java.util.regex.Pattern;
|
|
|
@@ -2818,7 +2818,307 @@ public class ExcelTabController extends BladeController {
|
|
|
toClient.close();
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
+// /**
|
|
|
+// * 日志预览
|
|
|
+// */
|
|
|
+// @GetMapping("/get-the-log-pdfInfo")
|
|
|
+// @ApiOperationSupport(order = 25)
|
|
|
+// @ApiOperation(value = "日志预览")
|
|
|
+// @ApiImplicitParams({
|
|
|
+// @ApiImplicitParam(name = "nodePrimaryKeyId", value = "当前操作的日志类型ID,即左侧列表的节点primaryKeyId"),
|
|
|
+// @ApiImplicitParam(name = "String pkeyId", value = "当前表pKeyId"),
|
|
|
+// @ApiImplicitParam(name = "recordTime", value = "当前选择的填写日期,即右侧日期控件所选日期,格式为 yyyy-MM-dd")
|
|
|
+// })
|
|
|
+// public R<String> getTheLogPdInfo(String pkeyId, String nodePrimaryKeyId, String recordTime, String contractId,Long createUser) throws Exception {
|
|
|
+// //获取配置的路径
|
|
|
+// String file_path = FileUtils.getSysLocalFileUrl();
|
|
|
+// if (StringUtils.isEmpty(recordTime)) {
|
|
|
+// recordTime = DateUtil.format(DateUtil.now(), "yyyy-MM-dd");
|
|
|
+// }
|
|
|
+// List<ContractLog> contractLogList = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId,createUser);
|
|
|
+// List<String> ids = contractLogList.stream().map(ContractLog::getId).map(String::valueOf).collect(Collectors.toList());
|
|
|
+// if (ids.size() > 0) {
|
|
|
+// //PDF路径
|
|
|
+// List<String> pdfUrls = new ArrayList<>();
|
|
|
+//
|
|
|
+// for (String dataId : ids) {
|
|
|
+// //查询对应的html
|
|
|
+// WbsTreePrivate tableNode = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, pkeyId));
|
|
|
+//
|
|
|
+// if (tableNode == null) {
|
|
|
+// return R.fail("该数据下无此节点!");
|
|
|
+// }
|
|
|
+//
|
|
|
+// String htmlString = this.getHtmlString(pkeyId);
|
|
|
+//
|
|
|
+// if (StringUtils.isEmpty(tableNode.getHtmlUrl()) || StringUtils.isEmpty(htmlString)) {
|
|
|
+// return R.fail("未获取到元素表信息!");
|
|
|
+// }
|
|
|
+//
|
|
|
+// // 获取清表信息
|
|
|
+// ExcelTab excelTab = excelTabService.getById(tableNode.getExcelId());
|
|
|
+// if (excelTab == null) {
|
|
|
+// return R.fail("失败");
|
|
|
+// }
|
|
|
+//
|
|
|
+// //获取数据
|
|
|
+// List<Map<String, Object>> businessDataMapList = this.getTheLogBusinessData(dataId, nodePrimaryKeyId, recordTime, contractId).getData();
|
|
|
+// ProjectInfo projectInfo = projectInfoService.getById(tableNode.getProjectId());
|
|
|
+// //处理数据
|
|
|
+// for (Map<String, Object> dataMap : businessDataMapList) {
|
|
|
+// // 获取excel流 和 html流
|
|
|
+// Workbook wb = new Workbook();
|
|
|
+// wb.loadFromMHtml(CommonUtil.getOSSInputStream(excelTab.getFileUrl()));
|
|
|
+// //获取工作表
|
|
|
+// Worksheet sheet = wb.getWorksheets().get(0);
|
|
|
+// Document doc = Jsoup.parse(htmlString);
|
|
|
+// Element table = doc.select("table").first();
|
|
|
+// Elements trs = table.select("tr");
|
|
|
+//
|
|
|
+// //添加标题
|
|
|
+// String sys_isonline = ParamCache.getValue(CommonConstant.SYS_ISONLINE);
|
|
|
+// if ("20".equals(sys_isonline)) { //甬台温
|
|
|
+// CellRange[] columns = sheet.getMergedCells();
|
|
|
+// for (int i = 0; i < columns.length; i++) {
|
|
|
+// CellRange cellRange = columns[i];
|
|
|
+// if (cellRange.getStyle().getFont().getSize() >= 12 && (Func.isNotEmpty(cellRange.getValue2()) || Func.isNotEmpty(cellRange.getValue()))) {
|
|
|
+// String title = projectInfo.getProjectName();
|
|
|
+// if (title.length() >= 30) {
|
|
|
+// cellRange.setRowHeight(40);
|
|
|
+// cellRange.getStyle().setWrapText(true);
|
|
|
+// }
|
|
|
+// cellRange.getStyle().getFont().setSize(18);
|
|
|
+// cellRange.getStyle().setHorizontalAlignment(HorizontalAlignType.Center);
|
|
|
+// cellRange.setText(projectInfo.getProjectName());
|
|
|
+// break;
|
|
|
+// }
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// for (int i = 1; i < 6; i++) {
|
|
|
+// Element tr = trs.get(i);
|
|
|
+// Elements tds = tr.select("td");
|
|
|
+// for (int j = 0; j < tds.size(); j++) {
|
|
|
+// Element data = tds.get(j);
|
|
|
+// String style = data.attr("style");
|
|
|
+// if (style.contains("font-size")) {
|
|
|
+// int fontsize = Integer.parseInt(style.substring(style.indexOf("font-size:") + 10, style.indexOf(".0pt")));
|
|
|
+// if (StringUtils.isNotEmpty(data.text()) && fontsize >= 12) {
|
|
|
+// Element element = trs.get(i - 1).select("td").get(0);
|
|
|
+// String textainfo = element.text();
|
|
|
+// if (textainfo == null || textainfo == "" || Func.isEmpty(textainfo)) {
|
|
|
+// int x1, y1;
|
|
|
+// if ((element.html().indexOf("x1") >= 0 && element.html().indexOf("y1") >= 0) || (element.hasAttr("x1") && element.hasAttr("y1"))) {
|
|
|
+// if (element.html().indexOf("el-tooltip") >= 0) {
|
|
|
+// x1 = Integer.parseInt(element.children().get(0).children().get(0).attr("x1"));
|
|
|
+// y1 = Integer.parseInt(element.children().get(0).children().get(0).attr("y1"));
|
|
|
+// } else {
|
|
|
+// Elements children = element.children();
|
|
|
+// if (children.size() >= 1) {
|
|
|
+// x1 = Integer.parseInt(element.children().get(0).attr("x1"));
|
|
|
+// y1 = Integer.parseInt(element.children().get(0).attr("y1"));
|
|
|
+// } else {
|
|
|
+// x1 = Integer.parseInt(element.attr("x1"));
|
|
|
+// y1 = Integer.parseInt(element.attr("y1"));
|
|
|
+// }
|
|
|
+// }
|
|
|
+// if (x1 == 0) {
|
|
|
+// x1 = 1;
|
|
|
+// }
|
|
|
+// final CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
+// cellRange.setText(projectInfo.getProjectName());
|
|
|
+// }
|
|
|
+// break;
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (ObjectUtil.isNotEmpty(dataMap)) {
|
|
|
+// for (String val : dataMap.keySet()) {
|
|
|
+// boolean flag = false;
|
|
|
+// if (val.indexOf("__") >= 0) {
|
|
|
+// String[] DataVal = val.split("__");
|
|
|
+// String[] xy = DataVal[1].split("_");
|
|
|
+// if (trs.size() > Integer.parseInt(xy[0])) {
|
|
|
+// Element trData = trs.get(Integer.parseInt(xy[0]));
|
|
|
+// Elements tdDatas = trData.select("td");
|
|
|
+// if (tdDatas.size() > Integer.parseInt(xy[1])) {
|
|
|
+// Element data = tdDatas.get(Integer.parseInt(xy[1]));
|
|
|
+// if (data.html().indexOf("date") >= 0) {
|
|
|
+// flag = true;
|
|
|
+// }
|
|
|
+// if (data.html().indexOf("x1") >= 0 && data.html().indexOf("y1") >= 0) {
|
|
|
+// int x1, y1;
|
|
|
+//
|
|
|
+// if (data.html().indexOf("el-tooltip") >= 0) {
|
|
|
+// x1 = Integer.parseInt(data.children().get(0).children().get(0).attr("x1"));
|
|
|
+// y1 = Integer.parseInt(data.children().get(0).children().get(0).attr("y1"));
|
|
|
+// } else {
|
|
|
+// x1 = Integer.parseInt(data.children().get(0).attr("x1"));
|
|
|
+// y1 = Integer.parseInt(data.children().get(0).attr("y1"));
|
|
|
+// }
|
|
|
+// if (x1 == 0) {
|
|
|
+// x1 = 1;
|
|
|
+// }
|
|
|
+// String myData = dataMap.get(val) + "";
|
|
|
+// if (((myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0) || (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0)) && flag) {
|
|
|
+// SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
|
|
+// sdf.setTimeZone(TimeZone.getTimeZone("GTM+8"));
|
|
|
+// SimpleDateFormat formatStr = new SimpleDateFormat("yyyy年MM月dd日");
|
|
|
+// if (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0) {
|
|
|
+// myData = myData.replace("[", "").replace("]", "").replaceAll("'", "");
|
|
|
+// String[] dataVal = myData.split(",");
|
|
|
+// Date Start_dataStr = sdf.parse(dataVal[0]);
|
|
|
+// Date end_dataStr = sdf.parse(dataVal[1]);
|
|
|
+// String StartDate = formatStr.format(Start_dataStr);
|
|
|
+// String endDate = formatStr.format(end_dataStr);
|
|
|
+// if (StartDate.equals(endDate)) {
|
|
|
+// myData = StartDate;
|
|
|
+// } else {
|
|
|
+// myData = StartDate + "-" + endDate;
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// String[] dataStr = myData.split("T")[0].split("-");
|
|
|
+// if (dataStr.length == 3) {
|
|
|
+// myData = StringUtil.format("{}年{}月{}日", dataStr[0], dataStr[1], Integer.parseInt(dataStr[2]));
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// if (myData.indexOf("lang.String") >= 0) {
|
|
|
+// Object obj = dataMap.get(val);
|
|
|
+// if (obj instanceof String[]) {
|
|
|
+// String[] dataDate = (String[]) obj;
|
|
|
+// String HtmlEle = data.toString();
|
|
|
+// if (HtmlEle.indexOf("el-date-picker") >= 0) {//时间时间段处理格式
|
|
|
+// if ((dataDate[0].trim()).equals((dataDate[1].trim()))) {
|
|
|
+// myData = dataDate[0];
|
|
|
+// } else {
|
|
|
+// myData = dataDate[0].replace("\"", "") + "-" + dataDate[1].trim().replace("\"", "");
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// myData = Func.convert(dataDate, String.class).replaceAll(" ", "").replaceAll(",","、");
|
|
|
+// if (myData.startsWith("[") && myData.endsWith("]")) {
|
|
|
+// // 去掉两端的中括号
|
|
|
+// myData=myData.replaceAll("\\[","").replaceAll("]","");
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// if (myData.indexOf("http") >= 0 && (myData.indexOf("aliyuncs") >= 0 || myData.indexOf("183.247.216.148") >= 0)) {
|
|
|
+// Element element = trs.get(y1).select("td").get(x1);
|
|
|
+// String[] styles = element.attr("style").split(";");
|
|
|
+// int Height = 0;
|
|
|
+// for (String sty : styles) {
|
|
|
+// if (sty.indexOf("height:") >= 0) {
|
|
|
+// Height = Integer.parseInt(sty.replace("height:", "").replace("px", ""));
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// BufferedImage image = ImageIO.read(CommonUtil.getOSSInputStream(myData));
|
|
|
+// ExcelPicture pic = sheet.getPictures().add(y1, x1, image);
|
|
|
+// pic.setHeight(Height);
|
|
|
+// sheet.getCellRange(y1, x1).getStyle().setShrinkToFit(true);
|
|
|
+//
|
|
|
+// } else if (data.html().indexOf("hc-form-checkbox-group") >= 0) {
|
|
|
+// CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
+// String exceVal = cellRange.getValue().replaceAll(" ", "");
|
|
|
+// //如果有□ 代表 自动生成 如果没有 代表后期添加 需要显示html 中的值
|
|
|
+// if (exceVal.indexOf("□") >= 0) {
|
|
|
+// if (myData.equals("1")) {
|
|
|
+// cellRange.setValue(exceVal.replace("□", "\u2611"));
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// List<Node> nodes = data.childNodes();
|
|
|
+// Node node = nodes.get(nodes.size() - 1);
|
|
|
+// String dataJson = node.attr(":objs");
|
|
|
+// if (StringUtils.isNotEmpty(dataJson)) {
|
|
|
+// JSONArray jsonArray = JSONArray.parseArray(dataJson);
|
|
|
+// List<Integer> idList = Func.toIntList(myData);
|
|
|
+// int indexx = 0;
|
|
|
+// if (idList.get(0) >= 1) {
|
|
|
+// indexx = idList.get(0) - 1;
|
|
|
+// }
|
|
|
+//
|
|
|
+// String dataInfo = jsonArray.getJSONObject(indexx).getString("name");
|
|
|
+// for (int inx = 1; inx < idList.size(); inx++) {
|
|
|
+// int valIndex = idList.get(inx) - 1;
|
|
|
+// dataInfo = dataInfo + "," + jsonArray.getJSONObject(valIndex).getString("name");
|
|
|
+// }
|
|
|
+// cellRange.setValue(dataInfo);
|
|
|
+// }
|
|
|
+//
|
|
|
+// }
|
|
|
+// } else {
|
|
|
+// final CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
+// cellRange.setText(myData);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+// // 组装电签设置
|
|
|
+// Elements dqids = table.getElementsByAttribute("dqid");
|
|
|
+// for (Element element : dqids) {
|
|
|
+// String dqid = element.attr("dqid");
|
|
|
+// Elements x11 = element.getElementsByAttribute("x1");
|
|
|
+// if (x11 != null && x11.size() >= 1) {
|
|
|
+// Element element1 = x11.get(x11.size() - 1);
|
|
|
+// int x1 = Func.toInt(element1.attr("x1"));
|
|
|
+// int y1 = Func.toInt(element1.attr("y1"));
|
|
|
+//
|
|
|
+// CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
+// if (cellRange != null) {
|
|
|
+// // 创建字体
|
|
|
+// String text = cellRange.getText();
|
|
|
+// if (StringUtil.hasText(text)) {
|
|
|
+// dqid = text + "*" + dqid;
|
|
|
+// }
|
|
|
+// cellRange.setText(dqid);
|
|
|
+// cellRange.getCellStyle().getExcelFont().setSize(1);
|
|
|
+// cellRange.getCellStyle().getExcelFont().setColor(Color.WHITE);
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// Long fileName = SnowFlakeUtil.getId();
|
|
|
+// String onePdfPath = file_path + "/pdf//" + fileName + ".pdf";
|
|
|
+// sheet.saveToPdf(onePdfPath);
|
|
|
+// BladeFile bladeFile = this.newIOSSClient.uploadFile(fileName + ".pdf", onePdfPath);
|
|
|
+// pdfUrls.add(bladeFile.getLink());
|
|
|
+// wb.dispose();
|
|
|
+// }
|
|
|
+// }
|
|
|
+// if (pdfUrls.size() > 0) {
|
|
|
+// try {
|
|
|
+// String mergePdfPath = file_path + "/pdf//" + SnowFlakeUtil.getId() + ".pdf";
|
|
|
+// File oldMergePdf = ResourceUtil.getFile(mergePdfPath);
|
|
|
+// if (oldMergePdf.exists()) {
|
|
|
+// oldMergePdf.delete();
|
|
|
+// }
|
|
|
+// FileUtils.mergePdfPublicMethods(pdfUrls, mergePdfPath);
|
|
|
+// BladeFile mergeFile = this.newIOSSClient.uploadFile(SnowFlakeUtil.getId() + new Date().getTime() + ".pdf", mergePdfPath);
|
|
|
+//
|
|
|
+// //修改记录,当天的日志所有表的合并pdf都一样,即ids都修改成一样的
|
|
|
+// this.contractLogClient.updateTheLogPdfUrlByIds(StringUtils.join(ids, ","), mergeFile.getLink());
|
|
|
+//
|
|
|
+// return R.data(mergeFile.getLink());
|
|
|
+// } catch (Exception e) {
|
|
|
+// e.printStackTrace();
|
|
|
+// return R.fail("数据异常");
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|
|
|
+//
|
|
|
+// return R.data(null);
|
|
|
+// }
|
|
|
+
|
|
|
+ /**
|
|
|
* 日志预览
|
|
|
*/
|
|
|
@GetMapping("/get-the-log-pdfInfo")
|
|
|
@@ -2829,293 +3129,471 @@ public class ExcelTabController extends BladeController {
|
|
|
@ApiImplicitParam(name = "String pkeyId", value = "当前表pKeyId"),
|
|
|
@ApiImplicitParam(name = "recordTime", value = "当前选择的填写日期,即右侧日期控件所选日期,格式为 yyyy-MM-dd")
|
|
|
})
|
|
|
- public R<String> getTheLogPdInfo(String pkeyId, String nodePrimaryKeyId, String recordTime, String contractId,Long createUser) throws Exception {
|
|
|
- //获取配置的路径
|
|
|
+ public R<String> getTheLogPdInfo(
|
|
|
+ String pkeyId, String nodePrimaryKeyId, String recordTime, String contractId, Long createUser) throws Exception {
|
|
|
+ // ========================= 1. 前置参数校验+初始化(仅1次)=========================
|
|
|
String file_path = FileUtils.getSysLocalFileUrl();
|
|
|
- if (StringUtils.isEmpty(recordTime)) {
|
|
|
+ if (StrUtil.isEmpty(recordTime)) {
|
|
|
recordTime = DateUtil.format(DateUtil.now(), "yyyy-MM-dd");
|
|
|
}
|
|
|
- List<ContractLog> contractLogList = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(nodePrimaryKeyId, recordTime, contractId,createUser);
|
|
|
- List<String> ids = contractLogList.stream().map(ContractLog::getId).map(String::valueOf).collect(Collectors.toList());
|
|
|
- if (ids.size() > 0) {
|
|
|
- //PDF路径
|
|
|
- List<String> pdfUrls = new ArrayList<>();
|
|
|
|
|
|
- for (String dataId : ids) {
|
|
|
- //查询对应的html
|
|
|
- WbsTreePrivate tableNode = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, pkeyId));
|
|
|
+ // 获取 ContractLog ID列表(原逻辑不变)
|
|
|
+ List<ContractLog> contractLogList = this.contractLogClient.queryContractLogByPrimaryKeyIdAndRecordTimeList(
|
|
|
+ nodePrimaryKeyId, recordTime, contractId, createUser
|
|
|
+ );
|
|
|
+ if (CollUtil.isEmpty(contractLogList)) {
|
|
|
+ return R.data(null);
|
|
|
+ }
|
|
|
+ List<String> logIds = contractLogList.stream()
|
|
|
+ .map(ContractLog::getId)
|
|
|
+ .map(String::valueOf)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ // ========================= 2. 循环外预加载不变资源(核心优化:避免重复IO/查询)=========================
|
|
|
+ // 2.1 查询Wbs节点+Excel模板(仅1次)
|
|
|
+ WbsTreePrivate tableNode = this.wbsTreePrivateService.getOne(
|
|
|
+ Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, pkeyId)
|
|
|
+ );
|
|
|
+ if (tableNode == null) {
|
|
|
+ return R.fail("该数据下无此节点!");
|
|
|
+ }
|
|
|
+ ExcelTab excelTab = excelTabService.getById(tableNode.getExcelId());
|
|
|
+ if (excelTab == null) {
|
|
|
+ return R.fail("未找到Excel模板!");
|
|
|
+ }
|
|
|
|
|
|
- if (tableNode == null) {
|
|
|
- return R.fail("该数据下无此节点!");
|
|
|
- }
|
|
|
+ // 2.2 缓存Excel模板(字节流,仅1次OSS下载)
|
|
|
+ byte[] excelTemplateBytes = downloadOssToBytes(excelTab.getFileUrl());
|
|
|
+ if (excelTemplateBytes == null) {
|
|
|
+ return R.fail("Excel模板下载失败!");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2.3 缓存HTML模板+DOM解析结果(仅1次下载+解析)
|
|
|
+ String htmlString = this.getHtmlString(pkeyId);
|
|
|
+ if (StrUtil.isEmpty(tableNode.getHtmlUrl()) || StrUtil.isEmpty(htmlString)) {
|
|
|
+ return R.fail("未获取到元素表信息!");
|
|
|
+ }
|
|
|
+ Document htmlDoc = Jsoup.parse(htmlString);
|
|
|
+ Element table = htmlDoc.select("table").first();
|
|
|
+ if (table == null) {
|
|
|
+ return R.fail("HTML中未找到表格!");
|
|
|
+ }
|
|
|
+ Elements trs = table.select("tr");
|
|
|
+ Map<String, int[]> dqIdXYMap = preloadDqIdMap(table); // 预缓存电签坐标
|
|
|
+
|
|
|
+ // 2.4 预查询公共数据(仅1次)
|
|
|
+ ProjectInfo projectInfo = projectInfoService.getById(tableNode.getProjectId());
|
|
|
+ // 日期格式化器(线程不安全,单线程复用)
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
|
|
+ sdf.setTimeZone(TimeZone.getTimeZone("GMT+8")); // 修复原拼写错误(GTM→GMT)
|
|
|
+ SimpleDateFormat formatStr = new SimpleDateFormat("yyyy年MM月dd日");
|
|
|
+ String sysIsonline = ParamCache.getValue(CommonConstant.SYS_ISONLINE);
|
|
|
+
|
|
|
+ // ========================= 3. 批量查询业务数据(1次查询替代N次)=========================
|
|
|
+ R<List<Map<String, Object>>> batchDataR = this.getTheLogBusinessData(String.join( ",", logIds), nodePrimaryKeyId, recordTime, contractId);
|
|
|
+ if (CollUtil.isEmpty(batchDataR.getData())) {
|
|
|
+ return R.data(null);
|
|
|
+ }
|
|
|
+ List<Map<String, Object>> businessDataMapList = batchDataR.getData();
|
|
|
+
|
|
|
+ // ========================= 4. 异步生成单个PDF(核心优化:并行处理,提升吞吐量)=========================
|
|
|
+ // 线程池(核心数=CPU核心数*2,避免资源耗尽)
|
|
|
+ ExecutorService pdfGenerateExecutor = new ThreadPoolExecutor(
|
|
|
+ Runtime.getRuntime().availableProcessors() * 2,
|
|
|
+ Runtime.getRuntime().availableProcessors() * 4,
|
|
|
+ 60L, TimeUnit.SECONDS,
|
|
|
+ new LinkedBlockingQueue<>(100),
|
|
|
+ new ThreadFactoryBuilder().setNameFormat("pdf-generate-pool-%d").build()
|
|
|
+ );
|
|
|
+
|
|
|
+ List<Future<String>> pdfLocalPathFutures = new ArrayList<>(businessDataMapList.size());
|
|
|
+ for (Map<String, Object> dataMap : businessDataMapList) {
|
|
|
+ if (CollUtil.isEmpty(dataMap)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 提交异步任务:生成单个PDF到本地
|
|
|
+ pdfLocalPathFutures.add(pdfGenerateExecutor.submit(() -> {
|
|
|
+ Workbook wb = null;
|
|
|
+ try {
|
|
|
+ // 从缓存字节流创建Excel(无OSS重复下载)
|
|
|
+ wb = new Workbook();
|
|
|
+ wb.loadFromMHtml(new ByteArrayInputStream(excelTemplateBytes));
|
|
|
+ Worksheet sheet = wb.getWorksheets().get(0);
|
|
|
+
|
|
|
+ // 添加项目标题(复用预解析的trs)
|
|
|
+ addProjectTitle(sheet, trs, projectInfo, sysIsonline);
|
|
|
+
|
|
|
+ // 填充业务数据(复用DOM缓存和格式化器)
|
|
|
+ fillBusinessData(sheet, trs, dataMap, sdf, formatStr);
|
|
|
|
|
|
- String htmlString = this.getHtmlString(pkeyId);
|
|
|
+ // 填充电签信息(复用预缓存的dqIdXYMap)
|
|
|
+ fillDqInfo(sheet, dqIdXYMap);
|
|
|
|
|
|
- if (StringUtils.isEmpty(tableNode.getHtmlUrl()) || StringUtils.isEmpty(htmlString)) {
|
|
|
- return R.fail("未获取到元素表信息!");
|
|
|
+ // 生成本地PDF(临时文件)
|
|
|
+ Long fileName = SnowFlakeUtil.getId();
|
|
|
+ String localPdfPath = file_path + "/pdf//" + fileName + ".pdf";
|
|
|
+ sheet.saveToPdf(localPdfPath);
|
|
|
+ return localPdfPath;
|
|
|
+ } finally {
|
|
|
+ if (wb != null) {
|
|
|
+ wb.dispose(); // 释放资源
|
|
|
+ }
|
|
|
}
|
|
|
+ }));
|
|
|
+ }
|
|
|
|
|
|
- // 获取清表信息
|
|
|
- ExcelTab excelTab = excelTabService.getById(tableNode.getExcelId());
|
|
|
- if (excelTab == null) {
|
|
|
- return R.fail("失败");
|
|
|
+ // 等待所有单个PDF生成完成,收集本地路径
|
|
|
+ List<String> localPdfPaths = new ArrayList<>();
|
|
|
+ try {
|
|
|
+ for (Future<String> future : pdfLocalPathFutures) {
|
|
|
+ String localPath = future.get(10, TimeUnit.MINUTES); // 单个PDF生成超时控制
|
|
|
+ if (StrUtil.isNotEmpty(localPath) && FileUtils.exist(localPath)) {
|
|
|
+ localPdfPaths.add(localPath);
|
|
|
}
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ return R.fail("PDF生成异常");
|
|
|
+ } finally {
|
|
|
+ pdfGenerateExecutor.shutdown(); // 关闭线程池
|
|
|
+ }
|
|
|
|
|
|
- //获取数据
|
|
|
- List<Map<String, Object>> businessDataMapList = this.getTheLogBusinessData(dataId, nodePrimaryKeyId, recordTime, contractId).getData();
|
|
|
- ProjectInfo projectInfo = projectInfoService.getById(tableNode.getProjectId());
|
|
|
- //处理数据
|
|
|
- for (Map<String, Object> dataMap : businessDataMapList) {
|
|
|
- // 获取excel流 和 html流
|
|
|
- Workbook wb = new Workbook();
|
|
|
- wb.loadFromMHtml(CommonUtil.getOSSInputStream(excelTab.getFileUrl()));
|
|
|
- //获取工作表
|
|
|
- Worksheet sheet = wb.getWorksheets().get(0);
|
|
|
- Document doc = Jsoup.parse(htmlString);
|
|
|
- Element table = doc.select("table").first();
|
|
|
- Elements trs = table.select("tr");
|
|
|
-
|
|
|
- //添加标题
|
|
|
- String sys_isonline = ParamCache.getValue(CommonConstant.SYS_ISONLINE);
|
|
|
- if ("20".equals(sys_isonline)) { //甬台温
|
|
|
- CellRange[] columns = sheet.getMergedCells();
|
|
|
- for (int i = 0; i < columns.length; i++) {
|
|
|
- CellRange cellRange = columns[i];
|
|
|
- if (cellRange.getStyle().getFont().getSize() >= 12 && (Func.isNotEmpty(cellRange.getValue2()) || Func.isNotEmpty(cellRange.getValue()))) {
|
|
|
- String title = projectInfo.getProjectName();
|
|
|
- if (title.length() >= 30) {
|
|
|
- cellRange.setRowHeight(40);
|
|
|
- cellRange.getStyle().setWrapText(true);
|
|
|
- }
|
|
|
- cellRange.getStyle().getFont().setSize(18);
|
|
|
- cellRange.getStyle().setHorizontalAlignment(HorizontalAlignType.Center);
|
|
|
- cellRange.setText(projectInfo.getProjectName());
|
|
|
+ if (CollUtil.isEmpty(localPdfPaths)) {
|
|
|
+ return R.data(null);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ========================= 5. 合并PDF+上传OSS(本地合并后单次上传,避免多次下载)=========================
|
|
|
+ String mergePdfName = SnowFlakeUtil.getId() + "_" + System.currentTimeMillis() + ".pdf";
|
|
|
+ String mergePdfLocalPath = file_path + "/pdf//" + mergePdfName;
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 合并本地PDF(无需下载OSS文件,直接操作本地文件,效率更高)
|
|
|
+ FileUtils.mergePdfPublicMethods(localPdfPaths, mergePdfLocalPath);
|
|
|
+
|
|
|
+ // 上传合并后的PDF到OSS
|
|
|
+ BladeFile mergeFile = this.newIOSSClient.uploadFile(mergePdfName, mergePdfLocalPath);
|
|
|
+ String mergePdfUrl = mergeFile.getLink();
|
|
|
+
|
|
|
+ // 更新ContractLog的PDF链接(批量更新,避免循环调用)
|
|
|
+ this.contractLogClient.updateTheLogPdfUrlByIds(StringUtils.join(logIds, ","), mergePdfUrl);
|
|
|
+
|
|
|
+ return R.data(mergePdfUrl);
|
|
|
+ } catch (Exception e) {
|
|
|
+ return R.fail("数据异常");
|
|
|
+ } finally {
|
|
|
+ // 清理临时文件(单个PDF+合并后的PDF)
|
|
|
+ localPdfPaths.forEach(FileUtils::del);
|
|
|
+ FileUtils.del(mergePdfLocalPath);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 预缓存电签坐标(仅解析1次DOM)
|
|
|
+ */
|
|
|
+ private Map<String, int[]> preloadDqIdMap(Element table) {
|
|
|
+ Map<String, int[]> dqIdXYMap = new HashMap<>();
|
|
|
+ Elements dqids = table.getElementsByAttribute("dqid");
|
|
|
+ for (Element element : dqids) {
|
|
|
+ String dqid = element.attr("dqid");
|
|
|
+ Elements x1Elements = element.getElementsByAttribute("x1");
|
|
|
+ if (CollUtil.isNotEmpty(x1Elements)) {
|
|
|
+ Element lastX1 = x1Elements.get(x1Elements.size() - 1);
|
|
|
+ int x1 = Func.toInt(lastX1.attr("x1"), 1);
|
|
|
+ int y1 = Func.toInt(lastX1.attr("y1"), 0);
|
|
|
+ dqIdXYMap.put(dqid, new int[]{x1, y1});
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return dqIdXYMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * OSS文件下载为字节数组(仅1次下载,缓存复用)
|
|
|
+ */
|
|
|
+ private byte[] downloadOssToBytes(String ossUrl) {
|
|
|
+ try (InputStream ossIs = CommonUtil.getOSSInputStream(ossUrl);
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
|
|
+ IoUtil.copy(ossIs, baos);
|
|
|
+ return baos.toByteArray();
|
|
|
+ } catch (Exception e) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统一添加项目标题(消除重复逻辑)
|
|
|
+ */
|
|
|
+ private void addProjectTitle(Worksheet sheet, Elements trs, ProjectInfo projectInfo, String sysIsonline) {
|
|
|
+ if (projectInfo == null || StrUtil.isEmpty(projectInfo.getProjectName())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if ("20".equals(sysIsonline)) { // 甬台温
|
|
|
+ CellRange[] columns = sheet.getMergedCells();
|
|
|
+ for (CellRange cellRange : columns) {
|
|
|
+ if (cellRange.getStyle().getFont().getSize() >= 12 && Func.isNotEmpty(cellRange.getValue2())) {
|
|
|
+ String projectName = projectInfo.getProjectName();
|
|
|
+ if (projectName.length() >= 30) {
|
|
|
+ cellRange.setRowHeight(40);
|
|
|
+ cellRange.getStyle().setWrapText(true);
|
|
|
+ }
|
|
|
+ cellRange.getStyle().getFont().setSize(18);
|
|
|
+ cellRange.getStyle().setHorizontalAlignment(HorizontalAlignType.Center);
|
|
|
+ cellRange.setText(projectName);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ boolean titleSet = false;
|
|
|
+ for (int i = 1; i < Math.min(6, trs.size()) && !titleSet; i++) {
|
|
|
+ Element tr = trs.get(i);
|
|
|
+ Elements tds = tr.select("td");
|
|
|
+ for (Element td : tds) {
|
|
|
+ String style = td.attr("style");
|
|
|
+ if (style.contains("font-size")) {
|
|
|
+ int fontsize = Integer.parseInt(style.substring(style.indexOf("font-size:") + 10, style.indexOf(".0pt")));
|
|
|
+ if (StrUtil.isNotEmpty(td.text()) && fontsize >= 12) {
|
|
|
+ Element prevTd = trs.get(i - 1).select("td").get(0);
|
|
|
+ if (Func.isEmpty(prevTd.text())) {
|
|
|
+ int[] xy = parseXyFromElement(prevTd);
|
|
|
+ sheet.getCellRange(xy[1], xy[0]).setText(projectInfo.getProjectName());
|
|
|
+ titleSet = true;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- } else {
|
|
|
- for (int i = 1; i < 6; i++) {
|
|
|
- Element tr = trs.get(i);
|
|
|
- Elements tds = tr.select("td");
|
|
|
- for (int j = 0; j < tds.size(); j++) {
|
|
|
- Element data = tds.get(j);
|
|
|
- String style = data.attr("style");
|
|
|
- if (style.contains("font-size")) {
|
|
|
- int fontsize = Integer.parseInt(style.substring(style.indexOf("font-size:") + 10, style.indexOf(".0pt")));
|
|
|
- if (StringUtils.isNotEmpty(data.text()) && fontsize >= 12) {
|
|
|
- Element element = trs.get(i - 1).select("td").get(0);
|
|
|
- String textainfo = element.text();
|
|
|
- if (textainfo == null || textainfo == "" || Func.isEmpty(textainfo)) {
|
|
|
- int x1, y1;
|
|
|
- if ((element.html().indexOf("x1") >= 0 && element.html().indexOf("y1") >= 0) || (element.hasAttr("x1") && element.hasAttr("y1"))) {
|
|
|
- if (element.html().indexOf("el-tooltip") >= 0) {
|
|
|
- x1 = Integer.parseInt(element.children().get(0).children().get(0).attr("x1"));
|
|
|
- y1 = Integer.parseInt(element.children().get(0).children().get(0).attr("y1"));
|
|
|
- } else {
|
|
|
- Elements children = element.children();
|
|
|
- if (children.size() >= 1) {
|
|
|
- x1 = Integer.parseInt(element.children().get(0).attr("x1"));
|
|
|
- y1 = Integer.parseInt(element.children().get(0).attr("y1"));
|
|
|
- } else {
|
|
|
- x1 = Integer.parseInt(element.attr("x1"));
|
|
|
- y1 = Integer.parseInt(element.attr("y1"));
|
|
|
- }
|
|
|
- }
|
|
|
- if (x1 == 0) {
|
|
|
- x1 = 1;
|
|
|
- }
|
|
|
- final CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
- cellRange.setText(projectInfo.getProjectName());
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (ObjectUtil.isNotEmpty(dataMap)) {
|
|
|
- for (String val : dataMap.keySet()) {
|
|
|
- boolean flag = false;
|
|
|
- if (val.indexOf("__") >= 0) {
|
|
|
- String[] DataVal = val.split("__");
|
|
|
- String[] xy = DataVal[1].split("_");
|
|
|
- if (trs.size() > Integer.parseInt(xy[0])) {
|
|
|
- Element trData = trs.get(Integer.parseInt(xy[0]));
|
|
|
- Elements tdDatas = trData.select("td");
|
|
|
- if (tdDatas.size() > Integer.parseInt(xy[1])) {
|
|
|
- Element data = tdDatas.get(Integer.parseInt(xy[1]));
|
|
|
- if (data.html().indexOf("date") >= 0) {
|
|
|
- flag = true;
|
|
|
- }
|
|
|
- if (data.html().indexOf("x1") >= 0 && data.html().indexOf("y1") >= 0) {
|
|
|
- int x1, y1;
|
|
|
+ /**
|
|
|
+ * 解析元素的x1、y1坐标(复用逻辑)
|
|
|
+ */
|
|
|
+ private int[] parseXyFromElement(Element element) {
|
|
|
+ int x1 = 1, y1 = 0;
|
|
|
+ if (element.html().indexOf("x1") >= 0 && element.html().indexOf("y1") >= 0) {
|
|
|
+ if (element.html().indexOf("el-tooltip") >= 0) {
|
|
|
+ x1 = Func.toInt(element.children().get(0).children().get(0).attr("x1"), 1);
|
|
|
+ y1 = Func.toInt(element.children().get(0).children().get(0).attr("y1"), 0);
|
|
|
+ } else {
|
|
|
+ Elements children = element.children();
|
|
|
+ if (CollUtil.isNotEmpty(children)) {
|
|
|
+ x1 = Func.toInt(children.get(0).attr("x1"), 1);
|
|
|
+ y1 = Func.toInt(children.get(0).attr("y1"), 0);
|
|
|
+ } else {
|
|
|
+ x1 = Func.toInt(element.attr("x1"), 1);
|
|
|
+ y1 = Func.toInt(element.attr("y1"), 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return new int[]{x1, y1};
|
|
|
+ }
|
|
|
|
|
|
- if (data.html().indexOf("el-tooltip") >= 0) {
|
|
|
- x1 = Integer.parseInt(data.children().get(0).children().get(0).attr("x1"));
|
|
|
- y1 = Integer.parseInt(data.children().get(0).children().get(0).attr("y1"));
|
|
|
- } else {
|
|
|
- x1 = Integer.parseInt(data.children().get(0).attr("x1"));
|
|
|
- y1 = Integer.parseInt(data.children().get(0).attr("y1"));
|
|
|
- }
|
|
|
- if (x1 == 0) {
|
|
|
- x1 = 1;
|
|
|
- }
|
|
|
- String myData = dataMap.get(val) + "";
|
|
|
- if (((myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0) || (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0)) && flag) {
|
|
|
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
|
|
- sdf.setTimeZone(TimeZone.getTimeZone("GTM+8"));
|
|
|
- SimpleDateFormat formatStr = new SimpleDateFormat("yyyy年MM月dd日");
|
|
|
- if (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0) {
|
|
|
- myData = myData.replace("[", "").replace("]", "").replaceAll("'", "");
|
|
|
- String[] dataVal = myData.split(",");
|
|
|
- Date Start_dataStr = sdf.parse(dataVal[0]);
|
|
|
- Date end_dataStr = sdf.parse(dataVal[1]);
|
|
|
- String StartDate = formatStr.format(Start_dataStr);
|
|
|
- String endDate = formatStr.format(end_dataStr);
|
|
|
- if (StartDate.equals(endDate)) {
|
|
|
- myData = StartDate;
|
|
|
- } else {
|
|
|
- myData = StartDate + "-" + endDate;
|
|
|
- }
|
|
|
- } else {
|
|
|
- String[] dataStr = myData.split("T")[0].split("-");
|
|
|
- if (dataStr.length == 3) {
|
|
|
- myData = StringUtil.format("{}年{}月{}日", dataStr[0], dataStr[1], Integer.parseInt(dataStr[2]));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- if (myData.indexOf("lang.String") >= 0) {
|
|
|
- Object obj = dataMap.get(val);
|
|
|
- if (obj instanceof String[]) {
|
|
|
- String[] dataDate = (String[]) obj;
|
|
|
- String HtmlEle = data.toString();
|
|
|
- if (HtmlEle.indexOf("el-date-picker") >= 0) {//时间时间段处理格式
|
|
|
- if ((dataDate[0].trim()).equals((dataDate[1].trim()))) {
|
|
|
- myData = dataDate[0];
|
|
|
- } else {
|
|
|
- myData = dataDate[0].replace("\"", "") + "-" + dataDate[1].trim().replace("\"", "");
|
|
|
- }
|
|
|
- } else {
|
|
|
- myData = Func.convert(dataDate, String.class).replaceAll(" ", "").replaceAll(",","、");
|
|
|
- if (myData.startsWith("[") && myData.endsWith("]")) {
|
|
|
- // 去掉两端的中括号
|
|
|
- myData=myData.replaceAll("\\[","").replaceAll("]","");
|
|
|
- }
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 填充业务数据(复用缓存和工具类)
|
|
|
+ */
|
|
|
+ private void fillBusinessData(Worksheet sheet, Elements trs, Map<String, Object> dataMap, SimpleDateFormat sdf, SimpleDateFormat formatStr) {
|
|
|
+ for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
|
|
|
+ String val = entry.getKey();
|
|
|
+ if (!val.contains("__")) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
- }
|
|
|
+ // 解析key中的坐标(仅split一次)
|
|
|
+ String[] dataVal = val.split("__");
|
|
|
+ if (dataVal.length < 2) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String[] xy = dataVal[1].split("_");
|
|
|
+ if (xy.length < 2) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ int trIndex = Func.toInt(xy[0], -1);
|
|
|
+ int tdIndex = Func.toInt(xy[1], -1);
|
|
|
+ if (trIndex < 0 || tdIndex < 0 || trIndex >= trs.size()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- if (myData.indexOf("http") >= 0 && (myData.indexOf("aliyuncs") >= 0 || myData.indexOf("183.247.216.148") >= 0)) {
|
|
|
- Element element = trs.get(y1).select("td").get(x1);
|
|
|
- String[] styles = element.attr("style").split(";");
|
|
|
- int Height = 0;
|
|
|
- for (String sty : styles) {
|
|
|
- if (sty.indexOf("height:") >= 0) {
|
|
|
- Height = Integer.parseInt(sty.replace("height:", "").replace("px", ""));
|
|
|
- }
|
|
|
- }
|
|
|
+ Element trData = trs.get(trIndex);
|
|
|
+ Elements tdDatas = trData.select("td");
|
|
|
+ if (tdIndex >= tdDatas.size()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ Element dataTd = tdDatas.get(tdIndex);
|
|
|
|
|
|
- BufferedImage image = ImageIO.read(CommonUtil.getOSSInputStream(myData));
|
|
|
- ExcelPicture pic = sheet.getPictures().add(y1, x1, image);
|
|
|
- pic.setHeight(Height);
|
|
|
- sheet.getCellRange(y1, x1).getStyle().setShrinkToFit(true);
|
|
|
-
|
|
|
- } else if (data.html().indexOf("hc-form-checkbox-group") >= 0) {
|
|
|
- CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
- String exceVal = cellRange.getValue().replaceAll(" ", "");
|
|
|
- //如果有□ 代表 自动生成 如果没有 代表后期添加 需要显示html 中的值
|
|
|
- if (exceVal.indexOf("□") >= 0) {
|
|
|
- if (myData.equals("1")) {
|
|
|
- cellRange.setValue(exceVal.replace("□", "\u2611"));
|
|
|
- }
|
|
|
- } else {
|
|
|
- List<Node> nodes = data.childNodes();
|
|
|
- Node node = nodes.get(nodes.size() - 1);
|
|
|
- String dataJson = node.attr(":objs");
|
|
|
- if (StringUtils.isNotEmpty(dataJson)) {
|
|
|
- JSONArray jsonArray = JSONArray.parseArray(dataJson);
|
|
|
- List<Integer> idList = Func.toIntList(myData);
|
|
|
- int indexx = 0;
|
|
|
- if (idList.get(0) >= 1) {
|
|
|
- indexx = idList.get(0) - 1;
|
|
|
- }
|
|
|
+ // 缓存关键属性
|
|
|
+ boolean isDateComponent = dataTd.html().indexOf("date") >= 0;
|
|
|
+ boolean hasXy = dataTd.html().indexOf("x1") >= 0 && dataTd.html().indexOf("y1") >= 0;
|
|
|
+ if (!hasXy) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
|
|
|
- String dataInfo = jsonArray.getJSONObject(indexx).getString("name");
|
|
|
- for (int inx = 1; inx < idList.size(); inx++) {
|
|
|
- int valIndex = idList.get(inx) - 1;
|
|
|
- dataInfo = dataInfo + "," + jsonArray.getJSONObject(valIndex).getString("name");
|
|
|
- }
|
|
|
- cellRange.setValue(dataInfo);
|
|
|
- }
|
|
|
+ int[] xyArr = parseXyFromElement(dataTd);
|
|
|
+ int x1 = xyArr[0], y1 = xyArr[1];
|
|
|
+ String myData = Func.toStr(entry.getValue(), "");
|
|
|
|
|
|
- }
|
|
|
- } else {
|
|
|
- final CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
- cellRange.setText(myData);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ // 日期格式处理(复用格式化器)
|
|
|
+ if (((myData.contains("T") && myData.contains("-")) || (myData.contains(",") && myData.contains("]"))) && isDateComponent) {
|
|
|
+ myData = formatDate(myData, sdf, formatStr);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 字符串数组处理
|
|
|
+ if (myData.contains("lang.String")) {
|
|
|
+ myData = handleStringArray(myData, dataTd);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 图片处理
|
|
|
+ if (myData.startsWith("http") && (myData.contains("aliyuncs") || myData.contains("183.247.216.148"))) {
|
|
|
+ handleImage(sheet, trs, x1, y1, myData);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 复选框组处理
|
|
|
+ if (dataTd.html().indexOf("hc-form-checkbox-group") >= 0) {
|
|
|
+ handleCheckboxGroup(sheet, dataTd, x1, y1, myData);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 普通文本填充
|
|
|
+ sheet.getCellRange(y1, x1).setText(myData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 日期格式化(复用方法)
|
|
|
+ */
|
|
|
+ private String formatDate(String myData, SimpleDateFormat sdf, SimpleDateFormat formatStr) {
|
|
|
+ try {
|
|
|
+ if (myData.contains(",") && myData.contains("]")) {
|
|
|
+ myData = myData.replace("[", "").replace("]", "").replaceAll("'", "");
|
|
|
+ String[] dateArr = myData.split(",");
|
|
|
+ if (dateArr.length >= 2) {
|
|
|
+ Date start = sdf.parse(dateArr[0].trim());
|
|
|
+ Date end = sdf.parse(dateArr[1].trim());
|
|
|
+ String startStr = formatStr.format(start);
|
|
|
+ String endStr = formatStr.format(end);
|
|
|
+ return startStr.equals(endStr) ? startStr : startStr + "-" + endStr;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ String[] dateStr = myData.split("T")[0].split("-");
|
|
|
+ if (dateStr.length == 3) {
|
|
|
+ return StrUtil.format("{}年{}月{}日", dateStr[0], dateStr[1], Integer.parseInt(dateStr[2]));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ return myData;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 字符串数组处理(复用方法)
|
|
|
+ */
|
|
|
+ private String handleStringArray(String myData, Element dataTd) {
|
|
|
+ Object obj = dataTd.data();
|
|
|
+ if (obj instanceof String[]) {
|
|
|
+ String[] dataArr = (String[]) obj;
|
|
|
+ if (dataTd.html().indexOf("el-date-picker") >= 0) {
|
|
|
+ if (dataArr.length >= 2 && dataArr[0].trim().equals(dataArr[1].trim())) {
|
|
|
+ return dataArr[0].replace("\"", "");
|
|
|
+ } else {
|
|
|
+ return dataArr[0].replace("\"", "") + "-" + dataArr[1].trim().replace("\"", "");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return Arrays.stream(dataArr)
|
|
|
+ .collect(Collectors.joining("、"))
|
|
|
+ .replaceAll("\\[|]", "")
|
|
|
+ .replaceAll(" ", "");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return myData;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 图片处理(复用方法)
|
|
|
+ */
|
|
|
+ private void handleImage(Worksheet sheet, Elements trs, int x1, int y1, String imageUrl) {
|
|
|
+ try {
|
|
|
+ // 解析单元格高度
|
|
|
+ Element td = trs.get(y1).select("td").get(x1);
|
|
|
+ int height = 0;
|
|
|
+ String style = td.attr("style");
|
|
|
+ if (StrUtil.isNotEmpty(style)) {
|
|
|
+ for (String sty : style.split(";")) {
|
|
|
+ if (sty.contains("height:")) {
|
|
|
+ height = Func.toInt(sty.replace("height:", "").replace("px", ""), 0);
|
|
|
+ break;
|
|
|
}
|
|
|
- // 组装电签设置
|
|
|
- Elements dqids = table.getElementsByAttribute("dqid");
|
|
|
- for (Element element : dqids) {
|
|
|
- String dqid = element.attr("dqid");
|
|
|
- Elements x11 = element.getElementsByAttribute("x1");
|
|
|
- if (x11 != null && x11.size() >= 1) {
|
|
|
- Element element1 = x11.get(x11.size() - 1);
|
|
|
- int x1 = Func.toInt(element1.attr("x1"));
|
|
|
- int y1 = Func.toInt(element1.attr("y1"));
|
|
|
-
|
|
|
- CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
- if (cellRange != null) {
|
|
|
- // 创建字体
|
|
|
- String text = cellRange.getText();
|
|
|
- if (StringUtil.hasText(text)) {
|
|
|
- dqid = text + "*" + dqid;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 下载图片并插入Excel
|
|
|
+ try (InputStream imgIs = CommonUtil.getOSSInputStream(imageUrl)) {
|
|
|
+ BufferedImage image = ImageIO.read(imgIs);
|
|
|
+ ExcelPicture pic = sheet.getPictures().add(y1, x1, image);
|
|
|
+ if (height > 0) {
|
|
|
+ pic.setHeight(height);
|
|
|
+ }
|
|
|
+ sheet.getCellRange(y1, x1).getStyle().setShrinkToFit(true);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 复选框组处理(复用方法)
|
|
|
+ */
|
|
|
+ private void handleCheckboxGroup(Worksheet sheet, Element dataTd, int x1, int y1, String myData) {
|
|
|
+ CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
+ String excelVal = Func.toStr(cellRange.getValue(), "").replaceAll(" ", "");
|
|
|
+ if (excelVal.contains("□")) {
|
|
|
+ if ("1".equals(myData)) {
|
|
|
+ cellRange.setValue(excelVal.replace("□", "\u2611"));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ List<Node> nodes = dataTd.childNodes();
|
|
|
+ if (CollUtil.isNotEmpty(nodes)) {
|
|
|
+ Node lastNode = nodes.get(nodes.size() - 1);
|
|
|
+ String dataJson = lastNode.attr(":objs");
|
|
|
+ if (StrUtil.isNotEmpty(dataJson)) {
|
|
|
+ JSONArray jsonArray = JSONArray.parseArray(dataJson);
|
|
|
+ List<Integer> idList = Func.toIntList(myData);
|
|
|
+ if (CollUtil.isNotEmpty(idList) && jsonArray.size() > 0) {
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ for (int id : idList) {
|
|
|
+ int idx = id - 1;
|
|
|
+ if (idx >= 0 && idx < jsonArray.size()) {
|
|
|
+ if (sb.length() > 0) {
|
|
|
+ sb.append(",");
|
|
|
}
|
|
|
- cellRange.setText(dqid);
|
|
|
- cellRange.getCellStyle().getExcelFont().setSize(1);
|
|
|
- cellRange.getCellStyle().getExcelFont().setColor(Color.WHITE);
|
|
|
+ sb.append(jsonArray.getJSONObject(idx).getString("name"));
|
|
|
}
|
|
|
}
|
|
|
+ cellRange.setValue(sb.toString());
|
|
|
}
|
|
|
-
|
|
|
- Long fileName = SnowFlakeUtil.getId();
|
|
|
- String onePdfPath = file_path + "/pdf//" + fileName + ".pdf";
|
|
|
- sheet.saveToPdf(onePdfPath);
|
|
|
- BladeFile bladeFile = this.newIOSSClient.uploadFile(fileName + ".pdf", onePdfPath);
|
|
|
- pdfUrls.add(bladeFile.getLink());
|
|
|
- wb.dispose();
|
|
|
}
|
|
|
}
|
|
|
- if (pdfUrls.size() > 0) {
|
|
|
- try {
|
|
|
- String mergePdfPath = file_path + "/pdf//" + SnowFlakeUtil.getId() + ".pdf";
|
|
|
- File oldMergePdf = ResourceUtil.getFile(mergePdfPath);
|
|
|
- if (oldMergePdf.exists()) {
|
|
|
- oldMergePdf.delete();
|
|
|
- }
|
|
|
- FileUtils.mergePdfPublicMethods(pdfUrls, mergePdfPath);
|
|
|
- BladeFile mergeFile = this.newIOSSClient.uploadFile(SnowFlakeUtil.getId() + new Date().getTime() + ".pdf", mergePdfPath);
|
|
|
-
|
|
|
- //修改记录,当天的日志所有表的合并pdf都一样,即ids都修改成一样的
|
|
|
- this.contractLogClient.updateTheLogPdfUrlByIds(StringUtils.join(ids, ","), mergeFile.getLink());
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return R.data(mergeFile.getLink());
|
|
|
- } catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
- return R.fail("数据异常");
|
|
|
+ /**
|
|
|
+ * 填充电签信息(复用预缓存的坐标)
|
|
|
+ */
|
|
|
+ private void fillDqInfo(Worksheet sheet, Map<String, int[]> dqIdXYMap) {
|
|
|
+ for (Map.Entry<String, int[]> entry : dqIdXYMap.entrySet()) {
|
|
|
+ String dqid = entry.getKey();
|
|
|
+ int[] xy = entry.getValue();
|
|
|
+ int x1 = xy[0], y1 = xy[1];
|
|
|
+
|
|
|
+ CellRange cellRange = sheet.getCellRange(y1, x1);
|
|
|
+ if (cellRange != null) {
|
|
|
+ String text = cellRange.getText();
|
|
|
+ if (StringUtils.isNotEmpty( text)) {
|
|
|
+ dqid = text + "*" + dqid;
|
|
|
}
|
|
|
+ cellRange.setText(dqid);
|
|
|
+ cellRange.getCellStyle().getExcelFont().setSize(1);
|
|
|
+ cellRange.getCellStyle().getExcelFont().setColor(Color.WHITE);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- return R.data(null);
|
|
|
}
|
|
|
|
|
|
// /**
|