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.LimsHuanjingJianceBaogaoEntity;
|
import jnpf.limsEntity.LimsHuanjingJianceBaogaoZixiangEntity;
|
import jnpf.limsEntity.LimsHuanjingJianceBiaozhunEntity;
|
import jnpf.limsEntity.LimsHuanjingJianceYijuEntity;
|
import jnpf.limsEntity.LimsHuanjingQuyuEntity;
|
import jnpf.limsEntity.LimsPrintTemplateEntity;
|
import jnpf.limsMapper.LimsHuanjingJianceBaogaoMapper;
|
import jnpf.limsMapper.LimsHuanjingJianceBaogaoZixiangMapper;
|
import jnpf.limsMapper.LimsHuanjingJianceBiaozhunMapper;
|
import jnpf.limsMapper.LimsHuanjingJianceYijuMapper;
|
import jnpf.limsMapper.LimsHuanjingQuyuMapper;
|
import jnpf.permission.UserApi;
|
import jnpf.permission.entity.UserEntity;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Component;
|
|
import java.math.BigDecimal;
|
import java.text.SimpleDateFormat;
|
import java.util.ArrayList;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.stream.Collectors;
|
|
/**
|
* "浮游菌检测报告"模板渲染器(template_id = huanjing_fuyoujun)。
|
*
|
* <p>输入:lims_huanjing_jiance_baogao.f_id;子项来自
|
* lims_huanjing_jiance_baogao_zixiang.f_foreign_id。
|
*/
|
@Component
|
public class HuanjingFuyoujunRenderer implements PrintTemplateRenderer {
|
|
public static final String TEMPLATE_ID = "huanjing_fuyoujun";
|
|
private static final String DEFAULT_COMPANY_NAME = "华道(上海)生物医药有限公司";
|
private static final String DEFAULT_DOC_NUMBER = "SOP-MBC-A010-TO-R01-01";
|
private static final String DEFAULT_REVIEW_CYCLE = "3年";
|
private static final String DEFAULT_METHOD_TEXT = "SOP-MBC-A010-TO 《浮游菌检测标准操作规程》";
|
|
@Autowired
|
private LimsHuanjingJianceBaogaoMapper baogaoMapper;
|
|
@Autowired
|
private LimsHuanjingJianceBaogaoZixiangMapper zixiangMapper;
|
|
@Autowired
|
private LimsHuanjingJianceBiaozhunMapper biaozhunMapper;
|
|
@Autowired
|
private LimsHuanjingJianceYijuMapper yijuMapper;
|
|
@Autowired
|
private LimsHuanjingQuyuMapper quyuMapper;
|
|
@Autowired
|
private UserApi usersApi;
|
|
@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.isEmpty()) {
|
throw new DataException("缺少环境监测报告 id");
|
}
|
|
Map<String, Object> baogao = getBaogaoMap(baogaoId);
|
if (baogao.isEmpty()) {
|
throw new DataException("环境监测报告不存在或已删除: " + baogaoId);
|
}
|
|
Map<String, Object> cfg = parseConfig(tpl);
|
List<Map<String, Object>> items = buildItems(baogaoId);
|
Map<String, String> userNames = fetchUserNames(baogao);
|
|
Map<String, Object> data = new LinkedHashMap<>();
|
data.put("template_id", tpl.getTemplateId());
|
data.put("template_name", tpl.getTemplateName());
|
data.put("companyName", asString(cfg.get("company_name"), DEFAULT_COMPANY_NAME));
|
data.put("docNumber", asString(cfg.get("doc_number"), DEFAULT_DOC_NUMBER));
|
data.put("reviewCycle", asString(cfg.get("review_cycle"), DEFAULT_REVIEW_CYCLE));
|
data.put("distributionDepartment", asString(cfg.get("distribution_department")));
|
data.put("effectiveDate", formatDate(getAny(baogao, "fuhe_riqi")));
|
data.put("methodText", resolveMethodText(baogao, cfg));
|
data.put("header", buildHeader(baogao));
|
data.put("items", items);
|
data.put("standardRows", buildStandardRows(cfg));
|
data.put("jielun", normalizeConclusion(asString(getAny(baogao, "jielun"))));
|
data.put("signatures", buildSignatures(baogao, userNames));
|
data.put("beizhu", asString(getAny(baogao, "beizhu"), asString(cfg.get("beizhu"))));
|
return data;
|
}
|
|
private Map<String, Object> getBaogaoMap(String baogaoId) {
|
QueryWrapper<LimsHuanjingJianceBaogaoEntity> wrapper = new QueryWrapper<>();
|
wrapper.eq("f_id", baogaoId);
|
wrapper.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
List<Map<String, Object>> rows = baogaoMapper.selectMaps(wrapper);
|
return rows.isEmpty() ? Collections.emptyMap() : new LinkedHashMap<>(rows.get(0));
|
}
|
|
private List<Map<String, Object>> buildItems(String baogaoId) {
|
QueryWrapper<LimsHuanjingJianceBaogaoZixiangEntity> wrapper = new QueryWrapper<>();
|
wrapper.eq("f_foreign_id", baogaoId);
|
wrapper.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
wrapper.orderByAsc("weizhi_bianhao", "quyangdian_mingcheng", "f_id");
|
|
List<Map<String, Object>> items = new ArrayList<>();
|
for (Map<String, Object> row : zixiangMapper.selectMaps(wrapper)) {
|
Map<String, Object> item = new LinkedHashMap<>();
|
item.put("weizhi_bianhao", asString(getAny(row, "weizhi_bianhao")));
|
item.put("weizhi_mingcheng", asString(getAny(row, "weizhi_mingcheng")));
|
item.put("quyangdian_mingcheng", asString(getAny(row, "quyangdian_mingcheng")));
|
item.put("ceshi_jieguo", asString(getAny(row, "ceshi_jieguo")));
|
item.put("shifou_hege", normalizeYesNo(asString(getAny(row, "shifou_hege"))));
|
items.add(item);
|
}
|
return items;
|
}
|
|
private Map<String, Object> buildHeader(Map<String, Object> row) {
|
Map<String, Object> h = new LinkedHashMap<>();
|
String quyuId = asString(getAny(row, "jiance_quyu"));
|
h.put("jiance_quyu", quyuId);
|
h.put("jiance_quyu_name", resolveQuyuName(quyuId));
|
h.put("jiance_riqi", formatDate(getAny(row, "jiance_riqi")));
|
h.put("jiance_zhuangtai", asString(getAny(row, "jiance_zhuangtai")));
|
h.put("qizhi_shijian", asString(getAny(row, "qizhi_shijian")));
|
h.put("quyangliang", asString(getAny(row, "quyangliang")));
|
h.put("peiyangji_pihao", asString(getAny(row, "peiyangji_pihao")));
|
h.put("peiyangji_youxiaoqi", formatDate(getAny(row, "peiyangji_youxiaoqi")));
|
h.put("caiyangyi_bianhao", asString(getAny(row, "caiyangyi_bianhao")));
|
h.put("caiyangyi_jiaozhun_youxiaoqi", formatDate(getAny(row, "caiyangyi_jiaozhun_youxiaoqi")));
|
h.put("peiyang_shebei_biaohao", asString(getAny(row, "peiyang_shebei_biaohao")));
|
h.put("jiaozhun_youxiaoqi", formatDate(getAny(row, "jiaozhun_youxiaoqi")));
|
h.put("peiyang_kaishi_shijian", formatDate(getAny(row, "peiyang_kaishi_shijian")));
|
h.put("peiyang_jieshu_shijian", formatDate(getAny(row, "peiyang_jieshu_shijian")));
|
h.put("jiejing_jibie", formatLevel(asString(getAny(row, "jiejing_jibie"))));
|
h.put("biaozhun_guiding", asString(getAny(row, "biaozhun_guiding")));
|
h.put("moren_danwei", asString(getAny(row, "moren_danwei")));
|
h.put("beizhu", asString(getAny(row, "beizhu")));
|
return h;
|
}
|
|
private String resolveMethodText(Map<String, Object> baogao, Map<String, Object> cfg) {
|
String biaozhunIdOrCode = asString(getAny(baogao, "biaozhun_guiding"));
|
Map<String, Object> biaozhun = findBiaozhun(biaozhunIdOrCode);
|
if (biaozhun.isEmpty()) {
|
return asString(cfg.get("method_text"), DEFAULT_METHOD_TEXT);
|
}
|
|
String biaozhunGuiding = asString(getAny(biaozhun, "biaozhun_guiding"));
|
String yijuIdOrText = asString(getAny(biaozhun, "jiance_yiju"));
|
String jianceYiju = findJianceYiju(yijuIdOrText);
|
|
if (!biaozhunGuiding.isEmpty() && !jianceYiju.isEmpty()) {
|
return biaozhunGuiding + " " + jianceYiju;
|
}
|
if (!biaozhunGuiding.isEmpty()) {
|
return biaozhunGuiding;
|
}
|
if (!jianceYiju.isEmpty()) {
|
return jianceYiju;
|
}
|
return asString(cfg.get("method_text"), DEFAULT_METHOD_TEXT);
|
}
|
|
private Map<String, Object> findBiaozhun(String biaozhunIdOrCode) {
|
if (biaozhunIdOrCode == null || biaozhunIdOrCode.isEmpty()) {
|
return Collections.emptyMap();
|
}
|
|
QueryWrapper<LimsHuanjingJianceBiaozhunEntity> byGuiding = new QueryWrapper<>();
|
byGuiding.eq("biaozhun_guiding", biaozhunIdOrCode);
|
byGuiding.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
List<Map<String, Object>> rows = biaozhunMapper.selectMaps(byGuiding);
|
if (!rows.isEmpty()) {
|
return new LinkedHashMap<>(rows.get(0));
|
}
|
|
QueryWrapper<LimsHuanjingJianceBiaozhunEntity> byId = new QueryWrapper<>();
|
byId.eq("f_id", biaozhunIdOrCode);
|
byId.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
rows = biaozhunMapper.selectMaps(byId);
|
return rows.isEmpty() ? Collections.emptyMap() : new LinkedHashMap<>(rows.get(0));
|
}
|
|
private String findJianceYiju(String yijuIdOrText) {
|
if (yijuIdOrText == null || yijuIdOrText.isEmpty()) {
|
return "";
|
}
|
|
QueryWrapper<LimsHuanjingJianceYijuEntity> byId = new QueryWrapper<>();
|
byId.eq("f_id", yijuIdOrText);
|
byId.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
List<LimsHuanjingJianceYijuEntity> rows = yijuMapper.selectList(byId);
|
if (!rows.isEmpty() && rows.get(0).getJianceYiju() != null) {
|
return rows.get(0).getJianceYiju();
|
}
|
|
QueryWrapper<LimsHuanjingJianceYijuEntity> byText = new QueryWrapper<>();
|
byText.eq("jiance_yiju", yijuIdOrText);
|
byText.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
rows = yijuMapper.selectList(byText);
|
if (rows.isEmpty() || rows.get(0).getJianceYiju() == null) {
|
return yijuIdOrText;
|
}
|
return rows.get(0).getJianceYiju();
|
}
|
|
private String resolveQuyuName(String quyuId) {
|
if (quyuId == null || quyuId.isEmpty()) {
|
return "";
|
}
|
QueryWrapper<LimsHuanjingQuyuEntity> wrapper = new QueryWrapper<>();
|
wrapper.eq("f_id", quyuId);
|
wrapper.and(w -> w.isNull("f_delete_mark").or().ne("f_delete_mark", 1));
|
List<LimsHuanjingQuyuEntity> list = quyuMapper.selectList(wrapper);
|
if (list.isEmpty() || list.get(0).getJianceQuyu() == null) {
|
return quyuId;
|
}
|
return list.get(0).getJianceQuyu();
|
}
|
|
@SuppressWarnings("unchecked")
|
private List<Map<String, Object>> buildStandardRows(Map<String, Object> cfg) {
|
Object rows = cfg.get("standard_rows");
|
if (rows instanceof List) {
|
return (List<Map<String, Object>>) rows;
|
}
|
|
List<Map<String, Object>> result = new ArrayList<>();
|
result.add(standardRow("A", "<1", "<1"));
|
result.add(standardRow("B", "5", "10"));
|
result.add(standardRow("C", "50", "100"));
|
result.add(standardRow("D", "100", "200"));
|
return result;
|
}
|
|
private Map<String, Object> standardRow(String level, String staticLimit, String dynamicLimit) {
|
Map<String, Object> row = new LinkedHashMap<>();
|
row.put("level", level);
|
row.put("static_limit", staticLimit);
|
row.put("dynamic_limit", dynamicLimit);
|
return row;
|
}
|
|
private Map<String, Object> buildSignatures(Map<String, Object> row, Map<String, String> userNames) {
|
Map<String, Object> sig = new LinkedHashMap<>();
|
sig.put("operator", makeSignature(
|
asString(getAny(row, "jiance_ren")),
|
formatDate(getAny(row, "jiance_riqi")),
|
userNames));
|
sig.put("recorder", makeSignature(
|
asString(getAny(row, "jiance_ren")),
|
formatDate(getAny(row, "jiance_riqi")),
|
userNames));
|
sig.put("reviewer", makeSignature(
|
asString(getAny(row, "fuhe_ren")),
|
formatDate(getAny(row, "fuhe_riqi")),
|
userNames));
|
return sig;
|
}
|
|
private Map<String, Object> makeSignature(String userId, String date, Map<String, String> userNames) {
|
Map<String, Object> m = new LinkedHashMap<>();
|
m.put("user_id", userId);
|
m.put("name", userId == null ? "" : asString(userNames.get(userId)));
|
m.put("date", date);
|
return m;
|
}
|
|
private Map<String, String> fetchUserNames(Map<String, Object> row) {
|
List<String> userIds = Arrays.asList(
|
asString(getAny(row, "jiance_ren")),
|
asString(getAny(row, "quyang_ren")),
|
asString(getAny(row, "fuhe_ren")))
|
.stream()
|
.filter(s -> s != null && !s.isEmpty())
|
.distinct()
|
.collect(Collectors.toList());
|
if (userIds.isEmpty()) {
|
return Collections.emptyMap();
|
}
|
|
Map<String, String> idToRealName = new HashMap<>();
|
List<UserEntity> users = usersApi.getUserName(userIds);
|
if (users != null) {
|
for (UserEntity u : users) {
|
if (u != null && u.getId() != null) {
|
idToRealName.put(u.getId(), u.getRealName());
|
}
|
}
|
}
|
return idToRealName;
|
}
|
|
private Map<String, Object> parseConfig(LimsPrintTemplateEntity tpl) {
|
String json = tpl.getConfig();
|
if (json == null || json.isEmpty()) {
|
return Collections.emptyMap();
|
}
|
try {
|
return objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});
|
} catch (Exception e) {
|
throw new DataException("打印模板 config JSON 解析失败: " + e.getMessage());
|
}
|
}
|
|
private static Object getAny(Map<String, Object> row, String key) {
|
if (row == null || row.isEmpty()) {
|
return null;
|
}
|
if (row.containsKey(key)) {
|
return row.get(key);
|
}
|
String lowerKey = normalizeKey(key);
|
for (Map.Entry<String, Object> e : row.entrySet()) {
|
if (e.getKey() != null && normalizeKey(e.getKey()).equals(lowerKey)) {
|
return e.getValue();
|
}
|
}
|
return null;
|
}
|
|
private static String normalizeKey(String key) {
|
return key == null ? "" : key.replace("_", "").toLowerCase();
|
}
|
|
private static String formatDate(Object value) {
|
return format(value, "yyyy-MM-dd");
|
}
|
|
private static String formatDateTime(Object value) {
|
return format(value, "yyyy-MM-dd");
|
}
|
|
private static String format(Object value, String pattern) {
|
if (value == null) {
|
return "";
|
}
|
if (value instanceof Date) {
|
return new SimpleDateFormat(pattern).format((Date) value);
|
}
|
String text = value.toString();
|
if ("yyyy-MM-dd".equals(pattern) && text.matches("^\\d{4}-\\d{2}-\\d{2}.*")) {
|
return text.substring(0, 10);
|
}
|
return text;
|
}
|
|
private static String formatLevel(String level) {
|
if (level == null || level.isEmpty()) {
|
return "";
|
}
|
String lower = level.toLowerCase();
|
if (Arrays.asList("a", "b", "c", "d").contains(lower)) {
|
return lower.toUpperCase() + "级";
|
}
|
return level;
|
}
|
|
private static String normalizeConclusion(String value) {
|
if ("compliant".equalsIgnoreCase(value)
|
|| "qualified".equalsIgnoreCase(value)
|
|| "fuheguiding".equalsIgnoreCase(value)
|
|| "yes".equalsIgnoreCase(value)
|
|| "合格".equals(value)
|
|| "符合规定".equals(value)) {
|
return "yes";
|
}
|
if ("non_compliant".equalsIgnoreCase(value)
|
|| "uncompliant".equalsIgnoreCase(value)
|
|| "unqualified".equalsIgnoreCase(value)
|
|| "bufuheguiding".equalsIgnoreCase(value)
|
|| "no".equalsIgnoreCase(value)
|
|| "不合格".equals(value)
|
|| "不符合规定".equals(value)) {
|
return "no";
|
}
|
return value;
|
}
|
|
private static String normalizeYesNo(String value) {
|
if ("yes".equalsIgnoreCase(value)
|
|| "true".equalsIgnoreCase(value)
|
|| "1".equals(value)
|
|| "是".equals(value)
|
|| "合格".equals(value)) {
|
return "yes";
|
}
|
if ("no".equalsIgnoreCase(value)
|
|| "false".equalsIgnoreCase(value)
|
|| "0".equals(value)
|
|| "否".equals(value)
|
|| "不合格".equals(value)) {
|
return "no";
|
}
|
return value;
|
}
|
|
private static String asString(Object v) {
|
if (v instanceof BigDecimal) {
|
return ((BigDecimal) v).stripTrailingZeros().toPlainString();
|
}
|
return v == null ? "" : v.toString();
|
}
|
|
private static String asString(Object v, String fallback) {
|
String s = asString(v);
|
return s.isEmpty() ? fallback : s;
|
}
|
}
|