Quellcode durchsuchen

Merge remote-tracking branch 'origin/master'

赵越越 vor 1 Woche
Ursprung
Commit
75c12a333b

+ 20 - 12
assistMg/src/main/java/com/hotent/baseInfo/manager/impl/CostCatalogUnitManagerImpl.java

@@ -16,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -78,24 +79,31 @@ public class CostCatalogUnitManagerImpl extends BaseManagerImpl<CostCatalogUnitD
 
 
         List<CostCatalogUnit> records = pageList.getRecords();
-        records.forEach(costCatalogUnit -> {
-            if ("3".equals(costCatalogUnit.getFormatRequired())) {
-                if(fdTemplateMap!=null) {
-                    if (fdTemplateMap.containsKey(costCatalogUnit.getTemplateId())) {
-                        CostSurveyFdTemplate costSurveyFdTemplate = fdTemplateMap.get(costCatalogUnit.getTemplateId());
-                        costCatalogUnit.setSurveyTemplateName(costSurveyFdTemplate.getSurveyTemplateName());
-                    }
-                }else{
-                    costCatalogUnit.setSurveyTemplateName("-");
+        // 映射表
+        Map<String, String> formatMap = new HashMap<>();
+        formatMap.put("1", "文档文件");
+        formatMap.put("2", "Excel");
+        formatMap.put("3", "预置模");
+
+        records.forEach(unit -> {
+            // 类型名称
+            String formatName = formatMap.getOrDefault(unit.getFormatRequired(), "未知类型");
+            unit.setFormatRequiredName(formatName);
+
+            if ("3".equals(unit.getFormatRequired())) {
+                if (fdTemplateMap != null && fdTemplateMap.containsKey(unit.getTemplateId())) {
+                    unit.setSurveyTemplateName(fdTemplateMap.get(unit.getTemplateId()).getSurveyTemplateName());
+                } else {
+                    unit.setSurveyTemplateName("-");
                 }
-            }else{
-                costCatalogUnit.setSurveyTemplateName("-");
+            } else {
+                unit.setSurveyTemplateName("-");
             }
         });
-
         return pageList;
     }
 
+
     @Override
     public List<CostCatalogUnit> getListByCatalogId(String catalogId) {
         LambdaQueryWrapper<CostCatalogUnit> queryWrapper = new LambdaQueryWrapper<>();

+ 10 - 0
assistMg/src/main/java/com/hotent/baseInfo/model/CostCatalogUnit.java

@@ -74,6 +74,7 @@ public class CostCatalogUnit extends BaseModel<CostCatalogUnit> {
     @JsonProperty("formatRequired")
     @NotEmpty(message = "格式要求不能为空")
     private String formatRequired;
+    private String formatRequiredName;
 
     @ApiModelProperty(value = "创建时间")
     @TableField(value = "create_time", fill = FieldFill.INSERT)
@@ -90,6 +91,15 @@ public class CostCatalogUnit extends BaseModel<CostCatalogUnit> {
     @TableField(exist = false)
     private String surveyTemplateName;
 
+
+    public String getFormatRequiredName() {
+        return formatRequiredName;
+    }
+
+    public void setFormatRequiredName(String formatRequiredName) {
+        this.formatRequiredName = formatRequiredName;
+    }
+
     public String getSurveyTemplateName() {
         return surveyTemplateName;
     }

+ 254 - 71
assistMg/src/main/java/com/hotent/enterpriseDeclare/controller/material/CostProjectTaskSurveyGenericController.java

@@ -8,20 +8,23 @@ import com.hotent.base.constants.ApiGroupConsts;
 import com.hotent.base.model.CommonResult;
 import com.hotent.base.util.StringUtil;
 import com.hotent.baseInfo.manager.CostCatalogSurveyManager;
-import com.hotent.baseInfo.manager.CostDictTypeManager;
+import com.hotent.baseInfo.manager.CostCatalogUnitManager;
 import com.hotent.baseInfo.model.CostCatalogSurvey;
-import com.hotent.baseInfo.model.CostDictType;
 import com.hotent.enterpriseDeclare.manager.CostAuditPeriodRecordManager;
 import com.hotent.enterpriseDeclare.manager.CostSurveyTemplateUploadDataManager;
 import com.hotent.enterpriseDeclare.model.CostAuditPeriodRecord;
 import com.hotent.enterpriseDeclare.model.CostSurveyTemplateUploadData;
+import com.hotent.enterpriseDeclare.service.CellDataQueryService;
 import com.hotent.project.manager.CostProjectApprovalManager;
 import com.hotent.project.manager.CostProjectTaskManager;
 import com.hotent.project.manager.CostProjectTaskMaterialManager;
 import com.hotent.project.model.CostProjectApproval;
 import com.hotent.project.model.CostProjectTask;
 import com.hotent.project.model.CostProjectTaskMaterial;
-import com.hotent.surveyinfo.dao.*;
+import com.hotent.surveyinfo.dao.CostSurveyFdTemplateItemsDao;
+import com.hotent.surveyinfo.dao.CostSurveyTemplateItemsDao;
+import com.hotent.surveyinfo.dao.CostVerifyTemplateHeadersDao;
+import com.hotent.surveyinfo.dao.CostVerifyTemplateItemsDao;
 import com.hotent.surveyinfo.manager.*;
 import com.hotent.surveyinfo.model.*;
 import com.hotent.surveyinfo.model.dto.CostItemData;
@@ -36,7 +39,6 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.nfunk.jep.JEP;
-import org.nfunk.jep.function.Str;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -71,17 +73,12 @@ public class CostProjectTaskSurveyGenericController {
     private CostSurveyTemplateVersionManager costSurveyTemplateVersionManager;
 
     @Autowired
-    private CostSurveyTemplateHeadersDao costSurveyTemplateHeadersDao;
-
-    @Autowired
     private CostSurveyTemplateItemsDao costSurveyTemplateItemsDao;
     @Resource
     DataDictManager dataDictManager;
     @Resource
     SysTypeManager sysTypeManager;
 
-
-
     // 财务数据表相关
     @Autowired
     private CostSurveyFdTemplateManager costSurveyFdTemplateManager;
@@ -90,9 +87,6 @@ public class CostProjectTaskSurveyGenericController {
     private CostSurveyFdTemplateVersionManager costSurveyFdTemplateVersionManager;
 
     @Autowired
-    private CostSurveyFdTemplateHeadersDao costSurveyFdTemplateHeadersDao;
-
-    @Autowired
     private CostSurveyFdTemplateItemsDao costSurveyFdTemplateItemsDao;
 
     // 核定表
@@ -105,8 +99,6 @@ public class CostProjectTaskSurveyGenericController {
     @Autowired
     private CostVerifyTemplateItemsDao costVerifyTemplateItemsDao;
 
-
-    // 通用组件
     @Autowired
     private CostSurveyTemplateUploadManager costSurveyTemplateUploadManager;
     @Autowired
@@ -131,11 +123,17 @@ public class CostProjectTaskSurveyGenericController {
     private CostSurveyFdTemplateHeadersManager costSurveyFdTemplateHeadersManager;
 
 
+    @Autowired
+    private CostCatalogSurveyManager costCatalogSurveyManager;
+
+    @Autowired
+    private CellDataQueryService cellDataQueryService;
+
+
     /**
      * 企业报送-调查表-列表
      *
      * @param taskId    任务ID
-     * @param catalogId 目录ID(成本调查表使用)
      * @param type      类型:1-成本调查表 2-财务数据表
      * @return 上传记录列表
      * @throws Exception
@@ -145,21 +143,21 @@ public class CostProjectTaskSurveyGenericController {
     public CommonResult<?> listByTaskId(
             @ApiParam(name = "taskId", value = "任务ID", required = true)
             @RequestParam(required = true) String taskId,
-            @ApiParam(name = "catalogId", value = "目录ID(成本调查表使用)")
-            @RequestParam(required = false) String catalogId,
             @ApiParam(name = "type", value = "类型:1-成本调查表 2-财务数据表", required = true)
             @RequestParam(required = true) String type) throws Exception {
+        CostProjectTask task = costProjectTaskManager.getById(taskId);
 
         switch (type) {
             case "1": {
+                List<CostCatalogSurvey> list = costCatalogSurveyManager.list(
+                        new LambdaQueryWrapper<CostCatalogSurvey>().eq(CostCatalogSurvey::getCatalogId, task.getCatalogId())
+                );
                 // 成本调查表逻辑
                 List<CostSurveyTemplateUpload> uploadList = costSurveyTemplateUploadManager.listByTaskId(taskId);
                 //创建记录
                 if (uploadList.isEmpty()) {
-                    CostProjectTask task = costProjectTaskManager.getById(taskId);
-                    CostProjectApproval approval = costProjectApprovalManager.getById(task.getProjectId());
-                    List<CostSurveyTemplate> costSurveyTemplates = costSurveyTemplateManager.taskListByCatalogId(approval.getCatalogId());
-                    for (CostSurveyTemplate template : costSurveyTemplates) {
+                    for (CostCatalogSurvey survey : list) {
+                        CostSurveyTemplate template = costSurveyTemplateManager.getById(survey.getSurveyId());
                         CostSurveyTemplateUpload upload = new CostSurveyTemplateUpload();
                         upload.setSurveyTemplateId(template.getSurveyTemplateId());
                         upload.setSurveyTemplateName(template.getSurveyTemplateName());
@@ -175,7 +173,6 @@ public class CostProjectTaskSurveyGenericController {
                 }
                 List<CostSurveyTemplateUpload> costSurveyTemplateUploads = costSurveyTemplateUploadManager.listByTaskId(taskId);
                 for (CostSurveyTemplateUpload costSurveyTemplateUpload : costSurveyTemplateUploads) {
-                    CostProjectTask task = costProjectTaskManager.getById(taskId);
                     costSurveyTemplateUpload.setAuditedUnitId(task.getAuditedUnitId());
                 }
                 return CommonResult.ok().value(costSurveyTemplateUploads);
@@ -186,7 +183,6 @@ public class CostProjectTaskSurveyGenericController {
                 wrapper.eq("task_id", taskId);
                 List<CostProjectTaskMaterial> materialList = costProjectTaskMaterialManager.list(wrapper);
                 for (CostProjectTaskMaterial costProjectTaskMaterial : materialList) {
-                    CostProjectTask task = costProjectTaskManager.getById(taskId);
                     costProjectTaskMaterial.setAuditedUnitId(task.getAuditedUnitId()); ;
                 }
                 return CommonResult.ok().value(materialList);
@@ -629,6 +625,21 @@ public class CostProjectTaskSurveyGenericController {
                 List<CostSurveyTemplateItems> itemsList = costSurveyTemplateItemsDao.selectBySurveyTemplateIdAndVersion(
                         surveyTemplateId, currentVersion.getId());
 
+                // 校验跨表数据完整性
+                for (CostSurveyTemplateItems item : itemsList) {
+                    if (StringUtil.isNotEmpty(item.getCalculationTemplateId())) {
+                        // 有跨表引用,检查跨表数据是否存在
+                        Map<String, String> crossData = cellDataQueryService.getCrossTableFormulaData(
+                            taskId, item.getCalculationTemplateId(), type, "0");
+                        if (crossData.isEmpty()) {
+                            response.sendError(HttpServletResponse.SC_BAD_REQUEST,
+                                "导出失败:该表有跨表引用,但另外一个表(ID: " + item.getCalculationTemplateId() + ")的数据缺失。请先完成另外一个表的数据导入。");
+                            return;
+                        }
+                        break;
+                    }
+                }
+
                 Workbook workbook = new XSSFWorkbook();
                 String sheetName = "成本调查表";
                 Sheet sheet = workbook.createSheet(sheetName);
@@ -703,7 +714,7 @@ public class CostProjectTaskSurveyGenericController {
                     for (int i = 0; i < headersList.size(); i++) {
                         headerIndexMap.put(headersList.get(i).getId(), i);
                     }
-                    fillExcelData(sheet, itemsList, headerIndexMap, templateType, type, rowIdColIndex, parentIdColIndex, dataStyle);
+                    fillExcelData(sheet, itemsList, headerIndexMap, templateType, type, rowIdColIndex, parentIdColIndex, dataStyle, taskId);
                 }
 
                 for (int i = 0; i < headersList.size(); i++) {
@@ -785,6 +796,21 @@ public class CostProjectTaskSurveyGenericController {
                 List<CostSurveyFdTemplateItems> itemsList = costSurveyFdTemplateItemsDao.selectBySurveyTemplateIdAndVersion(
                         surveyTemplateId, currentVersion.getId());
 
+                // 校验跨表数据完整性
+                for (CostSurveyFdTemplateItems item : itemsList) {
+                    if (StringUtil.isNotEmpty(item.getCalculationTemplateId())) {
+                        // 有跨表引用,检查跨表数据是否存在
+                        Map<String, String> crossData = cellDataQueryService.getCrossTableFormulaData(
+                            taskId, item.getCalculationTemplateId(), type, "0");
+                        if (crossData.isEmpty()) {
+                            response.sendError(HttpServletResponse.SC_BAD_REQUEST,
+                                "导出失败:该表有跨表引用,但另外一个表(ID: " + item.getCalculationTemplateId() + ")的数据缺失。请先完成另外一个表的数据导入。");
+                            return;
+                        }
+                        break;
+                    }
+                }
+
                 // 5.返回excel
                 Workbook workbook = new XSSFWorkbook();
                 String sheetName = "财务数据表";
@@ -860,7 +886,7 @@ public class CostProjectTaskSurveyGenericController {
                     for (int i = 0; i < headersList.size(); i++) {
                         headerIndexMap.put(headersList.get(i).getId(), i);
                     }
-                    fillExcelDataFd(sheet, itemsList, headerIndexMap, templateType, rowIdColIndex, parentIdColIndex, dataStyle);
+                    fillExcelDataFd(sheet, itemsList, headerIndexMap, templateType, rowIdColIndex, parentIdColIndex, dataStyle, taskId);
                 }
 
                 for (int i = 0; i < headersList.size(); i++) {
@@ -1144,10 +1170,10 @@ public class CostProjectTaskSurveyGenericController {
                     // 固定表和动态表必须包含行ID和父行ID列
                     if ("2".equals(templateType) || "3".equals(templateType)) {
                         if (rowIdColumnIndex == null) {
-                            return CommonResult.<String>error().message("固定表/动态表导入失败:Excel文件缺少【行ID】列。请使用系统导出的模板,不要删除隐藏列。");
+                            return CommonResult.<String>error().message("固定表/动态表导入失败:请使用系统导出的模板,不要删除隐藏列。");
                         }
                         if (parentIdColumnIndex == null) {
-                            return CommonResult.<String>error().message("固定表/动态表导入失败:Excel文件缺少【父行ID】列。请使用系统导出的模板,不要删除隐藏列。");
+                            return CommonResult.<String>error().message("固定表/动态表导入失败:请使用系统导出的模板,不要删除隐藏列。");
                         }
                     }
 
@@ -1755,6 +1781,35 @@ public class CostProjectTaskSurveyGenericController {
             return errors;
         }
 
+        // 0. 检查是否修改了已有数据
+        String refId = dataList.get(0).getRefId();
+        if (StringUtil.isNotEmpty(refId)) {
+            QueryWrapper<CostSurveyTemplateUploadData> existingWrapper = new QueryWrapper<>();
+            existingWrapper.eq("ref_id", refId).eq("type", type).eq("is_deleted", "0");
+            List<CostSurveyTemplateUploadData> existingDataList = costSurveyTemplateUploadDataManager.list(existingWrapper);
+
+            if (!existingDataList.isEmpty()) {
+                // 构建已有数据的映射:rowid_rkey -> rvalue
+                Map<String, String> existingDataMap = new HashMap<>();
+                for (CostSurveyTemplateUploadData data : existingDataList) {
+                    String key = data.getRowid() + "_" + data.getRkey();
+                    existingDataMap.put(key, data.getRvalue());
+                }
+
+                // 检查导入数据是否修改了已有数据
+                for (CostSurveyTemplateUploadData data : dataList) {
+                    String key = data.getRowid() + "_" + data.getRkey();
+                    String existingValue = existingDataMap.get(key);
+                    if (existingValue != null && !existingValue.equals(data.getRvalue())) {
+                        Integer excelRowNum = rowIdToExcelRowMap.get(data.getRowid());
+                        String rowInfo = excelRowNum != null ? "第" + excelRowNum + "行" : "行[" + data.getRowid() + "]";
+                        errors.add(String.format("%s 字段[%s] 不能修改已有数据。原值:%s,新值:%s",
+                                rowInfo, data.getRkey(), existingValue, data.getRvalue()));
+                    }
+                }
+            }
+        }
+
         // 获取模板类型(templateType)
         String templateType = getTemplateType(type, surveyTemplateId);
 
@@ -1847,6 +1902,58 @@ public class CostProjectTaskSurveyGenericController {
                     }
                 }
 
+                // 处理跨表引用(检查模板项中的 calculation_template_id)
+                for (Object item : itemsList) {
+                    String calculationTemplateId = getItemCalculationTemplateId(item);
+                    if (StringUtil.isNotEmpty(calculationTemplateId)) {
+                        String crossTableType = type;
+
+                        // 收集所有年限
+                        Set<String> allPeriods = new HashSet<>();
+                        for (Map<String, String> rowData : rowDataMap.values()) {
+                            for (String key : rowData.keySet()) {
+                                if (key.matches("\\d{4}")) {
+                                    allPeriods.add(key);
+                                }
+                            }
+                        }
+
+                        // 使用 Service 获取跨表数据
+                        String taskId = dataList.get(0).getTaskId();
+                        List<String> missingCrossTableData = new ArrayList<>();
+
+                        for (String period : allPeriods) {
+                            Map<String, String> crossData = cellDataQueryService.getCrossTableFormulaData(
+                                taskId,
+                                calculationTemplateId,
+                                crossTableType,
+                                period
+                            );
+
+                            // 检查跨表数据是否完整
+                            if (crossData.isEmpty()) {
+                                missingCrossTableData.add(period);
+                            }
+
+                            // 为跨表数据加上表ID前缀,避免与当前表数据冲突
+                            for (Map.Entry<String, String> entry : crossData.entrySet()) {
+                                String prefixedKey = calculationTemplateId + "_" + entry.getKey();
+                                globalCellCodeMap.put(prefixedKey, entry.getValue());
+                            }
+                        }
+
+                        // 如果跨表数据缺失,报错
+                        if (!missingCrossTableData.isEmpty()) {
+                            List<String> errorList = new ArrayList<>();
+                            errorList.add("导入失败:该表有跨表引用,但另外一个表(ID: " + calculationTemplateId + ")的以下年限数据缺失:" +
+                                    String.join("、", missingCrossTableData) + "。请先完成另外一个表的数据导入。");
+                            return errorList;
+                        }
+
+                        break;
+                    }
+                }
+
                 // 收集所有的年限(年限的key是4位数字,如"2024")
                 Set<String> periods = new HashSet<>();
                 for (Map<String, String> rowData : rowDataMap.values()) {
@@ -1899,13 +2006,23 @@ public class CostProjectTaskSurveyGenericController {
                 .filter(StringUtil::isNotEmpty)
                 .collect(Collectors.toSet());
 
-        int expectedRowCount = templateRowIds.size();
-        int actualRowCount = rowDataMap.size();
+        Set<String> actualRowIds = rowDataMap.keySet();
+
+        // 2. 校验行数是否匹配(检查rowId集合是否完全相同)
+        if (!actualRowIds.equals(templateRowIds)) {
+            Set<String> missingRowIds = new HashSet<>(templateRowIds);
+            missingRowIds.removeAll(actualRowIds);
+            Set<String> extraRowIds = new HashSet<>(actualRowIds);
+            extraRowIds.removeAll(templateRowIds);
 
-        // 2. 校验行数是否匹配
-        if (actualRowCount != expectedRowCount) {
-            errors.add(String.format("固定表行数不匹配!模板定义:%d 行,导入数据:%d 行。固定表不允许增加或减少行。",
-                    expectedRowCount, actualRowCount));
+            StringBuilder errorMsg = new StringBuilder("固定表行不匹配!");
+            if (!missingRowIds.isEmpty()) {
+                errorMsg.append("缺少行:").append(String.join(", ", missingRowIds)).append(";");
+            }
+            if (!extraRowIds.isEmpty()) {
+                errorMsg.append("多余行:").append(String.join(", ", extraRowIds)).append(";");
+            }
+            errors.add(errorMsg.toString());
         }
 
         // 3. 校验每一行的字段是否完整
@@ -2466,11 +2583,13 @@ public class CostProjectTaskSurveyGenericController {
         // 找到该行的计算公式(同一行的所有模板项共享同一个公式)
         String calculationFormula = null;
         String cellCode = null;
+        String calculationTemplateId = null;
         for (Object item : rowItems) {
             String formula = getItemCalculationFormula(item);
             if (StringUtil.isNotEmpty(formula)) {
                 calculationFormula = formula;
                 cellCode = getItemCellCode(item);
+                calculationTemplateId = getItemCalculationTemplateId(item);
                 break;
             }
         }
@@ -2490,9 +2609,23 @@ public class CostProjectTaskSurveyGenericController {
         while (matcher.find()) {
             String referencedCell = matcher.group();
             String mapKey = referencedCell + "_" + period;
-            String value = globalCellCodeMap.get(mapKey);
-            String displayValue = StringUtil.isNotEmpty(value) ? value : "0";
+            String value = null;
+
+            if (StringUtil.isNotEmpty(calculationTemplateId)) {
+                // 有跨表引用
+                if (cellCodeToRowIdMap.containsKey(referencedCell)) {
+                    // 单元格在当前表
+                    value = globalCellCodeMap.get(mapKey);
+                } else {
+                    // 单元格在跨表
+                    value = globalCellCodeMap.get(calculationTemplateId + "_" + mapKey);
+                }
+            } else {
+                // 没有跨表引用,只查当前表
+                value = globalCellCodeMap.get(mapKey);
+            }
 
+            String displayValue = StringUtil.isNotEmpty(value) ? value : "0";
             referencedCellsDebug.add(referencedCell + "=" + displayValue);
             if (StringUtil.isNotEmpty(value)) {
                 hasAnyReferencedValue = true;
@@ -2510,12 +2643,22 @@ public class CostProjectTaskSurveyGenericController {
         try {
             // 将公式中的单元格引用替换为 cellCode_年限 的形式
             // 例如:(A1+A2+A3) -> (A1_2024+A2_2024+A3_2024)
+            // 对于跨表引用,需要加上表ID前缀:(B1) -> (calculationTemplateId_B1_2024)
             String formulaWithPeriod = calculationFormula;
             matcher = pattern.matcher(calculationFormula);
             StringBuffer sb = new StringBuffer();
             while (matcher.find()) {
                 String referencedCell = matcher.group();
-                matcher.appendReplacement(sb, referencedCell + "_" + period);
+                String mapKey = referencedCell + "_" + period;
+
+                // 检查是否是跨表引用
+                String currentTableRowId = cellCodeToRowIdMap.get(referencedCell);
+                if (StringUtil.isEmpty(currentTableRowId) && StringUtil.isNotEmpty(calculationTemplateId)) {
+                    // 是跨表引用,使用表ID前缀
+                    mapKey = calculationTemplateId + "_" + mapKey;
+                }
+
+                matcher.appendReplacement(sb, mapKey);
             }
             matcher.appendTail(sb);
             formulaWithPeriod = sb.toString();
@@ -2826,14 +2969,23 @@ public class CostProjectTaskSurveyGenericController {
 
     private void fillExcelData(Sheet sheet, List<CostSurveyTemplateItems> itemsList,
                                Map<String, Integer> headerIndexMap, String templateType, String dataType,
-                               int rowIdColIndex, int parentIdColIndex, CellStyle dataStyle) {
+                               int rowIdColIndex, int parentIdColIndex, CellStyle dataStyle, String taskId) {
         if ("1".equals(templateType)) {
             Row dataRow = sheet.createRow(2);
             for (CostSurveyTemplateItems item : itemsList) {
                 Integer colIndex = headerIndexMap.get(item.getHeadersId());
                 if (colIndex != null) {
                     Cell cell = dataRow.createCell(colIndex);
-                    cell.setCellValue(item.getRvalue());
+
+                    // 检查是否有跨表引用
+                    String value = item.getRvalue();
+                    if (StringUtil.isEmpty(value) && StringUtil.isNotEmpty(item.getCalculationTemplateId())) {
+                        // 从跨表获取数据
+                        value = cellDataQueryService.getCellValueByPeriod(taskId, item.getCalculationTemplateId(),
+                            item.getCellCode(), "0", dataType);
+                    }
+
+                    cell.setCellValue(StringUtil.isNotEmpty(value) ? value : "");
                     cell.setCellStyle(dataStyle);
                 }
             }
@@ -2861,7 +3013,16 @@ public class CostProjectTaskSurveyGenericController {
                         Integer colIndex = headerIndexMap.get(item.getHeadersId());
                         if (colIndex != null) {
                             Cell cell = dataRow.createCell(colIndex);
-                            cell.setCellValue(item.getRvalue());
+
+                            // 检查是否有跨表引用
+                            String value = item.getRvalue();
+                            if (StringUtil.isEmpty(value) && StringUtil.isNotEmpty(item.getCalculationTemplateId())) {
+                                // 从跨表获取数据
+                                value = cellDataQueryService.getCellValueByPeriod(taskId, item.getCalculationTemplateId(),
+                                    item.getCellCode(), "0", dataType);
+                            }
+
+                            cell.setCellValue(StringUtil.isNotEmpty(value) ? value : "");
                             cell.setCellStyle(dataStyle);
                         }
                     }
@@ -2975,7 +3136,7 @@ public class CostProjectTaskSurveyGenericController {
 
     private void fillExcelDataFd(Sheet sheet, List<CostSurveyFdTemplateItems> itemsList,
                                  Map<String, Integer> headerIndexMap, String templateType,
-                                 int rowIdColIndex, int parentIdColIndex, CellStyle dataStyle) {
+                                 int rowIdColIndex, int parentIdColIndex, CellStyle dataStyle, String taskId) {
         if ("1".equals(templateType)) {
             // 单表:所有数据在一行
             Row dataRow = sheet.createRow(2);
@@ -2983,7 +3144,16 @@ public class CostProjectTaskSurveyGenericController {
                 Integer colIndex = headerIndexMap.get(item.getHeadersId());
                 if (colIndex != null) {
                     Cell cell = dataRow.createCell(colIndex);
-                    cell.setCellValue(item.getRvalue());
+
+                    // 检查是否有跨表引用
+                    String value = item.getRvalue();
+                    if (StringUtil.isEmpty(value) && StringUtil.isNotEmpty(item.getCalculationTemplateId())) {
+                        // 从跨表获取数据
+                        value = cellDataQueryService.getCellValueByPeriod(taskId, item.getCalculationTemplateId(),
+                            item.getCellCode(), "0", "2");
+                    }
+
+                    cell.setCellValue(StringUtil.isNotEmpty(value) ? value : "");
                     cell.setCellStyle(dataStyle);
                 }
             }
@@ -3011,7 +3181,16 @@ public class CostProjectTaskSurveyGenericController {
                         Integer colIndex = headerIndexMap.get(item.getHeadersId());
                         if (colIndex != null) {
                             Cell cell = dataRow.createCell(colIndex);
-                            cell.setCellValue(item.getRvalue());
+
+                            // 检查是否有跨表引用
+                            String value = item.getRvalue();
+                            if (StringUtil.isEmpty(value) && StringUtil.isNotEmpty(item.getCalculationTemplateId())) {
+                                // 从跨表获取数据
+                                value = cellDataQueryService.getCellValueByPeriod(taskId, item.getCalculationTemplateId(),
+                                    item.getCellCode(), "0", "2");
+                            }
+
+                            cell.setCellValue(StringUtil.isNotEmpty(value) ? value : "");
                             cell.setCellStyle(dataStyle);
                         }
                     }
@@ -3490,18 +3669,12 @@ public class CostProjectTaskSurveyGenericController {
             }
         }
 
-        // 5. 检查是否有多余的表头
-        Set<String> extraHeaders = new HashSet<>(actualHeaders);
-        extraHeaders.removeAll(expectedHeaders);
-        if (!extraHeaders.isEmpty()) {
-            errors.add(String.format("Excel文件包含多余的表头列:%s", String.join("、", extraHeaders)));
-        }
-
-        // 6. 检查是否缺少必需的表头
-        Set<String> missingHeaders = new HashSet<>(expectedHeaders);
-        missingHeaders.removeAll(actualHeaders);
-        if (!missingHeaders.isEmpty()) {
-            errors.add(String.format("Excel文件缺少必需的表头列:%s", String.join("、", missingHeaders)));
+        // 5. 检查表头是否完全匹配
+        if (!actualHeaders.equals(expectedHeaders)) {
+            Set<String> displayHeaders = new HashSet<>(expectedHeaders);
+            displayHeaders.remove("行ID");
+            displayHeaders.remove("父行ID");
+            errors.add(String.format("表头校验不通过,应该的表头是:%s,请使用系统导出的模板", String.join("、", displayHeaders)));
         }
 
         return errors;
@@ -3557,18 +3730,12 @@ public class CostProjectTaskSurveyGenericController {
             }
         }
 
-        // 5. 检查是否有多余的表头
-        Set<String> extraHeaders = new HashSet<>(actualHeaders);
-        extraHeaders.removeAll(expectedHeaders);
-        if (!extraHeaders.isEmpty()) {
-            errors.add(String.format("Excel文件包含多余的表头列:%s", String.join("、", extraHeaders)));
-        }
-
-        // 6. 检查是否缺少必需的表头
-        Set<String> missingHeaders = new HashSet<>(expectedHeaders);
-        missingHeaders.removeAll(actualHeaders);
-        if (!missingHeaders.isEmpty()) {
-            errors.add(String.format("Excel文件缺少必需的表头列:%s", String.join("、", missingHeaders)));
+        // 5. 检查表头是否完全匹配
+        if (!actualHeaders.equals(expectedHeaders)) {
+            Set<String> displayHeaders = new HashSet<>(expectedHeaders);
+            displayHeaders.remove("行ID");
+            displayHeaders.remove("父行ID");
+            errors.add(String.format("表头校验不通过,应该的表头是:%s,请使用系统导出的模板", String.join("、", displayHeaders)));
         }
 
         return errors;
@@ -3581,7 +3748,7 @@ public class CostProjectTaskSurveyGenericController {
      * @param cellCodeToRowIdMap cellCode到rowid的映射
      * @param rowIdToExcelRowMap rowid到Excel行号的映射
      * @param period 当前校验的年限
-     * @return 计算过程字符串,如 "第3行2024年列(值=10)*(第6行2024年列(值=20)-第5行2024年列(值=5))"
+     * @return 计算过程字符串,如 "第3行2024年列(值=10)*(第6行2024年列(值=20)-第5行2024年列(值=5))+财务数据表B1(值=50)"
      */
     private String buildCalculationProcessWithNames(String formula, List<String> referencedCellsDebug,
                                                      Map<String, String> cellCodeToRowIdMap,
@@ -3600,15 +3767,17 @@ public class CostProjectTaskSurveyGenericController {
                 // 获取该cellCode对应的Excel行号
                 String rowId = cellCodeToRowIdMap.get(cellCode);
                 String rowDisplay;
+
                 if (rowId != null && rowIdToExcelRowMap.get(rowId) != null) {
+                    // 当前表的单元格
                     rowDisplay = "第" + rowIdToExcelRowMap.get(rowId) + "行";
+                    rowDisplay = String.format("%s%s年列(值=%s)", rowDisplay, period, value);
                 } else {
-                    rowDisplay = "行[" + cellCode + "]";
+                    // 跨表引用的单元格
+                    rowDisplay = String.format("其他表%s(值=%s)", cellCode, value);
                 }
 
-                // 构建替换字符串:第3行2024年列(值=10)
-                String replacement = String.format("%s%s年列(值=%s)", rowDisplay, period, value);
-                replacementMap.put(cellCode, replacement);
+                replacementMap.put(cellCode, rowDisplay);
             }
         }
 
@@ -3700,4 +3869,18 @@ public class CostProjectTaskSurveyGenericController {
 
         return style;
     }
+
+    /**
+     * 获取 item 的 calculation_template_id(跨表引用的模板ID)
+     */
+    private String getItemCalculationTemplateId(Object item) {
+        if (item instanceof CostSurveyTemplateItems) {
+            return ((CostSurveyTemplateItems) item).getCalculationTemplateId();
+        } else if (item instanceof CostSurveyFdTemplateItems) {
+            return ((CostSurveyFdTemplateItems) item).getCalculationTemplateId();
+        } else if (item instanceof CostVerifyTemplateItems) {
+            return ((CostVerifyTemplateItems) item).getCalculationTemplateId();
+        }
+        return null;
+    }
 }

+ 217 - 0
assistMg/src/main/java/com/hotent/enterpriseDeclare/service/CellDataQueryService.java

@@ -0,0 +1,217 @@
+package com.hotent.enterpriseDeclare.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.hotent.base.util.StringUtil;
+import com.hotent.enterpriseDeclare.manager.CostSurveyTemplateUploadDataManager;
+import com.hotent.enterpriseDeclare.model.CostSurveyTemplateUploadData;
+import com.hotent.surveyinfo.dao.CostSurveyFdTemplateItemsDao;
+import com.hotent.surveyinfo.dao.CostSurveyTemplateItemsDao;
+import com.hotent.surveyinfo.dao.CostVerifyTemplateItemsDao;
+import com.hotent.surveyinfo.manager.CostSurveyFdTemplateVersionManager;
+import com.hotent.surveyinfo.manager.CostSurveyTemplateVersionManager;
+import com.hotent.surveyinfo.model.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+
+/**
+ * 单元格数据查询服务
+ * 用于获取指定任务、模板、年限、单元格的数据值
+ */
+@Service
+public class CellDataQueryService {
+
+    @Autowired
+    private CostSurveyTemplateUploadDataManager costSurveyTemplateUploadDataManager;
+
+    @Autowired
+    private CostSurveyTemplateItemsDao costSurveyTemplateItemsDao;
+
+    @Autowired
+    private CostSurveyFdTemplateItemsDao costSurveyFdTemplateItemsDao;
+
+    @Autowired
+    private CostVerifyTemplateItemsDao costVerifyTemplateItemsDao;
+
+    @Autowired
+    private CostSurveyTemplateVersionManager costSurveyTemplateVersionManager;
+
+    @Autowired
+    private CostSurveyFdTemplateVersionManager costSurveyFdTemplateVersionManager;
+
+    /**
+     * 获取指定单元格在指定年限的值
+     * @param taskId 任务ID
+     * @param surveyTemplateId 模板ID
+     * @param cellCode 单元格代码(如 A1, Q2)
+     * @param period 年限(如 2024)
+     * @param type 类型:1-成本调查表 2-财务数据表 3-核定表
+     * @return 该单元格在该年限的值
+     */
+    public String getCellValueByPeriod(String taskId, String surveyTemplateId, String cellCode, String period, String type) {
+        // 1. 根据 cellCode 找到对应的 rowid
+        String rowid = getRowIdByCellCode(surveyTemplateId, cellCode, type);
+        if (StringUtil.isEmpty(rowid)) {
+            return null;
+        }
+
+        // 2. 查询上传数据
+        QueryWrapper<CostSurveyTemplateUploadData> wrapper = new QueryWrapper<>();
+        wrapper.eq("task_id", taskId)
+               .eq("survey_template_id", surveyTemplateId)
+               .eq("rowid", rowid)
+               .eq("rkey", period)
+               .eq("type", type)
+               .eq("is_deleted", "0");
+
+        CostSurveyTemplateUploadData data = costSurveyTemplateUploadDataManager.getOne(wrapper);
+        return data != null ? data.getRvalue() : null;
+    }
+
+    /**
+     * 获取跨表公式的所有引用数据
+     * @param taskId 任务ID
+     * @param calculationTemplateId 计算模板ID(跨表引用的模板)
+     * @param calculationType 计算模板的类型
+     * @param period 年限
+     * @return cellCode_年限 -> 值 的映射
+     */
+    public java.util.Map<String, String> getCrossTableFormulaData(String taskId, String calculationTemplateId, String calculationType, String period) {
+        java.util.Map<String, String> result = new java.util.HashMap<>();
+
+        if (StringUtil.isEmpty(calculationTemplateId)) {
+            return result;
+        }
+
+        // 查询该模板下所有的上传数据
+        QueryWrapper<CostSurveyTemplateUploadData> wrapper = new QueryWrapper<>();
+        wrapper.eq("task_id", taskId)
+               .eq("survey_template_id", calculationTemplateId)
+               .eq("rkey", period)
+               .eq("type", calculationType)
+               .eq("is_deleted", "0");
+
+        List<CostSurveyTemplateUploadData> dataList = costSurveyTemplateUploadDataManager.list(wrapper);
+
+        // 构建 cellCode_年限 -> 值 的映射
+        for (CostSurveyTemplateUploadData data : dataList) {
+            String rowid = data.getRowid();
+            String cellCode = getItemCellCodeByRowId(calculationTemplateId, rowid, calculationType);
+            if (StringUtil.isNotEmpty(cellCode)) {
+                String mapKey = cellCode + "_" + period;
+                result.put(mapKey, data.getRvalue());
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * 根据 cellCode 获取对应的 rowid
+     */
+    private String getRowIdByCellCode(String surveyTemplateId, String cellCode, String type) {
+        try {
+            switch (type) {
+                case "1": {
+                    // 成本调查表
+                    CostSurveyTemplateVersion version = costSurveyTemplateVersionManager.selectCurrentVersion(surveyTemplateId);
+                    if (version != null) {
+                        List<CostSurveyTemplateItems> items = costSurveyTemplateItemsDao.selectBySurveyTemplateIdAndVersion(surveyTemplateId, version.getId());
+                        if (items != null) {
+                            return items.stream()
+                                    .filter(item -> cellCode.equals(item.getCellCode()))
+                                    .map(item -> item.getRowid())
+                                    .findFirst()
+                                    .orElse(null);
+                        }
+                    }
+                    break;
+                }
+                case "2": {
+                    // 财务数据表
+                    CostSurveyFdTemplateVersion version = costSurveyFdTemplateVersionManager.selectCurrentVersion(surveyTemplateId);
+                    if (version != null) {
+                        List<CostSurveyFdTemplateItems> items = costSurveyFdTemplateItemsDao.selectBySurveyTemplateIdAndVersion(surveyTemplateId, version.getId());
+                        if (items != null) {
+                            return items.stream()
+                                    .filter(item -> cellCode.equals(item.getCellCode()))
+                                    .map(item -> item.getRowid())
+                                    .findFirst()
+                                    .orElse(null);
+                        }
+                    }
+                    break;
+                }
+                case "3": {
+                    // 核定表
+                    List<CostVerifyTemplateItems> items = costVerifyTemplateItemsDao.selectByVerifyTemplateId(surveyTemplateId, null);
+                    if (items != null) {
+                        return items.stream()
+                                .filter(item -> cellCode.equals(item.getCellCode()))
+                                .map(item -> item.getRowid())
+                                .findFirst()
+                                .orElse(null);
+                    }
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            return null;
+        }
+        return null;
+    }
+
+    /**
+     * 根据 rowid 获取对应的 cellCode
+     */
+    private String getItemCellCodeByRowId(String surveyTemplateId, String rowid, String type) {
+        try {
+            switch (type) {
+                case "1": {
+                    CostSurveyTemplateVersion version = costSurveyTemplateVersionManager.selectCurrentVersion(surveyTemplateId);
+                    if (version != null) {
+                        List<CostSurveyTemplateItems> items = costSurveyTemplateItemsDao.selectBySurveyTemplateIdAndVersion(surveyTemplateId, version.getId());
+                        if (items != null) {
+                            return items.stream()
+                                    .filter(item -> rowid.equals(item.getRowid()))
+                                    .map(item -> item.getCellCode())
+                                    .findFirst()
+                                    .orElse(null);
+                        }
+                    }
+                    break;
+                }
+                case "2": {
+                    CostSurveyFdTemplateVersion version = costSurveyFdTemplateVersionManager.selectCurrentVersion(surveyTemplateId);
+                    if (version != null) {
+                        List<CostSurveyFdTemplateItems> items = costSurveyFdTemplateItemsDao.selectBySurveyTemplateIdAndVersion(surveyTemplateId, version.getId());
+                        if (items != null) {
+                            return items.stream()
+                                    .filter(item -> rowid.equals(item.getRowid()))
+                                    .map(item -> item.getCellCode())
+                                    .findFirst()
+                                    .orElse(null);
+                        }
+                    }
+                    break;
+                }
+                case "3": {
+                    List<CostVerifyTemplateItems> items = costVerifyTemplateItemsDao.selectByVerifyTemplateId(surveyTemplateId, null);
+                    if (items != null) {
+                        return items.stream()
+                                .filter(item -> rowid.equals(item.getRowid()))
+                                .map(item -> item.getCellCode())
+                                .findFirst()
+                                .orElse(null);
+                    }
+                    break;
+                }
+            }
+        } catch (Exception e) {
+            return null;
+        }
+        return null;
+    }
+}

+ 7 - 1
assistMg/src/main/java/com/hotent/project/manager/impl/CostProjectApprovalManagerImpl.java

@@ -424,7 +424,13 @@ public class CostProjectApprovalManagerImpl extends BaseManagerImpl<CostProjectA
         CostProjectProccess projectProccess = costProjectProccessManager.getProcessByProjectId(costProjectApproval.getProjectId());
         //节点集合
         List<CostProjectProccessNode> proccessNodeList = costProjectProccessNodeManager.getListByProcessId(projectProccess.getProcessId());
-
+        //初始化开始节点
+        List<CostProjectProccessNode> collect = proccessNodeList.stream().filter(node -> node.getProcessNodeKey().equals(NodeConstant.tjcl.getNodeKey()))
+                .collect(Collectors.toList());
+        CostProjectProccessNode pnode = collect.get(0);
+        pnode.setActUserIds(req.getAuditGroup());
+        pnode.setActStartTime(LocalDateTime.now());
+        costProjectProccessNodeManager.updateById(pnode);
         //政策文件、监审对象提交资料清单、成本调查表
         //监审目录id
         String catalogId = costProjectApproval.getCatalogId();

+ 2 - 0
assistMg/src/main/java/com/hotent/project/req/CostProjectDocumentPageReq.java

@@ -21,4 +21,6 @@ public class CostProjectDocumentPageReq extends PageReq {
     @ApiModelProperty(value = "查看权限类型:0:查看全部,1:查看被监审单位是当前登录用户的,2:查看当前登录人创建的")
     private Integer permissionType=0;
 
+    private String documentName;
+
 }

+ 70 - 35
assistMg/src/main/java/com/hotent/project/service/AsyncMaterialSummaryService.java

@@ -220,6 +220,19 @@ public class AsyncMaterialSummaryService {
             // 继续执行,不中断整个流程
         }
     }
+    //1	卷宗封面
+    //2	卷内目录
+    //3	政府定价成本监审结论报告
+    //4	成本监审通知书
+    //5	成本审核初步意见告知书
+    //6	成本审核初步意见表
+    //7	成本监审集体审议记录
+    //8	成本监审工作底稿
+    //9	成本监审提取资料登记表
+    //10	成本监审补充资料通知书
+    //11	中止定价成本监审通知书
+    //12	送达回证
+    //13	成本监审卷宗备考表
 
     // ==================== 类型1:成本监审报告(含成本监审报告签发稿、送达回证) ====================
     // A.成本监审报告(含成本监审报告签发稿)
@@ -228,8 +241,8 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"成本监审报告"、"成本监审报告签发稿"、"送达回证"
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "政府定价成本监审结论报告".equals(doc.getDocumentName())
-                        || "政府定价成本监审结论报告-送达回证".equals(doc.getDocumentName())
+                .filter(doc -> "3".equals(doc.getDocumentType())
+                        || "3-送达回证".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName())
                 )
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
@@ -240,7 +253,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -267,7 +281,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("监审主体上传文件");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getScanDocumentUrl() != null ? document.getScanDocumentUrl() : "");
@@ -282,7 +297,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName("成本项目定(调)价依据");
             detail.setDocumentNumber("");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(approval.getAccordingFileUrl());
@@ -299,8 +315,8 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // "成本监审通知书"和"送达回证"
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本监审通知书".equals(doc.getDocumentName())
-                        || "成本监审通知书-送达回证".equals(doc.getDocumentName()))
+                .filter(doc -> "4".equals(doc.getDocumentType())
+                        || "4-送达回证".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -310,7 +326,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -327,7 +344,7 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"成本资料清单"
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本监审资料提取资料登记表".equals(doc.getDocumentName()))
+                .filter(doc -> "9".equals(doc.getDocumentType()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -337,7 +354,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -357,6 +375,7 @@ public class AsyncMaterialSummaryService {
                     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);
@@ -384,6 +403,7 @@ public class AsyncMaterialSummaryService {
                     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);
@@ -403,8 +423,8 @@ public class AsyncMaterialSummaryService {
     private void generateType6Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
         int orderNum = 1;
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本监审补充资料通知书".equals(doc.getDocumentName())
-                        || "成本监审补充资料通知书-送达回证".equals(doc.getDocumentName()))
+                .filter(doc -> "10".equals(doc.getDocumentType())
+                        || "10-送达回证".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -414,7 +434,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -431,8 +452,8 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"成本审核初步意见告知书"和"送达回证"
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本审核初步意见告知书".equals(doc.getDocumentName())
-                        || "成本审核初步意见告知书-送达回证".equals(doc.getDocumentName()))
+                .filter(doc -> "5".equals(doc.getDocumentType())
+                        || "5-送达回证".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -442,7 +463,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -459,7 +481,7 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"书面反馈材料"(来源:监审单位反馈文件)
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "书面反馈材料".equals(doc.getDocumentName()))
+                .filter(doc -> "书面反馈材料".equals(doc.getDocumentType()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -469,7 +491,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("监审单位反馈文件");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -491,6 +514,7 @@ public class AsyncMaterialSummaryService {
                     detail.setTaskId(mainTask.getId());
                     detail.setDocumentName("书面反馈材料");
                     detail.setDocumentNumber("");
+                    detail.setAuditedUnitId(childTask.getAuditedUnitId());
                     detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
                     detail.setFileSource("监审单位反馈文件");
                     detail.setPageCount(0);
@@ -509,7 +533,7 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"成本审核初步意见表"
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本审核初步意见表".equals(doc.getDocumentName()))
+                .filter(doc -> "6".equals(doc.getDocumentType()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -519,7 +543,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -535,7 +560,7 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"成本监审集体审议记录"
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本监审集体审议记录".equals(doc.getDocumentName()))
+                .filter(doc -> "7".equals(doc.getDocumentType()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -545,7 +570,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -565,7 +591,8 @@ public class AsyncMaterialSummaryService {
                 detail.setTaskId(mainTask.getId());
                 detail.setDocumentName("成本监审集体审议记录");
                 detail.setDocumentNumber("");
-                detail.setAuditedUnitName("");
+                detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+                detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
                 detail.setFileSource("系统生成电子文书");
                 detail.setPageCount(0);
                 detail.setAttachmentUrl(deliberate.getAttachmentUrl());
@@ -582,7 +609,7 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"成本监审工作底稿"
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本监审工作底稿".equals(doc.getDocumentName()))
+                .filter(doc -> "8".equals(doc.getDocumentType()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -592,7 +619,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -611,6 +639,7 @@ public class AsyncMaterialSummaryService {
                     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);
@@ -629,7 +658,7 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"成本监审提取资料登记表"
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本监审提取资料登记表".equals(doc.getDocumentName()))
+                .filter(doc -> "9".equals(doc.getDocumentType()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -639,7 +668,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("系统生成电子文书");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -660,6 +690,7 @@ public class AsyncMaterialSummaryService {
                     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);
@@ -678,7 +709,7 @@ public class AsyncMaterialSummaryService {
         int orderNum = 1;
         // 获取"成本资料和会计凭证"(来源:被监审单位提交的资料)
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "成本资料和会计凭证".equals(doc.getDocumentName()))
+                .filter(doc -> "成本资料和会计凭证".equals(doc.getDocumentType()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -688,7 +719,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("监审单位反馈文件");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -711,7 +743,8 @@ public class AsyncMaterialSummaryService {
                     detail.setTaskId(mainTask.getId());
                     detail.setDocumentName(material.getInformationName() != null ? material.getInformationName() : "补充资料");
                     detail.setDocumentNumber("");
-                    detail.setAuditedUnitName("");
+                    detail.setAuditedUnitId(childTask.getAuditedUnitId());
+                    detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
                     detail.setFileSource("监审单位反馈文件");
                     detail.setPageCount(0);
                     detail.setAttachmentUrl(material.getFileUrl());
@@ -727,10 +760,10 @@ public class AsyncMaterialSummaryService {
     // 来源:从“监审文书”中获取。
     private void generateType14Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
         int orderNum = 1;
-        // 获取"成本资料和会计凭证"(来源:被监审单位提交的资料)
+        // 获取"中止定价成本监审通知书"(来源:被监审单位提交的资料)
         List<CostProjectDocument> matchedDocuments = documents.stream()
-                .filter(doc -> "中止定价成本监审通知书".equals(doc.getDocumentName())
-                        || "中止定价成本监审通知书-送达回证".equals(doc.getDocumentName()))
+                .filter(doc -> "11".equals(doc.getDocumentType())
+                        || "11-送达回证".equals(doc.getDocumentType()+"-"+doc.getDocumentTypeName()))
                 .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
                 .collect(Collectors.toList());
 
@@ -740,7 +773,8 @@ public class AsyncMaterialSummaryService {
             detail.setTaskId(mainTask.getId());
             detail.setDocumentName(document.getDocumentName());
             detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
-            detail.setAuditedUnitName("");
+            detail.setAuditedUnitId(mainTask.getAuditedUnitId());
+            detail.setAuditedUnitName(mainTask.getAuditedUnitName() != null ? mainTask.getAuditedUnitName() : "");
             detail.setFileSource("监审单位反馈文件");
             detail.setPageCount(0);
             detail.setAttachmentUrl(document.getActUrl() != null ? document.getActUrl() : "");
@@ -1137,7 +1171,7 @@ public class AsyncMaterialSummaryService {
                 CostProjectTask task = costProjectTaskManager.getById(existingSummary.getTaskId());
                 if (task != null) {
                     task.setArchiveNo(req.getArchiveNo());
-                    task.setArchiveUser(ContextUtil.getCurrentUser().getAccount());
+                    task.setArchiveUser(ContextUtil.getCurrentUser().getFullname());
                     costProjectTaskManager.updateById(task);
                 }
             }
@@ -1364,6 +1398,7 @@ public class AsyncMaterialSummaryService {
         map.put("{卷宗件数}", "1"); // 默认1件
         map.put("{卷宗页数}", String.valueOf(totalPageCount));
         map.put("{第几件}", "1"); // 默认第1件
+        map.put("{备注}", req.getRemark());
 
         return map;
     }

+ 1 - 1
assistMg/src/main/java/com/hotent/util/FileUploadUtil.java

@@ -181,7 +181,7 @@ public class FileUploadUtil {
         // 使用时间戳+随机数避免重名
         String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
         String random = String.valueOf(new Random().nextInt(1000));
-        return name + "_" + timestamp + "_" + random + extension;
+        return name +  timestamp + random + extension;
     }
 
     /**