package jnpf.limsService.print;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import jnpf.exception.DataException;
|
import jnpf.limsEntity.LimsJianyanXiangEntity;
|
import jnpf.limsEntity.LimsPrintTemplateEntity;
|
import jnpf.limsEntity.LimsQingyandanEntity;
|
import jnpf.limsEntity.LimsWendingxingKaocaJihuaEntity;
|
import jnpf.limsEntity.LimsWendingxingKaocaJihuaZhouqiEntity;
|
import jnpf.limsMapper.LimsJianyanXiangMapper;
|
import jnpf.limsMapper.LimsQingyandanMapper;
|
import jnpf.limsMapper.LimsWendingxingKaocaJihuaMapper;
|
import jnpf.limsMapper.LimsWendingxingKaocaJihuaZhouqiMapper;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.math.BigDecimal;
|
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.stream.Collectors;
|
|
/**
|
* 稳定性考察汇总模板渲染器(template_id = wendingxing_kaoca_huizong)。
|
*/
|
@Component
|
public class WendingxingKaocaHuizongRenderer implements PrintTemplateRenderer {
|
|
public static final String TEMPLATE_ID = "wendingxing_kaoca_huizong";
|
private static final String EMPTY_RESULT = "/";
|
|
@Autowired
|
private LimsWendingxingKaocaJihuaMapper jihuaMapper;
|
|
@Autowired
|
private LimsWendingxingKaocaJihuaZhouqiMapper zhouqiMapper;
|
|
@Autowired
|
private LimsQingyandanMapper qingyandanMapper;
|
|
@Autowired
|
private LimsJianyanXiangMapper jianyanXiangMapper;
|
|
@Autowired
|
private ObjectMapper objectMapper;
|
|
@Override
|
public String getTemplateId() {
|
return TEMPLATE_ID;
|
}
|
|
@Override
|
public Map<String, Object> render(String baogaoId, LimsPrintTemplateEntity tpl) {
|
if (baogaoId == null || baogaoId.trim().isEmpty()) {
|
throw new DataException("缺少稳定性考察计划 id");
|
}
|
|
LimsWendingxingKaocaJihuaEntity jihua = selectJihua(baogaoId);
|
if (jihua == null) {
|
throw new DataException("稳定性考察计划不存在或已删除: " + baogaoId);
|
}
|
|
Map<String, Object> config = parseConfig(tpl);
|
List<LimsWendingxingKaocaJihuaZhouqiEntity> cycles = selectCycles(baogaoId);
|
Map<String, List<LimsQingyandanEntity>> qingyandanByCycle = selectQingyandan(baogaoId, cycles);
|
Map<String, List<LimsJianyanXiangEntity>> itemsByQingyandan = selectItems(qingyandanByCycle);
|
|
LinkedHashMap<String, String> periodLabels = buildPeriodLabels(cycles, config.get("zhouqiDanwei"));
|
Map<String, Object> data = new LinkedHashMap<>();
|
data.put("schemeName", jihua.getKaocaMingcheng());
|
data.put("periods", new ArrayList<>(periodLabels.values()));
|
data.put("reports", buildReports(cycles, periodLabels, qingyandanByCycle, itemsByQingyandan));
|
return data;
|
}
|
|
private LimsWendingxingKaocaJihuaEntity selectJihua(String baogaoId) {
|
QueryWrapper<LimsWendingxingKaocaJihuaEntity> query = new QueryWrapper<>();
|
query.eq("f_id", baogaoId);
|
query.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
return jihuaMapper.selectOne(query);
|
}
|
|
/**
|
*
|
* 根据计划 ID 查询周期列表数据
|
*
|
* @param baogaoId
|
* @return
|
*/
|
private List<LimsWendingxingKaocaJihuaZhouqiEntity> selectCycles(String baogaoId) {
|
QueryWrapper<LimsWendingxingKaocaJihuaZhouqiEntity> query = new QueryWrapper<>();
|
query.eq("kaoca_jihua_id", baogaoId);
|
query.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
query.and(w -> w.isNull("shifou_jixu_zhixing").or().ne("shifou_jixu_zhixing", "no"));
|
query.orderByAsc("jiahua_anpai_riqi", "f_id");
|
return zhouqiMapper.selectList(query);
|
}
|
|
private Map<String, List<LimsQingyandanEntity>> selectQingyandan(
|
String baogaoId, List<LimsWendingxingKaocaJihuaZhouqiEntity> cycles) {
|
if (cycles.isEmpty()) {
|
return Collections.emptyMap();
|
}
|
|
List<String> cycleIds = cycles.stream()
|
.map(LimsWendingxingKaocaJihuaZhouqiEntity::getId)
|
.collect(Collectors.toList());
|
QueryWrapper<LimsQingyandanEntity> query = new QueryWrapper<>();
|
query.eq("wendingxing_jilu_id", baogaoId);
|
query.in("wendingxing_zhouqi_id", cycleIds);
|
query.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
query.orderByAsc("f_id");
|
|
Map<String, List<LimsQingyandanEntity>> result = new HashMap<>();
|
for (LimsQingyandanEntity row : qingyandanMapper.selectList(query)) {
|
result.computeIfAbsent(row.getWendingxingZhouqiId(), key -> new ArrayList<>()).add(row);
|
}
|
return result;
|
}
|
|
private Map<String, List<LimsJianyanXiangEntity>> selectItems(
|
Map<String, List<LimsQingyandanEntity>> qingyandanByCycle) {
|
List<String> qingyandanIds = qingyandanByCycle.values().stream()
|
.flatMap(List::stream)
|
.map(LimsQingyandanEntity::getId)
|
.collect(Collectors.toList());
|
if (qingyandanIds.isEmpty()) {
|
return Collections.emptyMap();
|
}
|
|
QueryWrapper<LimsJianyanXiangEntity> query = new QueryWrapper<>();
|
query.in("qingyandan_id", qingyandanIds);
|
query.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
query.orderByAsc("f_id");
|
|
Map<String, List<LimsJianyanXiangEntity>> result = new HashMap<>();
|
for (LimsJianyanXiangEntity row : jianyanXiangMapper.selectList(query)) {
|
result.computeIfAbsent(row.getQingyandanId(), key -> new ArrayList<>()).add(row);
|
}
|
return result;
|
}
|
|
private LinkedHashMap<String, String> buildPeriodLabels(
|
List<LimsWendingxingKaocaJihuaZhouqiEntity> cycles, Object unitConfig) {
|
LinkedHashMap<String, String> result = new LinkedHashMap<>();
|
for (LimsWendingxingKaocaJihuaZhouqiEntity cycle : cycles) {
|
String key = periodKey(cycle);
|
result.putIfAbsent(key, formatNumber(cycle.getZhouqi())
|
+ resolveUnit(cycle.getZhouqiDanwei(), unitConfig));
|
}
|
return result;
|
}
|
|
private List<Map<String, Object>> buildReports(
|
List<LimsWendingxingKaocaJihuaZhouqiEntity> cycles,
|
LinkedHashMap<String, String> periodLabels,
|
Map<String, List<LimsQingyandanEntity>> qingyandanByCycle,
|
Map<String, List<LimsJianyanXiangEntity>> itemsByQingyandan) {
|
LinkedHashMap<String, List<LimsWendingxingKaocaJihuaZhouqiEntity>> cyclesByBatch =
|
new LinkedHashMap<>();
|
for (LimsWendingxingKaocaJihuaZhouqiEntity cycle : cycles) {
|
cyclesByBatch.computeIfAbsent(valueOrEmpty(cycle.getPihao()), key -> new ArrayList<>())
|
.add(cycle);
|
}
|
|
List<Map<String, Object>> reports = new ArrayList<>();
|
for (Map.Entry<String, List<LimsWendingxingKaocaJihuaZhouqiEntity>> batch
|
: cyclesByBatch.entrySet()) {
|
LinkedHashMap<String, ReportRow> rows = new LinkedHashMap<>();
|
for (LimsWendingxingKaocaJihuaZhouqiEntity cycle : batch.getValue()) {
|
String periodKey = periodKey(cycle);
|
for (LimsQingyandanEntity qingyandan
|
: qingyandanByCycle.getOrDefault(cycle.getId(), Collections.emptyList())) {
|
for (LimsJianyanXiangEntity item
|
: itemsByQingyandan.getOrDefault(qingyandan.getId(), Collections.emptyList())) {
|
String rowKey = valueOrEmpty(item.getJianyanXiangmuMingcheng()) + "\u0000"
|
+ valueOrEmpty(item.getBiaozhunGuiding());
|
String standard = resultOrSlash(item.getBiaozhunGuiding());
|
String value = resultOrSlash(item.getJianyanJieguo());
|
if ("数值".equals(item.getShujuLeixing())) {
|
value += item.getFenjianDanwei();
|
standard += item.getFenjianDanwei();
|
}
|
String finalStandard = standard;
|
ReportRow row = rows.computeIfAbsent(rowKey,
|
key -> new ReportRow(item.getJianyanXiangmuMingcheng(), finalStandard));
|
if (!row.values.containsKey(periodKey)
|
|| EMPTY_RESULT.equals(row.values.get(periodKey))) {
|
row.values.put(periodKey, value);
|
}
|
}
|
}
|
}
|
|
List<Map<String, Object>> reportRows = new ArrayList<>();
|
for (ReportRow source : rows.values()) {
|
Map<String, Object> row = new LinkedHashMap<>();
|
row.put("item", source.item);
|
row.put("standard", source.standard);
|
List<String> values = periodLabels.keySet().stream()
|
.map(key -> source.values.getOrDefault(key, EMPTY_RESULT))
|
.collect(Collectors.toList());
|
row.put("values", values);
|
reportRows.add(row);
|
}
|
|
Map<String, Object> report = new LinkedHashMap<>();
|
report.put("batchNo", batch.getKey());
|
report.put("rows", reportRows);
|
reports.add(report);
|
}
|
return reports;
|
}
|
|
private Map<String, Object> parseConfig(LimsPrintTemplateEntity tpl) {
|
if (tpl == null || tpl.getConfig() == null || tpl.getConfig().trim().isEmpty()) {
|
return Collections.emptyMap();
|
}
|
try {
|
return objectMapper.readValue(tpl.getConfig(), new TypeReference<Map<String, Object>>() { });
|
} catch (Exception e) {
|
throw new DataException("打印模板 config JSON 解析失败: " + e.getMessage());
|
}
|
}
|
|
@SuppressWarnings("unchecked")
|
private String resolveUnit(String code, Object config) {
|
String source = valueOrEmpty(code);
|
if (config instanceof Map) {
|
Object configured = ((Map<String, Object>) config).get(source);
|
return labelOf(configured, source);
|
}
|
if (config instanceof List) {
|
for (Object entry : (List<?>) config) {
|
if (!(entry instanceof Map)) {
|
continue;
|
}
|
Map<String, Object> option = (Map<String, Object>) entry;
|
String value = firstString(option, "value", "id", "code", "enCode");
|
if (source.equals(value)) {
|
return firstNonEmpty(firstString(option, "label", "name", "fullName", "text"), source);
|
}
|
}
|
}
|
return source;
|
}
|
|
@SuppressWarnings("unchecked")
|
private String labelOf(Object configured, String fallback) {
|
if (configured instanceof Map) {
|
return firstNonEmpty(firstString((Map<String, Object>) configured,
|
"label", "name", "fullName", "text", "value"), fallback);
|
}
|
return configured == null ? fallback : configured.toString();
|
}
|
|
private String firstString(Map<String, Object> values, String... keys) {
|
for (String key : keys) {
|
Object value = values.get(key);
|
if (value != null && !value.toString().trim().isEmpty()) {
|
return value.toString();
|
}
|
}
|
return "";
|
}
|
|
private String periodKey(LimsWendingxingKaocaJihuaZhouqiEntity cycle) {
|
return formatNumber(cycle.getZhouqi()) + "\u0000" + valueOrEmpty(cycle.getZhouqiDanwei());
|
}
|
|
private String formatNumber(BigDecimal value) {
|
return value == null ? "" : value.stripTrailingZeros().toPlainString();
|
}
|
|
private String resultOrSlash(String value) {
|
return value == null || value.trim().isEmpty() ? EMPTY_RESULT : value;
|
}
|
|
private String firstNonEmpty(String value, String fallback) {
|
return value == null || value.trim().isEmpty() ? fallback : value;
|
}
|
|
private String valueOrEmpty(String value) {
|
return value == null ? "" : value;
|
}
|
|
private static final class ReportRow {
|
private final String item;
|
private final String standard;
|
private final Map<String, String> values = new HashMap<>();
|
|
private ReportRow(String item, String standard) {
|
this.item = item;
|
this.standard = standard;
|
}
|
}
|
}
|