main
HuangHai 1 month ago
parent 91edaf6d38
commit 259bf1d701

@ -321,6 +321,23 @@
<artifactId>poi-scratchpad</artifactId>
<version>5.2.5</version>
</dependency>
<!-- CommonMark for Markdown parsing -->
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark</artifactId>
<version>0.21.0</version>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark-ext-gfm-tables</artifactId>
<version>0.21.0</version>
</dependency>
<dependency>
<groupId>org.commonmark</groupId>
<artifactId>commonmark-ext-heading-anchor</artifactId>
<version>0.21.0</version>
</dependency>
</dependencies>
<build>
<plugins>

@ -4,11 +4,20 @@ import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.commonmark.node.*;
import org.commonmark.parser.Parser;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.ext.heading.anchor.HeadingAnchorExtension;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* Word - Word
@ -105,52 +114,280 @@ public class WordGenerator {
}
/**
*
* - 使CommonMarkMarkdown
*/
private static void addAnalysisContent(XWPFDocument document, String analysisResult) {
String[] lines = analysisResult.split("\n");
XWPFParagraph currentParagraph = null;
XWPFRun currentRun = null;
for (String line : lines) {
if (line.trim().isEmpty()) {
// 空行,创建新段落
document.createParagraph();
currentParagraph = null;
currentRun = null;
} else {
// 检查是否是标题行
boolean isTitle = isTitle(line);
if (currentParagraph == null) {
currentParagraph = document.createParagraph();
currentRun = currentParagraph.createRun();
currentRun.setFontFamily("宋体");
currentRun.setFontSize(12);
// 创建CommonMark解析器支持表格和标题锚点扩展
List<org.commonmark.Extension> extensions = Arrays.asList(
TablesExtension.create(),
HeadingAnchorExtension.create()
);
Parser parser = Parser.builder().extensions(extensions).build();
// 解析Markdown文档
Node markdownDoc = parser.parse(analysisResult);
// 遍历并处理所有节点
processMarkdownNode(document, markdownDoc);
}
/**
* MarkdownWord
*/
private static void processMarkdownNode(XWPFDocument document, Node node) {
Node child = node.getFirstChild();
while (child != null) {
if (child instanceof Heading) {
processHeading(document, (Heading) child);
} else if (child instanceof Paragraph) {
processParagraph(document, (Paragraph) child);
} else if (child instanceof BulletList) {
processBulletList(document, (BulletList) child);
} else if (child instanceof OrderedList) {
processOrderedList(document, (OrderedList) child);
} else if (child instanceof org.commonmark.ext.gfm.tables.TableBlock) {
processTable(document, (org.commonmark.ext.gfm.tables.TableBlock) child);
} else if (child instanceof BlockQuote) {
processBlockQuote(document, (BlockQuote) child);
} else if (child instanceof FencedCodeBlock || child instanceof IndentedCodeBlock) {
processCodeBlock(document, child);
}
child = child.getNext();
}
}
/**
*
*/
private static void processHeading(XWPFDocument document, Heading heading) {
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
String text = getTextContent(heading);
run.setText(text);
run.setBold(true);
run.setFontFamily("宋体");
// 根据标题级别设置字体大小
switch (heading.getLevel()) {
case 1:
run.setFontSize(18);
paragraph.setAlignment(ParagraphAlignment.CENTER);
break;
case 2:
run.setFontSize(16);
break;
case 3:
run.setFontSize(14);
break;
case 4:
run.setFontSize(13);
break;
default:
run.setFontSize(12);
break;
}
}
/**
*
*/
private static void processParagraph(XWPFDocument document, Paragraph para) {
XWPFParagraph paragraph = document.createParagraph();
processInlineNodes(paragraph, para.getFirstChild());
}
/**
*
*/
private static void processBulletList(XWPFDocument document, BulletList bulletList) {
Node listItem = bulletList.getFirstChild();
while (listItem != null) {
if (listItem instanceof ListItem) {
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("• " + getTextContent(listItem));
run.setFontSize(12);
run.setFontFamily("宋体");
}
listItem = listItem.getNext();
}
}
/**
*
*/
private static void processOrderedList(XWPFDocument document, OrderedList orderedList) {
Node listItem = orderedList.getFirstChild();
int counter = orderedList.getStartNumber();
while (listItem != null) {
if (listItem instanceof ListItem) {
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText(counter + ". " + getTextContent(listItem));
run.setFontSize(12);
run.setFontFamily("宋体");
counter++;
}
listItem = listItem.getNext();
}
}
/**
*
*/
private static void processTable(XWPFDocument document, org.commonmark.ext.gfm.tables.TableBlock table) {
// 计算表格列数
int cols = 0;
Node firstRow = table.getFirstChild();
if (firstRow instanceof org.commonmark.ext.gfm.tables.TableHead) {
Node headerRow = firstRow.getFirstChild();
if (headerRow instanceof org.commonmark.ext.gfm.tables.TableRow) {
Node cell = headerRow.getFirstChild();
while (cell != null) {
cols++;
cell = cell.getNext();
}
if (isTitle) {
// 如果当前段落已有内容,创建新段落
String currentText = currentRun.getText(0);
if (currentText != null && !currentText.isEmpty()) {
currentParagraph = document.createParagraph();
currentRun = currentParagraph.createRun();
currentRun.setFontFamily("宋体");
}
currentRun.setText(line);
currentRun.setBold(true);
currentRun.setFontSize(14);
currentParagraph = null; // 强制下一行创建新段落
currentRun = null;
} else {
// 普通内容
String currentText = currentRun.getText(0);
if (currentText != null && !currentText.isEmpty()) {
currentRun.addBreak();
}
}
if (cols > 0) {
XWPFTable wordTable = document.createTable();
Node tableChild = table.getFirstChild();
boolean isFirstRow = true;
while (tableChild != null) {
if (tableChild instanceof org.commonmark.ext.gfm.tables.TableHead ||
tableChild instanceof org.commonmark.ext.gfm.tables.TableBody) {
Node rowNode = tableChild.getFirstChild();
while (rowNode != null) {
if (rowNode instanceof org.commonmark.ext.gfm.tables.TableRow) {
XWPFTableRow row;
if (isFirstRow) {
row = wordTable.getRow(0);
isFirstRow = false;
} else {
row = wordTable.createRow();
}
Node cellNode = rowNode.getFirstChild();
int cellIndex = 0;
while (cellNode != null && cellIndex < cols) {
if (cellNode instanceof org.commonmark.ext.gfm.tables.TableCell) {
XWPFTableCell cell = row.getCell(cellIndex);
if (cell == null) {
cell = row.addNewTableCell();
}
cell.setText(getTextContent(cellNode));
cellIndex++;
}
cellNode = cellNode.getNext();
}
}
rowNode = rowNode.getNext();
}
currentRun.setText(line);
currentRun.setFontSize(12);
}
tableChild = tableChild.getNext();
}
}
}
/**
*
*/
private static void processBlockQuote(XWPFDocument document, BlockQuote blockQuote) {
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("" + getTextContent(blockQuote));
run.setFontSize(12);
run.setFontFamily("宋体");
run.setItalic(true);
}
/**
*
*/
private static void processCodeBlock(XWPFDocument document, Node codeBlock) {
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
String code;
if (codeBlock instanceof FencedCodeBlock) {
code = ((FencedCodeBlock) codeBlock).getLiteral();
} else {
code = ((IndentedCodeBlock) codeBlock).getLiteral();
}
run.setText(code);
run.setFontSize(10);
run.setFontFamily("Courier New");
// 设置背景色(如果支持)
}
/**
*
*/
private static void processInlineNodes(XWPFParagraph paragraph, Node node) {
while (node != null) {
if (node instanceof Text) {
XWPFRun run = paragraph.createRun();
run.setText(((Text) node).getLiteral());
run.setFontSize(12);
run.setFontFamily("宋体");
} else if (node instanceof StrongEmphasis) {
XWPFRun run = paragraph.createRun();
run.setText(getTextContent(node));
run.setBold(true);
run.setFontSize(12);
run.setFontFamily("宋体");
} else if (node instanceof Emphasis) {
XWPFRun run = paragraph.createRun();
run.setText(getTextContent(node));
run.setItalic(true);
run.setFontSize(12);
run.setFontFamily("宋体");
} else if (node instanceof Code) {
XWPFRun run = paragraph.createRun();
run.setText(((Code) node).getLiteral());
run.setFontSize(10);
run.setFontFamily("Courier New");
} else if (node instanceof Link) {
XWPFRun run = paragraph.createRun();
run.setText(getTextContent(node) + " (" + ((Link) node).getDestination() + ")");
run.setFontSize(12);
run.setFontFamily("宋体");
run.setColor("0000FF");
} else {
// 递归处理子节点
processInlineNodes(paragraph, node.getFirstChild());
}
node = node.getNext();
}
}
/**
*
*/
private static String getTextContent(Node node) {
StringBuilder text = new StringBuilder();
extractText(node, text);
return text.toString().trim();
}
/**
*
*/
private static void extractText(Node node, StringBuilder text) {
if (node instanceof Text) {
text.append(((Text) node).getLiteral());
} else if (node instanceof Code) {
text.append(((Code) node).getLiteral());
} else {
Node child = node.getFirstChild();
while (child != null) {
extractText(child, text);
child = child.getNext();
}
}
}

@ -65,20 +65,20 @@ public class YunNanModel {
public String createAnalysisPrompt(String dataContent, String[] regions) {
String regionNames = String.join("和", regions);
return "你是一位专业的教育数据分析专家,请基于以下数据对" + regionNames + "的教育资源配置情况进行深入对比分析。\n\n" +
"重要要求:请生成结构化的纯文本格式报告使用清晰的段落结构不要使用markdown语法。\n\n" +
"重要要求:请生成结构化的Markdown格式报告使用标准的Markdown语法包括标题、列表、粗体等格式。\n\n" +
"请按照以下结构进行分析并生成专业的分析报告:\n\n" +
"1. 执行摘要\n" +
" 简要概述两州教育资源配置的整体情况和主要发现\n\n" +
"2. 数据概览\n" +
" 两州基本教育数据对比和关键指标汇总\n\n" +
"3. 详细对比分析\n" +
" 教育资源配置水平对比、发展趋势分析、优势与不足分析\n\n" +
"4. 问题识别\n" +
" 存在的主要问题和资源配置不均衡情况\n\n" +
"5. 建议与对策\n" +
" 针对性改进建议和资源优化配置方案\n\n" +
"6. 结论\n" +
" 总体评价和未来发展方向\n\n" +
"## 1. 执行摘要\n" +
"简要概述两州教育资源配置的整体情况和主要发现\n\n" +
"## 2. 数据概览\n" +
"两州基本教育数据对比和关键指标汇总\n\n" +
"## 3. 详细对比分析\n" +
"教育资源配置水平对比、发展趋势分析、优势与不足分析\n\n" +
"## 4. 问题识别\n" +
"存在的主要问题和资源配置不均衡情况\n\n" +
"## 5. 建议与对策\n" +
"针对性改进建议和资源优化配置方案\n\n" +
"## 6. 结论\n" +
"总体评价和未来发展方向\n\n" +
"请确保分析客观、专业,数据引用准确,建议具有可操作性。\n\n" +
"=== 原始数据 ===\n" + dataContent;
}

@ -148,6 +148,7 @@ public class CallDeepSeek {
if (saveToFile && outputPath != null) {
FileUtil.writeString(responseContent, new File(outputPath), "UTF-8");
listener.onComplete("内容已成功保存到" + outputPath);
System.out.println("内容已成功保存到" + outputPath);
} else {
listener.onComplete(responseContent);
}

Loading…
Cancel
Save