完善审计报告生成接口

This commit is contained in:
2026-03-29 21:03:05 +08:00
parent 5dde003ab3
commit 4865d170df
4 changed files with 397 additions and 161 deletions

View File

@@ -26,6 +26,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.util.ZipSecureFile; import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.BreakType; import org.apache.poi.xwpf.usermodel.BreakType;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFRun;
@@ -35,6 +36,7 @@ import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblWidth;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@@ -47,6 +49,7 @@ import com.gxwebsoft.ai.config.TemplateConfig;
import com.gxwebsoft.ai.dto.AuditReportRequest; import com.gxwebsoft.ai.dto.AuditReportRequest;
import com.gxwebsoft.ai.dto.AuditReportSaveRequest; import com.gxwebsoft.ai.dto.AuditReportSaveRequest;
import com.gxwebsoft.ai.dto.KnowledgeBaseRequest; import com.gxwebsoft.ai.dto.KnowledgeBaseRequest;
import com.gxwebsoft.ai.dto.AuditReportDefaultTextRequest;
import com.gxwebsoft.ai.entity.AuditReport; import com.gxwebsoft.ai.entity.AuditReport;
import com.gxwebsoft.ai.enums.AuditReportEnum; import com.gxwebsoft.ai.enums.AuditReportEnum;
import com.gxwebsoft.ai.service.AuditReportService; import com.gxwebsoft.ai.service.AuditReportService;
@@ -382,7 +385,6 @@ public class AuditReportController extends BaseController {
sectionRun6.setFontSize(18); sectionRun6.setFontSize(18);
sectionRun6.setFontFamily("仿宋_GB2312"); sectionRun6.setFontFamily("仿宋_GB2312");
sectionRun6.setColor("2c3e50"); sectionRun6.setColor("2c3e50");
document.createParagraph();
// 添加固定内容(两段话) // 添加固定内容(两段话)
addOtherMattersSectionFixedContent(document, project); addOtherMattersSectionFixedContent(document, project);
@@ -563,7 +565,6 @@ public class AuditReportController extends BaseController {
sectionRun6.setFontSize(18); sectionRun6.setFontSize(18);
sectionRun6.setFontFamily("仿宋_GB2312"); sectionRun6.setFontFamily("仿宋_GB2312");
sectionRun6.setColor("2c3e50"); sectionRun6.setColor("2c3e50");
document.createParagraph();
// 添加固定内容(两段话) // 添加固定内容(两段话)
addOtherMattersSectionFixedContent(document, project); addOtherMattersSectionFixedContent(document, project);
@@ -699,7 +700,7 @@ public class AuditReportController extends BaseController {
XWPFParagraph sectionPara3 = document.createParagraph(); XWPFParagraph sectionPara3 = document.createParagraph();
sectionPara3.setAlignment(ParagraphAlignment.LEFT); sectionPara3.setAlignment(ParagraphAlignment.LEFT);
XWPFRun sectionRun3 = sectionPara3.createRun(); XWPFRun sectionRun3 = sectionPara3.createRun();
sectionRun3.setText(String.format("三、%s同志主要业绩", project.getPersonName())); sectionRun3.setText(String.format("三、%s主要业绩", project.getPersonName()));
sectionRun3.setBold(true); sectionRun3.setBold(true);
sectionRun3.setFontSize(18); sectionRun3.setFontSize(18);
sectionRun3.setFontFamily("仿宋_GB2312"); sectionRun3.setFontFamily("仿宋_GB2312");
@@ -891,40 +892,9 @@ public class AuditReportController extends BaseController {
* 添加签名页(尾页)- 从 doc/尾页.docx 读取 * 添加签名页(尾页)- 从 doc/尾页.docx 读取
*/ */
private void addSignaturePage(XWPFDocument document) { private void addSignaturePage(XWPFDocument document) {
try (InputStream is = this.getClass().getResourceAsStream("/doc/尾页.docx")) { // 直接使用代码绘制签名页,避免复制模板带来的格式问题
if (is == null) {
log.warn("未找到尾页模板文件,使用默认表格方式创建");
createSignaturePageWithTable(document); createSignaturePageWithTable(document);
return; log.info("成功添加尾页(使用代码直接绘制)");
}
XWPFDocument signatureDoc = new XWPFDocument(is);
// 使用底层 XML 复制方式,确保样式 100% 保留
// 1. 复制所有段落 - 直接追加到文档末尾
for (XWPFParagraph srcPara : signatureDoc.getParagraphs()) {
document.createParagraph();
int paraPos = document.getParagraphPos(document.getParagraphs().size() - 1);
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP ctp = (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP)srcPara.getCTP().copy();
document.getDocument().getBody().setPArray(paraPos, ctp);
}
// 2. 复制所有表格
for (XWPFTable srcTable : signatureDoc.getTables()) {
document.createTable();
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl cttbl = (org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl)srcTable.getCTTbl().copy();
// 获取文档中所有表格的 XML 数组并替换最后一个
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody body = document.getDocument().getBody();
// 添加新的 tbl 元素
body.addNewTbl();
body.setTblArray(body.getTblArray().length - 1, cttbl);
}
log.info("成功添加尾页(从 doc/尾页.docx 读取,使用底层 XML 复制)");
} catch (IOException e) {
log.error("读取尾页文档失败", e);
createSignaturePageWithTable(document);
}
} }
/** /**
@@ -1051,10 +1021,12 @@ public class AuditReportController extends BaseController {
// 创建一个 3 行 3 列的表格 // 创建一个 3 行 3 列的表格
XWPFTable table = document.createTable(3, 3); XWPFTable table = document.createTable(3, 3);
// 设置表格宽度为 100%(自适应文档宽度) // 设置表格样式 - 添加边框
// 表格宽度单位二十分之一磅A4 纸默认宽度约 9696约 485 磅)
CTTbl ctTbl = table.getCTTbl(); CTTbl ctTbl = table.getCTTbl();
CTTblPr tblPr = ctTbl.getTblPr(); CTTblPr tblPr = ctTbl.getTblPr();
// 设置表格宽度为 100%(自适应文档宽度)
// 表格宽度单位二十分之一磅A4 纸默认宽度约 9696约 485 磅)
CTTblWidth tblWidth = tblPr.getTblW(); CTTblWidth tblWidth = tblPr.getTblW();
if (tblWidth == null) { if (tblWidth == null) {
tblWidth = tblPr.addNewTblW(); tblWidth = tblPr.addNewTblW();
@@ -1065,10 +1037,49 @@ public class AuditReportController extends BaseController {
// 设置表格右对齐 // 设置表格右对齐
tblPr.addNewJc().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc.RIGHT); tblPr.addNewJc().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc.RIGHT);
// 设置表格边框 - 保留所有边框,包括内部横线
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders borders = tblPr.addNewTblBorders();
// 上边框(实线)
borders.addNewTop().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder.SINGLE);
borders.getTop().setSz(java.math.BigInteger.valueOf(4));
borders.getTop().setSpace(java.math.BigInteger.valueOf(0));
// 下边框(实线)
borders.addNewBottom().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder.SINGLE);
borders.getBottom().setSz(java.math.BigInteger.valueOf(4));
borders.getBottom().setSpace(java.math.BigInteger.valueOf(0));
// 左边框(实线)
borders.addNewLeft().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder.SINGLE);
borders.getLeft().setSz(java.math.BigInteger.valueOf(4));
borders.getLeft().setSpace(java.math.BigInteger.valueOf(0));
// 右边框(实线)
borders.addNewRight().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder.SINGLE);
borders.getRight().setSz(java.math.BigInteger.valueOf(4));
borders.getRight().setSpace(java.math.BigInteger.valueOf(0));
// 内部横线(实线)- 第 2 行和第 3 行之间需要横线
borders.addNewInsideH().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder.SINGLE);
borders.getInsideH().setSz(java.math.BigInteger.valueOf(4));
borders.getInsideH().setSpace(java.math.BigInteger.valueOf(0));
// 内部竖线(实线)
borders.addNewInsideV().setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder.SINGLE);
borders.getInsideV().setSz(java.math.BigInteger.valueOf(4));
borders.getInsideV().setSpace(java.math.BigInteger.valueOf(0));
// 设置列宽比例(按照模板文件设置)
// 第 1 列XX 会计师事务所 - 约 15% 宽度
// 第 2 列:中国注册会计师 - 约 25% 宽度
// 第 3 列:签名区域 - 约 60% 宽度
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblGrid tblGrid = ctTbl.addNewTblGrid();
// 第 1 列宽度(约 1500 twips = 75 磅)
tblGrid.addNewGridCol().setW(java.math.BigInteger.valueOf(1500));
// 第 2 列宽度(约 2500 twips = 125 磅)
tblGrid.addNewGridCol().setW(java.math.BigInteger.valueOf(2500));
// 第 3 列宽度(约 6000 twips = 300 磅)
tblGrid.addNewGridCol().setW(java.math.BigInteger.valueOf(6000));
// 第一行 // 第一行
XWPFTableRow row1 = table.getRow(0); XWPFTableRow row1 = table.getRow(0);
// 设置第一行高度为 5 行字12px * 5 = 601 磅=1/72 英寸) // 设置第一行高度为 9 行字12 * 9 = 1081 磅=1/72 英寸)
row1.setHeight(4320); // 单位是二十分之一磅,60 磅 * 72 = 4320 row1.setHeight(7776); // 单位是二十分之一磅,108 磅 * 72 = 7776
// 第一行第一列XX 会计师事务所仿宋_GB2312小四- 跨两行合并 // 第一行第一列XX 会计师事务所仿宋_GB2312小四- 跨两行合并
XWPFTableCell cell1_1 = row1.getCell(0); XWPFTableCell cell1_1 = row1.getCell(0);
@@ -1087,27 +1098,97 @@ public class AuditReportController extends BaseController {
run1_1.setFontFamily("仿宋_GB2312"); run1_1.setFontFamily("仿宋_GB2312");
para1_1.setIndentationFirstLine(480); para1_1.setIndentationFirstLine(480);
// 第一行第二列中国注册会计师仿宋_GB2312小四 // 第一行第二列中国注册会计师仿宋_GB2312小四- 跨两行合并
XWPFTableCell cell1_2 = row1.getCell(1); XWPFTableCell cell1_2 = row1.getCell(1);
XWPFParagraph para1_2 = cell1_2.getParagraphs().get(0); // 设置垂直合并(向下合并)
XWPFRun run1_2 = para1_2.createRun(); org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr tcPr1_2 = cell1_2.getCTTc().getTcPr();
run1_2.setText("中国注册会计师"); if (tcPr1_2 == null) {
run1_2.setFontSize(12); // 小四 tcPr1_2 = cell1_2.getCTTc().addNewTcPr();
run1_2.setFontFamily("仿宋_GB2312"); }
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge vMerge1_2 = org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge.Factory.newInstance();
vMerge1_2.setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge.RESTART);
tcPr1_2.setVMerge(vMerge1_2);
// 第一行第三列签名线仿宋_GB2312小四 // 第 2 列内容:两个"中国注册会计师"之间间隔 7 个空行
// 第一个"中国注册会计师"
XWPFParagraph para1_2_first = cell1_2.addParagraph();
XWPFRun run1_2_first = para1_2_first.createRun();
run1_2_first.setText("中国注册会计师");
run1_2_first.setFontSize(12); // 小四
run1_2_first.setFontFamily("仿宋_GB2312");
// 添加 7 个空行(原来是 6 个,现在增加 1 个)
for (int i = 0; i < 7; i++) {
XWPFParagraph emptyPara = cell1_2.addParagraph();
emptyPara.createRun();
}
// 第二个"中国注册会计师"
XWPFParagraph para1_2_second = cell1_2.addParagraph();
XWPFRun run1_2_second = para1_2_second.createRun();
run1_2_second.setText("中国注册会计师");
run1_2_second.setFontSize(12); // 小四
run1_2_second.setFontFamily("仿宋_GB2312");
// 第一行第三列签名线仿宋_GB2312小四- 跨两行合并 - 先画下划线,再写 XXX
XWPFTableCell cell1_3 = row1.getCell(2); XWPFTableCell cell1_3 = row1.getCell(2);
XWPFParagraph para1_3 = cell1_3.getParagraphs().get(0); // 设置垂直合并(向下合并)
XWPFRun run1_3 = para1_3.createRun(); org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr tcPr1_3 = cell1_3.getCTTc().getTcPr();
run1_3.setText("XXX"); if (tcPr1_3 == null) {
run1_3.setFontSize(12); // 小四 tcPr1_3 = cell1_3.getCTTc().addNewTcPr();
run1_3.setFontFamily("仿宋_GB2312"); }
para1_3.setAlignment(ParagraphAlignment.CENTER); org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge vMerge1_3 = org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge.Factory.newInstance();
vMerge1_3.setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge.RESTART);
tcPr1_3.setVMerge(vMerge1_3);
// 第 3 列内容:
// 第一段:下划线(空行)
XWPFParagraph para1_3_line1 = cell1_3.addParagraph();
XWPFRun run1_3_line1 = para1_3_line1.createRun();
run1_3_line1.setText("____________________"); // 用下划线字符画线
run1_3_line1.setFontSize(12); // 小四
run1_3_line1.setFontFamily("仿宋_GB2312");
para1_3_line1.setAlignment(ParagraphAlignment.CENTER);
// 第二段XXX
XWPFParagraph para1_3_name1 = cell1_3.addParagraph();
XWPFRun run1_3_name1 = para1_3_name1.createRun();
run1_3_name1.setText("XXX");
run1_3_name1.setFontSize(12); // 小四
run1_3_name1.setFontFamily("仿宋_GB2312");
para1_3_name1.setAlignment(ParagraphAlignment.CENTER);
// 添加 5 个空行(让第二条下划线比第 2 列的第二个“中国注册会计师”高一行)
for (int i = 0; i < 5; i++) {
XWPFParagraph emptyPara = cell1_3.addParagraph();
emptyPara.createRun();
}
// 第三段:下划线(空行)
XWPFParagraph para1_3_line2 = cell1_3.addParagraph();
XWPFRun run1_3_line2 = para1_3_line2.createRun();
run1_3_line2.setText("____________________"); // 用下划线字符画线
run1_3_line2.setFontSize(12); // 小四
run1_3_line2.setFontFamily("仿宋_GB2312");
para1_3_line2.setAlignment(ParagraphAlignment.CENTER);
// 第四段XXX
XWPFParagraph para1_3_name2 = cell1_3.addParagraph();
XWPFRun run1_3_name2 = para1_3_name2.createRun();
run1_3_name2.setText("XXX");
run1_3_name2.setFontSize(12); // 小四
run1_3_name2.setFontFamily("仿宋_GB2312");
para1_3_name2.setAlignment(ParagraphAlignment.CENTER);
// XXX 下方添加 6 个空行(距离底部边框)
for (int i = 0; i < 6; i++) {
XWPFParagraph emptyPara = cell1_3.addParagraph();
emptyPara.createRun();
}
// 第二行 // 第二行
XWPFTableRow row2 = table.getRow(1); XWPFTableRow row2 = table.getRow(1);
// 设置第二行高度为 5 行字12px * 5 = 60 磅) // 设置固定高度,让行高自适应内容
row2.setHeight(4320); // 单位是二十分之一磅60 磅 * 72 = 4320
// 第二行第一列:被合并(不显示内容) // 第二行第一列:被合并(不显示内容)
XWPFTableCell cell2_1 = row2.getCell(0); XWPFTableCell cell2_1 = row2.getCell(0);
@@ -1120,22 +1201,27 @@ public class AuditReportController extends BaseController {
vMerge2.setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge.CONTINUE); vMerge2.setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge.CONTINUE);
tcPr2_1.setVMerge(vMerge2); tcPr2_1.setVMerge(vMerge2);
// 第二行第二列:中国注册会计师仿宋_GB2312小四 // 第二行第二列:被合并(不显示内容
XWPFTableCell cell2_2 = row2.getCell(1); XWPFTableCell cell2_2 = row2.getCell(1);
XWPFParagraph para2_2 = cell2_2.getParagraphs().get(0); // 设置垂直合并(继续上一行的合并)
XWPFRun run2_2 = para2_2.createRun(); org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr tcPr2_2 = cell2_2.getCTTc().getTcPr();
run2_2.setText("中国注册会计师"); if (tcPr2_2 == null) {
run2_2.setFontSize(12); // 小四 tcPr2_2 = cell2_2.getCTTc().addNewTcPr();
run2_2.setFontFamily("仿宋_GB2312"); }
org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge vMerge2_2 = org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge.Factory.newInstance();
vMerge2_2.setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge.CONTINUE);
tcPr2_2.setVMerge(vMerge2_2);
// 第二行第三列:签名仿宋_GB2312小四 // 第二行第三列:被合并(不显示内容
XWPFTableCell cell2_3 = row2.getCell(2); XWPFTableCell cell2_3 = row2.getCell(2);
XWPFParagraph para2_3 = cell2_3.getParagraphs().get(0); // 设置垂直合并(继续上一行的合并)
XWPFRun run2_3 = para2_3.createRun(); org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr tcPr2_3 = cell2_3.getCTTc().getTcPr();
run2_3.setText("XXX"); if (tcPr2_3 == null) {
run2_3.setFontSize(12); // 小四 tcPr2_3 = cell2_3.getCTTc().addNewTcPr();
run2_3.setFontFamily("仿宋_GB2312"); }
para2_3.setAlignment(ParagraphAlignment.CENTER); org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge vMerge2_3 = org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge.Factory.newInstance();
vMerge2_3.setVal(org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge.CONTINUE);
tcPr2_3.setVMerge(vMerge2_3);
// 第三行 - 使用 gridAfter 来正确合并单元格 // 第三行 - 使用 gridAfter 来正确合并单元格
XWPFTableRow row3 = table.getRow(2); XWPFTableRow row3 = table.getRow(2);
@@ -1184,10 +1270,16 @@ public class AuditReportController extends BaseController {
private void addBodyTitle(XWPFDocument document, String title) throws IOException { private void addBodyTitle(XWPFDocument document, String title) throws IOException {
XWPFParagraph titlePara = document.createParagraph(); XWPFParagraph titlePara = document.createParagraph();
titlePara.setAlignment(ParagraphAlignment.CENTER); titlePara.setAlignment(ParagraphAlignment.CENTER);
// 设置行距为 1.5 倍
CTSpacing spacing = titlePara.getCTP().addNewPPr().addNewSpacing();
spacing.setLineRule(org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule.AUTO);
spacing.setLine(java.math.BigInteger.valueOf(360)); // 1.5 倍行距
XWPFRun titleRun = titlePara.createRun(); XWPFRun titleRun = titlePara.createRun();
titleRun.setText(title); titleRun.setText(title);
titleRun.setBold(true); titleRun.setBold(true);
titleRun.setFontSize(16); // 三号 titleRun.setFontSize(16); // 三号 (16 磅)
titleRun.setFontFamily("仿宋_GB2312"); titleRun.setFontFamily("仿宋_GB2312");
// 添加 2 个空行 // 添加 2 个空行
@@ -1218,6 +1310,12 @@ public class AuditReportController extends BaseController {
private void addDocumentNumber(XWPFDocument document, String docNumber) throws IOException { private void addDocumentNumber(XWPFDocument document, String docNumber) throws IOException {
XWPFParagraph para = document.createParagraph(); XWPFParagraph para = document.createParagraph();
para.setAlignment(ParagraphAlignment.RIGHT); para.setAlignment(ParagraphAlignment.RIGHT);
// 设置行距为 1.5 倍
CTSpacing spacing = para.getCTP().addNewPPr().addNewSpacing();
spacing.setLineRule(org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule.AUTO);
spacing.setLine(java.math.BigInteger.valueOf(360)); // 1.5 倍行距
XWPFRun run = para.createRun(); XWPFRun run = para.createRun();
run.setText(docNumber); run.setText(docNumber);
run.setFontSize(12); // 小四 run.setFontSize(12); // 小四
@@ -1235,6 +1333,12 @@ public class AuditReportController extends BaseController {
private void addClientUnit(XWPFDocument document, PwlProject project) throws IOException { private void addClientUnit(XWPFDocument document, PwlProject project) throws IOException {
XWPFParagraph para = document.createParagraph(); XWPFParagraph para = document.createParagraph();
para.setAlignment(ParagraphAlignment.LEFT); para.setAlignment(ParagraphAlignment.LEFT);
// 设置行距为 1.5 倍
CTSpacing spacing = para.getCTP().addNewPPr().addNewSpacing();
spacing.setLineRule(org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule.AUTO);
spacing.setLine(java.math.BigInteger.valueOf(360)); // 1.5 倍行距
XWPFRun run = para.createRun(); XWPFRun run = para.createRun();
run.setText(project.getName()+":"); run.setText(project.getName()+":");
run.setFontSize(12); // 小四 run.setFontSize(12); // 小四
@@ -1262,8 +1366,14 @@ public class AuditReportController extends BaseController {
// 整段话作为一个段落仿宋_GB2312小四 // 整段话作为一个段落仿宋_GB2312小四
XWPFParagraph para = document.createParagraph(); XWPFParagraph para = document.createParagraph();
para.setAlignment(ParagraphAlignment.LEFT); para.setAlignment(ParagraphAlignment.LEFT);
// 设置行距为 1.5 倍
CTSpacing spacing = para.getCTP().addNewPPr().addNewSpacing();
spacing.setLineRule(org.openxmlformats.schemas.wordprocessingml.x2006.main.STLineSpacingRule.AUTO);
spacing.setLine(java.math.BigInteger.valueOf(360)); // 1.5 倍行距
XWPFRun run = para.createRun(); XWPFRun run = para.createRun();
run.setText(String.format(intro, project.getName(), project.getPersonName(), project.getPosition(), project.getPersonName())); run.setText(String.format(intro, project.getName(), project.getPersonName(), project.getPosition(), project.getPersonName()));;
run.setFontSize(12); // 小四 run.setFontSize(12); // 小四
run.setFontFamily("仿宋_GB2312"); run.setFontFamily("仿宋_GB2312");
@@ -1304,9 +1414,6 @@ public class AuditReportController extends BaseController {
sectionRun.setFontSize(16); // 三号 sectionRun.setFontSize(16); // 三号
sectionRun.setFontFamily("仿宋_GB2312"); sectionRun.setFontFamily("仿宋_GB2312");
// 添加空行
document.createParagraph();
// 添加子章节 // 添加子章节
if (subSections != null && !subSections.isEmpty()) { if (subSections != null && !subSections.isEmpty()) {
for (String subSection : subSections) { for (String subSection : subSections) {
@@ -1378,9 +1485,6 @@ public class AuditReportController extends BaseController {
sectionRun.setFontSize(16); // 三号 sectionRun.setFontSize(16); // 三号
sectionRun.setFontFamily("仿宋_GB2312"); sectionRun.setFontFamily("仿宋_GB2312");
// 添加空行
document.createParagraph();
// 添加子章节内容(根据固定的子章节结构) // 添加子章节内容(根据固定的子章节结构)
if (formCommits != null && !formCommits.isEmpty()) { if (formCommits != null && !formCommits.isEmpty()) {
for (Integer formCommit : formCommits) { for (Integer formCommit : formCommits) {
@@ -1396,9 +1500,6 @@ public class AuditReportController extends BaseController {
subsectionRun.setFontFamily("仿宋_GB2312"); subsectionRun.setFontFamily("仿宋_GB2312");
subsectionPara.setIndentationFirstLine(480); subsectionPara.setIndentationFirstLine(480);
// 添加空行
document.createParagraph();
// 添加子章节内容(如果有) // 添加子章节内容(如果有)
String content = contentMap.get(formCommit); String content = contentMap.get(formCommit);
if (content != null && !content.trim().isEmpty()) { if (content != null && !content.trim().isEmpty()) {
@@ -1461,9 +1562,6 @@ public class AuditReportController extends BaseController {
run1.setFontFamily("仿宋_GB2312"); run1.setFontFamily("仿宋_GB2312");
para1.setIndentationFirstLine(480); para1.setIndentationFirstLine(480);
// 添加空行
document.createParagraph();
// (二)本报告仅供委托方 XX 单位了解 XX 同志经济责任履行情况之用未经本所书面同意不得用作其他用途因使用不当造成的后果与执行本次专项审计业务的注册会计师及会计师事务所无关。仿宋_GB2312小四 // (二)本报告仅供委托方 XX 单位了解 XX 同志经济责任履行情况之用未经本所书面同意不得用作其他用途因使用不当造成的后果与执行本次专项审计业务的注册会计师及会计师事务所无关。仿宋_GB2312小四
XWPFParagraph para2 = document.createParagraph(); XWPFParagraph para2 = document.createParagraph();
para2.setAlignment(ParagraphAlignment.LEFT); para2.setAlignment(ParagraphAlignment.LEFT);
@@ -1472,9 +1570,6 @@ public class AuditReportController extends BaseController {
run2.setFontSize(12); // 小四 run2.setFontSize(12); // 小四
run2.setFontFamily("仿宋_GB2312"); run2.setFontFamily("仿宋_GB2312");
para2.setIndentationFirstLine(480); para2.setIndentationFirstLine(480);
// 添加空行
document.createParagraph();
} }
/** /**
@@ -1592,32 +1687,40 @@ public class AuditReportController extends BaseController {
*/ */
@Operation(summary = "AI 生成默认话术") @Operation(summary = "AI 生成默认话术")
@PostMapping("/generateDefaultText") @PostMapping("/generateDefaultText")
public ApiResult<?> generateDefaultText( public ApiResult<?> generateDefaultText(@RequestBody AuditReportDefaultTextRequest request) {
@RequestParam Integer projectId,
@RequestParam Integer formCommit,
@RequestParam(required = false) String chapterTitle) {
try { try {
final User loginUser = getLoginUser(); final User loginUser = getLoginUser();
log.info("AI 生成默认话术 - formCommit: {}, chapterTitle: {}", formCommit, chapterTitle); log.info("AI 生成默认话术 - formCommit: {}, chapterTitle: {}", request.getFormCommit(), request.getChapterTitle());
// 获取章节标题 // 获取章节标题
String title = chapterTitle; String title = request.getChapterTitle();
if (title == null || title.trim().isEmpty()) { if (title == null || title.trim().isEmpty()) {
title = AuditReportEnum.getByCode(formCommit) != null title = AuditReportEnum.getByCode(request.getFormCommit()) != null
? AuditReportEnum.getByCode(formCommit).getDesc() ? AuditReportEnum.getByCode(request.getFormCommit()).getDesc()
: "审计内容"; : "审计内容";
} }
// 从请求体中获取选中的取证单 ID 列表
List<Long> evidenceIds = new ArrayList<>();
if (request.getEvidenceIds() != null && !request.getEvidenceIds().isEmpty()) {
evidenceIds = request.getEvidenceIds().stream()
.map(Long::valueOf)
.collect(Collectors.toList());
}
// 构建提示词,根据 formCommit 使用不同的默认 prompt // 构建提示词,根据 formCommit 使用不同的默认 prompt
PwlProject project = pwlProjectService.getById(projectId); PwlProject project = pwlProjectService.getById(request.getProjectId());
if (project == null) {
return fail("项目不存在projectId: " + request.getProjectId(), null);
}
String companyName = project.getName(); String companyName = project.getName();
String personName = project.getPersonName(); String personName = project.getPersonName();
String prompt; String prompt;
if (formCommit == 20) { if (request.getFormCommit() == 20) {
// 二、总体评价的特殊提示词模板 // 二、总体评价的特殊提示词模板
// 查询该项目的所有取证单,判断是否有发现问题 // 查询该项目的所有取证单,判断是否有发现问题
LambdaQueryWrapper<AuditEvidence> evidenceWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<AuditEvidence> evidenceWrapper = new LambdaQueryWrapper<>();
evidenceWrapper.eq(AuditEvidence::getProjectId, projectId) evidenceWrapper.eq(AuditEvidence::getProjectId, request.getProjectId())
.eq(AuditEvidence::getDeleted, 0); .eq(AuditEvidence::getDeleted, 0);
List<AuditEvidence> allEvidences = auditEvidenceMapper.selectList(evidenceWrapper); List<AuditEvidence> allEvidences = auditEvidenceMapper.selectList(evidenceWrapper);
@@ -1634,61 +1737,78 @@ public class AuditReportController extends BaseController {
} }
prompt = promptBuilder.toString(); prompt = promptBuilder.toString();
} else if (formCommit == 30) { } else if (request.getFormCommit() == 30) {
// 三、XX 同志主要业绩的特殊提示词模板 // 三、XX 同志主要业绩的特殊提示词模板
prompt = String.format("请根据传入的取证单及相关资料库的数据,总结%s 任职期间的主要业绩。要求1.基于审计事实和数据2.突出重要贡献和成绩3.内容客观真实4.条理清晰。", personName); prompt = String.format("请根据传入的取证单及相关资料库的数据,总结%s 任职期间的主要业绩。要求1.基于审计事实和数据2.突出重要贡献和成绩3.内容客观真实4.条理清晰。", personName);
} else if (formCommit == 41) { } else if (request.getFormCommit() == 41) {
// XX 公司概况的特殊提示词模板 // XX 公司概况的特殊提示词模板
prompt = String.format("请生成关于'%s'的详细说明。要求按以下格式返回:\n" + prompt = String.format("请生成关于'%s'的详细说明。要求按以下格式返回:\n" +
"%s 为(说明企业性质,如:国有独资/控股公司),成立于 XXXX 年 X 月 X 日,注册资本**元,法定代表人 XX统一社会信用代码XXX。\n" + "%s 为(说明企业性质,如:国有独资/控股公司),成立于 XXXX 年 X 月 X 日,注册资本**元,法定代表人 XX统一社会信用代码XXX。\n" +
"公司主营业务为……(简述主营业务)。\n" + "公司主营业务为……(简述主营业务)。\n" +
"%s 下设……(组织架构)。", title, companyName, companyName); "%s 下设……(组织架构)。", title, companyName, companyName);
} else if (formCommit == 42) { } else if (request.getFormCommit() == 42) {
// XX 同志任职及分工情况的特殊提示词模板 // XX 同志任职及分工情况的特殊提示词模板
prompt = String.format("请生成关于《%s任职及分工情况》的详细说明。按以下格式返回\n" + prompt = String.format("请生成关于《%s任职及分工情况》的详细说明。按以下格式返回\n" +
"%s(同本章节标题人名) 自 XXXX 年 X 月至 XXXX 年 X 月任 XXXX单位名称XXX职务名称其主要职责是...(描述主要工作职责)。", personName, personName); "%s(同本章节标题人名) 自 XXXX 年 X 月至 XXXX 年 X 月任 XXXX单位名称XXX职务名称其主要职责是...(描述主要工作职责)。", personName, personName);
} else if (formCommit == 43) { } else if (request.getFormCommit() == 43) {
// (四)实施审计的基本情况,要求返回两段内容 // (四)实施审计的基本情况,要求返回两段内容
prompt = String.format("请生成关于'%s'的详细说明。要求返回两段内容:\n" + prompt = String.format("请生成关于'%s'的详细说明。要求返回两段内容:\n" +
"第一段格式:本次审计的时间范围是 20XX 年 XX 月 XX 日至 20XX 年 XX 月 XX 日。本次审计以 %s 会计报表、账簿、凭证及相关经济活动资料为基础,对 %s 任职期间履行经济责任的情况进行审查,主要包括:...(具体内容)。\n" + "第一段格式:本次审计的时间范围是 20XX 年 XX 月 XX 日至 20XX 年 XX 月 XX 日。本次审计以 %s 会计报表、账簿、凭证及相关经济活动资料为基础,对 %s 任职期间履行经济责任的情况进行审查,主要包括:...(具体内容)。\n" +
"第二段格式:%s 及 %s 对所提供的与审计相关的会计资料以及其他证明材料作出了书面承诺,对其真实性和完整性负责。我们按照审计实施方案确定的范围和内容,实施了在当时情况下认为有必要采取的审计程序和方法,包括(具体的程序和方案)等,并对重要事项进行了必要的延伸和追溯。", "第二段格式:%s 及 %s 对所提供的与审计相关的会计资料以及其他证明材料作出了书面承诺,对其真实性和完整性负责。我们按照审计实施方案确定的范围和内容,实施了在当时情况下认为有必要采取的审计程序和方法,包括(具体的程序和方案)等,并对重要事项进行了必要的延伸和追溯。",
title, companyName, personName, companyName, personName); title, companyName, personName, companyName, personName);
} else if (formCommit >= 51 && formCommit <= 57) { } else if (request.getFormCommit() >= 51 && request.getFormCommit() <= 57) {
// 四、履行经济责任的主要情况及审计发现的问题与责任认定的所有子章节 // 四、履行经济责任的主要情况及审计发现的问题与责任认定的所有子章节
// 要求返回三段:第一段概述和问题列示,第二段原因分析,第三段责任界定 // 要求返回三段:第一段概述和问题列示,第二段原因分析,第三段责任界定
prompt = String.format("请生成关于'%s'的详细说明。要求返回三段内容:\n" + StringBuilder promptBuilder = new StringBuilder();
"第一段(概述和问题列示):概述%s 任职期间履行经济责任所涉及的主要工作,重点说明其在职责范围内开展的经济活动和管理行为的核心内容;列示审计中发现的问题,例如:未严格落实国家相关政策要求、在某类业务操作中违反国有资产监管程序等,需列明具体事实、涉及金额以及所违反的具体规定条文;并对问题进行责任认定。\n" +
"第二段标题'原因分析:',针对上述问题,深入分析问题产生的原因,包括主观原因和客观原因,从制度机制、内部管理、人员素质等多个角度进行剖析。\n" + // 只传递取证单 ID 列表,让 AI 自行从数据库读取
"第三段标题'责任界定:',根据问题性质和情节轻重,结合%s 的职责分工,对其应承担的责任进行界定,明确是直接责任、主管责任还是领导责任,并说明认定依据。", if (evidenceIds != null && !evidenceIds.isEmpty()) {
title, personName, personName); // 将 ID 列表转换为逗号分隔的字符串
String evidenceIdsStr = evidenceIds.stream()
.map(String::valueOf)
.collect(Collectors.joining(","));
promptBuilder.append(String.format("取证单编号(仅用于查询数据,不要在输出中显示):%s\n", evidenceIdsStr));
}
// 生成指令
promptBuilder.append(String.format("请根据上述取证单数据,为%s生成审计报告该章节内容。\n", personName));
promptBuilder.append("要求生成三段:\n");
promptBuilder.append("1. 履职情况 + 发现问题及责任认定\n");
promptBuilder.append("2. 原因分析\n");
promptBuilder.append("3. 责任界定\n");
promptBuilder.append("\n注意输出内容中不要显示取证单编号直接生成正式的审计报告内容。\n");
prompt = promptBuilder.toString();
} }
else { else {
// 其他章节使用通用 prompt - 查询审计相关法规 // 其他章节使用通用 prompt - 查询审计相关法规
prompt = String.format("请查询与'%s'相关的所有审计法规、制度和政策文件。要求1.列出完整的法规名称2.注明颁布单位3.注明发文字号如有4.列出相关条款5.按重要性排序6.使用规范的格式。", title); prompt = String.format("请查询与'%s'相关的所有审计法规、制度和政策文件。要求1.列出完整的法规名称2.注明颁布单位3.注明发文字号如有4.列出相关条款5.按重要性排序6.使用规范的格式。", title);
} }
prompt += "(请注意:数据源必须来自资料库或者数据库相关数据,不能从其他地方获取数据。)"; prompt += "\n重要提示:数据源必须严格来自页面上选择的取证单数据,不能从其他地方获取数据。)";
log.info("生成审计报告标题:{}AI提示词: {}", chapterTitle, prompt); log.info("生成审计报告标题:{}AI 提示词{}", request.getChapterTitle(), prompt);
// 调用 AI 接口
String result = invokeDefaultTextGeneration(prompt, loginUser.getUsername()); // 调用 AI 接口,同时传递取证单 ID 列表
String result = invokeDefaultTextGeneration(prompt, loginUser.getUsername(), evidenceIds);
// 保存历史记录到数据库 // 保存历史记录到数据库
try { try {
// 构建请求数据 // 构建请求数据
JSONObject requestData = new JSONObject(); JSONObject requestData = new JSONObject();
requestData.put("projectId", projectId); requestData.put("projectId", request.getProjectId());
requestData.put("formCommit", formCommit); requestData.put("formCommit", request.getFormCommit());
requestData.put("chapterTitle", chapterTitle); requestData.put("chapterTitle", request.getChapterTitle());
// 根据 formCommit 生成不同的接口名称 // 根据 formCommit 生成不同的接口名称
String interfaceName = "/api/ai/auditReport/generateDefaultText_" + formCommit; String interfaceName = "/api/ai/auditReport/generateDefaultText_" + request.getFormCommit();
// 生成请求哈希 // 生成请求哈希
String requestHash = DigestUtil.md5Hex(interfaceName + ":" + requestData.toJSONString()); String requestHash = DigestUtil.md5Hex(interfaceName + ":" + requestData.toJSONString());
// 保存历史记录 // 保存历史记录
aiHistoryService.saveHistory( aiHistoryService.saveHistory(
Long.valueOf(projectId), Long.valueOf(request.getProjectId()),
requestHash, requestHash,
interfaceName, interfaceName,
requestData.toJSONString(), requestData.toJSONString(),
@@ -1697,7 +1817,7 @@ public class AuditReportController extends BaseController {
loginUser.getUsername(), loginUser.getUsername(),
loginUser.getTenantId() loginUser.getTenantId()
); );
log.info("保存 AI 生成历史记录成功 - projectId: {}, interfaceName: {}", projectId, interfaceName); log.info("保存 AI 生成历史记录成功 - projectId: {}, interfaceName: {}", request.getProjectId(), interfaceName);
} catch (Exception e) { } catch (Exception e) {
log.warn("保存 AI 生成历史记录失败", e); log.warn("保存 AI 生成历史记录失败", e);
} }
@@ -1749,7 +1869,7 @@ public class AuditReportController extends BaseController {
/** /**
* 调用 AI 生成默认话术 * 调用 AI 生成默认话术
*/ */
private String invokeDefaultTextGeneration(String prompt, String userName) { private String invokeDefaultTextGeneration(String prompt, String userName, List<Long> evidenceIds) {
// 构建请求体 // 构建请求体
JSONObject requestBody = new JSONObject(); JSONObject requestBody = new JSONObject();
JSONObject inputs = new JSONObject(); JSONObject inputs = new JSONObject();
@@ -1759,10 +1879,16 @@ public class AuditReportController extends BaseController {
inputs.put("suggestion", ""); inputs.put("suggestion", "");
inputs.put("title", "审计报告默认话术生成"); inputs.put("title", "审计报告默认话术生成");
// 如果有取证单 ID加入到请求中
if (evidenceIds != null && !evidenceIds.isEmpty()) {
inputs.put("evidenceIds", evidenceIds);
}
requestBody.put("inputs", inputs); requestBody.put("inputs", inputs);
requestBody.put("response_mode", "blocking"); requestBody.put("response_mode", "blocking");
requestBody.put("user", userName); requestBody.put("user", userName);
try {
// 发送 POST 请求 // 发送 POST 请求
String result = HttpUtil.createPost("http://1.14.159.185:8180/v1/workflows/run") String result = HttpUtil.createPost("http://1.14.159.185:8180/v1/workflows/run")
.header("Authorization", "Bearer app-d7Ok9FECVZG2Ybw9wpg7tGu9") .header("Authorization", "Bearer app-d7Ok9FECVZG2Ybw9wpg7tGu9")
@@ -1772,13 +1898,42 @@ public class AuditReportController extends BaseController {
.execute() .execute()
.body(); .body();
log.info("AI 工作流返回结果:{}", result);
// 解析返回的 JSON 字符串 // 解析返回的 JSON 字符串
JSONObject jsonResponse = JSONObject.parseObject(result); JSONObject jsonResponse = JSONObject.parseObject(result);
// 检查是否有错误
if (jsonResponse.containsKey("error")) {
JSONObject error = jsonResponse.getJSONObject("error");
String errorMsg = error != null ? error.getString("message") : "未知错误";
throw new RuntimeException("AI 服务返回错误:" + errorMsg);
}
JSONObject data = jsonResponse.getJSONObject("data"); JSONObject data = jsonResponse.getJSONObject("data");
if (data == null) {
log.error("AI 响应中缺少 data 字段,完整响应:{}", result);
throw new RuntimeException("AI 服务响应格式异常,缺少 data 字段");
}
JSONObject outputs = data.getJSONObject("outputs"); JSONObject outputs = data.getJSONObject("outputs");
if (outputs == null) {
log.error("AI 响应中缺少 outputs 字段,完整响应:{}", result);
throw new RuntimeException("AI 服务响应格式异常,缺少 outputs 字段");
}
String resultStr = outputs.getString("result"); String resultStr = outputs.getString("result");
return resultStr != null ? resultStr : ""; if (resultStr == null || resultStr.trim().isEmpty()) {
log.warn("AI 返回的结果为空,完整响应:{}", result);
return "";
}
return resultStr;
} catch (Exception e) {
log.error("调用 AI 工作流失败", e);
throw new RuntimeException("调用 AI 工作流失败:" + e.getMessage(), e);
}
} }
/** /**
@@ -1798,6 +1953,7 @@ public class AuditReportController extends BaseController {
requestBody.put("response_mode", "blocking"); requestBody.put("response_mode", "blocking");
requestBody.put("user", userName); requestBody.put("user", userName);
try {
// 发送 POST 请求 // 发送 POST 请求
String result = HttpUtil.createPost("http://1.14.159.185:8180/v1/workflows/run") String result = HttpUtil.createPost("http://1.14.159.185:8180/v1/workflows/run")
.header("Authorization", "Bearer app-d7Ok9FECVZG2Ybw9wpg7tGu9") .header("Authorization", "Bearer app-d7Ok9FECVZG2Ybw9wpg7tGu9")
@@ -1807,13 +1963,42 @@ public class AuditReportController extends BaseController {
.execute() .execute()
.body(); .body();
log.info("AI 工作流返回结果:{}", result);
// 解析返回的 JSON 字符串 // 解析返回的 JSON 字符串
JSONObject jsonResponse = JSONObject.parseObject(result); JSONObject jsonResponse = JSONObject.parseObject(result);
// 检查是否有错误
if (jsonResponse.containsKey("error")) {
JSONObject error = jsonResponse.getJSONObject("error");
String errorMsg = error != null ? error.getString("message") : "未知错误";
throw new RuntimeException("AI 服务返回错误:" + errorMsg);
}
JSONObject data = jsonResponse.getJSONObject("data"); JSONObject data = jsonResponse.getJSONObject("data");
if (data == null) {
log.error("AI 响应中缺少 data 字段,完整响应:{}", result);
throw new RuntimeException("AI 服务响应格式异常,缺少 data 字段");
}
JSONObject outputs = data.getJSONObject("outputs"); JSONObject outputs = data.getJSONObject("outputs");
if (outputs == null) {
log.error("AI 响应中缺少 outputs 字段,完整响应:{}", result);
throw new RuntimeException("AI 服务响应格式异常,缺少 outputs 字段");
}
String resultStr = outputs.getString("result"); String resultStr = outputs.getString("result");
return resultStr != null ? resultStr : ""; if (resultStr == null || resultStr.trim().isEmpty()) {
log.warn("AI 返回的结果为空,完整响应:{}", result);
return "";
}
return resultStr;
} catch (Exception e) {
log.error("调用 AI 工作流失败", e);
throw new RuntimeException("调用 AI 工作流失败:" + e.getMessage(), e);
}
} }
/** /**
@@ -1877,8 +2062,8 @@ public class AuditReportController extends BaseController {
suggestionsBuilder.toString() suggestionsBuilder.toString()
); );
// 调用 AI 接口 // 调用 AI 接口,传递取证单 ID
String result = invokeDefaultTextGeneration(prompt, loginUser.getUsername()); String result = invokeDefaultTextGeneration(prompt, loginUser.getUsername(), evidenceIds.stream().map(Long::valueOf).collect(Collectors.toList()));
return success(result); return success(result);
} catch (Exception e) { } catch (Exception e) {

View File

@@ -0,0 +1,26 @@
package com.gxwebsoft.ai.dto;
import java.util.List;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* AI 生成默认话术请求 DTO
*/
@Schema(description = "AI 生成默认话术请求")
@Data
public class AuditReportDefaultTextRequest {
@Schema(description = "项目 ID", required = true)
private Integer projectId;
@Schema(description = "章节类型编码1-11", required = true)
private Integer formCommit;
@Schema(description = "章节标题")
private String chapterTitle;
@Schema(description = "选中的取证单 ID 列表")
private List<Integer> evidenceIds;
}

View File

@@ -64,11 +64,11 @@ public class AuditReportServiceImpl extends ServiceImpl<AuditReportMapper, Audit
private static final String QUESTION_ANALYSIS_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run"; private static final String QUESTION_ANALYSIS_WORKFLOW_URL = "http://1.14.159.185:8180/v1/workflows/run";
private static final String QUESTION_ANALYSIS_TOKEN = "Bearer app-5CQWPxctsPape0HePWA3cP4Y"; private static final String QUESTION_ANALYSIS_TOKEN = "Bearer app-5CQWPxctsPape0HePWA3cP4Y";
private static final String QUOTA_STR = "1. 《自治区国资委监管企业内部审计管理办法》【颁布单位】广西壮族自治区人民政府国有资产监督管理委员会【涉及条款】第五条、第十七条、第二十条、第二十一条、第十四条、第十六条、第十七条\n" + private static final String QUOTA_STR = "1.《中华人民共和国审计法》;\n" +
"2. 《自治区国资委关于深化监管企业内部审计监督工作的实施意见》【颁布单位】广西壮族自治区人民政府国有资产监督管理委员会【发文字号】桂国资发(2020)43号【涉及条款】\n" + "2.《中华人民共和国注册会计师法》;\n" +
"3. 《广西壮族自治区直属企业审计监督工作办法》【颁布单位】中共广西壮族自治区委员会审计委员会办公室【发文字号】桂审委办202039号【涉及条款】第六条、第二十五条\n" + "3.《中国注册会计师执业准则》;\n" +
"4. 《广西北投公路建设投资集团有限公司内部审计管理办法2021年修订\n" + "4.《党政主要领导干部和国有企事业单位主要领导人员经济责任审计规定》中办发201945号以下简称“两办《规定》”\n" +
"5. 《BTGL公司经济责任审计管理办法2021年修订"; "5.《企业国有资本保值增值结果确认暂行办法》国资委令第9号";
@Override @Override
public JSONObject generateCompleteAuditReport(String auditContent, String fileName, public JSONObject generateCompleteAuditReport(String auditContent, String fileName,
@@ -501,7 +501,7 @@ public class AuditReportServiceImpl extends ServiceImpl<AuditReportMapper, Audit
List<Map<String, Object>> sectionOrder = new ArrayList<>(); List<Map<String, Object>> sectionOrder = new ArrayList<>();
sectionOrder.add(createSectionInfo(1, "基本情况", Arrays.asList(41, 42, 43))); sectionOrder.add(createSectionInfo(1, "基本情况", Arrays.asList(41, 42, 43)));
sectionOrder.add(createSectionInfo(2, "总体评价", null)); sectionOrder.add(createSectionInfo(2, "总体评价", null));
sectionOrder.add(createSectionInfo(3, String.format("%s同志主要业绩", project.getPersonName()), null)); sectionOrder.add(createSectionInfo(3, String.format("%s主要业绩", project.getPersonName()), null));
sectionOrder.add(createSectionInfo(4, "履行经济责任的主要情况及审计发现的问题与责任认定", Arrays.asList(51, 52, 53, 54, 55, 56, 57))); sectionOrder.add(createSectionInfo(4, "履行经济责任的主要情况及审计发现的问题与责任认定", Arrays.asList(51, 52, 53, 54, 55, 56, 57)));
sectionOrder.add(createSectionInfo(5, "审计建议", null)); sectionOrder.add(createSectionInfo(5, "审计建议", null));
sectionOrder.add(createSectionInfo(6, "其他事项说明", null)); sectionOrder.add(createSectionInfo(6, "其他事项说明", null));

View File

@@ -0,0 +1,25 @@
package com.gxwebsoft.common.core.config;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Tomcat 配置类,用于解决 URL 中包含特殊字符的问题
*/
@Configuration
public class TomcatConfig {
/**
* 允许 URL 中包含特殊字符(如中文、括号等)
* 解决错误Invalid character found in the request target
*/
@Bean
public TomcatConnectorCustomizer tomcatConnectorCustomizer() {
return connector -> {
// 允许 [] 等特殊字符
connector.setProperty("relaxedPathChars", "[]|{}^<>\"");
connector.setProperty("relaxedQueryChars", "[]|{}^<>\"\\`");
};
}
}