Browse Source

Trial prepare

master
han\hanst 14 hours ago
parent
commit
31f435f239
  1. 165
      src/main/java/com/xujie/sys/modules/sampletracking/service/impl/SampleProofTrackingServiceImpl.java

165
src/main/java/com/xujie/sys/modules/sampletracking/service/impl/SampleProofTrackingServiceImpl.java

@ -60,8 +60,11 @@ import java.util.Objects;
import java.util.Set;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.DefaultIndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFFont;
/**
* 产品打样记录跟踪 Service 实现
@ -157,6 +160,8 @@ public class SampleProofTrackingServiceImpl implements SampleProofTrackingServic
buProcessConfigMap,
exportHeaderRowCount
);
Map<Long, ExportCellAppearance> cellAppearances = collectExportCellAppearances(
exportRows, trackingColumns, bodyRows, completedProcessCellKeySet, exportHeaderRowCount);
try {
String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
String fileName = URLEncoder.encode("项目打样跟踪_" + timestamp, StandardCharsets.UTF_8.name())
@ -193,9 +198,8 @@ public class SampleProofTrackingServiceImpl implements SampleProofTrackingServic
.autoCloseStream(false)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.registerWriteHandler(noHeaderBackgroundStyle);
if (!completedProcessCellKeySet.isEmpty()) {
// 已完成工序单元格灰底高亮导出视觉与前端表格完成态保持一致
writerBuilder.registerWriteHandler(new CompletedProcessCellStyleHandler(completedProcessCellKeySet));
if (!cellAppearances.isEmpty()) {
writerBuilder.registerWriteHandler(new ProofTrackingCellStyleHandler(cellAppearances));
}
writerBuilder
.head(headerRows)
@ -398,6 +402,67 @@ public class SampleProofTrackingServiceImpl implements SampleProofTrackingServic
return rows;
}
private Map<Long, ExportCellAppearance> collectExportCellAppearances(
List<ProofTrackingData> exportRows,
List<ProofTrackingExportColumnData> trackingColumns,
List<List<String>> bodyRows,
Set<Long> completedProcessCellKeySet,
int headerRowCount) {
Map<Long, ExportCellAppearance> appearances = new HashMap<>();
for (Long cellKey : completedProcessCellKeySet) {
appearances.put(cellKey, ExportCellAppearance.COMPLETED_PROCESS);
}
for (int rowIndex = 0; rowIndex < exportRows.size(); rowIndex++) {
ProofTrackingData row = exportRows.get(rowIndex);
if (row == null) {
continue;
}
for (int columnIndex = 0; columnIndex < trackingColumns.size(); columnIndex++) {
String columnProp = trackingColumns.get(columnIndex).getColumnProp();
String displayValue = bodyRows.get(rowIndex).get(columnIndex);
ExportCellAppearance appearance = resolveExportCellAppearance(row, columnProp, displayValue);
if (appearance != null) {
appearances.put(buildExportCellCoordinateKey(headerRowCount + rowIndex, columnIndex), appearance);
}
}
}
return appearances;
}
private ExportCellAppearance resolveExportCellAppearance(ProofTrackingData row,
String columnProp,
String displayValue) {
// projectProofTracking.vue 的链接状态和预警样式保持一致不给未同步的编码着色
switch (columnProp) {
case "projectNo":
return !isBlank(displayValue) && isNpiAlignedId(row.getProjectId())
? ExportCellAppearance.NPI_LINK : null;
case "testPartNo":
return !isBlank(displayValue) && isNpiAlignedId(row.getProjectPartId())
? ExportCellAppearance.NPI_LINK : null;
case "proofingStatus":
return TRACKING_PROOFING_STATUS_FINISHED.equals(row.getProofingStatus())
? ExportCellAppearance.PROOF_FINISHED : ExportCellAppearance.PROOF_IN_PROGRESS;
case "trackingStatus":
// 复用已生成的导出文案避免颜色与日期回退完成态优先级的判断不一致
if ("Complete".equals(displayValue)) {
return ExportCellAppearance.TRACKING_COMPLETE;
}
if ("Trial prepare".equals(displayValue) || (displayValue != null && displayValue.startsWith("Delay-"))) {
return ExportCellAppearance.TRACKING_DELAY;
}
if (displayValue != null && displayValue.startsWith("On schedule-")) {
return ExportCellAppearance.TRACKING_ON_SCHEDULE;
}
return ExportCellAppearance.TRACKING_UNKNOWN;
case "deliveryVariance":
return row.getDeliveryVariance() != null && row.getDeliveryVariance() < -7
? ExportCellAppearance.DELIVERY_ALERT : null;
default:
return null;
}
}
private static long buildExportCellCoordinateKey(int rowIndex, int columnIndex) {
return (((long) rowIndex) << 32) | (columnIndex & 0xffffffffL);
}
@ -457,11 +522,15 @@ public class SampleProofTrackingServiceImpl implements SampleProofTrackingServic
if (rowData == null) {
return "";
}
String packageDate = resolveTrackingPackageDateForExport(rowData);
// 与页面一致打样单号为空且 Delivery&Package 有值时才显示准备阶段
if (isBlank(rowData.getProofingNo()) && !isBlank(packageDate)) {
return "Trial prepare";
}
// 业务口径打样状态为打样完成Tracking Status 固定展示 Complete不再展示 Delay/On schedule
if (isTrackingProofingCompleted(rowData.getProofingStatus())) {
return "Complete";
}
String packageDate = resolveTrackingPackageDateForExport(rowData);
String baseline = toDateString(rowData.getBaseline());
if (isBlank(packageDate) || isBlank(baseline)) {
return "";
@ -2987,17 +3056,42 @@ public class SampleProofTrackingServiceImpl implements SampleProofTrackingServic
data.setProofingStatusList(normalizedStatusList.isEmpty() ? null : normalizedStatusList);
}
private static class CompletedProcessCellStyleHandler implements CellWriteHandler {
/** 页面使用的 RGB 色值;不使用近似的 Excel 索引色。 */
private enum ExportCellAppearance {
NPI_LINK(null, "0C4DBB", false),
PROOF_FINISHED(null, "67C23A", false),
PROOF_IN_PROGRESS(null, "046E97", false),
TRACKING_ON_SCHEDULE("E8F5E9", "303133", false),
TRACKING_DELAY("FDE2E2", "303133", false),
TRACKING_UNKNOWN("F4F4F5", "303133", false),
TRACKING_COMPLETE("F4F4F5", "909399", false),
DELIVERY_ALERT(null, "F56C6C", true),
COMPLETED_PROCESS("ECECEC", "8C8C8C", false);
private final String background;
private final String foreground;
private final boolean bold;
ExportCellAppearance(String background, String foreground, boolean bold) {
this.background = background;
this.foreground = foreground;
this.bold = bold;
}
}
private static class ProofTrackingCellStyleHandler implements CellWriteHandler {
private final Set<Long> completedCellKeySet;
private final Map<Integer, CellStyle> completedStyleCache = new HashMap<>();
private final Map<Long, ExportCellAppearance> cellAppearances;
private final Map<String, CellStyle> styleCache = new HashMap<>();
private final Map<String, XSSFFont> fontCache = new HashMap<>();
private CompletedProcessCellStyleHandler(Set<Long> completedCellKeySet) {
this.completedCellKeySet = completedCellKeySet == null ? new LinkedHashSet<>() : completedCellKeySet;
private ProofTrackingCellStyleHandler(Map<Long, ExportCellAppearance> cellAppearances) {
this.cellAppearances = cellAppearances;
}
@Override
public int order() {
// 晚于默认样式策略执行避免灰底被后续样式覆盖
// 晚于默认样式策略执行避免颜色被后续样式覆盖
return Integer.MAX_VALUE;
}
@ -3009,28 +3103,49 @@ public class SampleProofTrackingServiceImpl implements SampleProofTrackingServic
Head head,
Integer relativeRowIndex,
Boolean isHead) {
if (cell == null || Boolean.TRUE.equals(isHead) || completedCellKeySet.isEmpty()) {
if (cell == null || Boolean.TRUE.equals(isHead)) {
return;
}
long cellKey = buildExportCellCoordinateKey(cell.getRowIndex(), cell.getColumnIndex());
if (!completedCellKeySet.contains(cellKey)) {
ExportCellAppearance appearance = cellAppearances.get(
buildExportCellCoordinateKey(cell.getRowIndex(), cell.getColumnIndex()));
if (appearance == null) {
return;
}
CellStyle sourceStyle = cell.getCellStyle();
Workbook workbook = cell.getSheet().getWorkbook();
int sourceStyleKey = sourceStyle == null ? -1 : sourceStyle.getIndex();
CellStyle completedStyle = completedStyleCache.get(sourceStyleKey);
if (completedStyle == null) {
completedStyle = workbook.createCellStyle();
if (sourceStyle != null) {
completedStyle.cloneStyleFrom(sourceStyle);
String styleKey = sourceStyle.getIndex() + ":" + appearance.name();
CellStyle styledCell = styleCache.get(styleKey);
if (styledCell == null) {
// 导出固定为 xlsx流式 SXSSF 工作簿也使用 XSSF 样式和字体
XSSFCellStyle style = (XSSFCellStyle) workbook.createCellStyle();
style.cloneStyleFrom(sourceStyle);
if (appearance.background != null) {
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(toExcelColor(appearance.background));
}
completedStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
completedStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
completedStyle.setFillBackgroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
completedStyleCache.put(sourceStyleKey, completedStyle);
String fontKey = sourceStyle.getFontIndex() + ":" + appearance.foreground + ":" + appearance.bold;
XSSFFont font = fontCache.get(fontKey);
if (font == null) {
XSSFFont sourceFont = (XSSFFont) workbook.getFontAt(sourceStyle.getFontIndex());
font = (XSSFFont) workbook.createFont();
font.getCTFont().set(sourceFont.getCTFont());
font.setColor(toExcelColor(appearance.foreground));
if (appearance.bold) {
font.setBold(true);
}
fontCache.put(fontKey, font);
}
style.setFont(font);
styledCell = style;
styleCache.put(styleKey, styledCell);
}
cell.setCellStyle(completedStyle);
cell.setCellStyle(styledCell);
}
private static XSSFColor toExcelColor(String rgb) {
int color = Integer.parseInt(rgb, 16);
return new XSSFColor(new byte[]{(byte) (color >> 16), (byte) (color >> 8), (byte) color},
new DefaultIndexedColorMap());
}
}

Loading…
Cancel
Save