Просмотр исходного кода

试验汇总

Signed-off-by: liuyc <56808083@qq.com>
liuyc 1 год назад
Родитель
Сommit
bbce83eb8a
13 измененных файлов с 953 добавлено и 539 удалено
  1. 0 3
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/TrialSummaryClassificationConfigurationMatchDTO.java
  2. 2 5
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/TrialSummaryClassificationConfigurationRelevancyDTO.java
  3. 31 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/TrialSummaryReflectionSaveDTO.java
  4. 8 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TrialSummaryClassificationConfiguration.java
  5. 25 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TrialSummaryExcelTabReflection.java
  6. 14 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExcelTabTreeVO.java
  7. 20 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SelectedTabVO.java
  8. 2 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TrialTreeVO.java
  9. 9 473
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSummaryController.java
  10. 498 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSummaryMonthlyController.java
  11. 196 5
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TrialSummaryClassificationConfigurationController.java
  12. 5 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/ITrialSummaryClassificationConfigurationService.java
  13. 143 49
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TrialSummaryClassificationConfigurationServiceImpl.java

+ 0 - 3
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/TrialSummaryClassificationConfigurationMatchDTO.java

@@ -8,9 +8,6 @@ import java.io.Serializable;
 @Data
 public class TrialSummaryClassificationConfigurationMatchDTO implements Serializable {
 
-    @ApiModelProperty(value = "项目id")
-    private String projectId;
-
     @ApiModelProperty(value = "分类id(page接口的id)")
     private String classId;
 

+ 2 - 5
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/TrialSummaryClassificationConfigurationRelevancyDTO.java

@@ -8,13 +8,10 @@ import java.io.Serializable;
 @Data
 public class TrialSummaryClassificationConfigurationRelevancyDTO implements Serializable {
 
-    @ApiModelProperty(value = "项目id")
-    private String projectId;
-
     @ApiModelProperty(value = "分类id(page接口的id)")
     private String classId;
 
-    @ApiModelProperty(value = "选择节点的pKeyId英文逗号拼接成ids")
-    private String ids;
+    @ApiModelProperty(value = "选择的清表id")
+    private String excelId;
 
 }

+ 31 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/TrialSummaryReflectionSaveDTO.java

@@ -0,0 +1,31 @@
+package org.springblade.manager.dto;
+
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class TrialSummaryReflectionSaveDTO implements Serializable {
+
+    @ApiModelProperty(value = "分类id")
+    private Long classId;
+
+    @ApiModelProperty(value = "映射数组信息")
+    private List<ReflectionBean> reflectionBeanList;
+
+    @Data
+    public class ReflectionBean implements Serializable {
+        @ApiModelProperty(value = "试验表的p_key_id")
+        private Long trialTabId;
+
+        @ApiModelProperty(value = "试验表下的元素id")
+        private Long elementId;
+
+        @ApiModelProperty(value = "对应html的坐标信息")
+        private String htmlKeyName;
+    }
+
+}

+ 8 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TrialSummaryClassificationConfiguration.java

@@ -1,6 +1,7 @@
 package org.springblade.manager.entity;
 
 import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.springblade.core.mp.base.BaseEntity;
@@ -16,12 +17,19 @@ public class TrialSummaryClassificationConfiguration extends BaseEntity {
 
     private static final long serialVersionUID = 1L;
 
+    @ApiModelProperty(value = "分类名称")
     private String className;
 
+    @ApiModelProperty(value = "关联的试验树id,英文逗号字符串拼接")
     private String trialTreeIds;
 
+    @ApiModelProperty(value = "关联的清表id")
     private Long excelId;
 
+    @ApiModelProperty(value = "清表对应的html路径")
+    private String htmlUrl;
+
+    @ApiModelProperty(value = "排序")
     private Integer sort;
 
 }

+ 25 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TrialSummaryExcelTabReflection.java

@@ -0,0 +1,25 @@
+package org.springblade.manager.entity;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class TrialSummaryExcelTabReflection implements Serializable {
+
+    private Long id;
+
+    @ApiModelProperty(value = "关联的清表id")
+    private Long excelId;
+
+    @ApiModelProperty(value = "试验表的p_key_id")
+    private Long trialTabId;
+
+    @ApiModelProperty(value = "试验表下的元素id")
+    private Long elementId;
+
+    @ApiModelProperty(value = "对应html的坐标信息")
+    private String htmlKeyName;
+
+}

+ 14 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExcelTabTreeVO.java

@@ -0,0 +1,14 @@
+package org.springblade.manager.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.manager.entity.ExcelTab;
+
+
+@Data
+public class ExcelTabTreeVO extends ExcelTab {
+
+    @ApiModelProperty(value = "回显状态 1=勾选")
+    private Integer recordStatus;
+
+}

+ 20 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SelectedTabVO.java

@@ -0,0 +1,20 @@
+package org.springblade.manager.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class SelectedTabVO implements Serializable {
+
+    @ApiModelProperty(value = "主键id")
+    private Long pKeyId;
+
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "表单名称")
+    private String tabName;
+
+}

+ 2 - 2
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TrialTreeVO.java

@@ -28,7 +28,7 @@ public class TrialTreeVO implements Serializable {
     @ApiModelProperty(value = "是否存在子节点 true=存在子级 false=不存在子级")
     private boolean hasChild;
 
-    @ApiModelProperty(value = "回显状态 0=未勾选 1=勾选")
-    private Integer status;
+    @ApiModelProperty(value = "回显状态 1=勾选")
+    private Integer recordStatus;
 
 }

+ 9 - 473
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSummaryController.java

@@ -1,498 +1,34 @@
 package org.springblade.business.controller;
 
-import com.aspose.cells.PageSetup;
-import com.aspose.cells.PaperSizeType;
-import com.aspose.cells.PdfSaveOptions;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
-import org.apache.commons.lang.StringUtils;
-import org.apache.poi.ss.usermodel.*;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.usermodel.*;
-import org.springblade.business.dto.TrialSummaryMonthlyEditDTO;
-import org.springblade.business.dto.TrialSummaryMonthlyPageDTO;
-import org.springblade.business.entity.TrialSelfInspectionRecord;
-import org.springblade.business.entity.TrialSummaryMonthlyRemarks;
-import org.springblade.common.utils.SnowFlakeUtil;
-import org.springblade.core.log.exception.ServiceException;
-import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.api.R;
-import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.manager.entity.TrialSummaryClassificationConfiguration;
 import org.springblade.resource.feign.NewIOSSClient;
-import org.springframework.core.io.ByteArrayResource;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.mock.web.MockMultipartFile;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServletResponse;
-import java.io.*;
-import java.net.URLDecoder;
-import java.util.*;
 import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Collectors;
 
 @RestController
 @AllArgsConstructor
 @RequestMapping("/trial/summary")
-@Api(value = "试验、月报汇总", tags = "试验、月报汇总接口")
+@Api(value = "试验汇总", tags = "试验汇总接口")
 public class TrialSummaryController {
 
     private final JdbcTemplate jdbcTemplate;
     private final NewIOSSClient newIOSSClient;
 
-    @PostMapping("/monthly/page")
+    @PostMapping("/list")
     @ApiOperationSupport(order = 1)
-    @ApiOperation(value = "月报汇总分页查询", notes = "传入TrialSummaryMonthlyPageDTO")
-    public R<IPage<Map<String, Object>>> monthlyPage(@RequestBody TrialSummaryMonthlyPageDTO dto) {
-        if (ObjectUtil.isEmpty(dto.getContractId()) || ObjectUtil.isEmpty(dto.getType()) || ObjectUtil.isEmpty(dto.getIds()) || StringUtils.isBlank(dto.getStartTime()) || StringUtils.isBlank(dto.getEndTime())) {
-            throw new ServiceException("入参异常");
-        }
-        List<Object> params = new ArrayList<>();
-        StringBuilder sqlString = new StringBuilder("SELECT * FROM u_trial_self_inspection_record WHERE 1=1 AND is_deleted = 0");
-        if (ObjectUtil.isNotEmpty(dto.getContractId())) {
-            sqlString.append(" AND contract_id = ?");
-            params.add(dto.getContractId());
-        }
-        if (ObjectUtil.isNotEmpty(dto.getType())) {
-            sqlString.append(" AND detection_category = ?");
-            params.add(dto.getType());
-        } else {
-            sqlString.append(" AND detection_category = 1");
-        }
-        if (StringUtils.isNotBlank(dto.getStartTime()) && StringUtils.isNotBlank(dto.getEndTime())) {
-            sqlString.append(" AND report_date BETWEEN ? AND ?");
-            params.add(dto.getStartTime());
-            params.add(dto.getEndTime());
-        }
-        if (StringUtils.isNotEmpty(dto.getIds())) {
-            sqlString.append(" AND node_id in(?)");
-            params.add(dto.getIds());
-        }
-
-        String sqlPage = sqlString.append(" ORDER BY create_time;").toString();
-        List<TrialSelfInspectionRecord> resultList = jdbcTemplate.query(
-                sqlPage,
-                new BeanPropertyRowMapper<>(TrialSelfInspectionRecord.class),
-                params.toArray()
-        );
-
-        Map<String, List<TrialSelfInspectionRecord>> groupTOTrialProjectName = resultList.stream()
-                .collect(Collectors.groupingBy(TrialSelfInspectionRecord::getTrialProjectName, LinkedHashMap::new, Collectors.toList()));
-
-        int current = dto.getCurrent();
-        int size = dto.getSize();
-        int start = (current - 1) * size;
-        Map<String, List<TrialSelfInspectionRecord>> paginatedMap = groupTOTrialProjectName.entrySet()
-                .stream()
-                .skip(start)
-                .limit(size)
-                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
-
-        if (paginatedMap.size() <= 0) {
-            return R.data(null);
-        }
-
-        Set<String> names = paginatedMap.keySet();
-        String commaSeparatedQuotedNames = names.stream()
-                .map(name -> "'" + name + "'")
-                .collect(Collectors.joining(","));
-        String sql = "SELECT * FROM u_trial_self_inspection_record WHERE is_deleted = 0 AND contract_id = " + dto.getContractId() + " AND trial_project_name IN (" + commaSeparatedQuotedNames + ")";
-        List<TrialSelfInspectionRecord> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TrialSelfInspectionRecord.class));
-        Map<String, List<TrialSelfInspectionRecord>> groupAllTOTrialProjectName = query.stream().collect(Collectors.groupingBy(TrialSelfInspectionRecord::getTrialProjectName));
-
-        String sqlRemarks = "SELECT record_id,remarks FROM m_trial_summary_monthly_remarks WHERE contract_id = ?";
-        List<TrialSummaryMonthlyRemarks> trialSummaryMonthlyRemarks = jdbcTemplate.query(sqlRemarks, new Object[]{dto.getContractId()}, new BeanPropertyRowMapper<>(TrialSummaryMonthlyRemarks.class));
-        Map<Long, TrialSummaryMonthlyRemarks> trialSummaryMonthlyRemarksMaps = trialSummaryMonthlyRemarks.stream().collect(Collectors.toMap(TrialSummaryMonthlyRemarks::getRecordId, Function.identity()));
-
-        IPage<Map<String, Object>> page = new Page<>();
-        List<Map<String, Object>> result = new LinkedList<>();
-
-        for (Map.Entry<String, List<TrialSelfInspectionRecord>> stringListEntry : paginatedMap.entrySet()) {
-            String key = stringListEntry.getKey();
-            if (ObjectUtil.isEmpty(key)) {
-                continue;
-            }
-
-            Map<String, Object> map = new LinkedHashMap<>();
-            map.put("trialProjectName", key);
-
-            List<TrialSelfInspectionRecord> currentMonthValue = stringListEntry.getValue();
-            Map<String, Object> currentMonthValueMap = new HashMap<>();
-            Optional<TrialSelfInspectionRecord> minIdRecord = currentMonthValue.stream()
-                    .min(Comparator.comparingLong(TrialSelfInspectionRecord::getId));
-            TrialSelfInspectionRecord minIdRecordOrNull = minIdRecord.orElse(null);
-            if (minIdRecordOrNull != null) {
-                long recordId = minIdRecordOrNull.getId() + 1; //防止与累加id重复,+1
-                currentMonthValueMap.put("recordId", recordId);
-                TrialSummaryMonthlyRemarks orDefault = trialSummaryMonthlyRemarksMaps.getOrDefault(recordId, null);
-                currentMonthValueMap.put("remarks", ObjectUtil.isNotEmpty(orDefault) ? ObjectUtil.isNotEmpty(orDefault.getRemarks()) ? orDefault.getRemarks() : "" : "");
-            }
-            currentMonthValueMap.put("qualifiedTotal", currentMonthValue.stream().filter(f -> f.getDetectionResult() == 1).count());
-            currentMonthValueMap.put("unQualifiedTotal", currentMonthValue.stream().filter(f -> f.getDetectionResult() == 0).count());
-            map.put("currentMonth", currentMonthValueMap);
-
-            List<TrialSelfInspectionRecord> totalMonthValue = groupAllTOTrialProjectName.getOrDefault(key, null);
-            Map<String, Object> totalMonthValueMap = new HashMap<>();
-            Optional<TrialSelfInspectionRecord> minIdRecordAll = totalMonthValue.stream()
-                    .min(Comparator.comparingLong(TrialSelfInspectionRecord::getId));
-            TrialSelfInspectionRecord minIdRecordOrNullAll = minIdRecordAll.orElse(null);
-            if (minIdRecordOrNullAll != null) {
-                long recordId = minIdRecordOrNullAll.getId() + 2; //防止与本月id重复,+2
-                totalMonthValueMap.put("recordId", recordId);
-                TrialSummaryMonthlyRemarks orDefault = trialSummaryMonthlyRemarksMaps.getOrDefault(recordId, null);
-                totalMonthValueMap.put("remarks", ObjectUtil.isNotEmpty(orDefault) ? ObjectUtil.isNotEmpty(orDefault.getRemarks()) ? orDefault.getRemarks() : "" : "");
-            }
-            totalMonthValueMap.put("qualifiedTotal", totalMonthValue.stream().filter(f -> f.getDetectionResult() == 1).count());
-            totalMonthValueMap.put("unQualifiedTotal", totalMonthValue.stream().filter(f -> f.getDetectionResult() == 0).count());
-            map.put("totalMonth", totalMonthValueMap);
-
-            result.add(map);
-        }
-
-        page.setRecords(result);
-        page.setSize(size);
-        page.setCurrent(current);
-        page.setTotal(groupTOTrialProjectName.size());
-        page.setPages((page.getTotal() + size - 1) / size);
-        return R.data(page);
+    @ApiOperation(value = "汇总分类列表", notes = "")
+    public R<List<TrialSummaryClassificationConfiguration>> list() {
+        return R.data(jdbcTemplate.query("SELECT * FROM m_trial_summary_classification_configuration WHERE is_deleted = 0 AND status = 1 ORDER BY sort,create_time", new BeanPropertyRowMapper<>(TrialSummaryClassificationConfiguration.class)));
     }
 
-    @PostMapping("/monthly/edit")
-    @ApiOperationSupport(order = 2)
-    @ApiOperation(value = "月报汇总编辑备注", notes = "传入TrialSummaryMonthlyEditDTO")
-    public R<Object> monthlyEdit(@RequestBody TrialSummaryMonthlyEditDTO dto) {
-        if (ObjectUtil.isEmpty(dto.getRecordId()) || ObjectUtil.isEmpty(dto.getContractId())) {
-            throw new ServiceException("入参异常");
-        }
-        if (ObjectUtil.isNotEmpty(dto.getRemarks()) && dto.getRemarks().length() > 2000) {
-            throw new ServiceException("备注信息最长2000个字符,请重新输入");
-        }
-        try {
-            String sql = "SELECT COUNT(*) FROM m_trial_summary_monthly_remarks WHERE record_id = ? AND contract_id = ?";
-            Integer count = jdbcTemplate.queryForObject(sql, Integer.class, dto.getRecordId(), dto.getContractId());
-            int rowCount = (count != null) ? count : 0;
-            if (rowCount == 0) {
-                String insertSql = "INSERT INTO m_trial_summary_monthly_remarks(id, contract_id, record_id, remarks) VALUES (?, ?, ?, ?)";
-                Object[] insertParams = {
-                        SnowFlakeUtil.getId(),
-                        dto.getContractId(),
-                        dto.getRecordId(),
-                        ObjectUtil.isNotEmpty(dto.getRemarks()) ? dto.getRemarks() : null
-                };
-                jdbcTemplate.update(insertSql, insertParams);
-            } else {
-                String updateSql = "UPDATE m_trial_summary_monthly_remarks SET remarks = ? WHERE record_id = ? AND contract_id = ?";
-                Object[] updateParams = {
-                        ObjectUtil.isNotEmpty(dto.getRemarks()) ? dto.getRemarks() : null,
-                        dto.getRecordId(),
-                        dto.getContractId()
-                };
-                jdbcTemplate.update(updateSql, updateParams);
-            }
-
-            return R.data(200, null, "操作成功");
-        } catch (Exception e) {
-            return R.fail("操作失败" + e.getMessage());
-        }
-    }
-
-    @PostMapping("/monthly/download")
-    @ApiOperationSupport(order = 3)
-    @ApiOperation(value = "月报汇总下载", notes = "传入TrialSummaryMonthlyPageDTO")
-    public void monthlyDownload(@RequestBody TrialSummaryMonthlyPageDTO dto, HttpServletResponse response) {
-        List<Map<String, Object>> records = monthlyPage(dto).getData().getRecords();
-        try (Workbook workbook = new XSSFWorkbook()) {
-            Sheet sheet = workbook.createSheet("Sheet1");
-            Row titleRow_1 = sheet.createRow(0);
-            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 1));
-            titleRow_1.setHeight((short) 500);
-            setCellValueWithNullCheck(titleRow_1.createCell(0), "", "");
-
-            CreationHelper helper = workbook.getCreationHelper();
-            XSSFDrawing xssfDrawing = (XSSFDrawing) sheet.createDrawingPatriarch();
-            ClientAnchor anchor = helper.createClientAnchor();
-            anchor.setCol1(0);
-            anchor.setCol2(2);
-            anchor.setRow1(0);
-            anchor.setRow2(2);
-            XSSFSimpleShape simpleShape = xssfDrawing.createSimpleShape((XSSFClientAnchor) anchor);
-            simpleShape.setShapeType(ShapeTypes.LINE);
-            simpleShape.setLineWidth(0.5);
-            simpleShape.setLineStyle(0);
-            simpleShape.setLineStyleColor(0, 0, 0);
-
-            int leftBottomX = anchor.getDx1();
-            int leftBottomY = anchor.getDy1();
-            int rightTopX = anchor.getDx2();
-            int rightTopY = anchor.getDy2();
-            XSSFDrawing xssfDrawingText1 = (XSSFDrawing) sheet.createDrawingPatriarch();
-            XSSFClientAnchor textBoxAnchor1 = new XSSFClientAnchor(leftBottomX, leftBottomY, leftBottomX, leftBottomY, 1, 0, 2, 1);
-            XSSFTextBox textBox1 = xssfDrawingText1.createTextbox(textBoxAnchor1);
-            textBox1.setText("试验组数");
-            XSSFDrawing xssfDrawingText2 = (XSSFDrawing) sheet.createDrawingPatriarch();
-            XSSFClientAnchor textBoxAnchor2 = new XSSFClientAnchor(rightTopX, rightTopY, rightTopX, rightTopY, 0, 1, 1, 2);
-            XSSFTextBox textBox2 = xssfDrawingText2.createTextbox(textBoxAnchor2);
-            textBox2.setText("试验项目");
-
-            sheet.addMergedRegion(new CellRangeAddress(0, 0, 2, 4));
-            setCellValueWithNullCheck(titleRow_1.createCell(2), "承包人", "");
-            Row titleRow_2 = sheet.createRow(1);
-            titleRow_2.setHeight((short) 500);
-            setCellValueWithNullCheck(titleRow_2.createCell(2), "合格数", "");
-            setCellValueWithNullCheck(titleRow_2.createCell(3), "不合格数", "");
-            setCellValueWithNullCheck(titleRow_2.createCell(4), "备注", "");
-
-            int rowNum = 2;
-            for (Map<String, Object> record : records) {
-                Row currentMonthRow = sheet.createRow(rowNum);
-                sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum + 1, 0, 0));
-                setCellValueWithNullCheck(currentMonthRow.createCell(0), "", record.get("trialProjectName"));
-
-                Map<String, Object> currentMonth = (Map<String, Object>) record.get("currentMonth");
-                setCellValueWithNullCheck(currentMonthRow.createCell(1), "本月", "");
-                setCellValueWithNullCheck(currentMonthRow.createCell(2), "", currentMonth.get("qualifiedTotal"));
-                setCellValueWithNullCheck(currentMonthRow.createCell(3), "", currentMonth.get("unQualifiedTotal"));
-                setCellValueWithNullCheck(currentMonthRow.createCell(4), "", currentMonth.get("remarks"));
-
-                Map<String, Object> totalMonth = (Map<String, Object>) record.get("totalMonth");
-                Row totalMonthRow = sheet.createRow(++rowNum);
-                setCellValueWithNullCheck(totalMonthRow.createCell(1), "累计", "");
-                setCellValueWithNullCheck(totalMonthRow.createCell(2), "", totalMonth.get("qualifiedTotal"));
-                setCellValueWithNullCheck(totalMonthRow.createCell(3), "", totalMonth.get("unQualifiedTotal"));
-                setCellValueWithNullCheck(totalMonthRow.createCell(4), "", totalMonth.get("remarks"));
-
-                rowNum++;
-            }
-
-            sheet.setColumnWidth(0, 5000);
-            sheet.setColumnWidth(1, 5000);
-            sheet.setColumnWidth(2, 5000);
-            sheet.setColumnWidth(3, 5000);
-            sheet.setColumnWidth(4, 5000);
-
-            try (ServletOutputStream outputStream = response.getOutputStream();
-                 ByteArrayOutputStream byteArrayOutputStreamResult = new ByteArrayOutputStream()) {
-                String fileName = dto.getStartTime() + "~" + dto.getEndTime() + ".xlsx";
-                String decodedFileName = URLDecoder.decode(fileName, "UTF-8");
-                response.setHeader("Content-Disposition", "attachment; filename=\"" + decodedFileName + "\"");
-                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
-                workbook.write(byteArrayOutputStreamResult);
-                byte[] excelBytesResult = byteArrayOutputStreamResult.toByteArray();
-                outputStream.write(excelBytesResult);
-
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                workbook.close();
-            }
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    private void setCellValueWithNullCheck(Cell cell, String defaultValue, Object value) {
-        if (ObjectUtil.isNotEmpty(value)) {
-            cell.setCellValue(String.valueOf(value));
-        } else {
-            cell.setCellValue(defaultValue);
-        }
-    }
-
-    @PostMapping("/monthly/print")
-    @ApiOperationSupport(order = 4)
-    @ApiOperation(value = "月报汇总打印", notes = "传入TrialSummaryMonthlyPageDTO")
-    public R<Object> monthlyPrint(@RequestBody TrialSummaryMonthlyPageDTO dto) {
-        List<Map<String, Object>> records = monthlyPage(dto).getData().getRecords();
-        try (Workbook workbook = new XSSFWorkbook()) {
-            Sheet sheet = workbook.createSheet("Sheet1");
-            Row titleRow_1 = sheet.createRow(0);
-            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 1));
-            titleRow_1.setHeight((short) 500);
-            setCellValueWithNullCheck(titleRow_1.createCell(0), "", "");
-
-            CreationHelper helper = workbook.getCreationHelper();
-            XSSFDrawing xssfDrawing = (XSSFDrawing) sheet.createDrawingPatriarch();
-            ClientAnchor anchor = helper.createClientAnchor();
-            anchor.setCol1(0);
-            anchor.setCol2(2);
-            anchor.setRow1(0);
-            anchor.setRow2(2);
-            XSSFSimpleShape simpleShape = xssfDrawing.createSimpleShape((XSSFClientAnchor) anchor);
-            simpleShape.setShapeType(ShapeTypes.LINE);
-            simpleShape.setLineWidth(0.5);
-            simpleShape.setLineStyle(0);
-            simpleShape.setLineStyleColor(0, 0, 0);
-
-            int leftBottomX = anchor.getDx1();
-            int leftBottomY = anchor.getDy1();
-            int rightTopX = anchor.getDx2();
-            int rightTopY = anchor.getDy2();
-            XSSFDrawing xssfDrawingText1 = (XSSFDrawing) sheet.createDrawingPatriarch();
-            XSSFClientAnchor textBoxAnchor1 = new XSSFClientAnchor(leftBottomX, leftBottomY, leftBottomX, leftBottomY, 1, 0, 2, 1);
-            XSSFTextBox textBox1 = xssfDrawingText1.createTextbox(textBoxAnchor1);
-            textBox1.setText("试验组数");
-            XSSFDrawing xssfDrawingText2 = (XSSFDrawing) sheet.createDrawingPatriarch();
-            XSSFClientAnchor textBoxAnchor2 = new XSSFClientAnchor(rightTopX, rightTopY, rightTopX, rightTopY, 0, 1, 1, 2);
-            XSSFTextBox textBox2 = xssfDrawingText2.createTextbox(textBoxAnchor2);
-            textBox2.setText("试验项目");
-
-            sheet.addMergedRegion(new CellRangeAddress(0, 0, 2, 4));
-            setCellValueWithNullCheck(titleRow_1.createCell(2), "承包人", "");
-            Row titleRow_2 = sheet.createRow(1);
-            titleRow_2.setHeight((short) 500);
-            setCellValueWithNullCheck(titleRow_2.createCell(2), "合格数", "");
-            setCellValueWithNullCheck(titleRow_2.createCell(3), "不合格数", "");
-            setCellValueWithNullCheck(titleRow_2.createCell(4), "备注", "");
-
-            int rowNum = 2;
-            for (Map<String, Object> record : records) {
-                Row currentMonthRow = sheet.createRow(rowNum);
-                sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum + 1, 0, 0));
-                setCellValueWithNullCheck(currentMonthRow.createCell(0), "", record.get("trialProjectName"));
-
-                Map<String, Object> currentMonth = (Map<String, Object>) record.get("currentMonth");
-                setCellValueWithNullCheck(currentMonthRow.createCell(1), "本月", "");
-                setCellValueWithNullCheck(currentMonthRow.createCell(2), "", currentMonth.get("qualifiedTotal"));
-                setCellValueWithNullCheck(currentMonthRow.createCell(3), "", currentMonth.get("unQualifiedTotal"));
-                setCellValueWithNullCheck(currentMonthRow.createCell(4), "", currentMonth.get("remarks"));
-
-                Map<String, Object> totalMonth = (Map<String, Object>) record.get("totalMonth");
-                Row totalMonthRow = sheet.createRow(++rowNum);
-                setCellValueWithNullCheck(totalMonthRow.createCell(1), "累计", "");
-                setCellValueWithNullCheck(totalMonthRow.createCell(2), "", totalMonth.get("qualifiedTotal"));
-                setCellValueWithNullCheck(totalMonthRow.createCell(3), "", totalMonth.get("unQualifiedTotal"));
-                setCellValueWithNullCheck(totalMonthRow.createCell(4), "", totalMonth.get("remarks"));
-
-                rowNum++;
-            }
-
-            sheet.setColumnWidth(0, 5000);
-            sheet.setColumnWidth(1, 5000);
-            sheet.setColumnWidth(2, 5000);
-            sheet.setColumnWidth(3, 5000);
-            sheet.setColumnWidth(4, 5000);
-
-            try (ByteArrayOutputStream byteArrayOutputStreamResult = new ByteArrayOutputStream()) {
-                workbook.write(byteArrayOutputStreamResult);
-                byte[] excelBytesResult = byteArrayOutputStreamResult.toByteArray();
-                MultipartFile multipartFile = convertExcelToPdf(excelBytesResult);
-                if (multipartFile != null) {
-                    BladeFile bladeFile = newIOSSClient.uploadFileByInputStream(multipartFile);
-                    if (bladeFile != null) {
-                        return R.data(bladeFile.getLink());
-                    }
-                }
-            } catch (IOException e) {
-                e.printStackTrace();
-            } finally {
-                workbook.close();
-            }
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return R.fail("操作失败");
-    }
-
-    private MultipartFile convertExcelToPdf(byte[] excelBytes) {
-        ByteArrayInputStream byteArrayInputStream = null;
-        ByteArrayOutputStream outReport = null;
-        try {
-            byteArrayInputStream = new ByteArrayInputStream(excelBytes);
-            Workbook ss = WorkbookFactory.create(byteArrayInputStream);
-            Sheet sheet = ss.getSheetAt(0);
-            for (int r = 0; r <= sheet.getLastRowNum(); r++) {
-                Row row = sheet.getRow(r);
-                if (row != null) {
-                    for (int c = 0; c < row.getLastCellNum(); c++) {
-                        Cell cell = row.getCell(c);
-                        if (cell != null) {
-                            CellStyle cellStyle = ss.createCellStyle();
-                            cellStyle.cloneStyleFrom(cell.getCellStyle());
-                            cellStyle.setBorderBottom(BorderStyle.THIN);
-                            cellStyle.setBorderTop(BorderStyle.THIN);
-                            cellStyle.setBorderRight(BorderStyle.THIN);
-                            cellStyle.setBorderLeft(BorderStyle.THIN);
-                            cell.setCellStyle(cellStyle);
-                            CellRangeAddress mergedRegion = getMergedRegion(sheet, r, c);
-                            if (mergedRegion != null) {
-                                setMergedRegionBorders(sheet, mergedRegion, cellStyle);
-                            }
-                        }
-                    }
-                }
-                sheet.setPrintGridlines(false);
-                sheet.setFitToPage(true);
-            }
-
-            outReport = new ByteArrayOutputStream();
-            ss.write(outReport);
-
-            PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
-            pdfSaveOptions.setOnePagePerSheet(true);
-
-            com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook(new ByteArrayInputStream(outReport.toByteArray()));
-            PageSetup pageSetup = wb.getWorksheets().get(0).getPageSetup();
-            pageSetup.setPaperSize(PaperSizeType.PAPER_A_4);
-
-            ByteArrayOutputStream pdfByteArrayOutputStream = new ByteArrayOutputStream();
-            wb.save(pdfByteArrayOutputStream, pdfSaveOptions);
-
-            ByteArrayResource resource = new ByteArrayResource(pdfByteArrayOutputStream.toByteArray());
-
-            return new MockMultipartFile("file", SnowFlakeUtil.getId() + ".pdf", "application/pdf", resource.getInputStream());
-
-        } catch (Exception e) {
-            e.printStackTrace();
-            return null;
-        } finally {
-            if (outReport != null) {
-                try {
-                    outReport.close();
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-            if (byteArrayInputStream != null) {
-                try {
-                    byteArrayInputStream.close();
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-        }
-    }
-
-    private void setMergedRegionBorders(Sheet sheet, CellRangeAddress region, CellStyle style) {
-        for (int row = region.getFirstRow(); row <= region.getLastRow(); row++) {
-            Row currentRow = sheet.getRow(row);
-            if (currentRow == null) {
-                currentRow = sheet.createRow(row);
-            }
-            for (int col = region.getFirstColumn(); col <= region.getLastColumn(); col++) {
-                Cell currentCell = currentRow.getCell(col);
-                if (currentCell == null) {
-                    currentCell = currentRow.createCell(col);
-                }
-                currentCell.setCellStyle(style);
-            }
-        }
-    }
-
-    private CellRangeAddress getMergedRegion(Sheet sheet, int row, int col) {
-        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
-            CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
-            if (mergedRegion.isInRange(row, col)) {
-                return mergedRegion;
-            }
-        }
-        return null;
-    }
 }

+ 498 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSummaryMonthlyController.java

@@ -0,0 +1,498 @@
+package org.springblade.business.controller;
+
+import com.aspose.cells.PageSetup;
+import com.aspose.cells.PaperSizeType;
+import com.aspose.cells.PdfSaveOptions;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.*;
+import org.springblade.business.dto.TrialSummaryMonthlyEditDTO;
+import org.springblade.business.dto.TrialSummaryMonthlyPageDTO;
+import org.springblade.business.entity.TrialSelfInspectionRecord;
+import org.springblade.business.entity.TrialSummaryMonthlyRemarks;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.resource.feign.NewIOSSClient;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLDecoder;
+import java.util.*;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@RestController
+@AllArgsConstructor
+@RequestMapping("/trial/summary")
+@Api(value = "月报汇总", tags = "月报汇总接口")
+public class TrialSummaryMonthlyController {
+
+    private final JdbcTemplate jdbcTemplate;
+    private final NewIOSSClient newIOSSClient;
+
+    @PostMapping("/monthly/page")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "月报汇总分页查询", notes = "传入TrialSummaryMonthlyPageDTO")
+    public R<IPage<Map<String, Object>>> monthlyPage(@RequestBody TrialSummaryMonthlyPageDTO dto) {
+        if (ObjectUtil.isEmpty(dto.getContractId()) || ObjectUtil.isEmpty(dto.getType()) || ObjectUtil.isEmpty(dto.getIds()) || StringUtils.isBlank(dto.getStartTime()) || StringUtils.isBlank(dto.getEndTime())) {
+            throw new ServiceException("入参异常");
+        }
+        List<Object> params = new ArrayList<>();
+        StringBuilder sqlString = new StringBuilder("SELECT * FROM u_trial_self_inspection_record WHERE 1=1 AND is_deleted = 0");
+        if (ObjectUtil.isNotEmpty(dto.getContractId())) {
+            sqlString.append(" AND contract_id = ?");
+            params.add(dto.getContractId());
+        }
+        if (ObjectUtil.isNotEmpty(dto.getType())) {
+            sqlString.append(" AND detection_category = ?");
+            params.add(dto.getType());
+        } else {
+            sqlString.append(" AND detection_category = 1");
+        }
+        if (StringUtils.isNotBlank(dto.getStartTime()) && StringUtils.isNotBlank(dto.getEndTime())) {
+            sqlString.append(" AND report_date BETWEEN ? AND ?");
+            params.add(dto.getStartTime());
+            params.add(dto.getEndTime());
+        }
+        if (StringUtils.isNotEmpty(dto.getIds())) {
+            sqlString.append(" AND node_id in(?)");
+            params.add(dto.getIds());
+        }
+
+        String sqlPage = sqlString.append(" ORDER BY create_time;").toString();
+        List<TrialSelfInspectionRecord> resultList = jdbcTemplate.query(
+                sqlPage,
+                new BeanPropertyRowMapper<>(TrialSelfInspectionRecord.class),
+                params.toArray()
+        );
+
+        Map<String, List<TrialSelfInspectionRecord>> groupTOTrialProjectName = resultList.stream()
+                .collect(Collectors.groupingBy(TrialSelfInspectionRecord::getTrialProjectName, LinkedHashMap::new, Collectors.toList()));
+
+        int current = dto.getCurrent();
+        int size = dto.getSize();
+        int start = (current - 1) * size;
+        Map<String, List<TrialSelfInspectionRecord>> paginatedMap = groupTOTrialProjectName.entrySet()
+                .stream()
+                .skip(start)
+                .limit(size)
+                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
+
+        if (paginatedMap.size() <= 0) {
+            return R.data(null);
+        }
+
+        Set<String> names = paginatedMap.keySet();
+        String commaSeparatedQuotedNames = names.stream()
+                .map(name -> "'" + name + "'")
+                .collect(Collectors.joining(","));
+        String sql = "SELECT * FROM u_trial_self_inspection_record WHERE is_deleted = 0 AND contract_id = " + dto.getContractId() + " AND trial_project_name IN (" + commaSeparatedQuotedNames + ")";
+        List<TrialSelfInspectionRecord> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TrialSelfInspectionRecord.class));
+        Map<String, List<TrialSelfInspectionRecord>> groupAllTOTrialProjectName = query.stream().collect(Collectors.groupingBy(TrialSelfInspectionRecord::getTrialProjectName));
+
+        String sqlRemarks = "SELECT record_id,remarks FROM m_trial_summary_monthly_remarks WHERE contract_id = ?";
+        List<TrialSummaryMonthlyRemarks> trialSummaryMonthlyRemarks = jdbcTemplate.query(sqlRemarks, new Object[]{dto.getContractId()}, new BeanPropertyRowMapper<>(TrialSummaryMonthlyRemarks.class));
+        Map<Long, TrialSummaryMonthlyRemarks> trialSummaryMonthlyRemarksMaps = trialSummaryMonthlyRemarks.stream().collect(Collectors.toMap(TrialSummaryMonthlyRemarks::getRecordId, Function.identity()));
+
+        IPage<Map<String, Object>> page = new Page<>();
+        List<Map<String, Object>> result = new LinkedList<>();
+
+        for (Map.Entry<String, List<TrialSelfInspectionRecord>> stringListEntry : paginatedMap.entrySet()) {
+            String key = stringListEntry.getKey();
+            if (ObjectUtil.isEmpty(key)) {
+                continue;
+            }
+
+            Map<String, Object> map = new LinkedHashMap<>();
+            map.put("trialProjectName", key);
+
+            List<TrialSelfInspectionRecord> currentMonthValue = stringListEntry.getValue();
+            Map<String, Object> currentMonthValueMap = new HashMap<>();
+            Optional<TrialSelfInspectionRecord> minIdRecord = currentMonthValue.stream()
+                    .min(Comparator.comparingLong(TrialSelfInspectionRecord::getId));
+            TrialSelfInspectionRecord minIdRecordOrNull = minIdRecord.orElse(null);
+            if (minIdRecordOrNull != null) {
+                long recordId = minIdRecordOrNull.getId() + 1; //防止与累加id重复,+1
+                currentMonthValueMap.put("recordId", recordId);
+                TrialSummaryMonthlyRemarks orDefault = trialSummaryMonthlyRemarksMaps.getOrDefault(recordId, null);
+                currentMonthValueMap.put("remarks", ObjectUtil.isNotEmpty(orDefault) ? ObjectUtil.isNotEmpty(orDefault.getRemarks()) ? orDefault.getRemarks() : "" : "");
+            }
+            currentMonthValueMap.put("qualifiedTotal", currentMonthValue.stream().filter(f -> f.getDetectionResult() == 1).count());
+            currentMonthValueMap.put("unQualifiedTotal", currentMonthValue.stream().filter(f -> f.getDetectionResult() == 0).count());
+            map.put("currentMonth", currentMonthValueMap);
+
+            List<TrialSelfInspectionRecord> totalMonthValue = groupAllTOTrialProjectName.getOrDefault(key, null);
+            Map<String, Object> totalMonthValueMap = new HashMap<>();
+            Optional<TrialSelfInspectionRecord> minIdRecordAll = totalMonthValue.stream()
+                    .min(Comparator.comparingLong(TrialSelfInspectionRecord::getId));
+            TrialSelfInspectionRecord minIdRecordOrNullAll = minIdRecordAll.orElse(null);
+            if (minIdRecordOrNullAll != null) {
+                long recordId = minIdRecordOrNullAll.getId() + 2; //防止与本月id重复,+2
+                totalMonthValueMap.put("recordId", recordId);
+                TrialSummaryMonthlyRemarks orDefault = trialSummaryMonthlyRemarksMaps.getOrDefault(recordId, null);
+                totalMonthValueMap.put("remarks", ObjectUtil.isNotEmpty(orDefault) ? ObjectUtil.isNotEmpty(orDefault.getRemarks()) ? orDefault.getRemarks() : "" : "");
+            }
+            totalMonthValueMap.put("qualifiedTotal", totalMonthValue.stream().filter(f -> f.getDetectionResult() == 1).count());
+            totalMonthValueMap.put("unQualifiedTotal", totalMonthValue.stream().filter(f -> f.getDetectionResult() == 0).count());
+            map.put("totalMonth", totalMonthValueMap);
+
+            result.add(map);
+        }
+
+        page.setRecords(result);
+        page.setSize(size);
+        page.setCurrent(current);
+        page.setTotal(groupTOTrialProjectName.size());
+        page.setPages((page.getTotal() + size - 1) / size);
+        return R.data(page);
+    }
+
+    @PostMapping("/monthly/edit")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "月报汇总编辑备注", notes = "传入TrialSummaryMonthlyEditDTO")
+    public R<Object> monthlyEdit(@RequestBody TrialSummaryMonthlyEditDTO dto) {
+        if (ObjectUtil.isEmpty(dto.getRecordId()) || ObjectUtil.isEmpty(dto.getContractId())) {
+            throw new ServiceException("入参异常");
+        }
+        if (ObjectUtil.isNotEmpty(dto.getRemarks()) && dto.getRemarks().length() > 2000) {
+            throw new ServiceException("备注信息最长2000个字符,请重新输入");
+        }
+        try {
+            String sql = "SELECT COUNT(*) FROM m_trial_summary_monthly_remarks WHERE record_id = ? AND contract_id = ?";
+            Integer count = jdbcTemplate.queryForObject(sql, Integer.class, dto.getRecordId(), dto.getContractId());
+            int rowCount = (count != null) ? count : 0;
+            if (rowCount == 0) {
+                String insertSql = "INSERT INTO m_trial_summary_monthly_remarks(id, contract_id, record_id, remarks) VALUES (?, ?, ?, ?)";
+                Object[] insertParams = {
+                        SnowFlakeUtil.getId(),
+                        dto.getContractId(),
+                        dto.getRecordId(),
+                        ObjectUtil.isNotEmpty(dto.getRemarks()) ? dto.getRemarks() : null
+                };
+                jdbcTemplate.update(insertSql, insertParams);
+            } else {
+                String updateSql = "UPDATE m_trial_summary_monthly_remarks SET remarks = ? WHERE record_id = ? AND contract_id = ?";
+                Object[] updateParams = {
+                        ObjectUtil.isNotEmpty(dto.getRemarks()) ? dto.getRemarks() : null,
+                        dto.getRecordId(),
+                        dto.getContractId()
+                };
+                jdbcTemplate.update(updateSql, updateParams);
+            }
+
+            return R.data(200, null, "操作成功");
+        } catch (Exception e) {
+            return R.fail("操作失败" + e.getMessage());
+        }
+    }
+
+    @PostMapping("/monthly/download")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "月报汇总下载", notes = "传入TrialSummaryMonthlyPageDTO")
+    public void monthlyDownload(@RequestBody TrialSummaryMonthlyPageDTO dto, HttpServletResponse response) {
+        List<Map<String, Object>> records = monthlyPage(dto).getData().getRecords();
+        try (Workbook workbook = new XSSFWorkbook()) {
+            Sheet sheet = workbook.createSheet("Sheet1");
+            Row titleRow_1 = sheet.createRow(0);
+            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 1));
+            titleRow_1.setHeight((short) 500);
+            setCellValueWithNullCheck(titleRow_1.createCell(0), "", "");
+
+            CreationHelper helper = workbook.getCreationHelper();
+            XSSFDrawing xssfDrawing = (XSSFDrawing) sheet.createDrawingPatriarch();
+            ClientAnchor anchor = helper.createClientAnchor();
+            anchor.setCol1(0);
+            anchor.setCol2(2);
+            anchor.setRow1(0);
+            anchor.setRow2(2);
+            XSSFSimpleShape simpleShape = xssfDrawing.createSimpleShape((XSSFClientAnchor) anchor);
+            simpleShape.setShapeType(ShapeTypes.LINE);
+            simpleShape.setLineWidth(0.5);
+            simpleShape.setLineStyle(0);
+            simpleShape.setLineStyleColor(0, 0, 0);
+
+            int leftBottomX = anchor.getDx1();
+            int leftBottomY = anchor.getDy1();
+            int rightTopX = anchor.getDx2();
+            int rightTopY = anchor.getDy2();
+            XSSFDrawing xssfDrawingText1 = (XSSFDrawing) sheet.createDrawingPatriarch();
+            XSSFClientAnchor textBoxAnchor1 = new XSSFClientAnchor(leftBottomX, leftBottomY, leftBottomX, leftBottomY, 1, 0, 2, 1);
+            XSSFTextBox textBox1 = xssfDrawingText1.createTextbox(textBoxAnchor1);
+            textBox1.setText("试验组数");
+            XSSFDrawing xssfDrawingText2 = (XSSFDrawing) sheet.createDrawingPatriarch();
+            XSSFClientAnchor textBoxAnchor2 = new XSSFClientAnchor(rightTopX, rightTopY, rightTopX, rightTopY, 0, 1, 1, 2);
+            XSSFTextBox textBox2 = xssfDrawingText2.createTextbox(textBoxAnchor2);
+            textBox2.setText("试验项目");
+
+            sheet.addMergedRegion(new CellRangeAddress(0, 0, 2, 4));
+            setCellValueWithNullCheck(titleRow_1.createCell(2), "承包人", "");
+            Row titleRow_2 = sheet.createRow(1);
+            titleRow_2.setHeight((short) 500);
+            setCellValueWithNullCheck(titleRow_2.createCell(2), "合格数", "");
+            setCellValueWithNullCheck(titleRow_2.createCell(3), "不合格数", "");
+            setCellValueWithNullCheck(titleRow_2.createCell(4), "备注", "");
+
+            int rowNum = 2;
+            for (Map<String, Object> record : records) {
+                Row currentMonthRow = sheet.createRow(rowNum);
+                sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum + 1, 0, 0));
+                setCellValueWithNullCheck(currentMonthRow.createCell(0), "", record.get("trialProjectName"));
+
+                Map<String, Object> currentMonth = (Map<String, Object>) record.get("currentMonth");
+                setCellValueWithNullCheck(currentMonthRow.createCell(1), "本月", "");
+                setCellValueWithNullCheck(currentMonthRow.createCell(2), "", currentMonth.get("qualifiedTotal"));
+                setCellValueWithNullCheck(currentMonthRow.createCell(3), "", currentMonth.get("unQualifiedTotal"));
+                setCellValueWithNullCheck(currentMonthRow.createCell(4), "", currentMonth.get("remarks"));
+
+                Map<String, Object> totalMonth = (Map<String, Object>) record.get("totalMonth");
+                Row totalMonthRow = sheet.createRow(++rowNum);
+                setCellValueWithNullCheck(totalMonthRow.createCell(1), "累计", "");
+                setCellValueWithNullCheck(totalMonthRow.createCell(2), "", totalMonth.get("qualifiedTotal"));
+                setCellValueWithNullCheck(totalMonthRow.createCell(3), "", totalMonth.get("unQualifiedTotal"));
+                setCellValueWithNullCheck(totalMonthRow.createCell(4), "", totalMonth.get("remarks"));
+
+                rowNum++;
+            }
+
+            sheet.setColumnWidth(0, 5000);
+            sheet.setColumnWidth(1, 5000);
+            sheet.setColumnWidth(2, 5000);
+            sheet.setColumnWidth(3, 5000);
+            sheet.setColumnWidth(4, 5000);
+
+            try (ServletOutputStream outputStream = response.getOutputStream();
+                 ByteArrayOutputStream byteArrayOutputStreamResult = new ByteArrayOutputStream()) {
+                String fileName = dto.getStartTime() + "~" + dto.getEndTime() + ".xlsx";
+                String decodedFileName = URLDecoder.decode(fileName, "UTF-8");
+                response.setHeader("Content-Disposition", "attachment; filename=\"" + decodedFileName + "\"");
+                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+                workbook.write(byteArrayOutputStreamResult);
+                byte[] excelBytesResult = byteArrayOutputStreamResult.toByteArray();
+                outputStream.write(excelBytesResult);
+
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                workbook.close();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void setCellValueWithNullCheck(Cell cell, String defaultValue, Object value) {
+        if (ObjectUtil.isNotEmpty(value)) {
+            cell.setCellValue(String.valueOf(value));
+        } else {
+            cell.setCellValue(defaultValue);
+        }
+    }
+
+    @PostMapping("/monthly/print")
+    @ApiOperationSupport(order = 4)
+    @ApiOperation(value = "月报汇总打印", notes = "传入TrialSummaryMonthlyPageDTO")
+    public R<Object> monthlyPrint(@RequestBody TrialSummaryMonthlyPageDTO dto) {
+        List<Map<String, Object>> records = monthlyPage(dto).getData().getRecords();
+        try (Workbook workbook = new XSSFWorkbook()) {
+            Sheet sheet = workbook.createSheet("Sheet1");
+            Row titleRow_1 = sheet.createRow(0);
+            sheet.addMergedRegion(new CellRangeAddress(0, 1, 0, 1));
+            titleRow_1.setHeight((short) 500);
+            setCellValueWithNullCheck(titleRow_1.createCell(0), "", "");
+
+            CreationHelper helper = workbook.getCreationHelper();
+            XSSFDrawing xssfDrawing = (XSSFDrawing) sheet.createDrawingPatriarch();
+            ClientAnchor anchor = helper.createClientAnchor();
+            anchor.setCol1(0);
+            anchor.setCol2(2);
+            anchor.setRow1(0);
+            anchor.setRow2(2);
+            XSSFSimpleShape simpleShape = xssfDrawing.createSimpleShape((XSSFClientAnchor) anchor);
+            simpleShape.setShapeType(ShapeTypes.LINE);
+            simpleShape.setLineWidth(0.5);
+            simpleShape.setLineStyle(0);
+            simpleShape.setLineStyleColor(0, 0, 0);
+
+            int leftBottomX = anchor.getDx1();
+            int leftBottomY = anchor.getDy1();
+            int rightTopX = anchor.getDx2();
+            int rightTopY = anchor.getDy2();
+            XSSFDrawing xssfDrawingText1 = (XSSFDrawing) sheet.createDrawingPatriarch();
+            XSSFClientAnchor textBoxAnchor1 = new XSSFClientAnchor(leftBottomX, leftBottomY, leftBottomX, leftBottomY, 1, 0, 2, 1);
+            XSSFTextBox textBox1 = xssfDrawingText1.createTextbox(textBoxAnchor1);
+            textBox1.setText("试验组数");
+            XSSFDrawing xssfDrawingText2 = (XSSFDrawing) sheet.createDrawingPatriarch();
+            XSSFClientAnchor textBoxAnchor2 = new XSSFClientAnchor(rightTopX, rightTopY, rightTopX, rightTopY, 0, 1, 1, 2);
+            XSSFTextBox textBox2 = xssfDrawingText2.createTextbox(textBoxAnchor2);
+            textBox2.setText("试验项目");
+
+            sheet.addMergedRegion(new CellRangeAddress(0, 0, 2, 4));
+            setCellValueWithNullCheck(titleRow_1.createCell(2), "承包人", "");
+            Row titleRow_2 = sheet.createRow(1);
+            titleRow_2.setHeight((short) 500);
+            setCellValueWithNullCheck(titleRow_2.createCell(2), "合格数", "");
+            setCellValueWithNullCheck(titleRow_2.createCell(3), "不合格数", "");
+            setCellValueWithNullCheck(titleRow_2.createCell(4), "备注", "");
+
+            int rowNum = 2;
+            for (Map<String, Object> record : records) {
+                Row currentMonthRow = sheet.createRow(rowNum);
+                sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum + 1, 0, 0));
+                setCellValueWithNullCheck(currentMonthRow.createCell(0), "", record.get("trialProjectName"));
+
+                Map<String, Object> currentMonth = (Map<String, Object>) record.get("currentMonth");
+                setCellValueWithNullCheck(currentMonthRow.createCell(1), "本月", "");
+                setCellValueWithNullCheck(currentMonthRow.createCell(2), "", currentMonth.get("qualifiedTotal"));
+                setCellValueWithNullCheck(currentMonthRow.createCell(3), "", currentMonth.get("unQualifiedTotal"));
+                setCellValueWithNullCheck(currentMonthRow.createCell(4), "", currentMonth.get("remarks"));
+
+                Map<String, Object> totalMonth = (Map<String, Object>) record.get("totalMonth");
+                Row totalMonthRow = sheet.createRow(++rowNum);
+                setCellValueWithNullCheck(totalMonthRow.createCell(1), "累计", "");
+                setCellValueWithNullCheck(totalMonthRow.createCell(2), "", totalMonth.get("qualifiedTotal"));
+                setCellValueWithNullCheck(totalMonthRow.createCell(3), "", totalMonth.get("unQualifiedTotal"));
+                setCellValueWithNullCheck(totalMonthRow.createCell(4), "", totalMonth.get("remarks"));
+
+                rowNum++;
+            }
+
+            sheet.setColumnWidth(0, 5000);
+            sheet.setColumnWidth(1, 5000);
+            sheet.setColumnWidth(2, 5000);
+            sheet.setColumnWidth(3, 5000);
+            sheet.setColumnWidth(4, 5000);
+
+            try (ByteArrayOutputStream byteArrayOutputStreamResult = new ByteArrayOutputStream()) {
+                workbook.write(byteArrayOutputStreamResult);
+                byte[] excelBytesResult = byteArrayOutputStreamResult.toByteArray();
+                MultipartFile multipartFile = convertExcelToPdf(excelBytesResult);
+                if (multipartFile != null) {
+                    BladeFile bladeFile = newIOSSClient.uploadFileByInputStream(multipartFile);
+                    if (bladeFile != null) {
+                        return R.data(bladeFile.getLink());
+                    }
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            } finally {
+                workbook.close();
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return R.fail("操作失败");
+    }
+
+    private MultipartFile convertExcelToPdf(byte[] excelBytes) {
+        ByteArrayInputStream byteArrayInputStream = null;
+        ByteArrayOutputStream outReport = null;
+        try {
+            byteArrayInputStream = new ByteArrayInputStream(excelBytes);
+            Workbook ss = WorkbookFactory.create(byteArrayInputStream);
+            Sheet sheet = ss.getSheetAt(0);
+            for (int r = 0; r <= sheet.getLastRowNum(); r++) {
+                Row row = sheet.getRow(r);
+                if (row != null) {
+                    for (int c = 0; c < row.getLastCellNum(); c++) {
+                        Cell cell = row.getCell(c);
+                        if (cell != null) {
+                            CellStyle cellStyle = ss.createCellStyle();
+                            cellStyle.cloneStyleFrom(cell.getCellStyle());
+                            cellStyle.setBorderBottom(BorderStyle.THIN);
+                            cellStyle.setBorderTop(BorderStyle.THIN);
+                            cellStyle.setBorderRight(BorderStyle.THIN);
+                            cellStyle.setBorderLeft(BorderStyle.THIN);
+                            cell.setCellStyle(cellStyle);
+                            CellRangeAddress mergedRegion = getMergedRegion(sheet, r, c);
+                            if (mergedRegion != null) {
+                                setMergedRegionBorders(sheet, mergedRegion, cellStyle);
+                            }
+                        }
+                    }
+                }
+                sheet.setPrintGridlines(false);
+                sheet.setFitToPage(true);
+            }
+
+            outReport = new ByteArrayOutputStream();
+            ss.write(outReport);
+
+            PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
+            pdfSaveOptions.setOnePagePerSheet(true);
+
+            com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook(new ByteArrayInputStream(outReport.toByteArray()));
+            PageSetup pageSetup = wb.getWorksheets().get(0).getPageSetup();
+            pageSetup.setPaperSize(PaperSizeType.PAPER_A_4);
+
+            ByteArrayOutputStream pdfByteArrayOutputStream = new ByteArrayOutputStream();
+            wb.save(pdfByteArrayOutputStream, pdfSaveOptions);
+
+            ByteArrayResource resource = new ByteArrayResource(pdfByteArrayOutputStream.toByteArray());
+
+            return new MockMultipartFile("file", SnowFlakeUtil.getId() + ".pdf", "application/pdf", resource.getInputStream());
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            if (outReport != null) {
+                try {
+                    outReport.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+            if (byteArrayInputStream != null) {
+                try {
+                    byteArrayInputStream.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private void setMergedRegionBorders(Sheet sheet, CellRangeAddress region, CellStyle style) {
+        for (int row = region.getFirstRow(); row <= region.getLastRow(); row++) {
+            Row currentRow = sheet.getRow(row);
+            if (currentRow == null) {
+                currentRow = sheet.createRow(row);
+            }
+            for (int col = region.getFirstColumn(); col <= region.getLastColumn(); col++) {
+                Cell currentCell = currentRow.getCell(col);
+                if (currentCell == null) {
+                    currentCell = currentRow.createCell(col);
+                }
+                currentCell.setCellStyle(style);
+            }
+        }
+    }
+
+    private CellRangeAddress getMergedRegion(Sheet sheet, int row, int col) {
+        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
+            CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
+            if (mergedRegion.isInRange(row, col)) {
+                return mergedRegion;
+            }
+        }
+        return null;
+    }
+}

+ 196 - 5
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TrialSummaryClassificationConfigurationController.java

@@ -1,22 +1,49 @@
 package org.springblade.manager.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.CommonUtil;
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.IoUtil;
+import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.manager.dto.TrialSummaryClassificationConfigurationMatchDTO;
 import org.springblade.manager.dto.TrialSummaryClassificationConfigurationRelevancyDTO;
-import org.springblade.manager.entity.TrialSummaryClassificationConfiguration;
+import org.springblade.manager.dto.TrialSummaryReflectionSaveDTO;
+import org.springblade.manager.entity.*;
+import org.springblade.manager.mapper.ExcelTabMapper;
 import org.springblade.manager.service.ITrialSummaryClassificationConfigurationService;
+import org.springblade.manager.service.IWbsFormElementService;
+import org.springblade.manager.service.impl.WbsTreePrivateServiceImpl;
+import org.springblade.manager.vo.ExcelTabTreeVO;
+import org.springblade.manager.vo.SelectedTabVO;
 import org.springblade.manager.vo.TrialTreeVO;
+import org.springblade.system.cache.ParamCache;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
+import java.io.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 
 @RestController
@@ -26,6 +53,10 @@ import javax.validation.Valid;
 public class TrialSummaryClassificationConfigurationController extends BladeController {
 
     private final ITrialSummaryClassificationConfigurationService iTrialSummaryClassificationConfigurationService;
+    private final WbsTreePrivateServiceImpl wbsTreePrivateServiceImpl;
+    private final ExcelTabMapper excelTabMapper;
+    private final JdbcTemplate jdbcTemplate;
+    private final IWbsFormElementService wbsFormElementService;
 
     @ApiOperationSupport(order = 1)
     @ApiOperation(value = "详情", notes = "传入id")
@@ -66,15 +97,175 @@ public class TrialSummaryClassificationConfigurationController extends BladeCont
     @ApiOperationSupport(order = 6)
     @ApiOperation(value = "关联清表", notes = "传入TrialSummaryClassificationConfigurationRelevancyDTO")
     @RequestMapping(value = "/relevancy", method = RequestMethod.POST)
-    public R<Object> relevancy(@RequestBody TrialSummaryClassificationConfigurationRelevancyDTO dto) {
+    public R<Object> relevancy(@RequestBody TrialSummaryClassificationConfigurationRelevancyDTO dto) throws IOException {
         return R.data(iTrialSummaryClassificationConfigurationService.relevancy(dto));
     }
 
     @ApiOperationSupport(order = 7)
-    @ApiOperation(value = "试验树全加载", notes = "传入项目id、classId=page接口数据id、type=1匹配划分 =2关联清表")
+    @ApiOperation(value = "试验树全加载", notes = "传入项目id、classId=page接口数据id")
     @RequestMapping(value = "/tree", method = RequestMethod.GET)
-    public R<TrialTreeVO> tree(@RequestParam String projectId, @RequestParam String classId, @RequestParam String type) {
-        return R.data(iTrialSummaryClassificationConfigurationService.tree(projectId, classId, type));
+    public R<TrialTreeVO> tree(@RequestParam String projectId, @RequestParam String classId) {
+        return R.data(iTrialSummaryClassificationConfigurationService.tree(projectId, classId));
+    }
+
+    @ApiOperationSupport(order = 8)
+    @ApiOperation(value = "关联清表-清表懒加载", notes = "清表列表调/api/blade-manager/exceltab/page接口;传入父级id、modeId、分类classId")
+    @RequestMapping(value = "/lazy", method = RequestMethod.GET)
+    public R<List<ExcelTabTreeVO>> lazy(@RequestParam String parentId, @RequestParam String modeId, @RequestParam String classId) {
+        List<ExcelTab> excelTabs = excelTabMapper.selectList(Wrappers.<ExcelTab>lambdaQuery().eq(ExcelTab::getParentId, parentId).like(ExcelTab::getAlias, modeId));
+        List<ExcelTabTreeVO> excelTabTreeVOS = BeanUtil.copyProperties(excelTabs, ExcelTabTreeVO.class);
+        TrialSummaryClassificationConfiguration classificationConfiguration = iTrialSummaryClassificationConfigurationService.getById(classId);
+        if (classificationConfiguration != null) {
+            for (ExcelTabTreeVO excelTabTreeVO : excelTabTreeVOS) {
+                if (excelTabTreeVO.getId().equals(classificationConfiguration.getExcelId())) {
+                    excelTabTreeVO.setRecordStatus(1);
+                }
+            }
+        }
+        return R.data(excelTabTreeVOS);
+    }
+
+    @ApiOperationSupport(order = 9)
+    @ApiOperation(value = "获取关联清表html", notes = "传入外层page接口分类id")
+    @RequestMapping(value = "/tab/html", method = RequestMethod.GET)
+    public R<String> html(@RequestParam String classId) throws Exception {
+        TrialSummaryClassificationConfiguration classificationConfiguration = iTrialSummaryClassificationConfigurationService.getById(classId);
+        if (classificationConfiguration != null && ObjectUtil.isNotEmpty(classificationConfiguration.getExcelId()) && ObjectUtil.isNotEmpty(classificationConfiguration.getHtmlUrl())) {
+            String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+            String sys_file_net_url = ParamCache.getValue(CommonConstant.SYS_FILE_NET_URL);
+            String fileUrl = classificationConfiguration.getHtmlUrl();
+            File file1 = ResourceUtil.getFile(fileUrl);
+            InputStream fileInputStream;
+            if (file1.exists()) {
+                fileInputStream = new FileInputStream(file1);
+            } else {
+                String path = sys_file_net_url + fileUrl.replaceAll("//", "/").replaceAll(file_path, "");
+                fileInputStream = CommonUtil.getOSSInputStream(path);
+            }
+            String htmlString = IoUtil.readToString(fileInputStream);
+            Document doc = Jsoup.parse(htmlString);
+            Element table = doc.select("table").first();
+            doc.select("Col").remove();
+            if (fileInputStream != null) {
+                fileInputStream.close();
+            }
+            return R.data(table.toString());
+        }
+        return R.fail("未关联清表信息");
+    }
+
+    @ApiOperationSupport(order = 10)
+    @ApiOperation(value = "选择表单列表", notes = "传入外层page接口分类id")
+    @RequestMapping(value = "/tab/list", method = RequestMethod.GET)
+    public R<List<SelectedTabVO>> tabList(@RequestParam String classId) {
+        TrialSummaryClassificationConfiguration trialSummaryClassificationConfiguration = iTrialSummaryClassificationConfigurationService.getById(classId);
+        if (trialSummaryClassificationConfiguration != null && ObjectUtil.isNotEmpty(trialSummaryClassificationConfiguration.getTrialTreeIds())) {
+            List<WbsTreePrivate> query = jdbcTemplate.query("SELECT id,project_id,wbs_id,wbs_type FROM m_wbs_tree_private WHERE p_key_id in (" + trialSummaryClassificationConfiguration.getTrialTreeIds() + ")", new BeanPropertyRowMapper<>(WbsTreePrivate.class));
+            List<Long> ids = query.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
+            String projectId = query.stream().map(WbsTreePrivate::getProjectId).findAny().orElse(null);
+            String wbsId = query.stream().map(WbsTreePrivate::getWbsId).findAny().orElse(null);
+            String wbsType = query.stream().map(WbsTreePrivate::getWbsType).findAny().orElse(null);
+            if (ids.size() > 0 && projectId != null && wbsId != null && wbsType != null) {
+                List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateServiceImpl.getBaseMapper().selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
+                        .in(WbsTreePrivate::getId, ids).eq(WbsTreePrivate::getProjectId, projectId)
+                        .eq(WbsTreePrivate::getWbsType, wbsType)
+                        .eq(WbsTreePrivate::getWbsId, wbsId));
+                List<SelectedTabVO> list = new ArrayList<>();
+                for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates) {
+                    SelectedTabVO vo = new SelectedTabVO();
+                    vo.setPKeyId(wbsTreePrivate.getPKeyId());
+                    vo.setId(wbsTreePrivate.getId());
+                    vo.setTabName(ObjectUtil.isNotEmpty(wbsTreePrivate.getFullName()) ? wbsTreePrivate.getFullName() : wbsTreePrivate.getNodeName());
+                    list.add(vo);
+                }
+                return R.data(list);
+            }
+        }
+        return null;
+    }
+
+    @ApiOperationSupport(order = 11)
+    @ApiOperation(value = "选择元素列表", notes = "传入/tab/list接口的id")
+    @RequestMapping(value = "/element/list", method = RequestMethod.GET)
+    public R<List<WbsFormElement>> elementList(@RequestParam String id) {
+        return R.data(wbsFormElementService.selectElementListByFid(id));
+    }
+
+    @ApiOperationSupport(order = 12)
+    @ApiOperation(value = "获取输入框映射数据来源", notes = "传入classId、html输入框的keyname值")
+    @RequestMapping(value = "/input/detail", method = RequestMethod.GET)
+    public R<Object> inputDetail(@RequestParam String classId, @RequestParam String keyName) {
+        TrialSummaryClassificationConfiguration classificationConfiguration = iTrialSummaryClassificationConfigurationService.getById(classId);
+        if (classificationConfiguration != null && ObjectUtil.isNotEmpty(classificationConfiguration.getExcelId())) {
+            String sql = "SELECT * FROM m_trial_summary_excel_tab_reflection WHERE excel_id = ? AND html_key_name = ?";
+            TrialSummaryExcelTabReflection obj = jdbcTemplate.query(sql, new Object[]{classificationConfiguration.getExcelId(), keyName}, new BeanPropertyRowMapper<>(TrialSummaryExcelTabReflection.class)).stream().findAny().orElse(null);
+            if (obj != null) {
+                WbsTreePrivate trialTab = wbsTreePrivateServiceImpl.getBaseMapper().getByPKeyId(obj.getTrialTabId());
+                WbsFormElement element = wbsFormElementService.getById(obj.getElementId());
+                if (trialTab != null && element != null) {
+                    Map<String, String> map = new HashMap<>();
+                    map.put("id", obj.getId().toString());
+                    map.put("tabName", ObjectUtil.isNotEmpty(trialTab.getFullName()) ? trialTab.getFullName() : trialTab.getNodeName());
+                    map.put("elementName", element.getEName());
+                    return R.data(map);
+                }
+            }
+        }
+        return R.data(null);
+    }
+
+    @ApiOperationSupport(order = 13)
+    @ApiOperation(value = "映射数据保存", notes = "传入TrialSummaryReflectionSaveDTO")
+    @RequestMapping(value = "/reflection/save", method = RequestMethod.POST)
+    public R<Object> reflectionSave(@RequestBody TrialSummaryReflectionSaveDTO dto) {
+        if (ObjectUtil.isNotEmpty(dto.getClassId())) {
+            if (ObjectUtil.isEmpty(dto.getReflectionBeanList().size()) || dto.getReflectionBeanList().size() == 0) {
+                return R.success("操作成功");
+            } else {
+                TrialSummaryClassificationConfiguration classificationConfiguration = iTrialSummaryClassificationConfigurationService.getById(dto.getClassId());
+                if (classificationConfiguration != null && ObjectUtil.isNotEmpty(classificationConfiguration.getExcelId())) {
+                    List<TrialSummaryReflectionSaveDTO.ReflectionBean> reflectionBeanList = dto.getReflectionBeanList();
+                    List<String> keyNameList = reflectionBeanList.stream()
+                            .map(bean -> "'" + bean.getHtmlKeyName() + "'")
+                            .collect(Collectors.toList());
+                    String sqlDel = "DELETE FROM m_trial_summary_excel_tab_reflection WHERE excel_id = ? AND html_key_name IN (" +
+                            StringUtils.repeat("?", ",", keyNameList.size()) + ")";
+                    List<Object> paramsDel = new ArrayList<>();
+                    paramsDel.add(classificationConfiguration.getExcelId());
+                    paramsDel.addAll(keyNameList);
+                    jdbcTemplate.update(sqlDel, paramsDel.toArray());
+
+                    String sqlInsert = "INSERT INTO m_trial_summary_excel_tab_reflection(id,excel_id,trial_tab_id,element_id,html_key_name) VALUES (?,?,?,?,?)";
+                    List<Object[]> batchArgs = new ArrayList<>();
+                    for (TrialSummaryReflectionSaveDTO.ReflectionBean reflectionBean : reflectionBeanList) {
+                        Object[] paramsInsert = {
+                                SnowFlakeUtil.getId(),
+                                classificationConfiguration.getExcelId(),
+                                reflectionBean.getTrialTabId(),
+                                reflectionBean.getElementId(),
+                                reflectionBean.getHtmlKeyName(),
+                        };
+                        batchArgs.add(paramsInsert);
+                    }
+                    jdbcTemplate.batchUpdate(sqlInsert, batchArgs);
+
+                    return R.success("操作成功");
+                }
+            }
+        }
+        return R.fail("操作失败");
+    }
+
+    @ApiOperationSupport(order = 14)
+    @ApiOperation(value = "映射数据删除", notes = "传入/input/detail接口返回的id")
+    @RequestMapping(value = "/reflection/remove", method = RequestMethod.POST)
+    public R<Object> reflectionRemove(@RequestParam String id) {
+        if (ObjectUtil.isNotEmpty(id)) {
+            String sqlDel = "DELETE FROM m_trial_summary_excel_tab_reflection WHERE id = ?";
+            jdbcTemplate.update(sqlDel, id);
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
     }
 
 }

+ 5 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/service/ITrialSummaryClassificationConfigurationService.java

@@ -7,6 +7,9 @@ import org.springblade.manager.dto.TrialSummaryClassificationConfigurationReleva
 import org.springblade.manager.entity.TrialSummaryClassificationConfiguration;
 import org.springblade.manager.vo.TrialTreeVO;
 
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
 public interface ITrialSummaryClassificationConfigurationService extends BaseService<TrialSummaryClassificationConfiguration> {
 
     TrialSummaryClassificationConfiguration detail(Long id);
@@ -17,8 +20,8 @@ public interface ITrialSummaryClassificationConfigurationService extends BaseSer
 
     boolean matching(TrialSummaryClassificationConfigurationMatchDTO dto);
 
-    boolean relevancy(TrialSummaryClassificationConfigurationRelevancyDTO dto);
+    boolean relevancy(TrialSummaryClassificationConfigurationRelevancyDTO dto) throws IOException;
 
-    TrialTreeVO tree(String projectId, String classId, String type);
+    TrialTreeVO tree(String projectId, String classId);
 
 }

+ 143 - 49
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TrialSummaryClassificationConfigurationServiceImpl.java

@@ -1,23 +1,40 @@
 package org.springblade.manager.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.springblade.common.utils.MathUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springblade.core.tool.utils.BeanUtil;
-import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.core.tool.utils.*;
 import org.springblade.manager.dto.TrialSummaryClassificationConfigurationMatchDTO;
 import org.springblade.manager.dto.TrialSummaryClassificationConfigurationRelevancyDTO;
-import org.springblade.manager.entity.TrialSummaryClassificationConfiguration;
-import org.springblade.manager.entity.WbsTreePrivate;
+import org.springblade.manager.entity.*;
 import org.springblade.manager.mapper.TrialSummaryClassificationConfigurationMapper;
+import org.springblade.manager.service.IExcelTabService;
+import org.springblade.manager.service.ITableInfoService;
 import org.springblade.manager.service.ITrialSummaryClassificationConfigurationService;
+import org.springblade.manager.service.IWbsFormElementService;
+import org.springblade.manager.utils.FileUtils;
+import org.springblade.manager.utils.RegularExpressionUtil;
+import org.springblade.manager.utils.WbsElementUtil;
 import org.springblade.manager.vo.TrialTreeVO;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.function.Function;
@@ -31,6 +48,8 @@ public class TrialSummaryClassificationConfigurationServiceImpl
 
     private final JdbcTemplate jdbcTemplate;
     private final WbsTreePrivateServiceImpl wbsTreePrivateServiceImpl;
+    private final IExcelTabService excelTabService;
+    private final IWbsFormElementService wbsFormElementService;
 
     @Override
     public TrialSummaryClassificationConfiguration detail(Long id) {
@@ -50,52 +69,129 @@ public class TrialSummaryClassificationConfigurationServiceImpl
 
     @Override
     public boolean matching(TrialSummaryClassificationConfigurationMatchDTO dto) {
-        if (ObjectUtil.isNotEmpty(dto.getIds()) && ObjectUtil.isNotEmpty(dto.getClassId()) && ObjectUtil.isNotEmpty(dto.getProjectId())) {
-            String delSql = "DELETE FROM m_trial_summary_class_config_record WHERE type = ? AND class_id = ?";
-            Object[] delParams = {1, dto.getClassId(),};
+        if (ObjectUtil.isNotEmpty(dto.getIds()) && ObjectUtil.isNotEmpty(dto.getClassId())) {
+            String delSql = "UPDATE m_trial_summary_classification_configuration SET trial_tree_ids = ? WHERE id = ?";
+            Object[] delParams = {dto.getIds(), dto.getClassId(),};
             jdbcTemplate.update(delSql, delParams);
-
-            for (String pKeyId : dto.getIds().split(",")) {
-                String insertSql = "INSERT INTO m_trial_summary_class_config_record(id,type,project_id,class_id,p_key_id) VALUES (?,?,?,?,?)";
-                Object[] insertParams = {
-                        SnowFlakeUtil.getId(),
-                        1,
-                        dto.getProjectId(),
-                        dto.getClassId(),
-                        pKeyId
-                };
-                jdbcTemplate.update(insertSql, insertParams);
-            }
             return true;
         }
         return false;
     }
 
     @Override
-    public boolean relevancy(TrialSummaryClassificationConfigurationRelevancyDTO dto) {
-        if (ObjectUtil.isNotEmpty(dto.getIds()) && ObjectUtil.isNotEmpty(dto.getClassId()) && ObjectUtil.isNotEmpty(dto.getProjectId())) {
-            String delSql = "DELETE FROM m_trial_summary_class_config_record WHERE type = ? AND class_id = ?";
-            Object[] delParams = {2, dto.getClassId(),};
-            jdbcTemplate.update(delSql, delParams);
+    public boolean relevancy(TrialSummaryClassificationConfigurationRelevancyDTO dto) throws IOException {
+        if (ObjectUtil.isNotEmpty(dto.getExcelId()) && ObjectUtil.isNotEmpty(dto.getClassId())) {
+            /*关联清表,重新生成html,重构定位信息*/
+            String file_path = FileUtils.getSysLocalFileUrl();
+            ExcelTab excelTab = excelTabService.getById(dto.getExcelId());
+            if (ObjectUtil.isEmpty(excelTab)) {
+                throw new ServiceException("未获取到清表信息");
+            }
+            if (ObjectUtil.isEmpty(excelTab.getTabId())) {
+                throw new ServiceException("未获取到清表tabId信息");
+            }
+            List<WbsFormElement> elementList = wbsFormElementService.selectElementListByFid(excelTab.getTabId());
+            if (elementList.size() == 0) {
+                throw new ServiceException("未获取到清表对应元素信息");
+            }
+
+            //复制模版htmlURL
+            File file_in = ResourceUtil.getFile(excelTab.getHtmlUrl());
+            String fileCode = SnowFlakeUtil.getId() + "";
+            String htmlUrl = file_path + "/privateUrl/" + fileCode + ".html";
+            File file_out = ResourceUtil.getFile(htmlUrl);
+            FileUtil.copy(file_in, file_out);
+
+            //匹配关联
+            File file1 = ResourceUtil.getFile(htmlUrl);
+            String htmlString = IoUtil.readToString(new FileInputStream(file1));
+            Document doc = Jsoup.parse(htmlString);
+            //解析
+            Element table = doc.select("table").first();
+            Elements trs = table.select("tr");
+            for (int i = 0; i < trs.size(); i++) {
+                Element tr = trs.get(i);
+                Elements tds = tr.select("td");
+                for (int j = 0; j < tds.size(); j++) {
+                    Element element = tds.get(j);
+                    if (element.html().indexOf("el-input") >= 0 || element.html().indexOf("el-date-picker") >= 0) {
+
+                        boolean is_true = false;
+                        String titleName = element.attr("title");
+                        double maxScore = 0.48;
+                        String lastName = "警告";
+                        String attrInfo = "key" + "__" + i + "_" + j;
+                        String filedType = "";
+                        String filedLength = "";
+
+                        for (WbsFormElement elementInfo : elementList) {
+                            String ysName = elementInfo.getEName();
+                            if (titleName.equals(ysName)) {
+                                lastName = elementInfo.getEName();
+                                attrInfo = elementInfo.getEKey() + "__" + i + "_" + j;
+
+                                filedType = WbsElementUtil.getInitTableFiledType(elementInfo.getEType());
 
-            for (String pKeyId : dto.getIds().split(",")) {
-                String sql = "INSERT INTO m_trial_summary_class_config_record(id,type,project_id,class_id,p_key_id) VALUES (?,?,?,?,?)";
-                Object[] insertParams = {
-                        SnowFlakeUtil.getId(),
-                        2,
-                        dto.getProjectId(),
-                        dto.getClassId(),
-                        pKeyId
-                };
-                jdbcTemplate.update(sql, insertParams);
+                                filedLength = elementInfo.getELength().toString();
+
+                                maxScore = 100;
+                                is_true = true;
+                                break;
+                            } else {
+                                if (MathUtil.sim(titleName, ysName) > maxScore) {
+                                    attrInfo = elementInfo.getEKey() + "__" + i + "_" + j;
+
+                                    filedType = WbsElementUtil.getInitTableFiledType(elementInfo.getEType());
+
+                                    filedLength = elementInfo.getELength().toString();
+
+                                    lastName = ysName;
+                                    maxScore = MathUtil.sim(titleName, ysName);
+                                    is_true = true;
+                                }
+                            }
+                        }
+                        String oncklickText = "'" + lastName + "'," + i + "," + j;
+
+                        //字段正则表达式校验
+                        String regularExpression = "$event" + "," + "'" + RegularExpressionUtil.getRegularExpression(filedType) + "','" + (StringUtils.isNotEmpty(filedType) ? WbsElementUtil.getTypeTips(filedType) : null) + "'," + i + "," + j;
+
+                        if (is_true) {
+                            element.children().get(0).attr("placeholder", lastName)
+                                    .attr("weighing", maxScore + "").attr("id", attrInfo).attr("keyName", attrInfo)
+                                    .attr("@blur", "getRegularExpression(" + regularExpression + ",'" + filedLength + "')")
+                                    .attr("v-model", "formData." + attrInfo)
+                                    .attr("maxlength", filedLength);
+                            if (element.html().indexOf("el-input") >= 0) {
+                                String mousedown = "$event" + "," + "'" + attrInfo + "'";
+                                element.children().get(0).attr("@mouseup.left", "inputLeftClick(" + mousedown + ")");
+                            }
+                        } else {
+                            element.children().get(0)
+                                    //.attr("placeholder", lastName)
+                                    .attr("weighing", maxScore + "").attr("id", attrInfo).attr("keyName", attrInfo)
+                                    .attr("@blur", "getRegularExpression(" + regularExpression + ",'" + filedLength + "')")
+                                    .attr("maxlength", filedLength)
+                                    .attr("class", "warnstyle");
+                        }
+                        element.attr("@click", "getInformation(" + oncklickText + ")");
+                    }
+                }
             }
+
+            File writeFile = new File(htmlUrl);
+            FileUtil.writeToFile(writeFile, doc.html(), Boolean.parseBoolean("UTF-8"));
+
+            String delSql = "UPDATE m_trial_summary_classification_configuration SET excel_id = ?,html_url = ? WHERE id = ?";
+            Object[] delParams = {dto.getExcelId(), htmlUrl, dto.getClassId()};
+            jdbcTemplate.update(delSql, delParams);
             return true;
         }
         return false;
     }
 
     @Override
-    public TrialTreeVO tree(String projectId, String classId, String type) {
+    public TrialTreeVO tree(String projectId, String classId) {
         List<WbsTreePrivate> wbsTreePrivatesNodes = wbsTreePrivateServiceImpl.getBaseMapper().selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
                 .select(WbsTreePrivate::getId, WbsTreePrivate::getPKeyId, WbsTreePrivate::getParentId, WbsTreePrivate::getNodeName)
                 .eq(WbsTreePrivate::getProjectId, projectId)
@@ -103,38 +199,36 @@ public class TrialSummaryClassificationConfigurationServiceImpl
                 .eq(WbsTreePrivate::getType, 1)
                 .eq(WbsTreePrivate::getStatus, 1)
         );
-        return buildTree(wbsTreePrivatesNodes, projectId, classId, type);
+        return buildTree(wbsTreePrivatesNodes, classId);
     }
 
-    private TrialTreeVO buildTree(List<WbsTreePrivate> wbsTreePrivatesNodes, String projectId, String classId, String type) {
+    private TrialTreeVO buildTree(List<WbsTreePrivate> wbsTreePrivatesNodes, String classId) {
         List<TrialTreeVO> trialTreeVOS = BeanUtil.copyProperties(wbsTreePrivatesNodes, TrialTreeVO.class);
         if (!trialTreeVOS.isEmpty()) {
-            String sql = "SELECT p_key_id FROM m_trial_summary_class_config_record WHERE class_id = ? AND project_id = ? AND type = ?";
-            Object[] params = {classId, projectId, type};
-            List<TrialTreeVO> query = jdbcTemplate.query(sql, params, new BeanPropertyRowMapper<>(TrialTreeVO.class));
-            Map<Long, TrialTreeVO> statusMap = query.stream().collect(Collectors.toMap(TrialTreeVO::getPKeyId, Function.identity()));
+            TrialSummaryClassificationConfiguration classificationConfiguration = baseMapper.selectById(classId);
+            List<String> trialTreeNodePKeyIds = new ArrayList<>();
+            if (classificationConfiguration != null) {
+                trialTreeNodePKeyIds = Func.toStrList(classificationConfiguration.getTrialTreeIds());
+            }
 
             Map<Long, List<TrialTreeVO>> map = trialTreeVOS.stream().collect(Collectors.groupingBy(TrialTreeVO::getParentId));
             List<TrialTreeVO> list = trialTreeVOS.stream().filter(f -> f.getParentId() == 0L).collect(Collectors.toList());
-            buildChildNodes(list, map, statusMap);
+            buildChildNodes(list, map, trialTreeNodePKeyIds);
             return trialTreeVOS.get(0);
         }
         return null;
     }
 
-    private void buildChildNodes(List<TrialTreeVO> list, Map<Long, List<TrialTreeVO>> map, Map<Long, TrialTreeVO> statusMap) {
+    private void buildChildNodes(List<TrialTreeVO> list, Map<Long, List<TrialTreeVO>> map, List<String> trialTreeNodePKeyIds) {
         for (TrialTreeVO trialTreeVO : list) {
-            TrialTreeVO orDefault = statusMap.getOrDefault(trialTreeVO.getPKeyId(), null);
-            if (orDefault != null) {
-                trialTreeVO.setStatus(1);
-            } else {
-                trialTreeVO.setStatus(0);
+            if (trialTreeNodePKeyIds.contains(trialTreeVO.getPKeyId().toString())) {
+                trialTreeVO.setRecordStatus(1);
             }
             List<TrialTreeVO> childrenList = map.getOrDefault(trialTreeVO.getId(), null);
             if (childrenList != null && childrenList.size() > 0) {
                 trialTreeVO.setChildNode(childrenList);
                 trialTreeVO.setHasChild(true);
-                buildChildNodes(childrenList, map, statusMap);
+                buildChildNodes(childrenList, map, trialTreeNodePKeyIds);
             }
         }
     }