Commit 2a8263fa authored by 盖献康's avatar 盖献康

Merge branch 'dev' into 'master'

Dev - master 6.0

See merge request !292
parents d4fece7a d50b63b3
......@@ -61,6 +61,16 @@
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.24</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-framework</artifactId>
......@@ -70,6 +80,23 @@
<artifactId>httpclient</artifactId>
<version>4.5.1</version>
</dependency>
<!-- markdown->h5 -->
<dependency>
<groupId>com.atlassian.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.15.2</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<!-- iText 7 pdfHTML -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>4.0.5</version>
</dependency>
</dependencies>
</project>
......@@ -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);
}
......@@ -2,6 +2,7 @@ package com.ruoyi.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.domain.TestType;
import com.ruoyi.domain.vo.TestTypeVO;
import com.ruoyi.web.request.TestTypeRequest;
import java.util.List;
......@@ -15,4 +16,10 @@ public interface ITestTypeService extends IService<TestType> {
* @return 测试类型库集合
*/
public List<TestType> selectTestTypeList(TestTypeRequest testTypeRequest);
/**
* 从科恩获取所有测试方法
* @return
*/
List<String> getTestTypeList();
}
......@@ -27,7 +27,8 @@ public interface PdfTemplateManagementService {
* 原始记录PDF下载
* @param taskId
* @return
* @throws Exception
*/
String generateOriginalRecord(Long taskId);
String generateOriginalRecord(Long taskId) throws Exception;
}
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.tool.xml.ElementList;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.css.CssFile;
import com.itextpdf.tool.xml.css.StyleAttrCSSResolver;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.ElementHandlerPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
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;
......@@ -18,19 +42,22 @@ import io.minio.MinioClient;
import io.minio.ObjectWriteArgs;
import io.minio.PutObjectArgs;
import lombok.SneakyThrows;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Entities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* PDF模板管理Service业务层处理
......@@ -61,6 +88,12 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
@Autowired
private SysDictDataMapper dictDataMapper;
@Autowired
private SampleManagementMapper sampleManagementMapper;
@Autowired
private TestRecordsMapper testRecordsMapper;
/**
* 检验报告PDF下载
*
......@@ -143,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
......@@ -263,33 +272,426 @@ public class PdfTemplateManagementServiceImpl implements PdfTemplateManagementSe
* 原始记录PDF下载
* @param taskId
* @return
* @throws Exception
*/
@Override
public String generateOriginalRecord(Long taskId) {
return null;
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(sample, recordsList, reportData);
PdfReader pdfReader = new PdfReader(minioUrl() + templateName);
totalNum = pdfReader.getNumberOfPages() - 1;
// 真正文档
String currentName = temporaryDocument(sample, recordsList, reportData);
// copy - 分割
Document currentDoc = new Document();
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
PdfCopy copy = new PdfCopy(currentDoc, arrayOutputStream);
currentDoc.open();
PdfReader templateReader = new PdfReader(minioUrl() + currentName);
int numberOfPages = templateReader.getNumberOfPages();
for (int i = 2; i <= numberOfPages; i++) {
PdfImportedPage page = copy.getImportedPage(templateReader, i);
copy.addPage(page);
}
currentDoc.close();
templateReader.close();
copy.close();
return uploadMinio(arrayOutputStream, "原始记录");
}
/**
* 创建临时文档
* @param sample 样品信息
* @param recordsList 定时任务接收数据List
* @param reportData
* @return
* @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);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
OriginalRecordHeaderFooter headerFooter = new OriginalRecordHeaderFooter();
writer.setPageEvent(headerFooter);
// open
document.open();
document.setParagraph(" ", 10f, Element.ALIGN_LEFT, 0,2f, 10f);
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(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.样品情况
* @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[]{20, 30, 20, 30});
sampleConditionTable.setWidthPercentage(100);
document.writeCell("样品名称", 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(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(sample.getSampleNumber(), Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("样品数量", Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell(sample.getNumberOfSamples(), Element.ALIGN_CENTER, 1, 1, sampleConditionTable);
document.writeCell("商标", Element.ALIGN_CENTER, 1, 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.仪器设备信息
* @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};
PdfPTable equipmentTable = document.createWithHeaderTable(equipmentList, columnWidths);
document.writeCell("xxxx", Element.ALIGN_CENTER, 1, 1, equipmentTable);
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);
document.writeNoBorderCell("检验人员:", Element.ALIGN_LEFT, 1, 1, inspectorTable);
document.writeNoBorderCell("", Element.ALIGN_LEFT, 1, 1, inspectorTable);
document.writeNoBorderCell("检验日期:", Element.ALIGN_LEFT, 1, 1, inspectorTable);
document.writeNoBorderCell("", Element.ALIGN_LEFT, 1, 1, inspectorTable);
document.writeBottomCell("检验负责人:", Element.ALIGN_LEFT, 1, 1, inspectorTable);
document.writeBottomCell("", Element.ALIGN_LEFT, 1, 1, inspectorTable);
document.writeBottomCell("检验地点:", Element.ALIGN_LEFT, 1, 1, inspectorTable);
document.writeBottomCell("口中汽研软件测评有限公司 口其他:", Element.ALIGN_LEFT, 1, 1, inspectorTable);
inspectorTable.writeSelectedRows(0, -1, document.left(), document.bottom() + 60, writer.getDirectContent());
// 开启下一页
document.newPage();
}
/**
* 车型试验原始记录 - 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);
// 获取数据 - 渲染
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("xxxxxxx", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell("测试时间", 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(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(record.getDescription(), Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell("风险等级", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell(record.getRiskLevel(), Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell("测试方法", Element.ALIGN_LEFT, 1, 1, useCaseTable);
document.writeCell(record.getTestMethod(), Element.ALIGN_LEFT, 3, 1, useCaseTable);
document.writeCell("测试结果", Element.ALIGN_LEFT, 1, 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);
// h5渲染到cell
Paragraph context = new Paragraph();
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);
} catch (DocumentException e) {
throw new RuntimeException(e);
}
document.setParagraph(" ", 10f, Element.ALIGN_LEFT, 0,2f, 10f);
});
}
}
/**
* html转pdf 写法
* @param html
* @param css
* @return
* @throws IOException
*/
public static ElementList parseToElementList(String html, String css) throws IOException {
// CSS
CSSResolver cssResolver = new StyleAttrCSSResolver();
if (css != null) {
CssFile cssFile = XMLWorkerHelper.getCSS(new ByteArrayInputStream(css.getBytes()));
cssResolver.addCss(cssFile);
}
// HTML
MyFontsProvider fontProvider = new MyFontsProvider();
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
htmlContext.autoBookmark(false);
// Pipelines
ElementList elements = new ElementList();
ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null);
HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, end);
CssResolverPipeline cssPipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
// XML Worker
XMLWorker worker = new XMLWorker(cssPipeline, true);
XMLParser p = new XMLParser(worker);
html = html.replace("<br>", "").replace("<hr>", "").replace("<img>", "").replace("<param>", "").replace("<link>", "");
p.parse(new ByteArrayInputStream(html.getBytes()));
return elements;
}
static class MyFontsProvider extends XMLWorkerFontProvider {
public MyFontsProvider() {
super(null, null);
}
@Override
public Font getFont(final String fontname, String encoding, float size, final int style) {
return getFontInf();
}
}
/**
* 设置字体信息
* @return
*/
@SneakyThrows
private static Font getFontInf() {
// 字体路径
String fontPath = "/fonts/STSong.TTF";
BaseFont baseFont = null;
Font font = null;
// 设置字体路径,字体编码,是否将字体嵌入pdf(默认false)
baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
// 设置默认字体数据
font = new Font(baseFont, 12f, Font.NORMAL,BaseColor.BLACK);
return font;
}
private static int totalNum = 0;
public static class OriginalRecordHeaderFooter extends PdfPageEventHelper {
// 一页加载完成触发,写入页眉和页脚
// PdfTemplate totalPage;
// @Override
// public void onOpenDocument (PdfWriter writer, Document document) {
// PdfContentByte contentByte = writer.getDirectContent();
// totalPage = contentByte.createTemplate(30, 16);
// }
@Override
@SneakyThrows
public void onCloseDocument(PdfWriter writer, Document document) {
// BaseFont font = BaseFont.createFont("/fonts/STSong.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
// String text = " 共 " + (writer.getPageNumber()) + " 页";
// ColumnText.showTextAligned(totalPage, Element.ALIGN_CENTER, new Paragraph(String.valueOf(text), new Font(font, 8f)), 2, 4 ,0);
totalNum = writer.getPageNumber() - 1;
System.out.println(totalNum);
}
/**
* 一页加载完成触发,写入页眉和页脚
*/
@Override
@SneakyThrows
public void onEndPage(PdfWriter writer, Document document) {
BaseFont font = BaseFont.createFont("/fonts/STSong.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
PdfPTable table = new PdfPTable(2);
try {
table.setTotalWidth(PageSize.A4.getWidth() - 80);
table.setWidths(new int[] { 40, 40 });
table.setLockedWidth(true);
table.getDefaultCell().setFixedHeight(-10);
table.getDefaultCell().setBorder(Rectangle.BOTTOM);
table.getDefaultCell().setBorderWidth(0.6f);
BaseFont font = BaseFont.createFont("/fonts/STSong.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
table.addCell(new Paragraph(headerText, new Font(font)));// 可以直接使用addCell(str),不过不能指定字体,中文无法显示
// 将页眉写到document中,位置可以指定,指定到下面就是页脚
table.writeSelectedRows(0, -1, 40, PageSize.A4.getHeight() - 20, writer.getDirectContent());
} catch (Exception de) {
throw new ExceptionConverter(de);
}
table.setTotalWidth(PageSize.A4.getWidth() - 80);
table.setWidths(new int[] { 60, 40 });
table.setLockedWidth(true);
table.getDefaultCell().setFixedHeight(30);
table.getDefaultCell().setBorder(Rectangle.BOX);
table.getDefaultCell().setBorderWidth(0.5f);
table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setRowspan(1);
table.getDefaultCell().setColspan(2);
table.addCell(new Paragraph("中汽研软件测评有限公司", new Font(font)));
table.getDefaultCell().setRowspan(1);
table.getDefaultCell().setColspan(1);
table.addCell(new Paragraph("检验记录", new Font(font)));
table.getDefaultCell().setRowspan(1);
table.getDefaultCell().setColspan(1);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setBorder(Rectangle.BOTTOM + Rectangle.TOP + Rectangle.LEFT + Rectangle.RIGHT);
table.addCell(new Paragraph("第 " + (writer.getCurrentPageNumber() - 1) + " 页 / 共 "+ totalNum +" 页", new Font(font)));
// 总页数
// table.getDefaultCell().setBorder(Rectangle.BOX);
// table.getDefaultCell().setColspan(1);
// table.getDefaultCell().setRowspan(1);
// table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_LEFT);
// table.getDefaultCell().setBorder(Rectangle.BOTTOM + Rectangle.TOP + Rectangle.RIGHT);
// table.addCell(Image.getInstance(totalPage));
// 将页眉写到document中,位置可以指定,指定到下面就是页脚
table.writeSelectedRows(0, -1, 40, PageSize.A4.getHeight() - 20, writer.getDirectContent());
// 页脚
PdfPTable bottomTable = new PdfPTable(1);
bottomTable.setTotalWidth(PageSize.A4.getWidth() - 80);
bottomTable.setWidths(new int[] { 50});
bottomTable.setLockedWidth(true);
bottomTable.getDefaultCell().setFixedHeight(-10);
bottomTable.getDefaultCell().setBorder(Rectangle.NO_BORDER);
bottomTable.getDefaultCell().setBorderWidth(0.5f);
bottomTable.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER);
bottomTable.addCell(new Paragraph(String.valueOf(writer.getPageNumber() - 1), new Font(font)));
bottomTable.writeSelectedRows(0, -1, 40, 40, writer.getDirectContent());
}
}
/**
*
* @param markdownContent
* @return
*/
public static String convertMarkdownToHtml(String markdownContent) {
// 创建 Markdown 解析器
Parser parser = Parser.builder().build();
// 解析 Markdown
Node document = parser.parse(markdownContent);
// 创建 HTML 渲染器
HtmlRenderer renderer = HtmlRenderer.builder().build();
// 渲染 HTML
org.jsoup.nodes.Document doc = Jsoup.parse(renderer.render(document).replaceAll("\\\\n", "<br>"));
// jsoup标准化标签,生成闭合标签
doc.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml);
doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml);
return doc.html();
}
private static String headerText;
......
package com.ruoyi.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.domain.ModelTestTask;
import com.ruoyi.mapper.ModelTestTaskMapper;
import com.ruoyi.service.StrategyModelTestTask;
import com.ruoyi.service.TestUseCaseService;
import com.ruoyi.web.response.ModelTestResponse;
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
......@@ -14,7 +18,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@Service
@Transactional
......@@ -32,6 +38,11 @@ public class StrategyModelTestTaskPending implements StrategyModelTestTask, Init
@Autowired
private StrategyModelTestTaskNew strategyModelTestTaskNew;
@Autowired
private TestUseCaseService testUseCaseService;
private static String url = "https://10.12.48.78:8090/DescribeProjectTestResult";
@Override
public ModelTestResponse doView(ModelTestTask modelTestTask) {
ModelTestResponse response = strategyModelTestTaskNew.getTestScheme(modelTestTask);
......@@ -45,12 +56,31 @@ public class StrategyModelTestTaskPending implements StrategyModelTestTask, Init
@Override
public void doConfirmTest(ModelTestTask modelTestTask) {
// 进行中的任务, 点击确认后, 状态改为待签字
modelTestTaskMapper.update(new ModelTestTask(),
new LambdaUpdateWrapper<ModelTestTask>()
.set(ModelTestTask::getTaskEndTime, new Date())
.set(ModelTestTask::getTaskStatus, ModelTestTask.TASK_STATUS_SIGNED)
.eq(ModelTestTask::getId, modelTestTask.getId()));
// 查看当前任务-用例完成情况
HashMap<String, Object> map = new HashMap<>();
map.put("id", modelTestTask.getTestSchemeId());
map.put("verbose", "BASIC");
JSONObject jsonObject = testUseCaseService.callThirdPartyInterface(url, map);
Integer sumCount = (Integer) jsonObject.get("case_count");
AtomicReference<Integer> currentCount = new AtomicReference<>(0);
List<CaseStatistics> caseStatisticsList = jsonObject.getList("case_statistics", CaseStatistics.class);
if (CollUtil.isNotEmpty(caseStatisticsList)) {
caseStatisticsList.forEach(obj -> {
if (CaseStatistics.CASE_STATUS_FAILED.equals(obj.status) || CaseStatistics.CASE_STATUS_PASSED.equals(obj.status)) {
currentCount.updateAndGet(v -> v + obj.getCount());
}
});
}
Integer integer = currentCount.get();
System.out.println(integer);
// 进行中的任务, 点击返回后, 判断当前用例完成程度, 用例都完成后状态改为待签字
if (sumCount.equals(currentCount.get())) {
modelTestTaskMapper.update(new ModelTestTask(),
new LambdaUpdateWrapper<ModelTestTask>()
.set(ModelTestTask::getTaskEndTime, new Date())
.set(ModelTestTask::getTaskStatus, ModelTestTask.TASK_STATUS_SIGNED)
.eq(ModelTestTask::getId, modelTestTask.getId()));
}
}
@Override
......@@ -62,4 +92,32 @@ public class StrategyModelTestTaskPending implements StrategyModelTestTask, Init
public void afterPropertiesSet() throws Exception {
strategyModelTestTaskContext.putResource(ModelTestTask.TASK_STATUS_PENDING, applicationContext.getBean(this.getClass()));
}
/**
* 接参DTO
*/
@Data
public class CaseStatistics {
/**
* 通过
*/
private static final String CASE_STATUS_PASSED = "PASSED";
/**
* 失败
*/
private static final String CASE_STATUS_FAILED = "FAILED";
/**
* 数量
*/
private Integer count;
/**
* 状态
*/
private String status;
}
}
......@@ -7,10 +7,8 @@ import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.DataStatisticsUtils;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
......@@ -798,7 +796,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task>implements Tas
} else if(resultNum == null) {
response.setTest(0.0);
} else {
BigDecimal num = new BigDecimal((resultNum / useCaseNum) * 90);
BigDecimal num = new BigDecimal((1.0 * resultNum / useCaseNum) * 90);
response.setTest(num.setScale(1,BigDecimal.ROUND_UP).doubleValue());
}
......
......@@ -9,6 +9,11 @@ import com.ruoyi.domain.vo.CaseResultVO;
import com.ruoyi.domain.vo.StepResultVO;
import com.ruoyi.mapper.TestRecordsMapper;
import com.ruoyi.service.TestRecordsService;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Entities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
......@@ -88,6 +93,7 @@ public class TestRecordsServiceImpl extends ServiceImpl<TestRecordsMapper, TestR
List<String> stepList = new ArrayList<>();
List<String> testDetailsList = new ArrayList<>();
int index = 1; // 序号从1开始
String testDetailsVO = "";
for (StepResultVO stepResultVO :stepResultVOS) {
// 测试方法
String stepName = stepResultVO.getName();
......@@ -100,10 +106,14 @@ public class TestRecordsServiceImpl extends ServiceImpl<TestRecordsMapper, TestR
// 测试详情
String testDetails = stepResultVO.getDescription();
testDetailsList.add(testDetails);
if (testDetails != null) {
convertMarkdownToHtml(testDetails);
}
testDetailsVO += testDetails + "`";
}
testDetailsVO = testDetailsVO.substring(0, testDetailsVO.length() - 1);
testRecords.setTestMethod(StringUtils.join(stepList,"`"));
testRecords.setTestDetails(StringUtils.join(testDetailsList,"\n"));
testRecords.setTestDetails(testDetailsVO);
}
list.add(testRecords);
......@@ -161,6 +171,7 @@ public class TestRecordsServiceImpl extends ServiceImpl<TestRecordsMapper, TestR
List<String> stepList = new ArrayList<>();
List<String> testDetailsList = new ArrayList<>();
int index = 1; // 序号从1开始
String testDetailsVO = "";
for (StepResultVO stepResultVO :stepResultVOS) {
// 测试方法
String stepName = stepResultVO.getName();
......@@ -173,10 +184,14 @@ public class TestRecordsServiceImpl extends ServiceImpl<TestRecordsMapper, TestR
// 测试详情
String testDetails = stepResultVO.getDescription();
testDetailsList.add(testDetails);
if (testDetails != null) {
convertMarkdownToHtml(testDetails);
}
testDetailsVO += testDetails + "`";
}
testDetailsVO = testDetailsVO.substring(0, testDetailsVO.length() - 1);
testRecords.setTestMethod(StringUtils.join(stepList,"`"));
testRecords.setTestDetails(StringUtils.join(testDetailsList,"\n"));
testRecords.setTestDetails(testDetailsVO);
}
list.add(testRecords);
......@@ -189,6 +204,25 @@ public class TestRecordsServiceImpl extends ServiceImpl<TestRecordsMapper, TestR
}
}
public static String convertMarkdownToHtml(String markdownContent) {
// 创建 Markdown 解析器
Parser parser = Parser.builder().build();
// 解析 Markdown
Node document = parser.parse(markdownContent);
// 创建 HTML 渲染器
HtmlRenderer renderer = HtmlRenderer.builder().build();
// 渲染 HTML
org.jsoup.nodes.Document doc = Jsoup.parse(renderer.render(document).replaceAll("\\\\n", "<br>"));
// jsoup标准化标签,生成闭合标签
doc.outputSettings().syntax(org.jsoup.nodes.Document.OutputSettings.Syntax.xml);
doc.outputSettings().escapeMode(Entities.EscapeMode.xhtml);
return doc.html();
}
@Override
public List<TestRecords> findByTaskId(String id) {
return testRecordsMapper.findByTaskId(id);
......
package com.ruoyi.service.impl;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.domain.TestType;
......@@ -8,11 +10,13 @@ import com.ruoyi.mapper.TestTypeMapper;
import com.ruoyi.service.ITestTypeService;
import com.ruoyi.web.request.TestTypeRequest;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Transactional
......@@ -34,4 +38,23 @@ public class TestTypeServiceImpl extends ServiceImpl<TestTypeMapper, TestType> i
}
return testTypeMapper.selectTestTypeList(testTypeRequest);
}
@Override
public List<String> getTestTypeList() {
//以post形式请求接口
String result= HttpUtil.post("https://10.12.48.78:8090/DescribeScenarioTestTypeList","");
JSONObject jsonObject = JSONObject.parseObject(result);
return jsonObject.getList("test_type_list", TypeVO.class)
.stream()
.map(TypeVO::getName)
.collect(Collectors.toList());
}
@Data
public static class TypeVO {
private String name;
}
}
......@@ -101,7 +101,7 @@ public class PdfTemplateManagementController {
if (StrUtil.isBlank(url)) {
// TODO 生成车型
url = pdfTemplateManagementService.generateOriginalRecord(request.getTaskId());
taskService.update(new UpdateWrapper<Task>().lambda().eq(Task::getId, request.getTaskId()).set(Task::getModelTestTaskId, url));
taskService.update(new UpdateWrapper<Task>().lambda().eq(Task::getId, request.getTaskId()).set(Task::getModelTestUrl, url));
}
break;
default:
......@@ -139,7 +139,7 @@ public class PdfTemplateManagementController {
case 2:
// 更新
url = pdfTemplateManagementService.generateOriginalRecord(request.getTaskId());
taskService.update(new UpdateWrapper<Task>().lambda().eq(Task::getId, request.getTaskId()).set(Task::getModelTestTaskId, url));
taskService.update(new UpdateWrapper<Task>().lambda().eq(Task::getId, request.getTaskId()).set(Task::getModelTestUrl, url));
break;
default:
break;
......
......@@ -4,6 +4,7 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.domain.TestType;
import com.ruoyi.domain.vo.TestTypeVO;
import com.ruoyi.service.ITestTypeService;
import com.ruoyi.web.request.TestTypeRequest;
import io.swagger.annotations.Api;
......@@ -51,4 +52,13 @@ public class TestTypeController extends BaseController {
return R.ok(testTypeService.selectTestTypeList(testTypeRequest));
}
// 从科恩获取所有测试方法
@ApiOperation("查询所有测试方法(科恩)")
@Trace
@Tags({@Tag(key = "param", value = "arg[0]"), @Tag(key = "result", value = "returnedObj")})
@RequestMapping(method = RequestMethod.POST, value = "/getTestTypeList")
public R<List<String>> getTestTypeList(){
return R.ok(testTypeService.getTestTypeList());
}
}
package com.ruoyi.web.request;
import com.ruoyi.common.core.page.PageDomain;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "TestUserCaseListRequest", description = "查询测试用例")
public class TestUserCaseListRequest extends PageDomain {
@ApiModelProperty("测试场景")
private String testScenario;
@ApiModelProperty("测试方法")
private String testType;
@ApiModelProperty("用例编号或者名称关键字")
private String searchKeywords;
}
package com.ruoyi.web.response;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "TestUserCaseListResponse", description = "查询测试用例")
@Data
public class TestUserCaseListResponse {
@ApiModelProperty("测试场景")
private String testScenario;
@ApiModelProperty("测试方法")
private String testType;
@ApiModelProperty("用例编号")
private String useCaseNo;
@ApiModelProperty("用例名称")
private String useCaseName;
@ApiModelProperty("对应输入")
private String input;
@ApiModelProperty("用例描述")
private String description;
}
......@@ -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