From 51b050bd4c5a7dfc824fdaa1fbb37a83bad69959 Mon Sep 17 00:00:00 2001 From: lianlonggang Date: Fri, 4 Sep 2026 18:54:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=85=A8=E9=9D=A2=E5=AF=B9=E9=BD=90?= =?UTF-8?q?=E5=8E=9F=20hospitalmiddle=20=E5=87=BA=E5=8F=82=E5=A5=91?= =?UTF-8?q?=E7=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Result 对齐旧结构 {"success","msg","data"}(移除 code 体系,异常统一 error(msg)) - nullAsWriteable=true:VO 序列化保留 null 字段(对齐 Jackson 默认) - getPeStatus/getExamListByDate 强类型化(PeStatusPhyVo/ExamListVo,契约不变) - getResultByPeId/getResultByIdcardAndYearAll 补报告组装(hospitalId/结论/建议/item子表) - bsm SQL 换回旧视图(V_PHYEXAM_PE_STATUS/V_PHYEXAM_PE_PERSONAL_ITEM),修复 PE_TRANSFER_HOSPITAL 列缺失与 peItemList 字段差异 - OkHttp → JDK HttpClient;shade 过滤重叠资源;排除重复 mybatis-plus-core 3.5.5 Co-Authored-By: Claude Code --- .gitignore | 2 +- pom.xml | 30 +- .../front/adapter/BsmAdapterBase.java | 48 +- .../front/adapter/HospitalAdapter.java | 79 +-- .../hospital/front/adapter/NxAdapterBase.java | 48 +- .../hospital/front/adapter/YaAdapterBase.java | 55 +- .../hospital/front/api/admin/AdminApi.java | 6 +- .../hospital/front/api/order/OrderApi.java | 121 +--- .../java/com/hospital/front/dto/Result.java | 121 +--- .../com/hospital/front/infra/ApiScanner.java | 8 +- .../infra/exception/BusinessException.java | 33 +- .../exception/GlobalExceptionHandler.java | 18 +- .../hospital/front/infra/util/JsonUtils.java | 42 ++ .../front/mapper/bsm/BsmOrderMapper.java | 41 +- .../front/mapper/nx/NxOrderMapper.java | 75 +-- .../front/mapper/ya/YaOrderMapper.java | 75 +-- .../hospital/front/service/OrderService.java | 249 +++----- .../hospital/front/task/UptimeKumaTask.java | 29 +- .../com/hospital/front/vo/ConclusionVo.java | 22 + .../com/hospital/front/vo/ExamListVo.java | 25 + .../com/hospital/front/vo/PeStatusPhyVo.java | 22 + .../com/hospital/front/vo/PeStatusVo.java | 29 + .../java/com/hospital/front/vo/SuggestVo.java | 18 + src/main/resources/app.yml | 4 + .../front/mapper/bsm/BsmOrderMapper.xml | 593 ++++++++---------- .../front/mapper/nx/NxOrderMapper.xml | 80 +-- .../front/mapper/ya/YaOrderMapper.xml | 72 +-- 27 files changed, 791 insertions(+), 1154 deletions(-) create mode 100644 src/main/java/com/hospital/front/infra/util/JsonUtils.java create mode 100644 src/main/java/com/hospital/front/vo/ConclusionVo.java create mode 100644 src/main/java/com/hospital/front/vo/ExamListVo.java create mode 100644 src/main/java/com/hospital/front/vo/PeStatusPhyVo.java create mode 100644 src/main/java/com/hospital/front/vo/PeStatusVo.java create mode 100644 src/main/java/com/hospital/front/vo/SuggestVo.java diff --git a/.gitignore b/.gitignore index d18a342..36c69f0 100644 --- a/.gitignore +++ b/.gitignore @@ -54,4 +54,4 @@ mvnw.cmd # JDK *.jdk -*.jre \ No newline at end of file +*.jredist/ diff --git a/pom.xml b/pom.xml index df8fb12..a968101 100644 --- a/pom.xml +++ b/pom.xml @@ -79,6 +79,14 @@ org.noear mybatis-plus-solon-plugin + + + + com.baomidou + mybatis-plus-core + + com.baomidou @@ -111,15 +119,8 @@ - sqlite-jdbc:原为 B 端 Agent 用,Agent 已拆分为独立 Python 项目 - h2:开发 Mock 数据源,需要时本地临时加回 - sa-token-solon-plugin:鉴权已改为 OrderApi 手写 HTTP Basic + - okhttp:UptimeKuma 心跳已改用 JDK 内置 java.net.http.HttpClient --> - - - - com.squareup.okhttp3 - okhttp - - - org.noear snack3 @@ -134,7 +135,7 @@ - hospital-front-${project.version} + hospital-front @@ -163,10 +164,19 @@ META-INF/*.SF META-INF/*.DSA META-INF/*.RSA + + module-info.class + META-INF/versions/*/module-info.class + + META-INF/solon/solon-configuration-metadata.json + META-INF/native-image/** + META-INF/LICENSE + META-INF/MANIFEST.MF - hospital-front-${project.version} + hospital-front diff --git a/src/main/java/com/hospital/front/adapter/BsmAdapterBase.java b/src/main/java/com/hospital/front/adapter/BsmAdapterBase.java index 9280503..161b05a 100644 --- a/src/main/java/com/hospital/front/adapter/BsmAdapterBase.java +++ b/src/main/java/com/hospital/front/adapter/BsmAdapterBase.java @@ -1,5 +1,11 @@ package com.hospital.front.adapter; +import com.hospital.front.vo.ConclusionVo; +import com.hospital.front.vo.ExamListVo; +import com.hospital.front.vo.MedicalMiddleResultVo; +import com.hospital.front.vo.PeStatusVo; +import com.hospital.front.vo.SuggestVo; + import com.hospital.front.dto.ProcResult; import com.hospital.front.dto.Result; import com.hospital.front.mapper.bsm.BsmOrderMapper; @@ -32,7 +38,7 @@ public abstract class BsmAdapterBase implements HospitalAdapter { try { return Result.success(mapper.ping() == 1); } catch (Exception e) { - return Result.error(Result.CODE_DB_UNREACHABLE, "数据库连接失败:" + e.getMessage()); + return Result.error("数据库连接失败:" + e.getMessage()); } } @@ -87,7 +93,7 @@ public abstract class BsmAdapterBase implements HospitalAdapter { } @Override - public List> getPhyexamStatus(String peIds) { + public List getPhyexamStatus(String peIds) { return mapper.getPhyexamStatus(peIds); } @@ -122,65 +128,45 @@ public abstract class BsmAdapterBase implements HospitalAdapter { } @Override - public List> getConclusion(String peId) { - return mapper.getConclusion(peId); - } - - @Override - public List> getConclusionAll(String peId) { + public List getConclusionAll(String peId) { return mapper.getConclusionAll(peId); } @Override - public List> getSuggest(String peId) { - return mapper.getSuggest(peId); - } - - @Override - public List> getSuggestAll(String peId) { + public List getSuggestAll(String peId) { return mapper.getSuggestAll(peId); } @Override - public Map getPeStatusByIdnoAndYear(String idNo, String year) { + public PeStatusVo getPeStatusByIdnoAndYear(String idNo, String year) { return mapper.getPeStatusByIdnoAndYear(idNo, year); } @Override - public List> getResultByIdcardAndYear(String idNo, String year) { + public List getResultByIdcardAndYear(String idNo, String year) { return mapper.getResultByIdcardAndYear(idNo, year); } @Override - public List> getResultByIdcardAndYearAll(String idNo, String year) { + public List getResultByIdcardAndYearAll(String idNo, String year) { return mapper.getResultByIdcardAndYearAll(idNo, year); } @Override - public List> getResultByPeId(String peId) { + public List getResultByPeId(String peId) { return mapper.getResultByPeId(peId); } @Override - public List> getDisResultByAuditDate(String auditDate) { - return mapper.getDisResultByAuditDate(auditDate); - } - - @Override - public List> getItemByPeId(String peId) { + public List getItemByPeId(String peId) { return mapper.getItemByPeId(peId); } @Override - public List> getItemByPeIdAll(String peId) { + public List getItemByPeIdAll(String peId) { return mapper.getItemByPeIdAll(peId); } - @Override - public List> getResultByIdNoOrPeId(String idNo, String peId, String auditYear) { - return mapper.getResultByIdNoOrPeId(idNo, peId, auditYear); - } - @Override public Map getPeIdAndDateByIdcard(String idNo) { return mapper.getPeIdAndDateByIdcard(idNo); @@ -192,7 +178,7 @@ public abstract class BsmAdapterBase implements HospitalAdapter { } @Override - public List> getExamListByDate(String auditDate) { + public List getExamListByDate(String auditDate) { return mapper.getExamListByDate(auditDate); } diff --git a/src/main/java/com/hospital/front/adapter/HospitalAdapter.java b/src/main/java/com/hospital/front/adapter/HospitalAdapter.java index 7f50282..7ee953b 100644 --- a/src/main/java/com/hospital/front/adapter/HospitalAdapter.java +++ b/src/main/java/com/hospital/front/adapter/HospitalAdapter.java @@ -1,5 +1,11 @@ package com.hospital.front.adapter; +import com.hospital.front.vo.ConclusionVo; +import com.hospital.front.vo.ExamListVo; +import com.hospital.front.vo.MedicalMiddleResultVo; +import com.hospital.front.vo.PeStatusVo; +import com.hospital.front.vo.SuggestVo; + import com.hospital.front.dto.ProcResult; import com.hospital.front.dto.Result; import com.hospital.front.vo.UnitVo; @@ -8,93 +14,76 @@ import java.util.List; import java.util.Map; /** - * 医院适配器接口(策略模式)。 + * 医院适配器接口(各医院方言实现:bsm/nx/ya)。 * - * 5 家医院各自实现本接口,通过 HospitalRouter 按医院编码路由。 - * 所有数据库差异(Oracle/SqlServer 方言、存储过程名)均封装在实现内; - * 存储过程的入参出参契约由医院 HIS 系统约定,不可修改。 - * - * 查询类方法统一返回 Map 列表(列名与医院视图/存储过程保持一致)。 + * getConclusion/getSuggest 与其 All 版 SQL 完全重复,已合并为 All 版 + * (对外接口路径 /getConclusion、/getSuggest 保留,内部走 All 版)。 */ public interface HospitalAdapter { - /** 医院编码(拼音):xinglongyuan / qingyang / ningxia / yanan / jinghe / dev */ + /** 医院编码(唯一,如 jinghe) */ String code(); - /** 医院中文名(日志与展示用) */ + /** 医院显示名 */ String displayName(); - /** Mapper 方言类型:bsm(Oracle)/ nx / ya(SqlServer) */ + /** 医院方言类型(bsm/nx/ya) */ String hmType(); - /** 轻量健康检查(SELECT 1 探测) */ + /** 数据库健康检查 */ Result healthCheck(); - // ================= 存储过程(写) ================= - - /** 提交预约(P_ADD_PE_REGIST) */ + /** 提交预约(存储过程) */ ProcResult saveOrder(String peInfoStr, String peItemStr); - /** 取消预约(P_DEL_PE_REGIST) */ + /** 取消预约(存储过程) */ ProcResult cancelOrder(String peId, String name, String idcard); - /** 添加/修改单位(P_ADD_UNIT) */ + /** 添加/修改单位(存储过程,V1/V2 参数不同) */ ProcResult addUnit(UnitVo unit, boolean useV2); - // ================= 查询(视图) ================= + /** 体检状态查询(多个 peId 逗号分隔) */ + List getPhyexamStatus(String peIds); - /** 按体检预约 ID(逗号分隔多个)查询体检状态 */ - List> getPhyexamStatus(String peIds); - - /** 医院所有体检项目(组合项) */ + /** 体检项目查询 */ List> getItemList(); - /** 医院所有体检项目及指标项 */ + /** 体检指标项及体检组合数据 */ List> getAllItemList(); - /** 医院所有体检指标项 */ + /** 体检指标项数据 */ List> getPeItemList(); - /** 按指标项 CODE 查询所属体检组合 */ + /** 按体检指标项查所属组合 */ List> getItemInfo(String peItemCode); /** 员工体检项目 */ List> getEmpItem(String peId); - /** 员工体检结果 */ + /** 按体检编号查体检结果 */ List> getResult(String peId); - /** 体检结论(列表 / 全量) */ - List> getConclusion(String peId); + /** 体检结论(列表) */ + List getConclusionAll(String peId); - List> getConclusionAll(String peId); - - /** 体检建议(列表 / 全量) */ - List> getSuggest(String peId); - - List> getSuggestAll(String peId); + /** 体检建议(全量,内部组装用) */ + List getSuggestAll(String peId); /** 按身份证号 + 年份查询体检状态 */ - Map getPeStatusByIdnoAndYear(String idNo, String year); + PeStatusVo getPeStatusByIdnoAndYear(String idNo, String year); /** 按身份证号 + 年份查询体检结果(默认 / 全量) */ - List> getResultByIdcardAndYear(String idNo, String year); + List getResultByIdcardAndYear(String idNo, String year); - List> getResultByIdcardAndYearAll(String idNo, String year); + List getResultByIdcardAndYearAll(String idNo, String year); /** 按体检编号查询体检结果 */ - List> getResultByPeId(String peId); - - /** 按审核日期查询体检报告(去重主表) */ - List> getDisResultByAuditDate(String auditDate); + List getResultByPeId(String peId); /** 按体检编号查询体检项目子表(默认 / 全量) */ - List> getItemByPeId(String peId); + List getItemByPeId(String peId); - List> getItemByPeIdAll(String peId); - - /** 按身份证号或体检编号 + 审核年份查询体检结果 */ - List> getResultByIdNoOrPeId(String idNo, String peId, String auditYear); + List getItemByPeIdAll(String peId); /** 按身份证号查询当年 peId 与预约日期(单条 / 列表) */ Map getPeIdAndDateByIdcard(String idNo); @@ -102,5 +91,5 @@ public interface HospitalAdapter { List> getPeIdAndDateByIdcardList(String idNo); /** 按审核日期查询当天体检人员列表(去重;日期空则当天) */ - List> getExamListByDate(String auditDate); + List getExamListByDate(String auditDate); } diff --git a/src/main/java/com/hospital/front/adapter/NxAdapterBase.java b/src/main/java/com/hospital/front/adapter/NxAdapterBase.java index 2b5774c..7a7bcc3 100644 --- a/src/main/java/com/hospital/front/adapter/NxAdapterBase.java +++ b/src/main/java/com/hospital/front/adapter/NxAdapterBase.java @@ -1,5 +1,11 @@ package com.hospital.front.adapter; +import com.hospital.front.vo.ConclusionVo; +import com.hospital.front.vo.ExamListVo; +import com.hospital.front.vo.MedicalMiddleResultVo; +import com.hospital.front.vo.PeStatusVo; +import com.hospital.front.vo.SuggestVo; + import com.hospital.front.dto.ProcResult; import com.hospital.front.dto.Result; import com.hospital.front.mapper.nx.NxOrderMapper; @@ -31,7 +37,7 @@ public abstract class NxAdapterBase implements HospitalAdapter { try { return Result.success(mapper.ping() == 1); } catch (Exception e) { - return Result.error(Result.CODE_DB_UNREACHABLE, "数据库连接失败:" + e.getMessage()); + return Result.error("数据库连接失败:" + e.getMessage()); } } @@ -83,7 +89,7 @@ public abstract class NxAdapterBase implements HospitalAdapter { } @Override - public List> getPhyexamStatus(String peIds) { + public List getPhyexamStatus(String peIds) { return mapper.getPhyexamStatus(peIds); } @@ -118,65 +124,45 @@ public abstract class NxAdapterBase implements HospitalAdapter { } @Override - public List> getConclusion(String peId) { - return mapper.getConclusion(peId); - } - - @Override - public List> getConclusionAll(String peId) { + public List getConclusionAll(String peId) { return mapper.getConclusionAll(peId); } @Override - public List> getSuggest(String peId) { - return mapper.getSuggest(peId); - } - - @Override - public List> getSuggestAll(String peId) { + public List getSuggestAll(String peId) { return mapper.getSuggestAll(peId); } @Override - public Map getPeStatusByIdnoAndYear(String idNo, String year) { + public PeStatusVo getPeStatusByIdnoAndYear(String idNo, String year) { return mapper.getPeStatusByIdnoAndYear(idNo, year); } @Override - public List> getResultByIdcardAndYear(String idNo, String year) { + public List getResultByIdcardAndYear(String idNo, String year) { return mapper.getResultByIdcardAndYear(idNo, year); } @Override - public List> getResultByIdcardAndYearAll(String idNo, String year) { + public List getResultByIdcardAndYearAll(String idNo, String year) { return mapper.getResultByIdcardAndYearAll(idNo, year); } @Override - public List> getResultByPeId(String peId) { + public List getResultByPeId(String peId) { return mapper.getResultByPeId(peId); } @Override - public List> getDisResultByAuditDate(String auditDate) { - return mapper.getDisResultByAuditDate(auditDate); - } - - @Override - public List> getItemByPeId(String peId) { + public List getItemByPeId(String peId) { return mapper.getItemByPeId(peId); } @Override - public List> getItemByPeIdAll(String peId) { + public List getItemByPeIdAll(String peId) { return mapper.getItemByPeIdAll(peId); } - @Override - public List> getResultByIdNoOrPeId(String idNo, String peId, String auditYear) { - return mapper.getResultByIdNoOrPeId(idNo, peId, auditYear); - } - @Override public Map getPeIdAndDateByIdcard(String idNo) { return mapper.getPeIdAndDateByIdcard(idNo); @@ -188,7 +174,7 @@ public abstract class NxAdapterBase implements HospitalAdapter { } @Override - public List> getExamListByDate(String auditDate) { + public List getExamListByDate(String auditDate) { return mapper.getExamListByDate(auditDate); } diff --git a/src/main/java/com/hospital/front/adapter/YaAdapterBase.java b/src/main/java/com/hospital/front/adapter/YaAdapterBase.java index a9f3484..f4f2c1d 100644 --- a/src/main/java/com/hospital/front/adapter/YaAdapterBase.java +++ b/src/main/java/com/hospital/front/adapter/YaAdapterBase.java @@ -1,5 +1,11 @@ package com.hospital.front.adapter; +import com.hospital.front.vo.ConclusionVo; +import com.hospital.front.vo.ExamListVo; +import com.hospital.front.vo.MedicalMiddleResultVo; +import com.hospital.front.vo.PeStatusVo; +import com.hospital.front.vo.SuggestVo; + import com.hospital.front.dto.ProcResult; import com.hospital.front.dto.Result; import com.hospital.front.mapper.ya.YaOrderMapper; @@ -31,7 +37,7 @@ public abstract class YaAdapterBase implements HospitalAdapter { try { return Result.success(mapper.ping() == 1); } catch (Exception e) { - return Result.error(Result.CODE_DB_UNREACHABLE, "数据库连接失败:" + e.getMessage()); + return Result.error("数据库连接失败:" + e.getMessage()); } } @@ -64,6 +70,7 @@ public abstract class YaAdapterBase implements HospitalAdapter { @Override public ProcResult addUnit(UnitVo unit, boolean useV2) { + // 延安医院仅有 V1 存储过程(对齐旧项目 YaOrderMapper),useV2 忽略统一走 V1 Map map = new HashMap<>(); map.put("unitCode", unit.getUnitCode()); map.put("unitName", unit.getUnitName()); @@ -73,11 +80,7 @@ public abstract class YaAdapterBase implements HospitalAdapter { map.put("phone1", unit.getPhone1()); map.put("connecter2", unit.getConnecter2()); map.put("phone2", unit.getPhone2()); - if (useV2) { - mapper.addUnitV2(map); - } else { - mapper.addUnit(map); - } + mapper.addUnit(map); return new ProcResult( str(map.get("resultCode")), str(map.get("errorMsg")), @@ -86,7 +89,7 @@ public abstract class YaAdapterBase implements HospitalAdapter { } @Override - public List> getPhyexamStatus(String peIds) { + public List getPhyexamStatus(String peIds) { return mapper.getPhyexamStatus(peIds); } @@ -121,65 +124,45 @@ public abstract class YaAdapterBase implements HospitalAdapter { } @Override - public List> getConclusion(String peId) { - return mapper.getConclusion(peId); - } - - @Override - public List> getConclusionAll(String peId) { + public List getConclusionAll(String peId) { return mapper.getConclusionAll(peId); } @Override - public List> getSuggest(String peId) { - return mapper.getSuggest(peId); - } - - @Override - public List> getSuggestAll(String peId) { + public List getSuggestAll(String peId) { return mapper.getSuggestAll(peId); } @Override - public Map getPeStatusByIdnoAndYear(String idNo, String year) { + public PeStatusVo getPeStatusByIdnoAndYear(String idNo, String year) { return mapper.getPeStatusByIdnoAndYear(idNo, year); } @Override - public List> getResultByIdcardAndYear(String idNo, String year) { + public List getResultByIdcardAndYear(String idNo, String year) { return mapper.getResultByIdcardAndYear(idNo, year); } @Override - public List> getResultByIdcardAndYearAll(String idNo, String year) { + public List getResultByIdcardAndYearAll(String idNo, String year) { return mapper.getResultByIdcardAndYearAll(idNo, year); } @Override - public List> getResultByPeId(String peId) { + public List getResultByPeId(String peId) { return mapper.getResultByPeId(peId); } @Override - public List> getDisResultByAuditDate(String auditDate) { - return mapper.getDisResultByAuditDate(auditDate); - } - - @Override - public List> getItemByPeId(String peId) { + public List getItemByPeId(String peId) { return mapper.getItemByPeId(peId); } @Override - public List> getItemByPeIdAll(String peId) { + public List getItemByPeIdAll(String peId) { return mapper.getItemByPeIdAll(peId); } - @Override - public List> getResultByIdNoOrPeId(String idNo, String peId, String auditYear) { - return mapper.getResultByIdNoOrPeId(idNo, peId, auditYear); - } - @Override public Map getPeIdAndDateByIdcard(String idNo) { return mapper.getPeIdAndDateByIdcard(idNo); @@ -191,7 +174,7 @@ public abstract class YaAdapterBase implements HospitalAdapter { } @Override - public List> getExamListByDate(String auditDate) { + public List getExamListByDate(String auditDate) { return mapper.getExamListByDate(auditDate); } diff --git a/src/main/java/com/hospital/front/api/admin/AdminApi.java b/src/main/java/com/hospital/front/api/admin/AdminApi.java index 407c85e..72525bd 100644 --- a/src/main/java/com/hospital/front/api/admin/AdminApi.java +++ b/src/main/java/com/hospital/front/api/admin/AdminApi.java @@ -53,7 +53,7 @@ public class AdminApi { private void checkToken(Context ctx) { String expected = Solon.cfg().get("admin.token", ""); if (expected != null && !expected.trim().isEmpty() && !expected.equals(ctx.header("X-Admin-Token"))) { - throw BusinessException.of(Result.CODE_AUTH_FAILED, "管理接口鉴权失败"); + throw BusinessException.of("管理接口鉴权失败"); } } @@ -66,12 +66,12 @@ public class AdminApi { Runtime mem = Runtime.getRuntime(); Result db = router.active().healthCheck(); Map out = new LinkedHashMap<>(); - out.put("status", db.getCode() == 0 ? "UP" : "DEGRADED"); + out.put("status", db.isSuccess() ? "UP" : "DEGRADED"); out.put("hospital", router.activeCode()); out.put("hospitalName", router.active().displayName()); out.put("registeredHospitals", router.registeredCodes()); Map database = new HashMap<>(); - database.put("ok", db.getCode() == 0); + database.put("ok", db.isSuccess()); database.put("msg", db.getMsg()); out.put("database", database); Map jvm = new HashMap<>(); diff --git a/src/main/java/com/hospital/front/api/order/OrderApi.java b/src/main/java/com/hospital/front/api/order/OrderApi.java index 62a0cb1..52d4aca 100644 --- a/src/main/java/com/hospital/front/api/order/OrderApi.java +++ b/src/main/java/com/hospital/front/api/order/OrderApi.java @@ -1,6 +1,7 @@ package com.hospital.front.api.order; -import java.util.ArrayList; +import com.hospital.front.vo.MedicalMiddleResultVo; + import java.util.Base64; import java.util.List; import java.util.Map; @@ -14,13 +15,14 @@ import org.noear.solon.annotation.Path; import org.noear.solon.core.handle.Context; import org.noear.solon.core.handle.MethodType; import org.noear.solon.Solon; -import org.noear.snack.ONode; import com.hospital.front.dto.Result; import com.hospital.front.infra.annotation.ApiMeta; import com.hospital.front.infra.annotation.ApiParam; import com.hospital.front.infra.exception.BusinessException; import com.hospital.front.service.OrderService; +import com.hospital.front.vo.ExamListVo; +import com.hospital.front.vo.PeStatusPhyVo; /** * 体检预约业务接口,路径前缀 /order。 @@ -74,7 +76,7 @@ public class OrderApi { // 认证失败:401 + 质询头(对齐 Sa-Token SaBasicUtil.check 的响应行为) ctx.status(401); ctx.headerSet("WWW-Authenticate", "Basic realm=\"hospital-front\""); - throw BusinessException.of(Result.CODE_AUTH_FAILED, "Basic 认证失败"); + throw BusinessException.of("Basic 认证失败"); } /** 恒定时间字符串比较(防时序攻击) */ @@ -91,12 +93,10 @@ public class OrderApi { @ApiParam(name = "body", desc = "预约 JSON 体") }) @Mapping(value = "/saveOrder", method = {MethodType.POST}) - public Result saveOrder(Context ctx, @Body String body) { + public Result saveOrder(Context ctx, @Body com.hospital.front.vo.OrderV2Vo body) { checkBasic(ctx); - // Solon 对 Map 泛型 body 反序列化支持不佳,用 snack3 手动解析 - @SuppressWarnings("unchecked") - Map map = (Map) ONode.load(body).toObject(Map.class); - return Result.success(service.saveOrder(map)); + // 强类型 DTO 直收(Solon 对 DTO 反序列化无问题),避免 Map 中转 + return Result.success(service.saveOrder(body)); } /** 5. 取消体检预约 */ @@ -123,7 +123,7 @@ public class OrderApi { @ApiParam(name = "peIds", desc = "体检编号逗号分隔") }) @Mapping("/getPeStatus/{peIds}") - public Result>> getPeStatus(Context ctx, @Path("peIds") String peIds) { + public Result> getPeStatus(Context ctx, @Path("peIds") String peIds) { checkBasic(ctx); return Result.success(service.getPhyexamStatus(peIds)); } @@ -197,58 +197,14 @@ public class OrderApi { return Result.success(service.getResult(peId)); } - /** 9. 体检结论(汇总) */ - @ApiMeta(desc = "体检结论(汇总)", params = { - @ApiParam(name = "peId", desc = "体检编号") - }) - @Mapping("/getTotalConclusion/{peId}") - public Result> getTotalConclusion(Context ctx, @Path("peId") String peId) { - checkBasic(ctx); - return Result.success(service.getTotalConclusion(peId)); - } - - /** 10. 体检建议(汇总) */ - @ApiMeta(desc = "体检建议(汇总)", params = { - @ApiParam(name = "peId", desc = "体检编号") - }) - @Mapping("/getTotalSuggest/{peId}") - public Result> getTotalSuggest(Context ctx, @Path("peId") String peId) { - checkBasic(ctx); - return Result.success(service.getTotalSuggest(peId)); - } - - /** 11. 体检结论(列表) */ - @ApiMeta(desc = "体检结论(列表)", params = { - @ApiParam(name = "peId", desc = "体检编号") - }) - @Mapping("/getConclusion/{peId}") - public Result>> getConclusion(Context ctx, @Path("peId") String peId) { - checkBasic(ctx); - return Result.success(service.getConclusion(peId)); - } - - /** 12. 体检建议(列表) */ - @ApiMeta(desc = "体检建议(列表)", params = { - @ApiParam(name = "peId", desc = "体检编号") - }) - @Mapping("/getSuggest/{peId}") - public Result>> getSuggest(Context ctx, @Path("peId") String peId) { - checkBasic(ctx); - return Result.success(service.getSuggest(peId)); - } + // 9/10/11/12(体检结论/建议 汇总与列表)不再对外暴露:结论/建议仅作为 + // 体检报告的组成部分在应用层组装,相关查询(getConclusionAll/getSuggestAll)为内部使用 // ================= 5. 按身份证 / 日期查询 ================= - /** 14. 根据身份证号及年份获取体检结果 */ - @ApiMeta(desc = "按身份证及年份查体检结果", params = { - @ApiParam(name = "idNo", desc = "身份证号"), - @ApiParam(name = "year", desc = "年份") - }) - @Mapping("/getResultByIdcardAndYear/{idNo}/{year}") - public Result>> getResultByIdcardAndYear(Context ctx, @Path("idNo") String idNo, @Path("year") String year) { - checkBasic(ctx); - return Result.success(service.getResultByIdcardAndYear(idNo, year)); - } + // 14(按身份证及年份查结果)/ 15.3(按审查日期查报告)/ 16(按身份证或编号+年份查报告) + // 不再对外暴露:相关查询为内部使用(如 getPeStatusByIdnoAndYear 的宁夏兜底) + // 14.1 全量版保留对外 /** 14.1 根据身份证号及年份获取体检结果(全量) */ @ApiMeta(desc = "按身份证及年份查全量结果", params = { @@ -256,7 +212,7 @@ public class OrderApi { @ApiParam(name = "year", desc = "年份") }) @Mapping("/getResultByIdcardAndYearAll/{idNo}/{year}") - public Result>> getResultByIdcardAndYearAll(Context ctx, @Path("idNo") String idNo, @Path("year") String year) { + public Result> getResultByIdcardAndYearAll(Context ctx, @Path("idNo") String idNo, @Path("year") String year) { checkBasic(ctx); return Result.success(service.getResultByIdcardAndYearAll(idNo, year)); } @@ -266,7 +222,7 @@ public class OrderApi { @ApiParam(name = "peId", desc = "体检编号") }) @Mapping("/getResultByPeId/{peId}") - public Result>> getResultByPeId(Context ctx, @Path("peId") String peId) { + public Result> getResultByPeId(Context ctx, @Path("peId") String peId) { checkBasic(ctx); return Result.success(service.getResultByPeId(peId)); } @@ -276,40 +232,11 @@ public class OrderApi { @ApiParam(name = "peId", desc = "体检编号") }) @Mapping("/getResultStatus/{peId}") - public Result>> getResultStatus(Context ctx, @Path("peId") String peId) { + public Result> getResultStatus(Context ctx, @Path("peId") String peId) { checkBasic(ctx); return Result.success(service.getResultByPeId(peId)); } - /** 15.3 根据 audit_date 查询当天的体检报告 */ - @ApiMeta(desc = "按审查日期查体检报告", params = { - @ApiParam(name = "auditDate", desc = "审查日期 yyyy-MM-dd") - }) - @Mapping("/getResultByAuditDate/{auditDate}") - public Result>> getResultByAuditDate(Context ctx, @Path("auditDate") String auditDate) { - checkBasic(ctx); - return Result.success(service.getResultByAuditDate(auditDate)); - } - - /** 16. 根据 id_code 或 pe_id 和审查年份查询体检报告 */ - @ApiMeta(desc = "按身份证或体检编号及年份查报告", params = { - @ApiParam(name = "idNo", desc = "身份证号(与 peId 二选一)"), - @ApiParam(name = "peId", desc = "体检编号(与 idNo 二选一)"), - @ApiParam(name = "auditYear", desc = "审查年份") - }) - @Mapping(value = "/getResultByIdNoOrPeId", method = {MethodType.POST}) - public Result>> getResultByIdNoOrPeId( - Context ctx, - @Param(value = "idNo", required = false) String idNo, - @Param(value = "peId", required = false) String peId, - @Param("auditYear") String auditYear) { - checkBasic(ctx); - if (isNullOrBlank(idNo) && isNullOrBlank(peId)) { - throw BusinessException.paramMissing("身份证号或体检编号"); - } - return Result.success(service.getResultByIdNoOrPeId(idNo, peId, auditYear)); - } - /** 17. 根据身份证号查询当前年的 peId 和预约日期 */ @ApiMeta(desc = "按身份证查当年 peId 和预约日期", params = { @ApiParam(name = "idNo", desc = "身份证号") @@ -339,16 +266,8 @@ public class OrderApi { @Mapping(value = "/addUnit", method = {MethodType.POST}) public Result addUnit(Context ctx, @Body String body) { checkBasic(ctx); - // Solon 对 List 泛型 body 反序列化支持不佳,此处用 snack3 手动解析 - List> units; - if (body == null || body.trim().isEmpty()) { - units = new ArrayList<>(); - } else { - @SuppressWarnings("unchecked") - List> parsed = (List>) ONode.load(body).toObject(List.class); - units = parsed; - } - String errors = service.addUnits(units); + // Solon 对 List 泛型 body 支持不佳,用 JsonUtils 统一解析(空串返回空列表) + String errors = service.addUnits(com.hospital.front.infra.util.JsonUtils.parseList(body)); return errors != null ? Result.error(errors) : Result.success(); } @@ -357,7 +276,7 @@ public class OrderApi { @ApiParam(name = "auditDate", desc = "审查日期(空则查当天)") }) @Mapping("/getExamListByDate") - public Result>> getExamListByDate(Context ctx, @Param("auditDate") String auditDate) { + public Result> getExamListByDate(Context ctx, @Param("auditDate") String auditDate) { checkBasic(ctx); return Result.success(service.getExamListByDate(auditDate)); } diff --git a/src/main/java/com/hospital/front/dto/Result.java b/src/main/java/com/hospital/front/dto/Result.java index 2812c83..f4551bf 100644 --- a/src/main/java/com/hospital/front/dto/Result.java +++ b/src/main/java/com/hospital/front/dto/Result.java @@ -1,114 +1,49 @@ package com.hospital.front.dto; +import lombok.Data; + /** * 统一 API 响应包装。 * - * 业务接口均使用此结构返回,便于前端统一处理。 + * 结构与原 hospitalmiddle 的 Result 保持一致(对外 JSON 契约,不可修改): + * {"success": true/false, "msg": "成功", "data": ...} * * @param 数据类型 - * @author hospital-front重构 */ +@Data public class Result { - /** 业务码(0=成功) */ - private final int code; + /** 是否成功 */ + private boolean success = false; /** 提示信息 */ - private final String msg; + private String msg; /** 业务数据 */ - private final T data; + private T data; - /** - * 全参构造器。 - * - * @param code 业务码(0=成功) - * @param msg 提示信息 - * @param data 业务数据(可为 null) - */ - public Result(int code, String msg, T data) { - this.code = code; - this.msg = msg; - this.data = data; + /** 成功响应(无数据),msg 固定"成功"(对齐原项目) */ + public static Result success() { + Result result = new Result(); + result.setSuccess(true); + result.setMsg("成功"); + return result; } - /** - * 两参构造器(data 默认为 null,与 Kotlin 默认参数语义一致)。 - * - * @param code 业务码 - * @param msg 提示信息 - */ - public Result(int code, String msg) { - this(code, msg, null); + /** 成功响应(带数据) */ + public static Result success(T t) { + Result result = new Result(); + result.setSuccess(true); + result.setMsg("成功"); + result.setData(t); + return result; } - /** 业务成功码 */ - public static final int SUCCESS_CODE = 0; - - /** 业务失败默认码 */ - public static final int ERROR_CODE = 5001; - - /** 参数缺失 */ - public static final int CODE_PARAM_MISSING = 1001; - - /** 参数格式错误 */ - public static final int CODE_PARAM_FORMAT = 1002; - - /** 业务校验失败 */ - public static final int CODE_BUSINESS = 1003; - - /** 存储过程调用失败 */ - public static final int CODE_PROC_FAILED = 2001; - - /** 数据库连接失败 */ - public static final int CODE_DB_UNREACHABLE = 2002; - - /** 医院系统返回业务失败 */ - public static final int CODE_HOSPITAL_FAILED = 2003; - - /** 鉴权失败 */ - public static final int CODE_AUTH_FAILED = 3001; - - /** Token 过期 */ - public static final int CODE_TOKEN_EXPIRED = 3002; - - /** - * 成功响应(无数据)。 - */ - public static Result success() { - return new Result<>(SUCCESS_CODE, "success", null); - } - - /** - * 成功响应。 - */ - public static Result success(T data) { - return new Result<>(SUCCESS_CODE, "success", data); - } - - /** - * 错误响应(默认错误码)。 - */ - public static Result error(String msg) { - return new Result<>(ERROR_CODE, msg, null); - } - - /** - * 错误响应(指定错误码)。 - */ - public static Result error(int code, String msg) { - return new Result<>(code, msg, null); - } - - public int getCode() { - return code; - } - - public String getMsg() { - return msg; - } - - public T getData() { - return data; + /** 错误响应 */ + public static Result error(String msg) { + Result result = new Result(); + result.setSuccess(false); + result.setMsg(msg); + return result; } } diff --git a/src/main/java/com/hospital/front/infra/ApiScanner.java b/src/main/java/com/hospital/front/infra/ApiScanner.java index 8e1d71a..b82aeec 100644 --- a/src/main/java/com/hospital/front/infra/ApiScanner.java +++ b/src/main/java/com/hospital/front/infra/ApiScanner.java @@ -58,11 +58,15 @@ public final class ApiScanner { // 拼接完整路径 String path = prefix + (methodMapping.value() == null ? "" : methodMapping.value()); - // HTTP 方法:method() 空数组视为 GET + // HTTP 方法:Solon @Mapping 不显式指定时 method() 返回 ALL(支持所有方法), + // 接口测试场景下默认按 GET 处理(OrderApi 的 GET 接口均未显式指定 method) String httpMethod = "GET"; MethodType[] mtypes = methodMapping.method(); if (mtypes != null && mtypes.length > 0) { - httpMethod = mtypes[0].name(); + String name = mtypes[0].name(); + if (!"ALL".equals(name) && !"UNKNOWN".equals(name)) { + httpMethod = name; + } } // @ApiMeta.params 转 name→desc 映射,供参数补充描述 diff --git a/src/main/java/com/hospital/front/infra/exception/BusinessException.java b/src/main/java/com/hospital/front/infra/exception/BusinessException.java index 3175fbe..bdb7d8d 100644 --- a/src/main/java/com/hospital/front/infra/exception/BusinessException.java +++ b/src/main/java/com/hospital/front/infra/exception/BusinessException.java @@ -1,11 +1,10 @@ package com.hospital.front.infra.exception; -import com.hospital.front.dto.Result; - /** * 业务异常。 * - * 用于业务层显式抛出指定错误码的异常,会被 GlobalExceptionHandler 捕获并包装为 Result。 + * 对外契约与原 hospitalmiddle 一致:异常统一以 {"success":false,"msg":...} 返回, + * 不携带错误码(code 体系已随 Result 对齐移除,分类信息仅用于日志排查)。 * * @author hospital-front重构 */ @@ -13,46 +12,32 @@ public class BusinessException extends RuntimeException { private static final long serialVersionUID = 1L; - /** 业务错误码(参见 Result 中的常量) */ - private final int code; - /** * 构造业务异常。 * - * @param code 业务错误码 * @param message 错误描述 */ - public BusinessException(int code, String message) { + public BusinessException(String message) { super(message); - this.code = code; } - /** - * 静态工厂方法。 - * - * @param code 业务错误码 - * @param message 错误描述 - */ - public static BusinessException of(int code, String message) { - return new BusinessException(code, message); + /** 静态工厂方法 */ + public static BusinessException of(String message) { + return new BusinessException(message); } /** 参数缺失异常 */ public static BusinessException paramMissing(String field) { - return new BusinessException(Result.CODE_PARAM_MISSING, "参数缺失:" + field); + return new BusinessException("参数缺失:" + field); } /** 业务校验失败异常 */ public static BusinessException businessFailed(String msg) { - return new BusinessException(Result.CODE_BUSINESS, msg); + return new BusinessException(msg); } /** 存储过程调用失败异常 */ public static BusinessException procFailed(String msg) { - return new BusinessException(Result.CODE_PROC_FAILED, msg); - } - - public int getCode() { - return code; + return new BusinessException(msg); } } diff --git a/src/main/java/com/hospital/front/infra/exception/GlobalExceptionHandler.java b/src/main/java/com/hospital/front/infra/exception/GlobalExceptionHandler.java index e98f59a..316041d 100644 --- a/src/main/java/com/hospital/front/infra/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/hospital/front/infra/exception/GlobalExceptionHandler.java @@ -25,34 +25,32 @@ public class GlobalExceptionHandler implements Filter { chain.doFilter(ctx); } catch (BusinessException e) { String msg = e.getMessage() != null ? e.getMessage() : "业务异常"; - log.warn("业务异常:code={}, msg={}", e.getCode(), e.getMessage()); - renderResult(ctx, Result.error(e.getCode(), msg)); + log.warn("业务异常:{}", e.getMessage()); + renderResult(ctx, Result.error(msg)); } catch (IllegalArgumentException e) { String msg = e.getMessage() != null ? e.getMessage() : "参数错误"; log.warn("参数异常:{}", e.getMessage()); - renderResult(ctx, Result.error(Result.CODE_PARAM_FORMAT, msg)); + renderResult(ctx, Result.error(msg)); } catch (Exception e) { log.error("系统异常", e); String msg = e.getMessage() != null ? e.getMessage() : e.getClass().getSimpleName(); - renderResult(ctx, Result.error(Result.ERROR_CODE, "系统异常:" + msg)); + renderResult(ctx, Result.error("系统异常:" + msg)); } catch (Throwable t) { // 兜底:捕获 Error 及其它 Throwable(如 OOM),保证响应不悬挂 log.error("严重异常(Throwable)", t); - renderResult(ctx, Result.error(Result.ERROR_CODE, "严重异常:" + t.getClass().getSimpleName())); + renderResult(ctx, Result.error("严重异常:" + t.getClass().getSimpleName())); } } /** - * 输出 Result JSON 响应。 + * 输出 Result JSON 响应(与原 hospitalmiddle 契约一致:{"success":false,"msg":...})。 */ private void renderResult(Context ctx, Result result) { ctx.status(200); ctx.contentType("application/json;charset=UTF-8"); - // 简易 JSON 序列化(避免引入 fastjson 依赖) - String dataJson = result.getData() != null ? toJsonValue(result.getData()) : "null"; - ctx.output("{\"code\":" + result.getCode() + ctx.output("{\"success\":" + result.isSuccess() + ",\"msg\":" + toJsonValue(result.getMsg()) - + ",\"data\":" + dataJson + "}"); + + ",\"data\":null}"); } /** diff --git a/src/main/java/com/hospital/front/infra/util/JsonUtils.java b/src/main/java/com/hospital/front/infra/util/JsonUtils.java new file mode 100644 index 0000000..1949e66 --- /dev/null +++ b/src/main/java/com/hospital/front/infra/util/JsonUtils.java @@ -0,0 +1,42 @@ +package com.hospital.front.infra.util; + +import org.noear.snack.ONode; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * JSON 解析工具(snack3 封装)。 + * + * Solon 对 Map/List 泛型 body 反序列化支持不佳(接口层只能拿 String body), + * 此处集中封装手动解析,接口层一行调用;单 DTO 结构应优先用 @Body 强类型直收。 + */ +public final class JsonUtils { + + private JsonUtils() { + } + + /** JSON 对象字符串 → Map(解析失败抛 IllegalArgumentException) */ + @SuppressWarnings("unchecked") + public static Map parseMap(String json) { + try { + return (Map) ONode.load(json).toObject(Map.class); + } catch (Exception e) { + throw new IllegalArgumentException("JSON 对象格式错误:" + e.getMessage()); + } + } + + /** JSON 数组字符串 → List<Map>(空串返回空列表) */ + @SuppressWarnings("unchecked") + public static List> parseList(String json) { + if (json == null || json.trim().isEmpty()) { + return new ArrayList<>(); + } + try { + return (List>) ONode.load(json).toObject(List.class); + } catch (Exception e) { + throw new IllegalArgumentException("JSON 数组格式错误:" + e.getMessage()); + } + } +} diff --git a/src/main/java/com/hospital/front/mapper/bsm/BsmOrderMapper.java b/src/main/java/com/hospital/front/mapper/bsm/BsmOrderMapper.java index 10a7fea..d39b871 100644 --- a/src/main/java/com/hospital/front/mapper/bsm/BsmOrderMapper.java +++ b/src/main/java/com/hospital/front/mapper/bsm/BsmOrderMapper.java @@ -1,5 +1,11 @@ package com.hospital.front.mapper.bsm; +import com.hospital.front.vo.ConclusionVo; +import com.hospital.front.vo.ExamListVo; +import com.hospital.front.vo.MedicalMiddleResultVo; +import com.hospital.front.vo.PeStatusVo; +import com.hospital.front.vo.SuggestVo; + import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -33,7 +39,7 @@ public interface BsmOrderMapper { void addUnitV2(Map map); /** 按体检预约 ID(逗号分隔)查询体检状态 */ - List> getPhyexamStatus(@Param("peIds") String peIds); + List getPhyexamStatus(@Param("peIds") String peIds); /** 医院所有体检项目(组合项) */ List> getItemList(); @@ -53,45 +59,32 @@ public interface BsmOrderMapper { /** 员工体检结果 */ List> getResult(@Param("peId") String peId); - /** 体检结论(列表) */ - List> getConclusion(@Param("peId") String peId); - /** 体检结论(全量) */ - List> getConclusionAll(@Param("peId") String peId); - - /** 体检建议(列表) */ - List> getSuggest(@Param("peId") String peId); + List getConclusionAll(@Param("peId") String peId); /** 体检建议(全量) */ - List> getSuggestAll(@Param("peId") String peId); + List getSuggestAll(@Param("peId") String peId); + /** 按身份证号及年份查询体检状态 */ - Map getPeStatusByIdnoAndYear(@Param("idNo") String idNo, @Param("year") String year); + PeStatusVo getPeStatusByIdnoAndYear(@Param("idNo") String idNo, @Param("year") String year); /** 按身份证号及年份查询体检结果 */ - List> getResultByIdcardAndYear(@Param("idNo") String idNo, @Param("year") String year); + List getResultByIdcardAndYear(@Param("idNo") String idNo, @Param("year") String year); /** 按身份证号及年份查询体检结果(全量) */ - List> getResultByIdcardAndYearAll(@Param("idNo") String idNo, @Param("year") String year); + List getResultByIdcardAndYearAll(@Param("idNo") String idNo, @Param("year") String year); /** 按体检编号查询体检结果 */ - List> getResultByPeId(@Param("peId") String peId); + List getResultByPeId(@Param("peId") String peId); - /** 按审核日期查询体检报告(去重) */ - List> getDisResultByAuditDate(@Param("auditDate") String auditDate); /** 按体检编号查询体检项目子表 */ - List> getItemByPeId(@Param("peId") String peId); + List getItemByPeId(@Param("peId") String peId); /** 按体检编号查询体检项目子表(全量) */ - List> getItemByPeIdAll(@Param("peId") String peId); + List getItemByPeIdAll(@Param("peId") String peId); - /** 按身份证号或体检编号 + 审核年份查询体检结果 */ - List> getResultByIdNoOrPeId( - @Param("idNo") String idNo, - @Param("peId") String peId, - @Param("auditYear") String auditYear - ); /** 按身份证号查询当年 peId 与预约日期 */ Map getPeIdAndDateByIdcard(@Param("idNo") String idNo); @@ -100,5 +93,5 @@ public interface BsmOrderMapper { List> getPeIdAndDateByIdcardList(@Param("idNo") String idNo); /** 按审核日期查询当天体检人员列表(去重) */ - List> getExamListByDate(@Param("auditDate") String auditDate); + List getExamListByDate(@Param("auditDate") String auditDate); } diff --git a/src/main/java/com/hospital/front/mapper/nx/NxOrderMapper.java b/src/main/java/com/hospital/front/mapper/nx/NxOrderMapper.java index ceeef7c..6aabc45 100644 --- a/src/main/java/com/hospital/front/mapper/nx/NxOrderMapper.java +++ b/src/main/java/com/hospital/front/mapper/nx/NxOrderMapper.java @@ -1,5 +1,11 @@ package com.hospital.front.mapper.nx; +import com.hospital.front.vo.ConclusionVo; +import com.hospital.front.vo.ExamListVo; +import com.hospital.front.vo.MedicalMiddleResultVo; +import com.hospital.front.vo.PeStatusVo; +import com.hospital.front.vo.SuggestVo; + import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -7,91 +13,70 @@ import java.util.List; import java.util.Map; /** - * BSM 医院组 Mapper(Oracle 方言)。 - * - * 适用医院:ningxia(宁夏宝石花,SqlServer) - * XML 位置:classpath:mapper/nx/OrderMapper.xml - * - * 存储过程参数与医院 HIS 系统约定,不可修改。 + * 宁夏医院 Mapper(SqlServer 方言)。 + * getConclusion/getSuggest 与 All 版 SQL 完全重复,已合并为 All 版。 */ @Mapper public interface NxOrderMapper { - /** 健康探测(SELECT 1) */ + /** 健康探测 */ int ping(); - /** 预约提交(存储过程 P_ADD_PE_REGIST,出参 resultCode/errorMsg/peId) */ + /** 提交预约(存储过程) */ void saveOrder(Map map); - /** 取消预约(存储过程 P_DEL_PE_REGIST) */ + /** 取消预约(存储过程) */ void cancelOrder(Map map); - /** 添加/修改单位 V1(存储过程 P_ADD_UNIT) */ - void addUnit(Map map); - - /** 添加/修改单位 V2(存储过程 P_ADD_UNIT,8 入参版) */ + /** 添加/修改单位 V2(存储过程) */ void addUnitV2(Map map); - /** 按体检预约 ID(逗号分隔)查询体检状态 */ - List> getPhyexamStatus(@Param("peIds") String peIds); + /** 体检状态查询(多个 peId 逗号分隔) */ + List getPhyexamStatus(@Param("peIds") String peIds); - /** 医院所有体检项目(组合项) */ + /** 体检项目查询 */ List> getItemList(); - /** 医院所有体检项目及指标项 */ + /** 体检指标项及体检组合数据 */ List> getAllItemList(); - /** 医院所有体检指标项 */ + /** 体检指标项数据 */ List> getPeItemList(); + /** 按体检指标项查所属组合 */ + List> getItemInfo(@Param("peItemCode") String peItemCode); + /** 员工体检项目 */ List> getEmpItem(@Param("peId") String peId); - /** 按指标项 CODE 查询体检组合 */ - List> getItemInfo(@Param("peItemCode") String peItemCode); - - /** 员工体检结果 */ + /** 按体检编号查体检结果 */ List> getResult(@Param("peId") String peId); /** 体检结论(列表) */ - List> getConclusion(@Param("peId") String peId); - - /** 体检结论(全量) */ - List> getConclusionAll(@Param("peId") String peId); - - /** 体检建议(列表) */ - List> getSuggest(@Param("peId") String peId); + List getConclusionAll(@Param("peId") String peId); /** 体检建议(全量) */ - List> getSuggestAll(@Param("peId") String peId); + List getSuggestAll(@Param("peId") String peId); /** 按身份证号及年份查询体检状态 */ - Map getPeStatusByIdnoAndYear(@Param("idNo") String idNo, @Param("year") String year); + PeStatusVo getPeStatusByIdnoAndYear(@Param("idNo") String idNo, @Param("year") String year); /** 按身份证号及年份查询体检结果 */ - List> getResultByIdcardAndYear(@Param("idNo") String idNo, @Param("year") String year); + List getResultByIdcardAndYear(@Param("idNo") String idNo, @Param("year") String year); /** 按身份证号及年份查询体检结果(全量) */ - List> getResultByIdcardAndYearAll(@Param("idNo") String idNo, @Param("year") String year); + List getResultByIdcardAndYearAll(@Param("idNo") String idNo, @Param("year") String year); /** 按体检编号查询体检结果 */ - List> getResultByPeId(@Param("peId") String peId); + List getResultByPeId(@Param("peId") String peId); - /** 按审核日期查询体检报告(去重) */ - List> getDisResultByAuditDate(@Param("auditDate") String auditDate); /** 按体检编号查询体检项目子表 */ - List> getItemByPeId(@Param("peId") String peId); + List getItemByPeId(@Param("peId") String peId); /** 按体检编号查询体检项目子表(全量) */ - List> getItemByPeIdAll(@Param("peId") String peId); + List getItemByPeIdAll(@Param("peId") String peId); - /** 按身份证号或体检编号 + 审核年份查询体检结果 */ - List> getResultByIdNoOrPeId( - @Param("idNo") String idNo, - @Param("peId") String peId, - @Param("auditYear") String auditYear - ); /** 按身份证号查询当年 peId 与预约日期 */ Map getPeIdAndDateByIdcard(@Param("idNo") String idNo); @@ -100,5 +85,5 @@ public interface NxOrderMapper { List> getPeIdAndDateByIdcardList(@Param("idNo") String idNo); /** 按审核日期查询当天体检人员列表(去重) */ - List> getExamListByDate(@Param("auditDate") String auditDate); + List getExamListByDate(@Param("auditDate") String auditDate); } diff --git a/src/main/java/com/hospital/front/mapper/ya/YaOrderMapper.java b/src/main/java/com/hospital/front/mapper/ya/YaOrderMapper.java index 5ea9977..cbbbbba 100644 --- a/src/main/java/com/hospital/front/mapper/ya/YaOrderMapper.java +++ b/src/main/java/com/hospital/front/mapper/ya/YaOrderMapper.java @@ -1,5 +1,11 @@ package com.hospital.front.mapper.ya; +import com.hospital.front.vo.ConclusionVo; +import com.hospital.front.vo.ExamListVo; +import com.hospital.front.vo.MedicalMiddleResultVo; +import com.hospital.front.vo.PeStatusVo; +import com.hospital.front.vo.SuggestVo; + import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @@ -7,91 +13,70 @@ import java.util.List; import java.util.Map; /** - * BSM 医院组 Mapper(Oracle 方言)。 - * - * 适用医院:yanan(延安,SqlServer) - * XML 位置:classpath:mapper/ya/OrderMapper.xml - * - * 存储过程参数与医院 HIS 系统约定,不可修改。 + * 延安医院 Mapper(SqlServer 方言)。 + * getConclusion/getSuggest 与 All 版 SQL 完全重复,已合并为 All 版。 */ @Mapper public interface YaOrderMapper { - /** 健康探测(SELECT 1) */ + /** 健康探测 */ int ping(); - /** 预约提交(存储过程 P_ADD_PE_REGIST,出参 resultCode/errorMsg/peId) */ + /** 提交预约(存储过程) */ void saveOrder(Map map); - /** 取消预约(存储过程 P_DEL_PE_REGIST) */ + /** 取消预约(存储过程) */ void cancelOrder(Map map); - /** 添加/修改单位 V1(存储过程 P_ADD_UNIT) */ + /** 添加/修改单位(存储过程,V1) */ void addUnit(Map map); - /** 添加/修改单位 V2(存储过程 P_ADD_UNIT,8 入参版) */ - void addUnitV2(Map map); + /** 体检状态查询(多个 peId 逗号分隔) */ + List getPhyexamStatus(@Param("peIds") String peIds); - /** 按体检预约 ID(逗号分隔)查询体检状态 */ - List> getPhyexamStatus(@Param("peIds") String peIds); - - /** 医院所有体检项目(组合项) */ + /** 体检项目查询 */ List> getItemList(); - /** 医院所有体检项目及指标项 */ + /** 体检指标项及体检组合数据 */ List> getAllItemList(); - /** 医院所有体检指标项 */ + /** 体检指标项数据 */ List> getPeItemList(); + /** 按体检指标项查所属组合 */ + List> getItemInfo(@Param("peItemCode") String peItemCode); + /** 员工体检项目 */ List> getEmpItem(@Param("peId") String peId); - /** 按指标项 CODE 查询体检组合 */ - List> getItemInfo(@Param("peItemCode") String peItemCode); - - /** 员工体检结果 */ + /** 按体检编号查体检结果 */ List> getResult(@Param("peId") String peId); /** 体检结论(列表) */ - List> getConclusion(@Param("peId") String peId); - - /** 体检结论(全量) */ - List> getConclusionAll(@Param("peId") String peId); - - /** 体检建议(列表) */ - List> getSuggest(@Param("peId") String peId); + List getConclusionAll(@Param("peId") String peId); /** 体检建议(全量) */ - List> getSuggestAll(@Param("peId") String peId); + List getSuggestAll(@Param("peId") String peId); /** 按身份证号及年份查询体检状态 */ - Map getPeStatusByIdnoAndYear(@Param("idNo") String idNo, @Param("year") String year); + PeStatusVo getPeStatusByIdnoAndYear(@Param("idNo") String idNo, @Param("year") String year); /** 按身份证号及年份查询体检结果 */ - List> getResultByIdcardAndYear(@Param("idNo") String idNo, @Param("year") String year); + List getResultByIdcardAndYear(@Param("idNo") String idNo, @Param("year") String year); /** 按身份证号及年份查询体检结果(全量) */ - List> getResultByIdcardAndYearAll(@Param("idNo") String idNo, @Param("year") String year); + List getResultByIdcardAndYearAll(@Param("idNo") String idNo, @Param("year") String year); /** 按体检编号查询体检结果 */ - List> getResultByPeId(@Param("peId") String peId); + List getResultByPeId(@Param("peId") String peId); - /** 按审核日期查询体检报告(去重) */ - List> getDisResultByAuditDate(@Param("auditDate") String auditDate); /** 按体检编号查询体检项目子表 */ - List> getItemByPeId(@Param("peId") String peId); + List getItemByPeId(@Param("peId") String peId); /** 按体检编号查询体检项目子表(全量) */ - List> getItemByPeIdAll(@Param("peId") String peId); + List getItemByPeIdAll(@Param("peId") String peId); - /** 按身份证号或体检编号 + 审核年份查询体检结果 */ - List> getResultByIdNoOrPeId( - @Param("idNo") String idNo, - @Param("peId") String peId, - @Param("auditYear") String auditYear - ); /** 按身份证号查询当年 peId 与预约日期 */ Map getPeIdAndDateByIdcard(@Param("idNo") String idNo); @@ -100,5 +85,5 @@ public interface YaOrderMapper { List> getPeIdAndDateByIdcardList(@Param("idNo") String idNo); /** 按审核日期查询当天体检人员列表(去重) */ - List> getExamListByDate(@Param("auditDate") String auditDate); + List getExamListByDate(@Param("auditDate") String auditDate); } diff --git a/src/main/java/com/hospital/front/service/OrderService.java b/src/main/java/com/hospital/front/service/OrderService.java index 3efefcf..e24c7db 100644 --- a/src/main/java/com/hospital/front/service/OrderService.java +++ b/src/main/java/com/hospital/front/service/OrderService.java @@ -1,5 +1,7 @@ package com.hospital.front.service; +import com.hospital.front.vo.MedicalMiddleResultVo; + import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; @@ -17,8 +19,10 @@ import com.hospital.front.adapter.HospitalAdapter; import com.hospital.front.adapter.HospitalRouter; import com.hospital.front.infra.exception.BusinessException; import com.hospital.front.infra.util.DateUtils; +import com.hospital.front.vo.ExamListVo; import com.hospital.front.vo.OrderItemVo; import com.hospital.front.vo.OrderV2Vo; +import com.hospital.front.vo.PeStatusPhyVo; import com.hospital.front.vo.UnitVo; /** @@ -79,8 +83,7 @@ public class OrderService { * * @return 成功时返回 peId */ - public String saveOrder(Map body) { - OrderV2Vo vo = convertOrderV2(body); + public String saveOrder(com.hospital.front.vo.OrderV2Vo vo) { if (isAllsecondFlag()) { vo = vo.applyAllsecondFlag(); } @@ -160,33 +163,17 @@ public class OrderService { return adapter().getResult(peId); } - public List> getConclusion(String peId) { - return adapter().getConclusion(peId); - } - - public List> getSuggest(String peId) { - return adapter().getSuggest(peId); - } - - public List> getResultByIdcardAndYear(String idNo, String year) { + /** 按身份证及年份查体检结果(内部使用:宁夏 getPeStatusByIdnoAndYear 兜底) */ + public List getResultByIdcardAndYear(String idNo, String year) { return adapter().getResultByIdcardAndYear(idNo, year); } - public List> getResultByIdcardAndYearAll(String idNo, String year) { - return adapter().getResultByIdcardAndYearAll(idNo, year); + public List getResultByIdcardAndYearAll(String idNo, String year) { + return enrichResultAll(adapter().getResultByIdcardAndYearAll(idNo, year)); } - public List> getResultByPeId(String peId) { - return adapter().getResultByPeId(peId); - } - - /** 按审核日期查询体检报告(去重主表) */ - public List> getResultByAuditDate(String auditDate) { - return adapter().getDisResultByAuditDate(auditDate); - } - - public List> getResultByIdNoOrPeId(String idNo, String peId, String auditYear) { - return adapter().getResultByIdNoOrPeId(idNo, peId, auditYear); + public List getResultByPeId(String peId) { + return enrichResultAll(adapter().getResultByPeId(peId)); } public Map getPeIdAndDateByIdcard(String idNo) { @@ -200,14 +187,13 @@ public class OrderService { /** * 体检状态查询:按医院返回的 PE_STATUS 名转字典数字。 */ - public List> getPhyexamStatus(String peIds) { - List> out = new ArrayList<>(); - for (Map row : adapter().getPhyexamStatus(peIds)) { - Map item = new HashMap<>(); - item.put("peId", row.get("PE_ID") != null ? String.valueOf(row.get("PE_ID")) : ""); - String statusName = row.get("PE_STATUS") != null ? String.valueOf(row.get("PE_STATUS")) : ""; - item.put("peStatus", PE_STATUS_DICT.getOrDefault(statusName, "")); - out.add(item); + public List getPhyexamStatus(String peIds) { + List out = new ArrayList<>(); + for (com.hospital.front.vo.PeStatusVo row : adapter().getPhyexamStatus(peIds)) { + out.add(new PeStatusPhyVo( + row.getPeId() != null ? row.getPeId() : "", + PE_STATUS_DICT.getOrDefault( + row.getPeStatus() != null ? row.getPeStatus() : "", ""))); } return out; } @@ -215,63 +201,39 @@ public class OrderService { /** * 按日期查询当天体检人员列表(日期空则当天)。 */ - public List> getExamListByDate(String auditDate) { + public List getExamListByDate(String auditDate) { return adapter().getExamListByDate(auditDate != null ? auditDate : DateUtils.today()); } - /** - * 体检结论(汇总为单字符串)。 - */ - public Map getTotalConclusion(String peId) { - Map map = new HashMap<>(); - map.put("totalConclusion", buildSummary(adapter().getConclusion(peId))); - return map; - } - - /** 体检结论(汇总,全量来源) */ - public Map getTotalConclusionAll(String peId) { - Map map = new HashMap<>(); - map.put("totalConclusion", buildSummary(adapter().getConclusionAll(peId))); - return map; - } - - /** - * 体检建议(汇总)。宁夏(nx)仅取首条 GUIDE_CONTENT。 - */ - public Map getTotalSuggest(String peId) { - Map map = new HashMap<>(); - map.put("totalSuggest", buildSuggest(adapter().getSuggest(peId), "nx".equals(adapter().hmType()))); - return map; - } - - /** 体检建议(汇总,全量来源) */ - public Map getTotalSuggestAll(String peId) { - Map map = new HashMap<>(); - map.put("totalSuggest", buildSuggest(adapter().getSuggestAll(peId), "nx".equals(adapter().hmType()))); - return map; - } - /** * 按身份证号 + 年份查询体检状态及项目(含宁夏体检报告兜底)。 */ public Map getPeStatusByIdnoAndYear(String idNo, String year) { - Map map = adapter().getPeStatusByIdnoAndYear(idNo, year); - if (map != null && map.get("PE_ID") != null) { - Map result = new LinkedHashMap<>(map); - result.put("peItemList", adapter().getEmpItem(String.valueOf(map.get("PE_ID")))); + com.hospital.front.vo.PeStatusVo vo = adapter().getPeStatusByIdnoAndYear(idNo, year); + if (vo != null && vo.getPeId() != null) { + Map result = new LinkedHashMap<>(); + result.put("PE_ID", vo.getPeId()); + result.put("NAME", vo.getName()); + result.put("ID_NO", vo.getIdNo()); + result.put("UNIT_NAME", vo.getUnitName()); + result.put("DEPARTMENT", vo.getDepartment()); + result.put("PE_PRE_DATE", vo.getPePreDate()); + result.put("PE_QUEUE_DATE", vo.getPeQueueDate()); + result.put("PE_STATUS", vo.getPeStatus()); + result.put("peItemList", adapter().getEmpItem(vo.getPeId())); return result; } else { // 宁夏:从体检报告继续查 if ("nx".equals(adapter().hmType())) { - List> rows = adapter().getResultByIdcardAndYear(idNo, year); + List rows = adapter().getResultByIdcardAndYear(idNo, year); if (!rows.isEmpty()) { - Map row = rows.get(0); - String auditDate = row.get("AUDIT_DATE") != null ? String.valueOf(row.get("AUDIT_DATE")) : null; + MedicalMiddleResultVo row = rows.get(0); + String auditDate = row.getAuditDate(); Map out = new LinkedHashMap<>(); - out.put("PE_ID", row.get("PE_ID")); + out.put("PE_ID", row.getPeId()); out.put("PE_PRE_DATE", auditDate != null && auditDate.length() >= 10 ? auditDate.substring(0, 10) : auditDate); - out.put("peItemList", adapter().getEmpItem(String.valueOf(row.get("PE_ID")))); + out.put("peItemList", adapter().getEmpItem(row.getPeId())); return out; } else { return null; @@ -284,107 +246,58 @@ public class OrderService { // ================= 私有工具 ================= - /** 医院侧业务失败:抛出 2003 业务异常 */ + /** + * 报告组装(对齐原 hospitalmiddle 的 dealMiddleChildDataAll): + * 为每条结果补 hospitalId、item 子表(全量)、体检结论、体检建议。 + */ + private List enrichResultAll(List rows) { + String hospitalId = Solon.cfg().get("hospital.id", ""); + for (MedicalMiddleResultVo row : rows) { + row.setHospitalId(hospitalId); + // item 子表(全量版) + row.setResultVoList(adapter().getItemByPeIdAll(row.getPeId())); + // 体检结论:多条按 "序号.科室:结论文本;
" 拼接 + StringBuilder conclusion = new StringBuilder(); + int cIndex = 1; + for (com.hospital.front.vo.ConclusionVo c : adapter().getConclusionAll(row.getPeId())) { + String deptName = c.getPeDeptName() != null ? c.getPeDeptName() : ""; + String text = c.getConclusionText() != null ? c.getConclusionText() : ""; + conclusion.append(cIndex).append(".").append(deptName).append(":").append(text).append(";
"); + cIndex++; + } + row.setConclusion(conclusion.toString()); + // 体检建议:宁夏取首条 guideContent;其余按 "序号.建议项:建议内容;
" 拼接(跳过建议内容为空的行) + StringBuilder suggest = new StringBuilder(); + List suggestRows = adapter().getSuggestAll(row.getPeId()); + if ("nx".equals(adapter().hmType())) { + if (!suggestRows.isEmpty() && suggestRows.get(0).getGuideContent() != null) { + suggest.append(suggestRows.get(0).getGuideContent()); + } + } else { + int sIndex = 1; + for (com.hospital.front.vo.SuggestVo s : suggestRows) { + if (s.getGuideContent() != null && !s.getGuideContent().isEmpty()) { + String rec = s.getRecContent() != null ? s.getRecContent() : ""; + suggest.append(sIndex).append(".").append(rec).append(":") + .append(s.getGuideContent()).append(";
"); + sIndex++; + } + } + } + row.setSuggest(suggest.toString()); + } + return rows; + } + + /** 医院侧业务失败:抛出业务异常 */ private void throwHospitalFailed(String errorMsg) { if (errorMsg != null && !errorMsg.isEmpty()) { - throw BusinessException.of(2003, errorMsg); + throw BusinessException.of(errorMsg); } else { throw BusinessException.procFailed("医院系统返回业务失败"); } } - /** 结论汇总:1.科室:结论;
*/ - private String buildSummary(List> rows) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < rows.size(); i++) { - Map row = rows.get(i); - String deptName = row.get("PE_DEPT_NAME") != null ? String.valueOf(row.get("PE_DEPT_NAME")) : ""; - String dept = !deptName.isEmpty() ? deptName + ":" : ""; - Object conclusion = row.get("CONCLUSION_TEXT"); - sb.append(i + 1).append(".").append(dept).append(conclusion != null ? conclusion : "").append(";
"); - } - return sb.toString(); - } - - /** 建议汇总:宁夏仅取首条 GUIDE_CONTENT;其余 1.建议项:内容;
*/ - private String buildSuggest(List> rows, boolean nxStyle) { - if (nxStyle) { - if (rows.isEmpty() || rows.get(0).get("GUIDE_CONTENT") == null) { - return ""; - } - return String.valueOf(rows.get(0).get("GUIDE_CONTENT")); - } else { - StringBuilder sb = new StringBuilder(); - int i = 1; - for (Map row : rows) { - String guide = row.get("GUIDE_CONTENT") != null ? String.valueOf(row.get("GUIDE_CONTENT")) : ""; - if (guide.isEmpty()) { - continue; - } - Object rec = row.get("REC_CONTENT"); - sb.append(i).append(".").append(rec != null ? rec : "").append(":").append(guide).append(";
"); - i++; - } - return sb.toString(); - } - } - - /** Map → OrderV2Vo(数值/空值容错) */ - private OrderV2Vo convertOrderV2(Map body) { - List itemList = null; - Object rawList = body.get("itemList"); - if (rawList instanceof List) { - itemList = new ArrayList<>(); - for (Object item : (List) rawList) { - if (item instanceof Map) { - Map m = (Map) item; - itemList.add(new OrderItemVo( - m.get("itemNo") != null ? String.valueOf(m.get("itemNo")) : null, - m.get("itemName") != null ? String.valueOf(m.get("itemName")) : null)); - } - } - } - return new OrderV2Vo( - str(body, "orderDate"), - str(body, "secondDepartId"), - str(body, "secondDepartName"), - str(body, "thirdDepartName"), - str(body, "name"), - str(body, "sexName"), - str(body, "birthDay"), - body.get("age") instanceof Number ? ((Number) body.get("age")).intValue() : null, - str(body, "idCard"), - str(body, "marrigeStatusName"), - str(body, "country"), - str(body, "nationName"), - str(body, "birthplace"), - str(body, "position"), - str(body, "profession"), - str(body, "feeType"), - str(body, "liveSpace"), - str(body, "zipCode"), - str(body, "mobile"), - str(body, "email"), - str(body, "empSysno"), - str(body, "medicalType"), - str(body, "medicalClass"), - str(body, "workShape"), - str(body, "workDate"), - str(body, "jobLevel"), - str(body, "workPlace"), - str(body, "baseSite"), - str(body, "workTypeCode"), - str(body, "workTypeOther"), - str(body, "education"), - str(body, "title"), - str(body, "oldDepartName"), - str(body, "harmReasonCode"), - str(body, "harmReasonOther"), - str(body, "harmDate"), - str(body, "defendCancer"), - itemList); - } - /** 取字符串值(null 安全) */ private static String str(Map map, String key) { Object v = map.get(key); diff --git a/src/main/java/com/hospital/front/task/UptimeKumaTask.java b/src/main/java/com/hospital/front/task/UptimeKumaTask.java index fcd12fb..e965844 100644 --- a/src/main/java/com/hospital/front/task/UptimeKumaTask.java +++ b/src/main/java/com/hospital/front/task/UptimeKumaTask.java @@ -2,11 +2,12 @@ package com.hospital.front.task; import lombok.extern.slf4j.Slf4j; -import java.util.concurrent.TimeUnit; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; import org.noear.solon.Solon; import org.noear.solon.annotation.Component; import org.noear.solon.annotation.Inject; @@ -33,9 +34,9 @@ public class UptimeKumaTask { @Inject private HospitalRouter router; - private final OkHttpClient http = new OkHttpClient.Builder() - .connectTimeout(5, TimeUnit.SECONDS) - .readTimeout(10, TimeUnit.SECONDS) + /** JDK 内置 HttpClient(替代 OkHttp,免额外依赖):连接 5s、读取 10s */ + private final HttpClient http = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(5)) .build(); /** @@ -51,15 +52,19 @@ public class UptimeKumaTask { } // 检查数据库连接 com.hospital.front.dto.Result health = router.active().healthCheck(); - if (health.getCode() == 0) { + if (health.isSuccess()) { try { - Response resp = http.newCall(new Request.Builder().url(kumaUrl).get().build()).execute(); - if (resp.isSuccessful()) { + HttpResponse resp = http.send( + HttpRequest.newBuilder(URI.create(kumaUrl)) + .GET() + .timeout(Duration.ofSeconds(10)) + .build(), + HttpResponse.BodyHandlers.ofString()); + if (resp.statusCode() >= 200 && resp.statusCode() < 300) { log.info("[Kuma] 心跳推送成功:{}", kumaUrl); } else { - log.warn("[Kuma] 心跳推送失败:HTTP {}", resp.code()); + log.warn("[Kuma] 心跳推送失败:HTTP {}", resp.statusCode()); } - resp.close(); } catch (Exception e) { log.warn("[Kuma] 心跳推送异常:{}", e.getMessage()); } diff --git a/src/main/java/com/hospital/front/vo/ConclusionVo.java b/src/main/java/com/hospital/front/vo/ConclusionVo.java new file mode 100644 index 0000000..353794e --- /dev/null +++ b/src/main/java/com/hospital/front/vo/ConclusionVo.java @@ -0,0 +1,22 @@ +package com.hospital.front.vo; + +import lombok.Data; + +/** + * 体检结论明细 VO(getConclusionAll 强类型映射,内部使用)。 + * + * 一个 peId 按科室返回多条结论(汇总拼接用),故为列表元素。 + */ +@Data +public class ConclusionVo { + /** 体检编号 */ + private String peId; + /** 就诊编号 */ + private String peVisitId; + /** 科室编码 */ + private String peDeptCode; + /** 科室名称 */ + private String peDeptName; + /** 结论文本(已去换行) */ + private String conclusionText; +} diff --git a/src/main/java/com/hospital/front/vo/ExamListVo.java b/src/main/java/com/hospital/front/vo/ExamListVo.java new file mode 100644 index 0000000..f55dbe7 --- /dev/null +++ b/src/main/java/com/hospital/front/vo/ExamListVo.java @@ -0,0 +1,25 @@ +package com.hospital.front.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 当天体检人员列表 VO(getExamListByDate 对外强类型出参)。 + * + * 三院 SQL 出参统一(列别名即驼峰字段),日期已在 SQL 层转为字符串。 + * 字段名与 snack3 默认序列化输出 key 一致,可直接返回 HTTP 调用方。 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ExamListVo { + /** 体检编号 */ + private String peId; + /** 身份证号 */ + private String idNo; + /** 姓名 */ + private String name; + /** 审查日期 yyyy-MM-dd */ + private String auditDate; +} diff --git a/src/main/java/com/hospital/front/vo/PeStatusPhyVo.java b/src/main/java/com/hospital/front/vo/PeStatusPhyVo.java new file mode 100644 index 0000000..0e99057 --- /dev/null +++ b/src/main/java/com/hospital/front/vo/PeStatusPhyVo.java @@ -0,0 +1,22 @@ +package com.hospital.front.vo; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 体检状态简版 VO(getPhyexamStatus 对外强类型出参)。 + * + * 字段名与 snack3 默认序列化输出 key 一致(peId / peStatus), + * 可直接返回给 HTTP 调用方,无需手工 Map 包装。 + * peStatus 已由 OrderService 加工为字典数字(与原 Map 契约一致)。 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PeStatusPhyVo { + /** 体检编号(null 时输出空字符串,保持与原 Map 契约一致) */ + private String peId; + /** 体检状态字典数字(原始状态名查不到时输出空字符串) */ + private String peStatus; +} \ No newline at end of file diff --git a/src/main/java/com/hospital/front/vo/PeStatusVo.java b/src/main/java/com/hospital/front/vo/PeStatusVo.java new file mode 100644 index 0000000..10a7442 --- /dev/null +++ b/src/main/java/com/hospital/front/vo/PeStatusVo.java @@ -0,0 +1,29 @@ +package com.hospital.front.vo; + +import lombok.Data; + +/** + * 体检状态 VO(getPhyexamStatus / getPeStatusByIdnoAndYear 强类型映射,内部中间态)。 + * + * 对外出参由 OrderService 加工(key 小写 peId/peStatus + 状态字典转换), + * 本 VO 仅作 adapter → service 的内部传输,不影响 HTTP 契约。 + */ +@Data +public class PeStatusVo { + /** 体检编号 */ + private String peId; + /** 姓名 */ + private String name; + /** 身份证号 */ + private String idNo; + /** 单位名称 */ + private String unitName; + /** 部门 */ + private String department; + /** 预约日期 */ + private String pePreDate; + /** 排队日期 */ + private String peQueueDate; + /** 状态名(报到/检中/初审/终审/预约/转向) */ + private String peStatus; +} diff --git a/src/main/java/com/hospital/front/vo/SuggestVo.java b/src/main/java/com/hospital/front/vo/SuggestVo.java new file mode 100644 index 0000000..1f4a35e --- /dev/null +++ b/src/main/java/com/hospital/front/vo/SuggestVo.java @@ -0,0 +1,18 @@ +package com.hospital.front.vo; + +import lombok.Data; + +/** + * 体检建议 VO(getSuggestAll 强类型映射,内部使用)。 + * + * 按 peId 查询仅一条建议记录,adapter 层取首条返回单对象。 + */ +@Data +public class SuggestVo { + /** 体检编号 */ + private String peId; + /** 建议项(科室/类别描述) */ + private String recContent; + /** 建议内容(已去换行) */ + private String guideContent; +} diff --git a/src/main/resources/app.yml b/src/main/resources/app.yml index 5d4ef2e..6289d62 100644 --- a/src/main/resources/app.yml +++ b/src/main/resources/app.yml @@ -11,6 +11,10 @@ solon: app: name: "hospital-front" group: "hospital" + # JSON 序列化对齐原 hospitalmiddle(Jackson 默认保留 null 字段) + serialization: + json: + nullAsWriteable: true # 应用配置 # 医院注册清单由代码决定(各 Adapter 的 @Component),此处仅指定激活哪家 diff --git a/src/main/resources/com/hospital/front/mapper/bsm/BsmOrderMapper.xml b/src/main/resources/com/hospital/front/mapper/bsm/BsmOrderMapper.xml index ae65ecc..000761f 100644 --- a/src/main/resources/com/hospital/front/mapper/bsm/BsmOrderMapper.xml +++ b/src/main/resources/com/hospital/front/mapper/bsm/BsmOrderMapper.xml @@ -7,102 +7,113 @@ SELECT 1 FROM DUAL + + - - - - - + + + + + {call P_ADD_PE_REGIST( - #{peInfoStr,mode=IN,jdbcType=VARCHAR}, - #{peItemStr,mode=IN,jdbcType=VARCHAR}, - #{resultCode,mode=OUT,jdbcType=VARCHAR}, - #{errorMsg,mode=OUT,jdbcType=VARCHAR}, - #{peId,mode=OUT,jdbcType=VARCHAR} + #{peInfoStr,mode=IN,jdbcType=VARCHAR}, + #{peItemStr,mode=IN,jdbcType=VARCHAR}, + #{resultCode,mode=OUT,jdbcType=VARCHAR}, + #{errorMsg,mode=OUT,jdbcType=VARCHAR}, + #{peId,mode=OUT,jdbcType=VARCHAR} )} - - - - - + + + + + {call P_DEL_PE_REGIST( - #{peId,mode=IN,jdbcType=VARCHAR}, - #{name,mode=IN,jdbcType=VARCHAR}, - #{idcard,mode=IN,jdbcType=VARCHAR}, - #{resultCode,mode=OUT,jdbcType=VARCHAR}, - #{errorMsg,mode=OUT,jdbcType=VARCHAR} + #{peId,mode=IN,jdbcType=VARCHAR}, + #{name,mode=IN,jdbcType=VARCHAR}, + #{idcard,mode=IN,jdbcType=VARCHAR}, + #{resultCode,mode=OUT,jdbcType=VARCHAR}, + #{errorMsg,mode=OUT,jdbcType=VARCHAR} )} - - - - + + + + - - {call P_ADD_UNIT( - #{unitCode,mode=IN,jdbcType=VARCHAR}, - #{unitName,mode=IN,jdbcType=VARCHAR}, - #{resultCode,mode=OUT,jdbcType=VARCHAR}, - #{errorMsg,mode=OUT,jdbcType=VARCHAR} + #{unitCode,mode=IN,jdbcType=VARCHAR}, + #{unitName,mode=IN,jdbcType=VARCHAR}, + #{resultCode,mode=OUT,jdbcType=VARCHAR}, + #{errorMsg,mode=OUT,jdbcType=VARCHAR} )} - - - - - - - - - - + + + + + + + + + + {call P_ADD_UNIT( - #{unitCode,mode=IN,jdbcType=VARCHAR}, - #{unitName,mode=IN,jdbcType=VARCHAR}, - #{parentUnitCode,mode=IN,jdbcType=VARCHAR}, - #{address,mode=IN,jdbcType=VARCHAR}, - #{connecter1,mode=IN,jdbcType=VARCHAR}, - #{phone1,mode=IN,jdbcType=VARCHAR}, - #{connecter2,mode=IN,jdbcType=VARCHAR}, - #{phone2,mode=IN,jdbcType=VARCHAR}, - #{resultCode,mode=OUT,jdbcType=VARCHAR}, - #{errorMsg,mode=OUT,jdbcType=VARCHAR} + #{unitCode,mode=IN,jdbcType=VARCHAR}, + #{unitName,mode=IN,jdbcType=VARCHAR}, + #{parentUnitCode,mode=IN,jdbcType=VARCHAR}, + #{address,mode=IN,jdbcType=VARCHAR}, + #{connecter1,mode=IN,jdbcType=VARCHAR}, + #{phone1,mode=IN,jdbcType=VARCHAR}, + #{connecter2,mode=IN,jdbcType=VARCHAR}, + #{phone2,mode=IN,jdbcType=VARCHAR}, + #{resultCode,mode=OUT,jdbcType=VARCHAR}, + #{errorMsg,mode=OUT,jdbcType=VARCHAR} )} - select PE_ID, NAME, ID_NO, UNIT_NAME, DEPARTMENT, PE_PRE_DATE, PE_QUEUE_DATE, PE_STATUS from V_PHYEXAM_PE_STATUS where instr(',' || #{peIds} || ',', ',' || pe_id || ',') > 0 - + select * from V_PHYEXAM_PE_STATUS + where ID_NO = #{idNo} + and to_char(PE_PRE_DATE, 'yyyy') = #{year} + + + + + + + - - - + - + SELECT PE_ID, + PE_VISIT_ID, + PE_DEPT_CODE, + PE_DEPT_NAME, + REPLACE(REPLACE(REPLACE(DBMS_LOB.SUBSTR(CONCLUSION_TEXT, 4000, 1), chr(13) || chr(10), ''), chr(13), ''), chr(10), '') CONCLUSION_TEXT + FROM ( + SELECT a.pe_id, a.pe_visit_id, a.pe_dept_code, a.pe_dept_name, a.conclusion_text + FROM pe_dept_result_dict a, pe_visit b + WHERE a.pe_id = b.pe_id + AND a.pe_visit_id = b.pe_visit_id + ) + WHERE PE_ID = #{peId} + AND CONCLUSION_TEXT IS NOT NULL - - + SELECT PE_ID, PE_VISIT_ID, REC_CONTENT, + REPLACE(REPLACE(REPLACE(DBMS_LOB.SUBSTR(GUIDE_CONTENT, 4000, 1), chr(13) || chr(10), ''), chr(13), ''), chr(10), '') GUIDE_CONTENT + FROM ( + SELECT a.pe_id, a.pe_visit_id, a.rec_content, a.guide_content + FROM pe_diagnosis_record a, pe_visit b + WHERE a.pe_id = b.pe_id + AND a.pe_visit_id = b.pe_visit_id + ) + WHERE PE_ID = #{peId} + AND GUIDE_CONTENT IS NOT NULL + + + + - - - - + - + SELECT DISTINCT + ID_NO, NAME, PE_ID, PE_VISIT_ID, UNIT_CODE, UNIT_NAME, + to_char(PE_QUEUE_DATE, 'yyyy-mm-dd HH24:mi:ss') PE_QUEUE_DATE, + to_char(AUDIT_DATE, 'yyyy-mm-dd HH24:mi:ss') AUDIT_DATE + FROM ( + SELECT b.pe_id, b.pe_visit_id, a.id_no, a.name, b.unit_code, + (SELECT t.unit_name FROM pe_unit_dict t WHERE t.unit_code = b.unit_code) unit_name, + b.pe_queue_date, b.audit_date, + c.pe_dept_code, c.pe_dept_name, c.item_assem_code, c.item_assem_name, + c.pe_item_code, c.pe_item_name, c.pe_result, c.unit, c.print_context + FROM pe_master_index a, pe_visit b, pe_result_dict c + WHERE a.pe_id = b.pe_id + AND b.pe_id = c.pe_id + AND b.pe_visit_id = c.pe_visit_id + ) + WHERE PE_ID = #{peId} + + - - - + - SELECT DISTINCT PE_ID AS "peId", ID_NO AS "idNo", NAME AS "name", TO_CHAR(audit_date, 'YYYY-MM-DD') AS "auditDate" - FROM V_PHYEXAM_RESULT + FROM ( + SELECT b.pe_id, b.pe_visit_id, a.id_no, a.name, b.unit_code, + (SELECT t.unit_name FROM pe_unit_dict t WHERE t.unit_code = b.unit_code) unit_name, + b.pe_queue_date, b.audit_date, + c.pe_dept_code, c.pe_dept_name, c.item_assem_code, c.item_assem_name, + c.pe_item_code, c.pe_item_name, c.pe_result, c.unit, c.print_context + FROM pe_master_index a, pe_visit b, pe_result_dict c + WHERE a.pe_id = b.pe_id + AND b.pe_id = c.pe_id + AND b.pe_visit_id = c.pe_visit_id + ) @@ -434,4 +362,5 @@ - \ No newline at end of file + + diff --git a/src/main/resources/com/hospital/front/mapper/nx/NxOrderMapper.xml b/src/main/resources/com/hospital/front/mapper/nx/NxOrderMapper.xml index 7a208a8..6d97b92 100644 --- a/src/main/resources/com/hospital/front/mapper/nx/NxOrderMapper.xml +++ b/src/main/resources/com/hospital/front/mapper/nx/NxOrderMapper.xml @@ -69,7 +69,7 @@ )} - SELECT PE_ID, NAME, @@ -144,17 +144,7 @@ - - select PE_ID, '' PE_VISIT_ID, PE_DEPT_CODE, @@ -165,7 +155,7 @@ and CONCLUSION_TEXT is not null - SELECT top 1 PE_ID, REPLACE( @@ -183,25 +173,7 @@ where PE_ID = #{peId} AND REC_CONTENT IS NOT NULL - - SELECT PE_ID, NAME, @@ -314,23 +286,6 @@ group by id_no,NAME,PE_ID,UNIT_NAME - - - - SELECT DISTINCT PE_ID AS "peId", ID_NO AS "idNo", NAME AS "name", diff --git a/src/main/resources/com/hospital/front/mapper/ya/YaOrderMapper.xml b/src/main/resources/com/hospital/front/mapper/ya/YaOrderMapper.xml index 26289ca..eba5372 100644 --- a/src/main/resources/com/hospital/front/mapper/ya/YaOrderMapper.xml +++ b/src/main/resources/com/hospital/front/mapper/ya/YaOrderMapper.xml @@ -57,7 +57,7 @@ )} - SELECT t.tjh PE_ID, t.xm NAME, @@ -156,14 +156,7 @@ and TJZBXBM is not null - - select TJH PE_ID,'' PE_VISIT_ID, REPLACE(REPLACE(REPLACE(REPLACE(TJJL,CHAR(10),''), ' ', ''),char(9),''),char(13),'') CONCLUSION_TEXT from V_TJJY @@ -177,15 +170,7 @@ and CONCLUSION_TEXT is not null --> - - select TJH PE_ID,'' PE_VISIT_ID, REPLACE(REPLACE(REPLACE(REPLACE(TJJL,CHAR(10),''), ' ', ''),char(9),''),char(13),'') REC_CONTENT, REPLACE(REPLACE(REPLACE(REPLACE(TJJY,CHAR(10),''), ' ', ''),char(9),''),char(13),'') GUIDE_CONTENT @@ -199,7 +184,7 @@ where PE_ID = #{peId} and GUIDE_CONTENT is not null --> - SELECT t.tjh PE_ID, t.xm NAME, @@ -262,30 +247,12 @@ group by SFZH,XM,TJH,DWMC - - - - - - SELECT DISTINCT TJH AS "peId", SFZH AS "idNo", XM AS "name",