From 9ee7acd9d16e59224ee5184c89374f06d6592ad3 Mon Sep 17 00:00:00 2001
From: xyc <jc_xiong@hotmail.com>
Date: 星期日, 04 十月 2026 17:47:34 +0800
Subject: [PATCH] feat(holiday): 新增节假日综合运输客流量走势图
---
traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendWordServiceTest.java | 143 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 143 insertions(+), 0 deletions(-)
diff --git a/traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendWordServiceTest.java b/traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendWordServiceTest.java
new file mode 100644
index 0000000..d973be0
--- /dev/null
+++ b/traffic-audit-server/src/test/java/com/trafficaudit/holiday/service/HolidayTrendWordServiceTest.java
@@ -0,0 +1,143 @@
+package com.trafficaudit.holiday.service;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayInputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class HolidayTrendWordServiceTest {
+
+ @Test
+ void rebuildsTemplateWithSectionsChartsAndAppendix() throws Exception {
+ Path template = resolveTemplate();
+ byte[] templateBytes = Files.readAllBytes(template);
+ HolidayTrendWordService service = new HolidayTrendWordService();
+
+ List<HolidayTrendWordService.DocumentBlock> blocks = new ArrayList<>();
+ blocks.add(new HolidayTrendWordService.SectionBlock("涓�銆佹�讳綋鎯呭喌"));
+ blocks.add(new HolidayTrendWordService.ChartBlock("瀹㈡祦鎬婚噺", png(1),
+ new HolidayTrendWordService.ImageSize(5000000L, 3000000L)));
+ blocks.add(new HolidayTrendWordService.ChartBlock("瀹㈡祦鍗犳瘮", png(2), true,
+ new HolidayTrendWordService.ImageSize(4000000L, 2500000L)));
+ blocks.add(new HolidayTrendWordService.PageBreakBlock());
+ blocks.add(new HolidayTrendWordService.SectionBlock("闄勫綍涓� 姣忔棩瀹㈡祦鏋勬垚鍙樺寲"));
+ blocks.add(new HolidayTrendWordService.ChartBlock("姣忔棩鏋勬垚", png(3), true));
+
+ byte[] result = service.generate(templateBytes, 2026, blocks);
+ List<String> entries = entries(result);
+ assertTrue(entries.contains("word/media/image1.png"));
+ assertTrue(entries.contains("word/media/image2.png"));
+ assertTrue(entries.contains("word/media/image3.png"));
+ assertEquals(3, entries.stream().filter(name -> name.endsWith(".png")).count());
+
+ String documentXml = readEntry(result, "word/document.xml");
+ assertTrue(documentXml.contains("涓�銆佹�讳綋鎯呭喌"));
+ assertTrue(documentXml.contains("闄勫綍涓� 姣忔棩瀹㈡祦鏋勬垚鍙樺寲"));
+ assertTrue(documentXml.contains("瀹㈡祦鎬婚噺"));
+ assertTrue(documentXml.contains("姣忔棩鏋勬垚"));
+ assertTrue(!paragraphHasNumbering(documentXml, "涓�銆佹�讳綋鎯呭喌"));
+ assertTrue(!paragraphHasNumbering(documentXml, "闄勫綍涓� 姣忔棩瀹㈡祦鏋勬垚鍙樺寲"));
+ assertTrue(documentXml.contains("cx=\"5000000\" cy=\"3000000\""));
+ assertTrue(documentXml.contains("cx=\"4000000\" cy=\"2500000\""));
+ assertEquals(2, pageBreakCount(documentXml));
+
+ String rels = readEntry(result, "word/_rels/document.xml.rels");
+ assertTrue(rels.contains("rId100"));
+ assertTrue(rels.contains("rId102"));
+ }
+
+ private Path resolveTemplate() {
+ Path direct = Paths.get("docs/涓撻」缁熻/閲嶈鑺傚亣鏃�/2026骞村崄涓�鍋囨湡鍏ㄧ渷缁煎悎杩愯緭瀹㈡祦閲忚蛋鍔垮浘.docx");
+ if (Files.exists(direct)) return direct;
+ return Paths.get("..", "docs", "涓撻」缁熻", "閲嶈鑺傚亣鏃�", "2026骞村崄涓�鍋囨湡鍏ㄧ渷缁煎悎杩愯緭瀹㈡祦閲忚蛋鍔垮浘.docx");
+ }
+
+ private boolean paragraphHasNumbering(String documentXml, String text) throws Exception {
+ javax.xml.parsers.DocumentBuilderFactory factory =
+ javax.xml.parsers.DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ org.w3c.dom.Document document = factory.newDocumentBuilder().parse(
+ new java.io.ByteArrayInputStream(documentXml.getBytes("UTF-8")));
+ org.w3c.dom.NodeList paragraphs = document.getElementsByTagNameNS(
+ "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p");
+ for (int i = 0; i < paragraphs.getLength(); i++) {
+ org.w3c.dom.Element paragraph = (org.w3c.dom.Element) paragraphs.item(i);
+ StringBuilder builder = new StringBuilder();
+ org.w3c.dom.NodeList texts = paragraph.getElementsByTagNameNS(
+ "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "t");
+ for (int j = 0; j < texts.getLength(); j++) {
+ builder.append(texts.item(j).getTextContent());
+ }
+ if (text.equals(builder.toString())) {
+ return paragraph.getElementsByTagNameNS(
+ "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "numPr")
+ .getLength() > 0;
+ }
+ }
+ throw new AssertionError("Paragraph not found: " + text);
+ }
+
+ private int pageBreakCount(String documentXml) throws Exception {
+ javax.xml.parsers.DocumentBuilderFactory factory =
+ javax.xml.parsers.DocumentBuilderFactory.newInstance();
+ factory.setNamespaceAware(true);
+ org.w3c.dom.Document document = factory.newDocumentBuilder().parse(
+ new java.io.ByteArrayInputStream(documentXml.getBytes("UTF-8")));
+ org.w3c.dom.NodeList breaks = document.getElementsByTagNameNS(
+ "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "br");
+ int count = 0;
+ for (int i = 0; i < breaks.getLength(); i++) {
+ org.w3c.dom.Element br = (org.w3c.dom.Element) breaks.item(i);
+ if ("page".equals(br.getAttributeNS(
+ "http://schemas.openxmlformats.org/wordprocessingml/2006/main", "type"))) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private byte[] png(int seed) {
+ byte[] bytes = new byte[256];
+ Arrays.fill(bytes, (byte) seed);
+ bytes[0] = (byte) 0x89;
+ bytes[1] = 0x50;
+ bytes[2] = 0x4e;
+ bytes[3] = 0x47;
+ return bytes;
+ }
+
+ private List<String> entries(byte[] zipBytes) throws Exception {
+ List<String> result = new ArrayList<>();
+ try (ZipInputStream input = new ZipInputStream(new ByteArrayInputStream(zipBytes))) {
+ ZipEntry entry;
+ while ((entry = input.getNextEntry()) != null) result.add(entry.getName());
+ }
+ return result;
+ }
+
+ private String readEntry(byte[] zipBytes, String name) throws Exception {
+ try (ZipInputStream input = new ZipInputStream(new ByteArrayInputStream(zipBytes))) {
+ ZipEntry entry;
+ while ((entry = input.getNextEntry()) != null) {
+ if (name.equals(entry.getName())) {
+ java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = input.read(buffer)) > 0) out.write(buffer, 0, length);
+ return out.toString("UTF-8");
+ }
+ }
+ }
+ return "";
+ }
+}
--
Gitblit v1.9.1