Quellcode durchsuchen

fit:财务数据表-财务表填报

zzw vor 1 Monat
Ursprung
Commit
4845cf6c08

+ 629 - 0
assistMg/src/main/java/com/hotent/enterpriseDeclare/controller/material/CostProjectTaskFdTemplateExportController.java

@@ -0,0 +1,629 @@
+package com.hotent.enterpriseDeclare.controller.material;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.hotent.base.annotation.ApiGroup;
+import com.hotent.base.constants.ApiGroupConsts;
+import com.hotent.base.util.StringUtil;
+import com.hotent.base.model.CommonResult;
+import com.hotent.enterpriseDeclare.manager.CostSurveyFdTemplateUploadDataManager;
+import com.hotent.enterpriseDeclare.model.CostSurveyFdTemplateUploadData;
+import com.hotent.project.manager.CostProjectTaskMaterialManager;
+import com.hotent.project.model.CostProjectTaskMaterial;
+import com.hotent.surveyinfo.dao.CostSurveyFdTemplateHeadersDao;
+import com.hotent.surveyinfo.dao.CostSurveyFdTemplateItemsDao;
+import com.hotent.surveyinfo.manager.CostSurveyFdTemplateManager;
+import com.hotent.surveyinfo.manager.CostSurveyFdTemplateVersionManager;
+import com.hotent.surveyinfo.model.CostSurveyFdTemplate;
+import com.hotent.surveyinfo.model.CostSurveyFdTemplateHeaders;
+import com.hotent.surveyinfo.model.CostSurveyFdTemplateItems;
+import com.hotent.surveyinfo.model.CostSurveyFdTemplateVersion;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 任务定制-财务表导出 前端控制器
+ *
+ * @company 山西清众科技股份有限公司
+ * @author 超级管理员
+ * @since 2025-01-27
+ */
+@RestController
+@RequestMapping("/api/fdTemplateExport/v1/")
+@Api(tags = "任务定制-财务表")
+@ApiGroup(group = {ApiGroupConsts.GROUP_COST})
+public class CostProjectTaskFdTemplateExportController {
+
+    @Autowired
+    private CostSurveyFdTemplateManager templateManager;
+
+    @Autowired
+    private CostSurveyFdTemplateVersionManager versionManager;
+
+    @Autowired
+    private CostSurveyFdTemplateHeadersDao headersDao;
+
+    @Autowired
+    private CostSurveyFdTemplateItemsDao itemsDao;
+
+    @Autowired
+    private CostSurveyFdTemplateUploadDataManager uploadDataManager;
+
+    @Autowired
+    private CostProjectTaskMaterialManager costProjectTaskMaterialManager;
+
+
+    /**
+     * 导出财务表Excel
+     * @param surveyTemplateId 模板ID
+     * @param versionId 版本ID(可选,不传则使用当前版本)
+     * @param response HTTP响应对象
+     * @throws Exception 异常
+     */
+    @GetMapping(value = "/exportExcel")
+    @ApiOperation(value = "导出财务表Excel", httpMethod = "GET", notes = "根据模板ID导出财务表Excel,支持指定版本,不传版本ID则使用当前版本")
+    public void exportExcel(
+            @ApiParam(name = "surveyTemplateId", value = "模板ID", required = true)
+            @RequestParam(required = true) String surveyTemplateId,
+            @ApiParam(name = "versionId", value = "版本ID(可选,不传则使用当前版本)", required = false)
+            @RequestParam(required = false) String versionId,
+            HttpServletResponse response) throws Exception {
+
+        // 1. 获取模板信息
+        CostSurveyFdTemplate template = templateManager.get(surveyTemplateId);
+        if (template == null) {
+            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到指定的财务模板");
+            return;
+        }
+
+        // 2. 获取版本信息
+        CostSurveyFdTemplateVersion currentVersion = null;
+        if (StringUtil.isNotEmpty(versionId)) {
+            currentVersion = versionManager.get(versionId);
+        } else {
+            // 获取当前启用版本
+            currentVersion = versionManager.selectCurrentVersion(surveyTemplateId);
+        }
+        
+        if (currentVersion == null) {
+            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到指定的模板版本");
+            return;
+        }
+
+        // 3. 获取表头信息(根据版本)
+        List<CostSurveyFdTemplateHeaders> headersList = headersDao.selectBySurveyTemplateIdAndVersion(
+                surveyTemplateId, currentVersion.getId());
+        
+        // 过滤可见字段
+        headersList = headersList.stream()
+                .filter(header -> StringUtil.isEmpty(header.getShowVisible()) || "1".equals(header.getShowVisible()))
+                .collect(Collectors.toList());
+
+        if (headersList == null || headersList.isEmpty()) {
+            response.sendError(HttpServletResponse.SC_BAD_REQUEST, "未找到表头信息");
+            return;
+        }
+
+        // 4. 获取数据项信息(根据版本)
+        List<CostSurveyFdTemplateItems> itemsList = itemsDao.selectBySurveyTemplateIdAndVersion(
+                surveyTemplateId, currentVersion.getId());
+
+        // 5. 按照orderNum排序表头
+        headersList.sort(Comparator.comparing(header -> {
+            String orderNum = header.getOrderNum();
+            if (StringUtil.isEmpty(orderNum)) {
+                return Integer.MAX_VALUE;
+            }
+            try {
+                return Integer.parseInt(orderNum);
+            } catch (NumberFormatException e) {
+                return Integer.MAX_VALUE;
+            }
+        }));
+
+        // 6. 创建Excel工作簿
+        Workbook workbook = new XSSFWorkbook();
+        String sheetName = currentVersion.getSurveyTemplateName() != null ? 
+                currentVersion.getSurveyTemplateName() : 
+                (template.getSurveyTemplateName() != null ? template.getSurveyTemplateName() : "财务表");
+        Sheet sheet = workbook.createSheet(sheetName);
+
+        // 7. 创建表头行
+        Row headerRow = sheet.createRow(0);
+        for (int i = 0; i < headersList.size(); i++) {
+            CostSurveyFdTemplateHeaders header = headersList.get(i);
+            Cell cell = headerRow.createCell(i);
+            cell.setCellValue(header.getFieldName() != null ? header.getFieldName() : "");
+        }
+
+        // 8. 根据模板类型处理数据并填充到Excel
+        String templateType = template.getTemplateType();
+        if (itemsList != null && !itemsList.isEmpty()) {
+            // 构建表头ID到索引的映射
+            Map<String, Integer> headerIndexMap = new HashMap<>();
+            for (int i = 0; i < headersList.size(); i++) {
+                headerIndexMap.put(headersList.get(i).getId(), i);
+            }
+
+            // 根据模板类型采用不同的数据处理方式
+            switch (templateType != null ? templateType : "") {
+                case "1":
+                    // 单表(单记录):所有数据在一行
+                    exportSingleTable(sheet, itemsList, headerIndexMap);
+                    break;
+                case "2":
+                    // 固定表:按rowid或orderNum分组,每个分组一行
+                    exportFixedTable(sheet, itemsList, headerIndexMap);
+                    break;
+                case "3":
+                    // 动态表:按rowid分组,支持树形结构
+                    exportDynamicTable(sheet, itemsList, headerIndexMap);
+                    break;
+                default:
+                    // 未知类型,使用默认处理方式(按rowid分组)
+                    throw new IllegalArgumentException("未知的模板类型:" + templateType);
+            }
+        }
+
+        // 9. 自动调整列宽
+        for (int i = 0; i < headersList.size(); i++) {
+            sheet.autoSizeColumn(i);
+            // 设置最小列宽
+            sheet.setColumnWidth(i, Math.max(sheet.getColumnWidth(i), 3000));
+        }
+
+        // 10. 设置响应头
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setCharacterEncoding("utf-8");
+        String fileName = sheetName + "_" + System.currentTimeMillis() + ".xlsx";
+        response.setHeader("Content-Disposition", "attachment; filename=" +
+                URLEncoder.encode(fileName, "UTF-8"));
+
+        // 11. 写入响应输出流
+        workbook.write(response.getOutputStream());
+        workbook.close();
+    }
+
+    /**
+     * 导出单表(单记录):所有数据在一行
+     */
+    private void exportSingleTable(Sheet sheet, List<CostSurveyFdTemplateItems> itemsList, 
+                                    Map<String, Integer> headerIndexMap) {
+        Row dataRow = sheet.createRow(1);
+        for (CostSurveyFdTemplateItems item : itemsList) {
+            Integer colIndex = headerIndexMap.get(item.getHeadersId());
+            if (colIndex != null) {
+                Cell cell = dataRow.createCell(colIndex);
+                String value = getItemValue(item);
+                cell.setCellValue(value);
+            }
+        }
+    }
+
+    /**
+     * 导出固定表:按rowid或orderNum分组,每个分组一行
+     */
+    private void exportFixedTable(Sheet sheet, List<CostSurveyFdTemplateItems> itemsList, 
+                                   Map<String, Integer> headerIndexMap) {
+        // 优先按rowid分组
+        Map<String, List<CostSurveyFdTemplateItems>> itemsByRowId = itemsList.stream()
+                .filter(item -> StringUtil.isNotEmpty(item.getRowid()))
+                .collect(Collectors.groupingBy(CostSurveyFdTemplateItems::getRowid));
+
+        if (!itemsByRowId.isEmpty()) {
+            // 按rowid分组处理
+            int rowNum = 1;
+            // 按orderNum排序rowid(如果rowid是数字)
+            List<String> sortedRowIds = itemsByRowId.keySet().stream()
+                    .sorted((id1, id2) -> {
+                        try {
+                            return Integer.compare(Integer.parseInt(id1), Integer.parseInt(id2));
+                        } catch (NumberFormatException e) {
+                            return id1.compareTo(id2);
+                        }
+                    })
+                    .collect(Collectors.toList());
+
+            for (String rowId : sortedRowIds) {
+                Row dataRow = sheet.createRow(rowNum++);
+                List<CostSurveyFdTemplateItems> rowItems = itemsByRowId.get(rowId);
+                
+                // 按orderNum排序该行的数据
+                rowItems.sort(Comparator.comparing(item -> {
+                    Integer orderNum = item.getOrderNum();
+                    return orderNum != null ? orderNum : Integer.MAX_VALUE;
+                }));
+
+                // 填充该行的数据
+                fillRowData(sheet, dataRow, rowItems, headerIndexMap);
+            }
+        } else {
+            // 如果没有rowid,按orderNum分组
+            Map<Integer, List<CostSurveyFdTemplateItems>> itemsByOrderNum = itemsList.stream()
+                    .filter(item -> item.getOrderNum() != null)
+                    .collect(Collectors.groupingBy(CostSurveyFdTemplateItems::getOrderNum));
+
+            if (!itemsByOrderNum.isEmpty()) {
+                int rowNum = 1;
+                List<Integer> sortedOrderNums = itemsByOrderNum.keySet().stream()
+                        .sorted()
+                        .collect(Collectors.toList());
+
+                for (Integer orderNum : sortedOrderNums) {
+                    Row dataRow = sheet.createRow(rowNum++);
+                    List<CostSurveyFdTemplateItems> rowItems = itemsByOrderNum.get(orderNum);
+                    fillRowData(sheet, dataRow, rowItems, headerIndexMap);
+                }
+            } else {
+                // 如果既没有rowid也没有orderNum,按headersId分组(每个headersId一行)
+                Map<String, List<CostSurveyFdTemplateItems>> itemsByHeaderId = itemsList.stream()
+                        .filter(item -> StringUtil.isNotEmpty(item.getHeadersId()))
+                        .collect(Collectors.groupingBy(CostSurveyFdTemplateItems::getHeadersId));
+
+                int rowNum = 1;
+                for (Map.Entry<String, List<CostSurveyFdTemplateItems>> entry : itemsByHeaderId.entrySet()) {
+                    Row dataRow = sheet.createRow(rowNum++);
+                    List<CostSurveyFdTemplateItems> rowItems = entry.getValue();
+                    
+                    // 填充该行的数据(取第一个数据值)
+                    if (!rowItems.isEmpty()) {
+                        CostSurveyFdTemplateItems item = rowItems.get(0);
+                        Integer colIndex = headerIndexMap.get(item.getHeadersId());
+                        if (colIndex != null) {
+                            Cell cell = dataRow.createCell(colIndex);
+                            String value = getItemValue(item);
+                            cell.setCellValue(value);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * 导出动态表:按rowid分组,支持树形结构
+     */
+    private void exportDynamicTable(Sheet sheet, List<CostSurveyFdTemplateItems> itemsList, 
+                                     Map<String, Integer> headerIndexMap) {
+        Map<String, List<CostSurveyFdTemplateItems>> itemsByRowId = itemsList.stream()
+                .filter(item -> StringUtil.isNotEmpty(item.getRowid()))
+                .collect(Collectors.groupingBy(CostSurveyFdTemplateItems::getRowid));
+
+        if (!itemsByRowId.isEmpty()) {
+            int rowNum = 1;
+            // 按orderNum排序rowid
+            List<String> sortedRowIds = itemsByRowId.keySet().stream()
+                    .sorted((id1, id2) -> {
+                        try {
+                            return Integer.compare(Integer.parseInt(id1), Integer.parseInt(id2));
+                        } catch (NumberFormatException e) {
+                            return id1.compareTo(id2);
+                        }
+                    })
+                    .collect(Collectors.toList());
+
+            for (String rowId : sortedRowIds) {
+                Row dataRow = sheet.createRow(rowNum++);
+                List<CostSurveyFdTemplateItems> rowItems = itemsByRowId.get(rowId);
+                
+                // 按orderNum排序该行的数据
+                rowItems.sort(Comparator.comparing(item -> {
+                    Integer orderNum = item.getOrderNum();
+                    return orderNum != null ? orderNum : Integer.MAX_VALUE;
+                }));
+
+                fillRowData(sheet, dataRow, rowItems, headerIndexMap);
+            }
+        } else {
+            // 动态表如果没有rowid,按orderNum分组
+            Map<Integer, List<CostSurveyFdTemplateItems>> itemsByOrderNum = itemsList.stream()
+                    .filter(item -> item.getOrderNum() != null)
+                    .collect(Collectors.groupingBy(CostSurveyFdTemplateItems::getOrderNum));
+
+            int rowNum = 1;
+            List<Integer> sortedOrderNums = itemsByOrderNum.keySet().stream()
+                    .sorted()
+                    .collect(Collectors.toList());
+
+            for (Integer orderNum : sortedOrderNums) {
+                Row dataRow = sheet.createRow(rowNum++);
+                List<CostSurveyFdTemplateItems> rowItems = itemsByOrderNum.get(orderNum);
+                fillRowData(sheet, dataRow, rowItems, headerIndexMap);
+            }
+        }
+    }
+
+
+    /**
+     * 填充行数据
+     */
+    private void fillRowData(Sheet sheet, Row dataRow, List<CostSurveyFdTemplateItems> rowItems, 
+                             Map<String, Integer> headerIndexMap) {
+        for (CostSurveyFdTemplateItems item : rowItems) {
+            Integer colIndex = headerIndexMap.get(item.getHeadersId());
+            if (colIndex != null) {
+                Cell cell = dataRow.createCell(colIndex);
+                String value = getItemValue(item);
+                cell.setCellValue(value);
+            }
+        }
+    }
+
+    /**
+     * 获取数据项值(优先rvalue,其次jsonStr)
+     * @param item 数据项对象
+     * @return 数据值字符串
+     */
+    private String getItemValue(CostSurveyFdTemplateItems item) {
+        if (StringUtil.isNotEmpty(item.getRvalue())) {
+            return item.getRvalue();
+        } else if (StringUtil.isNotEmpty(item.getJsonStr())) {
+            return item.getJsonStr();
+        }
+        return "";
+    }
+
+    /**
+     * 导入财务表Excel数据
+     * @param file Excel文件
+     * @param surveyTemplateId 模板ID
+     * @param periodRecordId 监审期间记录ID(动态表使用,可选)
+     * @return 导入结果
+     * @throws Exception 异常
+     */
+    @PostMapping(value = "/importExcel")
+    @ApiOperation(value = "导入财务表Excel数据", httpMethod = "POST", notes = "导入Excel文件并存储数据到数据库")
+    public CommonResult<String> importExcel(
+            @ApiParam(name = "file", value = "Excel文件", required = true)
+            @RequestParam("file") MultipartFile file,
+            @ApiParam(name = "surveyTemplateId", value = "模板ID", required = true)
+            @RequestParam(required = true) String surveyTemplateId,
+            @ApiParam(name = "taskId", value = "任务ID", required = true)
+            @RequestParam(required = true) String taskId,
+            @ApiParam(name = "materialId", value = "材料ID", required = true)
+            @RequestParam(required = true) String materialId,
+            @ApiParam(name = "periodRecordId", value = "监审期间记录ID(动态表使用)", required = false)
+            @RequestParam(required = false) String periodRecordId) throws Exception {
+
+        // 1. 验证文件
+        if (file == null || file.isEmpty()) {
+            return CommonResult.<String>error().message("上传文件不能为空");
+        }
+
+        String fileName = file.getOriginalFilename();
+        if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
+            return CommonResult.<String>error().message("文件格式不正确,请上传Excel文件(.xlsx或.xls)");
+        }
+
+        // 2. 获取模板信息
+        CostSurveyFdTemplate template = templateManager.get(surveyTemplateId);
+        if (template == null) {
+            return CommonResult.<String>error().message("未找到指定的财务模板");
+        }
+
+        // 3. 获取当前版本(用于获取表头和数据项)
+        CostSurveyFdTemplateVersion currentVersion = versionManager.selectCurrentVersion(surveyTemplateId);
+        if (currentVersion == null) {
+            return CommonResult.<String>error().message("未找到启用的模板版本");
+        }
+
+        // 4. 获取表头信息(根据版本)
+        List<CostSurveyFdTemplateHeaders> headersList = headersDao.selectBySurveyTemplateIdAndVersion(
+                surveyTemplateId, currentVersion.getId());
+        
+        // 过滤可见字段
+        headersList = headersList.stream()
+                .filter(header -> StringUtil.isEmpty(header.getShowVisible()) || "1".equals(header.getShowVisible()))
+                .collect(Collectors.toList());
+        
+        if (headersList == null || headersList.isEmpty()) {
+            return CommonResult.<String>error().message("未找到表头信息");
+        }
+
+        // 5. 构建表头名称到表头信息的映射(包含ID和字段名)
+        Map<String, CostSurveyFdTemplateHeaders> headerNameToHeaderMap = new HashMap<>();
+        for (CostSurveyFdTemplateHeaders header : headersList) {
+            if (StringUtil.isNotEmpty(header.getFieldName())) {
+                headerNameToHeaderMap.put(header.getFieldName().trim(), header);
+            }
+        }
+
+        // 6. 读取Excel文件
+        Workbook workbook = null;
+        try (InputStream inputStream = file.getInputStream()) {
+            if (fileName.endsWith(".xlsx")) {
+                workbook = new XSSFWorkbook(inputStream);
+            } else {
+                workbook = new HSSFWorkbook(inputStream);
+            }
+
+            Sheet sheet = workbook.getSheetAt(0);
+            if (sheet == null || sheet.getPhysicalNumberOfRows() < 2) {
+                return CommonResult.<String>error().message("Excel文件没有数据或格式不正确");
+            }
+
+            // 7. 读取表头行(第一行)
+            Row headerRow = sheet.getRow(0);
+            if (headerRow == null) {
+                return CommonResult.<String>error().message("Excel文件第一行为空");
+            }
+
+            // 构建Excel列索引到表头信息的映射
+            Map<Integer, CostSurveyFdTemplateHeaders> columnIndexToHeaderMap = new HashMap<>();
+            for (int i = 0; i < headerRow.getLastCellNum(); i++) {
+                Cell cell = headerRow.getCell(i);
+                if (cell != null) {
+                    String cellValue = getCellStringValue(cell);
+                    if (StringUtil.isNotEmpty(cellValue)) {
+                        CostSurveyFdTemplateHeaders header = headerNameToHeaderMap.get(cellValue.trim());
+                        if (header != null) {
+                            columnIndexToHeaderMap.put(i, header);
+                        }
+                    }
+                }
+            }
+
+            if (columnIndexToHeaderMap.isEmpty()) {
+                return CommonResult.<String>error().message("Excel表头与模板表头不匹配");
+            }
+
+            // 8. 读取数据行并转换为实体对象
+            String templateType = template.getTemplateType();
+            List<CostSurveyFdTemplateUploadData> dataList = new ArrayList<>();
+            int dataRowCount = 0;
+            String currentRowId = null;
+
+            for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
+                Row dataRow = sheet.getRow(rowIndex);
+                if (dataRow == null) {
+                    continue;
+                }
+
+                // 判断是否为空行
+                boolean isEmptyRow = true;
+                for (int colIndex = 0; colIndex < dataRow.getLastCellNum(); colIndex++) {
+                    Cell cell = dataRow.getCell(colIndex);
+                    if (cell != null && StringUtil.isNotEmpty(getCellStringValue(cell))) {
+                        isEmptyRow = false;
+                        break;
+                    }
+                }
+                if (isEmptyRow) {
+                    continue;
+                }
+
+                // 根据模板类型处理数据
+                if ("1".equals(templateType)) {
+                    // 单表:所有数据在一行
+                    currentRowId = "row_" + System.currentTimeMillis();
+                    for (Map.Entry<Integer, CostSurveyFdTemplateHeaders> entry : columnIndexToHeaderMap.entrySet()) {
+                        int colIndex = entry.getKey();
+                        CostSurveyFdTemplateHeaders header = entry.getValue();
+                        Cell cell = dataRow.getCell(colIndex);
+                        String cellValue = getCellStringValue(cell);
+                        
+                        if (StringUtil.isNotEmpty(cellValue)) {
+                            CostSurveyFdTemplateUploadData uploadData = createUploadData(
+                                    surveyTemplateId,taskId,materialId, currentRowId,
+                                    header, cellValue, periodRecordId);
+                            dataList.add(uploadData);
+                        }
+                    }
+                    dataRowCount++;
+                } else {
+                    // 固定表和动态表:每行数据对应一个rowid
+                    currentRowId = "row_" + rowIndex;
+                    for (Map.Entry<Integer, CostSurveyFdTemplateHeaders> entry : columnIndexToHeaderMap.entrySet()) {
+                        int colIndex = entry.getKey();
+                        CostSurveyFdTemplateHeaders header = entry.getValue();
+                        Cell cell = dataRow.getCell(colIndex);
+                        String cellValue = getCellStringValue(cell);
+                        
+                        if (StringUtil.isNotEmpty(cellValue)) {
+                            CostSurveyFdTemplateUploadData uploadData = createUploadData(
+                                    surveyTemplateId, taskId,materialId, currentRowId,
+                                    header, cellValue, periodRecordId);
+                            dataList.add(uploadData);
+                        }
+                    }
+                    dataRowCount++;
+                }
+            }
+
+            if (dataList.isEmpty()) {
+                return CommonResult.<String>error().message("Excel文件中没有有效数据");
+            }
+
+            // 8. 保存数据
+            uploadDataManager.saveData(dataList);
+            CostProjectTaskMaterial manager = costProjectTaskMaterialManager.getById(materialId);
+            manager.setId(materialId);
+            manager.setIsUpload("1");
+            costProjectTaskMaterialManager.updateById(manager);
+            return CommonResult.<String>ok().message("导入成功,共导入 " + dataRowCount + " 行数据");
+        } catch (Exception e) {
+            return CommonResult.<String>error().message("导入失败:" + e.getMessage());
+        } finally {
+            if (workbook != null) {
+                workbook.close();
+            }
+        }
+
+    }
+
+    /**
+     * 创建上传数据对象
+     */
+    private CostSurveyFdTemplateUploadData createUploadData(String surveyTemplateId,
+                                                           String taskId, String materialId,
+                                                           String rowid, CostSurveyFdTemplateHeaders header, 
+                                                           String value, String periodRecordId) {
+        CostSurveyFdTemplateUploadData uploadData = new CostSurveyFdTemplateUploadData();
+        uploadData.setSurveyTemplateId(surveyTemplateId);
+        uploadData.setMaterialId(materialId);
+        uploadData.setTaskId(taskId);
+        uploadData.setRowid(rowid);
+        String rkey = StringUtil.isNotEmpty(header.getFieldEname()) ?
+                header.getFieldEname() : header.getFieldName();
+        uploadData.setRkey(rkey);
+        uploadData.setRvalue(value);
+        if (StringUtil.isNotEmpty(periodRecordId)) {
+            uploadData.setPeriodRecordId(periodRecordId);
+        }
+        uploadData.setIsDeleted("0");
+        return uploadData;
+    }
+
+    /**
+     * 获取单元格的字符串值
+     */
+    private String getCellStringValue(Cell cell) {
+        if (cell == null) {
+            return "";
+        }
+        
+        switch (cell.getCellType()) {
+            case STRING:
+                return cell.getStringCellValue();
+            case NUMERIC:
+                if (DateUtil.isCellDateFormatted(cell)) {
+                    return cell.getDateCellValue().toString();
+                } else {
+                    // 处理数字,避免科学计数法
+                    double numericValue = cell.getNumericCellValue();
+                    if (numericValue == (long) numericValue) {
+                        return String.valueOf((long) numericValue);
+                    } else {
+                        return String.valueOf(numericValue);
+                    }
+                }
+            case BOOLEAN:
+                return String.valueOf(cell.getBooleanCellValue());
+            case FORMULA:
+                try {
+                    return cell.getStringCellValue();
+                } catch (Exception e) {
+                    try {
+                        return String.valueOf(cell.getNumericCellValue());
+                    } catch (Exception ex) {
+                        return "";
+                    }
+                }
+            default:
+                return "";
+        }
+    }
+}
+

+ 44 - 0
assistMg/src/main/java/com/hotent/enterpriseDeclare/dao/CostSurveyFdTemplateUploadDataDao.java

@@ -0,0 +1,44 @@
+package com.hotent.enterpriseDeclare.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.hotent.enterpriseDeclare.model.CostSurveyFdTemplateUploadData;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 财务数据表模板上传数据表 Mapper 接口
+ *
+ * @company 山西清众科技股份有限公司
+ * @author 超级管理员
+ * @since 2025-01-27
+ */
+public interface CostSurveyFdTemplateUploadDataDao extends BaseMapper<CostSurveyFdTemplateUploadData> {
+    
+    /**
+     * 根据模板ID查询数据列表
+     * @param surveyTemplateId 模板ID
+     * @return 数据列表
+     */
+    List<CostSurveyFdTemplateUploadData> selectBySurveyTemplateId(@Param("surveyTemplateId") String surveyTemplateId);
+    
+    /**
+     * 根据模板ID和企业ID查询数据列表
+     * @param surveyTemplateId 模板ID
+     * @param auditedUnitId 企业ID
+     * @return 数据列表
+     */
+    List<CostSurveyFdTemplateUploadData> selectBySurveyTemplateIdAndAuditedUnitId(
+            @Param("surveyTemplateId") String surveyTemplateId,
+            @Param("auditedUnitId") String auditedUnitId);
+    
+    /**
+     * 根据行数据ID查询数据列表
+     * @param rowid 行数据ID
+     * @return 数据列表
+     */
+    List<CostSurveyFdTemplateUploadData> selectByRowid(@Param("rowid") String rowid);
+    
+
+}
+

+ 62 - 0
assistMg/src/main/java/com/hotent/enterpriseDeclare/manager/CostSurveyFdTemplateUploadDataManager.java

@@ -0,0 +1,62 @@
+package com.hotent.enterpriseDeclare.manager;
+
+import com.hotent.base.manager.BaseManager;
+import com.hotent.enterpriseDeclare.model.CostSurveyFdTemplateUploadData;
+
+import java.util.List;
+
+/**
+ * 财务数据表模板上传数据表 服务类
+ *
+ * @company 山西清众科技股份有限公司
+ * @author 超级管理员
+ * @since 2025-01-27
+ */
+public interface CostSurveyFdTemplateUploadDataManager extends BaseManager<CostSurveyFdTemplateUploadData> {
+    
+    /**
+     * 根据主键获取详情
+     * @param id
+     * @return
+     */
+    CostSurveyFdTemplateUploadData getDetail(String id);
+    
+    /**
+     * 新建、更新数据
+     * @param costSurveyFdTemplateUploadData
+     */
+    void createOrUpdate(CostSurveyFdTemplateUploadData costSurveyFdTemplateUploadData);
+    
+    /**
+     * 根据模板ID查询数据列表
+     * @param surveyTemplateId 模板ID
+     * @return 数据列表
+     */
+    List<CostSurveyFdTemplateUploadData> listBySurveyTemplateId(String surveyTemplateId);
+    
+    /**
+     * 根据模板ID和企业ID查询数据列表
+     * @param surveyTemplateId 模板ID
+     * @param auditedUnitId 企业ID
+     * @return 数据列表
+     */
+    List<CostSurveyFdTemplateUploadData> listBySurveyTemplateIdAndAuditedUnitId(String surveyTemplateId, String auditedUnitId);
+    
+    /**
+     * 根据行数据ID查询数据列表
+     * @param rowid 行数据ID
+     * @return 数据列表
+     */
+    List<CostSurveyFdTemplateUploadData> listByRowid(String rowid);
+    
+
+    
+    /**
+     * 保存数据(直接使用实体类列表)
+     * @param dataList 数据列表(实体类列表)
+     */
+    void saveData(List<CostSurveyFdTemplateUploadData> dataList);
+    
+
+}
+

+ 105 - 0
assistMg/src/main/java/com/hotent/enterpriseDeclare/manager/impl/CostSurveyFdTemplateUploadDataManagerImpl.java

@@ -0,0 +1,105 @@
+package com.hotent.enterpriseDeclare.manager.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.hotent.base.manager.impl.BaseManagerImpl;
+import com.hotent.base.util.StringUtil;
+import com.hotent.enterpriseDeclare.dao.CostSurveyFdTemplateUploadDataDao;
+import com.hotent.enterpriseDeclare.manager.CostSurveyFdTemplateUploadDataManager;
+import com.hotent.enterpriseDeclare.model.CostSurveyFdTemplateUploadData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 财务数据表模板上传数据表 服务实现类
+ *
+ * @company 山西清众科技股份有限公司
+ * @author 超级管理员
+ * @since 2025-01-27
+ */
+@Service
+public class CostSurveyFdTemplateUploadDataManagerImpl extends BaseManagerImpl<CostSurveyFdTemplateUploadDataDao, CostSurveyFdTemplateUploadData> implements CostSurveyFdTemplateUploadDataManager {
+
+    @Autowired
+    private CostSurveyFdTemplateUploadDataDao costSurveyFdTemplateUploadDataDao;
+
+    @Override
+    public CostSurveyFdTemplateUploadData getDetail(String id) {
+        CostSurveyFdTemplateUploadData data = this.get(id);
+        return data;
+    }
+
+    @Override
+    @Transactional
+    public void createOrUpdate(CostSurveyFdTemplateUploadData costSurveyFdTemplateUploadData) {
+        //新建或更新
+        this.saveOrUpdate(costSurveyFdTemplateUploadData);
+    }
+
+    @Override
+    public List<CostSurveyFdTemplateUploadData> listBySurveyTemplateId(String surveyTemplateId) {
+        return costSurveyFdTemplateUploadDataDao.selectBySurveyTemplateId(surveyTemplateId);
+    }
+
+    @Override
+    public List<CostSurveyFdTemplateUploadData> listBySurveyTemplateIdAndAuditedUnitId(String surveyTemplateId, String auditedUnitId) {
+        return costSurveyFdTemplateUploadDataDao.selectBySurveyTemplateIdAndAuditedUnitId(surveyTemplateId, auditedUnitId);
+    }
+
+    @Override
+    public List<CostSurveyFdTemplateUploadData> listByRowid(String rowid) {
+        return costSurveyFdTemplateUploadDataDao.selectByRowid(rowid);
+    }
+
+    @Override
+    @Transactional
+    public void saveData(List<CostSurveyFdTemplateUploadData> dataList) {
+        if (dataList == null || dataList.isEmpty()) {
+            return;
+        }
+
+        // 从第一条数据中提取信息
+        CostSurveyFdTemplateUploadData firstData = dataList.get(0);
+        String periodRecordId = firstData.getPeriodRecordId();
+        String materialId = firstData.getMaterialId();
+
+
+
+        // 先删除该模板和企业下的所有数据
+        QueryWrapper<CostSurveyFdTemplateUploadData> wrapper = new QueryWrapper<>();
+        wrapper.eq("material_id", materialId);
+        this.remove(wrapper);
+
+        // 设置公共字段并保存新数据
+        List<CostSurveyFdTemplateUploadData> saveList = new ArrayList<>();
+        for (CostSurveyFdTemplateUploadData data : dataList) {
+            if (data.getRowid() == null || data.getRowid().isEmpty() || 
+                data.getRkey() == null || data.getRkey().isEmpty()) {
+                continue;
+            }
+
+
+            data.setMaterialId(materialId);
+            // 如果是动态表,设置periodRecordId
+            if (StringUtil.isNotEmpty(periodRecordId)) {
+                data.setPeriodRecordId(periodRecordId);
+            }
+            if (data.getRvalue() == null) {
+                data.setRvalue("");
+            }
+            saveList.add(data);
+        }
+
+        // 批量保存
+        if (!saveList.isEmpty()) {
+            this.saveBatch(saveList);
+        }
+    }
+
+
+
+}
+

+ 252 - 0
assistMg/src/main/java/com/hotent/enterpriseDeclare/model/CostSurveyFdTemplateUploadData.java

@@ -0,0 +1,252 @@
+package com.hotent.enterpriseDeclare.model;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.hotent.base.entity.BaseModel;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * 财务数据表模板上传数据表
+ *
+ * @company 山西清众科技股份有限公司
+ * @author 超级管理员
+ * @since 2025-01-27
+ */
+@ApiModel(value="CostSurveyFdTemplateUploadData对象", description="财务数据表模板上传数据表")
+public class CostSurveyFdTemplateUploadData extends BaseModel<CostSurveyFdTemplateUploadData> {
+
+    private static final long serialVersionUID = 1L;
+    
+    @ApiModelProperty(value = "主键ID")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    @JsonProperty("id")
+    private String id;
+    
+    @ApiModelProperty(value = "财务数据表模板ID")
+    @TableField("survey_template_id")
+    @JsonProperty("surveyTemplateId")
+    private String surveyTemplateId;
+
+    private String materialId;
+
+    private String taskId;
+    
+    @ApiModelProperty(value = "企业ID")
+    @TableField("audited_unit_id")
+    @JsonProperty("auditedUnitId")
+    private String auditedUnitId;
+    
+    @ApiModelProperty(value = "行数据ID(标识同一行的数据)")
+    @TableField("rowid")
+    @JsonProperty("rowid")
+    private String rowid;
+    
+    @ApiModelProperty(value = "数据key(动态字段名)")
+    @TableField("rkey")
+    @JsonProperty("rkey")
+    private String rkey;
+    
+    @ApiModelProperty(value = "数据值(动态字段值)")
+    @TableField("rvalue")
+    @JsonProperty("rvalue")
+    private String rvalue;
+    
+    @ApiModelProperty(value = "关联监审期间记录ID(动态表使用)")
+    @TableField("period_record_id")
+    @JsonProperty("periodRecordId")
+    private String periodRecordId;
+
+    @ApiModelProperty(value = "父节点ID")
+    @TableField(exist = false)
+    @JsonProperty("parentId")
+    private String parentId;
+    
+    @ApiModelProperty(value = "逻辑删除:0正常 1删除")
+    @TableField("is_deleted")
+    @JsonProperty("isDeleted")
+    private String isDeleted;
+    
+    @ApiModelProperty(value = "创建时间")
+    @TableField("create_time")
+    @JsonProperty("createTime")
+    private LocalDateTime createTime;
+    
+    @ApiModelProperty(value = "创建人")
+    @TableField("create_by")
+    @JsonProperty("createBy")
+    private String createBy;
+    
+    @ApiModelProperty(value = "更新时间")
+    @TableField("update_time")
+    @JsonProperty("updateTime")
+    private LocalDateTime updateTime;
+    
+    @ApiModelProperty(value = "更新人")
+    @TableField("update_by")
+    @JsonProperty("updateBy")
+    private String updateBy;
+
+    // 临时字段(非数据库字段)
+    @ApiModelProperty(value = "监管目录ID")
+    @TableField(exist = false)
+    @JsonProperty("catalogId")
+    private String catalogId;
+
+
+    public String getMaterialId() {
+        return materialId;
+    }
+
+    public void setMaterialId(String materialId) {
+        this.materialId = materialId;
+    }
+
+    public String getTaskId() {
+        return taskId;
+    }
+
+    public void setTaskId(String taskId) {
+        this.taskId = taskId;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getSurveyTemplateId() {
+        return surveyTemplateId;
+    }
+
+    public void setSurveyTemplateId(String surveyTemplateId) {
+        this.surveyTemplateId = surveyTemplateId;
+    }
+
+    public String getAuditedUnitId() {
+        return auditedUnitId;
+    }
+
+    public void setAuditedUnitId(String auditedUnitId) {
+        this.auditedUnitId = auditedUnitId;
+    }
+
+    public String getRowid() {
+        return rowid;
+    }
+
+    public void setRowid(String rowid) {
+        this.rowid = rowid;
+    }
+
+    public String getRkey() {
+        return rkey;
+    }
+
+    public void setRkey(String rkey) {
+        this.rkey = rkey;
+    }
+
+    public String getRvalue() {
+        return rvalue;
+    }
+
+    public void setRvalue(String rvalue) {
+        this.rvalue = rvalue;
+    }
+
+    public String getPeriodRecordId() {
+        return periodRecordId;
+    }
+
+    public void setPeriodRecordId(String periodRecordId) {
+        this.periodRecordId = periodRecordId;
+    }
+
+    public String getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(String parentId) {
+        this.parentId = parentId;
+    }
+
+    public String getIsDeleted() {
+        return isDeleted;
+    }
+
+    public void setIsDeleted(String isDeleted) {
+        this.isDeleted = isDeleted;
+    }
+
+    public LocalDateTime getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(LocalDateTime createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getCreateBy() {
+        return createBy;
+    }
+
+    public void setCreateBy(String createBy) {
+        this.createBy = createBy;
+    }
+
+    public LocalDateTime getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(LocalDateTime updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getUpdateBy() {
+        return updateBy;
+    }
+
+    public void setUpdateBy(String updateBy) {
+        this.updateBy = updateBy;
+    }
+
+    public String getCatalogId() {
+        return catalogId;
+    }
+
+    public void setCatalogId(String catalogId) {
+        this.catalogId = catalogId;
+    }
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+    @Override
+    public String toString() {
+        return "CostSurveyFdTemplateUploadData{" +
+            "id='" + id + '\'' +
+            ", surveyTemplateId='" + surveyTemplateId + '\'' +
+            ", auditedUnitId='" + auditedUnitId + '\'' +
+            ", rowid='" + rowid + '\'' +
+            ", rkey='" + rkey + '\'' +
+            ", rvalue='" + rvalue + '\'' +
+            ", periodRecordId='" + periodRecordId + '\'' +
+            ", isDeleted='" + isDeleted + '\'' +
+            ", createTime=" + createTime +
+            ", createBy='" + createBy + '\'' +
+            ", updateTime=" + updateTime +
+            ", updateBy='" + updateBy + '\'' +
+            '}';
+    }
+}
+