Browse Source

word模板导出demov10

aqm-ops-supervision-platform
gjh 7 days ago
parent
commit
831c9ced5c
  1. 4
      ruoyi-modules/ruoyi-demo/pom.xml
  2. 6
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/SiteEvaluationInfoController.java
  3. 4
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/ISiteEvaluationInfoService.java
  4. 345
      ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/SiteEvaluationInfoServiceImpl.java

4
ruoyi-modules/ruoyi-demo/pom.xml

@ -113,6 +113,10 @@
<groupId>org.dromara</groupId>
<artifactId>ruoyi-common-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-system</artifactId>
</dependency>
</dependencies>

6
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/SiteEvaluationInfoController.java

@ -1,5 +1,6 @@
package org.dromara.demo.controller;
import java.io.IOException;
import java.util.List;
import com.fasterxml.jackson.core.JsonProcessingException;
@ -103,4 +104,9 @@ public class SiteEvaluationInfoController extends BaseController {
@PathVariable String[] ids) {
return toAjax(siteEvaluationInfoService.deleteWithValidByIds(List.of(ids), true));
}
@GetMapping("/download/world")
public void download( HttpServletResponse response) throws Exception {
siteEvaluationInfoService.download(response);
}
}

4
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/ISiteEvaluationInfoService.java

@ -1,11 +1,13 @@
package org.dromara.demo.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import jakarta.servlet.http.HttpServletResponse;
import org.dromara.demo.domain.vo.SiteEvaluationInfoVo;
import org.dromara.demo.domain.bo.SiteEvaluationInfoBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
@ -66,4 +68,6 @@ public interface ISiteEvaluationInfoService {
* @return 是否删除成功
*/
Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid);
void download(HttpServletResponse response) throws Exception;
}

345
ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/SiteEvaluationInfoServiceImpl.java

@ -1,9 +1,21 @@
package org.dromara.demo.service.impl;
import cn.afterturn.easypoi.word.WordExportUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.dromara.common.core.service.OssService;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
@ -11,8 +23,15 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.oss.core.OssClient;
import org.dromara.common.oss.factory.OssFactory;
import org.dromara.demo.domain.Attachment;
import org.dromara.demo.domain.EvaluationDataJson;
import org.dromara.demo.domain.WordExportTest;
import org.dromara.demo.domain.vo.AttachmentVo;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.service.ISysOssService;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.dromara.demo.domain.bo.SiteEvaluationInfoBo;
import org.dromara.demo.domain.vo.SiteEvaluationInfoVo;
@ -20,11 +39,13 @@ import org.dromara.demo.domain.SiteEvaluationInfo;
import org.dromara.demo.mapper.SiteEvaluationInfoMapper;
import org.dromara.demo.service.ISiteEvaluationInfoService;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.*;
/**
* 现场考核信息Service业务层处理
@ -38,7 +59,8 @@ public class SiteEvaluationInfoServiceImpl implements ISiteEvaluationInfoService
private final SiteEvaluationInfoMapper baseMapper;
private final ObjectMapper objectMapper = new ObjectMapper();
@Resource
private final ISysOssService ossService;
/**
* 查询现场考核信息
*
@ -198,4 +220,319 @@ public class SiteEvaluationInfoServiceImpl implements ISiteEvaluationInfoService
}
return baseMapper.deleteByIds(ids) > 0;
}
@Override
public void download(HttpServletResponse response) throws Exception {
// 1. 准备数据
Map<String, Object> data = getData();
String siteName = (String) data.get("siteName");
String fileName = siteName + "现场技术核查评分表.docx";
// 2. 加载模板
InputStream templateIs = this.getClass().getClassLoader()
.getResourceAsStream("score_template.docx");
if (templateIs == null) {
throw new FileNotFoundException("模板未找到");
}
try (templateIs) {
// 3. 创建临时文件 → 填充模板
File tempFile = File.createTempFile("temp", ".docx");
tempFile.deleteOnExit();
Files.copy(templateIs, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
XWPFDocument document = WordExportUtil.exportWord07(tempFile.getAbsolutePath(), data);
AttachmentVo attachmentVo = new AttachmentVo();
List<Attachment> attachmentList = new ArrayList<>();
Attachment attachment1 = new Attachment();
attachment1.setDescription("描述1");
attachment1.setOssId("1964745602352324609");
attachment1.setName("故障图片.png");
attachmentList.add(attachment1);
Attachment attachment2 = new Attachment();
attachment2.setDescription("描述2");
attachment2.setOssId("1964745602352324609");
attachment2.setName("故障图片.png");
attachmentList.add(attachment2);
attachmentVo.setAttachmentList(attachmentList);
appendImages(document,attachmentVo ,ossService);
// ✅ 4. 设置响应头
String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setHeader("Content-Disposition",
"attachment1; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
response.setCharacterEncoding("UTF-8");
// ✅ 5. 写入输出流
document.write(response.getOutputStream());
// ✅ 6. 关闭 document
document.close();
// ✅ 7. 强制刷新输出缓冲区(关键!)
response.flushBuffer();
}
// ✅ try 结束前,数据已发出
}
private static void appendImages(XWPFDocument document,
AttachmentVo attachmentVo,
ISysOssService ossService) throws Exception {
if (attachmentVo == null || attachmentVo.getAttachmentList() == null || attachmentVo.getAttachmentList().isEmpty()) {
System.out.println("📭 无图片需要插入");
return;
}
List<Attachment> attachmentList = attachmentVo.getAttachmentList();
for (int i = 0; i < attachmentList.size(); i++) {
Attachment attachment = attachmentList.get(i);
String ossIdStr = attachment.getOssId();
String description = attachment.getDescription();
String imageName = attachment.getName();
if (ossIdStr == null || ossIdStr.trim().isEmpty()) {
System.err.println("⚠️ 缺少 ossId,跳过图片:" + imageName);
continue;
}
Long ossId;
try {
ossId = Long.valueOf(ossIdStr);
} catch (NumberFormatException e) {
System.err.println("⚠️ ossId 格式错误:" + ossIdStr);
continue;
}
// 查询文件信息
SysOssVo sysOss = SpringUtils.getAopProxy(ossService).getById(ossId);
if (sysOss == null) {
System.err.println("⚠️ 文件不存在,ossId: " + ossId);
continue;
}
// 获取 OssClient
OssClient storage = OssFactory.instance(sysOss.getService());
// ✅ 使用 ByteArrayOutputStream 获取图片字节流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
// 调用已有方法,把文件写入 baos
storage.download(sysOss.getFileName(), baos);
byte[] imageBytes = baos.toByteArray();
if (imageBytes.length == 0) {
System.err.println("⚠️ 下载图片为空:" + ossId);
continue;
}
// 创建图片段落(居中)
XWPFParagraph imgParagraph = document.createParagraph();
imgParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun imgRun = imgParagraph.createRun();
// 推断图片类型
int pictureType = getPictureType(imageName);
// 插入图片
imgRun.addPicture(
new ByteArrayInputStream(imageBytes),
pictureType,
imageName,
Units.toEMU(300),
Units.toEMU(150)
);
} catch (Exception e) {
System.err.println("⚠️ 图片插入失败 (ossId: " + ossId + "):" + e.getMessage());
e.printStackTrace();
continue;
} finally {
baos.close(); // 关闭流
}
// 添加图注
if (description != null && !description.trim().isEmpty()) {
XWPFParagraph captionParagraph = document.createParagraph();
captionParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun captionRun = captionParagraph.createRun();
captionRun.setText("图" + (i + 1) + ":" + description);
captionRun.setColor("666666");
captionRun.setFontSize(10);
captionRun.setItalic(true);
captionRun.setFontFamily("宋体");
}
// 每张图后空一行
document.createParagraph();
}
}
// ✅ 根据文件扩展名判断图片类型
private static int getPictureType(String filename) {
String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
return switch (ext) {
case "png" -> XWPFDocument.PICTURE_TYPE_PNG;
case "jpg", "jpeg" -> XWPFDocument.PICTURE_TYPE_JPEG;
case "gif" -> XWPFDocument.PICTURE_TYPE_GIF;
case "bmp" -> XWPFDocument.PICTURE_TYPE_BMP;
default -> XWPFDocument.PICTURE_TYPE_JPEG;
};
}
@NotNull
private static Map<String, Object> getData() {
// 1. 准备数据(用户填写的内容)
Map<String, Object> data = new LinkedHashMap<>();
data.put("siteName", "临安区龙岗镇站");
// ✅ 自动生成当前时间,并格式化为 "yyyy-MM-dd HH:mm:ss"
String currentDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
data.put("checkDateTime", currentDateTime);
data.put("operationUnit", "安徽蓝盾光电子股份有限公司");
data.put("checkPeople", "李工");
data.put("totalScore", "140"); // 28项 × 5分 = 140
// === 简单粗暴:score_01 到 score_28 全部设为 5 ===
for (int i = 1; i <= 28; i++) {
data.put("score_" + String.format("%02d", i), "5");
}
// -------------------- 零气测试 --------------------
double zero_flow = 5.0; // 零气MFC设定流量(L/min)
double zero_std = 4.98; // 标准流量计实测值(L/min)
// -------------------- 标气测试 --------------------
double span_flow = 100.0; // 标气MFC设定流量(ml/min)
double span_std = 101.5; // 标准流量计实测值(ml/min)
data.put("zero_flow", String.valueOf(zero_flow));
data.put("zero_std", String.valueOf(zero_std));
data.put("zero_error", calcError(zero_flow, zero_std)); // 自动计算
data.put("span_flow", String.valueOf(span_flow));
data.put("span_std", String.valueOf(span_std));
data.put("span_error", calcError(span_flow, span_std)); // 自动计算
// -------------------- SO2 流量测试 --------------------
double soDisplay = 0.8; // SO2显示流量(L/min)
double soStd = 0.78; // 标准流量计测值(L/min)
data.put("so_display", String.valueOf(soDisplay));
data.put("so_std", String.valueOf(soStd));
data.put("so_error", calcError(soDisplay, soStd)); // 自动计算:相对误差
// -------------------- SO2 浓度测试 --------------------
double soConcOutput = 500.0; // 标气稀释输出浓度(ppb)
double soConcResponse = 492.0; // 仪器响应浓度(ppb)
data.put("so_conc_output", String.valueOf(soConcOutput));
data.put("so_conc_response", String.valueOf(soConcResponse));
data.put("so_conc_error", calcError(soConcResponse, soConcOutput)); // (响应 - 输出)/输出 × 100%
// -------------------- t90响应时间(用户填写,不参与计算)--------------------
data.put("so_time", "4.2"); // 用户手动填写,单位:min,不参与任何计算
// -------------------- NO2 流量测试 --------------------
double noDisplay = 0.8;
double noStd = 0.78;
data.put("no_display", String.valueOf(noDisplay));
data.put("no_std", String.valueOf(noStd));
data.put("no_error", calcError(noDisplay, noStd)); // 自动计算:相对误差
// -------------------- NO 浓度测试 --------------------
double noConcOutput = 500.0; // 标气稀释输出浓度(ppb)
double noConcResponse = 492.0; // 仪器响应浓度(ppb)
data.put("no_conc_output", String.valueOf(noConcOutput));
data.put("no_conc_response", String.valueOf(noConcResponse));
data.put("no_conc_error", calcError(noConcResponse, noConcOutput)); // (响应 - 输出)/输出 × 100%
// -------------------- t90响应时间(用户填写,不参与计算)--------------------
data.put("no_time", "4.2"); // 用户手动填写,单位:min,不参与任何计算
// -------------------- CO 流量测试 --------------------
double coDisplay = 0.8; // SO2显示流量(L/min)
double coStd = 0.78; // 标准流量计测值(L/min)
data.put("co_display", String.valueOf(coDisplay));
data.put("co_std", String.valueOf(coStd));
data.put("co_error", calcError(coDisplay, coStd)); // 自动计算:相对误差
// -------------------- NO2 浓度测试 --------------------
double coConcOutput = 500.0; // 标气稀释输出浓度(ppb)
double coConcResponse = 492.0; // 仪器响应浓度(ppb)
data.put("co_conc_output", String.valueOf(coConcOutput));
data.put("co_conc_response", String.valueOf(coConcResponse));
data.put("co_conc_error", calcError(coConcResponse, coConcOutput)); // (响应 - 输出)/输出 × 100%
// -------------------- t90响应时间(用户填写,不参与计算)--------------------
data.put("co_time", "4.2"); // 用户手动填写,单位:min,不参与任何计算
double oDisplay = 0.8; // SO2显示流量(L/min)
double oStd = 0.78; // 标准流量计测值(L/min)
data.put("o_display", String.valueOf(oDisplay));
data.put("o_std", String.valueOf(oStd));
data.put("o_error", calcError(oDisplay, oStd)); // 自动计算:相对误差
double oConcOutput = 500.0; // 标气稀释输出浓度(ppb)
double oConcResponse = 492.0; // 仪器响应浓度(ppb)
data.put("o_conc_output", String.valueOf(oConcOutput));
data.put("o_conc_response", String.valueOf(oConcResponse));
data.put("o_conc_error", calcError(oConcResponse, oConcOutput)); // (响应 - 输出)/输出 × 100%
// -------------------- t90响应时间(用户填写,不参与计算)--------------------
data.put("o_time", "4.2"); // 用户手动填写,单位:min,不参与任何计算
//----------PM10 测试----------
double pmTenDisplay = 0.8;
double pmTenStd = 0.78;
data.put("pm_ten_display", String.valueOf(pmTenDisplay));
data.put("pm_ten_std", String.valueOf(pmTenStd));
data.put("pm_ten_error", calcError(pmTenDisplay, pmTenStd)); // 自动计算:相对误差
data.put("pm_ten_k", 0.8);
data.put("slope_a", 0.8);
//----------PM2 测试----------
double pmTwoDisplay = 0.8;
double pmTwoStd = 0.78;
data.put("pm_two_display", String.valueOf(pmTwoDisplay));
data.put("pm_two_std", String.valueOf(pmTwoStd));
data.put("pm_two_error", calcError(pmTwoDisplay, pmTwoStd)); // 自动计算:相对误差
data.put("pm_two_k", 0.5);
data.put("slope_b", 0.5);
System.out.println("✅ 数据准备完成!");
System.out.println(JSONUtil.toJsonStr(data));
//System.out.println(JSONUtil.toJsonPrettyStr(data)); // 格式化 + 缩进输出
JSONObject jsonObject = JSONUtil.parseObj(data);
System.out.println(jsonObject.toStringPretty());
return data;
}
// 工具方法:计算相对误差,保留1位小数
private static String calcError(double mfcFlow, double stdFlow) {
if (Math.abs(stdFlow) < 0.0001) return "0.0"; // 防止除0
double error = (mfcFlow - stdFlow) / stdFlow * 100;
return String.format("%.1f", error);
}
// ✅ 假设这是你要插入的图片路径列表(可以来自数据库、文件夹扫描等)
private static final List<String> IMAGE_PATHS = List.of(
"D:\\Users\\14212\\Desktop\\故障图片.png",
"D:\\Users\\14212\\Desktop\\故障图片.png",
"D:\\Users\\14212\\Desktop\\故障图片.png"
// 可以是 0 个、1 个、N 个
);
}

Loading…
Cancel
Save