diff --git a/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DocxTemplateController.java b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DocxTemplateController.java new file mode 100644 index 0000000..1c3af35 --- /dev/null +++ b/application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DocxTemplateController.java @@ -0,0 +1,141 @@ + +package apelet.tenantadmin.tenant.controller; + +import apelet.common.core.annotation.MyRequestBody; +import apelet.common.core.exception.MyRuntimeException; +import apelet.common.core.object.ObjectValue; +import apelet.common.generator.utils.OrmGenDataSourceUtil; +import cn.hutool.core.io.IoUtil; +import org.apache.poi.xwpf.usermodel.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@RestController +@RequestMapping("/api/template") +public class DocxTemplateController { + + + @Autowired + private OrmGenDataSourceUtil ormGenDataSourceUtil; + + private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{(.+?)\\}"); + + /** + * 替换字符串中 ${key},JDK8兼容 + */ + private String replaceContent(String text, Map dataMap) { + if (text == null) return ""; + Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); + StringBuffer sb = new StringBuffer(); + while (matcher.find()) { + String key = matcher.group(1).trim(); + Object val = dataMap.get(key); + String realVal = val == null ? "" : val.toString(); + matcher.appendReplacement(sb, Matcher.quoteReplacement(realVal)); + } + matcher.appendTail(sb); + return sb.toString(); + } + + @GetMapping("/downloadDocx") + public void downloadDocx(@RequestParam("id") String quotationId, HttpServletResponse response) { + XWPFDocument document = null; + InputStream templateIs = null; + OutputStream out = null; + try { + // 1. 查数据 + ObjectValue objectValue = ormGenDataSourceUtil.queryOne("quotation", quotationId); + Map hashMap = new HashMap<>(); + hashMap.put("name", objectValue.getString("name")); + hashMap.put("number", objectValue.getString("number")); + hashMap.put("create_time", objectValue.getString("create_time")); + hashMap.put("qty", objectValue.getObjectValue("qty")); + ObjectValue managerperson = objectValue.getObjectValue("managerperson"); + if(managerperson != null){ + managerperson = ormGenDataSourceUtil.queryOne(managerperson.getTableName(), managerperson.getString("id")); + hashMap.put("managerperson",1); + } + // 2. 读模板 + File file = new File("D:\\work\\xykj-project\\xhgl\\zz-resource\\quotation_template.docx"); + templateIs = new FileInputStream(file); + document = new XWPFDocument(templateIs); + // 3. 替换占位符 + replaceParagraph(document, hashMap); + replaceTable(document, hashMap); + // 4. 设置响应头 —— 关键! + response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + response.setCharacterEncoding("UTF-8"); + String fileName = URLEncoder.encode("报价单.docx", StandardCharsets.UTF_8.name()) + .replaceAll("\\+", "%20"); + // 兼容各浏览器的文件名写法 + response.setHeader("Content-Disposition", + "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + fileName); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + // 5. 写出 + out = response.getOutputStream(); + document.write(out); + out.flush(); + } catch (Exception e) { + e.printStackTrace(); + throw new MyRuntimeException("导出失败: " + e.getMessage()); + } finally { + IoUtil.close(document); + IoUtil.close(templateIs); + IoUtil.close(out); + } + } + + + + + private void replaceParagraph(XWPFDocument document, Map dataMap) { + for (XWPFParagraph paragraph : document.getParagraphs()) { + String text = paragraph.getText(); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); + if (!matcher.find()) { + continue; + } + //清空原有run + for (XWPFRun run : paragraph.getRuns()) { + run.setText("", 0); + } + String newText = replaceContent(text, dataMap); + paragraph.createRun().setText(newText); + } + } + + private void replaceTable(XWPFDocument document, Map dataMap) { + for (XWPFTable table : document.getTables()) { + for (XWPFTableRow row : table.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + for (XWPFParagraph paragraph : cell.getParagraphs()) { + String text = paragraph.getText(); + Matcher matcher = PLACEHOLDER_PATTERN.matcher(text); + if (!matcher.find()) { + continue; + } + for (XWPFRun run : paragraph.getRuns()) { + run.setText("", 0); + } + String newText = replaceContent(text, dataMap); + paragraph.createRun().setText(newText); + } + } + } + } + } + + +}