| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535 |
- package com.hotent.project.service;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.hotent.base.util.StringUtil;
- import com.hotent.config.EipConfig;
- import com.hotent.project.manager.*;
- import com.hotent.project.model.*;
- import com.hotent.surveyinfo.manager.CostSurveyTemplateUploadManager;
- import com.hotent.surveyinfo.model.CostSurveyTemplateUpload;
- import com.hotent.uc.manager.OrgManager;
- import com.hotent.uc.manager.UserManager;
- import com.hotent.uc.model.Org;
- import com.hotent.uc.model.User;
- import com.hotent.uc.util.ContextUtil;
- import com.hotent.util.FileUploadUtil;
- import com.hotent.util.wordexcelutils.CompleteTemplateProcessor;
- import com.hotent.util.wordexcelutils.SmartTemplateWriter;
- import org.apache.poi.xwpf.usermodel.*;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Service;
- import java.io.FileOutputStream;
- import java.time.LocalDateTime;
- import java.util.Comparator;
- import java.util.List;
- import java.util.Map;
- import java.util.stream.Collectors;
- /**
- * 异步资料归纳服务
- *
- * @company 山西清众科技股份有限公司
- * @author 超级管理员
- * @since 2025-12-02
- */
- @Service
- public class AsyncMaterialSummaryService {
- private static final Logger logger = LoggerFactory.getLogger(AsyncMaterialSummaryService.class);
- @Autowired
- private CostProjectTaskMaterialSummaryManager costProjectTaskMaterialSummaryManager;
- @Autowired
- private CostProjectTaskMaterialSummaryDetailManager costProjectTaskMaterialSummaryDetailManager;
- @Autowired
- private CostProjectDocumentManager costProjectDocumentManager;
- @Autowired
- private CostProjectTaskManager costProjectTaskManager;
- @Autowired
- private CostSurveyTemplateUploadManager costSurveyTemplateUploadManager;
- @Autowired
- private CostProjectTaskMaterialManager costProjectTaskMaterialManager;
- @Autowired
- private CostProjectDeliberateManager costProjectDeliberateManager;
- @Autowired
- private CostProjectTaskAdjustmentRecordManager adjustmentRecordManager;
- @Autowired
- private CostProjectTaskEvidenceManager costProjectTaskEvidenceManager;
- @Autowired
- private CostProjectTaskPreliminaryOpinionManager preliminaryOpinionManager;
- @Autowired
- private CostProjectApprovalManager costProjectApprovalManager;
- @Autowired
- private OrgManager orgManager;
- @Autowired
- private UserManager userManager;
- // 从配置文件读取模板路径
- @org.springframework.beans.factory.annotation.Value("${archive.template.coverPath:}")
- private String coverTemplatePath;
- @org.springframework.beans.factory.annotation.Value("${archive.template.catalogPath:}")
- private String catalogTemplatePath;
- @org.springframework.beans.factory.annotation.Value("${archive.template.backCoverPath:}")
- private String backCoverTemplatePath;
- /**
- * 生成资料归纳主表(14个基础资料类别)- 核心逻辑
- *
- * @param mainTask 主任务
- * @param childTasks 子任务列表
- */
- public void generateMaterialSummary(CostProjectTask mainTask, List<CostProjectTask> childTasks) {
- try {
- // 定义14个基础资料类别
- String[] materialNames = {
- "成本监审报告(含成本监审报告签发稿、送达回证)",
- "被监审单位申请定(调)价报告(复印件)",
- "成本监审通知书(含送达回证)",
- "经营者需提供成本资料清单",
- "《政府定价成本监审调查表》",
- "成本监审补充资料通知书(含送达回证)",
- "成本审核初步意见告知书(含送达回证)",
- "经营者书面反馈的材料",
- "成本审核初步意见表(集体审议用)",
- "成本监审集体审议记录",
- "成本监审工作底稿",
- "成本监审提取资料登记表",
- "提取的成本资料和会计凭证等复印件",
- "中止定价成本监审料通知书(含送达回证)"
- };
- // 为主任务生成14个资料归纳主表记录
- for (int i = 0; i < materialNames.length; i++) {
- CostProjectTaskMaterialSummary summary = new CostProjectTaskMaterialSummary();
- summary.setTaskId(mainTask.getId());
- summary.setMaterialName(materialNames[i]);
- summary.setMaterialOrderNum(i + 1);
- summary.setIsDeleted("0");
- costProjectTaskMaterialSummaryManager.createOrUpdate(summary);
- // 根据不同的资料类别生成对应的明细记录
- generateDetailsByMaterialType(summary, mainTask, childTasks, i + 1);
- }
- } catch (Exception e) {
- // 记录异常日志,但不影响主流程
- logger.error("生成资料归纳失败", e);
- }
- }
- /**
- * 根据资料类别生成对应的明细记录
- *
- * @param summary 资料归纳主表
- * @param mainTask 主任务
- * @param childTasks 子任务列表
- * @param materialType 资料类别序号(1-13)
- */
- private void generateDetailsByMaterialType(CostProjectTaskMaterialSummary summary,
- CostProjectTask mainTask,
- List<CostProjectTask> childTasks,
- int materialType) {
- try {
- // 查询项目下的所有文书
- List<CostProjectDocument> documents = costProjectDocumentManager.getListByProjectId(mainTask.getProjectId());
- if (documents == null) {
- documents = new java.util.ArrayList<>();
- }
- switch (materialType) {
- case 1:
- // 成本监审报告(含成本监审报告签发稿、送达回证)
- generateType1Details(summary, mainTask, documents);
- break;
- case 2:
- // 被监审单位申请定(调)价报告(复印件)
- generateType2Details(summary, mainTask, childTasks, documents);
- break;
- case 3:
- // 成本监审通知书(含送达回证)
- generateType3Details(summary, mainTask, childTasks, documents);
- break;
- case 4:
- // 经营者需提供成本资料清单
- generateType4Details(summary, mainTask, childTasks, documents);
- break;
- case 5:
- // 《政府定价成本监审调查表》
- generateType5Details(summary, mainTask, childTasks, documents);
- break;
- case 6:
- // 成本监审补充资料通知书(含送达回证)
- generateType6Details(summary, mainTask, childTasks, documents);
- break;
- case 7:
- // 成本审核初步意见告知书(含送达回证)
- generateType7Details(summary, mainTask, childTasks, documents);
- break;
- case 8:
- // 经营者书面反馈的材料
- generateType8Details(summary, mainTask, childTasks, documents);
- break;
- case 9:
- // 成本审核初步意见表(集体审议用)
- generateType9Details(summary, mainTask, childTasks, documents);
- break;
- case 10:
- // 成本监审集体审议记录
- generateType10Details(summary, mainTask, documents);
- break;
- case 11:
- // 成本监审工作底稿
- generateType11Details(summary, mainTask, childTasks, documents);
- break;
- case 12:
- // 成本监审提取资料登记表
- generateType12Details(summary, mainTask, childTasks, documents);
- break;
- case 13:
- // 提取的成本资料和会计凭证等复印件
- generateType13Details(summary, mainTask, childTasks, documents);
- break;
- case 14:
- // 中止定价成本监审料通知书(含送达回证)
- generateType14Details(summary, mainTask, childTasks, documents);
- break;
- default:
- throw new RuntimeException("未知的资料类型");
- }
- } catch (Exception e) {
- logger.error("生成资料类型 {} 的明细时出错:{}", materialType, e.getMessage(), e);
- // 继续执行,不中断整个流程
- }
- }
- //1 卷宗封面
- //2 卷内目录
- //3 政府定价成本监审结论报告
- //4 成本监审通知书
- //5 成本审核初步意见告知书
- //6 成本审核初步意见表
- //7 成本监审集体审议记录
- //8 成本监审工作底稿
- //9 成本监审提取资料登记表
- //10 成本监审补充资料通知书
- //11 中止定价成本监审通知书
- //12 送达回证
- //13 成本监审卷宗备考表
- // ==================== 类型1:成本监审报告(含成本监审报告签发稿、送达回证) ====================
- // A.成本监审报告(含成本监审报告签发稿)
- // 包括成本监审报告、报告签发稿等文书。
- private void generateType1Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"成本监审报告"、"成本监审报告签发稿"、"送达回证"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "3".equals(doc.getDocumentType())
- || "3-12".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName())
- )
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- // ==================== 类型2:被监审单位申请定(调)价报告(复印件) ====================
- // 被监审单位申请定(调)价报告等。
- //来源:从“监审立项”附件获取。
- private void generateType2Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"申请定(调)价报告"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "申请定(调)价报告".equals(doc.getDocumentName()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("监审主体上传文件");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getScanDocumentUrl() != null ? document.getScanDocumentUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- CostProjectApproval approval = costProjectApprovalManager.getById(mainTask.getProjectId());
- if (approval != null && StringUtil.isNotEmpty(approval.getAccordingFileUrl())) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName("成本项目定(调)价依据");
- detail.setDocumentNumber("");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(approval.getAccordingFileUrl());
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- // ==================== 类型3:成本监审通知书(含送达回证) ====================
- // 包括成本监审通知书、送达回证等文书。
- //来源:从“监审文书”中获取。
- private void generateType3Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // "成本监审通知书"和"送达回证"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "4".equals(doc.getDocumentType())
- || "4-12".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- // ==================== 类型4:经营者需提供成本资料清单(提取资料) ====================
- // 成本监审任务中的资料报送要求。
- //来源:从“监审任务部署”中获取。
- private void generateType4Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"成本资料清单"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "9".equals(doc.getDocumentType()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- for (CostProjectTask childTask : childTasks) {
- List<CostProjectTaskEvidence> list = costProjectTaskEvidenceManager.list(
- new LambdaQueryWrapper<CostProjectTaskEvidence>().eq(CostProjectTaskEvidence::getTaskId, childTask.getId())
- );
- for (CostProjectTaskEvidence evidence : list) {
- // 只处理有附件的资料登记
- if (StringUtil.isNotEmpty(evidence.getAttachmentUrl())) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(evidence.getMaterialName() != null ? evidence.getMaterialName() : "提取资料登记");
- detail.setDocumentNumber("");
- detail.setAuditedUnitId(childTask.getAuditedUnitId());
- detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(evidence.getPageCount() != null ? evidence.getPageCount() : 0);
- detail.setAttachmentUrl(evidence.getAttachmentUrl());
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- }
- }
- // ==================== 类型5:《政府定价成本监审调查表》 ====================
- // 各被监审单位的“成本监审调查表”文档。
- //来源:从“监审任务”中获取各被监审单位填报的成本监审调查表。
- private void generateType5Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- for (CostProjectTask childTask : childTasks) {
- List<CostSurveyTemplateUpload> costSurveyTemplateUploads = costSurveyTemplateUploadManager.listByTaskId(childTask.getId());
- for (CostSurveyTemplateUpload upload : costSurveyTemplateUploads) {
- if ("1".equals(upload.getIsUpload()) && StringUtil.isNotEmpty(upload.getFileUrl())) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(upload.getSurveyTemplateName() != null ? upload.getSurveyTemplateName() : "政府定价成本监审调查表");
- detail.setDocumentNumber("");
- detail.setAuditedUnitId(childTask.getAuditedUnitId());
- detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
- detail.setFileSource("监审单位反馈文件");
- detail.setPageCount(0);
- detail.setAttachmentUrl(upload.getFileUrl());
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- }
- // 成本调查表(kkkk)
- }
- // ==================== 类型6:成本监审补充资料通知书(含送达回证) ====================
- // 监审主体发送给各被监审单位的补充资料通知书、送达回证等文书。
- //来源:从“监审文书”中获取。
- private void generateType6Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "10".equals(doc.getDocumentType())
- || "10-12".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- // ==================== 类型7:成本审核初步意见告知书(含送达回证) ====================
- // 监审主体发送给各被监审单位的初步意见告知书、送达回证等文书。
- // 来源:从“监审文书”中获取。
- private void generateType7Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"成本审核初步意见告知书"和"送达回证"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "5".equals(doc.getDocumentType())
- || "5-12".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- // ==================== 类型8:经营者书面反馈的材料 ====================
- // 各被监审单位对初步意见告知书的意见反馈资料。
- //来源:从“监审任务”中获取反馈意见。
- private void generateType8Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"书面反馈材料"(来源:监审单位反馈文件)
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "书面反馈材料".equals(doc.getDocumentType()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("监审单位反馈文件");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- // 获取被监审单位的反馈意见和反馈资料
- for (CostProjectTask childTask : childTasks) {
- List<CostProjectTaskPreliminaryOpinion> list = preliminaryOpinionManager.list(
- new LambdaQueryWrapper<>(CostProjectTaskPreliminaryOpinion.class)
- .eq(CostProjectTaskPreliminaryOpinion::getTaskId, childTask.getId())
- );
- for (CostProjectTaskPreliminaryOpinion opinion : list) {
- // 只处理有反馈资料的记录
- if (StringUtil.isNotEmpty(opinion.getFeedbackMaterials())) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName("书面反馈材料");
- detail.setDocumentNumber("");
- detail.setAuditedUnitId(childTask.getAuditedUnitId());
- detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
- detail.setFileSource("监审单位反馈文件");
- detail.setPageCount(0);
- detail.setAttachmentUrl(opinion.getFeedbackMaterials());
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- }
- }
- // ==================== 类型9:成本审核初步意见表(集体审议用) ====================
- // 来源:从“监审文书”中获取
- private void generateType9Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"成本审核初步意见表"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "6".equals(doc.getDocumentType()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- // ==================== 类型10:成本监审集体审议记录 ====================
- // 来源:从“监审文书”中获取。
- private void generateType10Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"成本监审集体审议记录"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "7".equals(doc.getDocumentType()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- // 获取集体审议记录
- List<CostProjectDeliberate> list = costProjectDeliberateManager.list(
- new LambdaQueryWrapper<CostProjectDeliberate>().eq(CostProjectDeliberate::getTaskId, mainTask.getId())
- );
- for (CostProjectDeliberate deliberate : list) {
- // 只处理有附件的审议记录
- if (StringUtil.isNotEmpty(deliberate.getAttachmentUrl())) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName("成本监审集体审议记录");
- detail.setDocumentNumber("");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(deliberate.getAttachmentUrl());
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- }
- // ==================== 类型11:成本监审工作底稿 ====================
- // 来源:从“监审文书”中获取。
- private void generateType11Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"成本监审工作底稿"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "8".equals(doc.getDocumentType()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- // 获取核增核减记录(工作底稿的一部分)
- for (CostProjectTask childTask : childTasks) {
- List<CostProjectTaskAdjustmentRecord> costProjectTaskAdjustmentRecords = adjustmentRecordManager.listByTaskId(childTask.getId());
- for (CostProjectTaskAdjustmentRecord record : costProjectTaskAdjustmentRecords) {
- // 只处理有附件的记录
- if (StringUtil.isNotEmpty(record.getAttachmentUrl())) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(record.getSubject() != null ? record.getSubject() + "-工作底稿" : "成本监审工作底稿");
- detail.setDocumentNumber("");
- detail.setAuditedUnitId(childTask.getAuditedUnitId());
- detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(record.getAttachmentUrl());
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- }
- }
- // ==================== 类型12:成本监审提取资料登记表 ====================
- // 来源:从“监审文书”中获取。
- private void generateType12Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"成本监审提取资料登记表"
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "9".equals(doc.getDocumentType()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- // 获取子任务的资料登记表
- for (CostProjectTask childTask : childTasks) {
- List<CostProjectTaskEvidence> list = costProjectTaskEvidenceManager.list(
- new LambdaQueryWrapper<CostProjectTaskEvidence>().eq(CostProjectTaskEvidence::getTaskId, childTask.getId())
- );
- for (CostProjectTaskEvidence evidence : list) {
- // 只处理有附件的资料登记
- if (StringUtil.isNotEmpty(evidence.getAttachmentUrl())) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(evidence.getMaterialName() != null ? evidence.getMaterialName() : "提取资料登记");
- detail.setDocumentNumber("");
- detail.setAuditedUnitId(childTask.getAuditedUnitId());
- detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
- detail.setFileSource("系统生成电子文书");
- detail.setPageCount(evidence.getPageCount() != null ? evidence.getPageCount() : 0);
- detail.setAttachmentUrl(evidence.getAttachmentUrl());
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- }
- }
- // ==================== 类型13:提取的成本资料和会计凭证等复印件 ====================
- // 来源:各被监审单位首次及补充材料时提交的资料,包括综合性材料、财会资料等。
- private void generateType13Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"成本资料和会计凭证"(来源:被监审单位提交的资料)
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "成本资料和会计凭证".equals(doc.getDocumentType()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("监审单位反馈文件");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- // 获取子任务的资料登记表
- for (CostProjectTask childTask : childTasks) {
- // 获取任务的报送资料要求(被监审单位提交的补充资料)
- List<CostProjectTaskMaterial> list = costProjectTaskMaterialManager.list(
- new LambdaQueryWrapper<>(CostProjectTaskMaterial.class)
- .eq(CostProjectTaskMaterial::getTaskId, childTask.getId())
- );
- for (CostProjectTaskMaterial material : list) {
- // 只处理已上传的资料
- if ("1".equals(material.getIsUpload()) && StringUtil.isNotEmpty(material.getFileUrl())) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(material.getInformationName() != null ? material.getInformationName() : "补充资料");
- detail.setDocumentNumber("");
- detail.setAuditedUnitId(childTask.getAuditedUnitId());
- detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
- detail.setFileSource("监审单位反馈文件");
- detail.setPageCount(0);
- detail.setAttachmentUrl(material.getFileUrl());
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- }
- }
- // ==================== 类型14:中止定价成本监审料通知书(含送达回证) ====================
- // 来源:从“监审文书”中获取。
- private void generateType14Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
- int orderNum = 1;
- // 获取"中止定价成本监审通知书"(来源:被监审单位提交的资料)
- List<CostProjectDocument> matchedDocuments = documents.stream()
- .filter(doc -> "11".equals(doc.getDocumentType())
- || "11-12".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName()))
- .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
- .collect(Collectors.toList());
- for (CostProjectDocument document : matchedDocuments) {
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(summary.getId());
- detail.setTaskId(mainTask.getId());
- detail.setDocumentName(document.getDocumentName());
- detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
- detail.setAuditedUnitId(mainTask.getAuditedUnitId());
- detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
- detail.setFileSource("监审单位反馈文件");
- detail.setPageCount(0);
- detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
- detail.setOrderNum(orderNum++);
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- }
- /**
- * 档案校对通过后,异步生成Word卷宗
- * 顺序:封面(-1) -> 目录(-2) -> 14个资料(1-13) -> 封底(-3)
- *
- * @param taskId 任务ID
- */
- @Async
- public void generateWordArchiveAsync(String taskId) {
- CostProjectTask task = costProjectTaskManager.getById(taskId);
- try {
- logger.info("开始生成Word卷宗,任务ID:{}", taskId);
- // 查询任务的所有资料归纳主表(包含封面、目录、封底)
- List<CostProjectTaskMaterialSummary> allSummaryList =
- costProjectTaskMaterialSummaryManager.listAllByTaskId(taskId);
- // 创建Word文档
- XWPFDocument document = new XWPFDocument();
- boolean isFirstDocument = true;
- // 按顺序合并:封面(-1) -> 目录(-2) -> 14个资料(1-13) -> 封底(-3)
- // 排序:-1, -2, 1, 2, ..., 13, -3
- allSummaryList.sort((a, b) -> {
- int orderA = a.getMaterialOrderNum() != null ? a.getMaterialOrderNum() : 0;
- int orderB = b.getMaterialOrderNum() != null ? b.getMaterialOrderNum() : 0;
- // -1(封面) < -2(目录) < 1-13(资料) < -3(封底)
- int sortA = orderA == -1 ? -100 : (orderA == -2 ? -99 : (orderA == -3 ? 100 : orderA));
- int sortB = orderB == -1 ? -100 : (orderB == -2 ? -99 : (orderB == -3 ? 100 : orderB));
- return Integer.compare(sortA, sortB);
- });
- // 遍历所有主表,从明细表获取附件URL进行合并
- for (CostProjectTaskMaterialSummary summary : allSummaryList) {
- logger.info("合并资料:{}", summary.getMaterialName());
- List<CostProjectTaskMaterialSummaryDetail> detailList = summary.getDetailList();
- if (detailList != null && !detailList.isEmpty()) {
- detailList.sort(Comparator.comparing(d -> d.getOrderNum() != null ? d.getOrderNum() : 0));
- for (CostProjectTaskMaterialSummaryDetail detail : detailList) {
- if (StringUtil.isNotEmpty(detail.getAttachmentUrl())) {
- isFirstDocument = mergeDocumentFile(document, detail.getAttachmentUrl(), isFirstDocument);
- }
- }
- }
- }
- // 生成输出文件路径
- String fileName = FileUploadUtil.generateFileName("卷宗_" + taskId + ".docx");
- String outputPath = FileUploadUtil.generateSavePath(
- EipConfig.getUploadPath(), fileName, "docx");
- // 确保目录存在
- java.io.File outputFile = new java.io.File(outputPath);
- if (!outputFile.getParentFile().exists()) {
- outputFile.getParentFile().mkdirs();
- }
- // 保存Word文档
- FileOutputStream out = new FileOutputStream(outputPath);
- document.write(out);
- out.close();
- document.close();
- // 生成访问URL
- String archiveUrl = FileUploadUtil.getPathFileName(outputPath, fileName);
- logger.info("Word卷宗生成完成,任务ID:{},URL:{}", taskId, archiveUrl);
- // 更新任务的卷宗URL
- if (task != null) {
- task.setArchiveUrl(archiveUrl);
- task.setArchiveStatus("2");
- task.setArchiveTime(LocalDateTime.now());
- costProjectTaskManager.updateById(task);
- logger.info("卷宗URL已更新,任务ID:{}", taskId);
- }
- } catch (Exception e) {
- if (task != null) {
- task.setArchiveStatus("3");
- costProjectTaskManager.updateById(task);
- }
- logger.error("生成Word卷宗失败,任务ID:,错误:{}", taskId, e.getMessage(), e);
- }
- }
- /**
- * 合并单个文档文件到主文档(保持原始样式)
- *
- * @param document 主文档
- * @param fileUrl 文件URL(如:/profile/upload/20251116/xxx.docx)
- * @param isFirstDocument 是否是第一个文档
- * @return 是否是第一个文档(用于下次调用)
- */
- private boolean mergeDocumentFile(XWPFDocument document, String fileUrl, boolean isFirstDocument) {
- try {
- String filePath = fileUrl;
- // 处理路径:/profile 开头的路径需要替换为实际路径
- if (filePath.startsWith("/profile")) {
- filePath = EipConfig.getProfile() + filePath.substring(8);
- }
- java.io.File file = new java.io.File(filePath);
- if (!file.exists()) {
- logger.warn("文件不存在:{}(原始路径:{})", filePath, fileUrl);
- return isFirstDocument;
- }
- // 添加分页符(非第一个文档)
- if (!isFirstDocument) {
- XWPFParagraph pageBreakPara = document.createParagraph();
- XWPFRun pageBreakRun = pageBreakPara.createRun();
- pageBreakRun.addBreak(BreakType.PAGE);
- }
- // 读取Word文件
- java.io.FileInputStream fis = new java.io.FileInputStream(filePath);
- XWPFDocument sourceDoc = new XWPFDocument(fis);
- // 使用XML级别复制,保持原始样式
- org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody srcBody = sourceDoc.getDocument().getBody();
- org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody destBody = document.getDocument().getBody();
- // 复制所有元素(段落、表格等)
- for (org.apache.xmlbeans.XmlObject obj : srcBody.selectPath("./*")) {
- if (obj instanceof org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP) {
- // 复制段落
- org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP newP = destBody.addNewP();
- newP.set(obj.copy());
- } else if (obj instanceof org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl) {
- // 复制表格
- org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl newTbl = destBody.addNewTbl();
- newTbl.set(obj.copy());
- }
- }
- sourceDoc.close();
- fis.close();
- return false;
- } catch (Exception e) {
- logger.error("合并文件失败:{},错误:{}", fileUrl, e.getMessage(), e);
- return isFirstDocument;
- }
- }
- /**
- * 更新单个资料归纳主表的总页数
- *
- * @param masterId 主表ID
- */
- public void updateMasterTotalPageCount(String masterId) {
- try {
- CostProjectTaskMaterialSummary summary = costProjectTaskMaterialSummaryManager.getById(masterId);
- if (summary == null) {
- logger.warn("资料归纳主表不存在,ID:{}", masterId);
- return;
- }
- int totalPageCount = 0;
- // 查询该主表的所有明细
- List<CostProjectTaskMaterialSummaryDetail> detailList = costProjectTaskMaterialSummaryDetailManager.list(
- new LambdaQueryWrapper<CostProjectTaskMaterialSummaryDetail>()
- .eq(CostProjectTaskMaterialSummaryDetail::getMasterId, masterId)
- .eq(CostProjectTaskMaterialSummaryDetail::getIsDeleted, "0")
- );
- // 累加所有明细的页数
- for (CostProjectTaskMaterialSummaryDetail detail : detailList) {
- if (detail.getPageCount() != null) {
- totalPageCount += detail.getPageCount();
- }
- }
- // 更新主表的总页数
- summary.setTotalPageCount(String.valueOf(totalPageCount));
- costProjectTaskMaterialSummaryManager.updateById(summary);
- logger.info("资料归纳【{}】总页数已更新:{}", summary.getMaterialName(), totalPageCount);
- } catch (Exception e) {
- logger.error("更新主表总页数失败,主表ID:{},错误:{}", masterId, e.getMessage(), e);
- }
- }
- /**
- * 统计每个资料归纳主表的总页数(所有明细的页数之和)
- *
- * @param taskId 任务ID
- */
- public void calculatePageCountAsync(String taskId) {
- try {
- logger.info("开始异步统计页数,任务ID:{}", taskId);
- // 查询任务的所有资料归纳主表
- List<CostProjectTaskMaterialSummary> summaryList = costProjectTaskMaterialSummaryManager.listByTaskId(taskId);
- for (CostProjectTaskMaterialSummary summary : summaryList) {
- int totalPageCount = 0;
- // 获取该主表的所有明细
- if (summary.getDetailList() != null && !summary.getDetailList().isEmpty()) {
- for (CostProjectTaskMaterialSummaryDetail detail : summary.getDetailList()) {
- if (StringUtil.isNotEmpty(detail.getAttachmentUrl())) {
- // 统计该明细的页数
- int pageCount = calculateFilePageCount(detail.getAttachmentUrl());
- detail.setPageCount(pageCount);
- costProjectTaskMaterialSummaryDetailManager.updateById(detail);
- // 累加到总页数
- totalPageCount += pageCount;
- }
- }
- }
- // 更新主表的总页数
- summary.setTotalPageCount(String.valueOf(totalPageCount));
- costProjectTaskMaterialSummaryManager.updateById(summary);
- logger.info("资料归纳【{}】统计完成,总页数:{}", summary.getMaterialName(), totalPageCount);
- }
- logger.info("页数统计完成,任务ID:{}", taskId);
- } catch (Exception e) {
- logger.error("统计页数失败,任务ID:{},错误:{}", taskId, e.getMessage(), e);
- }
- }
- /**
- * 计算文件页数(公共方法,可被外部调用)
- *
- * @param fileUrl 文件URL或路径
- * @return 页数
- */
- public int calculateFilePageCount(String fileUrl) {
- try {
- if (StringUtil.isEmpty(fileUrl)) {
- return 0;
- }
- // 判断文件类型
- String lowerCaseUrl = fileUrl.toLowerCase();
- if (lowerCaseUrl.endsWith(".xls") || lowerCaseUrl.endsWith(".xlsx")) {
- // Excel文件算1页
- return 1;
- } else if (lowerCaseUrl.endsWith(".doc") || lowerCaseUrl.endsWith(".docx")) {
- // Word文件需要读取实际页数
- return getWordPageCount(fileUrl);
- } else {
- // 其他格式默认1页
- return 1;
- }
- } catch (Exception e) {
- logger.error("计算文件页数失败,文件:{},错误:{}", fileUrl, e.getMessage(), e);
- return 0;
- }
- }
- /**
- * 获取Word文档的页数
- *
- * @param fileUrl 文件URL或路径(如:/profile/upload/20251116/xxx.docx)
- * @return 页数
- */
- private int getWordPageCount(String fileUrl) {
- java.io.FileInputStream fis = null;
- XWPFDocument document = null;
- try {
- String filePath = fileUrl;
- if (filePath.startsWith("/profile")) {
- filePath = EipConfig.getProfile() + filePath.substring(8);
- }
- fis = new java.io.FileInputStream(filePath);
- document = new XWPFDocument(fis);
- // 获取页数
- int pageCount = document.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
- return pageCount > 0 ? pageCount : 1;
- } catch (Exception e) {
- logger.error("读取Word页数失败,文件:{},错误:{}", fileUrl, e.getMessage(), e);
- // 读取失败默认返回1页
- return 1;
- } finally {
- // 关闭资源
- try {
- if (document != null) {
- document.close();
- }
- if (fis != null) {
- fis.close();
- }
- } catch (Exception e) {
- logger.warn("关闭文件流失败:{}", e.getMessage());
- }
- }
- }
- // ==================== 卷宗校对文书生成功能 ====================
- /**
- * 生成卷宗文书(封面/目录/封底)
- * id为空是新增,id不为空是编辑
- *
- * @param req 生成请求
- * @return 生成的文书URL
- */
- public String generateArchiveDocument(com.hotent.project.req.ArchiveProofreadReq req) throws Exception {
- Integer documentType = req.getDocumentType();
- String existingId = req.getRelatedId();
- // 如果id不为空,从数据库获取已有记录的documentType(id是主表ID)
- if (StringUtil.isNotEmpty(existingId)) {
- CostProjectTaskMaterialSummary existing = costProjectTaskMaterialSummaryManager.getById(existingId);
- if (existing == null) {
- throw new RuntimeException("主表记录不存在:" + existingId);
- }
- Integer orderNum = existing.getMaterialOrderNum();
- if (orderNum != null && orderNum == -1) {
- documentType = 1;
- } else if (orderNum != null && orderNum == -2) {
- documentType = 2;
- } else if (orderNum != null && orderNum == -3) {
- documentType = 3;
- } else {
- throw new RuntimeException("无效的文书记录");
- }
- }
- String templatePath;
- String documentName;
- switch (documentType) {
- case 1:
- templatePath = coverTemplatePath;
- documentName = "案卷封面";
- if (StringUtil.isEmpty(templatePath)) {
- throw new RuntimeException("案卷封面模板路径未配置");
- }
- break;
- case 2:
- templatePath = catalogTemplatePath;
- documentName = "卷内目录";
- if (StringUtil.isEmpty(templatePath)) {
- throw new RuntimeException("卷内目录模板路径未配置");
- }
- break;
- case 3:
- templatePath = backCoverTemplatePath;
- documentName = "案卷封底";
- if (StringUtil.isEmpty(templatePath)) {
- throw new RuntimeException("案卷封底模板路径未配置");
- }
- break;
- default:
- throw new RuntimeException("不支持的文书类型:" + documentType);
- }
- // 检查模板文件是否存在
- java.io.File templateFile = new java.io.File(templatePath);
- if (!templateFile.exists()) {
- throw new RuntimeException("模板文件不存在:" + templatePath);
- }
- // 生成文书
- String outputUrl = generateDocumentFromTemplate(templatePath, documentName, req);
- // 保存到数据库(主表+明细表)
- int orderNum = -documentType; // -1封面、-2目录、-3封底
- String masterId;
- if (StringUtil.isNotEmpty(existingId)) {
- // 编辑:existingId是主表ID,查找对应的明细记录
- masterId = existingId;
- CostProjectTaskMaterialSummary existingSummary = costProjectTaskMaterialSummaryManager.getById(masterId);
- if (existingSummary != null) {
- // 更新task的卷宗号和归档人
- CostProjectTask task = costProjectTaskManager.getById(existingSummary.getTaskId());
- if (task != null) {
- task.setArchiveNo(req.getArchiveNo());
- task.setArchiveUser(ContextUtil.getCurrentUser().getFullname());
- costProjectTaskManager.updateById(task);
- }
- }
- CostProjectTaskMaterialSummaryDetail existingDetail = costProjectTaskMaterialSummaryDetailManager.getOne(
- new LambdaQueryWrapper<CostProjectTaskMaterialSummaryDetail>()
- .eq(CostProjectTaskMaterialSummaryDetail::getMasterId, masterId)
- .eq(CostProjectTaskMaterialSummaryDetail::getIsDeleted, "0")
- );
- if (existingDetail != null) {
- // 更新已有明细
- existingDetail.setAttachmentUrl(outputUrl);
- existingDetail.setGenerateTime(java.time.LocalDateTime.now());
- costProjectTaskMaterialSummaryDetailManager.updateById(existingDetail);
- } else {
- // 创建新明细
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(masterId);
- detail.setTaskId(req.getTaskId());
- detail.setDocumentName(documentName);
- detail.setFileSource("系统生成电子文书");
- detail.setAttachmentUrl(outputUrl);
- detail.setOrderNum(1);
- detail.setGenerateTime(java.time.LocalDateTime.now());
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- } else {
- // 新增:创建主表记录
- CostProjectTaskMaterialSummary summary = new CostProjectTaskMaterialSummary();
- summary.setTaskId(req.getTaskId());
- summary.setMaterialOrderNum(orderNum);
- summary.setMaterialName(documentName);
- summary.setIsDeleted("0");
- costProjectTaskMaterialSummaryManager.save(summary);
- masterId = summary.getId();
- // 更新task的卷宗号和归档人
- CostProjectTask task = costProjectTaskManager.getById(req.getTaskId());
- if (task != null) {
- task.setArchiveNo(req.getArchiveNo());
- task.setArchiveUser(ContextUtil.getCurrentUser().getAccount());
- costProjectTaskManager.updateById(task);
- }
- // 创建明细记录
- CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
- detail.setMasterId(masterId);
- detail.setTaskId(req.getTaskId());
- detail.setDocumentName(documentName);
- detail.setFileSource("系统生成电子文书");
- detail.setAttachmentUrl(outputUrl);
- detail.setOrderNum(1);
- detail.setGenerateTime(java.time.LocalDateTime.now());
- detail.setIsDeleted("0");
- costProjectTaskMaterialSummaryDetailManager.save(detail);
- }
- return outputUrl;
- }
- /**
- * 根据模板生成文书
- *
- * @param templatePath 模板路径
- * @param documentName 文书名称
- * @param req 请求参数
- * @return 生成的文书URL
- */
- private String generateDocumentFromTemplate(String templatePath, String documentName,
- com.hotent.project.req.ArchiveProofreadReq req) throws Exception {
- java.io.FileInputStream fis = null;
- XWPFDocument document = null;
- java.io.FileOutputStream fos = null;
- try {
- // 读取模板
- fis = new java.io.FileInputStream(templatePath);
- document = new XWPFDocument(fis);
- // 构建替换映射
- Map<String, String> replacements = buildReplacementMap(req);
- // 根据文书类型进行不同处理
- switch (req.getDocumentType()) {
- case 1:
- // 案卷封面
- generateCoverDocument(document, replacements);
- break;
- case 2:
- // 卷内目录
- generateCatalogDocument(document, replacements, req.getTaskId());
- break;
- case 3:
- // 案卷封底
- generateBackCoverDocument(document, replacements);
- break;
- }
- // 生成输出文件路径
- String fileName = FileUploadUtil.generateFileName(documentName + ".docx");
- String outputPath = FileUploadUtil.generateSavePath(
- EipConfig.getUploadPath(), fileName, "docx");
- // 确保目录存在
- java.io.File outputFile = new java.io.File(outputPath);
- if (!outputFile.getParentFile().exists()) {
- outputFile.getParentFile().mkdirs();
- }
- // 写入文件
- fos = new java.io.FileOutputStream(outputPath);
- document.write(fos);
- // 返回访问URL
- return FileUploadUtil.getPathFileName(outputPath, fileName);
- } finally {
- // 关闭资源
- try {
- if (fos != null) fos.close();
- if (document != null) document.close();
- if (fis != null) fis.close();
- } catch (Exception e) {
- logger.warn("关闭文件流失败:{}", e.getMessage());
- }
- }
- }
- /**
- * 构建替换映射
- * 自动从数据库获取:年份、监审项目名称、被监审单位、监审期间(开始-结束年度)、监审人员、办结时间
- * 需要用户传递:价格主管部门、卷宗号、保管期间周期、立卷人、立卷日期、检查人、检查日期、备注
- */
- private Map<String, String> buildReplacementMap(com.hotent.project.req.ArchiveProofreadReq req) {
- Map<String, String> map = new java.util.HashMap<>();
- // 从数据库获取任务信息
- CostProjectTask task = costProjectTaskManager.getById(req.getTaskId());
- // 从数据库获取立项审批信息(包含监审组人员)
- CostProjectApproval approval = costProjectApprovalManager.getOne(
- new LambdaQueryWrapper<CostProjectApproval>()
- .eq(CostProjectApproval::getProjectId, task.getProjectId())
- );
- // ========== 自动获取的字段 ==========
- Org org = orgManager.getById(approval.getOrgId());
- map.put("{价格主管部门或成本监审机构}", org.getName());
- map.put("{年份}", task.getYear());
- map.put("{监审项目名称}", task.getProjectName());
- map.put("{被监审单位}", task.getAuditedUnitName());
- // 监审期间(解析开始-结束年度,格式如:2024,2025,2023 逗号分隔)
- String startYear = "";
- String endYear = "";
- String auditPeriod = task.getAuditPeriod();
- if (StringUtil.isNotEmpty(auditPeriod)) {
- String[] years = auditPeriod.split(",");
- int minYear = Integer.MAX_VALUE;
- int maxYear = Integer.MIN_VALUE;
- for (String year : years) {
- try {
- int y = Integer.parseInt(year.trim());
- if (y < minYear) minYear = y;
- if (y > maxYear) maxYear = y;
- } catch (NumberFormatException e) {
- }
- }
- if (minYear != Integer.MAX_VALUE) {
- startYear = String.valueOf(minYear);
- endYear = String.valueOf(maxYear);
- }
- }
- map.put("{监审开始年度}", startYear);
- map.put("{监审结束年度}", endYear);
- // 监审组负责人及人员(将ID转换为姓名)
- String auditGroupNames = "";
- if (approval != null && StringUtil.isNotEmpty(approval.getAuditGroup())) {
- String[] userIds = approval.getAuditGroup().split(",");
- StringBuilder names = new StringBuilder();
- for (String userId : userIds) {
- try {
- User user = userManager.get(userId.trim());
- if (user != null) {
- if (names.length() > 0) {
- names.append(",");
- }
- names.append(user.getFullname());
- }
- } catch (Exception e) {
- }
- }
- auditGroupNames = names.toString();
- }
- map.put("{监审组负责人及人员}", auditGroupNames);
- // 监审办结时间(任务状态为办结时,取更新时间,格式:xxxx年xx月)
- String auditEndTime = "";
- if ("400".equals(task.getStatus()) && task.getUpdateTime() != null) {
- auditEndTime = task.getUpdateTime().getYear() + "年" + task.getUpdateTime().getMonthValue() + "月";
- }
- map.put("{监审办结时间}", auditEndTime);
- // ========== 需要用户传递的字段 ==========
- map.put("{卷宗号}", req.getArchiveNo() != null ? req.getArchiveNo() : "");
- map.put("{保管期间周期}", req.getRetentionPeriod() != null ? req.getRetentionPeriod() : "");
- // ========== 卷宗统计信息 ==========
- // 获取14个资料归纳的总页数
- List<CostProjectTaskMaterialSummary> summaryList = costProjectTaskMaterialSummaryManager.listByTaskId(req.getTaskId());
- summaryList = summaryList.stream()
- .filter(s -> s.getMaterialOrderNum() != null && s.getMaterialOrderNum() > 0)
- .collect(Collectors.toList());
- int totalPageCount = 0;
- for (CostProjectTaskMaterialSummary summary : summaryList) {
- if (summary.getTotalPageCount() != null) {
- try {
- totalPageCount += Integer.parseInt(summary.getTotalPageCount());
- } catch (NumberFormatException e) {
- }
- }
- }
- map.put("{卷宗件数}", "1"); // 默认1件
- map.put("{卷宗页数}", String.valueOf(totalPageCount));
- map.put("{第几件}", "1"); // 默认第1件
- map.put("{备注}", req.getRemark());
- return map;
- }
- /**
- * 生成案卷封面
- */
- private void generateCoverDocument(XWPFDocument document, Map<String, String> replacements) {
- SmartTemplateWriter.writeToTemplate(document, replacements);
- }
- /**
- * 生成卷内目录(只填充表格,不替换占位符)
- */
- private void generateCatalogDocument(XWPFDocument document, Map<String, String> replacements, String taskId) {
- // 获取资料归纳列表,生成目录表格
- List<CostProjectTaskMaterialSummary> summaryList = costProjectTaskMaterialSummaryManager.listByTaskId(taskId);
- // 过滤掉封面、目录、封底(负数序号)
- summaryList = summaryList.stream()
- .filter(s -> s.getMaterialOrderNum() != null && s.getMaterialOrderNum() > 0)
- .sorted(Comparator.comparing(CostProjectTaskMaterialSummary::getMaterialOrderNum))
- .collect(Collectors.toList());
- // 构建目录数据
- List<CompleteTemplateProcessor.TableRowData> tableDataList = new java.util.ArrayList<>();
- int currentPage = 1;
- for (CostProjectTaskMaterialSummary summary : summaryList) {
- CompleteTemplateProcessor.TableRowData rowData =
- new CompleteTemplateProcessor.TableRowData();
- rowData.setDocumentName(summary.getMaterialName());
- int pageCount = 0;
- if (summary.getTotalPageCount() != null) {
- try {
- pageCount = Integer.parseInt(summary.getTotalPageCount());
- } catch (NumberFormatException e) {
- pageCount = 0;
- }
- }
- rowData.setPageCount(pageCount);
- // 计算页码范围作为备注
- if (pageCount > 0) {
- rowData.setRemark(currentPage + "-" + (currentPage + pageCount - 1));
- currentPage += pageCount;
- } else {
- rowData.setRemark("—");
- }
- tableDataList.add(rowData);
- }
- // 只填充表格数据,
- if (!tableDataList.isEmpty()) {
- processTableData(document, tableDataList);
- }
- }
- /**
- * 生成案卷封底
- */
- private void generateBackCoverDocument(XWPFDocument document, Map<String, String> replacements) {
- SmartTemplateWriter.writeToTemplate(document, replacements);
- }
- /**
- * 处理目录表格数据
- */
- private void processTableData(XWPFDocument document, List<CompleteTemplateProcessor.TableRowData> dataList) {
- List<XWPFTable> tables = document.getTables();
- if (tables.isEmpty()) {
- logger.warn("未找到表格");
- return;
- }
- XWPFTable table = tables.get(0);
- // 找到模板行(第二行,第一行是表头)
- int templateRowIndex = 0;
- if (table.getRows().size() <= templateRowIndex) {
- logger.warn("表格行数不足");
- return;
- }
- // 获取模板行的单元格数量
- int cellCount = table.getRow(templateRowIndex).getTableCells().size();
- // 删除模板行
- table.removeRow(templateRowIndex);
- // 从模板行位置开始插入数据行
- for (int i = 0; i < dataList.size(); i++) {
- CompleteTemplateProcessor.TableRowData data = dataList.get(i);
- XWPFTableRow newRow = table.insertNewTableRow(templateRowIndex + i);
- // 创建单元格
- for (int j = 0; j < cellCount; j++) {
- newRow.addNewTableCell();
- }
- fillTableRow(newRow, i + 1, data);
- }
- }
- /**
- * 填充表格行数据
- */
- private void fillTableRow(XWPFTableRow row, int sequence,
- CompleteTemplateProcessor.TableRowData data) {
- List<XWPFTableCell> cells = row.getTableCells();
- if (cells.size() >= 4) {
- setCellText(cells.get(0), String.valueOf(sequence));
- setCellText(cells.get(1), data.getDocumentName());
- setCellText(cells.get(2), data.getPageCount() > 0 ? String.valueOf(data.getPageCount()) : "");
- setCellText(cells.get(3), data.getRemark() != null ? data.getRemark() : "");
- }
- }
- /**
- * 设置单元格文本
- */
- private void setCellText(XWPFTableCell cell, String text) {
- // 清除现有内容
- for (int i = cell.getParagraphs().size() - 1; i >= 0; i--) {
- cell.removeParagraph(i);
- }
- // 添加新内容
- XWPFParagraph paragraph = cell.addParagraph();
- XWPFRun run = paragraph.createRun();
- run.setText(text);
- paragraph.setAlignment(ParagraphAlignment.CENTER);
- }
- }
|