新增下载审计取证单Word文档接口

This commit is contained in:
2026-02-04 16:50:28 +08:00
parent ddc1fa2dbd
commit 58c4d5a540
6 changed files with 144 additions and 5 deletions

View File

@@ -8,5 +8,9 @@ import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "ai.template")
public class TemplateConfig {
private String wordTemplatePath;
private String evidenceTemplatePath;
}

View File

@@ -16,6 +16,21 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.openxml4j.util.ZipSecureFile;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import java.util.ArrayList;
import java.util.List;
import com.gxwebsoft.ai.config.TemplateConfig;
import cn.afterturn.easypoi.word.WordExportUtil;
/**
* 审计取证单控制器
*/
@@ -27,6 +42,9 @@ public class AuditEvidenceController extends BaseController {
@Autowired
private AuditEvidenceService auditEvidenceService;
@Autowired
private TemplateConfig templateConfig;
/**
* 生成审计取证单
@@ -50,4 +68,109 @@ public class AuditEvidenceController extends BaseController {
return fail("生成审计取证单异常: " + e.getMessage());
}
}
}
/**
* 下载审计取证单Word文档
*/
@Operation(summary = "下载审计取证单Word文档")
@PostMapping("/download")
public void downloadAuditEvidence(@RequestBody AuditEvidenceRequest request, HttpServletResponse response) {
double originalMinInflateRatio = ZipSecureFile.getMinInflateRatio();
try {
ZipSecureFile.setMinInflateRatio(0.001);
// 准备模板数据 - 将取证单字段映射到Word模板
Map<String, Object> map = new HashMap<>();
// map.put("caseIndex", request.getCaseIndex() != null ? request.getCaseIndex() : "");
map.put("caseIndex", request.getCaseIndex() != null ? String.format("%-50s", request.getCaseIndex()) : String.format("%-50s", ""));
map.put("pageIndex", request.getPageIndex() != null ? request.getPageIndex() : "1");
map.put("pageTotal", request.getPageTotal() != null ? request.getPageTotal() : "1");
map.put("projectName", request.getProjectName() != null ? request.getProjectName() : "");
map.put("auditedTarget", request.getAuditedTarget() != null ? request.getAuditedTarget() : "");
map.put("auditMatter", request.getAuditMatter() != null ? request.getAuditMatter() : "");
map.put("summaryTitle", request.getSummaryTitle() != null ? request.getSummaryTitle() : "");
map.put("auditRecord", request.getAuditRecord() != null ? request.getAuditRecord() : "");
map.put("auditFinding", request.getAuditFinding() != null ? request.getAuditFinding() : "");
map.put("evidenceBasis", request.getEvidenceBasis() != null ? request.getEvidenceBasis() : "");
map.put("handling", request.getHandling() != null ? request.getHandling() : "");
map.put("attachment", request.getAttachment() != null ? request.getAttachment() : "");
map.put("auditors", request.getAuditors() != null ? request.getAuditors() : "");
map.put("compileDate", request.getCompileDate() != null ? request.getCompileDate() : "");
map.put("providerOpinion", request.getProviderOpinion() != null ? request.getProviderOpinion() : "");
map.put("providerDate", request.getProviderDate() != null ? request.getProviderDate() : "");
map.put("attachmentPages", request.getAttachmentPages() != null ? request.getAttachmentPages() : "");
map.put("feedbackDeadline", request.getFeedbackDeadline() != null ? request.getFeedbackDeadline() : "");
// 获取登录用户信息
final User loginUser = getLoginUser();
if (request.getAuditors() == null || request.getAuditors().isEmpty()) {
map.put("auditors", loginUser.getUsername());
}
// 使用 Easypoi 的 Word 模板功能生成取证单
XWPFDocument document = WordExportUtil.exportWord07(
templateConfig.getEvidenceTemplatePath(), // 需要配置取证单模板路径
map
);
// 处理换行,确保 \n 转为硬回车(新段落)
processParagraphs(document);
// 设置响应头
String fileName = "审计取证单_" + (request.getProjectName() != null ? request.getProjectName() : "取证单") + ".docx";
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setHeader("Content-Disposition", "attachment; filename=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
// 输出文档
try (OutputStream out = response.getOutputStream()) {
document.write(out);
out.flush();
}
} catch (Exception e) {
log.error("生成审计取证单Word文档失败", e);
throw new RuntimeException("生成审计取证单失败", e);
} finally {
ZipSecureFile.setMinInflateRatio(originalMinInflateRatio);
}
}
/**
* 处理段落换行(与审计报告相同的处理逻辑)
*/
private void processParagraphs(XWPFDocument document) {
List<XWPFParagraph> originalParas = new ArrayList<>(document.getParagraphs());
for (XWPFParagraph para : originalParas) {
String text = para.getText();
if (text == null || !text.contains("\n")) {
continue;
}
String[] parts = text.replace("\r\n", "\n").replace("\r", "\n").split("\n");
// 在原段落位置之前插入新段落
int pos = document.getPosOfParagraph(para);
// 修正:按正序插入(从前往后)
for (int i = 0; i < parts.length; i++) {
// 创建新段落
XWPFParagraph newPara = document.insertNewParagraph(para.getCTP().newCursor());
// 复制样式
newPara.getCTP().setPPr(para.getCTP().getPPr());
XWPFRun newRun = newPara.createRun();
newRun.setText(parts[i].trim());
if (!para.getRuns().isEmpty()) {
newRun.getCTR().setRPr(para.getRuns().get(0).getCTR().getRPr());
}
}
// 删除原段落
document.removeBodyElement(pos + parts.length);
}
}
}

View File

@@ -23,6 +23,10 @@ public class AuditEvidenceRequest {
private String attachmentPages; // 附件页数
private String feedbackDeadline; // 反馈期限
// 导出取证单使用
private String pageIndex;
private String pageTotal;
// 历史内容(用于工作流生成)
private String history;

View File

@@ -65,8 +65,8 @@ public class AuditEvidenceServiceImpl implements AuditEvidenceService {
context.append("## 输出格式要求\n");
context.append("请严格按照以下JSON格式输出不要包含任何额外文本\n");
context.append("{\n");
context.append(" \"caseIndex\": \"案件编号,如审计-[2024]-001\",\n");
context.append(" \"projectName\": \"具体项目名称\",\n");
// context.append(" \"caseIndex\": \"案件编号,如审计-[2024]-001\",\n");
// context.append(" \"projectName\": \"具体项目名称\",\n");
context.append(" \"auditedTarget\": \"被审计单位或个人\",\n");
context.append(" \"auditMatter\": \"审计事项描述\",\n");
context.append(" \"summaryTitle\": \"核心问题标题\",\n");

View File

@@ -76,4 +76,8 @@ ai:
# Word 模板路径
word-template-path: classpath:templates/audit_report_template.docx
# 或者使用绝对路径
# word-template-path: D:\\公司经济责任审计方案模板.docx
# word-template-path: D:\\公司经济责任审计方案模板.docx
# Word 取证单模板路径
evidence-template-path: classpath:templates/audit_evidence_template.docx
# Word 取证单绝对路径
#evidence-template-path: D:\\audit_evidence_template.docx

View File

@@ -82,4 +82,8 @@ ai:
# Word 模板路径
word-template-path: classpath:templates/audit_report_template.docx
# 或者使用绝对路径
# word-template-path: D:\\公司经济责任审计方案模板.docx
# word-template-path: D:\\公司经济责任审计方案模板.docx
# Word 取证单模板路径
evidence-template-path: classpath:templates/audit_evidence_template.docx
# Word 取证单绝对路径
#evidence-template-path: D:\\audit_evidence_template.docx