package com.ruoyi.process.service.impl;
|
|
import cn.hutool.core.lang.UUID;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.deepoove.poi.XWPFTemplate;
|
import com.deepoove.poi.config.Configure;
|
import com.deepoove.poi.config.ConfigureBuilder;
|
import com.deepoove.poi.data.*;
|
import com.deepoove.poi.data.style.*;
|
import com.ruoyi.common.core.domain.entity.User;
|
import com.ruoyi.common.utils.QueryWrappers;
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.common.utils.SignatureImageUtil;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.ruoyi.framework.exception.ErrorException;
|
import com.ruoyi.inspect.mapper.InsOrderMapper;
|
import com.ruoyi.inspect.mapper.InsReportMapper;
|
import com.ruoyi.inspect.pojo.InsOrder;
|
import com.ruoyi.inspect.pojo.InsReport;
|
import com.ruoyi.inspect.util.HackLoopTableRenderPolicy;
|
import com.ruoyi.process.dto.ProcessReportDto;
|
import com.ruoyi.process.mapper.ProcessReportMapper;
|
import com.ruoyi.process.pojo.ProcessReport;
|
import com.ruoyi.process.service.ProcessReportService;
|
import com.ruoyi.system.mapper.UserMapper;
|
import org.apache.commons.io.IOUtils;
|
import org.apache.poi.xwpf.usermodel.*;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import javax.annotation.Resource;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.*;
|
import java.net.URLEncoder;
|
import java.nio.file.Files;
|
import java.nio.file.Path;
|
import java.nio.file.Paths;
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.HashSet;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.stream.Collectors;
|
|
/**
|
* <p>
|
* 检验报告发放登记表 服务实现类
|
* </p>
|
*
|
* @author
|
* @since 2024-11-05 08:58:39
|
*/
|
@Service
|
@Transactional(rollbackFor = Exception.class)
|
public class ProcessReportServiceImpl extends ServiceImpl<ProcessReportMapper, ProcessReport> implements ProcessReportService {
|
|
@Resource
|
private ProcessReportMapper processReportMapper;
|
@Value("${file.path}")
|
private String imgUrl;
|
@Value("${wordUrl}")
|
private String wordUrl;
|
|
@Resource
|
private UserMapper userMapper;
|
|
@Resource
|
private InsReportMapper insReportMapper;
|
|
@Resource
|
private InsOrderMapper insOrderMapper;
|
|
@Override
|
public IPage<ProcessReportDto> pageProcessReport(Page page, ProcessReportDto processReport) {
|
// #21 打开列表时,自动带出已通过审批(批准状态=批准)但尚未登记的检验单
|
autoBringOutApproved();
|
IPage<ProcessReportDto> processReportIPage = processReportMapper.pageProcessReport(page, QueryWrappers.queryWrappers(processReport));
|
|
return processReportIPage;
|
}
|
|
/**
|
* 扫描已批准但尚未进入报告结果登记表的检验报告,自动生成待登记记录(以报告编号去重,幂等)。
|
*/
|
private void autoBringOutApproved() {
|
List<InsReport> approved = insReportMapper.selectList(Wrappers.<InsReport>lambdaQuery()
|
.eq(InsReport::getIsRatify, 1)
|
.eq(InsReport::getIsPass, 1));
|
if (approved.isEmpty()) {
|
return;
|
}
|
Set<String> existing = this.list(Wrappers.<ProcessReport>lambdaQuery()
|
.select(ProcessReport::getInsReportCode)).stream()
|
.map(ProcessReport::getInsReportCode)
|
.filter(StringUtils::isNotBlank)
|
.collect(Collectors.toCollection(HashSet::new));
|
for (InsReport report : approved) {
|
String code = report.getCode();
|
if (StringUtils.isBlank(code) || existing.contains(code)) {
|
continue;
|
}
|
ProcessReport pr = new ProcessReport();
|
pr.setInsReportCode(code);
|
pr.setInspectionOrderId(report.getInsOrderId());
|
if (report.getRatifyTime() != null) {
|
pr.setSendTime(report.getRatifyTime().toLocalDate());
|
}
|
if (report.getInsOrderId() != null) {
|
InsOrder order = insOrderMapper.selectById(report.getInsOrderId());
|
if (order != null) {
|
pr.setSend(order.getCompany());
|
pr.setMethod(getReportDeliveryName(order));
|
}
|
}
|
this.save(pr);
|
existing.add(code);
|
}
|
}
|
|
private String getReportDeliveryName(InsOrder order) {
|
if (order.getReportDelivery() != null) {
|
switch (order.getReportDelivery()) {
|
case 1:
|
return "自取";
|
case 2:
|
return "快递";
|
case 3:
|
return "电子传送";
|
default:
|
break;
|
}
|
}
|
// 兼容尚未维护 report_delivery 的历史委托单。
|
return order.getSend() != null && order.getSend() == 1 ? "自取" : "其他";
|
}
|
|
@Override
|
public void downloadStampedReport(Integer id, String format, HttpServletResponse response) {
|
if (id == null) {
|
throw new ErrorException("报告结果不能为空");
|
}
|
ProcessReport processReport = getById(id);
|
if (processReport == null) {
|
throw new ErrorException("报告结果不存在");
|
}
|
if (StringUtils.isBlank(processReport.getInsReportCode())
|
&& processReport.getInspectionOrderId() == null) {
|
throw new ErrorException("该记录未关联检验报告,无法下载");
|
}
|
|
String downloadFormat = StringUtils.isBlank(format) ? "pdf" : format.trim().toLowerCase();
|
if (!"pdf".equals(downloadFormat) && !"word".equals(downloadFormat)) {
|
throw new ErrorException("下载格式不正确");
|
}
|
|
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<InsReport> query =
|
Wrappers.<InsReport>lambdaQuery()
|
.eq(InsReport::getIsRatify, 1)
|
.eq(StringUtils.isNotBlank(processReport.getInsReportCode()),
|
InsReport::getCode, processReport.getInsReportCode())
|
.eq(processReport.getInspectionOrderId() != null,
|
InsReport::getInsOrderId, processReport.getInspectionOrderId())
|
.orderByDesc(InsReport::getId)
|
.last("limit 1");
|
InsReport report = insReportMapper.selectOne(query);
|
if (report == null) {
|
throw new ErrorException("未找到已批准的报告,无法下载有章报告");
|
}
|
|
String fileUrl;
|
String extension;
|
String contentType;
|
if ("word".equals(downloadFormat)) {
|
fileUrl = StringUtils.isNotBlank(report.getUrlS()) ? report.getUrlS() : report.getUrl();
|
extension = ".docx";
|
contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
} else {
|
fileUrl = report.getTempUrlPdf();
|
extension = ".pdf";
|
contentType = "application/pdf";
|
}
|
if ("pdf".equals(downloadFormat) && StringUtils.isBlank(fileUrl)) {
|
String reportUrl = StringUtils.isNotBlank(report.getUrlS()) ? report.getUrlS() : report.getUrl();
|
if (StringUtils.isNotBlank(reportUrl) && reportUrl.toLowerCase().endsWith(".docx")) {
|
fileUrl = reportUrl.substring(0, reportUrl.length() - 5) + ".pdf";
|
}
|
}
|
if (StringUtils.isBlank(fileUrl) || !fileUrl.replace('\\', '/').startsWith("/word/")) {
|
throw new ErrorException("有章报告尚未生成,请先完成报告批准");
|
}
|
|
Path root = Paths.get(wordUrl).toAbsolutePath().normalize();
|
Path file = root.resolve(fileUrl.replace('\\', '/').substring("/word/".length())).normalize();
|
if (!file.startsWith(root) || !Files.isRegularFile(file)) {
|
throw new ErrorException("有章报告文件不存在,请重新批准生成");
|
}
|
|
try {
|
String filename = StringUtils.isNotBlank(processReport.getInsReportCode())
|
? processReport.getInsReportCode() + extension : file.getFileName().toString();
|
String encodedName = URLEncoder.encode(filename, "UTF-8").replace("+", "%20");
|
response.setContentType(contentType);
|
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedName);
|
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
|
response.setHeader("download-filename", encodedName);
|
response.setContentLengthLong(Files.size(file));
|
try (InputStream inputStream = Files.newInputStream(file);
|
OutputStream outputStream = response.getOutputStream()) {
|
IOUtils.copy(inputStream, outputStream);
|
outputStream.flush();
|
}
|
} catch (IOException e) {
|
throw new ErrorException("有章报告下载失败");
|
}
|
}
|
|
@Override
|
public void exportProcessReport(ProcessReportDto dto, HttpServletResponse response) {
|
List<ProcessReportDto> processReports = processReportMapper.exportProcessReport();
|
for (ProcessReportDto processReport : processReports) {
|
// 发送人生成签名图片
|
processReport.setSendUserRender(StringUtils.isNotBlank(processReport.getSendUserUrl())
|
? Pictures.ofLocal(imgUrl + "/" + processReport.getSendUserUrl()).create() : null);
|
|
// 签收人生成图片
|
processReport.setSignatoryRender(StringUtils.isNotBlank(processReport.getSignatory())
|
? Pictures.ofStream(SignatureImageUtil.saveImageToFile(processReport.getSignatory())).create() : null);
|
}
|
|
// 获取路径
|
InputStream inputStream = this.getClass().getResourceAsStream("/static/report-deal.docx");
|
Configure configure = Configure.builder()
|
.bind("reportList", new HackLoopTableRenderPolicy())
|
.build();
|
XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render(
|
new HashMap<String, Object>() {{
|
put("reportList", processReports);
|
}});
|
try {
|
response.setContentType("application/msword");
|
String fileName = URLEncoder.encode(
|
"检验报告发放登记表", "UTF-8");
|
response.setHeader("Content-disposition",
|
"attachment;filename=" + fileName + ".docx");
|
OutputStream os = response.getOutputStream();
|
template.write(os);
|
os.flush();
|
os.close();
|
inputStream.close();
|
inputStream.close();
|
} catch (Exception e) {
|
e.printStackTrace();
|
throw new RuntimeException("导出失败");
|
}
|
}
|
}
|