Compare commits
No commits in common. 'd55394e5a1ce970cb759de51194f7c1facb523fb' and '912644f02fd3397a75642924b78b79424856220d' have entirely different histories.
d55394e5a1
...
912644f02f
6 changed files with 1 additions and 346 deletions
@ -1,35 +0,0 @@ |
|||||||
package com.biutag.supervision.pojo.vo; |
|
||||||
|
|
||||||
import com.alibaba.excel.annotation.ExcelProperty; |
|
||||||
import com.alibaba.excel.annotation.write.style.ColumnWidth; |
|
||||||
import lombok.Getter; |
|
||||||
import lombok.Setter; |
|
||||||
|
|
||||||
import java.time.LocalDateTime; |
|
||||||
|
|
||||||
@Setter |
|
||||||
@Getter |
|
||||||
public class ExportNegativeReturnVo { |
|
||||||
|
|
||||||
@ExcelProperty("问题编号") |
|
||||||
private String id; |
|
||||||
|
|
||||||
@ExcelProperty("样本源头编号") |
|
||||||
private String originId; |
|
||||||
|
|
||||||
@ExcelProperty("退回次数") |
|
||||||
private Integer returnCount; |
|
||||||
|
|
||||||
@ExcelProperty(value = "退回时间", format = "yyyy-MM-dd HH:mm:ss") |
|
||||||
private LocalDateTime returnTime; |
|
||||||
|
|
||||||
@ExcelProperty("退回人员") |
|
||||||
private String returnUser; |
|
||||||
|
|
||||||
@ExcelProperty("退回意见") |
|
||||||
private String returnOpinion; |
|
||||||
|
|
||||||
@ExcelProperty("修改核查内容") |
|
||||||
@ColumnWidth(80) |
|
||||||
private String modifiedVerifyContent; |
|
||||||
} |
|
||||||
@ -1,79 +0,0 @@ |
|||||||
package com.biutag.supervision.service; |
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil; |
|
||||||
import com.alibaba.excel.write.handler.CellWriteHandler; |
|
||||||
import com.alibaba.excel.write.handler.context.CellWriteHandlerContext; |
|
||||||
import org.apache.poi.ss.usermodel.Cell; |
|
||||||
import org.apache.poi.ss.usermodel.CellStyle; |
|
||||||
import org.apache.poi.ss.usermodel.Font; |
|
||||||
import org.apache.poi.ss.usermodel.IndexedColors; |
|
||||||
import org.apache.poi.ss.usermodel.RichTextString; |
|
||||||
import org.apache.poi.ss.usermodel.Workbook; |
|
||||||
|
|
||||||
public class ModifiedVerifyContentCellWriteHandler implements CellWriteHandler { |
|
||||||
|
|
||||||
private static final int MODIFIED_VERIFY_CONTENT_COLUMN_INDEX = 6; |
|
||||||
|
|
||||||
private Font labelFont; |
|
||||||
private Font arrowFont; |
|
||||||
private CellStyle wrappedStyle; |
|
||||||
|
|
||||||
@Override |
|
||||||
public void afterCellDispose(CellWriteHandlerContext context) { |
|
||||||
if (Boolean.TRUE.equals(context.getHead()) |
|
||||||
|| !Integer.valueOf(MODIFIED_VERIFY_CONTENT_COLUMN_INDEX).equals(context.getColumnIndex())) { |
|
||||||
return; |
|
||||||
} |
|
||||||
Cell cell = context.getCell(); |
|
||||||
String content = cell.getStringCellValue(); |
|
||||||
if (StrUtil.isBlank(content)) { |
|
||||||
return; |
|
||||||
} |
|
||||||
Workbook workbook = cell.getSheet().getWorkbook(); |
|
||||||
applyWrappedStyle(workbook, cell); |
|
||||||
RichTextString richText = workbook.getCreationHelper().createRichTextString(content); |
|
||||||
String[] lines = content.split("\\n", -1); |
|
||||||
int offset = 0; |
|
||||||
for (String line : lines) { |
|
||||||
int separatorIndex = line.indexOf(':'); |
|
||||||
if (separatorIndex > 0) { |
|
||||||
richText.applyFont(offset, offset + separatorIndex, getLabelFont(workbook)); |
|
||||||
} |
|
||||||
int arrowIndex = line.indexOf('→', separatorIndex + 1); |
|
||||||
if (arrowIndex >= 0) { |
|
||||||
richText.applyFont(offset + arrowIndex, offset + arrowIndex + 1, getArrowFont(workbook)); |
|
||||||
} |
|
||||||
offset += line.length() + 1; |
|
||||||
} |
|
||||||
float requiredHeight = Math.max(cell.getRow().getHeightInPoints(), lines.length * 18F); |
|
||||||
cell.getRow().setHeightInPoints(requiredHeight); |
|
||||||
cell.setCellValue(richText); |
|
||||||
} |
|
||||||
|
|
||||||
private Font getLabelFont(Workbook workbook) { |
|
||||||
if (labelFont == null) { |
|
||||||
labelFont = workbook.createFont(); |
|
||||||
labelFont.setBold(true); |
|
||||||
labelFont.setColor(IndexedColors.BLACK.getIndex()); |
|
||||||
} |
|
||||||
return labelFont; |
|
||||||
} |
|
||||||
|
|
||||||
private Font getArrowFont(Workbook workbook) { |
|
||||||
if (arrowFont == null) { |
|
||||||
arrowFont = workbook.createFont(); |
|
||||||
arrowFont.setBold(true); |
|
||||||
arrowFont.setColor(IndexedColors.RED.getIndex()); |
|
||||||
} |
|
||||||
return arrowFont; |
|
||||||
} |
|
||||||
|
|
||||||
private void applyWrappedStyle(Workbook workbook, Cell cell) { |
|
||||||
if (wrappedStyle == null) { |
|
||||||
wrappedStyle = workbook.createCellStyle(); |
|
||||||
wrappedStyle.cloneStyleFrom(cell.getCellStyle()); |
|
||||||
wrappedStyle.setWrapText(true); |
|
||||||
} |
|
||||||
cell.setCellStyle(wrappedStyle); |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,165 +0,0 @@ |
|||||||
package com.biutag.supervision.service; |
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil; |
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|
||||||
import com.biutag.supervision.pojo.entity.NegativeHistory; |
|
||||||
import com.biutag.supervision.pojo.vo.ExportNegativeReturnVo; |
|
||||||
import com.biutag.supervision.pojo.vo.NegativeQueryVo; |
|
||||||
import com.biutag.supervision.util.JSON; |
|
||||||
import com.fasterxml.jackson.databind.JsonNode; |
|
||||||
import lombok.RequiredArgsConstructor; |
|
||||||
import org.springframework.stereotype.Service; |
|
||||||
|
|
||||||
import java.util.ArrayList; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.LinkedHashMap; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Map; |
|
||||||
import java.util.Objects; |
|
||||||
import java.util.stream.Collectors; |
|
||||||
|
|
||||||
@RequiredArgsConstructor |
|
||||||
@Service |
|
||||||
public class NegativeReturnExportService { |
|
||||||
|
|
||||||
private final NegativeHistoryService negativeHistoryService; |
|
||||||
|
|
||||||
public ExportData build(List<NegativeQueryVo> data) { |
|
||||||
if (data.isEmpty()) { |
|
||||||
return new ExportData(Collections.emptyMap(), Collections.emptyList()); |
|
||||||
} |
|
||||||
List<String> negativeIds = data.stream().map(NegativeQueryVo::getId).toList(); |
|
||||||
List<NegativeHistory> histories = negativeHistoryService.list(new LambdaQueryWrapper<NegativeHistory>() |
|
||||||
.in(NegativeHistory::getNegativeId, negativeIds) |
|
||||||
.orderByAsc(NegativeHistory::getNegativeId) |
|
||||||
.orderByAsc(NegativeHistory::getCrtTime)); |
|
||||||
Map<String, List<NegativeHistory>> historyMap = histories.stream() |
|
||||||
.collect(Collectors.groupingBy(NegativeHistory::getNegativeId, LinkedHashMap::new, Collectors.toList())); |
|
||||||
Map<String, Integer> returnCountMap = new HashMap<>(); |
|
||||||
List<ExportNegativeReturnVo> returnRecords = new ArrayList<>(); |
|
||||||
|
|
||||||
for (NegativeQueryVo negative : data) { |
|
||||||
List<NegativeHistory> negativeHistories = historyMap.getOrDefault(negative.getId(), Collections.emptyList()); |
|
||||||
VerifySnapshot latestSnapshot = null; |
|
||||||
PendingReturn pendingReturn = null; |
|
||||||
int returnCount = 0; |
|
||||||
for (NegativeHistory history : negativeHistories) { |
|
||||||
ParsedHistory parsedHistory = parseHistory(history); |
|
||||||
if (parsedHistory.snapshot() != null) { |
|
||||||
latestSnapshot = parsedHistory.snapshot(); |
|
||||||
} |
|
||||||
if (isReturnAction(parsedHistory.actionKey())) { |
|
||||||
returnCount++; |
|
||||||
ExportNegativeReturnVo returnVo = new ExportNegativeReturnVo(); |
|
||||||
returnVo.setId(negative.getId()); |
|
||||||
returnVo.setOriginId(negative.getOriginId()); |
|
||||||
returnVo.setReturnCount(returnCount); |
|
||||||
returnVo.setReturnTime(history.getCrtTime()); |
|
||||||
returnVo.setReturnUser(history.getCrtName()); |
|
||||||
returnVo.setReturnOpinion(parsedHistory.comments()); |
|
||||||
returnVo.setModifiedVerifyContent("尚未再次提交"); |
|
||||||
returnRecords.add(returnVo); |
|
||||||
pendingReturn = new PendingReturn(parsedHistory.actionKey(), latestSnapshot, returnVo); |
|
||||||
} else if (pendingReturn != null && parsedHistory.snapshot() != null) { |
|
||||||
pendingReturn.returnVo().setModifiedVerifyContent( |
|
||||||
buildVerifyDiff(pendingReturn.beforeSnapshot(), latestSnapshot)); |
|
||||||
} else if (pendingReturn != null && isResubmitAction(pendingReturn.returnActionKey(), parsedHistory.actionKey())) { |
|
||||||
pendingReturn.returnVo().setModifiedVerifyContent(buildVerifyDiff(pendingReturn.beforeSnapshot(), latestSnapshot)); |
|
||||||
} |
|
||||||
} |
|
||||||
returnCountMap.put(negative.getId(), returnCount); |
|
||||||
} |
|
||||||
return new ExportData(returnCountMap, returnRecords); |
|
||||||
} |
|
||||||
|
|
||||||
private ParsedHistory parseHistory(NegativeHistory history) { |
|
||||||
if (StrUtil.isBlank(history.getDataJson())) { |
|
||||||
return new ParsedHistory(null, null, null); |
|
||||||
} |
|
||||||
try { |
|
||||||
JsonNode root = JSON.readTree(history.getDataJson()); |
|
||||||
String actionKey = textValue(root, "actionKey"); |
|
||||||
JsonNode actionData = root.path("data"); |
|
||||||
String comments = actionData.isObject() ? textValue(actionData, "comments") : null; |
|
||||||
VerifySnapshot snapshot = hasVerifyData(actionData) |
|
||||||
? new VerifySnapshot( |
|
||||||
textValue(actionData, "checkStatusName"), |
|
||||||
textValue(actionData, "isRectifyName"), |
|
||||||
textValue(actionData, "checkStatusDesc"), |
|
||||||
textValue(actionData, "rectifyDesc")) |
|
||||||
: null; |
|
||||||
return new ParsedHistory(actionKey, comments, snapshot); |
|
||||||
} catch (RuntimeException ignored) { |
|
||||||
return new ParsedHistory(null, null, null); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private boolean hasVerifyData(JsonNode actionData) { |
|
||||||
return actionData.isObject() && (actionData.has("checkStatusName") |
|
||||||
|| actionData.has("isRectifyName") |
|
||||||
|| actionData.has("checkStatusDesc") |
|
||||||
|| actionData.has("rectifyDesc")); |
|
||||||
} |
|
||||||
|
|
||||||
private String textValue(JsonNode node, String fieldName) { |
|
||||||
JsonNode value = node.path(fieldName); |
|
||||||
return value.isMissingNode() || value.isNull() ? null : value.asText(); |
|
||||||
} |
|
||||||
|
|
||||||
private boolean isReturnAction(String actionKey) { |
|
||||||
return "second_approve_return".equals(actionKey) || "first_approve_return".equals(actionKey); |
|
||||||
} |
|
||||||
|
|
||||||
private boolean isResubmitAction(String returnActionKey, String actionKey) { |
|
||||||
if ("second_approve_return".equals(returnActionKey)) { |
|
||||||
return "apply_completion".equals(actionKey); |
|
||||||
} |
|
||||||
if ("first_approve_return".equals(returnActionKey)) { |
|
||||||
return "second_approve".equals(actionKey) || "apply_completion".equals(actionKey); |
|
||||||
} |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
private String buildVerifyDiff(VerifySnapshot before, VerifySnapshot after) { |
|
||||||
if (before == null || after == null) { |
|
||||||
return "无法获取核查办理内容"; |
|
||||||
} |
|
||||||
List<String> diffs = new ArrayList<>(); |
|
||||||
addVerifyDiff(diffs, "核查结论", before.checkStatusName(), after.checkStatusName()); |
|
||||||
addVerifyDiff(diffs, "是否整改", before.isRectifyName(), after.isRectifyName()); |
|
||||||
addVerifyDiff(diffs, "问题核查情况", before.checkStatusDesc(), after.checkStatusDesc()); |
|
||||||
addVerifyDiff(diffs, "问题整改情况", before.rectifyDesc(), after.rectifyDesc()); |
|
||||||
return diffs.isEmpty() ? null : String.join("\n", diffs); |
|
||||||
} |
|
||||||
|
|
||||||
private void addVerifyDiff(List<String> diffs, String label, String before, String after) { |
|
||||||
String beforeText = normalizeCellText(before); |
|
||||||
String afterText = normalizeCellText(after); |
|
||||||
if (!Objects.equals(beforeText, afterText)) { |
|
||||||
diffs.add(String.format("%s:%s → %s", label, beforeText, afterText)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
private String normalizeCellText(String text) { |
|
||||||
if (StrUtil.isBlank(text)) { |
|
||||||
return "无"; |
|
||||||
} |
|
||||||
return text.replaceAll("[\\r\\n]+", " ").trim(); |
|
||||||
} |
|
||||||
|
|
||||||
public record ExportData(Map<String, Integer> returnCountMap, |
|
||||||
List<ExportNegativeReturnVo> returnRecords) { |
|
||||||
} |
|
||||||
|
|
||||||
private record ParsedHistory(String actionKey, String comments, VerifySnapshot snapshot) { |
|
||||||
} |
|
||||||
|
|
||||||
private record VerifySnapshot(String checkStatusName, String isRectifyName, |
|
||||||
String checkStatusDesc, String rectifyDesc) { |
|
||||||
} |
|
||||||
|
|
||||||
private record PendingReturn(String returnActionKey, VerifySnapshot beforeSnapshot, |
|
||||||
ExportNegativeReturnVo returnVo) { |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue