This commit is contained in:
wangjinlei
2026-05-25 17:21:41 +08:00
parent 836b99311c
commit 4ac6e4da52
2 changed files with 229 additions and 5 deletions

View File

@@ -77,6 +77,11 @@
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>ch.stegmaier.java2tex</groupId>
<artifactId>latex</artifactId>
<version>0.6.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>

View File

@@ -209,20 +209,231 @@ public class TypesetController {
return new ReturnValue(ReturnCodeAndMsgEnum.Success);
}
/**
* 将Word文档内容转换为LaTeX格式
* @param filename 文件名
* @return ReturnValue 包含LaTeX代码的返回值对象
*/
@ApiOperation(value = "生成LaTeX排版代码")
@PostMapping("generateLatex")
public ReturnValue generateLatex(String filename) {
System.out.println("Generating LaTeX for file: " + filename);
StringBuilder latexContent = new StringBuilder();
try {
// 构建文件路径并打开文件输入流
File file = new File(this.BASE_DIR + filename);
FileInputStream fis = new FileInputStream(file);
XWPFDocument xdoc = new XWPFDocument(fis);
// 添加LaTeX文档基本结构
latexContent.append("\\documentclass{article}\n");
latexContent.append("\\usepackage[utf8]{inputenc}\n");
latexContent.append("\\usepackage{graphicx}\n");
latexContent.append("\\usepackage{amsmath}\n");
latexContent.append("\\usepackage{amsfonts}\n");
latexContent.append("\\usepackage{amssymb}\n");
latexContent.append("\\usepackage{hyperref}\n");
latexContent.append("\\begin{document}\n\n");
// 遍历文档段落,提取文本内容并处理格式标记
List<XWPFParagraph> paragraphs = xdoc.getParagraphs();
for (int i = 0; i < paragraphs.size(); i++) {
String paragraphText = "";
List<XWPFRun> runs = paragraphs.get(i).getRuns();
// 处理每个文本运行单元根据格式添加LaTeX命令
for (XWPFRun run : runs) {
String formattedText = "";
if (run.getText(0) == null) {
continue;
}
String text = run.getText(0);
// 转义LaTeX特殊字符
text = escapeLatexSpecialChars(text);
// 根据格式应用LaTeX命令
if (run.isBold() && run.isItalic()) {
formattedText = "\\textbf{\\textit{" + text + "}}";
} else if (run.isBold()) {
formattedText = "\\textbf{" + text + "}";
} else if (run.isItalic()) {
formattedText = "\\textit{" + text + "}";
} else {
formattedText = text;
}
// 处理上标和下标(如果可获取)
if (isSuperscript(run)) {
formattedText = "\\textsuperscript{" + text + "}";
} else if (isSubscript(run)) {
formattedText = "\\textsubscript{" + text + "}";
}
paragraphText += formattedText;
}
// 根据段落样式添加相应的LaTeX命令
String style = paragraphs.get(i).getStyle();
if (style != null) {
if (style.contains("Heading1")) {
latexContent.append("\\section{").append(paragraphText).append("}\n\n");
} else if (style.contains("Heading2")) {
latexContent.append("\\subsection{").append(paragraphText).append("}\n\n");
} else if (style.contains("Heading3")) {
latexContent.append("\\subsubsection{").append(paragraphText).append("}\n\n");
} else {
latexContent.append(paragraphText).append("\n\n");
}
} else {
latexContent.append(paragraphText).append("\n\n");
}
}
// 处理表格(如果需要)
List<XWPFTable> tables = xdoc.getTables();
for (XWPFTable table : tables) {
latexContent.append(convertTableToLatex(table)).append("\n\n");
}
// 结束文档
latexContent.append("\\end{document}");
fis.close();
xdoc.close();
} catch (Exception e) {
e.printStackTrace();
return new ReturnValue(ReturnCodeAndMsgEnum.SYSTEM_ERROR, "生成LaTeX代码失败: " + e.getMessage());
}
Map<String, String> result = new HashMap<>();
result.put("latex", latexContent.toString());
return new ReturnValue(ReturnCodeAndMsgEnum.Success, result);
}
/**
* 转义LaTeX特殊字符
* @param text 原始文本
* @return 转义后的文本
*/
private String escapeLatexSpecialChars(String text) {
if (text == null) return null;
return text.replace("\\", "\\textbackslash{}")
.replace("{", "\\{")
.replace("}", "\\}")
.replace("$", "\\$")
.replace("&", "\\&")
.replace("#", "\\#")
.replace("^", "\\textasciicircum{}")
.replace("_", "\\_")
.replace("~", "\\textasciitilde{}")
.replace("%", "\\%");
}
public ReturnValue myGenerateLatex(String filename) {
return new ReturnValue(ReturnCodeAndMsgEnum.Success);
}
/**
* 检查是否为上标格式需要根据实际API调整实现
* @param run XWPFRun对象
* @return 是否为上标
*/
private boolean isSuperscript(XWPFRun run) {
// 这里需要根据实际的API来判断上标格式
// 目前Apache POI可能没有直接的方法检查上标
// 可能需要通过其他方式判断,例如字体位置等
return false;
}
/**
* 检查是否为下标格式需要根据实际API调整实现
* @param run XWPFRun对象
* @return 是否为下标
*/
private boolean isSubscript(XWPFRun run) {
// 这里需要根据实际的API来判断下标格式
// 目前Apache POI可能没有直接的方法检查下标
// 可能需要通过其他方式判断,例如字体位置等
return false;
}
/**
* 将Word表格转换为LaTeX表格
* @param table XWPFTable对象
* @return LaTeX表格代码
*/
private String convertTableToLatex(XWPFTable table) {
StringBuilder latexTable = new StringBuilder();
latexTable.append("\\begin{tabular}{|");
// 确定列数并添加列定义
if (table.getRows().size() > 0) {
int columnCount = table.getRows().get(0).getTableCells().size();
for (int i = 0; i < columnCount; i++) {
latexTable.append("l|"); // 默认左对齐
}
}
latexTable.append("}\n\\hline\n");
// 添加表格内容
for (XWPFTableRow row : table.getRows()) {
List<XWPFTableCell> cells = row.getTableCells();
for (int i = 0; i < cells.size(); i++) {
XWPFTableCell cell = cells.get(i);
String cellText = cell.getText();
cellText = escapeLatexSpecialChars(cellText);
latexTable.append(cellText);
if (i < cells.size() - 1) {
latexTable.append(" & ");
}
}
latexTable.append(" \\\\\n\\hline\n");
}
latexTable.append("\\end{tabular}");
return latexTable.toString();
}
/**
* 读取Word文档文件内容
* @param filename 文件名
* @return ReturnValue 包含文件内容的返回值对象
*/
@ApiOperation(value = "读取文件")
@PostMapping("readdoc")
public ReturnValue myDocReader(String filename) {
System.out.println(filename);
ArrayList al = new ArrayList();
try {
// 构建文件路径并打开文件输入流
File file = new File(this.BASE_DIR + filename);
FileInputStream fis = new FileInputStream(file);
XWPFDocument xdoc = new XWPFDocument(fis);
// 遍历文档段落,提取文本内容并处理格式标记
List<XWPFParagraph> list = xdoc.getParagraphs();
for (int i = 0; i < list.size(); i++) {
String cache = "";
List<XWPFRun> runs = list.get(i).getRuns();
// 处理每个文本运行单元根据格式添加HTML标签
for (XWPFRun r : runs) {
String cach = "";
if (r.getText(0) == null) {
@@ -247,11 +458,13 @@ public class TypesetController {
return new ReturnValue(ReturnCodeAndMsgEnum.Success, al);
}
//网上专用文件读取接口
@ApiOperation(value = "网上专用文件读取接口")
@PostMapping("webReaddoc")
public ReturnValue DocReader(String fileRoute, HttpServletRequest request, HttpServletResponse response) {
ArrayList al = new ArrayList();
try {
InputStream inputStream = FileDownloadUtil.getInputStream(fileRoute);
@@ -330,14 +543,20 @@ public class TypesetController {
if (r.getText(0) == null) {
continue;
}
// 核心修改:转义 < 和 > 符号
String originalText = r.getText(0);
// 先转义 < 为 &lt;,再转义 > 为 &gt;
String escapedText = originalText.replace("<", "&lt;").replace(">", "&gt;");
if (r.isItalic() && r.isBold()) {
cach = "<b><i>" + r.getText(0) + "</i></b>";
cach = "<b><i>" + escapedText + "</i></b>";
} else if (r.isItalic()) {
cach = "<i>" + r.getText(0) + "</i>";
cach = "<i>" + escapedText + "</i>";
} else if (r.isBold()) {
cach = "<b>" + r.getText(0) + "</b>";
cach = "<b>" + escapedText + "</b>";
} else {
cach = r.getText(0);
cach = escapedText;
}
cache += cach;
}