新增下载审计取证单Word文档接口
This commit is contained in:
@@ -8,5 +8,9 @@ import org.springframework.stereotype.Component;
|
|||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties(prefix = "ai.template")
|
@ConfigurationProperties(prefix = "ai.template")
|
||||||
public class TemplateConfig {
|
public class TemplateConfig {
|
||||||
|
|
||||||
private String wordTemplatePath;
|
private String wordTemplatePath;
|
||||||
|
|
||||||
|
private String evidenceTemplatePath;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,21 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
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
|
@Autowired
|
||||||
private AuditEvidenceService auditEvidenceService;
|
private AuditEvidenceService auditEvidenceService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateConfig templateConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成审计取证单
|
* 生成审计取证单
|
||||||
@@ -50,4 +68,109 @@ public class AuditEvidenceController extends BaseController {
|
|||||||
return fail("生成审计取证单异常: " + e.getMessage());
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ public class AuditEvidenceRequest {
|
|||||||
private String attachmentPages; // 附件页数
|
private String attachmentPages; // 附件页数
|
||||||
private String feedbackDeadline; // 反馈期限
|
private String feedbackDeadline; // 反馈期限
|
||||||
|
|
||||||
|
// 导出取证单使用
|
||||||
|
private String pageIndex;
|
||||||
|
private String pageTotal;
|
||||||
|
|
||||||
// 历史内容(用于工作流生成)
|
// 历史内容(用于工作流生成)
|
||||||
private String history;
|
private String history;
|
||||||
|
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ public class AuditEvidenceServiceImpl implements AuditEvidenceService {
|
|||||||
context.append("## 输出格式要求\n");
|
context.append("## 输出格式要求\n");
|
||||||
context.append("请严格按照以下JSON格式输出,不要包含任何额外文本:\n");
|
context.append("请严格按照以下JSON格式输出,不要包含任何额外文本:\n");
|
||||||
context.append("{\n");
|
context.append("{\n");
|
||||||
context.append(" \"caseIndex\": \"案件编号,如审计-[2024]-001\",\n");
|
// context.append(" \"caseIndex\": \"案件编号,如审计-[2024]-001\",\n");
|
||||||
context.append(" \"projectName\": \"具体项目名称\",\n");
|
// context.append(" \"projectName\": \"具体项目名称\",\n");
|
||||||
context.append(" \"auditedTarget\": \"被审计单位或个人\",\n");
|
context.append(" \"auditedTarget\": \"被审计单位或个人\",\n");
|
||||||
context.append(" \"auditMatter\": \"审计事项描述\",\n");
|
context.append(" \"auditMatter\": \"审计事项描述\",\n");
|
||||||
context.append(" \"summaryTitle\": \"核心问题标题\",\n");
|
context.append(" \"summaryTitle\": \"核心问题标题\",\n");
|
||||||
|
|||||||
@@ -76,4 +76,8 @@ ai:
|
|||||||
# Word 模板路径
|
# Word 模板路径
|
||||||
word-template-path: classpath:templates/audit_report_template.docx
|
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
|
||||||
|
|||||||
@@ -82,4 +82,8 @@ ai:
|
|||||||
# Word 模板路径
|
# Word 模板路径
|
||||||
word-template-path: classpath:templates/audit_report_template.docx
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user