Commit d50b63b3 authored by 盖献康's avatar 盖献康

Merge branch 'gaixiankang' into 'dev'

原始记录PDF完成

See merge request !291
parents 3f19553f e7443402
......@@ -61,4 +61,10 @@ public interface SampleManagementMapper extends BaseMapper<Sample> {
List<Sample> findByIdList(@Param("relationList") List<TaskSampleRelation> relationList,@Param("id") Long id);
/**
* 通过总任务ID获取与之有关的样品的车型第一个
* @param id
* @return
*/
Sample selectSampleByTaskId(@Param("id") Long id);
}
......@@ -13,4 +13,11 @@ public interface TestRecordsMapper extends BaseMapper<TestRecords> {
List<TestRecords> findByTaskId(@Param("id") String id);
Long countResult(@Param("projectId") String projectId);
/**
* 通过总任务ID查询List
* @param id
* @return
*/
List<TestRecords> selectListByGeneralTaskId(@Param("id") Long id);
}
package com.ruoyi.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.SimpleTextExtractionStrategy;
import com.itextpdf.text.pdf.parser.TextExtractionStrategy;
import com.itextpdf.tool.xml.ElementList;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
......@@ -28,10 +27,14 @@ import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PdfBaseWriter;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.domain.Sample;
import com.ruoyi.domain.TestRecords;
import com.ruoyi.domain.vo.EnterpriseFilePdfVO;
import com.ruoyi.domain.vo.InspectionReportPdfVO;
import com.ruoyi.domain.vo.ReviewEnterpriseArchiveViewVO;
import com.ruoyi.mapper.SampleManagementMapper;
import com.ruoyi.mapper.TaskMapper;
import com.ruoyi.mapper.TestRecordsMapper;
import com.ruoyi.service.PdfTemplateManagementService;
import com.ruoyi.service.ReviewEnterpriseArchiveService;
import com.ruoyi.system.mapper.SysDictDataMapper;
......@@ -54,6 +57,7 @@ import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* PDF模板管理Service业务层处理
......@@ -84,6 +88,12 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
@Autowired
private SysDictDataMapper dictDataMapper;
@Autowired
private SampleManagementMapper sampleManagementMapper;
@Autowired
private TestRecordsMapper testRecordsMapper;
/**
* 检验报告PDF下载
*
......@@ -166,31 +176,7 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
document.addContent(signTable);
document.setParagraph("7.附录", 10.5f, Element.ALIGN_LEFT, 45,1f, 10f);
// 添加内容到新页面
PdfPTable pictureTable = new PdfPTable(new float[]{25, 25, 25, 25});
pictureTable.setWidthPercentage(90);
pictureTable.setSpacingBefore(10);
List<String> pictureList = Arrays.stream(data.getSamplePhotos().split(",")).filter(StringUtils::isNotBlank).collect(Collectors.toList());
int result = pictureList.size();
while (result % 4 != 0) {
result++;
}
for (int i = 0; i < result; i++) {
PdfPCell cell = new PdfPCell();
cell.setBorder(Rectangle.NO_BORDER);
Optional<String> optionalElement = i < pictureList.size() - 1
? Optional.of(pictureList.get(i))
: Optional.empty();
if (optionalElement.isPresent() && StrUtil.isNotEmpty(optionalElement.get())) {
Image image = Image.getInstance(new URL((minioEndpoint + optionalElement.get()).replace(" ", "%20")));
image.scaleAbsolute(100, 100);
cell.addElement(image);
} else {
Paragraph paragraph = new Paragraph();
cell.addElement(paragraph);
}
pictureTable.addCell(cell);
}
document.addContent(pictureTable);
addSamplePhoto(document, data.getSamplePhotos());
document.setParagraph("图 1 样品照片", 10.5f, Element.ALIGN_CENTER, 0,20f, 0f);
document.setParagraph("图 2 试验照片", 10.5f, Element.ALIGN_CENTER, 0,20f, 0f);
// 关闭PDF
......@@ -290,12 +276,20 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
*/
@Override
public String generateOriginalRecord(Long taskId) throws Exception{
// 样品数据
Sample sample = sampleManagementMapper.selectSampleByTaskId(taskId);
// 测试用例
List<TestRecords> recordsList = testRecordsMapper.selectListByGeneralTaskId(taskId);
// 查询本任务对应的所有样品编号、样品照片
InspectionReportPdfVO reportData = taskMapper.selectInspectionReportData(taskId);
// 创建临时文档
String templateName = temporaryDocument();
String templateName = temporaryDocument(sample, recordsList, reportData);
PdfReader pdfReader = new PdfReader(minioUrl() + templateName);
totalNum = pdfReader.getNumberOfPages() - 1;
// 真正文档
String currentName = temporaryDocument();
String currentName = temporaryDocument(sample, recordsList, reportData);
// copy - 分割
Document currentDoc = new Document();
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
......@@ -315,10 +309,16 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
/**
* 创建临时文档
* @param sample 样品信息
* @param recordsList 定时任务接收数据List
* @param reportData
* @return
* @throws Exception
*/
private String temporaryDocument() throws Exception {
@SneakyThrows
private String temporaryDocument(Sample sample, List<TestRecords> recordsList, InspectionReportPdfVO reportData) throws Exception {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfBaseWriter document = new PdfBaseWriter(outputStream);
document.setMargins(50, 50, 85, 40);
......@@ -331,33 +331,112 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
document.newPage();
// 内容
// 1.检验依据
inspectionBasisSection(document);
// 2.样品情况
sampleConditionSection(document, sample);
// 3.仪器设备信息
instrumentInformationSection(document);
// 第一页下方信息
bottomOfTheFirstPage(document, writer);
// 4.检验结果(循环遍历用例)
testResultSection(document, recordsList, reportData);
// 5.附录
document.setParagraph("5.附录", 10f, Element.ALIGN_LEFT, 0,2f, 0f);
// 样品照片
addSamplePhoto(document, reportData.getSamplePhotos());
document.setParagraph("图1 样品照片", 10f, Element.ALIGN_CENTER, 0,20f, 0f);
document.setParagraph("图2 试验照片", 10f, Element.ALIGN_CENTER, 0,20f, 0f);
// close
document.close();
writer.close();
return uploadMinio(outputStream, "原始记录临时");
}
/**
* 往PDF中添加图片组
* @param document
* @param samplePhoto
*/
@SneakyThrows
private void addSamplePhoto(PdfBaseWriter document, String samplePhoto) {
PdfPTable pictureTable = new PdfPTable(new float[]{25, 25, 25, 25});
pictureTable.setWidthPercentage(90);
pictureTable.setSpacingBefore(10);
List<String> pictureList = Arrays.stream(samplePhoto.split(",")).filter(StringUtils::isNotBlank).collect(Collectors.toList());
int result = pictureList.size();
while (result % 4 != 0) {
result++;
}
for (int i = 0; i < result; i++) {
PdfPCell cell = new PdfPCell();
cell.setBorder(Rectangle.NO_BORDER);
Optional<String> optionalElement = i < pictureList.size()
? Optional.of(pictureList.get(i))
: Optional.empty();
if (optionalElement.isPresent() && StrUtil.isNotEmpty(optionalElement.get())) {
Image image = Image.getInstance(new URL((minioEndpoint + optionalElement.get()).replace(" ", "%20")));
image.scaleAbsolute(100, 100);
cell.addElement(image);
} else {
Paragraph paragraph = new Paragraph();
cell.addElement(paragraph);
}
pictureTable.addCell(cell);
}
document.addContent(pictureTable);
}
/**
* 车型试验原始记录 - 1.检验依据
* @param document
*/
private void inspectionBasisSection(PdfBaseWriter document) {
PdfPTable reportNumberTable = new PdfPTable(new float[]{30, 15});
reportNumberTable.setWidthPercentage(100);
reportNumberTable.setSpacingBefore(40);
document.writeNoBorderCell("报告编号:", Element.ALIGN_RIGHT, 1, 1, reportNumberTable);
document.writeBottomCell("", Element.ALIGN_RIGHT, 1, 1, reportNumberTable);
document.writeBottomCell(DateUtils.dateTimeNow(), Element.ALIGN_CENTER, 1, 1, reportNumberTable);
document.addContent(reportNumberTable);
document.setParagraph("1.检验依据", 10f, Element.ALIGN_LEFT, 0,2f, 10f);
document.setParagraph("口《汽车整车信息安全技术要求》", 10f, Element.ALIGN_LEFT, 14,0f, 0f);
// 2.样品情况
}
/**
* 车型试验原始记录 - 2.样品情况
* @param document
* @param sample
*/
@SneakyThrows
private void sampleConditionSection(PdfBaseWriter document, Sample sample) {
document.setParagraph("2.样品情况", 10f, Element.ALIGN_LEFT, 0,10f, 10f);
PdfPTable sampleConditionTable = new PdfPTable(new float[]{30, 20, 30, 20});
PdfPTable sampleConditionTable = new PdfPTable(new float[]{20, 30, 20, 30});
sampleConditionTable.setWidthPercentage(100);
document.writeCell("样品名称", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("xxxxxxx", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell(sample.getSampleName(), Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("生产企业", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("xxxxxxx", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell(sample.getManufacturingEnterprise(), Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("样品型号", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("xxxxxxx", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("样品编号", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("xxxxxxx", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell(sample.getSampleNumber(), Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("样品数量", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("xxxxxxx", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell(sample.getNumberOfSamples(), Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("商标", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("xxxxxxx", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("备注:", Element.ALIGN_LEFT, 4, 1, sampleConditionTable);
if (ObjectUtil.isNotEmpty(sample.getTrademark())) {
document.newPdfPCellOfImage(1, 1, Image.getInstance(minioEndpoint + sample.getTrademark()), 30, 30, sampleConditionTable);
} else {
document.writeCell("---", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
}
document.writeCell("备注:" + sample.getRemark(), Element.ALIGN_LEFT, 4, 1, sampleConditionTable);
document.addContent(sampleConditionTable);
// 3.仪器设备信息
}
/**
* 车型试验原始记录 - 3.仪器设备信息
* @param document
*/
@SneakyThrows
private void instrumentInformationSection(PdfBaseWriter document) {
document.setParagraph("3.仪器设备信息", 10f, Element.ALIGN_LEFT, 0,10f, 0f);
List<String> equipmentList = Arrays.asList("设备编号", "设备名称", "溯源有效期");
float[] columnWidths = {20, 20, 60};
......@@ -366,7 +445,14 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
document.writeCell("xxxxxxxxx", Element.ALIGN_CENTER, 1, 1, equipmentTable);
document.writeCell("xxxx-xx-xx", Element.ALIGN_CENTER, 1, 1, equipmentTable);
document.add(equipmentTable);
// 第一页下方信息
}
/**
* 车型试验原始记录 - 第一页下方固定内容
* @param document
* @param writer
*/
private void bottomOfTheFirstPage(PdfBaseWriter document, PdfWriter writer) {
PdfPTable inspectorTable = new PdfPTable(new float[]{20, 20, 10, 40});
inspectorTable.setWidthPercentage(100);
inspectorTable.setTotalWidth(PageSize.A4.getWidth() - 80);
......@@ -381,51 +467,68 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
inspectorTable.writeSelectedRows(0, -1, document.left(), document.bottom() + 60, writer.getDirectContent());
// 开启下一页
document.newPage();
// 4.检验结果(循环遍历用例)
}
/**
* 车型试验原始记录 - 4.检验结果
* @param document
* @param recordsList
* @param reportData
*/
private void testResultSection(PdfBaseWriter document, List<TestRecords> recordsList, InspectionReportPdfVO reportData) {
document.setParagraph("4.检验结果", 10f, Element.ALIGN_LEFT, 0,10f, 0f);
// 获取数据 - 渲染
document.setParagraph("4.1硬件安全-关键芯片丝印信息测试", 10f, Element.ALIGN_LEFT, 0,2f, 10f);
if (CollUtil.isNotEmpty(recordsList)) {
IntStream.range(0, recordsList.size())
.forEach(index -> {
TestRecords record = recordsList.get(index);
document.setParagraph("4." + (index + 1) + " " + record.getUsecase(), 10f, Element.ALIGN_LEFT, 0,2f, 10f);
PdfPTable useCaseTable = new PdfPTable(new float[]{15, 35, 15, 35});
useCaseTable.setWidthPercentage(100);
document.writeCell("测试编号", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("激光雷达_001", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("xxxxxxx", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("测试时间", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("2021年8月23日", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell(String.valueOf(record.getTestTime()), Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("样品编号", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("STCS-2021-08-0013(01)", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell(reportData.getSampleNumberSummary(), Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("测试人员", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("简述", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("检测PCB板上的核心芯片是否存在可用丝印信息。", Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell(record.getDescription(), Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell("风险等级", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("中危", Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell(record.getRiskLevel(), Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell("测试方法", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("1.使用专用工具将雷达拆卸至PCB板;", Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell(record.getTestMethod(), Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell("测试结果", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("芯片丝印未擦除,且PCB板上暴露的丝印信息较多,有泄露电路设计的风险。", Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell(record.getTestResult(), Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell("测试详情", Element.ALIGN_LEFT, 1, 1, useCaseTable);
PdfPCell cell = new PdfPCell();
cell.setColspan(3);
cell.setRowspan(1);
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
String htmlContent = convertMarkdownToHtml("**请依次完成以下操作:**\\n\\n1)使用电动螺丝刀拆开车机外壳,注意不要造成物理性破坏;\\n\\n2)肉眼观察板子上是否有明显的JTAG调试接口,需要注意CPU附近的点和引脚的各种信息;\\n\\n注:JTAG通常主要由以下4个针脚组成:\\n\\n①TCK ... Test Clock\\n\\n②TMS ... Test Mode Select \\n\\n③TDI ... Test Data In\\n\\n④TDO ... Test Data Out\\n\\n3)通过五倍光学放大镜仔细查看PCB板上的信息,找到带有JTAG、TCK、TMS、TDI、TDO等相关的信息的点位,比如下图:\\n\\n![](http://49.232.167.247:22038/vehicle-quality-review-oss/2024/04/11/1712827970222_20240411173255A009.jpg)\\n\\n4)将测试过程中的 PCB 板照片等作为测试证明材料上传至平台。\\n\\n<br>\\n\\n**请根据PCB板上是否存在明显的JTAG调试接口对节点结果进行判断。**");
// h5渲染到cell
// String htmlContent = "<h1 style=\"font-size: 36pt;\">Hello, World!</h1><h2>我的</h2><p style=\"color: red;\">This is some HTML content.</p><img src=\"http://49.232.167.247:22038/vehicle-quality-review-oss/2024/04/11/1712827970222_20240411173255A009.jpg\" />";
Paragraph context = new Paragraph();
// ElementList elementList = XMLWorkerHelper.parseToElementList(htmlContent, css);
ElementList elementList = parseToElementList(htmlContent, null);
ElementList elementList = null;
try {
elementList = parseToElementList(record.getTestDetails(), null);
} catch (IOException e) {
throw new RuntimeException(e);
}
context.addAll(elementList);
cell.addElement(context);
useCaseTable.addCell(cell);
if (ObjectUtil.isNotEmpty(record.getRemediation())) {
document.writeCell("修复建议", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell(record.getRemediation(), Element.ALIGN_LEFT, 3, 1, useCaseTable);
}
try {
document.add(useCaseTable);
// 5.附录
document.setParagraph("5.附录", 10f, Element.ALIGN_LEFT, 0,10f, 0f);
document.setParagraph("图1 样品照片", 10f, Element.ALIGN_CENTER, 0,20f, 0f);
document.setParagraph("图2 试验照片", 10f, Element.ALIGN_CENTER, 0,20f, 0f);
// close
document.close();
writer.close();
return uploadMinio(outputStream, "原始记录临时");
} catch (DocumentException e) {
throw new RuntimeException(e);
}
document.setParagraph(" ", 10f, Element.ALIGN_LEFT, 0,2f, 10f);
});
}
}
/**
......
......@@ -184,4 +184,24 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
ORDER BY ts.id
</select>
<select id="selectSampleByTaskId" parameterType="java.lang.Long" resultType="com.ruoyi.domain.Sample">
select
s.sample_name,
s.manufacturing_enterprise,
s.sample_number,
s.number_of_samples,
s.trademark,
s.remark
from
t_sample s
left join t_task_sample_relation ts on s.id = ts.sample_id
left join t_task t on ts.task_id = t.id
where
t.id = #{id}
and s.deleted = 0
and ts.flag = '0'
order by s.id
limit 1;
</select>
</mapper>
......@@ -29,5 +29,23 @@
GROUP BY project_id
</select>
<select id="selectListByGeneralTaskId" parameterType="java.lang.Long" resultType="com.ruoyi.domain.TestRecords">
select
tr.usecase,
tr.usecase_id,
tr.test_time,
tr.description,
tr.risk_level,
tr.test_method,
tr.test_result,
tr.remediation,
tr.test_details
from
t_test_records tr
left join t_task t on tr.task_id = t.model_test_task_id
where
t.id = #{id}
</select>
</mapper>
......@@ -320,7 +320,7 @@ public class PdfBaseWriter extends Document{
* @param fitHeight 高度自适应
* @return 单元格 {@link PdfPCell}
*/
public PdfPCell newPdfPCellOfImage(int colspan, int rowspan, Image image, float fitWidth, float fitHeight) {
public PdfPCell newPdfPCellOfImage(int colspan, int rowspan, Image image, float fitWidth, float fitHeight, PdfPTable table) {
PdfPCell cell = new PdfPCell();
cell.setUseAscender(Boolean.TRUE);
cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
......@@ -330,7 +330,9 @@ public class PdfBaseWriter extends Document{
cell.setColspan(colspan);
cell.setRowspan(rowspan);
image.scaleToFit(fitWidth, fitHeight);
image.setAlignment(Image.ALIGN_CENTER);
cell.addElement(image);
table.addCell(cell);
return cell;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment