ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceDonatebaseinfoController.java
@@ -262,18 +262,16 @@ //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会导致生成的 doc 内容不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); @@ -292,44 +290,56 @@ throw new ServiceException("下载失败,用户信息出错", HttpStatus.NO_CONTENT); } // 以下字段在数据库中均可为空,统一取空串兜底,避免拼装模板时抛空指针异常 String diseasetype = serviceDonatebaseinfo.getDiseasetype() == null ? "" : serviceDonatebaseinfo.getDiseasetype(); String infectious = serviceDonatebaseinfo.getInfectious() == null ? "" : serviceDonatebaseinfo.getInfectious(); String infosources = serviceDonatebaseinfo.getInfosources() == null ? "" : serviceDonatebaseinfo.getInfosources(); String selfwill = serviceDonatebaseinfo.getSelfwill() == null ? "" : serviceDonatebaseinfo.getSelfwill(); String othercases = serviceDonatebaseinfo.getOthercases() == null ? "" : serviceDonatebaseinfo.getOthercases(); String kinship = serviceDonatebaseinfo.getKinship() == null ? "" : serviceDonatebaseinfo.getKinship(); String patientstate = serviceDonatebaseinfo.getPatientstate() == null ? "" : serviceDonatebaseinfo.getPatientstate(); dataMap.put("JXBH", serviceDonatebaseinfo.getDonorno() == null ? "" : serviceDonatebaseinfo.getDonorno()); dataMap.put("SZYLJG", serviceDonatebaseinfo.getTreatmenthospitalname() == null ? "" : serviceDonatebaseinfo.getTreatmenthospitalname()); dataMap.put("KS", serviceDonatebaseinfo.getTreatmentdeptname() == null ? "" : serviceDonatebaseinfo.getTreatmentdeptname()); dataMap.put("XM", serviceDonatebaseinfo.getName() == null ? "" : serviceDonatebaseinfo.getName()); if (serviceDonatebaseinfo.getSex().equals("0")) { if ("0".equals(serviceDonatebaseinfo.getSex())) { dataMap.put("XB", "未知的性别"); } else if (serviceDonatebaseinfo.getSex().equals("1")) { } else if ("1".equals(serviceDonatebaseinfo.getSex())) { dataMap.put("XB", "男"); } else if (serviceDonatebaseinfo.getSex().equals("2")) { } else if ("2".equals(serviceDonatebaseinfo.getSex())) { dataMap.put("XB", "女"); } Date dt = serviceDonatebaseinfo.getBirthday(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String date = formatter.format(dt); String time = date.substring(0, 10); dataMap.put("CSRQ", serviceDonatebaseinfo.getBirthday() == null ? "" : time); String csrq = ""; if (serviceDonatebaseinfo.getBirthday() != null) { csrq = formatter.format(serviceDonatebaseinfo.getBirthday()).substring(0, 10); } dataMap.put("CSRQ", csrq); dataMap.put("GJ", serviceDonatebaseinfo.getNationality() == null ? "" : serviceDonatebaseinfo.getNationality()); if (serviceDonatebaseinfo.getIdcardtype() == 1) { // idcardtype 为包装类型 Long,数据库中可为 NULL;先取值再判断,避免自动拆箱抛空指针 Long idcardtype = serviceDonatebaseinfo.getIdcardtype(); if (idcardtype != null && idcardtype == 1) { dataMap.put("ZJLX", "身份证"); } else if (serviceDonatebaseinfo.getIdcardtype() == 2) { } else if (idcardtype != null && idcardtype == 2) { dataMap.put("ZJLX", "军人证"); } else if (serviceDonatebaseinfo.getIdcardtype() == 3) { } else if (idcardtype != null && idcardtype == 3) { dataMap.put("ZJLX", "护照"); } else if (serviceDonatebaseinfo.getIdcardtype() == 4) { } else if (idcardtype != null && idcardtype == 4) { dataMap.put("ZJLX", "户口本"); } else if (serviceDonatebaseinfo.getIdcardtype() == 5) { } else if (idcardtype != null && idcardtype == 5) { dataMap.put("ZJLX", "外国人永久居住证"); } else if (serviceDonatebaseinfo.getIdcardtype() == 6) { } else if (idcardtype != null && idcardtype == 6) { dataMap.put("ZJLX", "武警证"); } else if (serviceDonatebaseinfo.getIdcardtype() == 10) { } else if (idcardtype != null && idcardtype == 10) { dataMap.put("ZJLX", "学生证"); } else if (serviceDonatebaseinfo.getIdcardtype() == 11) { } else if (idcardtype != null && idcardtype == 11) { dataMap.put("ZJLX", "士兵证"); } else if (serviceDonatebaseinfo.getIdcardtype() == 16) { } else if (idcardtype != null && idcardtype == 16) { dataMap.put("ZJLX", "港澳居民来往内地通行证"); } else if (serviceDonatebaseinfo.getIdcardtype() == 17) { } else if (idcardtype != null && idcardtype == 17) { dataMap.put("ZJLX", "台湾居民来往大陆通行证"); } else if (serviceDonatebaseinfo.getIdcardtype() == 18) { } else if (idcardtype != null && idcardtype == 18) { dataMap.put("ZJLX", "其他证件类型"); } dataMap.put("ZJHM", serviceDonatebaseinfo.getIdcardno() == null ? "" : serviceDonatebaseinfo.getIdcardno()); @@ -346,28 +356,28 @@ dataMap.put("ZYH", serviceDonatebaseinfo.getInpatientno() == null ? "" : serviceDonatebaseinfo.getInpatientno()); if (serviceDonatebaseinfo.getBloodtype().equals("1")) { if ("1".equals(serviceDonatebaseinfo.getBloodtype())) { dataMap.put("XXA", (char) 8730); dataMap.put("XXB", "□"); dataMap.put("XXO", "□"); dataMap.put("XXAB", "□"); } else if (serviceDonatebaseinfo.getBloodtype().equals("2")) { } else if ("2".equals(serviceDonatebaseinfo.getBloodtype())) { dataMap.put("XXA", "□"); dataMap.put("XXB", (char) 8730); dataMap.put("XXO", "□"); dataMap.put("XXAB", "□"); } else if (serviceDonatebaseinfo.getBloodtype().equals("3")) { } else if ("3".equals(serviceDonatebaseinfo.getBloodtype())) { dataMap.put("XXA", "□"); dataMap.put("XXB", "□"); dataMap.put("XXO", (char) 8730); dataMap.put("XXAB", "□"); } else if (serviceDonatebaseinfo.getBloodtype().equals("4")) { } else if ("4".equals(serviceDonatebaseinfo.getBloodtype())) { dataMap.put("XXA", "□"); dataMap.put("XXB", "□"); dataMap.put("XXO", "□"); dataMap.put("XXAB", (char) 8730); } if (serviceDonatebaseinfo.getRhyin().equals("1")) { if ("1".equals(serviceDonatebaseinfo.getRhyin())) { dataMap.put("YX", (char) 8730); } else { dataMap.put("YX", "□"); @@ -376,22 +386,22 @@ dataMap.put("JBZD", serviceDonatebaseinfo.getDiagnosisname() == null ? "" : serviceDonatebaseinfo.getDiagnosisname()); //疾病类型 if (serviceDonatebaseinfo.getDiseasetype().contains("0")) { if (diseasetype.contains("0")) { dataMap.put("NXGYW", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("1")) { if (diseasetype.contains("1")) { dataMap.put("NWS", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("2")) { if (diseasetype.contains("2")) { dataMap.put("QXQY", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("3")) { if (diseasetype.contains("3")) { dataMap.put("NZL", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); } } else { dataMap.put("NZL", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); @@ -399,16 +409,16 @@ } } else { dataMap.put("QXQY", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("3")) { if (diseasetype.contains("3")) { dataMap.put("NZL", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); } } else { dataMap.put("NZL", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); @@ -417,18 +427,18 @@ } } else { dataMap.put("NWS", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("2")) { if (diseasetype.contains("2")) { dataMap.put("QXQY", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("3")) { if (diseasetype.contains("3")) { dataMap.put("NZL", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); } } else { dataMap.put("NZL", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); @@ -436,16 +446,16 @@ } } else { dataMap.put("QXQY", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("3")) { if (diseasetype.contains("3")) { dataMap.put("NZL", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); } } else { dataMap.put("NZL", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); @@ -455,20 +465,20 @@ } } else { dataMap.put("NXGYW", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("1")) { if (diseasetype.contains("1")) { dataMap.put("NWS", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("2")) { if (diseasetype.contains("2")) { dataMap.put("QXQY", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("3")) { if (diseasetype.contains("3")) { dataMap.put("NZL", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); } } else { dataMap.put("NZL", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); @@ -476,16 +486,16 @@ } } else { dataMap.put("QXQY", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("3")) { if (diseasetype.contains("3")) { dataMap.put("NZL", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); } } else { dataMap.put("NZL", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); @@ -494,18 +504,18 @@ } } else { dataMap.put("NWS", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("2")) { if (diseasetype.contains("2")) { dataMap.put("QXQY", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("3")) { if (diseasetype.contains("3")) { dataMap.put("NZL", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); } } else { dataMap.put("NZL", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); @@ -513,16 +523,16 @@ } } else { dataMap.put("QXQY", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("3")) { if (diseasetype.contains("3")) { dataMap.put("NZL", (char) 8730); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); } } else { dataMap.put("NZL", "□"); if (serviceDonatebaseinfo.getDiseasetype().contains("4")) { if (diseasetype.contains("4")) { dataMap.put("XXGJB", (char) 8730); } else { dataMap.put("XXGJB", "□"); @@ -536,20 +546,20 @@ //传染病情况 if (serviceDonatebaseinfo.getInfectious().contains("1")) { if (infectious.contains("1")) { dataMap.put("YG", (char) 8730); if (serviceDonatebaseinfo.getInfectious().contains("2")) { if (infectious.contains("2")) { dataMap.put("BG", (char) 8730); if (serviceDonatebaseinfo.getInfectious().contains("3")) { if (infectious.contains("3")) { dataMap.put("MD", (char) 8730); if (serviceDonatebaseinfo.getInfectious().contains("4")) { if (infectious.contains("4")) { dataMap.put("AZB", (char) 8730); } else { dataMap.put("AZB", "□"); } } else { dataMap.put("MD", "□"); if (serviceDonatebaseinfo.getInfectious().contains("4")) { if (infectious.contains("4")) { dataMap.put("AZB", (char) 8730); } else { dataMap.put("AZB", "□"); @@ -557,16 +567,16 @@ } } else { dataMap.put("BG", "□"); if (serviceDonatebaseinfo.getInfectious().contains("3")) { if (infectious.contains("3")) { dataMap.put("MD", (char) 8730); if (serviceDonatebaseinfo.getInfectious().contains("4")) { if (infectious.contains("4")) { dataMap.put("AZB", (char) 8730); } else { dataMap.put("AZB", "□"); } } else { dataMap.put("MD", "□"); if (serviceDonatebaseinfo.getInfectious().contains("4")) { if (infectious.contains("4")) { dataMap.put("AZB", (char) 8730); } else { dataMap.put("AZB", "□"); @@ -575,18 +585,18 @@ } } else { dataMap.put("YG", "□"); if (serviceDonatebaseinfo.getInfectious().contains("2")) { if (infectious.contains("2")) { dataMap.put("BG", (char) 8730); if (serviceDonatebaseinfo.getInfectious().contains("3")) { if (infectious.contains("3")) { dataMap.put("MD", (char) 8730); if (serviceDonatebaseinfo.getInfectious().contains("4")) { if (infectious.contains("4")) { dataMap.put("AZB", (char) 8730); } else { dataMap.put("AZB", "□"); } } else { dataMap.put("MD", "□"); if (serviceDonatebaseinfo.getInfectious().contains("4")) { if (infectious.contains("4")) { dataMap.put("AZB", (char) 8730); } else { dataMap.put("AZB", "□"); @@ -594,16 +604,16 @@ } } else { dataMap.put("BG", "□"); if (serviceDonatebaseinfo.getInfectious().contains("3")) { if (infectious.contains("3")) { dataMap.put("MD", (char) 8730); if (serviceDonatebaseinfo.getInfectious().contains("4")) { if (infectious.contains("4")) { dataMap.put("AZB", (char) 8730); } else { dataMap.put("AZB", "□"); } } else { dataMap.put("MD", "□"); if (serviceDonatebaseinfo.getInfectious().contains("4")) { if (infectious.contains("4")) { dataMap.put("AZB", (char) 8730); } else { dataMap.put("AZB", "□"); @@ -613,16 +623,16 @@ } dataMap.put("CRBQT", serviceDonatebaseinfo.getInfectiousOther() == null ? "" : serviceDonatebaseinfo.getInfectiousOther()); //病人状况 if (serviceDonatebaseinfo.getPatientstate().contains("0")) { if (patientstate.contains("0")) { dataMap.put("SDHM", (char) 8730); if (serviceDonatebaseinfo.getPatientstate().contains("1")) { if (patientstate.contains("1")) { dataMap.put("WZZHX", (char) 8730); } else { dataMap.put("WZZHX", "□"); } } else { dataMap.put("SDHM", "□"); if (serviceDonatebaseinfo.getPatientstate().contains("1")) { if (patientstate.contains("1")) { dataMap.put("WZZHX", (char) 8730); } else { dataMap.put("WZZHX", "□"); @@ -630,20 +640,20 @@ } //其他情况 if (serviceDonatebaseinfo.getOthercases().contains("0")) { if (othercases.contains("0")) { dataMap.put("JTSG", (char) 8730); if (serviceDonatebaseinfo.getOthercases().contains("1")) { if (othercases.contains("1")) { dataMap.put("XSAJ", (char) 8730); if (serviceDonatebaseinfo.getOthercases().contains("2")) { if (othercases.contains("2")) { dataMap.put("GSSG", (char) 8730); if (serviceDonatebaseinfo.getOthercases().contains("3")) { if (othercases.contains("3")) { dataMap.put("QTYWSG", (char) 8730); } else { dataMap.put("QTYWSG", "□"); } } else { dataMap.put("GSSG", "□"); if (serviceDonatebaseinfo.getOthercases().contains("3")) { if (othercases.contains("3")) { dataMap.put("QTYWSG", (char) 8730); } else { dataMap.put("QTYWSG", "□"); @@ -651,16 +661,16 @@ } } else { dataMap.put("XSAJ", "□"); if (serviceDonatebaseinfo.getOthercases().contains("2")) { if (othercases.contains("2")) { dataMap.put("GSSG", (char) 8730); if (serviceDonatebaseinfo.getOthercases().contains("3")) { if (othercases.contains("3")) { dataMap.put("QTYWSG", (char) 8730); } else { dataMap.put("QTYWSG", "□"); } } else { dataMap.put("GSSG", "□"); if (serviceDonatebaseinfo.getOthercases().contains("3")) { if (othercases.contains("3")) { dataMap.put("QTYWSG", (char) 8730); } else { dataMap.put("QTYWSG", "□"); @@ -669,18 +679,18 @@ } } else { dataMap.put("JTSG", "□"); if (serviceDonatebaseinfo.getOthercases().contains("1")) { if (othercases.contains("1")) { dataMap.put("XSAJ", (char) 8730); if (serviceDonatebaseinfo.getOthercases().contains("2")) { if (othercases.contains("2")) { dataMap.put("GSSG", (char) 8730); if (serviceDonatebaseinfo.getOthercases().contains("3")) { if (othercases.contains("3")) { dataMap.put("QTYWSG", (char) 8730); } else { dataMap.put("QTYWSG", "□"); } } else { dataMap.put("GSSG", "□"); if (serviceDonatebaseinfo.getOthercases().contains("3")) { if (othercases.contains("3")) { dataMap.put("QTYWSG", (char) 8730); } else { dataMap.put("QTYWSG", "□"); @@ -688,16 +698,16 @@ } } else { dataMap.put("XSAJ", "□"); if (serviceDonatebaseinfo.getOthercases().contains("2")) { if (othercases.contains("2")) { dataMap.put("GSSG", (char) 8730); if (serviceDonatebaseinfo.getOthercases().contains("3")) { if (othercases.contains("3")) { dataMap.put("QTYWSG", (char) 8730); } else { dataMap.put("QTYWSG", "□"); } } else { dataMap.put("GSSG", "□"); if (serviceDonatebaseinfo.getOthercases().contains("3")) { if (othercases.contains("3")) { dataMap.put("QTYWSG", (char) 8730); } else { dataMap.put("QTYWSG", "□"); @@ -707,20 +717,20 @@ } //情亲属关系情况 if (serviceDonatebaseinfo.getKinship().contains("0")) { if (kinship.contains("0")) { dataMap.put("PE", (char) 8730); if (serviceDonatebaseinfo.getKinship().contains("1")) { if (kinship.contains("1")) { dataMap.put("ZN", (char) 8730); if (serviceDonatebaseinfo.getKinship().contains("2")) { if (kinship.contains("2")) { dataMap.put("FQ", (char) 8730); if (serviceDonatebaseinfo.getKinship().contains("3")) { if (kinship.contains("3")) { dataMap.put("MQ", (char) 8730); } else { dataMap.put("MQ", "□"); } } else { dataMap.put("FQ", "□"); if (serviceDonatebaseinfo.getKinship().contains("3")) { if (kinship.contains("3")) { dataMap.put("MQ", (char) 8730); } else { dataMap.put("MQ", "□"); @@ -728,16 +738,16 @@ } } else { dataMap.put("ZN", "□"); if (serviceDonatebaseinfo.getKinship().contains("2")) { if (kinship.contains("2")) { dataMap.put("FQ", (char) 8730); if (serviceDonatebaseinfo.getKinship().contains("3")) { if (kinship.contains("3")) { dataMap.put("MQ", (char) 8730); } else { dataMap.put("MQ", "□"); } } else { dataMap.put("FQ", "□"); if (serviceDonatebaseinfo.getKinship().contains("3")) { if (kinship.contains("3")) { dataMap.put("MQ", (char) 8730); } else { dataMap.put("MQ", "□"); @@ -746,18 +756,18 @@ } } else { dataMap.put("PE", "□"); if (serviceDonatebaseinfo.getKinship().contains("1")) { if (kinship.contains("1")) { dataMap.put("ZN", (char) 8730); if (serviceDonatebaseinfo.getKinship().contains("2")) { if (kinship.contains("2")) { dataMap.put("FQ", (char) 8730); if (serviceDonatebaseinfo.getKinship().contains("3")) { if (kinship.contains("3")) { dataMap.put("MQ", (char) 8730); } else { dataMap.put("MQ", "□"); } } else { dataMap.put("FQ", "□"); if (serviceDonatebaseinfo.getKinship().contains("3")) { if (kinship.contains("3")) { dataMap.put("MQ", (char) 8730); } else { dataMap.put("MQ", "□"); @@ -765,16 +775,16 @@ } } else { dataMap.put("ZN", "□"); if (serviceDonatebaseinfo.getKinship().contains("2")) { if (kinship.contains("2")) { dataMap.put("FQ", (char) 8730); if (serviceDonatebaseinfo.getKinship().contains("3")) { if (kinship.contains("3")) { dataMap.put("MQ", (char) 8730); } else { dataMap.put("MQ", "□"); } } else { dataMap.put("FQ", "□"); if (serviceDonatebaseinfo.getKinship().contains("3")) { if (kinship.contains("3")) { dataMap.put("MQ", (char) 8730); } else { dataMap.put("MQ", "□"); @@ -785,20 +795,20 @@ dataMap.put("QSQT", serviceDonatebaseinfo.getKinshipOther() == null ? "" : serviceDonatebaseinfo.getKinshipOther()); //本人捐献 if (serviceDonatebaseinfo.getSelfwill().contains("0")) { if (selfwill.contains("0")) { dataMap.put("ZYDJ", (char) 8730); if (serviceDonatebaseinfo.getSelfwill().contains("1")) { if (selfwill.contains("1")) { dataMap.put("SMTY", (char) 8730); if (serviceDonatebaseinfo.getSelfwill().contains("2")) { if (selfwill.contains("2")) { dataMap.put("KTTY", (char) 8730); if (serviceDonatebaseinfo.getSelfwill().contains("3")) { if (selfwill.contains("3")) { dataMap.put("WBSBTY", (char) 8730); } else { dataMap.put("WBSBTY", "□"); } } else { dataMap.put("KTTY", "□"); if (serviceDonatebaseinfo.getSelfwill().contains("3")) { if (selfwill.contains("3")) { dataMap.put("WBSBTY", (char) 8730); } else { dataMap.put("WBSBTY", "□"); @@ -806,16 +816,16 @@ } } else { dataMap.put("SMTY", "□"); if (serviceDonatebaseinfo.getSelfwill().contains("2")) { if (selfwill.contains("2")) { dataMap.put("KTTY", (char) 8730); if (serviceDonatebaseinfo.getSelfwill().contains("3")) { if (selfwill.contains("3")) { dataMap.put("WBSBTY", (char) 8730); } else { dataMap.put("WBSBTY", "□"); } } else { dataMap.put("KTTY", "□"); if (serviceDonatebaseinfo.getSelfwill().contains("3")) { if (selfwill.contains("3")) { dataMap.put("WBSBTY", (char) 8730); } else { dataMap.put("WBSBTY", "□"); @@ -824,18 +834,18 @@ } } else { dataMap.put("ZYDJ", "□"); if (serviceDonatebaseinfo.getSelfwill().contains("1")) { if (selfwill.contains("1")) { dataMap.put("SMTY", (char) 8730); if (serviceDonatebaseinfo.getSelfwill().contains("2")) { if (selfwill.contains("2")) { dataMap.put("KTTY", (char) 8730); if (serviceDonatebaseinfo.getSelfwill().contains("3")) { if (selfwill.contains("3")) { dataMap.put("WBSBTY", (char) 8730); } else { dataMap.put("WBSBTY", "□"); } } else { dataMap.put("KTTY", "□"); if (serviceDonatebaseinfo.getSelfwill().contains("3")) { if (selfwill.contains("3")) { dataMap.put("WBSBTY", (char) 8730); } else { dataMap.put("WBSBTY", "□"); @@ -843,16 +853,16 @@ } } else { dataMap.put("SMTY", "□"); if (serviceDonatebaseinfo.getSelfwill().contains("2")) { if (selfwill.contains("2")) { dataMap.put("KTTY", (char) 8730); if (serviceDonatebaseinfo.getSelfwill().contains("3")) { if (selfwill.contains("3")) { dataMap.put("WBSBTY", (char) 8730); } else { dataMap.put("WBSBTY", "□"); } } else { dataMap.put("KTTY", "□"); if (serviceDonatebaseinfo.getSelfwill().contains("3")) { if (selfwill.contains("3")) { dataMap.put("WBSBTY", (char) 8730); } else { dataMap.put("WBSBTY", "□"); @@ -883,25 +893,25 @@ dataMap.put("YJXZGX", "受委托人"); } //信息来源 if (serviceDonatebaseinfo.getInfosources().contains("红十字会")) { if (infosources.contains("红十字会")) { dataMap.put("HSZH2", (char) 8730); // 勾选符号 } else { dataMap.put("HSZH2", "□"); // 方框符号 } if (serviceDonatebaseinfo.getInfosources().contains("医疗机构")) { if (infosources.contains("医疗机构")) { dataMap.put("YLJG", (char) 8730); if (serviceDonatebaseinfo.getInfosources().contains("家属")) { if (infosources.contains("家属")) { dataMap.put("QS", (char) 8730); if (serviceDonatebaseinfo.getInfosources().contains("交通")) { if (infosources.contains("交通")) { dataMap.put("JT", (char) 8730); if (serviceDonatebaseinfo.getInfosources().contains("公安")) { if (infosources.contains("公安")) { dataMap.put("GA", (char) 8730); } else { dataMap.put("GA", "□"); } } else { dataMap.put("JT", "□"); if (serviceDonatebaseinfo.getInfosources().contains("公安")) { if (infosources.contains("公安")) { dataMap.put("GA", (char) 8730); } else { dataMap.put("GA", "□"); @@ -909,16 +919,16 @@ } } else { dataMap.put("QS", "□"); if (serviceDonatebaseinfo.getInfosources().contains("交通")) { if (infosources.contains("交通")) { dataMap.put("JT", (char) 8730); if (serviceDonatebaseinfo.getInfosources().contains("公安")) { if (infosources.contains("公安")) { dataMap.put("GA", (char) 8730); } else { dataMap.put("GA", "□"); } } else { dataMap.put("JT", "□"); if (serviceDonatebaseinfo.getInfosources().contains("公安")) { if (infosources.contains("公安")) { dataMap.put("GA", (char) 8730); } else { dataMap.put("GA", "□"); @@ -927,18 +937,18 @@ } } else { dataMap.put("YLJG", "□"); if (serviceDonatebaseinfo.getInfosources().contains("家属")) { if (infosources.contains("家属")) { dataMap.put("QS", (char) 8730); if (serviceDonatebaseinfo.getInfosources().contains("交通")) { if (infosources.contains("交通")) { dataMap.put("JT", (char) 8730); if (serviceDonatebaseinfo.getInfosources().contains("公安")) { if (infosources.contains("公安")) { dataMap.put("GA", (char) 8730); } else { dataMap.put("GA", "□"); } } else { dataMap.put("JT", "□"); if (serviceDonatebaseinfo.getInfosources().contains("公安")) { if (infosources.contains("公安")) { dataMap.put("GA", (char) 8730); } else { dataMap.put("GA", "□"); @@ -946,16 +956,16 @@ } } else { dataMap.put("QS", "□"); if (serviceDonatebaseinfo.getInfosources().contains("交通")) { if (infosources.contains("交通")) { dataMap.put("JT", (char) 8730); if (serviceDonatebaseinfo.getInfosources().contains("公安")) { if (infosources.contains("公安")) { dataMap.put("GA", (char) 8730); } else { dataMap.put("GA", "□"); } } else { dataMap.put("JT", "□"); if (serviceDonatebaseinfo.getInfosources().contains("公安")) { if (infosources.contains("公安")) { dataMap.put("GA", (char) 8730); } else { dataMap.put("GA", "□"); @@ -967,10 +977,11 @@ dataMap.put("HSZH", serviceDonatebaseinfo.getRedorganname() == null ? "" : serviceDonatebaseinfo.getRedorganname()); dataMap.put("LXR", serviceDonatebaseinfo.getContactperson() == null ? "" : serviceDonatebaseinfo.getContactperson()); Date dt1 = serviceDonatebaseinfo.getContacttime(); String date1 = formatter.format(dt1); String time1 = date1.substring(0, 16); dataMap.put("LXSJ", serviceDonatebaseinfo.getContacttime() == null ? "" : time1); String lxsj = ""; if (serviceDonatebaseinfo.getContacttime() != null) { lxsj = formatter.format(serviceDonatebaseinfo.getContacttime()).substring(0, 16); } dataMap.put("LXSJ", lxsj); dataMap.put("HQZZ", serviceDonatebaseinfo.getAcquisitiontissuename() == null ? "" : serviceDonatebaseinfo.getAcquisitiontissuename()); dataMap.put("BGR", serviceDonatebaseinfo.getReportername() == null ? "" : serviceDonatebaseinfo.getReportername()); dataMap.put("BGRDH", serviceDonatebaseinfo.getReporterphone() == null ? "" : serviceDonatebaseinfo.getReporterphone()); ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceDonatecompletioninfoController.java
@@ -3,11 +3,13 @@ import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.OrganEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.bean.DtoConversionUtils; import com.ruoyi.common.utils.poi.ExcelUtil; @@ -221,18 +223,16 @@ String name = "人体器官捐献完成结果登记表_" + dataMap.get("XM") + "_" + newTime; //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceDonationwitnessController.java
@@ -6,7 +6,9 @@ import com.ruoyi.common.annotation.NotRepeatCommit; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.enums.OrganEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.DtoConversionUtils; @@ -210,18 +212,16 @@ String name = "人体器官捐献获取见证登记表_" + dataMap.get("XM") + "_" + newTime; //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceDonorpaymentController.java
@@ -3,10 +3,12 @@ import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.project.domain.ServiceDonorpayment; import com.ruoyi.project.service.IServiceDonorpaymentService; @@ -131,19 +133,16 @@ String name = "浙江省接收器官结算表_"+ newTime; //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { logger.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceExternalpersonController.java
@@ -96,7 +96,8 @@ { return AjaxResult.error("新增人员需要确定人员类型!"); } if (!"org".equals(usertype)){ // UserType 自 2026-09-27 起为多值字段(逗号分隔),单位判断改为"包含 org" if (!hasUserType(usertype, "org")){ String idcardno = serviceExternalperson.getIdcardno(); List<ServiceExternalperson> existpsersons = serviceExternalpersonService.getInfoByIDCardNo(idcardno); if (existpsersons.size() > 0) { @@ -148,4 +149,23 @@ public AjaxResult getInfoByIDCardNo(@PathVariable("idcardno") String idcardno) { return AjaxResult.success(serviceExternalpersonService.getInfoByIDCardNo(idcardno)); } /** * 判断人员类型(多值,逗号分隔)中是否包含指定类型 * * @param usertype 人员类型,如 "zzry,performance";兼容改造前的单值 * @param code 字典 sys_UserType 的取值,如 "org" * @return 是否包含 */ private static boolean hasUserType(String usertype, String code) { if (usertype == null || usertype.isEmpty()) { return false; } for (String item : usertype.split(",")) { if (code.equals(item.trim())) { return true; } } return false; } } ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceFundController.java
@@ -322,6 +322,23 @@ return AjaxResult.success(serviceFundService.addOrUpdateNew(serviceFundVO)); } /** * 专家劳务费:保存前的费用控制校验(干跑,不落库) * * <p>供专家劳务费填报页在点“保存”前调用,把 9 条规则的校验结果 * (errors 阻断 / warnings 提示)返回前端展示;真正的落库拦截在 addOrUpdateNew 中。 */ @ApiOperation("专家劳务费保存前校验") @PostMapping("/validateExpertFee") public AjaxResult validateExpertFee(@RequestBody ServiceFundVO serviceFundVO) { ExpertFeeCheckResult result = serviceFundService.validateExpertFee(serviceFundVO); AjaxResult ajaxResult = AjaxResult.success(); ajaxResult.put("errors", result.getErrors()); ajaxResult.put("warnings", result.getWarnings()); ajaxResult.put("blocked", result.hasError()); return ajaxResult; } /** * 审核费用 @@ -475,18 +492,16 @@ //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); @@ -659,18 +674,16 @@ //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); @@ -756,18 +769,16 @@ //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); @@ -858,20 +869,16 @@ } //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { log.error("FileNotFoundException报错信息是:{}", e1.getMessage()); // e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { log.error("TemplateException报错信自是:{}", e.getMessage()); e.getMessage(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); @@ -1083,18 +1090,16 @@ //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); @@ -1152,18 +1157,16 @@ //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); @@ -1652,18 +1655,16 @@ //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); @@ -1741,18 +1742,16 @@ //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceReimbursementController.java
@@ -14,6 +14,7 @@ import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.project.domain.*; import com.ruoyi.project.common.FundNotifyMessageBuilder; import com.ruoyi.project.domain.dto.ServiceReimbursementDto; import com.ruoyi.project.domain.vo.CheckFundVO; import com.ruoyi.project.domain.vo.DingTalkReqVo; @@ -346,17 +347,27 @@ //陈慕华信息 sysUser = sysUserService.selectUserByUserName("047"); } ConcurrentHashMap map = new ConcurrentHashMap(); ArrayList<ConcurrentHashMap<String, Object>> contentList = new ArrayList<>(); map.put("提交人:", loginUser.getUser().getUserName()); map.put("提交时间:", new Date()); map.put("内容:", serviceReimbursement.getReason()); contentList.add(map); //差旅费上报提交:单据信息 + 提交人/提交时间/内容 //钉钉属于旁路通知,任何失败都不得影响"上报"主流程(否则前端会提示失败但数据已更新) try { List<ConcurrentHashMap<String, Object>> contentList = FundNotifyMessageBuilder.newRows(); FundNotifyMessageBuilder.addBillInfo(contentList, "0", serviceReimbursement.getUsername(), serviceReimbursement.getAmountrequested(), null, FundNotifyMessageBuilder.billNo(serviceReimbursement.getBh(), serviceReimbursement.getId())); FundNotifyMessageBuilder.addTravelInfo(contentList, serviceReimbursement.getTravelers(), serviceReimbursement.getReason()); FundNotifyMessageBuilder.addSubmitInfo(contentList, loginUser.getUser().getNickName(), new Date(), serviceReimbursement.getReason()); DingTalkReqVo dingTalkReqVo = new DingTalkReqVo(); dingTalkReqVo.setTitle("差旅审批信息"); dingTalkReqVo.setTitle(FundNotifyMessageBuilder.TITLE); dingTalkReqVo.setNumber(sysUser != null ? sysUser.getPhonenumber() : ""); dingTalkReqVo.setContents(contentList); dingTalkService.sendNotification(dingTalkReqVo); } catch (Throwable t) { log.error("差旅上报钉钉通知失败,已忽略(不影响上报主流程),id={}", serviceReimbursement.getId(), t); } } serviceReimbursementService.updateById(serviceReimbursement); @@ -467,18 +478,16 @@ System.out.println("目录已存在"); } Writer out = null; try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); } catch (FileNotFoundException e1) { e1.printStackTrace(); if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); ruoyi-admin/src/main/java/com/ruoyi/web/controller/project/ServiceRelativesconfirmationController.java
@@ -189,13 +189,16 @@ String name = "人体器官捐献亲属确认登记表_" + dataMap.get("XM") + "_" + newTime; //输出文档路径及名称 File outFile = new File(RuoYiConfig.getProfile() + "/download/wordtemplate/" + name + ".doc"); Writer out = null; if (t == null) { throw new ServiceException("模板加载失败,请检查模板文件是否存在", HttpStatus.NO_CONTENT); } try { out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")); // Writer 必须关闭/刷新:BufferedWriter 带缓冲,不关闭会造成文件句柄泄漏且内容可能不完整 try (Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"))) { t.process(dataMap, out); } catch (TemplateException e) { e.printStackTrace(); } catch (TemplateException | IOException e) { log.error("生成模板文档失败, name={}", name, e); throw new ServiceException("生成文档失败", HttpStatus.ERROR); } Map<String, Object> map = new HashMap<>(); map.put("downloadUrl", "/profile/download/wordtemplate/" + name + ".doc"); ruoyi-admin/src/main/resources/application.yml
@@ -53,8 +53,9 @@ # 国际化资源文件路径 basename: i18n/messages profiles: # active: srm active: druid active: srm # active: druid # 文件上传 servlet: multipart: ruoyi-common/src/main/java/com/ruoyi/common/utils/MergeFilesToPDFUtils.java
@@ -76,11 +76,16 @@ * @param outputPath */ public Boolean wordtoPdf(String inputPath, String outputPath) { // Spire.Doc 的 Document 持有文件句柄,必须显式关闭,否则句柄要等 finalize 才释放,且会占用源文件 Document doc = new Document(); try { //加载Word doc.loadFromFile(inputPath); //保存为PDF格式 doc.saveToFile(outputPath, FileFormat.PDF); } finally { doc.close(); } return true; } @@ -91,18 +96,25 @@ com.itextpdf.text.Document document = new com.itextpdf.text.Document(); log.info("fileName的全路径:{}", archived + "/" + fileName); PdfCopy copy = new PdfCopy(document, new FileOutputStream(archived + "/" + fileName)); // 合并过程中任何一步抛异常都必须关闭 document:document.close() 会级联关闭 PdfWriter 及其输出流, // 否则输出流句柄会被长时间占用(依赖 finalize 才能释放),且异常时文件内容不完整 try { document.open(); for (String pdfFile : pdfFiles) { PdfReader reader = new PdfReader(pdfFile); try { int totalPages = reader.getNumberOfPages(); for (int page = 1; page <= totalPages; page++) { PdfImportedPage importedPage = copy.getImportedPage(reader, page); copy.addPage(importedPage); } } finally { reader.close(); } } } finally { document.close(); } } } ruoyi-project/src/main/java/com/ruoyi/project/domain/ServiceFunddetail.java
@@ -77,6 +77,13 @@ private String unituserno; /** * 单位标识:1=单位(受益人选择单位时不需要身份证号),0=个人 */ @ApiModelProperty("单位标识:1=单位,0=个人") @Excel(name = "单位标识", readConverterExp = "1=单位,0=个人") private Integer isunit; /** * 职称,见字典sys_professionaltitle */ @ApiModelProperty("职称") ruoyi-project/src/main/java/com/ruoyi/project/mapper/ServiceDonationwitnessMapper.java
@@ -12,6 +12,7 @@ import com.ruoyi.project.domain.vo.DonationWitnessVO; import com.ruoyi.project.domain.vo.TimeVO; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * 捐献见证Mapper接口 @@ -30,6 +31,18 @@ */ public List<ServiceDonationwitness> selectServiceDonationwitnessList(ServiceDonationwitness serviceDonationwitness); /** * 一次性查出全部「捐献基础ID -> 死亡时间」对应关系。 * * 用于列表页计算年龄:原实现在记录循环里按 InfoID 逐条查询见证表(N+1), * 首页/列表有多少条记录就会发多少次 SQL。改为一次查询后在内存中匹配。 * 只取 InfoID 与 DeathTime 两列,避免拉取整行宽表数据。 * * @param infoIds 需要查询的捐献基础ID集合;为空时查全部 * @return 仅含 infoid 与 deathtime 的列表 */ List<ServiceDonationwitness> selectDeathTimeByInfoIds(@Param("infoIds") Collection<Long> infoIds); List<ServiceDonationwitness> getWitnessList(); List<DonationWitnessVO> selectVOList(DonationWitnessVO donationWitnessVO); ruoyi-project/src/main/java/com/ruoyi/project/service/IServiceFundService.java
@@ -89,5 +89,15 @@ public Boolean updateFundTaxIdById(Long id, Long fundTaxIds); /** * 专家劳务费:9 条费用控制规则的表单校验(不落库)。 * * <p>供填报保存前调用,返回 errors(阻断性,不能保存)与 warnings(仅提示); * 真正的落库拦截在 {@link #addOrUpdateNew} 内。 * * @param serviceFundVO 本次提交的表单 * @return 校验结果 */ ExpertFeeCheckResult validateExpertFee(ServiceFundVO serviceFundVO); } ruoyi-project/src/main/java/com/ruoyi/project/service/impl/DingTalkServiceImpl.java
@@ -18,7 +18,7 @@ import com.ruoyi.project.service.DingTalkService; import com.ruoyi.system.mapper.SysUserMapper; import com.taobao.api.ApiException; import lombok.extern.log4j.Log4j; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -38,7 +38,7 @@ * @date 2023-05-23 */ @Service @Log4j @Slf4j public class DingTalkServiceImpl implements DingTalkService { @@ -51,119 +51,195 @@ @Value("${agentId}") private Long agentId; /** * access_token 缓存。 * 钉钉 token 有效期 7200 秒,这里按 6000 秒保守刷新; * 原实现每次发消息都调一次 /gettoken,钉钉对取 token 有频次限制,审核高峰期容易整体失败。 */ private volatile String cachedAccessToken; /** access_token 过期时间(epoch millis) */ private volatile long accessTokenExpireAt; private static final long ACCESS_TOKEN_TTL_MILLIS = 6000L * 1000L; /** * 钉钉接口超时(毫秒)。 * SDK 未显式设置超时时会无限等待,钉钉网络不通将占满容器线程、拖死审批等调用方, * 因此这里对所有出站请求统一设置连接/读取超时。 */ private static final int CONNECT_TIMEOUT_MS = 3000; private static final int READ_TIMEOUT_MS = 5000; @Autowired private SysUserMapper sysUserMapper; /** * 创建带超时的钉钉客户端 */ private DefaultDingTalkClient newClient(String url) { DefaultDingTalkClient client = new DefaultDingTalkClient(url); client.setConnectTimeout(CONNECT_TIMEOUT_MS); client.setReadTimeout(READ_TIMEOUT_MS); return client; } /** * 发送钉钉通知(对外唯一入口)。 * * <p><b>本方法保证不向外抛任何异常</b>:钉钉属于旁路通知,任何失败都只记日志并返回 false, * 绝不能影响审批、上报等业务主流程。 */ @Override public Boolean sendNotification(DingTalkReqVo dingTalkReqVo) { String body = null; try { return doSendNotification(dingTalkReqVo); } catch (Throwable t) { log.error("钉钉通知发送发生未预期异常,已忽略(不影响业务主流程)", t); return false; } } private Boolean doSendNotification(DingTalkReqVo dingTalkReqVo) { List<String> userIdlist = new ArrayList(); Boolean result = false; log.info("发送钉钉通知"); if (dingTalkReqVo == null) { log.warn("钉钉通知入参为空,跳过发送"); return false; } log.info("发送钉钉通知,title={}", dingTalkReqVo.getTitle()); String accessToken = null; try { accessToken = getAccessToken(); } catch (ApiException e) { e.printStackTrace(); } catch (Exception e) { log.error("钉钉获取 access_token 失败,无法发送通知", e); } if (StringUtils.isEmpty(accessToken)) { log.error("钉钉 access_token 为空,无法发送通知"); return false; } // ---- 解析收件人:优先手机号,其次部门 ---- if (StringUtils.isNotEmpty(dingTalkReqVo.getNumber())) { DingTalkClient clientT = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile"); try { DingTalkClient clientT = newClient("https://oapi.dingtalk.com/topapi/v2/user/getbymobile"); OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest(); req.setMobile(dingTalkReqVo.getNumber()); OapiV2UserGetbymobileResponse rsp = null; try { rsp = clientT.execute(req, accessToken); body = rsp.getBody(); String jsonObject = JSONObject.parseObject(body).getJSONObject("result").get("userid").toString(); userIdlist.add(jsonObject); } catch (ApiException e) { e.printStackTrace(); OapiV2UserGetbymobileResponse rsp = clientT.execute(req, accessToken); String body = rsp == null ? null : rsp.getBody(); if (StringUtils.isEmpty(body)) { log.error("钉钉按手机号查用户失败,mobile={},响应为空", dingTalkReqVo.getNumber()); return false; } } else { DingTalkClient client3 = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid"); JSONObject resultObj = JSONObject.parseObject(body).getJSONObject("result"); if (resultObj == null || resultObj.get("userid") == null) { log.error("钉钉按手机号查用户失败,mobile={},响应={}", dingTalkReqVo.getNumber(), body); return false; } userIdlist.add(resultObj.get("userid").toString()); } catch (Exception e) { log.error("钉钉按手机号查用户异常,mobile={}", dingTalkReqVo.getNumber(), e); return false; } } else if (dingTalkReqVo.getDeptId() != null) { try { DingTalkClient client3 = newClient("https://oapi.dingtalk.com/topapi/user/listid"); OapiUserListidRequest request2 = new OapiUserListidRequest(); request2.setDeptId(dingTalkReqVo.getDeptId()); // 设置要获取的部门 ID,这里以根部门为例675909059L // 设置部门 ID,如果获取所有员工手机号,可以设置为根部门的 ID OapiUserListidResponse response2 = null; try { response2 = client3.execute(request2, accessToken); } catch (ApiException e) { e.printStackTrace(); } body = response2.getBody(); OapiUserListidResponse response2 = client3.execute(request2, accessToken); String body = response2 == null ? null : response2.getBody(); if (StringUtils.isNotEmpty(body)) { // 解析为JSONObject JSONObject jsonObject = JSONObject.parseObject(body); if (jsonObject != null) { // 提取出JSONArray JSONArray jsonArray = new JSONArray(jsonObject.getJSONObject("result").getJSONArray("userid_list")); // 将JSONArray转为List列表 String str = JSONObject.toJSONString(jsonArray); userIdlist = JSONObject.parseObject(str, List.class); } } catch (Exception e) { log.error("钉钉按部门查用户异常,deptId={}", dingTalkReqVo.getDeptId(), e); return false; } } else { // 既无手机号也无部门:原实现会走 listid(null) 被钉钉拒绝且异常被吞掉,表现为"静默发不出去" log.warn("钉钉通知未提供收件人(手机号与部门均为空),跳过发送"); return false; } if (CollectionUtils.isEmpty(userIdlist)) { log.warn("钉钉通知未解析到任何收件人,跳过发送"); return false; } //userid数组 for (String urid : userIdlist) { DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2"); OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request(); request.setUseridList(urid); request.setAgentId(agentId); request.setToAllUser(false); //发送内容处理 // ---- 组装消息体(所有收件人共用) ---- // contents 中每行一个单键 map,用 List 顺序保证钉钉表单行序 List<OapiMessageCorpconversationAsyncsendV2Request.Form> objects = new ArrayList<>(); List<ConcurrentHashMap<String, Object>> contents = dingTalkReqVo.getContents(); ArrayList<OapiMessageCorpconversationAsyncsendV2Request.Form> objects = new ArrayList<>(); for (int i = 0; i < contents.size(); i++) { ConcurrentHashMap<String, Object> map = contents.get(i); if (contents != null) { for (ConcurrentHashMap<String, Object> map : contents) { if (map == null) { continue; } for (Map.Entry<String, Object> entry : map.entrySet()) { Object value = entry.getValue(); if (value == null) { continue; } OapiMessageCorpconversationAsyncsendV2Request.Form formSeverityDesc = new OapiMessageCorpconversationAsyncsendV2Request.Form(); formSeverityDesc.setKey(entry.getKey()); if (entry.getKey().contains("审批时间")) { Date date = (Date) entry.getValue(); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String format = simpleDateFormat.format(date); formSeverityDesc.setValue(format); if (entry.getKey().contains("审批时间") && value instanceof Date) { // 24 小时制:原实现用 hh(12 小时制且无 AM/PM),下午的时间会显示成 01:xx SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); formSeverityDesc.setValue(simpleDateFormat.format((Date) value)); } else { if (entry.getValue() != null) { formSeverityDesc.setValue(entry.getValue().toString()); } formSeverityDesc.setValue(value.toString()); } objects.add(formSeverityDesc); } } } // ---- 逐人发送;全部成功才算成功(原实现 result 写在循环内,只反映最后一个收件人) ---- boolean allSuccess = true; for (String urid : userIdlist) { OapiMessageCorpconversationAsyncsendV2Response response = null; try { DingTalkClient client = newClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2"); OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request(); request.setUseridList(urid); request.setAgentId(agentId); request.setToAllUser(false); OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg(); msg.setOa(new OapiMessageCorpconversationAsyncsendV2Request.OA()); msg.getOa().setMessageUrl(dingTalkReqVo.getUrl()); msg.getOa().setPcMessageUrl(dingTalkReqVo.getUrl()); msg.getOa().setHead(new OapiMessageCorpconversationAsyncsendV2Request.Head()); // msg.getOa().getHead().setText("你在说啥呢绒顶替苛夺阿斯蒂芬阿斯蒂芬"); msg.getOa().getHead().setBgcolor("00409eff"); msg.getOa().setBody(new OapiMessageCorpconversationAsyncsendV2Request.Body()); msg.getOa().getBody().setTitle(dingTalkReqVo.getTitle()); // msg.getOa().getBody().setContent("待处理:" + "123" + "条"); msg.getOa().getBody().setForm(objects); msg.setMsgtype("oa"); request.setMsg(msg); // log.info("获取发送通知消息体和获取发送通知人完成"); OapiMessageCorpconversationAsyncsendV2Response response = null; try { response = client.execute(request, accessToken); } catch (ApiException e) { e.getErrMsg(); } catch (Exception e) { log.error("钉钉消息发送异常,收件人={}", urid, e); } // log.info("消息任务ID"+response.getTaskId()); System.out.println(response.getTaskId()); result = response.isSuccess(); if (response == null || !response.isSuccess()) { allSuccess = false; log.error("钉钉消息发送失败,收件人={},响应={}", urid, response == null ? "null" : response.getBody()); // 失败可能是 access_token 失效,清掉缓存让下次重新获取 clearAccessToken(); } else { log.info("钉钉消息发送成功,收件人={},taskId={}", urid, response.getTaskId()); } return result; } return allSuccess; } /** @@ -193,7 +269,7 @@ //根据传过来的部门ID,去获取该部门下的用户信息 if (begin != 1) DingUserInfoList(deptID); //获取子部门的dept_id DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub"); DingTalkClient client = newClient("https://oapi.dingtalk.com/topapi/v2/department/listsub"); OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest(); req.setDeptId(deptID); req.setLanguage("zh_CN"); @@ -218,7 +294,7 @@ public void DingUserInfoList(Long deptId) { DingTalkClient client = null; try { client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list?access_token=" + getAccessToken()); client = newClient("https://oapi.dingtalk.com/topapi/v2/user/list?access_token=" + getAccessToken()); OapiV2UserListRequest req = new OapiV2UserListRequest(); req.setDeptId(deptId); req.setCursor(0L); @@ -248,10 +324,19 @@ /** * 获取 access_token * 获取 access_token(带缓存,失效自动重取) */ private String getAccessToken() throws ApiException { DefaultDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken"); String token = cachedAccessToken; if (StringUtils.isNotEmpty(token) && System.currentTimeMillis() < accessTokenExpireAt) { return token; } synchronized (this) { if (StringUtils.isNotEmpty(cachedAccessToken) && System.currentTimeMillis() < accessTokenExpireAt) { return cachedAccessToken; } DefaultDingTalkClient client = newClient("https://oapi.dingtalk.com/gettoken"); OapiGettokenRequest request = new OapiGettokenRequest(); //Appkey request.setAppkey(dingAppid); @@ -260,7 +345,22 @@ /*请求方式*/ request.setHttpMethod("GET"); OapiGettokenResponse response = client.execute(request); return response.getAccessToken(); String newToken = response == null ? null : response.getAccessToken(); if (StringUtils.isNotEmpty(newToken)) { cachedAccessToken = newToken; accessTokenExpireAt = System.currentTimeMillis() + ACCESS_TOKEN_TTL_MILLIS; } return newToken; } } /** * 清空 access_token 缓存。 * 发送失败有可能是 token 失效(钉钉 errcode 40014/42001),清掉后下次发送会重新获取。 */ private void clearAccessToken() { cachedAccessToken = null; accessTokenExpireAt = 0L; } } ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceDonatebaseinfoServiceImpl.java
@@ -236,6 +236,23 @@ serviceDonatebaseinfo.setDeptid(user.getDeptId()); } List<ServiceDonatebaseinfo> serviceDonatebaseinfos = serviceDonatebaseinfoMapper.selectServiceDonatebaseinfoList(serviceDonatebaseinfo); // 一次性取出各捐献基础对应的死亡时间,避免在循环里按 InfoID 逐条查见证表(N+1) List<Long> infoIds = new ArrayList<>(); for (ServiceDonatebaseinfo item : serviceDonatebaseinfos) { if (item.getId() != null) { infoIds.add(item.getId()); } } Map<Long, Date> deathTimeMap = new HashMap<>(); if (!infoIds.isEmpty()) { for (ServiceDonationwitness witness : serviceDonationwitnessMapper.selectDeathTimeByInfoIds(infoIds)) { if (witness.getInfoid() != null && !deathTimeMap.containsKey(witness.getInfoid())) { deathTimeMap.put(witness.getInfoid(), witness.getDeathtime()); } } } for (ServiceDonatebaseinfo serviceDonatebaseinfo1 : serviceDonatebaseinfos) { //先给个年龄默认值(因为age是数字类型,不能放横杠,所以就所横扛放到单位上) serviceDonatebaseinfo1.setAgeunit("-"); @@ -243,12 +260,8 @@ serviceDonatebaseinfo1.setAge2(null); //获取死亡时间,如果获取见证里有死亡时间,则进行计算他的年龄 ServiceDonationwitness sdw = new ServiceDonationwitness(); sdw.setInfoid(serviceDonatebaseinfo1.getId()); List<ServiceDonationwitness> serviceDonationwitnessList = serviceDonationwitnessMapper.selectServiceDonationwitnessList(sdw); if (!CollectionUtils.isEmpty(serviceDonationwitnessList) && serviceDonatebaseinfo1.getBirthday() != null) { Date deathtime = serviceDonationwitnessList.get(0).getDeathtime(); if (ObjectUtils.isNotEmpty(deathtime)) { Date deathtime = deathTimeMap.get(serviceDonatebaseinfo1.getId()); if (ObjectUtils.isNotEmpty(deathtime) && serviceDonatebaseinfo1.getBirthday() != null) { Map<String, String> map = CalculateDateUtils.calculateAge(serviceDonatebaseinfo1.getBirthday().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), deathtime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); if (Objects.isNull(map)) { log.error("ServiceDonationwitness出生日期:{},ServiceDonationwitness死亡日期:{}", serviceDonatebaseinfo1.getBirthday(), deathtime); @@ -258,7 +271,6 @@ serviceDonatebaseinfo1.setAgeunit(map.get("ageUnit")); serviceDonatebaseinfo1.setAge2(org.apache.commons.lang3.ObjectUtils.isNotEmpty(map.get("age2")) ? Long.valueOf(map.get("age2")) : null); serviceDonatebaseinfo1.setAgeunit2(map.get("ageUnit2")); } } } ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceDonatecompletioninfoServiceImpl.java
@@ -25,7 +25,9 @@ import java.time.LocalDate; import java.time.ZoneId; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -132,6 +134,22 @@ } List<DonationCompletionVO> donationCompletionVOS = serviceDonatecompletioninfoMapper.selectVOList(donationCompletionVO); // 一次性取出各捐献基础对应的死亡时间,避免在循环里按 InfoID 逐条查见证表(N+1) List<Long> infoIds = new ArrayList<>(); for (DonationCompletionVO item : donationCompletionVOS) { if (item.getInfoid() != null) { infoIds.add(item.getInfoid()); } } Map<Long, Date> deathTimeMap = new HashMap<>(); if (!infoIds.isEmpty()) { for (ServiceDonationwitness witness : serviceDonationwitnessMapper.selectDeathTimeByInfoIds(infoIds)) { if (witness.getInfoid() != null && !deathTimeMap.containsKey(witness.getInfoid())) { deathTimeMap.put(witness.getInfoid(), witness.getDeathtime()); } } } for (DonationCompletionVO donationCompletionVO1 : donationCompletionVOS) { // if (donationCompletionVO1.getBirthday() != null) { // Map<String, String> map = CalculateDateUtils.calculateAge(donationCompletionVO1.getBirthday().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), LocalDate.now()); @@ -146,12 +164,8 @@ donationCompletionVO1.setAge(null); donationCompletionVO1.setAge2(null); //获取死亡时间,如果获取见证里有死亡时间,则进行计算他的年龄 ServiceDonationwitness sdw = new ServiceDonationwitness(); sdw.setInfoid(donationCompletionVO1.getInfoid()); List<ServiceDonationwitness> serviceDonationwitnessList = serviceDonationwitnessMapper.selectServiceDonationwitnessList(sdw); if (!org.springframework.util.CollectionUtils.isEmpty(serviceDonationwitnessList) && donationCompletionVO1.getBirthday() != null) { Date deathtime = serviceDonationwitnessList.get(0).getDeathtime(); if (ObjectUtils.isNotEmpty(deathtime)) { Date deathtime = deathTimeMap.get(donationCompletionVO1.getInfoid()); if (ObjectUtils.isNotEmpty(deathtime) && donationCompletionVO1.getBirthday() != null) { Map<String, String> map = CalculateDateUtils.calculateAge(donationCompletionVO1.getBirthday().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), deathtime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); if (ObjectUtils.isEmpty(map)) { log.error("DonationCompletionVO出生日期:{},DonationCompletionVO死亡日期:{}", donationCompletionVO1.getBirthday(), deathtime); @@ -162,7 +176,6 @@ donationCompletionVO1.setAgeunit(map.get("ageUnit")); donationCompletionVO1.setAge2(org.apache.commons.lang3.ObjectUtils.isNotEmpty(map.get("age2")) ? Long.valueOf(map.get("age2")) : null); donationCompletionVO1.setAgeunit2(map.get("ageUnit2")); } } } ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceDonationwitnessServiceImpl.java
@@ -26,6 +26,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import com.ruoyi.common.utils.StringUtils; @@ -95,17 +96,30 @@ donationWitnessVO.setReporterno(user.getUserName()); } List<DonationWitnessVO> donationWitnessVOS = serviceDonationwitnessMapper.selectVOList(donationWitnessVO); // 一次性取出各捐献基础对应的死亡时间,避免在循环里按 InfoID 逐条查见证表(N+1) List<Long> infoIds = new ArrayList<>(); for (DonationWitnessVO item : donationWitnessVOS) { if (item.getInfoid() != null) { infoIds.add(item.getInfoid()); } } Map<Long, Date> deathTimeMap = new HashMap<>(); if (!infoIds.isEmpty()) { for (ServiceDonationwitness witness : serviceDonationwitnessMapper.selectDeathTimeByInfoIds(infoIds)) { if (witness.getInfoid() != null && !deathTimeMap.containsKey(witness.getInfoid())) { deathTimeMap.put(witness.getInfoid(), witness.getDeathtime()); } } } for (DonationWitnessVO donationWitnessVO1 : donationWitnessVOS) { //先给个年龄默认值(因为age是数字类型,不能放横杠,所以就所横扛放到单位上) donationWitnessVO1.setAgeunit("-"); //获取死亡时间,如果获取见证里有死亡时间,则进行计算他的年龄 ServiceDonationwitness sdw = new ServiceDonationwitness(); sdw.setInfoid(donationWitnessVO1.getInfoid()); List<ServiceDonationwitness> serviceDonationwitnessList = serviceDonationwitnessMapper.selectServiceDonationwitnessList(sdw); if (!CollectionUtils.isEmpty(serviceDonationwitnessList) && donationWitnessVO1.getBirthday() != null) { Date deathtime = serviceDonationwitnessList.get(0).getDeathtime(); if (ObjectUtils.isNotEmpty(deathtime)) { Date deathtime = deathTimeMap.get(donationWitnessVO1.getInfoid()); if (ObjectUtils.isNotEmpty(deathtime) && donationWitnessVO1.getBirthday() != null) { Map<String, String> map = CalculateDateUtils.calculateAge(donationWitnessVO1.getBirthday().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), deathtime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); if (ObjectUtils.isEmpty(map)) { log.error("DonationWitnessVO出生日期:{},DonationWitnessVO死亡日期:{}", donationWitnessVO1.getBirthday(), deathtime); @@ -116,7 +130,6 @@ donationWitnessVO1.setAgeunit(map.get("ageUnit")); donationWitnessVO1.setAge2(org.apache.commons.lang3.ObjectUtils.isNotEmpty(map.get("age2")) ? Long.valueOf(map.get("age2")) : null); donationWitnessVO1.setAgeunit2(map.get("ageUnit2")); } } } return donationWitnessVOS; ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceEthicalreviewopinionsServiceImpl.java
@@ -23,6 +23,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import com.ruoyi.common.utils.StringUtils; @@ -99,18 +100,30 @@ } List<EthicalReviewVO> ethicalReviewVOS = serviceEthicalreviewopinionsMapper.selectVOList(ethicalReviewVO); // 一次性取出各捐献基础对应的死亡时间,避免在循环里按捐献基础ID逐条查见证表(N+1) List<Long> infoIds = new ArrayList<>(); for (EthicalReviewVO item : ethicalReviewVOS) { if (item.getId() != null) { infoIds.add(item.getId()); } } Map<Long, Date> deathTimeMap = new HashMap<>(); if (!infoIds.isEmpty()) { for (ServiceDonationwitness witness : serviceDonationwitnessMapper.selectDeathTimeByInfoIds(infoIds)) { if (witness.getInfoid() != null && !deathTimeMap.containsKey(witness.getInfoid())) { deathTimeMap.put(witness.getInfoid(), witness.getDeathtime()); } } } for (EthicalReviewVO ethicalReviewVO1 : ethicalReviewVOS) { //先给个年龄默认值(因为age是数字类型,不能放横杠,所以就所横扛放到单位上) ethicalReviewVO1.setAgeunit("-"); ethicalReviewVO1.setAge(null); ethicalReviewVO1.setAge2(null); //获取死亡时间,如果获取见证里有死亡时间,则进行计算他的年龄 ServiceDonationwitness sdw = new ServiceDonationwitness(); sdw.setInfoid(ethicalReviewVO1.getId()); List<ServiceDonationwitness> serviceDonationwitnessList = serviceDonationwitnessMapper.selectServiceDonationwitnessList(sdw); if (!CollectionUtils.isEmpty(serviceDonationwitnessList) && ethicalReviewVO1.getBirthday() != null) { Date deathtime = serviceDonationwitnessList.get(0).getDeathtime(); if (ObjectUtils.isNotEmpty(deathtime)) { Date deathtime = deathTimeMap.get(ethicalReviewVO1.getId()); if (ObjectUtils.isNotEmpty(deathtime) && ethicalReviewVO1.getBirthday() != null) { Map<String, String> map = CalculateDateUtils.calculateAge(ethicalReviewVO1.getBirthday().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), deathtime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); if (ObjectUtils.isEmpty(map)) { log.error("EthicalReviewVO出生日期:{},EthicalReviewVO死亡日期:{}", ethicalReviewVO1.getBirthday(), deathtime); @@ -120,7 +133,6 @@ ethicalReviewVO1.setAgeunit(map.get("ageUnit")); ethicalReviewVO1.setAge2(org.apache.commons.lang3.ObjectUtils.isNotEmpty(map.get("age2")) ? Long.valueOf(map.get("age2")) : null); ethicalReviewVO1.setAgeunit2(map.get("ageUnit2")); } } } ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceExternalpersonServiceImpl.java
@@ -49,7 +49,8 @@ wrappers.like(ServiceExternalperson::getUsername, serviceExternalperson.getUsername()); } if (StringUtils.isNotBlank(serviceExternalperson.getUsertype())) { wrappers.eq(ServiceExternalperson::getUsertype, serviceExternalperson.getUsertype()); // UserType 自 2026-09-27 起为多值字段(逗号分隔),按"包含"匹配 wrappers.apply("FIND_IN_SET({0}, UserType)", serviceExternalperson.getUsertype()); } if (StringUtils.isNotBlank(serviceExternalperson.getUnitname())) { wrappers.like(ServiceExternalperson::getUnitname, serviceExternalperson.getUnitname()); ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFundServiceImpl.java
@@ -16,11 +16,13 @@ import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.ApplyTypeEnum; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.base.BaseException; import com.ruoyi.common.utils.HttpClientKit; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.DtoConversionUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.project.common.FundNotifyMessageBuilder; import com.ruoyi.project.common.IdGeneratorUtils; import com.ruoyi.project.domain.*; import com.ruoyi.project.domain.vo.*; @@ -28,6 +30,7 @@ import com.ruoyi.project.service.*; import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.mapper.SysUserRoleMapper; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysUserService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -61,6 +64,10 @@ public class ServiceFundServiceImpl extends ServiceImpl<ServiceFundMapper, ServiceFund> implements IServiceFundService { @Autowired ServiceFundMapper serviceFundMapper; /** 专家劳务费 9 条费用控制规则校验(同一案例累计) */ @Autowired private ExpertFeeValidateService expertFeeValidateService; @Autowired private DingTalkService dingTalkService; @@ -137,6 +144,35 @@ @Value("${spring.profiles.active}") private String active; @Autowired private ISysConfigService sysConfigService; /** * 审批单是否上传医院协友(致远)系统:0=不上传(测试环境),1=上传(正式环境)。 * * <p>2026-10-09 新增:原来用 {@code spring.profiles.active == druid} 判断是否推送, * 测试环境与正式环境无法通过参数区分。改为系统参数控制。 */ private static final String CFG_UPLOAD_OA = "sys.approval.upload.oa"; /** 参数缺省值:上传(保持正式环境原有行为) */ private static final boolean DEFAULT_UPLOAD_OA = true; /** 审批单是否需要上传医院协友(致远)系统 */ private boolean isUploadOaEnabled() { String value = null; try { value = sysConfigService.selectConfigByKey(CFG_UPLOAD_OA); } catch (Exception e) { log.warn("读取参数 {} 失败,按默认值 {} 处理", CFG_UPLOAD_OA, DEFAULT_UPLOAD_OA, e); } if (value == null || value.trim().isEmpty()) { return DEFAULT_UPLOAD_OA; } String v = value.trim(); return "1".equals(v) || "true".equalsIgnoreCase(v) || "y".equalsIgnoreCase(v) || "on".equalsIgnoreCase(v); } /** * 致远系统流程退回 * @@ -199,6 +235,12 @@ String phone = null; String applytype = null; Long flowlevel = null; //钉钉通知用的单据信息 Double amount = null; String donorName = null; String billNo = null; String travelers = null; String reason = null; if (serviceProcessVO.getApplytype().equals("0")) { ServiceReimbursement serviceReimbursement = new ServiceReimbursement(); serviceReimbursement.setId(StringUtils.isNotEmpty(serviceProcessVO.getBackCode()) ? Long.valueOf(serviceProcessVO.getBackCode()) : null); @@ -213,6 +255,11 @@ phone = serviceReimbursementList.get(0).getPhone(); flowlevel = serviceReimbursementList.get(0).getFlowlevel(); applytype = "0"; amount = serviceReimbursementList.get(0).getAmountrequested(); billNo = FundNotifyMessageBuilder.billNo(serviceReimbursementList.get(0).getBh(), serviceReimbursementList.get(0).getId()); travelers = serviceReimbursementList.get(0).getTravelers(); reason = serviceReimbursementList.get(0).getReason(); } else { ServiceFund serviceFund = new ServiceFund(); serviceFund.setId(StringUtils.isNotEmpty(serviceProcessVO.getBackCode()) ? Long.valueOf(serviceProcessVO.getBackCode()) : null); @@ -226,6 +273,10 @@ phone = serviceFunds.get(0).getPhone(); flowlevel = serviceFunds.get(0).getFlowlevel(); applytype = serviceFunds.get(0).getApplytype(); amount = serviceFunds.get(0).getPretaxcost(); donorName = serviceFunds.get(0).getDonorname(); billNo = FundNotifyMessageBuilder.billNo(serviceFunds.get(0).getBh(), serviceFunds.get(0).getId()); } // //将操作保存到fundflow表中 @@ -248,7 +299,16 @@ SysUser sysUser = sysUserService.selectUserByUserName(userNo); sendMeg(serviceProcessVO, phone); //钉钉通知内容:单据信息(类型/报销人/金额/案例/编号)+ 审批人/审批时间/意见 List<ConcurrentHashMap<String, Object>> notifyRows = FundNotifyMessageBuilder.newRows(); FundNotifyMessageBuilder.addBillInfo(notifyRows, applytype, userName, amount, donorName, billNo); FundNotifyMessageBuilder.addTravelInfo(notifyRows, travelers, reason); FundNotifyMessageBuilder.addAuditResult(notifyRows, serviceProcessVO.getCheckusername(), serviceProcessVO.getCheckTime(), FundNotifyMessageBuilder.opinion(serviceProcessVO.getFlowconclusion(), serviceProcessVO.getFlowcontent())); sendMeg(serviceProcessVO, phone, notifyRows); //发送信息保存 ServiceSystemmessage serviceSystemmessage = new ServiceSystemmessage(); serviceSystemmessage.setFundtype(1); @@ -260,7 +320,7 @@ serviceSystemmessage.setUpdateBy(sysUser.getNickName()); serviceSystemmessage.setIsread(0); serviceSystemmessage.setMessagetype(1); serviceSystemmessage.setMessagetitle("财务系统信息"); serviceSystemmessage.setMessagetitle("OPO系统审批"); serviceSystemmessage.setMessagecontent(serviceProcessVO.getFlowcontent()); iServiceSystemmessageService.save(serviceSystemmessage); @@ -374,6 +434,7 @@ } @Override @Transactional(rollbackFor = Exception.class) public Map<String, String> checkFund(CheckFundVO checkFundVO, LoginUser loginUser) { ServiceFund serviceFund = getById(checkFundVO.getFundid()); Map<String, String> map = new HashMap<>(); @@ -381,6 +442,19 @@ if (serviceFund == null) { map.put(HttpStatus.NO_CONTENT + "", "费用编号不正确"); return map; } // 专家劳务费:审核“通过”前校验 9 条费用控制规则(同一案例累计);不通过则不阻断 if (checkFundVO.getFlowconclusion() != null && checkFundVO.getFlowconclusion() == 1) { ExpertFeeCheckResult expertFeeResult = expertFeeValidateService.validateBeforeCheck(checkFundVO.getFundid()); if (expertFeeResult.hasError()) { map.put(HttpStatus.ERROR + "", expertFeeResult.errorMessage()); return map; } if (expertFeeResult.hasWarning()) { // 规则 5、6 仅提示,不阻断审核 log.warn("专家劳务费审核校验提示:fundId={},{}", checkFundVO.getFundid(), expertFeeResult.warningMessage()); } } Integer TotalLevel = 0; @@ -409,6 +483,11 @@ Integer RecordStatus = serviceFund.getRecordstatus(); Integer FlowLevel = serviceFund.getFlowlevel().intValue(); Integer OriginalFlowLevel = FlowLevel; //审批结论必填:原实现直接 == 1 拆箱,接口被直调传 null 会 NPE 500 if (checkFundVO.getFlowconclusion() == null) { map.put(HttpStatus.ERROR + "", "审批结论不能为空"); return map; } if (checkFundVO.getFlowconclusion() == 1) { CheckFlag = 1; if (TotalLevel == 0) { @@ -437,8 +516,9 @@ if (newSwitch == 1) { aBoolean1 = sendData(serviceFund); if (!aBoolean1) { map.put("500", "发送失败"); return map; // 推送医院协友系统失败:整个审批不生效(事务回滚),允许下次重新审批 log.error("费用审批单上传医院协友系统失败,审批不生效,fundId={},请重新审批", serviceFund.getId()); throw new ServiceException("医院协友系统接收失败,本次审批未生效,请稍后重新审批"); } } //保存审批流程表 @@ -481,21 +561,22 @@ } SysUser sysUser = sysUserService.selectUserByUserName(serviceFund.getUserno()); ArrayList<ConcurrentHashMap<String, Object>> contentList = new ArrayList<>(); ConcurrentHashMap cmap = new ConcurrentHashMap(); cmap.put("审批人:", loginUser.getUser().getUserName()); cmap.put("审批时间:", new Date()); cmap.put("意见:", "不通过"); if (StringUtils.isNotBlank(checkFundVO.getFlowcontent())) cmap.put("意见:", checkFundVO.getFlowcontent()); contentList.add(cmap); //审批未通过:单据信息 + 审批人/审批时间/意见(意见 = "审批未通过。" + 驳回意见) List<ConcurrentHashMap<String, Object>> contentList = FundNotifyMessageBuilder.newRows(); FundNotifyMessageBuilder.addBillInfo(contentList, serviceFund.getApplytype(), serviceFund.getUsername(), serviceFund.getPretaxcost(), serviceFund.getDonorname(), FundNotifyMessageBuilder.billNo(serviceFund.getBh(), serviceFund.getId())); FundNotifyMessageBuilder.addAuditResult(contentList, loginUser.getUser().getNickName(), new Date(), FundNotifyMessageBuilder.opinion(FundNotifyMessageBuilder.CONCLUSION_REJECT, checkFundVO.getFlowcontent())); try{ DingTalkReqVo dingTalkReqVo = new DingTalkReqVo(); dingTalkReqVo.setTitle("财务系统驳回信息"); dingTalkReqVo.setTitle(FundNotifyMessageBuilder.TITLE); dingTalkReqVo.setNumber(sysUser.getPhonenumber()); dingTalkReqVo.setContents(contentList); dingTalkService.sendNotification(dingTalkReqVo); }catch (Exception e){ log.error("费用---财务系统驳回信息报错了", e); log.error("费用---审批未通过钉钉通知失败,fundId={}", serviceFund.getId(), e); } } @@ -538,8 +619,9 @@ //搞一个开关,别影响老流程 aBoolean1 = sendData(serviceFund); if (!aBoolean1) { map.put("500", "发送失败"); return map; // 推送医院协友系统失败:整个审批不生效(事务回滚),允许下次重新审批 log.error("费用审批单上传医院协友系统失败,审批不生效,fundId={},请重新审批", serviceFund.getId()); throw new ServiceException("医院协友系统接收失败,本次审批未生效,请稍后重新审批"); } } } @@ -603,7 +685,30 @@ } /** * 审批单上传医院协友(致远)系统。 * * <p>2026-10-09:外层包一层兜底,保证**任何异常都不会向外抛**(原来 strRes 为 null 时 * 会在 parseObject 后取 code 触发 NPE,把整个审批请求打成 500)。 * 返回 false 表示推送失败,调用方按"审批不生效、允许下次重新审批"处理。 */ public Boolean sendData(ServiceFund serviceFund) { if (!isUploadOaEnabled()) { // 上传开关关闭(如测试环境):跳过上传并视为成功,绝不能因此阻断审批 log.info("审批单上传医院协友系统已关闭(sys.approval.upload.oa != 1),跳过上传并视为成功,fundId={}", serviceFund == null ? null : serviceFund.getId()); return true; } try { return doSendData(serviceFund); } catch (Throwable t) { log.error("费用审批单上传医院协友系统异常,审批不生效,fundId={}", serviceFund == null ? null : serviceFund.getId(), t); return false; } } private Boolean doSendData(ServiceFund serviceFund) { // fund和funddetail的数据获取 addFundSharedInfo(serviceFund.getId()); List<ServiceFundShared> fundShareInfos = serviceFundSharedMapper.getFundShareInfoById(serviceFund.getId()); @@ -644,7 +749,7 @@ map.put("data", data); String strRes = null; if (!active.equals("druid")) { if (isUploadOaEnabled()) { //如果是本地环境,就不调这个了 String token = getToken(); JSONObject json1 = JSONObject.parseObject(token); @@ -684,9 +789,28 @@ } } log.error("------------------strRes的值为:{}", strRes); JSONObject jsonObject = JSONObject.parseObject(strRes); if (strRes == null || strRes.trim().isEmpty()) { // 医院协友系统无返回(超时/异常/未配置):推送失败,由调用方回滚整个审批 log.error("费用审批单上传医院协友系统失败:接口无返回内容,fundId={}", serviceFund.getId()); return false; } JSONObject jsonObject = null; try { jsonObject = JSONObject.parseObject(strRes); } catch (Exception e) { log.error("费用审批单上传医院协友系统失败:返回内容无法解析,fundId={},strRes={}", serviceFund.getId(), strRes, e); return false; } if (jsonObject == null) { log.error("费用审批单上传医院协友系统失败:返回内容为空,fundId={},strRes={}", serviceFund.getId(), strRes); return false; } String code = jsonObject.getString("code"); if (!code.equals("0")) { if (code == null || !"0".equals(code)) { log.error("费用审批单上传医院协友系统失败:code={},fundId={},strRes={}", code, serviceFund.getId(), strRes); return false; } @@ -885,7 +1009,7 @@ serviceFunddetailShareds.get(i).setId(null); //数据发送给财务 try { if (!active.equals("druid")) uploadOAFileAndUpdateDb(serviceFunddetailShareds.get(i)); if (isUploadOaEnabled()) uploadOAFileAndUpdateDb(serviceFunddetailShareds.get(i)); } catch (Exception e) { e.printStackTrace(); log.error("Exception中入参的ID为:{},异常信息为 : {}", id, e.getMessage()); @@ -1421,8 +1545,23 @@ } @Override public ExpertFeeCheckResult validateExpertFee(ServiceFundVO serviceFundVO) { return expertFeeValidateService.validateBeforeSave(serviceFundVO); } @Override @Transactional(rollbackFor = Exception.class) public Long addOrUpdateNew(ServiceFundVO serviceFundVO) { // 专家劳务费:保存前校验 9 条费用控制规则(同一案例累计) ExpertFeeCheckResult expertFeeResult = expertFeeValidateService.validateBeforeSave(serviceFundVO); if (expertFeeResult.hasError()) { throw new BaseException(expertFeeResult.errorMessage()); } if (expertFeeResult.hasWarning()) { // 规则 5、6 仅提示,不阻断保存;前端单独取用提示文案 log.warn("专家劳务费保存校验提示:{}", expertFeeResult.warningMessage()); } Long id = null; //将数据保存到fund表 serviceFundVO.setUploadStates(0); @@ -1484,10 +1623,9 @@ return null; } //总税前 Double pretaxcosts = 0.00; //总税后 Double taxedcosts = 0.00; //总税前、总税后(金额累加用 BigDecimal,避免浮点尾差) BigDecimal pretaxcosts = BigDecimal.ZERO; BigDecimal taxedcosts = BigDecimal.ZERO; for (ServiceFunddetailVO serviceFunddetailVO : serviceFunddetails) { serviceFunddetailVO.setFundid(id); @@ -1496,13 +1634,18 @@ if (!performance.isEmpty()) { Double amount = performance.get("amount"); Double taxedamount = performance.get("taxedamount"); pretaxcosts = pretaxcosts + amount; taxedcosts = taxedcosts + taxedamount; if (amount != null) { pretaxcosts = pretaxcosts.add(BigDecimal.valueOf(amount)); } serviceFundVO.setPretaxcost(pretaxcosts); serviceFundVO.setTaxedcost(taxedcosts); if (taxedamount != null) { taxedcosts = taxedcosts.add(BigDecimal.valueOf(taxedamount)); } } } // 合计在循环结束后统一回写,原来写在循环内会每行都 UPDATE 一次,且中间值被反复覆盖 serviceFundVO.setPretaxcost(pretaxcosts.doubleValue()); serviceFundVO.setTaxedcost(taxedcosts.doubleValue()); updateById(serviceFundVO); } Map map = new HashMap(); map.put("fundId", id); return map; @@ -1700,7 +1843,7 @@ Map<String, Object> map = new HashMap<String, Object>(); map.put("userName", "opo"); map.put("password", "4126407a-9821-4874-be41-6568abd6dbe5"); map.put("loginName", "OPO系统"); map.put("loginName", "OPO系统审批"); JSONObject jsonObj = new JSONObject(map); @@ -1819,7 +1962,8 @@ } public void sendMeg(ServiceProcessVO serviceProcessVO, String phone) { public void sendMeg(ServiceProcessVO serviceProcessVO, String phone, List<ConcurrentHashMap<String, Object>> contentList) { //记录操作记录 ServiceFundflow serviceFundflow = new ServiceFundflow(); @@ -1838,20 +1982,14 @@ serviceFundflow.setFundid(StringUtils.isNotEmpty(serviceProcessVO.getBackCode()) ? Long.valueOf(serviceProcessVO.getBackCode()) : null); fundflowService.save(serviceFundflow); try { ArrayList<ConcurrentHashMap<String, Object>> contentList = new ArrayList<>(); ConcurrentHashMap map = new ConcurrentHashMap(); map.put("审批人:", serviceProcessVO.getCheckusername()); map.put("审批时间:", serviceProcessVO.getCheckTime()); map.put("意见:", serviceProcessVO.getFlowcontent()); contentList.add(map); DingTalkReqVo dingTalkReqVo = new DingTalkReqVo(); dingTalkReqVo.setTitle("财务系统信息"); dingTalkReqVo.setTitle(FundNotifyMessageBuilder.TITLE); dingTalkReqVo.setNumber(phone); dingTalkReqVo.setContents(contentList); log.info("钉钉发送消息:{}", dingTalkReqVo); dingTalkService.sendNotification(dingTalkReqVo); } catch (Exception e) { log.error("财务系统信息---钉钉消息发送失败,不影响主流程", e); log.error("报销审批钉钉消息发送失败,不影响主流程", e); } } } ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceFunddetailServiceImpl.java
@@ -136,21 +136,30 @@ */ @Override public Double getTaxByBeneFiciaryNo(TaxMoneyVO taxMoneyVo) { Double sum = 0.00; Double totalScore = 0.00; // 金额累加必须用 BigDecimal:double 累加会引入浮点尾差,导致算出的个税出现分以下误差 BigDecimal sum = BigDecimal.ZERO; BigDecimal totalScore = BigDecimal.ZERO; List<ServiceFunddetail> taxationByBeneFiciaryNo = serviceFunddetailMapper.getTaxBeforeByBeneFiciaryNo(taxMoneyVo); if (CollectionUtils.isNotEmpty(taxationByBeneFiciaryNo)) { //计算申请金额总和,不包括当前传进来的 sum = taxationByBeneFiciaryNo.stream().mapToDouble(ServiceFunddetail::getAmount).sum(); sum = taxationByBeneFiciaryNo.stream() .map(ServiceFunddetail::getAmount) .filter(java.util.Objects::nonNull) .map(BigDecimal::valueOf) .reduce(BigDecimal.ZERO, BigDecimal::add); //不加本次薪酬的个税 totalScore = taxationByBeneFiciaryNo.stream().mapToDouble(ServiceFunddetail::getTaxamount).sum(); totalScore = taxationByBeneFiciaryNo.stream() .map(ServiceFunddetail::getTaxamount) .filter(java.util.Objects::nonNull) .map(BigDecimal::valueOf) .reduce(BigDecimal.ZERO, BigDecimal::add); } sum = sum + new Double(taxMoneyVo.getMoney()); sum = sum.add(new BigDecimal(taxMoneyVo.getMoney())); //加上本次薪酬的总个税 String taxation = TaxtUtils.getTaxation(new BigDecimal(sum)); String taxation = TaxtUtils.getTaxation(sum); Double tax = Double.valueOf(taxation) - totalScore; Double tax = new BigDecimal(taxation).subtract(totalScore).doubleValue(); return tax; } @@ -163,21 +172,30 @@ @Override public TaxedMoneyVO getTaxBeforeByAfterMoney(TaxMoneyVO taxMoneyVo) { TaxedMoneyVO taxedMoneyVO = new TaxedMoneyVO(); Double sum = 0.00; Double totalScore = 0.00; // 金额累加必须用 BigDecimal,避免浮点尾差影响税前/税额结果 BigDecimal sum = BigDecimal.ZERO; BigDecimal totalScore = BigDecimal.ZERO; List<ServiceFunddetail> taxationByBeneFiciaryNo = serviceFunddetailMapper.getTaxBeforeByBeneFiciaryNo(taxMoneyVo); if (CollectionUtils.isNotEmpty(taxationByBeneFiciaryNo)) { //计算出税后总金额(不包含本次) sum = taxationByBeneFiciaryNo.stream().mapToDouble(ServiceFunddetail::getTaxedamount).sum(); sum = taxationByBeneFiciaryNo.stream() .map(ServiceFunddetail::getTaxedamount) .filter(java.util.Objects::nonNull) .map(BigDecimal::valueOf) .reduce(BigDecimal.ZERO, BigDecimal::add); //求出之前的总的个税 totalScore = taxationByBeneFiciaryNo.stream().mapToDouble(ServiceFunddetail::getTaxamount).sum(); totalScore = taxationByBeneFiciaryNo.stream() .map(ServiceFunddetail::getTaxamount) .filter(java.util.Objects::nonNull) .map(BigDecimal::valueOf) .reduce(BigDecimal.ZERO, BigDecimal::add); } //计算出总的税后薪酬(包含本次) sum = sum + Double.valueOf(taxMoneyVo.getMoney()); sum = sum.add(new BigDecimal(taxMoneyVo.getMoney())); //税前总金额 String taxationBefore = TaxtUtils.getTaxationBefore(new BigDecimal(sum)); String taxationBefore = TaxtUtils.getTaxationBefore(sum); //总个税 BigDecimal tax = new BigDecimal(taxationBefore).subtract(new BigDecimal(sum)); BigDecimal tax = new BigDecimal(taxationBefore).subtract(sum); //本次的税前金额 String nowTaxMoney = TaxtUtils.getTaxationBefore(new BigDecimal(taxMoneyVo.getMoney())); ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceReimbursementServiceImpl.java
@@ -17,6 +17,8 @@ import com.ruoyi.common.utils.HttpClientKit; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.DtoConversionUtils; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.project.common.FundNotifyMessageBuilder; import com.ruoyi.project.common.IdGeneratorUtils; import com.ruoyi.project.domain.*; import com.ruoyi.project.domain.dto.ServiceReimbursementDto; @@ -27,6 +29,7 @@ import com.ruoyi.project.service.*; import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.mapper.SysUserRoleMapper; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysPostService; import com.ruoyi.system.service.ISysUserService; import lombok.extern.slf4j.Slf4j; @@ -116,6 +119,35 @@ @Value("${spring.profiles.active}") private String active; @Autowired private ISysConfigService sysConfigService; /** * 审批单是否上传医院协友(致远)系统:0=不上传(测试环境),1=上传(正式环境)。 * * <p>2026-10-09 新增:原来用 {@code spring.profiles.active == druid} 来判断是否推送, * 导致测试环境与正式环境无法通过参数区分。改为系统参数控制,环境各自配置。 */ private static final String CFG_UPLOAD_OA = "sys.approval.upload.oa"; /** 参数缺省值:上传(保持正式环境原有行为) */ private static final boolean DEFAULT_UPLOAD_OA = true; /** 审批单是否需要上传医院协友(致远)系统 */ private boolean isUploadOaEnabled() { String value = null; try { value = sysConfigService.selectConfigByKey(CFG_UPLOAD_OA); } catch (Exception e) { log.warn("读取参数 {} 失败,按默认值 {} 处理", CFG_UPLOAD_OA, DEFAULT_UPLOAD_OA, e); } if (value == null || value.trim().isEmpty()) { return DEFAULT_UPLOAD_OA; } String v = value.trim(); return "1".equals(v) || "true".equalsIgnoreCase(v) || "y".equalsIgnoreCase(v) || "on".equalsIgnoreCase(v); } /** @@ -259,7 +291,7 @@ log.info("上传OA文件方法的入参:{}", serviceReimbursementdetailShareds.get(i)); try { //如果是本地环境,就不调这个了 if (!active.equals("druid")) uploadOAFileAndUpdateDb(serviceReimbursementdetailShareds.get(i)); if (isUploadOaEnabled()) uploadOAFileAndUpdateDb(serviceReimbursementdetailShareds.get(i)); } catch (Exception e) { log.error("Exception中reimShare的入参id为:{}", serviceReimbursementShared.getId()); if (serviceReimbursementShared.getId() != null) { @@ -333,6 +365,7 @@ } @Override @Transactional(rollbackFor = Exception.class) public Map<String, String> checkFund(LoginUser loginUser, CheckFundVO checkFundVO) { Map<String, String> allMap = new HashMap<>(); @@ -397,8 +430,9 @@ if (newSwitch == 1) { aBoolean1 = sendData(serviceReimbursement); if (!aBoolean1) { allMap.put("500", "发送失败"); return allMap; // 推送医院协友系统失败:整个审批不生效(事务回滚),允许下次重新审批 log.error("差旅审批单上传医院协友系统失败,审批不生效,id={},请重新审批", serviceReimbursement.getId()); throw new ServiceException("医院协友系统接收失败,本次审批未生效,请稍后重新审批"); } } //保存审批流程表 @@ -443,22 +477,25 @@ } } SysUser sysUser = sysUserService.selectUserByUserName(serviceReimbursement.getUserno()); ArrayList<ConcurrentHashMap<String, Object>> contentList = new ArrayList<>(); ConcurrentHashMap map = new ConcurrentHashMap(); map.put("审批人:", loginUser.getUser().getUserName()); map.put("审批时间:", new Date()); map.put("意见:", "不通过"); if (StringUtils.isNotBlank(checkFundVO.getFlowcontent())) map.put("意见:", checkFundVO.getFlowcontent()); contentList.add(map); //审批未通过:单据信息 + 出差信息 + 审批人/审批时间/意见(意见 = "审批未通过。" + 驳回意见) List<ConcurrentHashMap<String, Object>> contentList = FundNotifyMessageBuilder.newRows(); FundNotifyMessageBuilder.addBillInfo(contentList, "0", serviceReimbursement.getUsername(), serviceReimbursement.getAmountrequested(), null, FundNotifyMessageBuilder.billNo(serviceReimbursement.getBh(), serviceReimbursement.getId())); FundNotifyMessageBuilder.addTravelInfo(contentList, serviceReimbursement.getTravelers(), serviceReimbursement.getReason()); FundNotifyMessageBuilder.addAuditResult(contentList, loginUser.getUser().getNickName(), new Date(), FundNotifyMessageBuilder.opinion(FundNotifyMessageBuilder.CONCLUSION_REJECT, checkFundVO.getFlowcontent())); try { DingTalkReqVo dingTalkReqVo = new DingTalkReqVo(); dingTalkReqVo.setTitle("财务系统驳回信息"); dingTalkReqVo.setTitle(FundNotifyMessageBuilder.TITLE); dingTalkReqVo.setNumber(sysUser.getPhonenumber()); dingTalkReqVo.setContents(contentList); dingTalkService.sendNotification(dingTalkReqVo); }catch (Exception e){ log.error("差旅---财务系统驳回信息报错了", e); log.error("差旅---审批未通过钉钉通知失败,id={}", serviceReimbursement.getId(), e); } } @@ -515,8 +552,9 @@ log.info("差旅newSwitch返回的值为:{}", newSwitch); aBoolean1 = sendData(serviceReimbursement); if (!aBoolean1) { allMap.put("500", "发送失败"); return allMap; // 推送医院协友系统失败:整个审批不生效(事务回滚),允许下次重新审批 log.error("差旅审批单上传医院协友系统失败,审批不生效,id={},请重新审批", serviceReimbursement.getId()); throw new ServiceException("医院协友系统接收失败,本次审批未生效,请稍后重新审批"); } } } @@ -585,7 +623,30 @@ return "未找到审批记录"; } /** * 审批单上传医院协友(致远)系统。 * * <p>2026-10-09:外层包一层兜底,保证**任何异常都不会向外抛**(原来 strRes 为 null 时 * 会在 parseObject 后取 code 触发 NPE,把整个审批请求打成 500)。 * 返回 false 表示推送失败,调用方按"审批不生效、允许下次重新审批"处理。 */ public Boolean sendData(ServiceReimbursement serviceReimbursement) { if (!isUploadOaEnabled()) { // 上传开关关闭(如测试环境):跳过上传并视为成功,绝不能因此阻断审批 log.info("审批单上传医院协友系统已关闭(sys.approval.upload.oa != 1),跳过上传并视为成功,id={}", serviceReimbursement == null ? null : serviceReimbursement.getId()); return true; } try { return doSendData(serviceReimbursement); } catch (Throwable t) { log.error("差旅审批单上传医院协友系统异常,审批不生效,id={}", serviceReimbursement == null ? null : serviceReimbursement.getId(), t); return false; } } private Boolean doSendData(ServiceReimbursement serviceReimbursement) { // fund和funddetail的数据获取 addSharedData(serviceReimbursement.getId()); List<ServiceReimbursementShared> serviceReimbursementSharedList = sharedService.getRemShareInfoByRemId(serviceReimbursement.getId()); @@ -631,7 +692,7 @@ data.put("summaryId", serviceReimbursement1.getSummaryId() == null ? "" : serviceReimbursement1.getSummaryId()); map.put("data", data); String strRes = null; if (!active.equals("druid")) { if (isUploadOaEnabled()) { //如果是本地环境,就不调这个了 String token = getToken(); JSONObject json1 = JSONObject.parseObject(token); @@ -662,9 +723,28 @@ } } log.error("-----Reimbursement-------------strRes的值为:{}", strRes); JSONObject jsonObject = JSONObject.parseObject(strRes); if (strRes == null || strRes.trim().isEmpty()) { // 医院协友系统无返回(超时/异常/未配置):推送失败,由调用方回滚整个审批 log.error("差旅审批单上传医院协友系统失败:接口无返回内容,id={}", serviceReimbursement.getId()); return false; } JSONObject jsonObject = null; try { jsonObject = JSONObject.parseObject(strRes); } catch (Exception e) { log.error("差旅审批单上传医院协友系统失败:返回内容无法解析,id={},strRes={}", serviceReimbursement.getId(), strRes, e); return false; } if (jsonObject == null) { log.error("差旅审批单上传医院协友系统失败:返回内容为空,id={},strRes={}", serviceReimbursement.getId(), strRes); return false; } String code = jsonObject.getString("code"); if (!code.equals("0")) { if (code == null || !"0".equals(code)) { log.error("差旅审批单上传医院协友系统失败:code={},id={},strRes={}", code, serviceReimbursement.getId(), strRes); return false; } @@ -876,7 +956,7 @@ Map<String, Object> map = new HashMap<String, Object>(); map.put("userName", "opo"); map.put("password", "4126407a-9821-4874-be41-6568abd6dbe5"); map.put("loginName", "OPO系统"); map.put("loginName", "OPO系统审批"); JSONObject jsonObj = new JSONObject(map); ruoyi-project/src/main/java/com/ruoyi/project/service/impl/ServiceRelativesconfirmationServiceImpl.java
@@ -26,6 +26,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import com.ruoyi.common.utils.StringUtils; @@ -221,6 +222,23 @@ relativeConfirmationVO.setReporterno(user.getUserName()); } List<RelativeConfirmationVO> relativeConfirmationVOS = serviceRelativesconfirmationMapper.selectVOList(relativeConfirmationVO); // 一次性取出各捐献基础对应的死亡时间,避免在循环里按 InfoID 逐条查见证表(N+1) List<Long> infoIds = new ArrayList<>(); for (RelativeConfirmationVO item : relativeConfirmationVOS) { if (item.getInfoid() != null) { infoIds.add(item.getInfoid()); } } Map<Long, Date> deathTimeMap = new HashMap<>(); if (!infoIds.isEmpty()) { for (ServiceDonationwitness witness : serviceDonationwitnessMapper.selectDeathTimeByInfoIds(infoIds)) { if (witness.getInfoid() != null && !deathTimeMap.containsKey(witness.getInfoid())) { deathTimeMap.put(witness.getInfoid(), witness.getDeathtime()); } } } for (RelativeConfirmationVO relativeConfirmationVO1 : relativeConfirmationVOS) { //先给个年龄默认值(因为age是数字类型,不能放横杠,所以就所横扛放到单位上) relativeConfirmationVO1.setAgeunit("-"); @@ -228,12 +246,8 @@ relativeConfirmationVO1.setAge2(null); //获取死亡时间,如果获取见证里有死亡时间,则进行计算他的年龄 ServiceDonationwitness sdw = new ServiceDonationwitness(); sdw.setInfoid(relativeConfirmationVO1.getInfoid()); List<ServiceDonationwitness> serviceDonationwitnessList = serviceDonationwitnessMapper.selectServiceDonationwitnessList(sdw); if (!CollectionUtils.isEmpty(serviceDonationwitnessList) && relativeConfirmationVO1.getBirthday() != null) { Date deathtime = serviceDonationwitnessList.get(0).getDeathtime(); if (ObjectUtils.isNotEmpty(deathtime)) { Date deathtime = deathTimeMap.get(relativeConfirmationVO1.getInfoid()); if (ObjectUtils.isNotEmpty(deathtime) && relativeConfirmationVO1.getBirthday() != null) { Map<String, String> map = CalculateDateUtils.calculateAge(relativeConfirmationVO1.getBirthday().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), deathtime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate()); if (ObjectUtils.isEmpty(map)) { log.error("RelativeConfirmationVO出生日期:{},RelativeConfirmationVO死亡日期:{}", relativeConfirmationVO1.getBirthday(), deathtime); @@ -243,7 +257,6 @@ relativeConfirmationVO1.setAgeunit(map.get("ageUnit")); relativeConfirmationVO1.setAge2(org.apache.commons.lang3.ObjectUtils.isNotEmpty(map.get("age2")) ? Long.valueOf(map.get("age2")) : null); relativeConfirmationVO1.setAgeunit2(map.get("ageUnit2")); } } } return relativeConfirmationVOS; ruoyi-project/src/main/resources/mapper/project/ServiceDonationwitnessMapper.xml
@@ -111,6 +111,23 @@ </where> </select> <!-- 批量查询「捐献基础ID -> 死亡时间」,供列表页计算年龄使用。 代替原先在记录循环中按 InfoID 逐条查询的 N+1 写法(首页有 N 条记录就发 N 次 SQL)。 只返回 InfoID 与 DeathTime 两列;Infoid 与 DeathTime 均为空的行无意义,直接过滤, 同时避免与 selectServiceDonationwitnessList 返回的行数不一致。 --> <select id="selectDeathTimeByInfoIds" resultMap="ServiceDonationwitnessResult"> select InfoID, DeathTime from service_donationwitness where InfoID is not null and DeathTime is not null <if test="infoIds != null and infoIds.size() > 0"> and InfoID in <foreach collection="infoIds" item="infoId" open="(" separator="," close=")"> #{infoId} </foreach> </if> </select> <select id="selectVOList" resultType="com.ruoyi.project.domain.vo.DonationWitnessVO"> SELECT `service_donatebaseinfo`.`ID` AS `ID`, ruoyi-project/src/main/resources/mapper/project/ServiceExternalpersonMapper.xml
@@ -43,7 +43,7 @@ service_externalperson.del_flag = 0 <if test="userno != null and userno != ''">and UserNo = #{userno}</if> <if test="username != null and username != ''">and UserName like concat('%', #{username}, '%')</if> <if test="usertype != null and usertype != ''">and UserType = #{usertype}</if> <if test="usertype != null and usertype != ''">and FIND_IN_SET(#{usertype}, UserType)</if> <if test="sex != null and sex != ''">and Sex = #{sex}</if> <if test="telephone != null and telephone != ''">and Telephone = #{telephone}</if> <if test="address != null and address != ''">and Address = #{address}</if> @@ -59,7 +59,7 @@ <select id="getAllpeople" resultType="com.ruoyi.project.domain.ServiceExternalperson"> <include refid="selectServiceExternalpersonVo"/> where service_externalperson.del_flag = 0 and UserType = #{usertype} where service_externalperson.del_flag = 0 and FIND_IN_SET(#{usertype}, UserType) </select> <select id="getInfoByUserNo" resultType="com.ruoyi.project.domain.ServiceExternalperson"> <include refid="selectServiceExternalpersonVo"/> ruoyi-project/src/main/resources/mapper/project/ServiceFunddetailMapper.xml
@@ -20,6 +20,7 @@ <result property="unitname" column="UnitName"/> <result property="unitno" column="UnitNo"/> <result property="unituserno" column="UnitUserNo"/> <result property="isunit" column="IsUnit"/> <result property="title" column="Title"/> <result property="idcardtype" column="IDCardType"/> <result property="idcardno" column="IDCardNo"/> @@ -83,6 +84,7 @@ UnitName, UnitNo, UnitUserNo, IsUnit, Title, OrderNo, ItemCode, @@ -206,6 +208,7 @@ a.UnitName, a.UnitNo, a.UnitUserNo, a.IsUnit, a.Title, a.OrderNo, a.ItemCode, ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
@@ -2,6 +2,7 @@ import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.bean.DtoConversionUtils; import com.ruoyi.project.common.FundNotifyMessageBuilder; import com.ruoyi.project.domain.*; import com.ruoyi.project.domain.vo.DingTalkReqVo; import com.ruoyi.project.service.*; @@ -563,6 +564,14 @@ } /** * 财务系统驳回信息钉钉通知(定时任务用)。 * * @deprecated 2026-10-08 核实:本方法**已无调用方**(原调用点在本类中已注释), * 且 {@code sys_job} 中没有任何任务指向它,属于死代码。 * 与"钉钉失败补偿/重试"无关,请勿据此认为存在补偿机制。保留仅为避免误删历史逻辑。 */ @Deprecated public void sendMeg(String[] split, String phone, String applyType, Integer fundType, Long fundId) throws ApiException { String content = null; String time = null; @@ -607,7 +616,7 @@ map.put("意见:" , content); contentList.add(map); DingTalkReqVo dingTalkReqVo = new DingTalkReqVo(); dingTalkReqVo.setTitle("财务系统驳回信息"); dingTalkReqVo.setTitle(FundNotifyMessageBuilder.TITLE); dingTalkReqVo.setNumber(phone); dingTalkReqVo.setContents(contentList); log.info("钉钉发送消息:{}" , dingTalkReqVo);