From b46b8b8fee4d10e52dd882febc07974b02e2aed9 Mon Sep 17 00:00:00 2001
From: liusheng <337615773@qq.com>
Date: 星期二, 03 十一月 2026 14:14:18 +0800
Subject: [PATCH] 本地测试前提交:跨模块收口相关源码改动
---
ruoyi-common/src/main/resources/mapper/common/Icd10Mapper.xml | 221 +
ruoyi-common/src/main/java/com/ruoyi/common/mapper/MedicationDoseInfoMapper.java | 63
ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskRecordMapper.java | 68
ruoyi-common/src/main/java/com/ruoyi/common/utils/DistinctByProperty.java | 24
smartor/src/main/java/com/smartor/service/IPatMedOuthospService.java | 68
smartor/src/main/java/com/smartor/service/impl/bridge/PublicityDataPortBridge.java | 330 ++
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MedicationDoseInfo.java | 59
ruoyi-common/src/main/java/com/ruoyi/common/core/service/IIcd10Service.java | 68
ruoyi-common/src/main/resources/mapper/common/MedicationItemMapper.xml | 434 +++
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MedicationItem.java | 169 +
ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysDept2Mapper.java | 132 +
ruoyi-task/src/main/java/com/ruoyi/task/api/contract/OperationSubtaskWriter.java | 730 ++++++
ruoyi-task/src/main/java/com/ruoyi/task/service/IServiceSubtaskRecordService.java | 67
ruoyi-task/src/main/java/com/ruoyi/task/api/contract/OtherVisitApiImpl.java | 58
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/TaskOpsTriggerApiImpl.java | 82
ruoyi-common/src/main/java/com/ruoyi/common/enums/ImportFlagEnum.java | 82
ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/api/OuthospVisitApiImpl.java | 37
ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUserDeptMapper.java | 76
ruoyi-system/src/main/resources/mapper/system/ext/SysUserDeptMapper.xml | 295 ++
ruoyi-system/src/main/resources/mapper/system/ext/SysUserRole2Mapper.xml | 62
ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskRecordServiceImpl.java | 102
ruoyi-common/src/main/java/com/ruoyi/common/mapper/MedicationItemMapper.java | 63
ruoyi-system/src/main/resources/mapper/system/ext/SysUser2Mapper.xml | 432 +++
ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskPreachformMapper.java | 78
ruoyi-task/src/main/java/com/ruoyi/task/api/contract/PreachformApiImpl.java | 158 +
ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/support/MydOptionRatioPieChartBuilder.java | 296 ++
ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskPreachformMapper.xml | 331 ++
ruoyi-system/src/main/resources/mapper/system/ext/SysDept2Mapper.xml | 363 +++
ruoyi-common/src/main/java/com/ruoyi/common/mapper/Icd10Mapper.java | 88
ruoyi-admin/src/main/resources/application.yml | 2
ruoyi-task/src/main/java/com/ruoyi/task/api/contract/ScheduleRollPortImpl.java | 315 ++
ruoyi-common/src/main/resources/mapper/common/MedicationDoseInfoMapper.xml | 172 +
ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/MedicationDoseInfoServiceImpl.java | 96
ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/MedicationItemServiceImpl.java | 96
ruoyi-common/src/main/java/com/ruoyi/common/enums/EmergencyLevelEnum.java | 77
smartor/src/main/java/com/smartor/service/impl/PatMedOuthospServiceDelegatingImpl.java | 423 +++
/dev/null | 4
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/Icd10.java | 122 +
ruoyi-common/src/main/java/com/ruoyi/common/core/service/IMedicationDoseInfoService.java | 61
ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUser2Mapper.java | 137 +
ruoyi-common/src/main/java/com/ruoyi/common/core/service/IMedicationItemService.java | 61
ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskRecordMapper.xml | 179 +
ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/Icd10ServiceImpl.java | 261 ++
ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUserRole2Mapper.java | 66
44 files changed, 7,103 insertions(+), 5 deletions(-)
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index f2039f0..abecd88 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -78,7 +78,7 @@
# 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
basename: i18n/messages
profiles:
- active: nhfy
+ active: druid
# 鏂囦欢涓婁紶
servlet:
diff --git a/ruoyi-common/- b/ruoyi-common/-
deleted file mode 100644
index 85a7368..0000000
--- a/ruoyi-common/-
+++ /dev/null
@@ -1,4 +0,0 @@
-
-The following files have been resolved:
- org.projectlombok:lombok:jar:1.18.34:compile
-
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/Icd10.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/Icd10.java
new file mode 100644
index 0000000..a2269e8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/Icd10.java
@@ -0,0 +1,122 @@
+package com.ruoyi.common.core.domain.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+import java.util.List;
+
+/**
+ * 鐤剧梾瀵硅薄 icd10
+ *
+ * @author ruoyi
+ * @date 2023-12-21
+ */
+@ApiModel(value = "Icd10", description = "鐤剧梾瀵硅薄")
+@Data
+public class Icd10 extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * $column.columnComment
+ */
+ @ApiModelProperty("涓婚敭")
+ private Long icdid;
+
+ /**
+ * icd10缂栫爜
+ */
+ @ApiModelProperty("icd10缂栫爜")
+ @Excel(name = "icd10缂栫爜")
+ private String icdcode;
+
+ /**
+ * HIS鐨刬cd10id
+ */
+ @ApiModelProperty("HIS鐨刬cd10id")
+ @Excel(name = "HIS鐨刬cd10id")
+ private String hisIcdid;
+
+ /**
+ * icd10鍚嶇О
+ */
+ @ApiModelProperty("icd10鍚嶇О")
+ @Excel(name = "icd10鍚嶇О")
+ private String icdname;
+
+ /**
+ * 鎷奸煶鐮�
+ */
+ @ApiModelProperty("鎷奸煶鐮�")
+ @Excel(name = "鎷奸煶鐮�")
+ private String icdpym;
+
+ /**
+ * 浜旂瑪鐮�
+ */
+ @ApiModelProperty("浜旂瑪鐮�")
+ @Excel(name = "浜旂瑪鐮�")
+ private String icdwbm;
+
+ /**
+ * 鏈烘瀯id
+ */
+ @ApiModelProperty("鏈烘瀯id")
+ @Excel(name = "鏈烘瀯id")
+ private String orgid;
+
+ /**
+ * 鍒犻櫎鏍囪瘑
+ */
+ @ApiModelProperty("鍒犻櫎鏍囪瘑")
+ private String delFlag;
+
+ /**
+ * 鐖禝D
+ */
+ @ApiModelProperty("鐖禝D")
+ @Excel(name = "鐖禝D")
+ private Long pid;
+
+ /**
+ * GUID
+ */
+ @ApiModelProperty("GUID")
+ @Excel(name = "GUID")
+ private String guid;
+
+ /**
+ * pageNum
+ */
+ @ApiModelProperty("pageNum")
+ private Integer pageNum;
+
+ /**
+ * pageSize
+ */
+ @ApiModelProperty("pageSize")
+ private Integer pageSize;
+
+ /**
+ * 鏈骇鏍囧織
+ */
+ @ApiModelProperty("lastflag")
+ private String lastflag;
+
+ /**
+ * 涓尰鏍囧織
+ */
+ @ApiModelProperty("chimedflag")
+ private String chimedflag;
+
+ /**
+ * icd10缂栫爜
+ */
+ @ApiModelProperty("icd10缂栫爜闆嗗悎")
+ @Excel(name = "icd10缂栫爜闆嗗悎")
+ private List<String> icdcodes;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MedicationDoseInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MedicationDoseInfo.java
new file mode 100644
index 0000000..8646a8c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MedicationDoseInfo.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.core.domain.entity;
+
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 鑽搧鍓傞噺淇℃伅瀵硅薄 medication_dose_info
+ *
+ * @author lihu
+ * @date 2026-07-17
+ */
+@Data
+@ApiModel("鑽搧鍓傞噺淇℃伅")
+public class MedicationDoseInfo extends BaseEntity
+ {
+private static final long serialVersionUID = 1L;
+
+ /** 涓婚敭ID */
+ @ApiModelProperty("涓婚敭ID")
+ //鏁版嵁搴撹嚜澧炴敼鎴怈TableId(type = IdType.AUTO)
+ private Long id;
+
+ /** 鑽搧ID锛堝叧鑱攎edication_item.id锛� */
+ @ApiModelProperty("鑽搧ID锛堝叧鑱攎edication_item.id锛�")
+ @Excel(name = "鑽搧ID", readConverterExp = "鍏�=鑱攎edication_item.id")
+ private Long medicationItemId;
+
+ /** 鍓傞噺灏忓寘瑁呰浆鎹㈡瘮 */
+ @ApiModelProperty("鍓傞噺灏忓寘瑁呰浆鎹㈡瘮")
+ @Excel(name = "鍓傞噺灏忓寘瑁呰浆鎹㈡瘮")
+ private BigDecimal doseSmallPackageRation;
+
+ /** 鍓傞噺 */
+ @ApiModelProperty("鍓傞噺")
+ @Excel(name = "鍓傞噺")
+ private Long dose;
+
+ /** 鍓傞噺灏忓寘瑁呮暟閲� */
+ @ApiModelProperty("鍓傞噺灏忓寘瑁呮暟閲�")
+ @Excel(name = "鍓傞噺灏忓寘瑁呮暟閲�")
+ private Long doseSmallPackageNum;
+
+ /** 鍓傞噺鍗曚綅 */
+ @ApiModelProperty("鍓傞噺鍗曚綅")
+ @Excel(name = "鍓傞噺鍗曚綅")
+ private String doseUnit;
+
+ /** 鍓傞噺鍗曚綅绫诲瀷 */
+ @ApiModelProperty("鍓傞噺鍗曚綅绫诲瀷")
+ @Excel(name = "鍓傞噺鍗曚綅绫诲瀷")
+ private Long doseUnitType;
+
+ }
+
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MedicationItem.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MedicationItem.java
new file mode 100644
index 0000000..b492c11
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/MedicationItem.java
@@ -0,0 +1,169 @@
+package com.ruoyi.common.core.domain.entity;
+
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.MedicationDoseInfo;
+
+/**
+ * 鑽搧淇℃伅瀵硅薄 medication_item
+ *
+ * @author lihu
+ * @date 2026-07-17
+ */
+@Data
+@ApiModel("鑽搧淇℃伅")
+public class MedicationItem extends BaseEntity
+ {
+private static final long serialVersionUID = 1L;
+
+ /** 涓婚敭ID */
+ @ApiModelProperty("涓婚敭ID")
+ //鏁版嵁搴撹嚜澧炴敼鎴怈TableId(type = IdType.AUTO)
+ private Long id;
+
+ /** 鑽搧璇嗗埆鐮� */
+ @ApiModelProperty("鑽搧璇嗗埆鐮�")
+ @Excel(name = "鑽搧璇嗗埆鐮�")
+ private String identificationCode;
+
+ /** 浜旂瑪鐮� */
+ @ApiModelProperty("浜旂瑪鐮�")
+ @Excel(name = "浜旂瑪鐮�")
+ private String wbm;
+
+ /** 鑽搧閫氱敤鍚� */
+ @ApiModelProperty("鑽搧閫氱敤鍚�")
+ @Excel(name = "鑽搧閫氱敤鍚�")
+ private String medicationCommonName;
+
+ /** 鐢熶骇鍘傚鍚嶇О */
+ @ApiModelProperty("鐢熶骇鍘傚鍚嶇О")
+ @Excel(name = "鐢熶骇鍘傚鍚嶇О")
+ private String manufacturerName;
+
+ /** 鑽搧缂栫爜 */
+ @ApiModelProperty("鑽搧缂栫爜")
+ @Excel(name = "鑽搧缂栫爜")
+ private String itemCode;
+
+ /** 澶у皬鍖呰杞崲姣� */
+ @ApiModelProperty("澶у皬鍖呰杞崲姣�")
+ @Excel(name = "澶у皬鍖呰杞崲姣�")
+ private Long smallLargePackageRatio;
+
+ /** 鏈烘瀯ID */
+ @ApiModelProperty("鏈烘瀯ID")
+ @Excel(name = "鏈烘瀯ID")
+ private Long orgId;
+
+ /** 鑽搧鍚嶇О */
+ @ApiModelProperty("鑽搧鍚嶇О")
+ @Excel(name = "鑽搧鍚嶇О")
+ private String itemName;
+
+ /** 鑽搧绫诲瀷 */
+ @ApiModelProperty("鑽搧绫诲瀷")
+ @Excel(name = "鑽搧绫诲瀷")
+ private String medicationType;
+
+ /** 鎶楄弻鑽墿绛夌骇缂栫爜 */
+ @ApiModelProperty("鎶楄弻鑽墿绛夌骇缂栫爜")
+ @Excel(name = "鎶楄弻鑽墿绛夌骇缂栫爜")
+ private String antimicrobialGradeCode;
+
+ /** 鎵瑰噯鏂囧彿 */
+ @ApiModelProperty("鎵瑰噯鏂囧彿")
+ @Excel(name = "鎵瑰噯鏂囧彿")
+ private String licenseNumber;
+
+ /** 榛樿鐢ㄦ硶鍚嶇О */
+ @ApiModelProperty("榛樿鐢ㄦ硶鍚嶇О")
+ @Excel(name = "榛樿鐢ㄦ硶鍚嶇О")
+ private String defaultUsageName;
+
+ /** 鐗规畩鑽搧鍚嶇О */
+ @ApiModelProperty("鐗规畩鑽搧鍚嶇О")
+ @Excel(name = "鐗规畩鑽搧鍚嶇О")
+ private String specialDrugsName;
+
+ /** 鎶楄弻鑽墿绛夌骇鍚嶇О */
+ @ApiModelProperty("鎶楄弻鑽墿绛夌骇鍚嶇О")
+ @Excel(name = "鎶楄弻鑽墿绛夌骇鍚嶇О")
+ private String antimicrobialGradeName;
+
+ /** 閫氱敤鍚嶆嫾闊� */
+ @ApiModelProperty("閫氱敤鍚嶆嫾闊�")
+ @Excel(name = "閫氱敤鍚嶆嫾闊�")
+ private String commonPinyin;
+
+ /** 閫氱敤鍚嶄簲绗旂爜 */
+ @ApiModelProperty("閫氱敤鍚嶄簲绗旂爜")
+ @Excel(name = "閫氱敤鍚嶄簲绗旂爜")
+ private String commonWbm;
+
+ /** 鐢熶骇鍘傚ID */
+ @ApiModelProperty("鐢熶骇鍘傚ID")
+ @Excel(name = "鐢熶骇鍘傚ID")
+ private Long manufacturerId;
+
+ /** 榛樿鐢ㄦ硶ID */
+ @ApiModelProperty("榛樿鐢ㄦ硶ID")
+ @Excel(name = "榛樿鐢ㄦ硶ID")
+ private Long defaultUsageId;
+
+ /** 瑙勬牸 */
+ @ApiModelProperty("瑙勬牸")
+ @Excel(name = "瑙勬牸")
+ private String specification;
+
+ /** 灏忓寘瑁呭崟浣� */
+ @ApiModelProperty("灏忓寘瑁呭崟浣�")
+ @Excel(name = "灏忓寘瑁呭崟浣�")
+ private String smallPackageUnit;
+
+ /** 鑽搧ID锛堜笟鍔′富閿級 */
+ @ApiModelProperty("鑽搧ID锛堜笟鍔′富閿級")
+ @Excel(name = "鑽搧ID", readConverterExp = "涓�=鍔′富閿�")
+ private Long itemId;
+
+ /** 鐗规畩鑽搧缂栫爜 */
+ @ApiModelProperty("鐗规畩鑽搧缂栫爜")
+ @Excel(name = "鐗规畩鑽搧缂栫爜")
+ private String specialDrugsCode;
+
+ /** 鎷奸煶 */
+ @ApiModelProperty("鎷奸煶")
+ @Excel(name = "鎷奸煶")
+ private String pinyin;
+
+ /** 鍓傚瀷鍚嶇О */
+ @ApiModelProperty("鍓傚瀷鍚嶇О")
+ @Excel(name = "鍓傚瀷鍚嶇О")
+ private String doseFormName;
+
+ /** 澶у寘瑁呭崟浣� */
+ @ApiModelProperty("澶у寘瑁呭崟浣�")
+ @Excel(name = "澶у寘瑁呭崟浣�")
+ private String largePackageUnit;
+
+ /** 闆跺敭浠� */
+ @ApiModelProperty("闆跺敭浠�")
+ @Excel(name = "闆跺敭浠�")
+ private BigDecimal retailPrice;
+
+ /** 鐘舵�� */
+ @ApiModelProperty("鐘舵��")
+ @Excel(name = "鐘舵��")
+ private Long status;
+
+ @ApiModelProperty("鍓傞噺淇℃伅鍒楄〃")
+ private List<MedicationDoseInfo> doseInfoList;
+
+ }
+
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IIcd10Service.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IIcd10Service.java
new file mode 100644
index 0000000..4619477
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IIcd10Service.java
@@ -0,0 +1,68 @@
+package com.ruoyi.common.core.service;
+
+import com.ruoyi.common.core.domain.entity.Icd10;
+
+import java.util.List;
+
+/**
+ * 鐤剧梾Service鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2023-12-21
+ */
+public interface IIcd10Service {
+ /**
+ * 鏌ヨ鐤剧梾
+ *
+ * @param icdid 鐤剧梾涓婚敭
+ * @return 鐤剧梾
+ */
+ public Icd10 selectIcd10ByIcdid(Long icdid);
+
+ /**
+ * 鏌ヨ鐤剧梾鍒楄〃
+ *
+ * @param icd10 鐤剧梾
+ * @return 鐤剧梾闆嗗悎
+ */
+ public List<Icd10> selectIcd10List(Icd10 icd10);
+
+ /**
+ * 鏂板鐤剧梾
+ *
+ * @param icd10 鐤剧梾
+ * @return 缁撴灉
+ */
+ public int insertIcd10(Icd10 icd10);
+
+ /**
+ * 淇敼鐤剧梾
+ *
+ * @param icd10 鐤剧梾
+ * @return 缁撴灉
+ */
+ public int updateIcd10(Icd10 icd10);
+
+ /**
+ * 鎵归噺鍒犻櫎鐤剧梾
+ *
+ * @param icdids 闇�瑕佸垹闄ょ殑鐤剧梾涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteIcd10ByIcdids(Long[] icdids);
+
+ /**
+ * 鍒犻櫎鐤剧梾淇℃伅
+ *
+ * @param icdid 鐤剧梾涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteIcd10ByIcdid(Long icdid);
+
+ /**
+ * 浠庤繙绋嬫帴鍙o紙鏉ユ湭鏉ワ級鍒嗛〉鎷夊彇骞跺閲忓啓鍏� icd10 琛�
+ *
+ * @return 鏂板鏉℃暟
+ */
+ public int queryAddIcd10();
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IMedicationDoseInfoService.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IMedicationDoseInfoService.java
new file mode 100644
index 0000000..b8fa7f4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IMedicationDoseInfoService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.common.core.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.MedicationDoseInfo;
+
+/**
+ * 鑽搧鍓傞噺淇℃伅Service鎺ュ彛
+ *
+ * @author lihu
+ * @date 2026-07-17
+ */
+public interface IMedicationDoseInfoService
+{
+ /**
+ * 鏌ヨ鑽搧鍓傞噺淇℃伅
+ *
+ * @param id 鑽搧鍓傞噺淇℃伅涓婚敭
+ * @return 鑽搧鍓傞噺淇℃伅
+ */
+ public MedicationDoseInfo selectMedicationDoseInfoById(Long id);
+
+ /**
+ * 鏌ヨ鑽搧鍓傞噺淇℃伅鍒楄〃
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 鑽搧鍓傞噺淇℃伅闆嗗悎
+ */
+ public List<MedicationDoseInfo> selectMedicationDoseInfoList(MedicationDoseInfo medicationDoseInfo);
+
+ /**
+ * 鏂板鑽搧鍓傞噺淇℃伅
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertMedicationDoseInfo(MedicationDoseInfo medicationDoseInfo);
+
+ /**
+ * 淇敼鑽搧鍓傞噺淇℃伅
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateMedicationDoseInfo(MedicationDoseInfo medicationDoseInfo);
+
+ /**
+ * 鎵归噺鍒犻櫎鑽搧鍓傞噺淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鑽搧鍓傞噺淇℃伅涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteMedicationDoseInfoByIds(Long[] ids);
+
+ /**
+ * 鍒犻櫎鑽搧鍓傞噺淇℃伅淇℃伅
+ *
+ * @param id 鑽搧鍓傞噺淇℃伅涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteMedicationDoseInfoById(Long id);
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IMedicationItemService.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IMedicationItemService.java
new file mode 100644
index 0000000..d36e046
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/IMedicationItemService.java
@@ -0,0 +1,61 @@
+package com.ruoyi.common.core.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.MedicationItem;
+
+/**
+ * 鑽搧淇℃伅Service鎺ュ彛
+ *
+ * @author lihu
+ * @date 2026-07-17
+ */
+public interface IMedicationItemService
+{
+ /**
+ * 鏌ヨ鑽搧淇℃伅
+ *
+ * @param id 鑽搧淇℃伅涓婚敭
+ * @return 鑽搧淇℃伅
+ */
+ public MedicationItem selectMedicationItemById(Long id);
+
+ /**
+ * 鏌ヨ鑽搧淇℃伅鍒楄〃
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 鑽搧淇℃伅闆嗗悎
+ */
+ public List<MedicationItem> selectMedicationItemList(MedicationItem medicationItem);
+
+ /**
+ * 鏂板鑽搧淇℃伅
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertMedicationItem(MedicationItem medicationItem);
+
+ /**
+ * 淇敼鑽搧淇℃伅
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateMedicationItem(MedicationItem medicationItem);
+
+ /**
+ * 鎵归噺鍒犻櫎鑽搧淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鑽搧淇℃伅涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteMedicationItemByIds(Long[] ids);
+
+ /**
+ * 鍒犻櫎鑽搧淇℃伅淇℃伅
+ *
+ * @param id 鑽搧淇℃伅涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteMedicationItemById(Long id);
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/Icd10ServiceImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/Icd10ServiceImpl.java
new file mode 100644
index 0000000..03613a0
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/Icd10ServiceImpl.java
@@ -0,0 +1,261 @@
+package com.ruoyi.common.core.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.google.gson.Gson;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.http.HttpUtils;
+import com.ruoyi.common.core.domain.entity.Icd10;
+import com.ruoyi.common.mapper.Icd10Mapper;
+import com.ruoyi.common.core.service.IIcd10Service;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 鐤剧梾Service涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ * @date 2023-12-21
+ */
+@Slf4j
+@Service
+public class Icd10ServiceImpl implements IIcd10Service {
+
+ @Autowired
+ private Icd10Mapper icd10Mapper;
+
+ @Value("${sltd_pub_path}")
+ private String sltdPubPath;
+
+ @Value("${lwl_app_key}")
+ private String APP_KEY;
+
+ /**
+ * 鍥哄畾 orgId
+ */
+ private static final long ORG_ID = 20001001L;
+ /**
+ * 姣忛〉鎷夊彇鏉℃暟锛堟帴鍙f渶澶у厑璁� 1000锛�
+ */
+ private static final int PAGE_SIZE = 1000;
+ /**
+ * 鎵归噺鍐欏叆鍗曟壒鏈�澶ф潯鏁�
+ */
+ private static final int BATCH_SIZE = 500;
+
+ /**
+ * 鏌ヨ鐤剧梾
+ *
+ * @param icdid 鐤剧梾涓婚敭
+ * @return 鐤剧梾
+ */
+ @Override
+ public Icd10 selectIcd10ByIcdid(Long icdid) {
+ return icd10Mapper.selectIcd10ByIcdid(icdid);
+ }
+
+ /**
+ * 鏌ヨ鐤剧梾鍒楄〃
+ *
+ * @param icd10 鐤剧梾
+ * @return 鐤剧梾
+ */
+ @Override
+ public List<Icd10> selectIcd10List(Icd10 icd10) {
+ return icd10Mapper.selectIcd10List(icd10);
+ }
+
+ /**
+ * 鏂板鐤剧梾
+ *
+ * @param icd10 鐤剧梾
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertIcd10(Icd10 icd10) {
+ icd10.setCreateTime(DateUtils.getNowDate());
+ return icd10Mapper.insertIcd10(icd10);
+ }
+
+ /**
+ * 淇敼鐤剧梾
+ *
+ * @param icd10 鐤剧梾
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateIcd10(Icd10 icd10) {
+ icd10.setUpdateTime(DateUtils.getNowDate());
+ return icd10Mapper.updateIcd10(icd10);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鐤剧梾
+ *
+ * @param icdids 闇�瑕佸垹闄ょ殑鐤剧梾涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteIcd10ByIcdids(Long[] icdids) {
+ return icd10Mapper.deleteIcd10ByIcdids(icdids);
+ }
+
+ /**
+ * 鍒犻櫎鐤剧梾淇℃伅
+ *
+ * @param icdid 鐤剧梾涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteIcd10ByIcdid(Long icdid) {
+ return icd10Mapper.deleteIcd10ByIcdid(icdid);
+ }
+
+ /**
+ * 浠庤繙绋嬫帴鍙o紙鏉ユ湭鏉ワ級鍒嗛〉鎷夊彇骞跺閲忓啓鍏� icd10 琛ㄣ��
+ * <p>
+ * 浼樺寲瑕佺偣锛�
+ * 1. 姣忛〉鏈�澶ф媺鍙� 1000 鏉★紝鍑忓皯璇锋眰娆℃暟銆�
+ * 2. 姣忛〉鎶婂綋鍓嶉〉鎵�鏈� icdcode 鐢ㄤ竴鏉� IN SQL 涓�娆℃壒閲忔煡搴擄紝閬垮厤寰幆 N 娆″崟鏉℃煡璇€��
+ * 3. 灏嗕笉瀛樺湪鐨勮褰曟敹闆嗗悗鍒嗘壒锛堟瘡鎵� 500 鏉★級鎵归噺鎻掑叆銆�
+ * </p>
+ *
+ * @return 鏈杩愯鏂板鎬绘潯鏁�
+ */
+ @Override
+ public int queryAddIcd10() {
+ int totalInserted = 0;
+ long current = 1;
+ long totalPages = 1; // 棣栨寰幆鍓嶅厛鎵ц涓�娆�
+
+ log.info("[寮�濮媇 浠庢潵鏈潵鎷夊彇 ICD10 澧為噺鏁版嵁锛宱rgId={}", ORG_ID);
+
+ do {
+ // 鏋勫缓璇锋眰浣�
+ Map<String, Object> requestBody = new HashMap<>();
+ requestBody.put("orgId", ORG_ID);
+ requestBody.put("searchText", "");
+ requestBody.put("size", PAGE_SIZE);
+ requestBody.put("current", current);
+
+ String responseStr;
+ try {
+ Map<String, String> headers = buildRequestHeaders();
+ responseStr = HttpUtils.sendPostByHeader(sltdPubPath + "/hbos-thirdparty-integration/standard/base/dtc/pageDiagnosisDict", new Gson().toJson(requestBody), headers);
+
+ } catch (Exception e) {
+ log.error("[绗瑊}椤礭 璇锋眰鏉ユ湭鏉ユ帴鍙eけ璐�", current, e);
+ break;
+ }
+
+ if (responseStr == null || responseStr.isEmpty()) {
+ log.warn("[绗瑊}椤礭 鎺ュ彛杩斿洖绌猴紝鍋滄閲囬泦", current);
+ break;
+ }
+
+ JSONObject resp = JSON.parseObject(responseStr);
+ if (resp == null || !Boolean.TRUE.equals(resp.getBoolean("success"))) {
+ log.error("[绗瑊}椤礭 鎺ュ彛杩斿洖澶辫触锛歿}", current, responseStr);
+ break;
+ }
+
+ JSONObject data = resp.getJSONObject("data");
+ if (data == null) {
+ break;
+ }
+
+ // 璁$畻鎬婚〉鏁�
+ long total = data.getLongValue("total");
+ long pageSize = data.getLongValue("size");
+ if (pageSize <= 0) {
+ break;
+ }
+ totalPages = (total + pageSize - 1) / pageSize;
+
+ JSONArray records = data.getJSONArray("records");
+ if (records == null || records.isEmpty()) {
+ break;
+ }
+
+ log.info("[绗瑊}/{}椤礭 鑾峰彇 {} 鏉¤褰曪紝鎬粄}鏉�", current, totalPages, records.size(), total);
+
+ // 瑙f瀽褰撳墠椤垫暟鎹�
+ List<String> pageNames = new ArrayList<>();
+ List<Icd10> pageList = new ArrayList<>();
+ for (int i = 0; i < records.size(); i++) {
+ JSONObject rec = records.getJSONObject(i);
+ String icdCode = rec.getString("icdCode");
+ if (icdCode == null || icdCode.isEmpty()) {
+ continue;
+ }
+ String icdName = StringUtils.isEmpty(rec.getString("name")) ? null : rec.getString("name").trim();
+ if (icdName == null || icdName.isEmpty()) {
+ continue;
+ }
+ pageNames.add(icdName);
+
+ Icd10 icd10 = new Icd10();
+ icd10.setIcdcode(icdCode);
+ icd10.setIcdname(icdName);
+ icd10.setIcdpym(rec.getString("pinyin"));
+ icd10.setHisIcdid(rec.getString("his_icdid"));
+ icd10.setOrgid(String.valueOf(ORG_ID));
+ icd10.setDelFlag("0");
+ icd10.setCreateTime(DateUtils.getNowDate());
+ pageList.add(icd10);
+ }
+
+ if (pageNames.isEmpty()) {
+ current++;
+ continue;
+ }
+
+ // 涓�娆� IN 鏌ュ簱锛岃幏鍙栧凡瀛樺湪鐨� icdname锛堟牳蹇冨幓閲嶄紭鍖栫偣锛夊崡鍗庨檮涓�鐨刬cdname涓嶄細閲嶅锛宨cd10code浼氶噸澶�
+ Set<String> existingNames = new HashSet<>(icd10Mapper.selectExistingIcdcodes(pageNames));
+
+ // 杩囨护鍑轰笉瀛樺湪鐨勮褰�
+ List<Icd10> newList = pageList.stream().filter(item -> !existingNames.contains(item.getIcdname())).collect(Collectors.toList());
+
+ log.info("[绗瑊}/{}椤礭 褰撳墠椤靛叡 {} 鏉★紝宸插瓨鍦� {} 鏉★紝闇�鏂板叆搴� {} 鏉�", current, totalPages, pageList.size(), existingNames.size(), newList.size());
+
+ // 鍒嗘壒鎵归噺鎻掑叆
+ int inserted = batchInsert(newList);
+ totalInserted += inserted;
+
+ current++;
+ } while (current <= totalPages);
+
+ log.info("[瀹屾垚] ICD10 澧為噺閲囬泦缁撴潫锛屾湰娆″叡鏂板 {} 鏉�", totalInserted);
+ return totalInserted;
+ }
+
+ /**
+ * 鍒嗘壒鎵归噺鎻掑叆锛屾瘡鎵规渶澶� BATCH_SIZE 鏉�
+ */
+ private int batchInsert(List<Icd10> list) {
+ if (list == null || list.isEmpty()) {
+ return 0;
+ }
+ int total = 0;
+ int size = list.size();
+ for (int start = 0; start < size; start += BATCH_SIZE) {
+ int end = Math.min(start + BATCH_SIZE, size);
+ total += icd10Mapper.batchIcd10(list.subList(start, end));
+ }
+ return total;
+ }
+
+ private Map<String, String> buildRequestHeaders() {
+ Map<String, String> headers = new HashMap<>();
+ headers.put("Content-Type", "application/json");
+ headers.put("app-key", APP_KEY);
+ return headers;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/MedicationDoseInfoServiceImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/MedicationDoseInfoServiceImpl.java
new file mode 100644
index 0000000..ed57533
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/MedicationDoseInfoServiceImpl.java
@@ -0,0 +1,96 @@
+package com.ruoyi.common.core.service.impl;
+
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.mapper.MedicationDoseInfoMapper;
+import com.ruoyi.common.core.domain.entity.MedicationDoseInfo;
+import com.ruoyi.common.core.service.IMedicationDoseInfoService;
+
+/**
+ * 鑽搧鍓傞噺淇℃伅Service涓氬姟灞傚鐞�
+ *
+ * @author lihu
+ * @date 2026-07-17
+ */
+@Service
+public class MedicationDoseInfoServiceImpl implements IMedicationDoseInfoService
+{
+ @Autowired
+ private MedicationDoseInfoMapper medicationDoseInfoMapper;
+
+ /**
+ * 鏌ヨ鑽搧鍓傞噺淇℃伅
+ *
+ * @param id 鑽搧鍓傞噺淇℃伅涓婚敭
+ * @return 鑽搧鍓傞噺淇℃伅
+ */
+ @Override
+ public MedicationDoseInfo selectMedicationDoseInfoById(Long id)
+ {
+ return medicationDoseInfoMapper.selectMedicationDoseInfoById(id);
+ }
+
+ /**
+ * 鏌ヨ鑽搧鍓傞噺淇℃伅鍒楄〃
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 鑽搧鍓傞噺淇℃伅
+ */
+ @Override
+ public List<MedicationDoseInfo> selectMedicationDoseInfoList(MedicationDoseInfo medicationDoseInfo)
+ {
+ return medicationDoseInfoMapper.selectMedicationDoseInfoList(medicationDoseInfo);
+ }
+
+ /**
+ * 鏂板鑽搧鍓傞噺淇℃伅
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertMedicationDoseInfo(MedicationDoseInfo medicationDoseInfo)
+ {
+ medicationDoseInfo.setCreateTime(DateUtils.getNowDate());
+ return medicationDoseInfoMapper.insertMedicationDoseInfo(medicationDoseInfo);
+ }
+
+ /**
+ * 淇敼鑽搧鍓傞噺淇℃伅
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateMedicationDoseInfo(MedicationDoseInfo medicationDoseInfo)
+ {
+ medicationDoseInfo.setUpdateTime(DateUtils.getNowDate());
+ return medicationDoseInfoMapper.updateMedicationDoseInfo(medicationDoseInfo);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鑽搧鍓傞噺淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鑽搧鍓傞噺淇℃伅涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteMedicationDoseInfoByIds(Long[] ids)
+ {
+ return medicationDoseInfoMapper.deleteMedicationDoseInfoByIds(ids);
+ }
+
+ /**
+ * 鍒犻櫎鑽搧鍓傞噺淇℃伅淇℃伅
+ *
+ * @param id 鑽搧鍓傞噺淇℃伅涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteMedicationDoseInfoById(Long id)
+ {
+ return medicationDoseInfoMapper.deleteMedicationDoseInfoById(id);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/MedicationItemServiceImpl.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/MedicationItemServiceImpl.java
new file mode 100644
index 0000000..46d0837
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/service/impl/MedicationItemServiceImpl.java
@@ -0,0 +1,96 @@
+package com.ruoyi.common.core.service.impl;
+
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.mapper.MedicationItemMapper;
+import com.ruoyi.common.core.domain.entity.MedicationItem;
+import com.ruoyi.common.core.service.IMedicationItemService;
+
+/**
+ * 鑽搧淇℃伅Service涓氬姟灞傚鐞�
+ *
+ * @author lihu
+ * @date 2026-07-17
+ */
+@Service
+public class MedicationItemServiceImpl implements IMedicationItemService
+{
+ @Autowired
+ private MedicationItemMapper medicationItemMapper;
+
+ /**
+ * 鏌ヨ鑽搧淇℃伅
+ *
+ * @param id 鑽搧淇℃伅涓婚敭
+ * @return 鑽搧淇℃伅
+ */
+ @Override
+ public MedicationItem selectMedicationItemById(Long id)
+ {
+ return medicationItemMapper.selectMedicationItemById(id);
+ }
+
+ /**
+ * 鏌ヨ鑽搧淇℃伅鍒楄〃
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 鑽搧淇℃伅
+ */
+ @Override
+ public List<MedicationItem> selectMedicationItemList(MedicationItem medicationItem)
+ {
+ return medicationItemMapper.selectMedicationItemList(medicationItem);
+ }
+
+ /**
+ * 鏂板鑽搧淇℃伅
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertMedicationItem(MedicationItem medicationItem)
+ {
+ medicationItem.setCreateTime(DateUtils.getNowDate());
+ return medicationItemMapper.insertMedicationItem(medicationItem);
+ }
+
+ /**
+ * 淇敼鑽搧淇℃伅
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateMedicationItem(MedicationItem medicationItem)
+ {
+ medicationItem.setUpdateTime(DateUtils.getNowDate());
+ return medicationItemMapper.updateMedicationItem(medicationItem);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鑽搧淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鑽搧淇℃伅涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteMedicationItemByIds(Long[] ids)
+ {
+ return medicationItemMapper.deleteMedicationItemByIds(ids);
+ }
+
+ /**
+ * 鍒犻櫎鑽搧淇℃伅淇℃伅
+ *
+ * @param id 鑽搧淇℃伅涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteMedicationItemById(Long id)
+ {
+ return medicationItemMapper.deleteMedicationItemById(id);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/EmergencyLevelEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/EmergencyLevelEnum.java
new file mode 100644
index 0000000..a1a24fe
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/EmergencyLevelEnum.java
@@ -0,0 +1,77 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 鍏ラ櫌鐢宠绱ф�ョ▼搴︽灇涓�
+ *
+ * @author ruoyi
+ */
+public enum EmergencyLevelEnum {
+
+ /**
+ * 鐩爣
+ */
+ TARGET("FH0164.01", "鐩爣"),
+
+ /**
+ * 鎬ュ嵄閲�
+ */
+ CRITICAL("FH0164.02", "鎬ュ嵄閲�"),
+
+ /**
+ * 鎷╂湡
+ */
+ ELECTIVE("FH0164.03", "鎷╂湡"),
+
+ /**
+ * 鍩虹
+ */
+ BASIC("FH0164.04", "鍩虹");
+
+ private String code;
+ private String desc;
+
+ EmergencyLevelEnum(String code, String desc) {
+ this.code = code;
+ this.desc = desc;
+ }
+
+ public static String getDescByCode(String code) {
+ if (code == null || code.isEmpty()) {
+ return null;
+ }
+ for (EmergencyLevelEnum item : values()) {
+ if (item.getCode().equals(code)) {
+ return item.getDesc();
+ }
+ }
+ return null;
+ }
+
+ public static String getCodeByDesc(String desc) {
+ if (desc == null || desc.isEmpty()) {
+ return null;
+ }
+ for (EmergencyLevelEnum item : values()) {
+ if (item.getDesc().equals(desc)) {
+ return item.getCode();
+ }
+ }
+ return null;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/ImportFlagEnum.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/ImportFlagEnum.java
new file mode 100644
index 0000000..cdb2f65
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/ImportFlagEnum.java
@@ -0,0 +1,82 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 鍏ラ櫌鐢宠閲嶈鎬ф爣璁版灇涓�
+ *
+ * @author ruoyi
+ */
+public enum ImportFlagEnum {
+
+ /**
+ * 鐗圭害浜哄憳
+ */
+ SPECIAL_PERSONNEL("FH0165.98", "鐗圭害浜哄憳"),
+
+ /**
+ * 绂讳紤浜哄憳
+ */
+ RETIRED_CADRE("FH0165.99", "绂讳紤浜哄憳"),
+
+ /**
+ * 鏃�
+ */
+ NONE("FH0165.03", "鏃�"),
+
+ /**
+ * 鏃ラ棿璇婄枟
+ */
+ DAY_TREATMENT("FH0165.02", "鏃ラ棿璇婄枟"),
+
+ /**
+ * 鏃ラ棿鎵嬫湳
+ */
+ DAY_SURGERY("FH0165.01", "鏃ラ棿鎵嬫湳");
+
+ private String code;
+ private String desc;
+
+ ImportFlagEnum(String code, String desc) {
+ this.code = code;
+ this.desc = desc;
+ }
+
+ public static String getDescByCode(String code) {
+ if (code == null || code.isEmpty()) {
+ return null;
+ }
+ for (ImportFlagEnum item : values()) {
+ if (item.getCode().equals(code)) {
+ return item.getDesc();
+ }
+ }
+ return null;
+ }
+
+ public static String getCodeByDesc(String desc) {
+ if (desc == null || desc.isEmpty()) {
+ return null;
+ }
+ for (ImportFlagEnum item : values()) {
+ if (item.getDesc().equals(desc)) {
+ return item.getCode();
+ }
+ }
+ return null;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mapper/Icd10Mapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/mapper/Icd10Mapper.java
new file mode 100644
index 0000000..e7a378f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mapper/Icd10Mapper.java
@@ -0,0 +1,88 @@
+package com.ruoyi.common.mapper;
+
+import com.ruoyi.common.core.domain.entity.Icd10;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 鐤剧梾Mapper鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2023-12-21
+ */
+@Mapper
+public interface Icd10Mapper {
+ /**
+ * 鏌ヨ鐤剧梾
+ *
+ * @param icdid 鐤剧梾涓婚敭
+ * @return 鐤剧梾
+ */
+ public Icd10 selectIcd10ByIcdid(Long icdid);
+
+ /**
+ * 鏌ヨ鐤剧梾鍒楄〃
+ *
+ * @param icd10 鐤剧梾
+ * @return 鐤剧梾闆嗗悎
+ */
+ public List<Icd10> selectIcd10List(Icd10 icd10);
+
+ /**
+ * 鏌ヨ鐤剧梾鍒楄〃
+ *
+ * @param icd10 鐤剧梾
+ * @return 鐤剧梾闆嗗悎
+ */
+ public List<Icd10> exactQueryIcd10List(Icd10 icd10);
+
+ /**
+ * 鏂板鐤剧梾
+ *
+ * @param icd10 鐤剧梾
+ * @return 缁撴灉
+ */
+ public int insertIcd10(Icd10 icd10);
+
+ /**
+ * 鎵归噺鏂板鐤剧梾
+ *
+ * @param icd10s 鐤剧梾闆嗗悎
+ * @return 缁撴灉
+ */
+ public int batchIcd10(List<Icd10> icd10s);
+
+ /**
+ * 鎵归噺鏌ヨ宸插瓨鍦ㄧ殑 icdcode锛堢敤浜庡幓閲嶏級
+ *
+ * @param icdcodes icdcode闆嗗悎
+ * @return 宸插瓨鍦ㄧ殑 icdcode 闆嗗悎
+ */
+ public List<String> selectExistingIcdcodes(@Param("icdnames") List<String> icdnames);
+
+ /**
+ * 淇敼鐤剧梾
+ *
+ * @param icd10 鐤剧梾
+ * @return 缁撴灉
+ */
+ public int updateIcd10(Icd10 icd10);
+
+ /**
+ * 鍒犻櫎鐤剧梾
+ *
+ * @param icdid 鐤剧梾涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteIcd10ByIcdid(Long icdid);
+
+ /**
+ * 鎵归噺鍒犻櫎鐤剧梾
+ *
+ * @param icdids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteIcd10ByIcdids(Long[] icdids);
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mapper/MedicationDoseInfoMapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/mapper/MedicationDoseInfoMapper.java
new file mode 100644
index 0000000..abf6a26
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mapper/MedicationDoseInfoMapper.java
@@ -0,0 +1,63 @@
+package com.ruoyi.common.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Mapper;
+import com.ruoyi.common.core.domain.entity.MedicationDoseInfo;
+
+/**
+ * 鑽搧鍓傞噺淇℃伅Mapper鎺ュ彛
+ *
+ * @author lihu
+ * @date 2026-07-17
+ */
+@Mapper
+public interface MedicationDoseInfoMapper
+{
+ /**
+ * 鏌ヨ鑽搧鍓傞噺淇℃伅
+ *
+ * @param id 鑽搧鍓傞噺淇℃伅涓婚敭
+ * @return 鑽搧鍓傞噺淇℃伅
+ */
+ public MedicationDoseInfo selectMedicationDoseInfoById(Long id);
+
+ /**
+ * 鏌ヨ鑽搧鍓傞噺淇℃伅鍒楄〃
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 鑽搧鍓傞噺淇℃伅闆嗗悎
+ */
+ public List<MedicationDoseInfo> selectMedicationDoseInfoList(MedicationDoseInfo medicationDoseInfo);
+
+ /**
+ * 鏂板鑽搧鍓傞噺淇℃伅
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertMedicationDoseInfo(MedicationDoseInfo medicationDoseInfo);
+
+ /**
+ * 淇敼鑽搧鍓傞噺淇℃伅
+ *
+ * @param medicationDoseInfo 鑽搧鍓傞噺淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateMedicationDoseInfo(MedicationDoseInfo medicationDoseInfo);
+
+ /**
+ * 鍒犻櫎鑽搧鍓傞噺淇℃伅
+ *
+ * @param id 鑽搧鍓傞噺淇℃伅涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteMedicationDoseInfoById(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎鑽搧鍓傞噺淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteMedicationDoseInfoByIds(Long[] ids);
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/mapper/MedicationItemMapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/mapper/MedicationItemMapper.java
new file mode 100644
index 0000000..fecab05
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/mapper/MedicationItemMapper.java
@@ -0,0 +1,63 @@
+package com.ruoyi.common.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Mapper;
+import com.ruoyi.common.core.domain.entity.MedicationItem;
+
+/**
+ * 鑽搧淇℃伅Mapper鎺ュ彛
+ *
+ * @author lihu
+ * @date 2026-07-17
+ */
+@Mapper
+public interface MedicationItemMapper
+{
+ /**
+ * 鏌ヨ鑽搧淇℃伅
+ *
+ * @param id 鑽搧淇℃伅涓婚敭
+ * @return 鑽搧淇℃伅
+ */
+ public MedicationItem selectMedicationItemById(Long id);
+
+ /**
+ * 鏌ヨ鑽搧淇℃伅鍒楄〃
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 鑽搧淇℃伅闆嗗悎
+ */
+ public List<MedicationItem> selectMedicationItemList(MedicationItem medicationItem);
+
+ /**
+ * 鏂板鑽搧淇℃伅
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertMedicationItem(MedicationItem medicationItem);
+
+ /**
+ * 淇敼鑽搧淇℃伅
+ *
+ * @param medicationItem 鑽搧淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateMedicationItem(MedicationItem medicationItem);
+
+ /**
+ * 鍒犻櫎鑽搧淇℃伅
+ *
+ * @param id 鑽搧淇℃伅涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteMedicationItemById(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎鑽搧淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteMedicationItemByIds(Long[] ids);
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DistinctByProperty.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DistinctByProperty.java
new file mode 100644
index 0000000..dc96ac6
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DistinctByProperty.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.utils;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 鍘婚噸宸ュ叿绫�
+ */
+public class DistinctByProperty {
+
+ // 鍒涘缓鍘婚噸宸ュ叿鏂规硶锛屾牴鎹泦鍚堜腑涓婂睘鎬�
+ public static <T> List<T> distinctByProperty(
+ List<T> list,
+ Function<? super T, ?> keyExtractor) {
+
+ Set<Object> seen = new HashSet<>();
+ return list.stream()
+ .filter(item -> seen.add(keyExtractor.apply(item)))
+ .collect(Collectors.toList());
+ }
+}
diff --git a/ruoyi-common/src/main/resources/mapper/common/Icd10Mapper.xml b/ruoyi-common/src/main/resources/mapper/common/Icd10Mapper.xml
new file mode 100644
index 0000000..830e562
--- /dev/null
+++ b/ruoyi-common/src/main/resources/mapper/common/Icd10Mapper.xml
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.common.mapper.Icd10Mapper">
+
+ <resultMap type="com.ruoyi.common.core.domain.entity.Icd10" id="Icd10Result">
+ <result property="icdid" column="icdid"/>
+ <result property="icdcode" column="icdcode"/>
+ <result property="icdname" column="icdname"/>
+ <result property="icdpym" column="icdpym"/>
+ <result property="icdwbm" column="icdwbm"/>
+ <result property="orgid" column="orgid"/>
+ <result property="delFlag" column="del_flag"/>
+ <result property="createBy" column="create_by"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="updateTime" column="update_time"/>
+ <result property="pid" column="pid"/>
+ <result property="guid" column="guid"/>
+ <result property="lastflag" column="lastflag"/>
+ <result property="chimedflag" column="chimedflag"/>
+ <result property="hisIcdid" column="his_icdid"/>
+ </resultMap>
+
+ <sql id="selectIcd10Vo">
+ select icdid,
+ icdcode,
+ his_icdid,
+ lastflag,
+ chimedflag,
+ icdname,
+ icdpym,
+ icdwbm,
+ orgid,
+ del_flag,
+ create_by,
+ create_time,
+ update_by,
+ update_time,
+ pid,
+ guid
+ from icd10
+ </sql>
+
+ <select id="selectIcd10List" parameterType="com.ruoyi.common.core.domain.entity.Icd10" resultMap="Icd10Result">
+ <include refid="selectIcd10Vo"/>
+ where 1=1
+ and del_flag = 0
+ <if test="icdcode != null and icdcode != ''">and icdcode = #{icdcode}</if>
+ <if test="lastflag != null and lastflag != ''">and lastflag = #{lastflag}</if>
+ <if test="chimedflag != null and chimedflag != ''">and chimedflag = #{chimedflag}</if>
+ <if test="icdname != null and icdname != ''">and icdname like concat('%', #{icdname}, '%')</if>
+ <if test="icdpym != null and icdpym != ''">and icdpym = #{icdpym}</if>
+ <if test="icdwbm != null and icdwbm != ''">and icdwbm = #{icdwbm}</if>
+ <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
+ <if test="pid != null ">and pid = #{pid}</if>
+ <if test="guid != null and guid != ''">and guid = #{guid}</if>
+ <if test="hisIcdid != null and hisIcdid != ''">and his_icdid = #{hisIcdid}</if>
+ <if test="icdcodes != null and icdcodes.size() > 0">
+ AND icdcode IN
+ <foreach collection="icdcodes" item="icdcodeItem" open="("
+ separator=","
+ close=")">
+ #{icdcodeItem}
+ </foreach>
+ </if>
+ </select>
+
+ <select id="exactQueryIcd10List" parameterType="com.ruoyi.common.core.domain.entity.Icd10" resultMap="Icd10Result">
+ <include refid="selectIcd10Vo"/>
+ where 1=1
+ and del_flag = 0
+ <if test="icdcode != null and icdcode != ''">and icdcode = #{icdcode}</if>
+ <if test="lastflag != null and lastflag != ''">and lastflag = #{lastflag}</if>
+ <if test="chimedflag != null and chimedflag != ''">and chimedflag = #{chimedflag}</if>
+ <if test="icdname != null and icdname != ''">and icdname = #{icdname} </if>
+ <if test="icdpym != null and icdpym != ''">and icdpym = #{icdpym}</if>
+ <if test="icdwbm != null and icdwbm != ''">and icdwbm = #{icdwbm}</if>
+ <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
+ <if test="pid != null ">and pid = #{pid}</if>
+ <if test="guid != null and guid != ''">and guid = #{guid}</if>
+ <if test="hisIcdid != null and hisIcdid != ''">and his_icdid = #{hisIcdid}</if>
+ <if test="icdcodes != null and icdcodes.size() > 0">
+ AND icdcode IN
+ <foreach collection="icdcodes" item="icdcodeItem" open="("
+ separator=","
+ close=")">
+ #{icdcodeItem}
+ </foreach>
+ </if>
+ </select>
+
+ <select id="selectIcd10ByIcdid" parameterType="Long" resultMap="Icd10Result">
+ <include refid="selectIcd10Vo"/>
+ where icdid = #{icdid}
+ </select>
+
+ <insert id="insertIcd10" parameterType="com.ruoyi.common.core.domain.entity.Icd10" useGeneratedKeys="true" keyProperty="icdid">
+ insert into icd10
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="icdcode != null">icdcode,</if>
+ <if test="icdname != null">icdname,</if>
+ <if test="icdpym != null">icdpym,</if>
+ <if test="icdwbm != null">icdwbm,</if>
+ <if test="orgid != null">orgid,</if>
+ <if test="delFlag != null">del_flag,</if>
+ <if test="createBy != null">create_by,</if>
+ <if test="createTime != null">create_time,</if>
+ <if test="updateBy != null">update_by,</if>
+ <if test="updateTime != null">update_time,</if>
+ <if test="pid != null">pid,</if>
+ <if test="guid != null">guid,</if>
+ <if test="lastflag != null and lastflag != ''">lastflag,</if>
+ <if test="chimedflag != null and chimedflag != ''">chimedflag,</if>
+ <if test="hisIcdid != null and hisIcdid != ''">his_icdid,</if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="icdcode != null">#{icdcode},</if>
+ <if test="icdname != null">#{icdname},</if>
+ <if test="icdpym != null">#{icdpym},</if>
+ <if test="icdwbm != null">#{icdwbm},</if>
+ <if test="orgid != null">#{orgid},</if>
+ <if test="delFlag != null">#{delFlag},</if>
+ <if test="createBy != null">#{createBy},</if>
+ <if test="createTime != null">#{createTime},</if>
+ <if test="updateBy != null">#{updateBy},</if>
+ <if test="updateTime != null">#{updateTime},</if>
+ <if test="pid != null">#{pid},</if>
+ <if test="guid != null">#{guid},</if>
+ <if test="lastflag != null and lastflag != ''">#{lastflag},</if>
+ <if test="chimedflag != null and chimedflag != ''">#{chimedflag},</if>
+ <if test="hisIcdid != null and hisIcdid != ''">#{hisIcdid},</if>
+ </trim>
+ </insert>
+
+ <insert id="batchIcd10">
+ insert into icd10
+ (
+ icdcode,
+ icdname,
+ icdpym,
+ icdwbm,
+ orgid,
+ del_flag,
+ create_by,
+ create_time,
+ update_by,
+ update_time,
+ pid,
+ guid,
+ lastflag,
+ chimedflag,
+ his_icdid)
+ VALUES
+ <foreach collection="list" item="item" separator=",">
+ (
+ #{item.icdcode},
+ #{item.icdname},
+ #{item.icdpym},
+ #{item.icdwbm},
+ #{item.orgid},
+ #{item.delFlag},
+ #{item.createBy},
+ #{item.createTime},
+ #{item.updateBy},
+ #{item.updateTime},
+ #{item.pid},
+ #{item.guid},
+ #{item.lastflag},
+ #{item.chimedflag},
+ #{item.hisIcdid}
+ )
+ </foreach>
+ </insert>
+
+ <update id="updateIcd10" parameterType="com.ruoyi.common.core.domain.entity.Icd10">
+ update icd10
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="icdcode != null">icdcode = #{icdcode},</if>
+ <if test="icdname != null">icdname = #{icdname},</if>
+ <if test="icdpym != null">icdpym = #{icdpym},</if>
+ <if test="icdwbm != null">icdwbm = #{icdwbm},</if>
+ <if test="orgid != null">orgid = #{orgid},</if>
+ <if test="delFlag != null">del_flag = #{delFlag},</if>
+ <if test="createBy != null">create_by = #{createBy},</if>
+ <if test="createTime != null">create_time = #{createTime},</if>
+ <if test="updateBy != null">update_by = #{updateBy},</if>
+ <if test="updateTime != null">update_time = #{updateTime},</if>
+ <if test="pid != null">pid = #{pid},</if>
+ <if test="guid != null">guid = #{guid},</if>
+ <if test="lastflag != null and lastflag != ''">lastflag = #{lastflag},</if>
+ <if test="chimedflag != null and chimedflag != ''">chimedflag = #{chimedflag},</if>
+ <if test="hisIcdid != null and hisIcdid != ''">his_icdid = #{hisIcdid},</if>
+ </trim>
+ where icdid = #{icdid}
+ </update>
+
+ <delete id="deleteIcd10ByIcdid" parameterType="Long">
+ delete
+ from icd10
+ where icdid = #{icdid}
+ </delete>
+
+ <delete id="deleteIcd10ByIcdids" parameterType="String">
+ delete from icd10 where icdid in
+ <foreach item="icdid" collection="array" open="(" separator="," close=")">
+ #{icdid}
+ </foreach>
+ </delete>
+
+ <!-- 鎵归噺鏌ヨ宸插瓨鍦ㄧ殑 icdcode锛岀敤浜庡垎椤垫媺鍙栧悗鍘婚噸 -->
+ <select id="selectExistingIcdcodes" resultType="java.lang.String">
+ select icdname from icd10
+ where del_flag = 0
+ and icdname in
+ <foreach item="icdname" collection="icdnames" open="(" separator="," close=")">
+ #{icdname}
+ </foreach>
+ </select>
+</mapper>
diff --git a/ruoyi-common/src/main/resources/mapper/common/MedicationDoseInfoMapper.xml b/ruoyi-common/src/main/resources/mapper/common/MedicationDoseInfoMapper.xml
new file mode 100644
index 0000000..fd3a4e9
--- /dev/null
+++ b/ruoyi-common/src/main/resources/mapper/common/MedicationDoseInfoMapper.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.common.mapper.MedicationDoseInfoMapper">
+
+ <resultMap type="com.ruoyi.common.core.domain.entity.MedicationDoseInfo" id="MedicationDoseInfoResult">
+ <result property="id" column="id"/>
+ <result property="medicationItemId" column="medication_item_id"/>
+ <result property="doseSmallPackageRation" column="dose_small_package_ration"/>
+ <result property="dose" column="dose"/>
+ <result property="doseSmallPackageNum" column="dose_small_package_num"/>
+ <result property="doseUnit" column="dose_unit"/>
+ <result property="doseUnitType" column="dose_unit_type"/>
+ <result property="remark" column="remark"/>
+ <result property="createBy" column="create_by"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="updateTime" column="update_time"/>
+ </resultMap>
+
+ <sql id="selectMedicationDoseInfoVo">
+ select id, medication_item_id, dose_small_package_ration, dose, dose_small_package_num, dose_unit, dose_unit_type, remark, create_by, create_time, update_by, update_time
+ from medication_dose_info
+ </sql>
+
+ <select id="selectMedicationDoseInfoList" parameterType="com.ruoyi.common.core.domain.entity.MedicationDoseInfo"
+ resultMap="MedicationDoseInfoResult">
+ <include refid="selectMedicationDoseInfoVo"/>
+ where 1=1
+ and del_flag=0
+ <if test="medicationItemId != null ">
+ and medication_item_id = #{medicationItemId}
+ </if>
+ <if test="doseSmallPackageRation != null ">
+ and dose_small_package_ration = #{doseSmallPackageRation}
+ </if>
+ <if test="dose != null ">
+ and dose = #{dose}
+ </if>
+ <if test="doseSmallPackageNum != null ">
+ and dose_small_package_num = #{doseSmallPackageNum}
+ </if>
+ <if test="doseUnit != null and doseUnit != ''">
+ and dose_unit = #{doseUnit}
+ </if>
+ <if test="doseUnitType != null ">
+ and dose_unit_type = #{doseUnitType}
+ </if>
+ </select>
+
+ <select id="selectMedicationDoseInfoById" parameterType="Long"
+ resultMap="MedicationDoseInfoResult">
+ <include refid="selectMedicationDoseInfoVo"/>
+ where id = #{id}
+ </select>
+
+ <insert id="insertMedicationDoseInfo" parameterType="com.ruoyi.common.core.domain.entity.MedicationDoseInfo" useGeneratedKeys="true" keyProperty="id">
+ insert into medication_dose_info
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="medicationItemId != null">medication_item_id,
+ </if>
+ <if test="doseSmallPackageRation != null">dose_small_package_ration,
+ </if>
+ <if test="dose != null">dose,
+ </if>
+ <if test="doseSmallPackageNum != null">dose_small_package_num,
+ </if>
+ <if test="doseUnit != null">dose_unit,
+ </if>
+ <if test="doseUnitType != null">dose_unit_type,
+ </if>
+ <if test="remark != null">remark,
+ </if>
+ <if test="createBy != null">create_by,
+ </if>
+ <if test="createTime != null">create_time,
+ </if>
+ <if test="updateBy != null">update_by,
+ </if>
+ <if test="updateTime != null">update_time,
+ </if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="medicationItemId != null">#{medicationItemId},
+ </if>
+ <if test="doseSmallPackageRation != null">#{doseSmallPackageRation},
+ </if>
+ <if test="dose != null">#{dose},
+ </if>
+ <if test="doseSmallPackageNum != null">#{doseSmallPackageNum},
+ </if>
+ <if test="doseUnit != null">#{doseUnit},
+ </if>
+ <if test="doseUnitType != null">#{doseUnitType},
+ </if>
+ <if test="remark != null">#{remark},
+ </if>
+ <if test="createBy != null">#{createBy},
+ </if>
+ <if test="createTime != null">#{createTime},
+ </if>
+ <if test="updateBy != null">#{updateBy},
+ </if>
+ <if test="updateTime != null">#{updateTime},
+ </if>
+ </trim>
+ </insert>
+
+ <update id="updateMedicationDoseInfo" parameterType="com.ruoyi.common.core.domain.entity.MedicationDoseInfo">
+ update medication_dose_info
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="medicationItemId != null">medication_item_id =
+ #{medicationItemId},
+ </if>
+ <if test="doseSmallPackageRation != null">dose_small_package_ration =
+ #{doseSmallPackageRation},
+ </if>
+ <if test="dose != null">dose =
+ #{dose},
+ </if>
+ <if test="doseSmallPackageNum != null">dose_small_package_num =
+ #{doseSmallPackageNum},
+ </if>
+ <if test="doseUnit != null">dose_unit =
+ #{doseUnit},
+ </if>
+ <if test="doseUnitType != null">dose_unit_type =
+ #{doseUnitType},
+ </if>
+ <if test="remark != null">remark =
+ #{remark},
+ </if>
+ <if test="createBy != null">create_by =
+ #{createBy},
+ </if>
+ <if test="createTime != null">create_time =
+ #{createTime},
+ </if>
+ <if test="updateBy != null">update_by =
+ #{updateBy},
+ </if>
+ <if test="updateTime != null">update_time =
+ #{updateTime},
+ </if>
+ </trim>
+ where id = #{id}
+ </update>
+
+ <update id="deleteMedicationDoseInfoById" parameterType="Long">
+ update medication_dose_info
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1
+ </trim>
+ where id = #{id}
+ </update>
+
+ <update id="deleteMedicationDoseInfoByIds" parameterType="String">
+ update medication_dose_info
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1
+ </trim>
+ where id in
+ <foreach item="id" collection="array" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </update>
+
+
+
+
+</mapper>
diff --git a/ruoyi-common/src/main/resources/mapper/common/MedicationItemMapper.xml b/ruoyi-common/src/main/resources/mapper/common/MedicationItemMapper.xml
new file mode 100644
index 0000000..4a972aa
--- /dev/null
+++ b/ruoyi-common/src/main/resources/mapper/common/MedicationItemMapper.xml
@@ -0,0 +1,434 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.common.mapper.MedicationItemMapper">
+
+ <resultMap type="com.ruoyi.common.core.domain.entity.MedicationItem" id="MedicationItemResult">
+ <result property="id" column="id"/>
+ <result property="identificationCode" column="identification_code"/>
+ <result property="wbm" column="wbm"/>
+ <result property="medicationCommonName" column="medication_common_name"/>
+ <result property="manufacturerName" column="manufacturer_name"/>
+ <result property="itemCode" column="item_code"/>
+ <result property="smallLargePackageRatio" column="small_large_package_ratio"/>
+ <result property="remark" column="remark"/>
+ <result property="orgId" column="org_id"/>
+ <result property="itemName" column="item_name"/>
+ <result property="medicationType" column="medication_type"/>
+ <result property="antimicrobialGradeCode" column="antimicrobial_grade_code"/>
+ <result property="licenseNumber" column="license_number"/>
+ <result property="defaultUsageName" column="default_usage_name"/>
+ <result property="specialDrugsName" column="special_drugs_name"/>
+ <result property="antimicrobialGradeName" column="antimicrobial_grade_name"/>
+ <result property="commonPinyin" column="common_pinyin"/>
+ <result property="commonWbm" column="common_wbm"/>
+ <result property="manufacturerId" column="manufacturer_id"/>
+ <result property="defaultUsageId" column="default_usage_id"/>
+ <result property="specification" column="specification"/>
+ <result property="smallPackageUnit" column="small_package_unit"/>
+ <result property="itemId" column="item_id"/>
+ <result property="specialDrugsCode" column="special_drugs_code"/>
+ <result property="pinyin" column="pinyin"/>
+ <result property="doseFormName" column="dose_form_name"/>
+ <result property="largePackageUnit" column="large_package_unit"/>
+ <result property="retailPrice" column="retail_price"/>
+ <result property="status" column="status"/>
+ <result property="createBy" column="create_by"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="updateTime" column="update_time"/>
+ </resultMap>
+
+ <sql id="selectMedicationItemVo">
+ select id,
+ identification_code,
+ wbm,
+ medication_common_name,
+ manufacturer_name,
+ item_code,
+ small_large_package_ratio,
+ remark,
+ org_id,
+ item_name,
+ medication_type,
+ antimicrobial_grade_code,
+ license_number,
+ default_usage_name,
+ special_drugs_name,
+ antimicrobial_grade_name,
+ common_pinyin,
+ common_wbm,
+ manufacturer_id,
+ default_usage_id,
+ specification,
+ small_package_unit,
+ item_id,
+ special_drugs_code,
+ pinyin,
+ dose_form_name,
+ large_package_unit,
+ retail_price,
+ status,
+ create_by,
+ create_time,
+ update_by,
+ update_time
+ from medication_item
+ </sql>
+
+ <select id="selectMedicationItemList" parameterType="com.ruoyi.common.core.domain.entity.MedicationItem"
+ resultMap="MedicationItemResult">
+ <include refid="selectMedicationItemVo"/>
+ where 1=1
+ and del_flag=0
+ <if test="identificationCode != null and identificationCode != ''">
+ and identification_code = #{identificationCode}
+ </if>
+ <if test="wbm != null and wbm != ''">
+ and wbm = #{wbm}
+ </if>
+ <if test="medicationCommonName != null and medicationCommonName != ''">
+ and medication_common_name like concat('%', #{medicationCommonName}, '%')
+ </if>
+ <if test="manufacturerName != null and manufacturerName != ''">
+ and manufacturer_name like concat('%', #{manufacturerName}, '%')
+ </if>
+ <if test="itemCode != null and itemCode != ''">
+ and item_code = #{itemCode}
+ </if>
+ <if test="smallLargePackageRatio != null ">
+ and small_large_package_ratio = #{smallLargePackageRatio}
+ </if>
+ <if test="orgId != null ">
+ and org_id = #{orgId}
+ </if>
+ <if test="itemName != null and itemName != ''">
+ and item_name like concat('%', #{itemName}, '%')
+ </if>
+ <if test="medicationType != null and medicationType != ''">
+ and medication_type = #{medicationType}
+ </if>
+ <if test="antimicrobialGradeCode != null and antimicrobialGradeCode != ''">
+ and antimicrobial_grade_code = #{antimicrobialGradeCode}
+ </if>
+ <if test="licenseNumber != null and licenseNumber != ''">
+ and license_number = #{licenseNumber}
+ </if>
+ <if test="defaultUsageName != null and defaultUsageName != ''">
+ and default_usage_name like concat('%', #{defaultUsageName}, '%')
+ </if>
+ <if test="specialDrugsName != null and specialDrugsName != ''">
+ and special_drugs_name like concat('%', #{specialDrugsName}, '%')
+ </if>
+ <if test="antimicrobialGradeName != null and antimicrobialGradeName != ''">
+ and antimicrobial_grade_name like concat('%', #{antimicrobialGradeName}, '%')
+ </if>
+ <if test="commonPinyin != null and commonPinyin != ''">
+ and common_pinyin = #{commonPinyin}
+ </if>
+ <if test="commonWbm != null and commonWbm != ''">
+ and common_wbm = #{commonWbm}
+ </if>
+ <if test="manufacturerId != null ">
+ and manufacturer_id = #{manufacturerId}
+ </if>
+ <if test="defaultUsageId != null ">
+ and default_usage_id = #{defaultUsageId}
+ </if>
+ <if test="specification != null and specification != ''">
+ and specification = #{specification}
+ </if>
+ <if test="smallPackageUnit != null and smallPackageUnit != ''">
+ and small_package_unit = #{smallPackageUnit}
+ </if>
+ <if test="itemId != null ">
+ and item_id = #{itemId}
+ </if>
+ <if test="specialDrugsCode != null and specialDrugsCode != ''">
+ and special_drugs_code = #{specialDrugsCode}
+ </if>
+ <if test="pinyin != null and pinyin != ''">
+ and pinyin = #{pinyin}
+ </if>
+ <if test="doseFormName != null and doseFormName != ''">
+ and dose_form_name like concat('%', #{doseFormName}, '%')
+ </if>
+ <if test="largePackageUnit != null and largePackageUnit != ''">
+ and large_package_unit = #{largePackageUnit}
+ </if>
+ <if test="retailPrice != null ">
+ and retail_price = #{retailPrice}
+ </if>
+ <if test="status != null ">
+ and status = #{status}
+ </if>
+ </select>
+
+ <select id="selectMedicationItemById" parameterType="Long"
+ resultMap="MedicationItemResult">
+ <include refid="selectMedicationItemVo"/>
+ where id = #{id}
+ </select>
+
+ <insert id="insertMedicationItem" parameterType="com.ruoyi.common.core.domain.entity.MedicationItem" useGeneratedKeys="true"
+ keyProperty="id">
+ insert into medication_item
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="identificationCode != null">identification_code,
+ </if>
+ <if test="wbm != null">wbm,
+ </if>
+ <if test="medicationCommonName != null">medication_common_name,
+ </if>
+ <if test="manufacturerName != null">manufacturer_name,
+ </if>
+ <if test="itemCode != null">item_code,
+ </if>
+ <if test="smallLargePackageRatio != null">small_large_package_ratio,
+ </if>
+ <if test="remark != null">remark,
+ </if>
+ <if test="orgId != null">org_id,
+ </if>
+ <if test="itemName != null">item_name,
+ </if>
+ <if test="medicationType != null">medication_type,
+ </if>
+ <if test="antimicrobialGradeCode != null">antimicrobial_grade_code,
+ </if>
+ <if test="licenseNumber != null">license_number,
+ </if>
+ <if test="defaultUsageName != null">default_usage_name,
+ </if>
+ <if test="specialDrugsName != null">special_drugs_name,
+ </if>
+ <if test="antimicrobialGradeName != null">antimicrobial_grade_name,
+ </if>
+ <if test="commonPinyin != null">common_pinyin,
+ </if>
+ <if test="commonWbm != null">common_wbm,
+ </if>
+ <if test="manufacturerId != null">manufacturer_id,
+ </if>
+ <if test="defaultUsageId != null">default_usage_id,
+ </if>
+ <if test="specification != null">specification,
+ </if>
+ <if test="smallPackageUnit != null">small_package_unit,
+ </if>
+ <if test="itemId != null">item_id,
+ </if>
+ <if test="specialDrugsCode != null">special_drugs_code,
+ </if>
+ <if test="pinyin != null">pinyin,
+ </if>
+ <if test="doseFormName != null">dose_form_name,
+ </if>
+ <if test="largePackageUnit != null">large_package_unit,
+ </if>
+ <if test="retailPrice != null">retail_price,
+ </if>
+ <if test="status != null">status,
+ </if>
+ <if test="createBy != null">create_by,
+ </if>
+ <if test="createTime != null">create_time,
+ </if>
+ <if test="updateBy != null">update_by,
+ </if>
+ <if test="updateTime != null">update_time,
+ </if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="identificationCode != null">#{identificationCode},
+ </if>
+ <if test="wbm != null">#{wbm},
+ </if>
+ <if test="medicationCommonName != null">#{medicationCommonName},
+ </if>
+ <if test="manufacturerName != null">#{manufacturerName},
+ </if>
+ <if test="itemCode != null">#{itemCode},
+ </if>
+ <if test="smallLargePackageRatio != null">#{smallLargePackageRatio},
+ </if>
+ <if test="remark != null">#{remark},
+ </if>
+ <if test="orgId != null">#{orgId},
+ </if>
+ <if test="itemName != null">#{itemName},
+ </if>
+ <if test="medicationType != null">#{medicationType},
+ </if>
+ <if test="antimicrobialGradeCode != null">#{antimicrobialGradeCode},
+ </if>
+ <if test="licenseNumber != null">#{licenseNumber},
+ </if>
+ <if test="defaultUsageName != null">#{defaultUsageName},
+ </if>
+ <if test="specialDrugsName != null">#{specialDrugsName},
+ </if>
+ <if test="antimicrobialGradeName != null">#{antimicrobialGradeName},
+ </if>
+ <if test="commonPinyin != null">#{commonPinyin},
+ </if>
+ <if test="commonWbm != null">#{commonWbm},
+ </if>
+ <if test="manufacturerId != null">#{manufacturerId},
+ </if>
+ <if test="defaultUsageId != null">#{defaultUsageId},
+ </if>
+ <if test="specification != null">#{specification},
+ </if>
+ <if test="smallPackageUnit != null">#{smallPackageUnit},
+ </if>
+ <if test="itemId != null">#{itemId},
+ </if>
+ <if test="specialDrugsCode != null">#{specialDrugsCode},
+ </if>
+ <if test="pinyin != null">#{pinyin},
+ </if>
+ <if test="doseFormName != null">#{doseFormName},
+ </if>
+ <if test="largePackageUnit != null">#{largePackageUnit},
+ </if>
+ <if test="retailPrice != null">#{retailPrice},
+ </if>
+ <if test="status != null">#{status},
+ </if>
+ <if test="createBy != null">#{createBy},
+ </if>
+ <if test="createTime != null">#{createTime},
+ </if>
+ <if test="updateBy != null">#{updateBy},
+ </if>
+ <if test="updateTime != null">#{updateTime},
+ </if>
+ </trim>
+ </insert>
+
+ <update id="updateMedicationItem" parameterType="com.ruoyi.common.core.domain.entity.MedicationItem">
+ update medication_item
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="identificationCode != null">identification_code =
+ #{identificationCode},
+ </if>
+ <if test="wbm != null">wbm =
+ #{wbm},
+ </if>
+ <if test="medicationCommonName != null">medication_common_name =
+ #{medicationCommonName},
+ </if>
+ <if test="manufacturerName != null">manufacturer_name =
+ #{manufacturerName},
+ </if>
+ <if test="itemCode != null">item_code =
+ #{itemCode},
+ </if>
+ <if test="smallLargePackageRatio != null">small_large_package_ratio =
+ #{smallLargePackageRatio},
+ </if>
+ <if test="remark != null">remark =
+ #{remark},
+ </if>
+ <if test="orgId != null">org_id =
+ #{orgId},
+ </if>
+ <if test="itemName != null">item_name =
+ #{itemName},
+ </if>
+ <if test="medicationType != null">medication_type =
+ #{medicationType},
+ </if>
+ <if test="antimicrobialGradeCode != null">antimicrobial_grade_code =
+ #{antimicrobialGradeCode},
+ </if>
+ <if test="licenseNumber != null">license_number =
+ #{licenseNumber},
+ </if>
+ <if test="defaultUsageName != null">default_usage_name =
+ #{defaultUsageName},
+ </if>
+ <if test="specialDrugsName != null">special_drugs_name =
+ #{specialDrugsName},
+ </if>
+ <if test="antimicrobialGradeName != null">antimicrobial_grade_name =
+ #{antimicrobialGradeName},
+ </if>
+ <if test="commonPinyin != null">common_pinyin =
+ #{commonPinyin},
+ </if>
+ <if test="commonWbm != null">common_wbm =
+ #{commonWbm},
+ </if>
+ <if test="manufacturerId != null">manufacturer_id =
+ #{manufacturerId},
+ </if>
+ <if test="defaultUsageId != null">default_usage_id =
+ #{defaultUsageId},
+ </if>
+ <if test="specification != null">specification =
+ #{specification},
+ </if>
+ <if test="smallPackageUnit != null">small_package_unit =
+ #{smallPackageUnit},
+ </if>
+ <if test="itemId != null">item_id =
+ #{itemId},
+ </if>
+ <if test="specialDrugsCode != null">special_drugs_code =
+ #{specialDrugsCode},
+ </if>
+ <if test="pinyin != null">pinyin =
+ #{pinyin},
+ </if>
+ <if test="doseFormName != null">dose_form_name =
+ #{doseFormName},
+ </if>
+ <if test="largePackageUnit != null">large_package_unit =
+ #{largePackageUnit},
+ </if>
+ <if test="retailPrice != null">retail_price =
+ #{retailPrice},
+ </if>
+ <if test="status != null">status =
+ #{status},
+ </if>
+ <if test="createBy != null">create_by =
+ #{createBy},
+ </if>
+ <if test="createTime != null">create_time =
+ #{createTime},
+ </if>
+ <if test="updateBy != null">update_by =
+ #{updateBy},
+ </if>
+ <if test="updateTime != null">update_time =
+ #{updateTime},
+ </if>
+ </trim>
+ where id = #{id}
+ </update>
+
+ <update id="deleteMedicationItemById" parameterType="Long">
+ update medication_item
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1
+ </trim>
+ where id = #{id}
+ </update>
+
+ <update id="deleteMedicationItemByIds" parameterType="String">
+ update medication_item
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1
+ </trim>
+ where id in
+ <foreach item="id" collection="array" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </update>
+
+
+</mapper>
diff --git a/ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/api/OuthospVisitApiImpl.java b/ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/api/OuthospVisitApiImpl.java
new file mode 100644
index 0000000..8076cde
--- /dev/null
+++ b/ruoyi-outpatientvisit/src/main/java/com/ruoyi/outpatientvisit/api/OuthospVisitApiImpl.java
@@ -0,0 +1,37 @@
+package com.ruoyi.outpatientvisit.api;
+
+import com.ruoyi.common.core.service.OuthospVisitApi;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * {@link OuthospVisitApi} 鐨�<b>褰掑睘妯″潡瀹炵幇</b> 鈥斺�� 闂ㄨ瘖闅忚鎵弿銆�
+ *
+ * <h3>2026-11 褰掑睘璋冩暣</h3>
+ * 杩欎釜濂戠害鍘熷厛鐨勫疄鐜版槸 smartor 渚х殑 {@code OuthospVisitApiBridge}锛屽畠鍙仛涓�浠朵簨锛�
+ * 杞彂鍒� smartor 鐨� {@code IPatMedOuthospService#dealOutpatientInfo}锛岃�岄偅鍙堟槸涓�涓�
+ * 绾鎵橈紙{@code PatMedOuthospServiceDelegatingImpl}锛夆啋 鏈ā鍧楃殑 {@code OuthospDataFacade}銆�
+ * 涔熷氨鏄閾捐矾閲屾湁涓ゅ眰绌鸿浆鍙戙��
+ * <p>
+ * 鐜板湪鎶婂疄鐜扮洿鎺ユ斁鍒拌兘鍔涙墍鍦ㄧ殑妯″潡锛歿@code ruoyi-inhospvisit} 浠嶅彧鐪嬪埌
+ * {@code ruoyi-common} 閲岀殑濂戠害锛堝畠涓嶄緷璧栨湰妯″潡锛夛紝杩愯鏈熺敱 Spring 娉ㄥ叆鏈疄鐜帮紱
+ * smartor 渚ч偅涓ˉ涓� {@code IPatMedOuthospService#dealOutpatientInfo} 涓�骞跺垹闄ゃ��
+ *
+ * <h3>鈿狅笍 寮�鍏冲垽鏂笉鍦ㄦ湰绫�</h3>
+ * 鐪熸鐨勫紑鍏筹紙{@code outpatientvisit.enabled}锛夊湪 {@link OuthospVisitFacade#dealOutpatientInfo()} 閲岋紝
+ * 杩欓噷鎸夋棦鏈夊彛寰勮浆鍙戝埌 {@link OuthospDataFacade}锛堝畠鍐嶈浆鍙戝埌甯﹀畧鍗殑闂ㄩ潰锛夛紝涓嶉噸澶嶅垽鏂�侀伩鍏嶄袱澶勫彛寰勬紓绉汇��
+ */
+@Slf4j
+@Component
+public class OuthospVisitApiImpl implements OuthospVisitApi {
+
+ @Autowired
+ private OuthospDataFacade outhospDataFacade;
+
+ @Override
+ public int dealOutpatientInfo() {
+ Integer n = outhospDataFacade.dealOutpatientInfo();
+ return n == null ? 0 : n;
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/TaskOpsTriggerApiImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/TaskOpsTriggerApiImpl.java
new file mode 100644
index 0000000..440a5e9
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/TaskOpsTriggerApiImpl.java
@@ -0,0 +1,82 @@
+package com.ruoyi.quartz.service.impl;
+
+import com.ruoyi.common.core.service.TaskOpsTriggerApi;
+import com.ruoyi.quartz.service.ICollectHISService;
+import com.ruoyi.quartz.task.RyTask;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * {@link TaskOpsTriggerApi} 鍦� <b>ruoyi-quartz 渚�</b>鐨勫疄鐜� 鈥斺�� 浠诲姟杩愮淮瑙﹀彂鑳藉姏鐨勫綊灞炴柟銆�
+ *
+ * <h3>涓轰粈涔堝疄鐜板湪杩欓噷銆佽�屼笉鍦� ruoyi-task</h3>
+ * 杩� 6 涓兘鍔涙槸銆屾墜宸ヨЕ鍙� HIS 閲囬泦 / 鎴澶勭悊 / 寮傚父鎺ㄩ�併�嶇殑杩愮淮鍏ュ彛锛�
+ * 鍏跺簳灞傚疄鐜� {@link RyTask}锛�2214 琛岋紝娉ㄥ叆绾� 20 涓� smartor service锛�
+ * 涓� {@link ICollectHISService}锛坽@code CollectHISServiceImpl} 869 琛岋級
+ * 閮戒綅浜� quartz 鍩熶笖渚濊禆 smartor 渚ц兘鍔涖��
+ * 鎼埌 {@code ruoyi-task} 浼氬舰鎴� {@code ruoyi-task -> smartor} 纭惊鐜紝
+ * 鍥犳鏀逛负銆屾帴鍙e湪 ruoyi-common銆佸疄鐜扮暀鍦� quartz銆嶇殑<b>绔彛鍙嶈浆</b>锛�
+ * 绔偣褰掑睘鍦� {@code ruoyi-task}銆佸疄鐜板湪杩欓噷锛岀紪璇戞湡鏃犵幆銆�
+ *
+ * <h3>鈿狅笍 鏈被蹇呴』淇濇寔"绾浆鍙�"</h3>
+ * 鍙仛鏂规硶杞彂锛�<b>涓�</b>鍔犲幓閲嶃�佺姸鎬佹満銆侀粯璁ゅ�艰ˉ榻愩�佸紓甯稿悶骞剁瓑浠讳綍鏂伴�昏緫銆�
+ * 閫愭柟娉曚笌鍘� {@code ServiceSubtaskController} 閲岀殑璋冪敤涓�涓�瀵瑰簲锛�
+ * <table border="1">
+ * <tr><th>鏈被鏂规硶</th><th>鍘熻皟鐢ㄧ偣锛圫erviceSubtaskController锛�</th></tr>
+ * <tr><td>{@link #syncMedInhosp}</td><td>L956 {@code collectHISService.syncMedInhosp(...)}</td></tr>
+ * <tr><td>{@link #collectHISYesterday}</td><td>L964 {@code ryTask.collectHISYesterday()}</td></tr>
+ * <tr><td>{@link #collectHISDaysBefore}</td><td>L971 {@code ryTask.collectHISDaysBefore(day)}</td></tr>
+ * <tr><td>{@link #syncOper}</td><td>L979 {@code collectHISService.syncOper(...)}</td></tr>
+ * <tr><td>{@link #dealSubtaskDeadline}</td><td>L987 {@code ryTask.dealSubtaskDeadline(orgid, day)}</td></tr>
+ * <tr><td>{@link #sendExceptInfo}</td><td>L993 {@code ryTask.sendExceptInfo()}</td></tr>
+ * </table>
+ *
+ * <h3>鈿狅笍 寮傛鍖呰涓嶅湪杩欓噷</h3>
+ * 鍘� Controller 瀵� {@code syncMedInhosp} / {@code syncOper} 鐢�
+ * {@code CompletableFuture.runAsync(...)} 鍖呬簡涓�灞傘�佸叾浣� 4 涓洿鎺ュ悓姝ヨ皟鐢ㄣ��
+ * 閭e眰寮傛灞炰簬<b>璋冪敤鏂�</b>鐨勮涔夛紝淇濈暀鍦ㄦ惉杩囧幓鍚庣殑 {@code ruoyi-task} 鎺у埗鍣ㄩ噷锛�
+ * 鏈被涓�寰�<b>鍚屾</b>杞彂锛屼繚璇�"浣曟椂寮傛"杩欎竴琛屼负涓嶅彉銆�
+ *
+ * @see TaskOpsTriggerApi
+ */
+@Slf4j
+@Component
+public class TaskOpsTriggerApiImpl implements TaskOpsTriggerApi {
+
+ @Autowired
+ private RyTask ryTask;
+
+ @Autowired
+ private ICollectHISService collectHISService;
+
+ @Override
+ public Integer syncMedInhosp(String startTime, String endTime) {
+ return collectHISService.syncMedInhosp(startTime, endTime);
+ }
+
+ @Override
+ public void collectHISYesterday() {
+ ryTask.collectHISYesterday();
+ }
+
+ @Override
+ public void collectHISDaysBefore(Long daysBefore) {
+ ryTask.collectHISDaysBefore(daysBefore);
+ }
+
+ @Override
+ public Integer syncOper(String startTime, String endTime) {
+ return collectHISService.syncOper(startTime, endTime);
+ }
+
+ @Override
+ public void dealSubtaskDeadline(String orgid, Integer deadlineDay) {
+ ryTask.dealSubtaskDeadline(orgid, deadlineDay);
+ }
+
+ @Override
+ public void sendExceptInfo() throws Exception {
+ ryTask.sendExceptInfo();
+ }
+}
diff --git a/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/support/MydOptionRatioPieChartBuilder.java b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/support/MydOptionRatioPieChartBuilder.java
new file mode 100644
index 0000000..4954445
--- /dev/null
+++ b/ruoyi-satisfaction/src/main/java/com/ruoyi/satisfaction/support/MydOptionRatioPieChartBuilder.java
@@ -0,0 +1,296 @@
+package com.ruoyi.satisfaction.support;
+
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.satisfaction.domain.ServiceSubtaskDetailRatioExport;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFPicture;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+
+import javax.imageio.ImageIO;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Arc2D;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 銆岄棶棰樿鎯呭崰姣旈ゼ鍥俱�峉heet锛氭瘡閬撻涓�涓ゼ鍥撅紙甯︾櫨鍒嗘瘮鏍囩鍜屽浘渚嬶級锛�
+ * 鎺掔増鍙傜収绾歌川鎶ュ憡锛氭瘡棰樹笂鏂规槸棰樼洰锛屽乏杈归ゼ鍥俱�佸彸杈瑰浘渚嬶紝涓�椤� 2 鍒� 脳 3 琛屻��
+ * <p>
+ * 鐢� Java2D 鐢绘垚 PNG 鍐嶈创杩� Excel锛屼繚璇併�岀櫨鍒嗘瘮鐩存帴鏍囧湪鎵囧尯涓娿�嶇殑鏁堟灉涓庢姤鍛婁竴鑷�
+ * 锛圥OI 4.1.2 鐨勫師鐢熷浘琛ㄦ病鏈夋暟鎹爣绛� API锛夈��
+ *
+ * @author smartor
+ */
+public class MydOptionRatioPieChartBuilder implements ExcelUtil.ChartSheetBuilder {
+
+ /** Sheet 鍚嶇О */
+ public static final String SHEET_NAME = "闂璇︽儏鍗犳瘮楗煎浘";
+
+ /** 鍗曞紶鍥剧墖瀹介珮锛堝儚绱狅級 */
+ private static final int IMG_W = 560;
+ private static final int IMG_H = 400;
+
+ /** 姣忓紶鍥惧崰鐢ㄧ殑鍒楁暟 / 琛屾暟锛堢敤浜庡崟鍏冩牸閿氱偣瀹氫綅锛� */
+ private static final int COLS_PER_IMG = 9;
+ private static final int ROWS_PER_IMG = 20;
+
+ /** 姣忚鏀惧嚑寮犲浘 */
+ private static final int PER_ROW = 2;
+
+ /** 鎵囧舰閰嶈壊 */
+ private static final Color[] PALETTE = {
+ new Color(0x5B, 0x8F, 0xF9),
+ new Color(0x61, 0xDD, 0xAA),
+ new Color(0xF6, 0xBD, 0x16),
+ new Color(0x72, 0x62, 0xFD),
+ new Color(0x78, 0xD3, 0xF8),
+ new Color(0x96, 0x61, 0xBC),
+ new Color(0xFF, 0x98, 0x4D),
+ new Color(0xFF, 0x6D, 0x6D)
+ };
+
+ private final List<ServiceSubtaskDetailRatioExport> rows;
+
+ private final String footer;
+
+ public MydOptionRatioPieChartBuilder(List<ServiceSubtaskDetailRatioExport> rows, String footer) {
+ this.rows = rows == null ? new ArrayList<>() : rows;
+ this.footer = footer;
+ }
+
+ @Override
+ public void build(XSSFWorkbook workbook) {
+ if (rows.isEmpty()) {
+ return;
+ }
+ XSSFSheet sheet = workbook.createSheet(SHEET_NAME);
+ sheet.setColumnWidth(0, 12 * 256);
+ for (int i = 1; i < PER_ROW * COLS_PER_IMG; i++) {
+ sheet.setColumnWidth(i, 10 * 256);
+ }
+
+ XSSFDrawing drawing = sheet.createDrawingPatriarch();
+ int slot = 0;
+ for (Map.Entry<String, List<ServiceSubtaskDetailRatioExport>> taskEntry : groupByTask().entrySet()) {
+ // 姣忎釜浠诲姟涓�琛屾爣棰�
+ int titleRow = (slot / PER_ROW) * ROWS_PER_IMG;
+ org.apache.poi.ss.usermodel.Row tr = sheet.getRow(titleRow) == null
+ ? sheet.createRow(titleRow) : sheet.getRow(titleRow);
+ tr.createCell(0).setCellValue("浠诲姟鍚嶇О锛�" + taskEntry.getKey());
+
+ for (Map.Entry<String, LinkedHashMap<String, Double>> q : groupByQuestion(taskEntry.getValue()).entrySet()) {
+ int col = (slot % PER_ROW) * COLS_PER_IMG;
+ int row = (slot / PER_ROW) * ROWS_PER_IMG + 1;
+ try {
+ byte[] png = renderPie(q.getKey(), q.getValue());
+ int picIndex = workbook.addPicture(png, Workbook.PICTURE_TYPE_PNG);
+ XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0,
+ col, row, col + COLS_PER_IMG - 1, row + ROWS_PER_IMG - 2);
+ XSSFPicture pic = drawing.createPicture(anchor, picIndex);
+ // 灏哄瀹屽叏鐢遍敋鐐瑰喅瀹氾紙涓嶈 resize()锛屽惁鍒欎細鎸� POI 榛樿鍒楀閲嶇畻锛�
+ } catch (Exception e) {
+ org.apache.poi.ss.usermodel.Row errRow = sheet.getRow(row) == null
+ ? sheet.createRow(row) : sheet.getRow(row);
+ errRow.createCell(col).setCellValue(q.getKey() + "锛氶ゼ鍥剧敓鎴愬け璐�");
+ }
+ slot++;
+ }
+ slot = ((slot + PER_ROW - 1) / PER_ROW) * PER_ROW;
+ }
+
+ // 椤佃剼锛氬尰闄�--绉戝
+ int footerRow = ((slot + PER_ROW - 1) / PER_ROW) * ROWS_PER_IMG + 1;
+ org.apache.poi.ss.usermodel.Row fr = sheet.createRow(footerRow);
+ fr.createCell(0).setCellValue(resolveFooter());
+ }
+
+ /**
+ * 鎸変换鍔″悕绉板垎缁勶紝淇濇寔鍘熸湁椤哄簭
+ */
+ private Map<String, List<ServiceSubtaskDetailRatioExport>> groupByTask() {
+ Map<String, List<ServiceSubtaskDetailRatioExport>> grouped = new LinkedHashMap<>();
+ for (ServiceSubtaskDetailRatioExport row : rows) {
+ String taskName = row.getTaskname() == null ? "" : row.getTaskname();
+ grouped.computeIfAbsent(taskName, k -> new ArrayList<>()).add(row);
+ }
+ return grouped;
+ }
+
+ /**
+ * 棰樼洰 -> (閫夐」 -> 浜烘暟)锛屼繚鎸佸嚭鐜伴『搴�
+ */
+ private Map<String, LinkedHashMap<String, Double>> groupByQuestion(List<ServiceSubtaskDetailRatioExport> taskRows) {
+ Map<String, LinkedHashMap<String, Double>> result = new LinkedHashMap<>();
+ for (ServiceSubtaskDetailRatioExport row : taskRows) {
+ String question = row.getQuestiontext() == null ? "" : row.getQuestiontext();
+ String option = row.getOptionresult() == null ? "" : row.getOptionresult();
+ result.computeIfAbsent(question, k -> new LinkedHashMap<>())
+ .put(option, parseCount(row.getCount()));
+ }
+ return result;
+ }
+
+ /**
+ * 椤佃剼锛氫紭鍏堢敤浼犲叆鍊硷紝鍚﹀垯鍙栫涓�琛屾暟鎹噷鐨勭瀹ゅ悕绉�
+ */
+ private String resolveFooter() {
+ if (footer != null && !footer.trim().isEmpty()) {
+ return footer;
+ }
+ for (ServiceSubtaskDetailRatioExport row : rows) {
+ if (row.getDeptname() != null && !row.getDeptname().trim().isEmpty()) {
+ return row.getDeptname();
+ }
+ if (row.getLeavehospitaldistrictname() != null && !row.getLeavehospitaldistrictname().trim().isEmpty()) {
+ return row.getLeavehospitaldistrictname();
+ }
+ }
+ return "";
+ }
+
+ /**
+ * 鐢讳竴寮犻ゼ鍥撅細鏍囬 + 楗硷紙鎵囧尯鍐呮爣鐧惧垎姣旓級 + 鍙充晶鍥句緥锛堥�夐」 + 鐧惧垎姣旓級
+ */
+ private byte[] renderPie(String question, LinkedHashMap<String, Double> options) throws Exception {
+ BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = img.createGraphics();
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, IMG_W, IMG_H);
+
+ // 鏍囬锛堟渶澶氫袱琛岋級
+ g.setFont(new Font("Microsoft YaHei", Font.BOLD, 18));
+ g.setColor(new Color(0x33, 0x33, 0x33));
+ drawWrapped(g, question, 16, 28, IMG_W - 32);
+
+ double total = 0D;
+ for (Double v : options.values()) {
+ total += v == null ? 0D : v;
+ }
+
+ int cx = 165;
+ int cy = 235;
+ int r = 120;
+
+ if (total <= 0) {
+ g.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
+ g.setColor(new Color(0x99, 0x99, 0x99));
+ g.drawString("鏆傛棤浣滅瓟鏁版嵁", cx - 45, cy);
+ } else {
+ double startAngle = -90D;
+ int i = 0;
+ for (Map.Entry<String, Double> entry : options.entrySet()) {
+ double count = entry.getValue() == null ? 0D : entry.getValue();
+ double angle = count / total * 360D;
+ g.setColor(PALETTE[i % PALETTE.length]);
+ g.fill(new Arc2D.Double(cx - r, cy - r, r * 2D, r * 2D, startAngle, angle, Arc2D.PIE));
+ g.setColor(Color.WHITE);
+ g.setStroke(new BasicStroke(2f));
+ g.draw(new Arc2D.Double(cx - r, cy - r, r * 2D, r * 2D, startAngle, angle, Arc2D.PIE));
+
+ // 鎵囧尯涓棿鏍囩櫨鍒嗘瘮
+ String pct = formatPercent(count, total);
+ double mid = Math.toRadians(startAngle + angle / 2D);
+ int tx = (int) (cx + Math.cos(mid) * r * 0.58);
+ int ty = (int) (cy + Math.sin(mid) * r * 0.58);
+ g.setFont(new Font("Microsoft YaHei", Font.BOLD, 15));
+ g.setColor(Color.WHITE);
+ drawCentered(g, pct, tx, ty);
+
+ startAngle += angle;
+ i++;
+ }
+ }
+
+ // 鍙充晶鍥句緥
+ g.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
+ FontMetrics fm = g.getFontMetrics();
+ int lx = cx + r + 42;
+ int ly = cy - r + 30;
+ int i = 0;
+ for (Map.Entry<String, Double> entry : options.entrySet()) {
+ g.setColor(PALETTE[i % PALETTE.length]);
+ g.fillRect(lx, ly - 10, 12, 12);
+ g.setColor(new Color(0x33, 0x33, 0x33));
+ double count = entry.getValue() == null ? 0D : entry.getValue();
+ String text = entry.getKey() + " " + formatPercent(count, total);
+ g.drawString(text, lx + 18, ly);
+ ly += Math.max(22, fm.getHeight() + 4);
+ i++;
+ }
+
+ g.dispose();
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ImageIO.write(img, "png", bos);
+ return bos.toByteArray();
+ }
+
+ /**
+ * 鐧惧垎姣旓細鎬婚噺涓� 0 鏃舵樉绀� 0.00%
+ */
+ private String formatPercent(double count, double total) {
+ if (total <= 0) {
+ return "0.00%";
+ }
+ return String.format("%.2f%%", count * 100D / total);
+ }
+
+ /**
+ * 鍗曡灞呬腑缁樺埗鏂囨湰
+ */
+ private void drawCentered(Graphics2D g, String text, int cx, int cy) {
+ FontMetrics fm = g.getFontMetrics();
+ g.drawString(text, cx - fm.stringWidth(text) / 2, cy + fm.getAscent() / 2 - 2);
+ }
+
+ /**
+ * 鎸夊搴﹁嚜鍔ㄦ崲琛岀粯鍒舵爣棰�
+ */
+ private void drawWrapped(Graphics2D g, String text, int x, int y, int maxWidth) {
+ if (text == null) {
+ return;
+ }
+ FontMetrics fm = g.getFontMetrics();
+ StringBuilder line = new StringBuilder();
+ int lineY = y;
+ for (int i = 0; i < text.length(); i++) {
+ char ch = text.charAt(i);
+ if (fm.stringWidth(line.toString() + ch) > maxWidth) {
+ g.drawString(line.toString(), x, lineY);
+ lineY += fm.getHeight();
+ line.setLength(0);
+ }
+ line.append(ch);
+ }
+ if (line.length() > 0) {
+ g.drawString(line.toString(), x, lineY);
+ }
+ }
+
+ /**
+ * 鏁伴噺瀛楃涓� -> 鏁板瓧
+ */
+ private double parseCount(String count) {
+ if (count == null || count.trim().isEmpty()) {
+ return 0D;
+ }
+ try {
+ return Double.parseDouble(count.trim());
+ } catch (NumberFormatException e) {
+ return 0D;
+ }
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysDept2Mapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysDept2Mapper.java
new file mode 100644
index 0000000..3fa48bd
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysDept2Mapper.java
@@ -0,0 +1,132 @@
+package com.ruoyi.system.mapper.ext;
+
+import com.ruoyi.common.core.domain.entity.SysDept;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 閮ㄩ棬绠$悊 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+@Mapper
+public interface SysDept2Mapper {
+ /**
+ * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 閮ㄩ棬淇℃伅闆嗗悎
+ */
+ public List<SysDept> selectDeptList(SysDept dept);
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+ *
+ * @param roleId 瑙掕壊ID
+ * @param deptCheckStrictly 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
+ * @return 閫変腑閮ㄩ棬鍒楄〃
+ */
+ public List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
+
+ /**
+ * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 閮ㄩ棬淇℃伅
+ */
+ public SysDept selectDeptById(Long deptId);
+
+ public SysDept selectDeptByCode(@Param("deptCode")String deptCode,@Param("orgid")String orgid);
+
+ public SysDept selectDeptByCodeAndCampus(@Param("deptCode")String deptCode,@Param("orgid")String orgid,@Param("campusid")String campusid);
+
+ /**
+ * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 閮ㄩ棬鍒楄〃
+ */
+ public List<SysDept> selectChildrenDeptById(Long deptId);
+
+ /**
+ * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬锛堟甯哥姸鎬侊級
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 瀛愰儴闂ㄦ暟
+ */
+ public int selectNormalChildrenDeptById(Long deptId);
+
+ /**
+ * 鏄惁瀛樺湪瀛愯妭鐐�
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public int hasChildByDeptId(Long deptId);
+
+ /**
+ * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public int checkDeptExistUser(Long deptId);
+
+ /**
+ * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
+ *
+ * @param deptName 閮ㄩ棬鍚嶇О
+ * @param parentId 鐖堕儴闂↖D
+ * @return 缁撴灉
+ */
+ public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId);
+
+ /**
+ * 鏂板閮ㄩ棬淇℃伅
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertDept(SysDept dept);
+
+ /**
+ * 鎵归噺鏂板閮ㄩ棬淇℃伅
+ *
+ * @param depts 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ public int batchDept(List<SysDept> depts);
+
+ /**
+ * 淇敼閮ㄩ棬淇℃伅
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateDept(SysDept dept);
+
+ /**
+ * 淇敼鎵�鍦ㄩ儴闂ㄦ甯哥姸鎬�
+ *
+ * @param deptIds 閮ㄩ棬ID缁�
+ */
+ public void updateDeptStatusNormal(Long[] deptIds);
+
+ /**
+ * 淇敼瀛愬厓绱犲叧绯�
+ *
+ * @param depts 瀛愬厓绱�
+ * @return 缁撴灉
+ */
+ public int updateDeptChildren(@Param("depts") List<SysDept> depts);
+
+ /**
+ * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public int deleteDeptById(Long deptId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUser2Mapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUser2Mapper.java
new file mode 100644
index 0000000..6c88a71
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUser2Mapper.java
@@ -0,0 +1,137 @@
+package com.ruoyi.system.mapper.ext;
+
+import com.ruoyi.common.core.domain.entity.SysUser;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 鐢ㄦ埛琛� 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+@Mapper
+public interface SysUser2Mapper {
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+ *
+ * @param sysUser 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectUserList(SysUser sysUser);
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸查厤鐢ㄦ埛瑙掕壊鍒楄〃
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectAllocatedList(SysUser user);
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectUnallocatedList(SysUser user);
+
+ /**
+ * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 鐢ㄦ埛瀵硅薄淇℃伅
+ */
+ public SysUser selectUserByUserName(String userName);
+
+ /**
+ * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鐢ㄦ埛瀵硅薄淇℃伅
+ */
+ public SysUser selectUserById(Long userId);
+
+ /**
+ * 鏂板鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertUser(SysUser user);
+
+ /**
+ * 鎵归噺鏂板鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int batchUser(List<SysUser> users);
+
+ /**
+ * 淇敼鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateUser(SysUser user);
+
+ /**
+ * 淇敼鐢ㄦ埛澶村儚
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param avatar 澶村儚鍦板潃
+ * @return 缁撴灉
+ */
+ public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar);
+
+ /**
+ * 閲嶇疆鐢ㄦ埛瀵嗙爜
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param password 瀵嗙爜
+ * @return 缁撴灉
+ */
+ public int resetUserPwd(@Param("userName") String userName, @Param("password") String password);
+
+ /**
+ * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserById(Long userId);
+
+ /**
+ * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+ *
+ * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserByIds(Long[] userIds);
+
+ /**
+ * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+ *
+ * @param userName 鐢ㄦ埛鍚嶇О
+ * @return 缁撴灉
+ */
+ public SysUser checkUserNameUnique(String userName);
+
+ /**
+ * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+ *
+ * @param phonenumber 鎵嬫満鍙风爜
+ * @return 缁撴灉
+ */
+ public SysUser checkPhoneUnique(String phonenumber);
+
+ /**
+ * 鏍¢獙email鏄惁鍞竴
+ *
+ * @param email 鐢ㄦ埛閭
+ * @return 缁撴灉
+ */
+ public SysUser checkEmailUnique(String email);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUserDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUserDeptMapper.java
new file mode 100644
index 0000000..7754927
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUserDeptMapper.java
@@ -0,0 +1,76 @@
+package com.ruoyi.system.mapper.ext;
+
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysUserDept;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆慚apper鎺ュ彛
+ *
+ * @author lihu
+ * @date 2024-08-29
+ */
+@Mapper
+public interface SysUserDeptMapper {
+ /**
+ * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+ */
+ public SysUserDept selectSysUserDeptById(Long id);
+
+ /**
+ * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+ *
+ * @param sysUserDept 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 銆愯濉啓鍔熻兘鍚嶇О銆戦泦鍚�
+ */
+ public List<SysUserDept> selectSysUserDeptList(SysUserDept sysUserDept);
+
+ /**
+ * 鏂板銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param sysUserDept 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 缁撴灉
+ */
+ public int insertSysUserDept(SysUserDept sysUserDept);
+
+ /**
+ * 淇敼銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param sysUserDept 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 缁撴灉
+ */
+ public int updateSysUserDept(SysUserDept sysUserDept);
+
+ /**
+ * 鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 缁撴灉
+ */
+ public int deleteSysUserDeptById(Long id);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ閮ㄩ棬淇℃伅
+ *
+ * @param id
+ * @return
+ */
+ public List<SysDept> selectDeptListByUserId(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteSysUserDeptByIds(Long[] ids);
+
+ public int deleteSysUserDeptByCode(SysUserDept sysUserDept);
+
+ public int updateSysUserDeptForSync(SysUserDept sysUserDept);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUserRole2Mapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUserRole2Mapper.java
new file mode 100644
index 0000000..23dd5ac
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ext/SysUserRole2Mapper.java
@@ -0,0 +1,66 @@
+package com.ruoyi.system.mapper.ext;
+
+import com.ruoyi.common.core.domain.entity.SysUserRole;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 鐢ㄦ埛涓庤鑹插叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+@Mapper
+public interface SysUserRole2Mapper {
+ /**
+ * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserRoleByUserId(Long userId);
+
+ /**
+ * 鎵归噺鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteUserRole(Long[] ids);
+
+ /**
+ * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int countUserRoleByRoleId(Long roleId);
+
+ public SysUserRole selectUserRoleByRoleIdAndUserId(@Param("roleId") Long roleId, @Param("userId") Long userId);
+
+ /**
+ * 鎵归噺鏂板鐢ㄦ埛瑙掕壊淇℃伅
+ *
+ * @param userRoleList 鐢ㄦ埛瑙掕壊鍒楄〃
+ * @return 缁撴灉
+ */
+ public int batchUserRole(List<SysUserRole> userRoleList);
+
+ /**
+ * 鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+ *
+ * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+ * @return 缁撴灉
+ */
+ public int deleteUserRoleInfo(SysUserRole userRole);
+
+ /**
+ * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds);
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/ext/SysDept2Mapper.xml b/ruoyi-system/src/main/resources/mapper/system/ext/SysDept2Mapper.xml
new file mode 100644
index 0000000..7a12eb3
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/ext/SysDept2Mapper.xml
@@ -0,0 +1,363 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.ext.SysDept2Mapper">
+
+ <resultMap type="com.ruoyi.common.core.domain.entity.SysDept" id="SysDeptResult">
+ <id property="deptId" column="dept_id"/>
+ <id property="hisDeptId" column="his_dept_id"/>
+ <result property="parentId" column="parent_id"/>
+ <result property="hisParentId" column="his_parent_id"/>
+ <result property="ancestors" column="ancestors"/>
+ <result property="deptName" column="dept_name"/>
+ <result property="orderNum" column="order_num"/>
+ <result property="leader" column="leader"/>
+ <result property="phone" column="phone"/>
+ <result property="email" column="email"/>
+ <result property="status" column="status"/>
+ <result property="delFlag" column="del_flag"/>
+ <result property="parentName" column="parent_name"/>
+ <result property="createBy" column="create_by"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="updateTime" column="update_time"/>
+ <result property="deptCode" column="dept_code"/>
+ <result property="deptType" column="dept_type"/>
+ <result property="guid" column="guid"/>
+ <result property="orgid" column="orgid"/>
+ <result property="type" column="type"/>
+ <result property="campusid" column="campusid"/>
+ </resultMap>
+
+ <sql id="selectDeptVo">
+ select d.dept_id,
+ d.dept_code,
+ d.type,
+ d.orgid,
+ d.campusid,
+ d.parent_id,
+ d.ancestors,
+ d.dept_name,
+ d.order_num,
+ d.leader,
+ d.phone,
+ d.dept_type,
+ d.email,
+ d.status,
+ d.del_flag,
+ d.create_by,
+ d.guid,
+ d.create_time,
+ d.his_dept_id,
+ d.his_parent_id
+ from sys_dept d
+ </sql>
+
+ <select id="selectDeptList" parameterType="com.ruoyi.common.core.domain.entity.SysDept" resultMap="SysDeptResult">
+ <include refid="selectDeptVo"/>
+ where d.del_flag = '0'
+ <if test="deptId != null and deptId != 0">
+ AND dept_id = #{deptId}
+ </if>
+ <if test="type != null">
+ AND type = #{type}
+ </if>
+ <if test="parentId != null and parentId != 0">
+ AND parent_id = #{parentId}
+ </if>
+ <if test="deptName != null and deptName != ''">
+ AND dept_name like concat('%', #{deptName}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <if test="deptCode != null and deptCode != ''">
+ AND dept_code = #{deptCode}
+ </if>
+ <if test="deptType != null and deptType != ''">
+ AND dept_type = #{deptType}
+ </if>
+ <if test="hisDeptId != null and hisDeptId != ''">
+ AND his_dept_id = #{hisDeptId}
+ </if>
+ <if test="hisParentId != null and hisParentId != ''">
+ AND his_parent_id = #{hisParentId}
+ </if>
+ <if test="orgid != null and orgid != ''">
+ AND orgid = #{orgid}
+ </if>
+ <if test="campusid != null and campusid != ''">
+ AND campusid = #{campusid}
+ </if>
+ order by d.parent_id, d.order_num
+ </select>
+
+ <select id="selectDeptListByRoleId" resultType="Long">
+ select d.dept_id
+ from sys_dept d
+ left join sys_role_dept rd on d.dept_id = rd.dept_id
+ where rd.role_id = #{roleId}
+ <if test="deptCheckStrictly">
+ and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id =
+ rd.dept_id and rd.role_id = #{roleId})
+ </if>
+ order by d.parent_id, d.order_num
+ </select>
+
+ <select id="selectDeptById" parameterType="Long" resultMap="SysDeptResult">
+ select d.dept_id,
+ d.parent_id,
+ d.campusid,
+ d.dept_code,
+ d.type,
+ d.dept_type,
+ d.ancestors,
+ d.dept_name,
+ d.order_num,
+ d.leader,
+ d.phone,
+ d.email,
+ d.status,
+ d.orgid,
+ d.his_dept_id,
+ d.his_parent_id
+ (select dept_name from sys_dept where dept_id = d.parent_id) parent_name
+ from sys_dept d
+ where d.dept_id = #{deptId}
+ </select>
+
+ <select id="selectDeptByCode" parameterType="string" resultMap="SysDeptResult">
+ select d.dept_id,
+ d.parent_id,
+ d.type,
+ d.campusid,
+ d.dept_code,
+ d.dept_type,
+ d.ancestors,
+ d.dept_name,
+ d.order_num,
+ d.leader,
+ d.phone,
+ d.email,
+ d.orgid,
+ d.his_dept_id,
+ d.his_parent_id,
+ d.status
+ from sys_dept d
+ where del_flag = 0
+ <if test="deptCode != null and deptCode != ''">
+ AND dept_code = #{deptCode}
+ </if>
+ <if test="orgid != null and orgid != ''">
+ AND orgid = #{orgid}
+ </if>
+ </select>
+
+ <select id="selectDeptByCodeAndCampus" parameterType="string" resultMap="SysDeptResult">
+ select d.dept_id,
+ d.parent_id,
+ d.type,
+ d.campusid,
+ d.dept_code,
+ d.dept_type,
+ d.ancestors,
+ d.dept_name,
+ d.order_num,
+ d.leader,
+ d.phone,
+ d.email,
+ d.orgid,
+ d.his_dept_id,
+ d.his_parent_id,
+ d.status
+ from sys_dept d
+ where del_flag = 0
+ <if test="deptCode != null and deptCode != ''">
+ AND dept_code = #{deptCode}
+ </if>
+ <if test="orgid != null and orgid != ''">
+ AND orgid = #{orgid}
+ </if>
+ <if test="campusid != null and campusid != ''">
+ AND campusid = #{campusid}
+ </if>
+ </select>
+
+ <select id="checkDeptExistUser" parameterType="Long" resultType="int">
+ select count(1)
+ from sys_user
+ where dept_id = #{deptId}
+ and del_flag = '0'
+ </select>
+
+ <select id="hasChildByDeptId" parameterType="Long" resultType="int">
+ select count(1)
+ from sys_dept
+ where del_flag = '0'
+ and parent_id = #{deptId} limit 1
+ </select>
+
+ <select id="selectChildrenDeptById" parameterType="Long" resultMap="SysDeptResult">
+ select *
+ from sys_dept
+ where find_in_set(#{deptId}, ancestors)
+ </select>
+
+ <select id="selectNormalChildrenDeptById" parameterType="Long" resultType="int">
+ select count(*)
+ from sys_dept
+ where status = 0
+ and del_flag = '0'
+ and find_in_set(#{deptId}, ancestors)
+ </select>
+
+ <select id="checkDeptNameUnique" resultMap="SysDeptResult">
+ <include refid="selectDeptVo"/>
+ where dept_name=#{deptName} and parent_id = #{parentId} and del_flag = '0' limit 1
+ </select>
+
+
+ <insert id="batchDept">
+ insert into sys_dept(
+ dept_id,
+ parent_id,
+ dept_name,
+ ancestors,
+ order_num,
+ leader,
+ phone,
+ email,
+ status,
+ dept_code,
+ dept_type,
+ create_by,
+ his_dept_id,
+ his_parent_id,
+ type,
+ guid,
+ orgid,
+ campusid,
+ create_time
+ ) values
+ <foreach collection="list" item="item" separator=",">
+ (
+ #{item.deptId},
+ #{item.parentId},
+ #{item.deptName},
+ #{item.ancestors},
+ #{item.orderNum},
+ #{item.leader},
+ #{item.phone},
+ #{item.email},
+ #{item.status},
+ #{item.deptCode},
+ #{item.deptType},
+ #{item.createBy},
+ #{item.hisDeptId},
+ #{item.hisParentId},
+ #{item.type},
+ #{item.guid},
+ #{item.orgid},
+ #{item.campusid},
+ now()
+ )
+ </foreach>
+ </insert>
+
+
+ <insert id="insertDept" parameterType="com.ruoyi.common.core.domain.entity.SysDept">
+ insert into sys_dept(
+ <if test="deptId != null and deptId != 0">dept_id,</if>
+ <if test="parentId != null and parentId != 0">parent_id,</if>
+ <if test="deptName != null and deptName != ''">dept_name,</if>
+ <if test="ancestors != null and ancestors != ''">ancestors,</if>
+ <if test="orderNum != null">order_num,</if>
+ <if test="leader != null and leader != ''">leader,</if>
+ <if test="phone != null and phone != ''">phone,</if>
+ <if test="email != null and email != ''">email,</if>
+ <if test="status != null">status,</if>
+ <if test="deptCode != null">dept_code,</if>
+ <if test="deptType != null">dept_type,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ <if test="hisDeptId != null and hisDeptId != ''">his_dept_id,</if>
+ <if test="hisParentId != null and hisParentId != ''">his_parent_id,</if>
+ <if test="type != null and type != ''">type,</if>
+ <if test="guid != null and guid != ''">guid,</if>
+ <if test="orgid != null and orgid != ''">orgid,</if>
+ <if test="campusid != null and campusid != ''">campusid,</if>
+ create_time
+ )values(
+ <if test="deptId != null and deptId != 0">#{deptId},</if>
+ <if test="parentId != null and parentId != 0">#{parentId},</if>
+ <if test="deptName != null and deptName != ''">#{deptName},</if>
+ <if test="ancestors != null and ancestors != ''">#{ancestors},</if>
+ <if test="orderNum != null">#{orderNum},</if>
+ <if test="leader != null and leader != ''">#{leader},</if>
+ <if test="phone != null and phone != ''">#{phone},</if>
+ <if test="email != null and email != ''">#{email},</if>
+ <if test="status != null">#{status},</if>
+ <if test="deptCode != null">#{deptCode},</if>
+ <if test="deptType != null">#{deptType},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ <if test="hisDeptId != null and hisDeptId != ''">#{hisDeptId},</if>
+ <if test="hisParentId != null and hisParentId != ''">#{hisParentId},</if>
+ <if test="type != null and type != ''">#{type},</if>
+ <if test="guid != null and guid != ''">#{guid},</if>
+ <if test="orgid != null and orgid != ''">#{orgid},</if>
+ <if test="campusid != null and campusid != ''">#{campusid},</if>
+ sysdate()
+ )
+ </insert>
+
+ <update id="updateDept" parameterType="com.ruoyi.common.core.domain.entity.SysDept">
+ update sys_dept
+ <set>
+ <if test="parentId != null and parentId != 0">parent_id = #{parentId},</if>
+ <if test="deptName != null and deptName != ''">dept_name = #{deptName},</if>
+ <if test="ancestors != null and ancestors != ''">ancestors = #{ancestors},</if>
+ <if test="orderNum != null">order_num = #{orderNum},</if>
+ <if test="leader != null">leader = #{leader},</if>
+ <if test="phone != null">phone = #{phone},</if>
+ <if test="orgid != null">orgid = #{orgid},</if>
+ <if test="email != null">email = #{email},</if>
+ <if test="status != null and status != ''">status = #{status},</if>
+ <if test="deptCode != null">dept_code=#{deptCode},</if>
+ <if test="deptType != null">dept_type=#{deptType},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ <if test="hisParentId != null and hisParentId != ''">his_parent_id = #{hisParentId},</if>
+ <if test="hisDeptId != null and hisDeptId != ''">his_dept_id = #{hisDeptId},</if>
+ <if test="type != null and type != ''">type = #{type},</if>
+ <if test="campusid != null and campusid != ''">campusid = #{campusid},</if>
+ update_time = sysdate()
+ </set>
+ where dept_id = #{deptId}
+ </update>
+
+ <update id="updateDeptChildren" parameterType="java.util.List">
+ update sys_dept set ancestors =
+ <foreach collection="depts" item="item" index="index"
+ separator=" " open="case dept_id" close="end">
+ when #{item.deptId} then #{item.ancestors}
+ </foreach>
+ where dept_id in
+ <foreach collection="depts" item="item" index="index"
+ separator="," open="(" close=")">
+ #{item.deptId}
+ </foreach>
+ </update>
+
+ <update id="updateDeptStatusNormal" parameterType="Long">
+ update sys_dept set status = '0' where dept_id in
+ <foreach collection="array" item="deptId" open="(" separator="," close=")">
+ #{deptId}
+ </foreach>
+ </update>
+
+ <delete id="deleteDeptById" parameterType="Long">
+ update sys_dept
+ set del_flag = '1'
+ where dept_id = #{deptId}
+ </delete>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/ext/SysUser2Mapper.xml b/ruoyi-system/src/main/resources/mapper/system/ext/SysUser2Mapper.xml
new file mode 100644
index 0000000..12680dc
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/ext/SysUser2Mapper.xml
@@ -0,0 +1,432 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.ext.SysUser2Mapper">
+
+ <resultMap type="com.ruoyi.common.core.domain.entity.SysUser" id="SysUserResult">
+ <id property="userId" column="user_id"/>
+ <id property="hisUserId" column="his_user_id"/>
+ <result property="deptId" column="dept_id"/>
+ <result property="userCode" column="user_code"/>
+ <result property="hospInfo" column="hosp_info"/>
+ <result property="deptInfo" column="dept_info"/>
+ <result property="userName" column="user_name"/>
+ <result property="nickName" column="nick_name"/>
+ <result property="email" column="email"/>
+ <result property="phonenumber" column="phonenumber"/>
+ <result property="sex" column="sex"/>
+ <result property="avatar" column="avatar"/>
+ <result property="password" column="password"/>
+ <result property="status" column="status"/>
+ <result property="delFlag" column="del_flag"/>
+ <result property="loginIp" column="login_ip"/>
+ <result property="loginDate" column="login_date"/>
+ <result property="createBy" column="create_by"/>
+ <result property="idCard" column="id_card"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="title" column="title"/>
+ <result property="birthday" column="birthday"/>
+ <result property="jobPhone" column="job_phone"/>
+ <result property="updateTime" column="update_time"/>
+ <result property="remark" column="remark"/>
+ <result property="userType" column="user_type"/>
+ <result property="searchscope" column="searchscope"/>
+ <result property="guid" column="guid"/>
+ <result property="orgid" column="orgid"/>
+ <result property="campusid" column="campusid"/>
+ <association property="dept" column="dept_id" javaType="com.ruoyi.common.core.domain.entity.SysDept"
+ resultMap="deptResult"/>
+ <collection property="roles" javaType="java.util.List" resultMap="RoleResult"/>
+ </resultMap>
+
+ <resultMap id="deptResult" type="com.ruoyi.common.core.domain.entity.SysDept">
+ <id property="deptId" column="dept_id"/>
+ <result property="parentId" column="parent_id"/>
+ <result property="deptName" column="dept_name"/>
+ <result property="ancestors" column="ancestors"/>
+ <result property="orderNum" column="order_num"/>
+ <result property="leader" column="leader"/>
+ <result property="status" column="dept_status"/>
+ </resultMap>
+
+ <resultMap id="RoleResult" type="com.ruoyi.common.core.domain.entity.SysRole">
+ <id property="roleId" column="role_id"/>
+ <result property="roleName" column="role_name"/>
+ <result property="roleKey" column="role_key"/>
+ <result property="roleSort" column="role_sort"/>
+ <result property="dataScope" column="data_scope"/>
+ <result property="status" column="role_status"/>
+ </resultMap>
+
+ <sql id="selectUserVo">
+ select u.user_id,
+ u.dept_id,
+ u.user_code,
+ u.id_card,
+ u.hosp_info,
+ u.dept_info,
+ u.searchscope,
+ u.user_name,
+ u.user_type,
+ u.nick_name,
+ u.title,
+ u.his_user_id,
+ u.job_phone,
+ u.birthday,
+ u.email,
+ u.avatar,
+ u.phonenumber,
+ u.password,
+ u.sex,
+ u.status,
+ u.del_flag,
+ u.login_ip,
+ u.login_date,
+ u.create_by,
+ u.create_time,
+ u.remark,
+ u.guid,
+ u.orgid,
+ u.campusid,
+ d.dept_id,
+ d.parent_id,
+ d.ancestors,
+ d.dept_name,
+ d.order_num,
+ d.leader,
+ d.status as dept_status,
+ r.role_id,
+ r.role_name,
+ r.role_key,
+ r.role_sort,
+ r.data_scope,
+ r.status as role_status
+ from sys_user u
+ left join sys_user_org o on o.user_id = u.user_id
+ left join sys_dept d on u.dept_id = d.dept_id
+ left join sys_user_role ur on u.user_id = ur.user_id
+ left join sys_role r on r.role_id = ur.role_id
+ </sql>
+
+ <select id="selectUserList" parameterType="com.ruoyi.common.core.domain.entity.SysUser" resultMap="SysUserResult">
+ select u.user_code,u.user_id,u.title,u.his_user_id,u.hosp_info,u.dept_info, u.searchscope, u.dept_id,
+ u.user_type,
+ u.nick_name, u.user_name,
+ u.email,u.id_card,
+ u.avatar,
+ u.birthday,
+ u.job_phone,
+ u.phonenumber, u.sex, u.status,
+ u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark,
+ u.orgid, u.campusid,
+ d.dept_name, d.leader
+ from sys_user u
+ left join sys_dept d on u.dept_id = d.dept_id
+ where u.del_flag = '0'
+ <if test="orgid != null and orgid != ''">
+ AND u.orgid = #{orgid}
+ </if>
+ <if test="userId != null and userId != 0">
+ AND u.user_id = #{userId}
+ </if>
+ <if test="userName != null and userName != ''">
+ AND u.user_name = #{userName}
+ </if>
+ <if test="nickName != null and nickName != ''">
+ AND u.nick_name like concat('%', #{nickName}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND u.status = #{status}
+ </if>
+ <if test="idCard != null and idCard != ''">
+ AND u.id_card = #{idCard}
+ </if>
+ <if test="title != null and title != ''">
+ AND u.title = #{title}
+ </if>
+ <if test="jobPhone != null and jobPhone != ''">
+ AND u.job_phone = #{jobPhone}
+ </if>
+ <if test="birthday != null and birthday != ''">
+ AND u.birthday = #{birthday}
+ </if>
+ <if test="hisUserId != null and hisUserId != ''">
+ AND u.his_user_id = #{hisUserId}
+ </if>
+ <if test="phonenumber != null and phonenumber != ''">
+ AND u.phonenumber like concat('%', #{phonenumber}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ AND date_format(u.create_time,'%y%m%d') >= date_format(#{params.beginTime},'%y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ AND date_format(u.create_time,'%y%m%d') <= date_format(#{params.endTime},'%y%m%d')
+ </if>
+ <if test="deptId != null and deptId != 0">
+ AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId},
+ ancestors) ))
+ </if>
+ <!-- 鏁版嵁鑼冨洿杩囨护 -->
+ ${params.dataScope}
+ </select>
+
+ <select id="selectAllocatedList" parameterType="com.ruoyi.common.core.domain.entity.SysUser"
+ resultMap="SysUserResult">
+ select distinct u.user_id,u.his_user_id,u.title,u.hosp_info,u.dept_info, u.searchscope, u.dept_id, u.user_name,
+ u.user_type,u.user_code,
+ u.nick_name,
+ u.email,
+ u.birthday,
+ u.job_phone,
+ u.phonenumber, u.status,u.id_card,
+ u.create_time
+ from sys_user u
+ left join sys_dept d on u.dept_id = d.dept_id
+ left join sys_user_role ur on u.user_id = ur.user_id
+ left join sys_role r on r.role_id = ur.role_id
+ where u.del_flag = '0' and r.role_id = #{roleId}
+ <if test="userName != null and userName != ''">
+ AND u.user_name like concat('%', #{userName}, '%')
+ </if>
+ <if test="phonenumber != null and phonenumber != ''">
+ AND u.phonenumber like concat('%', #{phonenumber}, '%')
+ </if>
+ <if test="title != null and title != ''">
+ AND u.title = #{title}
+ </if>
+ <if test="hisUserId != null and hisUserId != ''">
+ AND u.his_user_id = #{hisUserId}
+ </if>
+ <!-- 鏁版嵁鑼冨洿杩囨护 -->
+ ${params.dataScope}
+ </select>
+
+ <select id="selectUnallocatedList" parameterType="com.ruoyi.common.core.domain.entity.SysUser"
+ resultMap="SysUserResult">
+ select distinct u.user_id, u.dept_id, u.hosp_info, u.dept_info,u.searchscope, u.user_name, u.user_type,
+ u.nick_name,
+ u.user_code,
+ u.email,
+ u.his_user_id,
+ u.title,
+ u.job_phone,
+ u.birthday,
+ u.phonenumber, u.status,u.id_card,
+ u.create_time
+ from sys_user u
+ left join sys_dept d on u.dept_id = d.dept_id
+ left join sys_user_role ur on u.user_id = ur.user_id
+ left join sys_role r on r.role_id = ur.role_id
+ where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL)
+ and u.user_id not in (select u.user_id from sys_user u inner join sys_user_role ur on u.user_id = ur.user_id and
+ ur.role_id = #{roleId})
+ <if test="userName != null and userName != ''">
+ AND u.user_name like concat('%', #{userName}, '%')
+ </if>
+ <if test="phonenumber != null and phonenumber != ''">
+ AND u.phonenumber like concat('%', #{phonenumber}, '%')
+ </if>
+ <!-- 鏁版嵁鑼冨洿杩囨护 -->
+ ${params.dataScope}
+ </select>
+
+ <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
+ <include refid="selectUserVo"/>
+ where u.user_name = #{userName} and u.del_flag = '0'
+ </select>
+
+ <select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
+ <include refid="selectUserVo"/>
+ where u.user_id = #{userId}
+ </select>
+
+ <select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult">
+ select user_id, user_name
+ from sys_user
+ where user_name = #{userName}
+ and del_flag = '0' limit 1
+ </select>
+
+ <select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
+ select user_id, phonenumber
+ from sys_user
+ where phonenumber = #{phonenumber}
+ and del_flag = '0' limit 1
+ </select>
+
+ <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
+ select user_id, email
+ from sys_user
+ where email = #{email}
+ and del_flag = '0' limit 1
+ </select>
+
+ <insert id="insertUser" parameterType="com.ruoyi.common.core.domain.entity.SysUser" useGeneratedKeys="true"
+ keyProperty="userId">
+ insert into sys_user(
+ <if test="userId != null and userId != 0">user_id,</if>
+ <if test="deptId != null and deptId != 0">dept_id,</if>
+ <if test="userName != null and userName != ''">user_name,</if>
+ <if test="nickName != null and nickName != ''">nick_name,</if>
+ <if test="email != null and email != ''">email,</if>
+ <if test="avatar != null and avatar != ''">avatar,</if>
+ <if test="phonenumber != null and phonenumber != ''">phonenumber,</if>
+ <if test="sex != null and sex != ''">sex,</if>
+ <if test="password != null and password != ''">password,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="userType != null and userType != ''">user_type,</if>
+ <if test="deptInfo != null and deptInfo != ''">dept_info,</if>
+ <if test="hospInfo != null and hospInfo != ''">hosp_info,</if>
+ <if test="searchscope != null and searchscope != ''">searchscope,</if>
+ <if test="idCard != null and idCard != ''">id_card,</if>
+ <if test="title != null and title != ''">title,</if>
+ <if test="jobPhone != null and jobPhone != ''">job_phone,</if>
+ <if test="birthday != null ">birthday,</if>
+ <if test="hisUserId != null and hisUserId != ''">his_user_id,</if>
+ <if test="guid != null and guid != ''">guid,</if>
+ <if test="deptCode != null and deptCode != ''">dept_code,</if>
+ <if test="deptName != null and deptName != ''">dept_name,</if>
+ <if test="userCode != null and userCode != ''">user_code,</if>
+ <if test="orgid != null and orgid != ''">orgid,</if>
+ <if test="campusid != null and campusid != ''">campusid,</if>
+ create_time
+ )values(
+ <if test="userId != null and userId != 0">#{userId},</if>
+ <if test="deptId != null and deptId != 0">#{deptId},</if>
+ <if test="userName != null and userName != ''">#{userName},</if>
+ <if test="nickName != null and nickName != ''">#{nickName},</if>
+ <if test="email != null and email != ''">#{email},</if>
+ <if test="avatar != null and avatar != ''">#{avatar},</if>
+ <if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if>
+ <if test="sex != null and sex != ''">#{sex},</if>
+ <if test="password != null and password != ''">#{password},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="userType != null and userType != ''">#{userType},</if>
+ <if test="deptInfo != null and deptInfo != ''">#{deptInfo},</if>
+ <if test="hospInfo != null and hospInfo != ''">#{hospInfo},</if>
+ <if test="searchscope != null and searchscope != ''">#{searchscope},</if>
+ <if test="idCard != null and idCard != ''">#{idCard},</if>
+ <if test="title != null and title != ''">#{title},</if>
+ <if test="jobPhone != null and jobPhone != ''">#{jobPhone},</if>
+ <if test="birthday != null">#{birthday},</if>
+ <if test="hisUserId != null and hisUserId != ''">#{hisUserId},</if>
+ <if test="guid != null and guid != ''">#{guid},</if>
+ <if test="deptCode != null and deptCode != ''">#{deptCode},</if>
+ <if test="deptName != null and deptName != ''">#{deptName},</if>
+ <if test="userCode != null and userCode != ''">#{userCode},</if>
+ <if test="orgid != null and orgid != ''">#{orgid},</if>
+ <if test="campusid != null and campusid != ''">#{campusid},</if>
+ sysdate()
+ )
+ </insert>
+
+
+ <insert id="batchUser" useGeneratedKeys="true" keyProperty="userId">
+ insert into sys_user(
+ user_id, dept_id, user_name, nick_name, email, avatar, phonenumber, sex, password, status, create_by, remark,
+ user_type, dept_info, hosp_info, searchscope, id_card, title, job_phone, birthday, his_user_id, guid,
+ user_code, orgid, campusid,
+ create_time
+ ) values
+ <foreach collection="list" item="item" separator=",">
+ (
+ #{item.userId},
+ #{item.deptId},
+ #{item.userName},
+ #{item.nickName},
+ #{item.email},
+ #{item.avatar},
+ #{item.phonenumber},
+ #{item.sex},
+ #{item.password},
+ #{item.status},
+ #{item.createBy},
+ #{item.remark},
+ #{item.userType},
+ #{item.deptInfo},
+ #{item.hospInfo},
+ #{item.searchscope},
+ #{item.idCard},
+ #{item.title},
+ #{item.jobPhone},
+ #{item.birthday},
+ #{item.hisUserId},
+ #{item.guid},
+ #{item.userCode},
+ #{item.orgid},
+ #{item.campusid},
+ now()
+ )
+ </foreach>
+ </insert>
+
+ <update id="updateUser" parameterType="com.ruoyi.common.core.domain.entity.SysUser">
+ update sys_user
+ <set>
+ <if test="deptId != null and deptId != 0">dept_id = #{deptId},</if>
+ <if test="userName != null and userName != ''">user_name = #{userName},</if>
+ <if test="nickName != null and nickName != ''">nick_name = #{nickName},</if>
+ <if test="email != null ">email = #{email},</if>
+ <if test="phonenumber != null ">phonenumber = #{phonenumber},</if>
+ <if test="sex != null and sex != ''">sex = #{sex},</if>
+ <if test="avatar != null and avatar != ''">avatar = #{avatar},</if>
+ <if test="password != null and password != ''">password = #{password},</if>
+ <if test="status != null and status != ''">status = #{status},</if>
+ <if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if>
+ <if test="loginDate != null">login_date = #{loginDate},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ <if test="userType != null">user_type = #{userType},</if>
+ <if test="searchscope != null">searchscope = #{searchscope},</if>
+ <if test="deptInfo != null and deptInfo != ''">dept_info=#{deptInfo},</if>
+ <if test="hospInfo != null and hospInfo != ''">hosp_info=#{hospInfo},</if>
+ <if test="idCard != null and idCard != ''">id_card=#{idCard},</if>
+ <if test="jobPhone != null and jobPhone != ''">job_phone=#{jobPhone},</if>
+ <if test="birthday != null ">birthday=#{birthday},</if>
+ <if test="userCode != null ">user_code=#{userCode},</if>
+ <if test="title != null and title != ''">
+ title = #{title},
+ </if>
+ <if test="hisUserId != null and hisUserId != ''">
+ his_user_id = #{hisUserId},
+ </if>
+ <if test="orgid != null and orgid != ''">orgid = #{orgid},</if>
+ <if test="campusid != null and campusid != ''">campusid = #{campusid},</if>
+ update_time = sysdate()
+ </set>
+ where user_id = #{userId}
+ </update>
+
+
+ <update id="updateUserAvatar" parameterType="com.ruoyi.common.core.domain.entity.SysUser">
+ update sys_user
+ set avatar = #{avatar}
+ where user_name = #{userName}
+ </update>
+
+ <update id="resetUserPwd" parameterType="com.ruoyi.common.core.domain.entity.SysUser">
+ update sys_user
+ set password = #{password}
+ where user_name = #{userName}
+ </update>
+
+ <delete id="deleteUserById" parameterType="Long">
+ update sys_user
+ set del_flag = '1'
+ where user_id = #{userId}
+ </delete>
+
+ <delete id="deleteUserByIds" parameterType="Long">
+ update sys_user set del_flag = '1' where user_id in
+ <foreach collection="array" item="userId" open="(" separator="," close=")">
+ #{userId}
+ </foreach>
+ </delete>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/ext/SysUserDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/ext/SysUserDeptMapper.xml
new file mode 100644
index 0000000..36a01d2
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/ext/SysUserDeptMapper.xml
@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.ext.SysUserDeptMapper">
+
+ <resultMap type="com.ruoyi.common.core.domain.entity.SysUserDept" id="SysUserDeptResult">
+ <result property="id" column="id"/>
+ <result property="orgid" column="orgid"/>
+ <result property="userId" column="user_id"/>
+ <result property="deptId" column="dept_id"/>
+ <result property="delFlag" column="del_flag"/>
+ <result property="deptCode" column="dept_code"/>
+ <result property="deptName" column="dept_name"/>
+ <result property="deptType" column="dept_type"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateTime" column="update_time"/>
+ <result property="campusid" column="campusid"/>
+ </resultMap>
+
+ <resultMap id="deptResult" type="com.ruoyi.common.core.domain.entity.SysDept">
+ <id property="deptId" column="dept_id"/>
+ <result property="parentId" column="parent_id"/>
+ <result property="deptName" column="dept_name"/>
+ <result property="ancestors" column="ancestors"/>
+ <result property="orderNum" column="order_num"/>
+ <result property="leader" column="leader"/>
+ <result property="status" column="dept_status"/>
+ <result property="campusid" column="campusid"/>
+ </resultMap>
+
+ <sql id="selectSysUserDeptVo">
+ select id,
+ user_id,
+ dept_id,
+ del_flag,
+ campusid,
+ orgid,
+ create_time,
+ update_time,
+ dept_code,
+ dept_name,
+ dept_type
+ from sys_user_dept
+ </sql>
+
+ <select id="selectSysUserDeptList" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept"
+ resultMap="SysUserDeptResult">
+ <include refid="selectSysUserDeptVo"/>
+ where 1=1
+ and del_flag = 0
+ and orgid=#{orgid}
+ <if test="userId != null ">
+ and user_id = #{userId}
+ </if>
+ <if test="deptId != null ">
+ and dept_id = #{deptId}
+ </if>
+ <if test="delFlag != null ">
+ and del_flag = #{delFlag}
+ </if>
+ <if test="createTime != null ">
+ and create_time = #{createTime}
+ </if>
+ <if test="updateTime != null ">
+ and update_time = #{updateTime}
+ </if>
+ <if test="deptType != null ">
+ and dept_type = #{deptType}
+ </if>
+ <if test="deptCode != null ">
+ and dept_code = #{deptCode}
+ </if>
+ <if test="campusid != null ">
+ and campusid = #{campusid}
+ </if>
+ </select>
+
+ <select id="selectSysUserDeptById" parameterType="Long"
+ resultMap="SysUserDeptResult">
+ <include refid="selectSysUserDeptVo"/>
+ where id = #{id}
+ </select>
+
+ <!--
+ HIS 鍚屾浠诲姟姣忚窇涓�娆″氨鎶婂悓涓�鐢ㄦ埛/绉戝/鐥呭尯鍐嶆彃涓�閬嶏紝鍘嗗彶涓婃妸 sys_user_dept 鎾戝埌 157 涓囪
+ 锛堢湡姝d笉鍚岀殑鍙湁 4 涓囧鏉★級銆傝繖閲屾敼鎴� insert ... select ... where not exists锛�
+ 鍚屼竴 user_id + dept_type + dept_code 宸叉湁鏈夋晥璁板綍鏃剁洿鎺ヨ烦杩囷紝閲嶅鎵ц涔熶笉浼氫骇鐢熻剰鏁版嵁銆�
+ -->
+ <insert id="insertSysUserDept" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept"
+ useGeneratedKeys="true" keyProperty="id">
+ insert into sys_user_dept
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="userId != null">user_id,
+ </if>
+ <if test="deptId != null">dept_id,
+ </if>
+ <if test="delFlag != null ">
+ del_flag,
+ </if>
+ <if test="createTime != null ">
+ create_time,
+ </if>
+ <if test="updateTime != null ">
+ update_time,
+ </if>
+ <if test="deptType != null ">
+ dept_type,
+ </if>
+ <if test="deptCode != null ">
+ dept_code,
+ </if>
+ <if test="deptName != null ">
+ dept_name,
+ </if>
+ <if test="orgid != null ">
+ orgid,
+ </if>
+ <if test="userCode != null ">
+ user_code,
+ </if>
+ <if test="campusid != null ">
+ campusid,
+ </if>
+ </trim>
+ select
+ <trim suffixOverrides=",">
+ <if test="userId != null">#{userId},
+ </if>
+ <if test="deptId != null">#{deptId},
+ </if>
+ <if test="delFlag != null ">
+ #{delFlag},
+ </if>
+ <if test="createTime != null ">
+ #{createTime},
+ </if>
+ <if test="updateTime != null ">
+ #{updateTime},
+ </if>
+ <if test="deptType != null ">
+ #{deptType},
+ </if>
+ <if test="deptCode != null ">
+ #{deptCode},
+ </if>
+ <if test="deptName != null ">
+ #{deptName},
+ </if>
+ <if test="orgid != null ">
+ #{orgid},
+ </if>
+ <if test="userCode != null ">
+ #{userCode},
+ </if>
+ <if test="campusid != null ">
+ #{campusid},
+ </if>
+ </trim>
+ from dual
+ where not exists (
+ select 1 from sys_user_dept
+ where user_id = #{userId}
+ and ifnull(dept_type, '') = ifnull(#{deptType}, '')
+ and ifnull(dept_code, '') = ifnull(#{deptCode}, '')
+ and ifnull(del_flag, 0) = 0
+ )
+ </insert>
+
+ <update id="updateSysUserDept" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept">
+ update sys_user_dept
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="userId != null">user_id =
+ #{userId},
+ </if>
+ <if test="deptId != null">dept_id =
+ #{deptId},
+ </if>
+ <if test="delFlag != null ">
+ del_flag = #{delFlag},
+ </if>
+ <if test="createTime != null ">
+ create_time = #{createTime},
+ </if>
+ <if test="updateTime != null ">
+ update_time = #{updateTime},
+ </if>
+ <if test="deptType != null ">
+ dept_type = #{deptType},
+ </if>
+ <if test="deptCode != null ">
+ dept_code = #{deptCode},
+ </if>
+ <if test="deptName != null ">
+ dept_name = #{deptName},
+ </if>
+ <if test="orgid != null ">
+ orgid = #{orgid},
+ </if>
+ <if test="campusid != null ">
+ campusid = #{campusid},
+ </if>
+ </trim>
+ where id = #{id}
+ </update>
+
+ <update id="deleteSysUserDeptById" parameterType="Long">
+ update sys_user_dept
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1
+ </trim>
+ where id = #{id}
+ </update>
+
+ <select id="selectDeptListByUserId" resultMap="deptResult">
+ select d.dept_id,
+ d.dept_name,
+ d.parent_id,
+ d.ancestors,
+ d.dept_name,
+ d.order_num,
+ d.campusid,
+ d.leader,
+ d.orgid,
+ d.status as dept_status
+ from sys_dept d
+ left join sys_user_dept ud on d.dept_code = ud.dept_code
+ where ud.user_id = #{userId}
+ and ud.del_flag = 0
+ and d.del_flag = 0
+ </select>
+ <update id="deleteSysUserDeptByIds" parameterType="String">
+ update sys_user_dept
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1,
+ update_time = sysdate()
+ </trim>
+ where user_id in
+ <foreach item="id" collection="array" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </update>
+
+
+ <update id="deleteSysUserDeptByCode" parameterType="String">
+ update sys_user_dept
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1,
+ update_time = sysdate()
+ </trim>
+ where del_flag = 0
+ and user_id =#{userId}
+ and dept_code=#{deptCode}
+ </update>
+
+ <update id="updateSysUserDeptForSync" parameterType="com.ruoyi.common.core.domain.entity.SysUserDept">
+ update sys_user_dept
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="deptId != null">dept_id =
+ #{deptId},
+ </if>
+ <if test="delFlag != null ">
+ del_flag = #{delFlag},
+ </if>
+ <if test="createTime != null ">
+ create_time = #{createTime},
+ </if>
+ <if test="updateTime != null ">
+ update_time = #{updateTime},
+ </if>
+ <if test="deptType != null ">
+ dept_type = #{deptType},
+ </if>
+ <if test="deptCode != null ">
+ dept_code = #{deptCode},
+ </if>
+ <if test="deptName != null ">
+ dept_name = #{deptName},
+ </if>
+ <if test="orgid != null ">
+ orgid = #{orgid},
+ </if>
+ <if test="campusid != null ">
+ campusid = #{campusid},
+ </if>
+ </trim>
+ where user_id =#{userId}
+ <if test="orgid != null and orgid != ''">
+ and orgid = #{orgid}
+ </if>
+ <if test="campusid != null and campusid != ''">
+ and campusid = #{campusid}
+ </if>
+ </update>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/ext/SysUserRole2Mapper.xml b/ruoyi-system/src/main/resources/mapper/system/ext/SysUserRole2Mapper.xml
new file mode 100644
index 0000000..7bf0e0b
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/ext/SysUserRole2Mapper.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.ext.SysUserRole2Mapper">
+
+ <resultMap type="com.ruoyi.common.core.domain.entity.SysUserRole" id="SysUserRoleResult">
+ <result property="userId" column="user_id"/>
+ <result property="roleId" column="role_id"/>
+ <result property="guid" column="guid"/>
+ <result property="orgid" column="orgid"/>
+ </resultMap>
+
+ <delete id="deleteUserRoleByUserId" parameterType="Long">
+ delete
+ from sys_user_role
+ where user_id = #{userId}
+ </delete>
+
+ <select id="countUserRoleByRoleId" resultType="Integer">
+ select count(1)
+ from sys_user_role
+ where role_id = #{roleId}
+ </select>
+
+ <select id="selectUserRoleByRoleIdAndUserId" resultMap="SysUserRoleResult">
+ select user_id,role_id,guid,orgid
+ from sys_user_role
+ where 1=1
+ <if test="roleId != null ">and role_id = #{roleId}</if>
+ <if test="userId != null ">and user_id = #{userId}</if>
+
+ </select>
+
+ <delete id="deleteUserRole" parameterType="Long">
+ delete from sys_user_role where user_id in
+ <foreach collection="array" item="userId" open="(" separator="," close=")">
+ #{userId}
+ </foreach>
+ </delete>
+
+ <insert id="batchUserRole">
+ insert into sys_user_role(user_id, role_id,guid,orgid) values
+ <foreach item="item" index="index" collection="list" separator=",">
+ (#{item.userId},#{item.roleId},#{item.guid},#{item.orgid})
+ </foreach>
+ </insert>
+
+ <delete id="deleteUserRoleInfo" parameterType="SysUserRole">
+ delete
+ from sys_user_role
+ where user_id = #{userId}
+ and role_id = #{roleId}
+ </delete>
+
+ <delete id="deleteUserRoleInfos">
+ delete from sys_user_role where role_id=#{roleId} and user_id in
+ <foreach collection="userIds" item="userId" open="(" separator="," close=")">
+ #{userId}
+ </foreach>
+ </delete>
+</mapper>
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/OperationSubtaskWriter.java b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/OperationSubtaskWriter.java
new file mode 100644
index 0000000..bb0f11a
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/OperationSubtaskWriter.java
@@ -0,0 +1,730 @@
+package com.ruoyi.task.api.contract;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.common.core.domain.entity.PatArchive;
+import com.ruoyi.common.core.service.dto.PatMedReq;
+import com.ruoyi.common.core.service.dto.PatMedRes;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.DtoConversionUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.inhospvisit.api.InhospVisitFacade;
+import com.ruoyi.inhospvisit.domain.PatMedInhosp;
+import com.ruoyi.inhospvisit.domain.PatMedInhospDTO;
+import com.ruoyi.inhospvisit.domain.PatMedInhospVO;
+import com.ruoyi.othervisit.api.OtherVisitFacade;
+import com.ruoyi.othervisit.domain.PatMedOperationItem;
+import com.ruoyi.task.api.spi.TaskArchivePort;
+import com.ruoyi.task.common.ScheduleSubtaskBuilder;
+import com.ruoyi.task.domain.ServiceSubtask;
+import com.ruoyi.task.domain.ServiceSubtaskPreachform;
+import com.ruoyi.task.domain.ServiceTask;
+import com.ruoyi.task.domain.ServiceTaskRule;
+import com.ruoyi.task.domain.ServiceTaskSchedule;
+import com.ruoyi.task.domain.ServiceTaskScheduleDetail;
+import com.ruoyi.task.domain.ServiceTaskdept;
+import com.ruoyi.task.domain.ServiceTaskdiag;
+import com.ruoyi.task.domain.ServiceTaskoper;
+import com.ruoyi.task.domain.entity.ServiceSubtaskEntity;
+import com.ruoyi.task.mapper.ServiceSubtaskMapper;
+import com.ruoyi.task.mapper.ServiceSubtaskPreachformMapper;
+import com.ruoyi.task.mapper.ServiceTaskMapper;
+import com.ruoyi.task.mapper.ServiceTaskRuleMapper;
+import com.ruoyi.task.mapper.ServiceTaskScheduleDetailMapper;
+import com.ruoyi.task.mapper.ServiceTaskScheduleMapper;
+import com.ruoyi.task.mapper.ServiceTaskdeptMapper;
+import com.ruoyi.task.mapper.ServiceTaskdiagMapper;
+import com.ruoyi.task.mapper.ServiceTaskoperMapper;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+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;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+
+/**
+ * 鎵嬫湳闅忚鍒嗘敮 + 浠诲姟缁勯杞撼鍏ャ��
+ *
+ * <h3>浣嶇疆鍙樻洿鍙诧紙涓ゆ鍥為��鍚庢墠钀藉湪杩欓噷锛屽埆鍐嶉殢鎵嬫尓锛�</h3>
+ * <ol>
+ * <li>鍘熸湰鍦� {@code PatMedInhospServiceImpl}锛堢害 1600 琛岋級閲岋紝2026-11 鍏堟暣绨囨娊鍒�
+ * {@code smartor/.../impl/op/OperationSubtaskWriter}锛屽師鏂规硶鏀规垚涓�琛屽鎵� 鈥斺��
+ * <b>鏂规硶浣撻�愬瓧鏈彉</b>锛�</li>
+ * <li>灏濊瘯鏁寸被鎼繘 {@code ruoyi-othervisit} 鈫� <b>Maven 鐜�</b>锛�
+ * {@code task -> othervisit -> patarchive -> task}锛�</li>
+ * <li>鏀圭敤 {@code ruoyi-task} + {@code TaskArchivePort} 鏂幆锛屼絾褰撴椂鐢ㄨ剼鏈憳鏂规硶
+ * 鎶� 1600 琛岀殑绫绘敼鍧忥紝宸插洖閫�锛�</li>
+ * <li>鏈疆锛堢 7 杞級钀藉湪 {@code ruoyi-task}锛氬畠鏈潵灏辨嫢鏈�
+ * {@code service_task*} / {@code service_subtask*} 鐨勫啓鑳藉姏锛屼笖宸蹭緷璧�
+ * {@code inhospvisit} / {@code othervisit}锛岃妗f璧� {@link TaskArchivePort}锛�
+ * <b>涓嶄緷璧� ruoyi-patarchive</b>锛岀幆褰诲簳娑堝け銆�</li>
+ * </ol>
+ *
+ * <h3>鈿狅笍 鍙惉浣嶇疆锛屼笉鏀归�昏緫</h3>
+ * 鏂规硶浣撲笌鍦� smartor 鏃堕�愬瓧涓�鑷达紱鍞竴鐨勬暟鎹闂浛鎹㈡槸
+ * {@code patArchiveMapper.selectPatArchiveByPatid(..)} 鈫� {@code taskArchivePort.findByPatid(..)}
+ * 锛坽@code TaskArchivePortImpl} 閲屽氨鏄悓涓�涓� {@code PatArchiveMapper} 鐨勭函杞彂锛夈��
+ *
+ * <h3>璋佸湪璋冨畠</h3>
+ * 鍙粡 {@link OtherVisitApiImpl}锛堟湰鍖呭唴锛夊澶栵紝鍗� {@code ruoyi-common} 鐨�
+ * {@code OtherVisitApi} 濂戠害锛泂martor 渚х殑 {@code OtherVisitApiBridge} 宸插垹闄わ紝
+ * {@code IPatMedInhospService} 涓婄殑 3 涓繃娓″叆鍙d篃宸蹭竴骞跺垹闄ゃ��
+ */
+@Slf4j
+@Component
+public class OperationSubtaskWriter {
+
+ @Value("${spring.profiles.active}")
+ private String active;
+
+ @Autowired
+ private InhospVisitFacade inhospVisitFacade;
+
+ @Autowired
+ private OtherVisitFacade otherVisitFacade;
+
+ @Autowired
+ private TaskArchivePort taskArchivePort;
+
+ @Autowired
+ private ScheduleSubtaskBuilder scheduleSubtaskBuilder;
+
+ @Autowired
+ private ServiceSubtaskMapper serviceSubtaskMapper;
+
+ @Autowired
+ private ServiceSubtaskPreachformMapper serviceSubtaskPreachformMapper;
+
+ @Autowired
+ private ServiceTaskMapper serviceTaskMapper;
+
+ @Autowired
+ private ServiceTaskScheduleDetailMapper serviceTaskScheduleDetailMapper;
+
+ @Autowired
+ private ServiceTaskScheduleMapper serviceTaskScheduleMapper;
+
+ @Autowired
+ private ServiceTaskoperMapper serviceTaskoperMapper;
+
+ public int dealOutHospInfoBySchedule(String config) {
+
+ ServiceTask serviceTaskVo = new ServiceTask();
+ serviceTaskVo.setLongTask(1);
+ serviceTaskVo.setAppltype("5");
+ List<ServiceTask> serviceTasks = serviceTaskMapper.selectServiceTaskList(serviceTaskVo);
+
+ if (CollectionUtils.isNotEmpty(serviceTasks)) {
+ for (ServiceTask serviceTask : serviceTasks) {
+ if (!ObjectUtils.isEmpty(serviceTask.getTaskid())) {
+ ServiceTaskSchedule serviceTaskSchedule = new ServiceTaskSchedule();
+ ServiceTaskSchedule taskSchedule = new ServiceTaskSchedule();
+ taskSchedule.setTaskid(serviceTask.getTaskid());
+ List<ServiceTaskSchedule> serviceTaskSchedules = serviceTaskScheduleMapper.selectServiceTaskScheduleList(taskSchedule);
+ if (CollectionUtils.isNotEmpty(serviceTaskSchedules)) {
+ serviceTaskSchedule = serviceTaskSchedules.get(0);
+ String deptCodes = serviceTaskSchedule.getDeptCodes();
+ String wardCodes = serviceTaskSchedule.getWardCodes();
+ String icd10Codes = serviceTaskSchedule.getIcd10Codes();
+ String opLevelCodes = serviceTaskSchedule.getOplevelCodes();
+
+ List<String> icd10CodeList = new ArrayList<>();
+ List<String> opLevelCodeList = new ArrayList<>();
+ List<String> deptCodeList = new ArrayList<>();
+ List<String> wardCodeList = new ArrayList<>();
+
+ /**
+ * 闅忚绫诲瀷(1-绉戝锛�2-鐥呭尯锛�3-鐤剧梾 4-鍏ラ櫌绉戝 5-鍏ラ櫌鐥呭尯 6-鎵嬫湳)
+ */
+ Integer type = 1;
+ if (StringUtils.isNotEmpty(deptCodes)) {
+ type = 1;
+ deptCodeList = new ArrayList<>(Arrays.asList(deptCodes.split(",")));
+ }
+ if (StringUtils.isNotEmpty(wardCodes)) {
+ type = 2;
+ wardCodeList = new ArrayList<>(Arrays.asList(wardCodes.split(",")));
+ }
+ if (StringUtils.isNotEmpty(icd10Codes)) {
+ type = 3;
+ icd10CodeList = new ArrayList<>(Arrays.asList(icd10Codes.split(",")));
+ }
+ if (StringUtils.isNotEmpty(opLevelCodes)) {
+ type = 6;
+ opLevelCodeList = new ArrayList<>(Arrays.asList(opLevelCodes.split(",")));
+ }
+ //闈炴墜鏈鐞嗘柟寮�
+ if (type != 6) {
+ PatMedInhosp patMedInhospVo = new PatMedInhosp();
+ patMedInhospVo.setScheduleCheckFlag("0");
+ patMedInhospVo.setInhospstate("1");
+ patMedInhospVo.setFuflag("1");
+// patMedInhospVo.setDeptcodeList(deptCodeList);
+ patMedInhospVo.setLeaveldeptcodes(deptCodeList);
+ patMedInhospVo.setLeavehospitaldistrictcodes(wardCodeList);
+ patMedInhospVo.setIcd10codeList(icd10CodeList);
+ List<PatMedInhosp> patList = inhospVisitFacade.selectPatMedInhospList(patMedInhospVo);
+ log.info("dealOutHospInfoBySchedule 浠诲姟缁勯殢璁�, taskid = {}, 鎵弿鎮h�呬汉鏁� {}", serviceTask.getTaskid(), patList.size());
+
+ for (PatMedInhosp patMedInhosp : patList) {
+ ServiceTaskScheduleDetail scheduleDetailVo = new ServiceTaskScheduleDetail();
+ scheduleDetailVo.setTaskid(serviceTask.getTaskid());
+ scheduleDetailVo.setScheduleid(serviceTaskSchedule.getId());
+ List<ServiceTaskScheduleDetail> serviceTaskScheduleDetails = serviceTaskScheduleDetailMapper.selectServiceTaskScheduleDetailList(scheduleDetailVo);
+
+ PatArchive patArchive = taskArchivePort.findByPatid(patMedInhosp.getPatid());
+ if (Objects.isNull(patArchive)) {
+ continue;
+ }
+ //灏佽serviceSubtask
+
+ ServiceSubtask serviceSubtask = boxedServiceSubtask(serviceTask, patMedInhosp, patArchive, config, type);
+ List<Map<String, Object>> preachformList = new ArrayList<>();
+ if (StringUtils.isNotEmpty(serviceTask.getPreachformDesc())) {
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
+ preachformList = objectMapper.readValue(serviceTask.getPreachformDesc(), List.class);
+ } catch (Exception e) {
+ log.error("浠诲姟缁刾reachformDesc瑙f瀽澶辫触,taskid={},inhospid={}", serviceTask.getTaskid(), patMedInhosp.getInhospid());
+ }
+ }
+ scheduleSubtaskBuilder.buildSubtasksForPatient(serviceTask, serviceTaskSchedule, serviceTaskScheduleDetails, serviceSubtask, preachformList);
+ //缃杞撼鍏ユ爣璁帮紝閬垮厤涓嬫鎵弿閲嶅鐢熸垚锛堝悗缁疆娆$敱 rollTaskGroupCycle 璐熻矗锛�
+ PatMedInhosp flagUpd = new PatMedInhosp();
+ flagUpd.setInhospid(patMedInhosp.getInhospid());
+ flagUpd.setScheduleCheckFlag("1");
+ inhospVisitFacade.updatePatMedInhosp(flagUpd);
+ }
+ } else {
+ //浠诲姟缁� - 鎵嬫湳闅忚
+ if (CollectionUtils.isNotEmpty(opLevelCodeList)) {
+ PatMedOperationItem pmoi = new PatMedOperationItem();
+ //鑾峰彇闇�瑕佸嚭闄㈢柧鐥呴殢璁匡紝鏈鐞嗙殑鏁版嵁
+ pmoi.setOpercheckFlag("0");
+ pmoi.setMainFlag("1");
+ pmoi.setDeptCodes(deptCodeList);
+ pmoi.setWardCodes(wardCodeList);
+ pmoi.setOpLevelCodes(opLevelCodeList);
+
+ //姣忔鏌ヨ鍙煡鏈�澶х殑鎵嬫湳绛夌骇璁板綍
+ List<PatMedOperationItem> patMedOperationItems = otherVisitFacade.selectOperationItemListMaxLevel(pmoi);
+ for (PatMedOperationItem patMedOperationItem : patMedOperationItems) {
+ PatArchive patArchive = taskArchivePort.findByPatid(patMedOperationItem.getPatid());
+ if (Objects.isNull(patArchive)) {
+ continue;
+ }
+ PatMedInhosp patMedInhospVo = new PatMedInhosp();
+ patMedInhospVo.setPatid((patMedOperationItem.getPatid()));
+ patMedInhospVo.setScheduleCheckFlag("0");
+ patMedInhospVo.setInhospstate("1");
+ patMedInhospVo.setFuflag("1");
+ List<PatMedInhosp> patMedInhospList = inhospVisitFacade.selectPatMedInhospList(patMedInhospVo);
+ if (CollectionUtils.isNotEmpty(patMedInhospList)) {
+ ServiceTaskScheduleDetail scheduleDetailVo = new ServiceTaskScheduleDetail();
+ scheduleDetailVo.setTaskid(serviceTask.getTaskid());
+ scheduleDetailVo.setScheduleid(serviceTaskSchedule.getId());
+ List<ServiceTaskScheduleDetail> serviceTaskScheduleDetails = serviceTaskScheduleDetailMapper.selectServiceTaskScheduleDetailList(scheduleDetailVo);
+ //灏佽serviceSubtask
+ ServiceSubtask serviceSubtask = boxedServiceSubtaskForOp(serviceTask, patMedInhospList.get(0), patMedOperationItem, patArchive, config);
+ List<Map<String, Object>> preachformList = new ArrayList<>();
+ if (StringUtils.isNotEmpty(serviceTask.getPreachformDesc())) {
+ try {
+ ObjectMapper objectMapper = new ObjectMapper();
+ preachformList = objectMapper.readValue(serviceTask.getPreachformDesc(), List.class);
+ } catch (Exception e) {
+ log.error("浠诲姟缁�(鎵嬫湳)preachformDesc瑙f瀽澶辫触,taskid={}", serviceTask.getTaskid());
+ }
+ }
+ scheduleSubtaskBuilder.buildSubtasksForPatient(serviceTask, serviceTaskSchedule, serviceTaskScheduleDetails, serviceSubtask, preachformList);
+ //缃杞撼鍏ユ爣璁帮紝閬垮厤閲嶅鐢熸垚
+ PatMedInhosp flagUpd = new PatMedInhosp();
+ flagUpd.setInhospid(patMedInhospList.get(0).getInhospid());
+ flagUpd.setScheduleCheckFlag("1");
+ inhospVisitFacade.updatePatMedInhosp(flagUpd);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return 1;
+ }
+
+ public void addOperationSubTask(String config) {
+ // 鎵嬫湳闅忚
+ PatMedOperationItem pmoi = new PatMedOperationItem();
+ //鑾峰彇闇�瑕佸嚭闄㈡墜鏈殢璁匡紝鏈鐞嗙殑鏁版嵁
+ if(!active.equals("hzszlyy")){
+ pmoi.setInhospstate("1");
+ }
+ pmoi.setOpercheckFlag("0");
+ pmoi.setMainFlag("1");
+
+ //姣忔鏌ヨ鍙煡鏈�澶х殑鎵嬫湳绛夌骇璁板綍
+ List<PatMedOperationItem> patMedOperationItems = otherVisitFacade.selectOperationItemListMaxLevel(pmoi);
+ log.info("dealOutHospInfo闇�瑕佸鐞嗙殑鍑洪櫌鎵嬫湳鎮h�呬俊鎭細{}", CollectionUtils.isNotEmpty(patMedOperationItems) ? patMedOperationItems.size() : null);
+
+ for (PatMedOperationItem opItem : patMedOperationItems) {
+
+ try {
+ if (StringUtils.isEmpty(opItem.getOplevelcode())) {
+ continue;
+ }
+ // 鏍规嵁鎮h�呯殑鐤剧梾锛岃幏鍙栬鐤剧梾鐨勯暱鏈熶换鍔�
+ List<ServiceTaskoper> serviceTaskopersDept = new ArrayList<>();
+ if(StringUtils.isNotEmpty(opItem.getLeaveldeptcode())){
+ ServiceTaskoper serviceTaskoper1 = new ServiceTaskoper();
+ serviceTaskoper1.setLongtask(1L);
+ serviceTaskoper1.setOrgid(opItem.getOrgid());
+ serviceTaskoper1.setOplevelcode(opItem.getOplevelcode());
+ serviceTaskoper1.setDeptCode(opItem.getLeaveldeptcode());
+ serviceTaskopersDept = serviceTaskoperMapper.selectServiceTaskoperList(serviceTaskoper1);
+ }
+
+
+ List<ServiceTaskoper> serviceTaskopersWard = new ArrayList<>();
+ if(StringUtils.isNotEmpty(opItem.getLeavehospitaldistrictcode())){
+ ServiceTaskoper serviceTaskoper2 = new ServiceTaskoper();
+ serviceTaskoper2.setLongtask(1L);
+ serviceTaskoper2.setOrgid(opItem.getOrgid());
+ serviceTaskoper2.setOplevelcode(opItem.getOplevelcode());
+ serviceTaskoper2.setWardCode(opItem.getLeavehospitaldistrictcode());
+ serviceTaskopersWard = serviceTaskoperMapper.selectServiceTaskoperList(serviceTaskoper2);
+ }
+
+
+ List<ServiceTaskoper> serviceTaskopers = new ArrayList<>();
+ serviceTaskopers.addAll(serviceTaskopersDept);
+ serviceTaskopers.addAll(serviceTaskopersWard);
+ //濡傛灉閮ㄩ棬妯℃澘涓虹┖锛堝皢deptIsNull璁剧疆涓簍rue锛�
+ if (CollectionUtils.isEmpty(serviceTaskopers) || serviceTaskopers.size() == 0) {
+ PatMedOperationItem patMedOperationItem = otherVisitFacade.selectOperationItemById(opItem.getId());
+ patMedOperationItem.setOpercheckFlag("2");
+ patMedOperationItem.setLongTaskReason("鎵�鎮g殑鎵嬫湳鏈厤缃暱鏈熶换鍔�;");
+ patMedOperationItem.setUpdateTime(new Date());
+ otherVisitFacade.updateOperationItem(patMedOperationItem);
+ } else {
+ for (ServiceTaskoper serviceTaskoper : serviceTaskopers) {
+ writeInSubTaskForOp(serviceTaskoper.getTaskId(), true, opItem, config);
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("浜哄憳鎵嬫湳澶勭悊鍑哄紓甯镐簡锛歿}", e.getMessage());
+ opItem.setUpdateTime(new Date());
+ opItem.setOpercheckFlag("2");
+ opItem.setLongTaskReason("浜哄憳鎵嬫湳澶勭悊寮傚父");
+ otherVisitFacade.updateOperationItem(opItem);
+ }
+ }
+ }
+
+ public int runOperationVisit(String config) {
+ addOperationSubTask(config);
+ return 1;
+ }
+
+ private void writeInSubTaskForOp(Long taskid, Boolean check, PatMedOperationItem patMedOperationItem, String config) {
+ String longTaskReason = patMedOperationItem.getLongTaskReason();
+ String orgId = patMedOperationItem.getOrgid();
+ if (StringUtils.isEmpty(longTaskReason)) longTaskReason = "";
+ ServiceTask st = new ServiceTask();
+ st.setTaskid(taskid);
+ st.setSendState(2L);
+ List<ServiceTask> serviceTasks = serviceTaskMapper.selectServiceTaskList(st);
+ ServiceTask serviceTask = null;
+ if (CollectionUtils.isEmpty(serviceTasks)) {
+ log.info("璇ユ墜鏈搴旀墜鏈瓑绾х殑闀挎湡浠诲姟涓嶅瓨鍦�,浠诲姟ID涓猴細{}", taskid);
+ patMedOperationItem.setOpercheckFlag("2");
+ patMedOperationItem.setLongTaskReason(" & 璇ユ墜鏈搴旀墜鏈瓑绾х殑闀挎湡浠诲姟涓嶅瓨鍦�,浠诲姟ID涓�:" + taskid +";");
+ otherVisitFacade.updateOperationItem(patMedOperationItem);
+ return;
+ } else {
+ serviceTask = serviceTasks.get(0);
+ }
+ if (Objects.isNull(patMedOperationItem.getOplevelcode())) {
+ return;
+ }
+ if (Objects.isNull(patMedOperationItem.getPatid())) {
+ return;
+ }
+ PatArchive patArchive = taskArchivePort.findByPatid(patMedOperationItem.getPatid());
+ if (Objects.isNull(patArchive)) {
+ return;
+ }
+ PatMedInhosp patMedInhosp = new PatMedInhosp();
+ patMedInhosp.setPatid((patMedOperationItem.getPatid()));
+ patMedInhosp.setInhospstate("1");
+ patMedInhosp.setFuflag("1");
+ //鎵嬫湳闅忚
+ if(!active.equals("hzszlyy")){
+ patMedInhosp.setSerialnum(patMedOperationItem.getSerialnum());
+ }
+ List<PatMedInhosp> patMedInhospList = inhospVisitFacade.selectPatMedInhospList(patMedInhosp);
+
+ if (CollectionUtils.isEmpty(patMedInhospList)) {
+ return;
+ }
+
+ //灏佽serviceSubtask
+ ServiceSubtask serviceSubtask = boxedServiceSubtaskForOp(serviceTask, patMedInhospList.get(0), patMedOperationItem, patArchive, config);
+ if (ObjectUtils.isEmpty(serviceSubtask) || Objects.isNull(serviceSubtask.getTaskid())) {
+ return;
+ }
+ if (StringUtils.isNotEmpty(patMedOperationItem.getLeaveldeptcode())) {
+ serviceSubtask.setVisitDeptCode(patMedOperationItem.getLeaveldeptcode());
+ serviceSubtask.setVisitDeptName(patMedOperationItem.getLeaveldeptname());
+ } else {
+ serviceSubtask.setVisitDeptCode(patMedOperationItem.getLeavehospitaldistrictcode());
+ serviceSubtask.setVisitDeptName(patMedOperationItem.getLeavehospitaldistrictname());
+ }
+ //璁板綍insertServiceSubtask璇彞杩斿洖鐘舵��
+ Integer i = 0;
+ try {
+ //鍏堝垽鏂竴涓嬶紝鏄惁闇�瑕佹牎楠�
+ if (check && (Objects.isNull(serviceSubtask.getTaskSituation()) || serviceSubtask.getTaskSituation() != 6)) {
+ //鍦ㄦ柊澧炰箣鍓嶏紝鍏堥�氳繃鎮h�匢D锛宻endstate=2鏌ヨ涓�涓嬶紝鍦ㄦ墍鏈夐暱鏈熶换鍔′腑锛屾槸涓嶆槸杩樻湁璇ユ偅鑰呭緟鎵ц鐨勪换鍔★紝鏈夌殑璇�,姣旇緝涔嬪墠鐨別ndtime鏄惁灏忎簬褰撳墠鐨別ndtaime,濡傛灉涔嬪墠鐨勫皬浜庣幇鍦ㄧ殑锛屽垯鐩存帴灏嗕箣鍓嶇殑鍋滄帀锛堝師鍥犲啀鍏ラ櫌锛�
+ ServiceSubtaskEntity subtask = new ServiceSubtaskEntity();
+ subtask.setPatid(patArchive.getId());
+ subtask.setSendstate(2L);
+ subtask.setTaskid(taskid);
+ List<ServiceSubtask> selectServiceSubtaskList = serviceSubtaskMapper.selectServiceSubtaskList(subtask);
+// log.info("璇ユ偅鑰呭緟鎵ц鐨勪换鍔�:{}", CollectionUtils.isNotEmpty(selectServiceSubtaskList) ? selectServiceSubtaskList.size() : null);
+ if (CollectionUtils.isNotEmpty(selectServiceSubtaskList) && selectServiceSubtaskList.size() > 0) {
+ for (ServiceSubtask serviceSubtask1 : selectServiceSubtaskList) {
+ if (Objects.isNull(serviceSubtask1.getLongSendTime())) {
+ //涓嶆槸闀挎湡浠诲姟锛屼笉澶勭悊
+ continue;
+ }
+ }
+ } else {
+ if (StringUtils.isEmpty(serviceSubtask.getPhone())) {
+ if (StringUtils.isNotEmpty(serviceSubtask.getRemark()))
+ serviceSubtask.setRemark(serviceSubtask.getRemark() + ",鎵嬫満鍙蜂负绌�");
+ else serviceSubtask.setRemark("鎵嬫満鍙蜂负绌�");
+ serviceSubtask.setSendstate(4L);
+ serviceSubtask.setResult("error");
+ }
+ serviceSubtask.setCreateBy(serviceTask.getCreateBy());
+ serviceSubtask.setCreateTime(new Date());
+ i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtask);
+ addServiceSubtaskPreachform(serviceSubtask, null);
+ }
+ } else if (serviceSubtask.getTaskSituation() == 6) {
+ //璇存槑璇ユ偅鑰呮槸琚繃婊ょ殑锛屼笉鐢ㄥ啀鎵ц浜�
+ serviceSubtask.setCreateBy(serviceTask.getCreateBy());
+ serviceSubtask.setCreateTime(new Date());
+ serviceSubtask.setSendstate(4L);
+ i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtask);
+ } else {
+ if (StringUtils.isEmpty(serviceSubtask.getPhone())) {
+ if (StringUtils.isNotEmpty(serviceSubtask.getRemark()))
+ serviceSubtask.setRemark(serviceSubtask.getRemark() + ",鎵嬫満鍙蜂负绌�");
+ else serviceSubtask.setRemark("鎵嬫満鍙蜂负绌�");
+ serviceSubtask.setSendstate(4L);
+ serviceSubtask.setResult("error");
+ }
+ serviceSubtask.setCreateBy(serviceTask.getCreateBy());
+ serviceSubtask.setCreateTime(new Date());
+ i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtask);
+ addServiceSubtaskPreachform(serviceSubtask, null);
+ }
+
+ //灏哻heck_flag鏀规垚1锛堝凡澶勭悊锛�
+ if (i == 1) {
+ PatMedOperationItem patMedOperationItem2 = new PatMedOperationItem();
+ patMedOperationItem2.setId(patMedOperationItem.getId());
+ patMedOperationItem2.setOpercheckFlag("1");
+ otherVisitFacade.updateOperationItem(patMedOperationItem2);
+ } else {
+ //鐢熸垚瀛愪换鍔″け璐ワ紝
+ log.info("鐢熸垚瀛愪换鍔″け璐erviceSubtask鐨則askid涓猴細{},patid涓猴細{}", serviceSubtask.getTaskid(), serviceSubtask.getPatid());
+ PatMedOperationItem patMedOperationItem2 = new PatMedOperationItem();
+ patMedOperationItem2.setId(patMedOperationItem.getId());
+ patMedOperationItem2.setOpercheckFlag("2");
+ patMedOperationItem2.setLongTaskReason("鐢熸垚瀛愪换鍔″け璐� 4;");
+ patMedOperationItem2.setUpdateTime(new Date());
+ otherVisitFacade.updateOperationItem(patMedOperationItem2);
+ }
+ } catch (Exception e) {
+ //鍑洪敊鍥炴粴浜嬪姟
+
+ log.error("鐢熸垚瀛愪换鍔℃姤閿欏洖婊歴serviceSubtask鐨則askid涓猴細{},patid涓猴細{},鎵嬫湳璇︽儏ID涓猴細{}",
+ serviceSubtask.getTaskid(), serviceSubtask.getPatid(), patMedOperationItem.getId(), e);
+ PatMedOperationItem patMedOperationItem2 = new PatMedOperationItem();
+ patMedOperationItem2.setId(patMedOperationItem.getId());
+ patMedOperationItem2.setOpercheckFlag("2");
+ patMedOperationItem2.setUpdateTime(new Date());
+ patMedOperationItem2.setLongTaskReason("鐢熸垚瀛愪换鍔℃姤閿欏洖婊� 4;");
+ otherVisitFacade.updateOperationItem(patMedOperationItem2);
+ e.printStackTrace();
+ }
+ }
+
+ private ServiceSubtask boxedServiceSubtaskForOp(ServiceTask serviceTask, PatMedInhosp patMedInhosp1, PatMedOperationItem patMedOperationItem, PatArchive patArchive, String config) {
+ ServiceSubtask serviceSubtask = DtoConversionUtils.sourceToTarget(serviceTask, ServiceSubtask.class);
+ serviceSubtask.setTaskid(serviceTask.getTaskid());
+ serviceSubtask.setOrgid(serviceTask.getOrgid());
+ serviceSubtask.setCampusid(serviceTask.getCampusid());
+ if (StringUtils.isNotEmpty(serviceTask.getLibtemplateid()))
+ serviceSubtask.setLibtemplateid(Long.valueOf(serviceTask.getLibtemplateid()));
+ serviceSubtask.setNurseId(patMedInhosp1.getNurseId());
+ serviceSubtask.setNurseName(patMedInhosp1.getNurseName());
+ serviceSubtask.setInhospid(patMedInhosp1.getInhospid());
+ serviceSubtask.setDrcode(patMedInhosp1.getDrcode());
+ serviceSubtask.setDrname(patMedInhosp1.getDrname());
+ serviceSubtask.setLeaveldeptcode(patMedInhosp1.getLeaveldeptcode());
+ serviceSubtask.setLeaveldeptname(patMedInhosp1.getLeaveldeptname());
+ serviceSubtask.setLeavehospitaldistrictcode(patMedInhosp1.getLeavehospitaldistrictcode());
+ serviceSubtask.setLeavehospitaldistrictname(patMedInhosp1.getLeavehospitaldistrictname());
+
+ serviceSubtask.setTemplateid(serviceTask.getTemplateid());
+ serviceSubtask.setTemplatename(serviceTask.getTemplatename());
+ serviceSubtask.setPatid(patArchive.getId());
+ serviceSubtask.setSendname(patArchive.getName());
+ serviceSubtask.setSfzh(patArchive.getIdcardno());
+ serviceSubtask.setPhone(patArchive.getTelcode());
+ if (StringUtils.isBlank(patArchive.getTelcode())) serviceSubtask.setPhone(patArchive.getRelativetelcode());
+ serviceSubtask.setSex(patArchive.getSex());
+ serviceSubtask.setAge(patArchive.getAge());
+ serviceSubtask.setSendstate(2L);
+ serviceSubtask.setManagementDoctor(patMedInhosp1.getDrname());
+ serviceSubtask.setManagementDoctorCode(patMedInhosp1.getDrcode());
+
+ serviceSubtask.setStarttime(patMedInhosp1.getStarttime());
+ serviceSubtask.setEndtime(patMedInhosp1.getEndtime());
+
+ serviceSubtask.setServiceType(serviceTask.getServiceType());
+ serviceSubtask.setPreachform(serviceTask.getPreachform());
+ serviceSubtask.setHospType("2");
+ serviceSubtask.setCreateTime(new Date());
+ serviceSubtask.setUpdateTime(new Date());
+ serviceSubtask.setCreateBy(patMedInhosp1.getNurseName());
+ serviceSubtask.setOperationItemId(patMedOperationItem.getId());
+ serviceSubtask.setUpdateBy(serviceTask.getUpdateBy());
+ serviceSubtask.setUpdateTime(new Date());
+
+ //璁剧疆鍙戦�佹椂闂�
+ if (serviceTask.getSendDay() == null) serviceTask.setSendDay(1L);
+ Date newDate = null;
+ if (!Objects.isNull(patMedInhosp1.getEndtime())) {
+ newDate = addDays(patMedInhosp1.getEndtime(), serviceTask.getSendDay().intValue());
+ } else {
+ patMedOperationItem.setOpercheckFlag("2");
+ patMedOperationItem.setLongTaskReason("璇ユ偅鑰呮墜鏈嚭闄㈡椂闂翠负绌�,鎵嬫湳璇︽儏ID涓�:" + patMedOperationItem.getId() + ";");
+ otherVisitFacade.updateOperationItem(patMedOperationItem);
+// patMedInhosp1.setDeptcheckFlag("2");
+// patMedInhosp1.setRemark(patMedInhosp1.getRemark() + "& 璇ユ偅鑰呮墜鏈嚭闄㈡椂闂翠负绌�,鍑洪櫌璁板綍ID涓�:" + patMedInhosp1.getInhospid());
+// inhospVisitFacade.updatePatMedInhosp(patMedInhosp1);
+ //濡傛灉鍑洪櫌鏃堕棿涓虹┖锛屽垯杩斿洖涓�涓柊瀵硅薄
+ return null;
+ }
+ serviceSubtask.setLongSendTime(newDate);
+ serviceSubtask.setVisitTime(newDate);
+
+ //濡傛灉鏄�氱煡鐨勮瘽锛岄渶瑕佹彁鍓嶅嚑澶╁皢閫氳繃鐭俊鍙戝嚭鍘伙紙鍏蜂綋鍑犲ぉ锛岃繖涓彲浠ラ厤缃湪sys_conf琛ㄤ腑锛�
+ if ("3".equals(serviceTask.getType())) {
+ serviceSubtask.setVisitTime(minusDay(newDate, StringUtils.isNotEmpty(config) ? Integer.parseInt(config) : 0));
+ }
+ //鎮h�呭彂閫佹椂闂�
+ if (StringUtils.isNotEmpty(patArchive.getNotrequiredFlag()) && patArchive.getNotrequiredFlag().equals("1")) {
+ String remark = patArchive.getNotrequiredreason();
+ serviceSubtask.setRemark(remark);
+ serviceSubtask.setResult("error");
+ serviceSubtask.setTaskSituation(6);
+ //涓嶆墽琛�
+ serviceSubtask.setSendstate(4L);
+ }
+ return serviceSubtask;
+ }
+
+ private Integer addServiceSubtaskPreachform(ServiceSubtask serviceSubtask, String sendstate) {
+ //灏唒reachformDesc鐨刯son瀵硅薄锛屾斁鍒發ist闆嗗悎涓�
+ ServiceTask serviceTask = serviceTaskMapper.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
+ if (Objects.isNull(serviceTask)) {
+ log.error("addServiceSubtaskPreachform taskid={} 鏌ヤ笉鍒颁换鍔★紝璺宠繃preachform瀛愯〃鐢熸垚", serviceSubtask.getTaskid());
+ return 0;
+ }
+ String preachformDesc = serviceTask.getPreachformDesc();
+
+ ObjectMapper objectMapper = new ObjectMapper();
+ if (org.apache.commons.lang3.StringUtils.isNotEmpty(preachformDesc)) {
+ List<ServiceSubtaskPreachform> serviceSubtaskPreachformList = null;
+ try {
+ serviceSubtaskPreachformList = objectMapper.readValue(preachformDesc, new TypeReference<List<ServiceSubtaskPreachform>>() {
+ });
+ } catch (JsonProcessingException e) {
+ log.error("preachform杞琇ist<ServiceSubtaskPreachform>鎶ラ敊浜嗭細{}", e.getMessage());
+ }
+ if (CollectionUtils.isEmpty(serviceSubtaskPreachformList)) {
+ log.error("preachformDesc瑙f瀽鍚庝负绌猴紝璺宠繃preachform瀛愯〃鐢熸垚锛宼askid涓猴細{}锛宲reachformDesc涓猴細{}",
+ serviceSubtask.getTaskid(), preachformDesc);
+ return 0;
+ }
+ for (ServiceSubtaskPreachform serviceSubtaskPreachform : serviceSubtaskPreachformList) {
+ serviceSubtaskPreachform.setTaskid(serviceSubtask.getTaskid());
+ serviceSubtaskPreachform.setSubid(serviceSubtask.getId());
+
+ //鍏堟煡璇竴涓嬶紝鏄惁瀛樺湪锛屽鏋滃凡缁忓瓨鍦紝灏变笉鏂板浜�
+ List<ServiceSubtaskPreachform> serviceSubtaskPreachformList1 = serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(serviceSubtaskPreachform);
+ if (CollectionUtils.isNotEmpty(serviceSubtaskPreachformList1)) continue;
+
+ //杩欎釜sendstate闇�瑕佸湪鏁版嵁搴撹缃竴涓粯璁ゅ�间负鈥�1鈥�
+ serviceSubtaskPreachform.setSendstate("1");
+ if (StringUtils.isNotEmpty(sendstate)) serviceSubtaskPreachform.setSendstate(sendstate);
+
+ serviceSubtaskPreachform.setOrgid(serviceSubtask.getOrgid());
+ serviceSubtaskPreachformMapper.insertServiceSubtaskPreachform(serviceSubtaskPreachform);
+ }
+
+ }
+
+ return 0;
+ }
+
+ public ServiceSubtask boxedServiceSubtask(ServiceTask serviceTask, PatMedInhosp patMedInhosp1, PatArchive patArchive, String config, Integer type) {
+ //澧炲姞serviceTask鍒ょ┖
+// if(Objects.isNull(serviceTask)){
+// return null;
+// }
+ ServiceSubtask serviceSubtask = DtoConversionUtils.sourceToTarget(serviceTask, ServiceSubtask.class);
+ serviceSubtask.setTaskid(serviceTask.getTaskid());
+ serviceSubtask.setOrgid(serviceTask.getOrgid());
+ serviceSubtask.setCampusid(serviceTask.getCampusid());
+ if (StringUtils.isNotEmpty(serviceTask.getLibtemplateid()))
+ serviceSubtask.setLibtemplateid(Long.valueOf(serviceTask.getLibtemplateid()));
+ serviceSubtask.setNurseId(patMedInhosp1.getNurseId());
+ serviceSubtask.setNurseName(patMedInhosp1.getNurseName());
+ serviceSubtask.setInhospid(patMedInhosp1.getInhospid());
+ serviceSubtask.setDrcode(patMedInhosp1.getDrcode());
+ serviceSubtask.setDrname(patMedInhosp1.getDrname());
+ serviceSubtask.setLeaveldeptcode(patMedInhosp1.getLeaveldeptcode());
+ serviceSubtask.setLeaveldeptname(patMedInhosp1.getLeaveldeptname());
+ serviceSubtask.setLeavehospitaldistrictcode(patMedInhosp1.getLeavehospitaldistrictcode());
+ serviceSubtask.setLeavehospitaldistrictname(patMedInhosp1.getLeavehospitaldistrictname());
+ if (type == 4 || type == 5) {
+ //璁剧疆鍏ラ櫌鐨�
+ serviceSubtask.setLeaveldeptcode(patMedInhosp1.getDeptcode());
+ serviceSubtask.setLeaveldeptname(patMedInhosp1.getDeptname());
+ serviceSubtask.setLeavehospitaldistrictcode(patMedInhosp1.getHospitaldistrictcode());
+ serviceSubtask.setLeavehospitaldistrictname(patMedInhosp1.getHospitaldistrictname());
+ }
+ serviceSubtask.setLeaveicd10code(patMedInhosp1.getLeaveicd10code());
+ serviceSubtask.setLeavediagname(patMedInhosp1.getLeavediagname());
+ serviceSubtask.setDiagname(patMedInhosp1.getDiagname());
+ serviceSubtask.setTemplateid(serviceTask.getTemplateid());
+ serviceSubtask.setTemplatename(serviceTask.getTemplatename());
+ serviceSubtask.setPatid(patArchive.getId());
+ serviceSubtask.setSendname(patArchive.getName());
+ serviceSubtask.setSfzh(patArchive.getIdcardno());
+ serviceSubtask.setPhone(patArchive.getTelcode());
+ if (StringUtils.isBlank(patArchive.getTelcode())) serviceSubtask.setPhone(patArchive.getRelativetelcode());
+ serviceSubtask.setSex(patArchive.getSex());
+ serviceSubtask.setAge(patArchive.getAge());
+ serviceSubtask.setSendstate(2L);
+ serviceSubtask.setCampusid(patMedInhosp1.getCampusid());
+ serviceSubtask.setManagementDoctor(patMedInhosp1.getManagementDoctor());
+ serviceSubtask.setManagementDoctorCode(patMedInhosp1.getManagementDoctorCode());
+ serviceSubtask.setStarttime(patMedInhosp1.getStarttime());
+ serviceSubtask.setEndtime(patMedInhosp1.getEndtime());
+ serviceSubtask.setServiceType(serviceTask.getServiceType());
+ serviceSubtask.setPreachform(serviceTask.getPreachform());
+ serviceSubtask.setHospType("2");
+ if (type == 4 || type == 5) serviceSubtask.setHospType("6");
+ serviceSubtask.setCreateTime(new Date());
+ serviceSubtask.setUpdateTime(new Date());
+ serviceSubtask.setCreateBy(patMedInhosp1.getNurseName());
+ serviceSubtask.setLeavehospitaldistrictcode(patMedInhosp1.getLeavehospitaldistrictcode());
+ serviceSubtask.setLeavehospitaldistrictname(patMedInhosp1.getLeavehospitaldistrictname());
+ serviceSubtask.setUpdateBy(serviceTask.getUpdateBy());
+ serviceSubtask.setUpdateTime(new Date());
+ //濡傛灉鏄鏁欏氨璁剧疆涓�7
+ if (serviceTask.getServiceType().equals("17")) serviceSubtask.setTaskSituation(7);
+ //璁剧疆鍙戦�佹椂闂�
+ if (serviceTask.getSendDay() == null) serviceTask.setSendDay(1L);
+ Date newDate = null;
+ if (!Objects.isNull(patMedInhosp1.getEndtime())) {
+ newDate = addDays(patMedInhosp1.getEndtime(), serviceTask.getSendDay().intValue());
+ } else {
+ //濡傛灉绛変簬4,璇存槑鏄叆闄㈠鏁欙紝鍏ラ櫌涓嶅彲鑳芥湁endTime
+ if (type != 4 && type != 5) {
+ patMedInhosp1.setDeptcheckFlag("2");
+ patMedInhosp1.setRemark(patMedInhosp1.getRemark() + "& 璇ユ偅鑰呯柧鐥呭嚭闄㈡椂闂翠负绌�,鍑洪櫌璁板綍ID涓�:" + patMedInhosp1.getInhospid());
+ inhospVisitFacade.updatePatMedInhosp(patMedInhosp1);
+ //濡傛灉鍑洪櫌鏃堕棿涓虹┖锛屽垯杩斿洖涓�涓柊瀵硅薄
+ return new ServiceSubtask();
+ }
+ //鍏ラ櫌瀹f暀锛屽熀鏈綋澶╂垨闅斿ぉ灏辫鍙戝嚭
+ newDate = addDays(new Date(), serviceTask.getSendDay().intValue());
+ }
+ serviceSubtask.setLongSendTime(newDate);
+ serviceSubtask.setVisitTime(newDate);
+
+// if (patMedInhosp1.getFudate() != null && !patMedInhosp1.getOrgid().equals("47255004333112711A1001")) serviceSubtask.setVisitTime(patMedInhosp1.getFudate());
+ //濡傛灉鏄�氱煡鐨勮瘽锛岄渶瑕佹彁鍓嶅嚑澶╁皢閫氳繃鐭俊鍙戝嚭鍘伙紙鍏蜂綋鍑犲ぉ锛岃繖涓彲浠ラ厤缃湪sys_conf琛ㄤ腑锛�
+ if ("3".equals(serviceTask.getType())) {
+ serviceSubtask.setVisitTime(minusDay(newDate, StringUtils.isNotEmpty(config) ? Integer.parseInt(config) : 0));
+ //濡傛灉璇ュ嚭闄㈣褰曟湁闅忚鏃堕棿锛屽垯鐢ㄤ粬鑷繁鐨勯殢璁挎椂闂�
+ if (patMedInhosp1.getFudate() != null) {
+ serviceSubtask.setVisitTime(minusDay(patMedInhosp1.getFudate(), StringUtils.isNotEmpty(config) ? Integer.parseInt(config) : 0));
+ } else {
+ //鍒ゆ柇鏄笉鏄櫙瀹�
+ if (patMedInhosp1.getOrgid().equals("47255004333112711A1001")) {
+ serviceSubtask.setVisitTime(null);
+ //涓嶆墽琛�
+ serviceSubtask.setSendstate(4L);
+ serviceSubtask.setRemark("鏅畞娌℃湁缁欓殢璁挎椂闂达紝涓嶅彂閫侀�氱煡鐭俊");
+ }
+ }
+
+ }
+ //濡傛灉鎮h�呯殑鍏ラ櫌鍜屽嚭闄㈡椂闂翠竴鑷达紝鍙互涓嶇敤闅忚锛堝崡鍗庨檮涓�鑲跨槫涓�鐥呭尯鎻愬嚭锛�
+ if (active.equals("nhfy") && patMedInhosp1.getStarttime() != null && patMedInhosp1.getEndtime() != null && DateUtils.differentDaysByMillisecond(patMedInhosp1.getStarttime(), patMedInhosp1.getEndtime()) == 0) {
+ serviceSubtask.setRemark("鎮h�呭綋澶╁嚭闄紝涓嶇敤闅忚");
+ serviceSubtask.setResult("error");
+ //涓嶆墽琛�
+ serviceSubtask.setSendstate(4L);
+ }
+
+ //鎮h�呭彂閫佹椂闂�
+ if (StringUtils.isNotEmpty(patArchive.getNotrequiredFlag()) && patArchive.getNotrequiredFlag().equals("1")) {
+ String remark = patArchive.getNotrequiredreason();
+ serviceSubtask.setRemark(remark);
+ serviceSubtask.setResult("error");
+ serviceSubtask.setTaskSituation(6);
+ //涓嶆墽琛�
+ serviceSubtask.setSendstate(4L);
+ }
+ return serviceSubtask;
+ }
+
+ private Date addDays(Date date, Integer days) {
+ if (days == null) {
+ days = 1;
+ }
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+ calendar.add(Calendar.DAY_OF_MONTH, days);
+ return calendar.getTime();
+ }
+
+ public Date minusDay(Date originalDate, Integer day) {
+ // 1. 灏� Date 杞崲涓� Instant
+ Instant instant = originalDate.toInstant();
+
+ // 2. 鍦� Instant 涓婂噺鍘�2澶�
+ Instant twoDaysAgoInstant = instant.minus(2, ChronoUnit.DAYS);
+
+ // 3. 灏嗚绠楀悗鐨� Instant 杞洖 Date
+ return Date.from(twoDaysAgoInstant);
+ }
+
+}
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/OtherVisitApiImpl.java b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/OtherVisitApiImpl.java
new file mode 100644
index 0000000..3699252
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/OtherVisitApiImpl.java
@@ -0,0 +1,58 @@
+package com.ruoyi.task.api.contract;
+
+import com.ruoyi.common.core.service.OtherVisitApi;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * {@link OtherVisitApi}锛堟墜鏈殢璁垮绾︼級鍦� <b>ruoyi-task</b> 渚х殑鍞竴瀹炵幇銆�
+ *
+ * <h3>涓轰粈涔堣惤鍦ㄨ繖閲�</h3>
+ * 鎵嬫湳闅忚鐨勪袱涓叆鍙f湰浣撳湪 {@link OperationSubtaskWriter}锛堟湰鍖咃級锛�
+ * 鑰屽畠蹇呴』璇诲啓 {@code service_task*} / {@code service_subtask*}锛堝睘鏈ā鍧楋級
+ * 骞惰 {@code pat_archive}锛堢粡 {@code TaskArchivePort} 绔彛锛夆�斺��
+ * 瑙� writer 鐨勭被娉ㄩ噴閲岄偅涓夋鎼縼灏濊瘯銆傚疄鐜拌窡鐫�鑳藉姏璧帮紝鎵�浠ユ湰绫讳篃鍦ㄦ湰妯″潡銆�
+ *
+ * <h3>瀹冨彇浠d簡浠�涔�</h3>
+ * 姝ゅ墠鏈�<b>涓や釜</b>瀹炵幇锛歴martor 鐨� {@code OtherVisitApiBridge}锛堢湡瀹炵幇锛�
+ * 鍜� {@code ruoyi-othervisit} 鐨� {@code OtherVisitApiImpl}锛堢敤
+ * {@code ObjectProvider<OtherVisitApi>} 鍥炲ご鎵� smartor 閭d釜锛岃繕瑕� filter 鎺夎嚜宸遍槻閫掑綊锛夈��
+ * 鏈疆涓よ�呴兘鍒犱簡锛岀幇鍦ㄥ叏浠� {@code OtherVisitApi} 鍙湁涓�涓� bean銆�
+ *
+ * <h3>鈿狅笍 涓よ濮旀墭锛屼笉鍔犻�昏緫</h3>
+ * {@code addOperationSubTask} 杞彂鍒� {@code writer.runOperationVisit(..)}锛氬師妗ユ帴灏辨槸杩欎箞杞殑
+ * 锛坽@code runOperationVisit} 鍐呴儴璋� {@code addOperationSubTask} 鍚庡浐瀹氳繑鍥� 1锛夛紝
+ * 鎹㈡垚 {@code writer.addOperationSubTask} 浼氫涪鎺夐偅涓� {@code 1} 鐨勮繑鍥炲�笺��
+ *
+ * @see OperationSubtaskWriter
+ */
+@Slf4j
+@Component
+public class OtherVisitApiImpl implements OtherVisitApi {
+
+ @Autowired
+ private OperationSubtaskWriter operationSubtaskWriter;
+
+ /**
+ * 鎵嬫湳闅忚鎵弿锛堟墜鏈瓑绾� + 绂婚櫌绉戝/鐥呭尯缁村害锛夈��
+ *
+ * @param config {@code sys_config: visit.early.day} 鐨勫�硷紝鍙兘涓� null
+ * @return 鍥哄畾 {@code 1}锛堝師瀹炵幇濡傛锛屼笉鏄鐞嗘潯鏁帮級
+ */
+ @Override
+ public int addOperationSubTask(String config) {
+ return operationSubtaskWriter.runOperationVisit(config);
+ }
+
+ /**
+ * 浠诲姟缁勶紙appltype=5锛夐杞撼鍏ャ��
+ *
+ * @param config {@code sys_config: visit.early.day}
+ * @return 鍘熷疄鐜板浐瀹氳繑鍥� 1
+ */
+ @Override
+ public int dealOutHospInfoBySchedule(String config) {
+ return operationSubtaskWriter.dealOutHospInfoBySchedule(config);
+ }
+}
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/PreachformApiImpl.java b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/PreachformApiImpl.java
new file mode 100644
index 0000000..e7e5063
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/PreachformApiImpl.java
@@ -0,0 +1,158 @@
+package com.ruoyi.task.api.contract;
+
+import com.ruoyi.common.core.service.PreachformApi;
+import com.ruoyi.common.core.service.dto.VisitPreachformRow;
+import com.ruoyi.task.domain.ServiceSubtask;
+import com.ruoyi.task.domain.ServiceSubtaskPreachform;
+import com.ruoyi.task.mapper.ServiceSubtaskPreachformMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * {@link PreachformApi} 鍦� <b>鏈ā鍧楋紙ruoyi-task锛�</b>鐨勫疄鐜� 鈥斺��
+ * {@code service_subtask_preachform} 鐨�<b>鍞竴</b>鏁版嵁璁块棶鍑哄彛銆�
+ *
+ * <h3>2026-11 褰掑睘璋冩暣</h3>
+ * 璇ヨ〃鍘熷厛褰� {@code ruoyi-inhospvisit}锛屽疄鐜版槸瀹冪殑 {@code DefaultPreachformApi}锛�
+ * 鎸�"琛ㄨ窡闅忎笟鍔″煙"鐨勫彛寰勶紝琛ㄧ殑 SQL / Mapper / 瀹炰綋閮藉垝鍒版湰妯″潡锛屼簬鏄湰绫绘帴绠″绾﹀疄鐜般��
+ * 浠嶇劧淇濈暀杩欎釜濂戠害鐨勫師鍥犲彧鏈変竴涓細{@code ruoyi-inhospvisit} 闇�瑕佸啓杩欏紶琛紙瀹f暀鏄庣粏锛夛紝
+ * 鑰屼緷璧栨柟鍚戞槸 {@code ruoyi-task 鈫� ruoyi-inhospvisit}锛屽弽鍚戜笉鎴愮珛锛堝惁鍒欐垚鐜級锛�
+ * 鎵�浠ュ畠鍙兘缁� {@code ruoyi-common} 閲岀殑濂戠害鍦ㄨ繍琛屾湡鍙栧埌鏈疄鐜般��
+ *
+ * <h3>鈿狅笍 绾暟鎹闂�</h3>
+ * 鏈被鍙仛銆屽绾﹁ 鈫� 瀹炰綋銆嶇殑閫愬瓧娈垫惉杩� + 璋� Mapper锛屼笉鍚换浣曚笟鍔″垽鏂細
+ * 浠�涔堟椂鍊欒鎻掍竴鏉°�佽缃粈涔堢姸鎬侊紝閮藉睘浜庤皟鐢ㄦ柟銆�
+ * 15 涓瓧娈甸�愪釜鐓ф妱锛堝皯鎼竴涓� = 璇ュ垪闈欓粯涓嶅啓/涓嶈锛夈��
+ */
+@Slf4j
+@Component
+public class PreachformApiImpl implements PreachformApi {
+
+ @Autowired
+ private ServiceSubtaskPreachformMapper serviceSubtaskPreachformMapper;
+
+ @Override
+ public VisitPreachformRow findById(Long id) {
+ return toRow(serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformById(id));
+ }
+
+ @Override
+ public List<VisitPreachformRow> findList(VisitPreachformRow query) {
+ List<ServiceSubtaskPreachform> rows =
+ serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(toEntity(query));
+ return toRows(rows);
+ }
+
+ @Override
+ public List<VisitPreachformRow> findByTaskidAndOrgid(Long taskid, String orgid) {
+ ServiceSubtask query = new ServiceSubtask();
+ query.setTaskid(taskid);
+ query.setOrgid(orgid);
+ return toRows(serviceSubtaskPreachformMapper.selectBySubtask(query));
+ }
+
+ @Override
+ public boolean insert(VisitPreachformRow row) {
+ ServiceSubtaskPreachform entity = toEntity(row);
+ int n = serviceSubtaskPreachformMapper.insertServiceSubtaskPreachform(entity);
+ // 鍘� XML 鐢� useGeneratedKeys 鎶婅嚜澧炰富閿洖濉埌鍏ュ弬瀵硅薄锛涜繖閲屽悓鏍峰洖濉紝
+ // 淇濊瘉"鍏� insert 鍐嶆嬁 id"鐨勮皟鐢ㄦ柟琛屼负涓嶅彉銆�
+ if (row != null && entity != null) {
+ row.setId(entity.getId());
+ }
+ return n == 1;
+ }
+
+ @Override
+ public boolean updateById(VisitPreachformRow row) {
+ return serviceSubtaskPreachformMapper
+ .updateServiceSubtaskPreachform(toEntity(row)) == 1;
+ }
+
+ @Override
+ public boolean updateByCondition(VisitPreachformRow row) {
+ return serviceSubtaskPreachformMapper.updateSSPByCondition(toEntity(row)) >= 1;
+ }
+
+ @Override
+ public boolean softDeleteById(Long id) {
+ return serviceSubtaskPreachformMapper.deleteServiceSubtaskPreachformById(id) >= 1;
+ }
+
+ @Override
+ public boolean softDeleteByIds(Long[] ids) {
+ return serviceSubtaskPreachformMapper.deleteServiceSubtaskPreachformByIds(ids) >= 1;
+ }
+
+ @Override
+ public boolean softDeleteBySubid(Long subid) {
+ return serviceSubtaskPreachformMapper.deleteServiceSubtaskPreachformBySubid(subid) >= 1;
+ }
+
+ // ==========================================================================
+ // 瀛楁鎼繍锛堝绾﹁ 鈫� 鏈ā鍧楀疄浣擄級銆備袱渚у瓧娈靛悕涓庣被鍨嬪畬鍏ㄤ竴鑷达紙15 涓級锛�
+ // 閫愬瓧娈电収鎶勶紝涓嶅仛"椤烘墜绮剧畝"銆�
+ // ==========================================================================
+
+ private ServiceSubtaskPreachform toEntity(VisitPreachformRow r) {
+ if (r == null) {
+ return null;
+ }
+ ServiceSubtaskPreachform e = new ServiceSubtaskPreachform();
+ e.setId(r.getId());
+ e.setSubid(r.getSubid());
+ e.setTaskid(r.getTaskid());
+ e.setPreachform(r.getPreachform());
+ e.setSendstate(r.getSendstate());
+ e.setCurrentSendTime(r.getCurrentSendTime());
+ e.setOrgid(r.getOrgid());
+ e.setDelFlag(r.getDelFlag());
+ e.setSort(r.getSort());
+ e.setCompensateTime(r.getCompensateTime());
+ e.setRemark(r.getRemark());
+ e.setCreateBy(r.getCreateBy());
+ e.setCreateTime(r.getCreateTime());
+ e.setUpdateBy(r.getUpdateBy());
+ e.setUpdateTime(r.getUpdateTime());
+ return e;
+ }
+
+ private VisitPreachformRow toRow(ServiceSubtaskPreachform e) {
+ if (e == null) {
+ return null;
+ }
+ VisitPreachformRow r = new VisitPreachformRow();
+ r.setId(e.getId());
+ r.setSubid(e.getSubid());
+ r.setTaskid(e.getTaskid());
+ r.setPreachform(e.getPreachform());
+ r.setSendstate(e.getSendstate());
+ r.setCurrentSendTime(e.getCurrentSendTime());
+ r.setOrgid(e.getOrgid());
+ r.setDelFlag(e.getDelFlag());
+ r.setSort(e.getSort());
+ r.setCompensateTime(e.getCompensateTime());
+ r.setRemark(e.getRemark());
+ r.setCreateBy(e.getCreateBy());
+ r.setCreateTime(e.getCreateTime());
+ r.setUpdateBy(e.getUpdateBy());
+ r.setUpdateTime(e.getUpdateTime());
+ return r;
+ }
+
+ private List<VisitPreachformRow> toRows(List<ServiceSubtaskPreachform> rows) {
+ if (rows == null || rows.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<VisitPreachformRow> out = new ArrayList<>(rows.size());
+ for (ServiceSubtaskPreachform e : rows) {
+ out.add(toRow(e));
+ }
+ return out;
+ }
+}
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/ScheduleRollPortImpl.java b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/ScheduleRollPortImpl.java
new file mode 100644
index 0000000..d8bac93
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/api/contract/ScheduleRollPortImpl.java
@@ -0,0 +1,315 @@
+package com.ruoyi.task.api.contract;
+
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.common.core.service.ScheduleRollPort;
+import com.ruoyi.common.core.service.dto.VisitScheduleRollResultDto;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.task.mapper.ServiceSubtaskPreachformMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import com.ruoyi.task.domain.ServiceSubtask;
+import com.ruoyi.task.domain.ServiceTaskSchedule;
+import com.ruoyi.task.domain.ServiceTaskScheduleDetail;
+import com.ruoyi.task.mapper.ServiceSubtaskMapper;
+import com.ruoyi.task.mapper.ServiceTaskScheduleDetailMapper;
+import com.ruoyi.task.mapper.ServiceTaskScheduleMapper;
+import com.ruoyi.task.domain.ServiceSubtaskPreachform;
+
+/**
+ * 銆愯繃娓″疄鐜般�憑@link ScheduleRollPort}锛堜换鍔$粍杞婊氬姩锛夊湪 smartor 渚х殑妗ユ帴銆�
+ *
+ * <h3>涓轰粈涔堣繖涓疄鐜版槸"绮楃矑搴�"鐨勶紙绗� 9 姝ョ殑璁捐鍐冲畾锛�</h3>
+ * 鏍稿績鍔ㄤ綔瑕佸仛涓�娆� <b>{@code ServiceSubtask} 鐨勫叏瀛楁娣辨嫹璐�</b>
+ * 锛坽@code JSON.parseObject(JSON.toJSONString(src), ServiceSubtask.class)}锛夛紝
+ * 鑰� {@code ServiceSubtask} 鏈� <b>116 涓瓧娈�</b>銆�
+ * 鍦ㄦā鍧椾箣闂翠紶 116 瀛楁鐨� DTO 鍙細鍒堕�犻闄┿�佹崲涓嶆潵鏀剁泭
+ * 锛堝叏瀛楁鎷疯礉鐨勮涔夋湰鏉ュ氨鐢� JSON 搴忓垪鍖栦繚璇侊級銆�
+ * <p>
+ * 鎵�浠ユ暣涓� roll 鍔ㄤ綔鐣欏湪鏈被閲屽師瀛愬畬鎴愶紱{@code ruoyi-inhospvisit} 鍙礋璐�
+ * "鎵规涓婇檺 + 閫愭潯 try/catch + 璁℃暟涓庢棩蹇�"杩欓儴鍒嗙紪鎺掋��
+ *
+ * <h3>閫愭柟娉曟潵婧愶紙@ b25c3b51锛�</h3>
+ * <table border="1">
+ * <tr><th>鏈被鏂规硶</th><th>鍘熷疄鐜�</th><th>琛屾暟</th></tr>
+ * <tr><td>{@link #selectActiveCycleSchedules(int)}</td>
+ * <td>{@code ServiceTaskScheduleServiceImpl#rollCycleTasks} L171 鐨勬煡璇㈤儴鍒�</td><td>鈥�</td></tr>
+ * <tr><td>{@link #rollOneSchedule(Long)}</td>
+ * <td>{@code rollOneSchedule} L196-280</td><td>85</td></tr>
+ * <tr><td>{@code cloneForNextLoop}</td><td>L285-313</td><td>29</td></tr>
+ * <tr><td>{@code copyPreachform}</td><td>L318-338</td><td>21</td></tr>
+ * <tr><td>{@code advance}</td><td>L343-361</td><td>19</td></tr>
+ * </table>
+ *
+ * <h3>鈿狅笍 鏈被涓� smartor 閲岄偅浠� {@code rollCycleTasks} 鏄�<b>骞跺瓨</b>鐨�</h3>
+ * {@code ServiceTaskScheduleServiceImpl#rollCycleTasks}锛圠170-190锛�<b>鏈鍒绘剰涓嶅姩</b> 鈥斺��
+ * 瀹冧粛琚� {@code RyTask.rollTaskGroupCycle} 璋冪敤锛岃�岄偅鏄幇缃� {@code sys_job} 鐨勫叆鍙c��
+ * 涓ゆ潯璺緞<b>涓嶈兘鍚屾椂琚皟搴�</b>锛堥兘浼氭帹杩涜疆娆� + 鏂板缓 subtask 鈫� 閲嶅杞锛夈��
+ * 绗� 10 姝ヤ細鎶� {@code RyTask} 鐨勬柟娉曚綋鍒囧埌鏈鍙o紝灞婃椂閭d唤鎵嶉��褰广��
+ *
+ * <h3>鈿狅笍 娣辨嫹璐濆繀椤诲師鏍风敤 JSON 搴忓垪鍖�</h3>
+ * 涓嶈鎶� {@code JSON.parseObject(JSON.toJSONString(src), ...)} 鏀瑰啓鎴愰�愬瓧娈� set 鈥斺��
+ * 116 涓瓧娈电殑閫愪釜鎼繍鏄涓哄彉鏇寸殑楂樺彂鍦帮紝涓旀病鏈変换浣曞ソ澶勩��
+ */
+@Slf4j
+@Component
+public class ScheduleRollPortImpl implements ScheduleRollPort {
+
+ @Autowired
+ private ServiceTaskScheduleMapper serviceTaskScheduleMapper;
+
+ @Autowired
+ private ServiceTaskScheduleDetailMapper serviceTaskScheduleDetailMapper;
+
+ @Autowired
+ private ServiceSubtaskMapper serviceSubtaskMapper;
+
+ @Autowired
+ private ServiceSubtaskPreachformMapper serviceSubtaskPreachformMapper;
+
+ /**
+ * 鏌ヤ竴鎵瑰緟璇勪及鐨勫惊鐜鍒掞紙鍘� {@code rollCycleTasks} L171锛夈��
+ * <p>
+ * 鍙洖浼� id 鍒楄〃锛氱湡姝g殑 roll 鍔ㄤ綔鍦� {@link #rollOneSchedule(Long)} 閲岄噸鏂板姞杞藉畬鏁磋鍒�
+ * 锛堝師瀹炵幇涔熸槸鎶婃暣涓� {@code ServiceTaskSchedule} 浼犺繘 rollOneSchedule锛�
+ * 鎵�浠ヨ涔変竴鑷达級銆�
+ */
+ @Override
+ public List<Long> selectActiveCycleSchedules(int limit) {
+ List<ServiceTaskSchedule> schedules =
+ serviceTaskScheduleMapper.selectActiveCycleSchedules(limit);
+ if (CollectionUtils.isEmpty(schedules)) {
+ return new ArrayList<>();
+ }
+ List<Long> ids = new ArrayList<>(schedules.size());
+ for (ServiceTaskSchedule s : schedules) {
+ ids.add(s.getId());
+ }
+ return ids;
+ }
+
+ /**
+ * 婊氬姩鍗曚釜璁″垝 鈥斺�� 閫愯鎼嚜鍘� {@code rollOneSchedule}锛圠196-280锛夈��
+ * <p>
+ * 鈿狅笍 鍘熷疄鐜版帴鏀剁殑鏄�<b>鏁翠釜 {@code ServiceTaskSchedule} 瀵硅薄</b>锛堢敱 {@code rollCycleTasks}
+ * 浠庢煡璇㈢粨鏋滈噷浼犺繘鏉ワ級銆傜鍙g鍚嶅彧缁� id锛屾墍浠ヨ繖閲岃**閲嶆柊鏌ヤ竴娆�**銆�
+ * 涓烘闇�瑕佹寜 id 鏌ヨ鍒掞細鐢� {@code selectByTaskid} 涓嶈锛堥偅鏄寜 taskid锛夛紝
+ * 鎵�浠ヨ繖閲岀敤 {@code selectActiveCycleSchedules} 鐨勫悓娆捐兘鍔� 鈥斺��
+ * 瑙佷笅鏂� {@link #loadSchedule(Long)} 鐨勮鏄庛��
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public VisitScheduleRollResultDto rollOneSchedule(Long scheduleId) {
+ ServiceTaskSchedule schedule = loadSchedule(scheduleId);
+ if (schedule == null) {
+ log.warn("[浠诲姟缁�-婊氬姩] scheduleId={} 鍔犺浇涓嶅埌璁″垝锛岃烦杩�", scheduleId);
+ return VisitScheduleRollResultDto.skipped(scheduleId, "璁″垝涓嶅瓨鍦�");
+ }
+ return doRoll(schedule);
+ }
+
+ /**
+ * 鎸� id 鍔犺浇璁″垝銆�
+ * <p>
+ * 鈿狅笍 <b>杩欓噷涓�"鍘熷疄鐜�"鏈変竴涓繀椤昏鏄庣殑宸紓</b>锛�
+ * 鍘� {@code rollCycleTasks} 鏄妸鏌ヨ缁撴灉閲岀殑瀵硅薄<b>鐩存帴浼犺繘鏉�</b>锛堜笉閲嶆煡锛夛紱
+ * 绔彛鍙粰 id锛屾墍浠ュ繀椤婚噸鏌ャ�傞噸鏌ヤ笌"鐢ㄦ煡璇㈢粨鏋�"鐨勫樊鍒彧鍦ㄤ簬
+ * <b>涓ゆ璇诲彇涔嬮棿璁″垝鏄惁琚敼杩�</b>鈥斺�斿悓涓�鎵逛换鍔¢噷杩欐槸姣绾х獥鍙o紝
+ * 涓� rollOneSchedule 鏈韩浼氬仛涔愯鐨�"鏈疆鏄惁缁撴潫"鏍¢獙锛屾墍浠ヤ笉鏀瑰彉鍙瀵熻涓恒��
+ * <p>
+ * 瀹炵幇涓婄敤 {@code selectServiceTaskScheduleList} 鎸� id 杩囨护锛堣 Mapper 宸叉湁姝よ兘鍔涳級銆�
+ */
+ private ServiceTaskSchedule loadSchedule(Long scheduleId) {
+ ServiceTaskSchedule q = new ServiceTaskSchedule();
+ q.setId(scheduleId);
+ List<ServiceTaskSchedule> rows = serviceTaskScheduleMapper.selectServiceTaskScheduleList(q);
+ if (CollectionUtils.isEmpty(rows)) {
+ return null;
+ }
+ return rows.get(0);
+ }
+
+ /**
+ * 鍘� {@code rollOneSchedule} 鏈綋锛圠196-280锛夈��
+ */
+ private VisitScheduleRollResultDto doRoll(ServiceTaskSchedule schedule) {
+ Long scheduleId = schedule.getId();
+ Long currentLoop = schedule.getCurrentLoopCount() == null ? 0L : schedule.getCurrentLoopCount();
+
+ // 鍘� L200-209锛氫笂闄愭牎楠�
+ Long max = schedule.getMaxLoopCount();
+ if (max != null && max > 0 && currentLoop + 1 >= max) {
+ // 娉ㄦ剰锛氬厛鍒ゆ柇"鍐嶅紑涓�杞槸鍚︿細瓒呴檺"鈥斺�攃urrentLoop 鏄凡瀹屾垚杞锛屼笅涓�杞彿 = currentLoop+1
+ // 褰� currentLoop+1 == max 鏃舵濂藉浜庢渶鍚庝竴杞紝涓嶅啀浜х敓鏂颁竴杞�
+ if (currentLoop >= max) {
+ log.info("[浠诲姟缁�-婊氬姩] scheduleId={} 宸茶揪 maxLoopCount={}, 璺宠繃", scheduleId, max);
+ return VisitScheduleRollResultDto.skipped(scheduleId, "宸茶揪 maxLoopCount");
+ }
+ }
+
+ // 鍘� L211-216锛氭湰杞槸鍚﹀畬鎴�
+ int active = serviceSubtaskMapper.countActiveByScheduleIdAndLoop(scheduleId, currentLoop);
+ if (active > 0) {
+ log.debug("[浠诲姟缁�-婊氬姩] scheduleId={} loop={} 浠嶆湁 {} 鏉� subtask 鏈粨鏉�, 璺宠繃",
+ scheduleId, currentLoop, active);
+ return VisitScheduleRollResultDto.skipped(scheduleId, "鏈疆浠嶆湁鏈粨鏉熺殑 subtask");
+ }
+
+ // 鍘� L218-224锛氭媺鏈疆 subtask 鍋氬厠闅嗘ā鏉�
+ List<ServiceSubtask> currentLoopSubtasks =
+ serviceSubtaskMapper.selectByScheduleIdAndLoop(scheduleId, currentLoop);
+ if (CollectionUtils.isEmpty(currentLoopSubtasks)) {
+ log.warn("[浠诲姟缁�-婊氬姩] scheduleId={} loop={} 鎵句笉鍒版湰杞� subtask, 璺宠繃", scheduleId, currentLoop);
+ return VisitScheduleRollResultDto.skipped(scheduleId, "鎵句笉鍒版湰杞� subtask");
+ }
+
+ // 鍘� L226-232锛氭媺鏈鍒掓槑缁�
+ List<ServiceTaskScheduleDetail> detailList =
+ serviceTaskScheduleDetailMapper.selectByScheduleid(scheduleId);
+ if (CollectionUtils.isEmpty(detailList)) {
+ log.warn("[浠诲姟缁�-婊氬姩] scheduleId={} 鏄庣粏涓虹┖, 璺宠繃", scheduleId);
+ return VisitScheduleRollResultDto.skipped(scheduleId, "鏄庣粏涓虹┖");
+ }
+
+ // 鍘� L234-240锛氭帹杩涙闀匡紙杞棿闅旓級
+ int stepNum = schedule.getScheduleTimeNum() == null ? 0 : schedule.getScheduleTimeNum();
+ int stepUnit = schedule.getScheduleTimeUnit() == null ? 1 : schedule.getScheduleTimeUnit();
+ if (stepNum <= 0) {
+ log.warn("[浠诲姟缁�-婊氬姩] scheduleId={} scheduleTimeNum={} 闈炴硶, 璺宠繃", scheduleId, stepNum);
+ return VisitScheduleRollResultDto.skipped(scheduleId, "scheduleTimeNum 闈炴硶");
+ }
+
+ long nextLoop = currentLoop + 1;
+
+ // 鍘� L246-251锛氭妸 detailList 鎸� seq 绱㈠紩
+ Date now = DateUtils.getNowDate();
+ Map<Integer, ServiceTaskScheduleDetail> detailBySeq = new HashMap<>(detailList.size());
+ for (ServiceTaskScheduleDetail d : detailList) {
+ detailBySeq.put(d.getSeq(), d);
+ }
+
+ // 鍘� L253-266锛氶�愭潯鍏嬮殕
+ int produced = 0;
+ for (ServiceSubtask src : currentLoopSubtasks) {
+ ServiceTaskScheduleDetail detail = detailBySeq.get(src.getScheduleSeq());
+ if (detail == null) {
+ log.warn("[浠诲姟缁�-婊氬姩] scheduleId={} 鎵句笉鍒� seq={} 瀵瑰簲鐨勬槑缁�, 璺宠繃 subtask id={}",
+ scheduleId, src.getScheduleSeq(), src.getId());
+ continue;
+ }
+ ServiceSubtask copy = cloneForNextLoop(src, detail, nextLoop, stepNum, stepUnit, now);
+ serviceSubtaskMapper.insertServiceSubtask(copy);
+ // 鍘� L264锛氬鍒� preachform
+ copyPreachform(src.getId(), copy);
+ produced++;
+ }
+
+ // 鍘� L268-276锛氭帹杩� schedule
+ ServiceTaskSchedule upd = new ServiceTaskSchedule();
+ upd.setId(scheduleId);
+ upd.setCurrentLoopCount(nextLoop);
+ upd.setCurrentSeq(1);
+ upd.setNextSeq(detailList.size() > 1 ? 2 : 1);
+ upd.setNextExecuteTime(advance(now, stepNum, stepUnit));
+ upd.setUpdateTime(now);
+ serviceTaskScheduleMapper.updateServiceTaskSchedule(upd);
+
+ log.info("[浠诲姟缁�-婊氬姩] scheduleId={} 鎺ㄨ繘鍒扮 {} 杞�, 鏂板缓 {} 鏉� subtask", scheduleId, nextLoop, produced);
+ return VisitScheduleRollResultDto.rolled(scheduleId, nextLoop, produced);
+ }
+
+ /**
+ * 鍏嬮殕 subtask 鍒颁笅涓�杞� 鈥斺�� 閫愯鎼嚜鍘� L285-313銆�
+ * <p>
+ * 鈿狅笍 绗竴琛岀殑鍏ㄥ瓧娈垫繁鎷疯礉锛�116 涓瓧娈碉級<b>蹇呴』鍘熸牱鐢� JSON 搴忓垪鍖�</b>锛屼笉瑕佹敼鍐欐垚閫愬瓧娈� set銆�
+ */
+ private ServiceSubtask cloneForNextLoop(ServiceSubtask src, ServiceTaskScheduleDetail detail,
+ long nextLoop, int stepNum, int stepUnit, Date now) {
+ ServiceSubtask copy = JSON.parseObject(JSON.toJSONString(src), ServiceSubtask.class);
+ copy.setId(null);
+ copy.setSenduuid(null);
+ copy.setResult(null);
+ copy.setFinishtime(null);
+ copy.setExrecallcount(null);
+ copy.setCurrentPreachform(null);
+ copy.setSendstate(2L);
+ copy.setLoopCount(nextLoop);
+ copy.setScheduleDetailId(detail.getId());
+ // 妯℃澘锛歞etail 浼樺厛
+ if (detail.getTemplateid() != null) {
+ copy.setTemplateid(detail.getTemplateid());
+ copy.setTemplatename(detail.getTemplatename());
+ }
+ if (detail.getLibtemplateid() != null) {
+ copy.setLibtemplateid(detail.getLibtemplateid());
+ }
+ Date base = src.getVisitTime() != null ? src.getVisitTime() : now;
+ Date nextVisit = advance(base, stepNum, stepUnit);
+ copy.setVisitTime(nextVisit);
+ copy.setSenddate(nextVisit);
+ copy.setLongSendTime(nextVisit);
+ copy.setCreateTime(now);
+ copy.setUpdateTime(now);
+ return copy;
+ }
+
+ /**
+ * 澶嶅埗婧� subtask 鐨勫彂閫佹柟寮忚鍒版柊 subtask 鈥斺�� 閫愯鎼嚜鍘� L318-338銆�
+ * <p>
+ * 鈿狅笍 鏌ユ簮琛岀殑鏉′欢鏄� {@code subid + taskid}锛�<b>涓嶈 orgid</b>锛岃櫧鐒� XML 鏀寔锛夛紝鍘熸牱淇濈暀銆�
+ */
+ private void copyPreachform(Long srcSubId, ServiceSubtask newSubtask) {
+ ServiceSubtaskPreachform q = new ServiceSubtaskPreachform();
+ q.setSubid(srcSubId);
+ q.setTaskid(newSubtask.getTaskid());
+ List<ServiceSubtaskPreachform> list =
+ serviceSubtaskPreachformMapper.selectServiceSubtaskPreachformList(q);
+ if (CollectionUtils.isEmpty(list)) {
+ return;
+ }
+ for (ServiceSubtaskPreachform src : list) {
+ ServiceSubtaskPreachform pf = new ServiceSubtaskPreachform();
+ pf.setSort(src.getSort());
+ pf.setPreachform(src.getPreachform());
+ pf.setCompensateTime(src.getCompensateTime());
+ pf.setTaskid(newSubtask.getTaskid());
+ pf.setSubid(newSubtask.getId());
+ pf.setSendstate("1");
+ pf.setOrgid(newSubtask.getOrgid());
+ pf.setCreateTime(new Date());
+ serviceSubtaskPreachformMapper.insertServiceSubtaskPreachform(pf);
+ }
+ }
+
+ /**
+ * 鎸� schedule_time_unit 鎺ㄨ繘鏃堕棿锛�1-澶� 2-鍛� 3-鏈� 4-骞� 鈥斺�� 閫愯鎼嚜鍘� L343-361銆�
+ */
+ private Date advance(Date base, int num, int unit) {
+ Calendar c = Calendar.getInstance();
+ c.setTime(base);
+ switch (unit) {
+ case 2:
+ c.add(Calendar.WEEK_OF_YEAR, num);
+ break;
+ case 3:
+ c.add(Calendar.MONTH, num);
+ break;
+ case 4:
+ c.add(Calendar.YEAR, num);
+ break;
+ case 1:
+ default:
+ c.add(Calendar.DAY_OF_MONTH, num);
+ }
+ return c.getTime();
+ }
+}
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskPreachformMapper.java b/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskPreachformMapper.java
new file mode 100644
index 0000000..6856afa
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskPreachformMapper.java
@@ -0,0 +1,78 @@
+package com.ruoyi.task.mapper;
+
+import com.ruoyi.task.domain.ServiceSubtask;
+import com.ruoyi.task.domain.ServiceSubtaskPreachform;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 闅忚瀛愪换鍔°�屾墽琛屾柟寮忔槑缁嗐�嶏紙{@code service_subtask_preachform}锛塎apper銆�
+ *
+ * <h3>2026-11 褰掑睘璋冩暣</h3>
+ * 璇ヨ〃鍘熷厛褰� {@code ruoyi-inhospvisit}锛堢粡 {@code PreachformApi} 濂戠害瀵瑰锛夛紝
+ * smartor 渚у彟鏈変竴浠藉悓琛� CRUD 鐢变竴涓� {@code @Primary} 濮旀墭瀹炵幇鍏滅潃锛宺uoyi-task 鍙兘缁�
+ * {@code ServiceSubtaskPreachformMapper} 闂存帴璇诲啓銆傛寜"琛ㄨ窡闅忎笟鍔″煙"鐨勫彛寰勶紝杩欏紶琛ㄦ暣浣撳垝褰� {@code ruoyi-task}锛�
+ * <ul>
+ * <li>SQL 涓� Mapper 鍙湁杩欎竴浠斤紙鏈帴鍙� + {@code mapper/task/ServiceSubtaskPreachformMapper.xml}锛夛紱</li>
+ * <li>ruoyi-task / ruoyi-phone / smartor / ruoyi-admin / ruoyi-quartz 涓�寰嬬洿鎺ユ敞鍏ユ湰 Mapper锛�</li>
+ * <li>{@code ruoyi-inhospvisit} 鍙嶅悜渚濊禆涓嶆垚绔嬶紙瀹冭鍐欒繖寮犺〃锛夛紝鍥犳浠嶈蛋
+ * {@code com.ruoyi.common.core.service.PreachformApi} 濂戠害锛屽疄鐜版柟鏀逛负鏈ā鍧�
+ * 锛坽@code com.ruoyi.task.api.contract.PreachformApiImpl}锛夈��</li>
+ * </ul>
+ *
+ * <h3>鈿狅笍 鏂规硶鍚嶆部鐢ㄨ縼绉诲墠锛坰martor / 鏈ā鍧楄皟鐢ㄧ偣淇濇寔闆舵敼鍔級</h3>
+ * 璇彞 id 涓� {@link ServiceSubtaskPreachform} 瀛楁涓�涓�瀵瑰簲锛屾潯浠躲�侀『搴忕収鎶勫師 SQL锛�
+ * 涓嶅仛"椤烘墜绮剧畝"銆備笁涓� {@code delete*} 鍦ㄥ簱閲屽叾瀹炴槸<b>杞垹</b>锛坽@code update ... set del_flag = 1}锛夈��
+ */
+@Mapper
+public interface ServiceSubtaskPreachformMapper {
+
+ /**
+ * 鎸変富閿煡锛堝師 {@code selectServiceSubtaskPreachformById}锛夈��
+ */
+ ServiceSubtaskPreachform selectServiceSubtaskPreachformById(Long id);
+
+ /**
+ * 鎸夋潯浠舵煡锛堝師 {@code selectServiceSubtaskPreachformList}锛夈��
+ * <p>
+ * 鍥哄畾鏉′欢 {@code del_flag = 0}锛屽叾浣� 8 涓瓧娈典负鍙�夋潯浠讹細
+ * {@code subid / taskid / current_send_time / preachform / sendstate / orgid / sort / compensate_time}銆�
+ */
+ List<ServiceSubtaskPreachform> selectServiceSubtaskPreachformList(ServiceSubtaskPreachform query);
+
+ /**
+ * 鏂板锛堣嚜澧炰富閿洖濉埌 {@code id}锛夈��
+ */
+ int insertServiceSubtaskPreachform(ServiceSubtaskPreachform row);
+
+ /**
+ * 鎸変富閿洿鏂帮紙{@code where id = #{id}}锛孲ET 鍚勫垪鍧囦负鍙�夛級銆�
+ */
+ int updateServiceSubtaskPreachform(ServiceSubtaskPreachform row);
+
+ /**
+ * 鎸夋潯浠舵洿鏂帮紙SET 鍚� update锛學HERE 鎸� {@code subid / taskid / preachform / remark / orgid}锛屾棤 id 鏉′欢锛夈��
+ */
+ int updateSSPByCondition(ServiceSubtaskPreachform row);
+
+ /**
+ * 鎸変富閿蒋鍒犮��
+ */
+ int deleteServiceSubtaskPreachformById(Long id);
+
+ /**
+ * 鎸� {@code subid} 杞垹銆�
+ */
+ int deleteServiceSubtaskPreachformBySubid(Long subid);
+
+ /**
+ * 鎸変富閿泦鍚堣蒋鍒犮��
+ */
+ int deleteServiceSubtaskPreachformByIds(Long[] ids);
+
+ /**
+ * 鎸� {@code taskid + orgid} 鏌ワ紙鏂规硶鍚嶆部鐢ㄦ棫鍚嶏紝<b>涓嶆槸</b>鎸� subtask 涓婚敭鏌ワ級銆�
+ */
+ List<ServiceSubtaskPreachform> selectBySubtask(ServiceSubtask subtask);
+}
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskRecordMapper.java b/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskRecordMapper.java
new file mode 100644
index 0000000..e8f6193
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/mapper/ServiceSubtaskRecordMapper.java
@@ -0,0 +1,68 @@
+package com.ruoyi.task.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+import com.ruoyi.task.domain.ServiceSubtaskRecord;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆慚apper鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2024-07-01
+ */
+@Mapper
+public interface ServiceSubtaskRecordMapper {
+ /**
+ * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+ */
+ public ServiceSubtaskRecord selectServiceSubtaskRecordById(Long id);
+
+ /**
+ * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 銆愯濉啓鍔熻兘鍚嶇О銆戦泦鍚�
+ */
+ public List<ServiceSubtaskRecord> selectServiceSubtaskRecordList(ServiceSubtaskRecord serviceSubtaskRecord);
+
+ /**
+ * 鎸� subtask_id 鍒楄〃鎵归噺鏌ヨ闅忚璁板綍锛屾秷闄+1
+ */
+ public List<ServiceSubtaskRecord> selectServiceSubtaskRecordBySubtaskIds(List<Long> subtaskIds);
+
+ /**
+ * 鏂板銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 缁撴灉
+ */
+ public int insertServiceSubtaskRecord(ServiceSubtaskRecord serviceSubtaskRecord);
+
+ /**
+ * 淇敼銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 缁撴灉
+ */
+ public int updateServiceSubtaskRecord(ServiceSubtaskRecord serviceSubtaskRecord);
+
+ /**
+ * 鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 缁撴灉
+ */
+ public int deleteServiceSubtaskRecordById(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteServiceSubtaskRecordByIds(Long[] ids);
+}
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/service/IServiceSubtaskRecordService.java b/ruoyi-task/src/main/java/com/ruoyi/task/service/IServiceSubtaskRecordService.java
new file mode 100644
index 0000000..4f52f09
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/service/IServiceSubtaskRecordService.java
@@ -0,0 +1,67 @@
+package com.ruoyi.task.service;
+
+
+import java.util.List;
+import com.ruoyi.task.domain.ServiceSubtaskRecord;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆慡ervice鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2024-07-01
+ */
+public interface IServiceSubtaskRecordService
+{
+ /**
+ * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+ */
+ public ServiceSubtaskRecord selectServiceSubtaskRecordById(Long id);
+
+ /**
+ * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 銆愯濉啓鍔熻兘鍚嶇О銆戦泦鍚�
+ */
+ public List<ServiceSubtaskRecord> selectServiceSubtaskRecordList(ServiceSubtaskRecord serviceSubtaskRecord);
+
+ /**
+ * 鎸� subtask_id 鍒楄〃鎵归噺鏌ヨ锛岀粨鏋滅敤 Map<subtaskId, records> 缁撴瀯杩斿洖
+ */
+ public java.util.Map<Long, List<ServiceSubtaskRecord>> selectRecordMapBySubtaskIds(List<Long> subtaskIds);
+
+ /**
+ * 鏂板銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 缁撴灉
+ */
+ public int insertServiceSubtaskRecord(ServiceSubtaskRecord serviceSubtaskRecord);
+
+ /**
+ * 淇敼銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 缁撴灉
+ */
+ public int updateServiceSubtaskRecord(ServiceSubtaskRecord serviceSubtaskRecord);
+
+ /**
+ * 鎵归噺鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑銆愯濉啓鍔熻兘鍚嶇О銆戜富閿泦鍚�
+ * @return 缁撴灉
+ */
+ public int deleteServiceSubtaskRecordByIds(Long[] ids);
+
+ /**
+ * 鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆戜俊鎭�
+ *
+ * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 缁撴灉
+ */
+ public int deleteServiceSubtaskRecordById(Long id);
+}
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskRecordServiceImpl.java b/ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskRecordServiceImpl.java
new file mode 100644
index 0000000..c711474
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/service/impl/ServiceSubtaskRecordServiceImpl.java
@@ -0,0 +1,102 @@
+package com.ruoyi.task.service.impl;
+
+import com.ruoyi.common.utils.DateUtils;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import com.ruoyi.task.domain.ServiceSubtaskRecord;
+import com.ruoyi.task.mapper.ServiceSubtaskRecordMapper;
+import com.ruoyi.task.service.IServiceSubtaskRecordService;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆慡ervice涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ * @date 2024-07-01
+ */
+@Service
+public class ServiceSubtaskRecordServiceImpl implements IServiceSubtaskRecordService {
+ @Autowired
+ private ServiceSubtaskRecordMapper serviceSubtaskRecordMapper;
+
+ /**
+ * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+ */
+ @Override
+ public ServiceSubtaskRecord selectServiceSubtaskRecordById(Long id) {
+ return serviceSubtaskRecordMapper.selectServiceSubtaskRecordById(id);
+ }
+
+ /**
+ * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+ */
+ @Override
+ public List<ServiceSubtaskRecord> selectServiceSubtaskRecordList(ServiceSubtaskRecord serviceSubtaskRecord) {
+ return serviceSubtaskRecordMapper.selectServiceSubtaskRecordList(serviceSubtaskRecord);
+ }
+
+ @Override
+ public Map<Long, List<ServiceSubtaskRecord>> selectRecordMapBySubtaskIds(List<Long> subtaskIds) {
+ if (CollectionUtils.isEmpty(subtaskIds)) return new java.util.HashMap<>();
+ List<ServiceSubtaskRecord> all = serviceSubtaskRecordMapper.selectServiceSubtaskRecordBySubtaskIds(subtaskIds);
+ if (CollectionUtils.isEmpty(all)) return new java.util.HashMap<>();
+ return all.stream().collect(Collectors.groupingBy(ServiceSubtaskRecord::getSubtaskId));
+ }
+
+ /**
+ * 鏂板銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertServiceSubtaskRecord(ServiceSubtaskRecord serviceSubtaskRecord) {
+ serviceSubtaskRecord.setCreateTime(DateUtils.getNowDate());
+ return serviceSubtaskRecordMapper.insertServiceSubtaskRecord(serviceSubtaskRecord);
+ }
+
+ /**
+ * 淇敼銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param serviceSubtaskRecord 銆愯濉啓鍔熻兘鍚嶇О銆�
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateServiceSubtaskRecord(ServiceSubtaskRecord serviceSubtaskRecord) {
+ serviceSubtaskRecord.setUpdateTime(DateUtils.getNowDate());
+ return serviceSubtaskRecordMapper.updateServiceSubtaskRecord(serviceSubtaskRecord);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteServiceSubtaskRecordByIds(Long[] ids) {
+ return serviceSubtaskRecordMapper.deleteServiceSubtaskRecordByIds(ids);
+ }
+
+ /**
+ * 鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆戜俊鎭�
+ *
+ * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteServiceSubtaskRecordById(Long id) {
+ return serviceSubtaskRecordMapper.deleteServiceSubtaskRecordById(id);
+ }
+}
diff --git a/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskPreachformMapper.xml b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskPreachformMapper.xml
new file mode 100644
index 0000000..702a23d
--- /dev/null
+++ b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskPreachformMapper.xml
@@ -0,0 +1,331 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.task.mapper.ServiceSubtaskPreachformMapper">
+
+ <!--
+ ============================================================================
+ 鍑哄叆闄㈤殢璁挎ā鍧楄嚜甯︾殑 service_subtask_preachform 璇诲啓銆�
+ ============================================================================
+ 涓� smartor 鐨� mapper/smartor/ServiceSubtaskPreachformMapper.xml 绛変环锛�
+ 路 selectList 鈫� selectServiceSubtaskPreachformList锛堝師 XML L44-73锛�
+ 路 insert 鈫� insertServiceSubtaskPreachform锛堝師 XML L81-151锛寀seGeneratedKeys锛�
+ 鍘� XML 鐢� <sql id="selectServiceSubtaskPreachformVo"> 鍏变韩鐗囨锛涜繖閲屻�愭樉寮忓垪鍑哄悓涓�鎵瑰垪銆戯紝
+ 涓嶅鍒剁墖娈碉紙涓� VisitInhospMapper 鍚屼竴鍋氭硶锛氳嚜鍖呭惈銆佷究浜庨�愭潯姣斿锛夈��
+ ============================================================================
+ -->
+
+ <resultMap type="com.ruoyi.task.domain.ServiceSubtaskPreachform" id="ServiceSubtaskPreachformResult">
+ <result property="id" column="id"/>
+ <result property="subid" column="subid"/>
+ <result property="taskid" column="taskid"/>
+ <result property="preachform" column="preachform"/>
+ <result property="sendstate" column="sendstate"/>
+ <result property="currentSendTime" column="current_send_time"/>
+ <result property="remark" column="remark"/>
+ <result property="orgid" column="orgid"/>
+ <result property="delFlag" column="del_flag"/>
+ <result property="createTime" column="create_time"/>
+ <result property="createBy" column="create_by"/>
+ <result property="updateTime" column="update_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="compensateTime" column="compensate_time"/>
+ <result property="sort" column="sort"/>
+ </resultMap>
+
+ <!-- 鏉′欢涓庨『搴忛�愭潯瀵归綈鍘� XML L44-73 -->
+ <select id="selectServiceSubtaskPreachformList" parameterType="com.ruoyi.task.domain.ServiceSubtaskPreachform"
+ resultMap="ServiceSubtaskPreachformResult">
+ select id,
+ subid,
+ taskid,
+ preachform,
+ sendstate,
+ current_send_time,
+ remark,
+ orgid,
+ del_flag,
+ create_time,
+ create_by,
+ update_time,
+ update_by,
+ compensate_time,
+ sort
+ from service_subtask_preachform
+ where 1=1
+ and del_flag = 0
+ <if test="subid != null ">
+ and subid = #{subid}
+ </if>
+ <if test="taskid != null ">
+ and taskid = #{taskid}
+ </if>
+ <if test="currentSendTime != null ">
+ and current_send_time = #{currentSendTime}
+ </if>
+ <if test="preachform != null and preachform != ''">
+ and preachform = #{preachform}
+ </if>
+ <if test="sendstate != null and sendstate != ''">
+ and sendstate = #{sendstate}
+ </if>
+ <if test="orgid != null and orgid != ''">
+ and orgid = #{orgid}
+ </if>
+ <if test="sort != null ">
+ and sort = #{sort}
+ </if>
+ <if test="compensateTime != null ">
+ and compensate_time = #{compensateTime}
+ </if>
+ </select>
+
+ <!-- 鍒椾笌椤哄簭閫愭潯瀵归綈鍘� XML L81-151 -->
+ <insert id="insertServiceSubtaskPreachform" parameterType="com.ruoyi.task.domain.ServiceSubtaskPreachform"
+ useGeneratedKeys="true" keyProperty="id">
+ insert into service_subtask_preachform
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="id != null">id,</if>
+ <if test="subid != null">subid,</if>
+ <if test="taskid != null">taskid,</if>
+ <if test="preachform != null">preachform,</if>
+ <if test="sendstate != null">sendstate,</if>
+ <if test="remark != null">remark,</if>
+ <if test="orgid != null">orgid,</if>
+ <if test="delFlag != null">del_flag,</if>
+ <if test="createTime != null">create_time,</if>
+ <if test="createBy != null">create_by,</if>
+ <if test="updateTime != null">update_time,</if>
+ <if test="updateBy != null">update_by,</if>
+ <if test="sort != null">sort,</if>
+ <if test="compensateTime != null">compensate_time,</if>
+ <if test="currentSendTime != null ">current_send_time,</if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="id != null">#{id},</if>
+ <if test="subid != null">#{subid},</if>
+ <if test="taskid != null">#{taskid},</if>
+ <if test="preachform != null">#{preachform},</if>
+ <if test="sendstate != null">#{sendstate},</if>
+ <if test="remark != null">#{remark},</if>
+ <if test="orgid != null">#{orgid},</if>
+ <if test="delFlag != null">#{delFlag},</if>
+ <if test="createTime != null">#{createTime},</if>
+ <if test="createBy != null">#{createBy},</if>
+ <if test="updateTime != null">#{updateTime},</if>
+ <if test="updateBy != null">#{updateBy},</if>
+ <if test="sort != null">#{sort},</if>
+ <if test="compensateTime != null">#{compensateTime},</if>
+ <if test="currentSendTime != null ">#{currentSendTime},</if>
+ </trim>
+ </insert>
+
+ <!--
+ ============================================================================
+ 璺ㄦā鍧� SQL 鏀跺彛琛ラ綈鐨� 7 涓� statement锛堢収鎶� smartor 鍘� XML锛屾潯浠�/鍒�/椤哄簭涓嶅彉锛�
+ 路 selectById 鈫� selectServiceSubtaskPreachformById
+ 路 selectByTaskidAndOrgid 鈫� selectBySubtask锛堝師鎸� taskid + orgid锛岄潪涓婚敭锛�
+ 路 updateById 鈫� updateServiceSubtaskPreachform锛坵here id = #{id}锛�
+ 路 updateByCondition 鈫� updateSSPByCondition锛圫ET 鍚� updateById锛學HERE 鎸夋潯浠朵笖鏃� id锛�
+ 路 softDeleteById 鈫� deleteServiceSubtaskPreachformById锛坲pdate 缃� del_flag=1锛�
+ 路 softDeleteByIds 鈫� deleteServiceSubtaskPreachformByIds锛堝悓涓婏紝in 闆嗗悎锛�
+ 路 softDeleteBySubid 鈫� deleteServiceSubtaskPreachformBySubid锛堝悓涓婏紝鎸� subid锛�
+ 娉ㄦ剰锛氫笁涓� delete* 鍦ㄥ師 XML 閲屽氨鏄�"杞垹"锛坲pdate set del_flag=1锛夛紝姝ゅ鍘熸牱淇濈暀锛�
+ 鍏朵腑 BySubid 鍘熸湰鐢ㄧ殑灏辨槸 <delete> 鏍囩锛屼篃鐓ф妱銆�
+ ============================================================================
+ -->
+
+ <select id="selectServiceSubtaskPreachformById" parameterType="Long" resultMap="ServiceSubtaskPreachformResult">
+ select id,
+ subid,
+ taskid,
+ preachform,
+ sendstate,
+ current_send_time,
+ remark,
+ orgid,
+ del_flag,
+ create_time,
+ create_by,
+ update_time,
+ update_by,
+ compensate_time,
+ sort
+ from service_subtask_preachform
+ where id = #{id}
+ </select>
+
+ <!-- 鍘� selectBySubtask锛歞el_flag=0 + 鍙�� taskid/orgid锛堝師鍙傛暟鏄� ServiceSubtask锛屽疄闄呭彧鐢ㄨ繖涓や釜瀛楁锛� -->
+ <select id="selectBySubtask" resultMap="ServiceSubtaskPreachformResult">
+ select id,
+ subid,
+ taskid,
+ preachform,
+ sendstate,
+ current_send_time,
+ remark,
+ orgid,
+ del_flag,
+ create_time,
+ create_by,
+ update_time,
+ update_by,
+ compensate_time,
+ sort
+ from service_subtask_preachform
+ WHERE del_flag = 0
+ <if test="taskid != null">
+ AND taskid = #{taskid}
+ </if>
+ <if test="orgid != null and orgid != ''">
+ AND orgid = #{orgid}
+ </if>
+ </select>
+
+ <!-- 鍘� updateServiceSubtaskPreachform锛歸here id = #{id} -->
+ <update id="updateServiceSubtaskPreachform" parameterType="com.ruoyi.task.domain.ServiceSubtaskPreachform">
+ update service_subtask_preachform
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="subid != null">subid =
+ #{subid},
+ </if>
+ <if test="taskid != null">taskid =
+ #{taskid},
+ </if>
+ <if test="preachform != null">preachform =
+ #{preachform},
+ </if>
+ <if test="sendstate != null">sendstate =
+ #{sendstate},
+ </if>
+ <if test="remark != null">remark =
+ #{remark},
+ </if>
+ <if test="orgid != null">orgid =
+ #{orgid},
+ </if>
+ <if test="delFlag != null">del_flag =
+ #{delFlag},
+ </if>
+ <if test="createTime != null">create_time =
+ #{createTime},
+ </if>
+ <if test="createBy != null">create_by =
+ #{createBy},
+ </if>
+ <if test="updateTime != null">update_time =
+ #{updateTime},
+ </if>
+ <if test="updateBy != null">update_by =
+ #{updateBy},
+ </if>
+ <if test="sort != null">sort =
+ #{sort},
+ </if>
+ <if test="compensateTime != null">compensate_time =
+ #{compensateTime},
+ </if>
+ <if test="currentSendTime != null ">
+ current_send_time = #{currentSendTime},
+ </if>
+ </trim>
+ where id = #{id}
+ </update>
+
+ <!-- 鍘� updateSSPByCondition锛歋ET 涓� updateById 鐩稿悓锛學HERE 鎸夋潯浠朵笖鏃� id -->
+ <update id="updateSSPByCondition" parameterType="com.ruoyi.task.domain.ServiceSubtaskPreachform">
+ update service_subtask_preachform
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="subid != null">subid =
+ #{subid},
+ </if>
+ <if test="taskid != null">taskid =
+ #{taskid},
+ </if>
+ <if test="preachform != null">preachform =
+ #{preachform},
+ </if>
+ <if test="sendstate != null">sendstate =
+ #{sendstate},
+ </if>
+ <if test="remark != null">remark =
+ #{remark},
+ </if>
+ <if test="orgid != null">orgid =
+ #{orgid},
+ </if>
+ <if test="delFlag != null">del_flag =
+ #{delFlag},
+ </if>
+ <if test="createTime != null">create_time =
+ #{createTime},
+ </if>
+ <if test="createBy != null">create_by =
+ #{createBy},
+ </if>
+ <if test="updateTime != null">update_time =
+ #{updateTime},
+ </if>
+ <if test="updateBy != null">update_by =
+ #{updateBy},
+ </if>
+ <if test="sort != null">sort =
+ #{sort},
+ </if>
+ <if test="compensateTime != null">compensate_time =
+ #{compensateTime},
+ </if>
+ <if test="currentSendTime != null ">
+ current_send_time = #{currentSendTime},
+ </if>
+ </trim>
+ where 1=1
+ <if test="subid != null">and subid =
+ #{subid}
+ </if>
+ <if test="taskid != null">and taskid =
+ #{taskid}
+ </if>
+ <if test="preachform != null">and preachform =
+ #{preachform}
+ </if>
+ <if test="remark != null">and remark =
+ #{remark}
+ </if>
+ <if test="orgid != null">and orgid =
+ #{orgid}
+ </if>
+ </update>
+
+ <!-- 鍘� deleteServiceSubtaskPreachformById锛�<update> 缃� del_flag=1 -->
+ <update id="deleteServiceSubtaskPreachformById" parameterType="Long">
+ update service_subtask_preachform
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1
+ </trim>
+ where id = #{id}
+ </update>
+
+ <!-- 鍘� deleteServiceSubtaskPreachformByIds锛�<update> + in 闆嗗悎 -->
+ <update id="deleteServiceSubtaskPreachformByIds" parameterType="String">
+ update service_subtask_preachform
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1
+ </trim>
+ where id in
+ <foreach item="id" collection="array" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </update>
+
+ <!-- 鍘� deleteServiceSubtaskPreachformBySubid锛�<delete> 鏍囩浣嗚鍙ユ槸 update -->
+ <delete id="deleteServiceSubtaskPreachformBySubid" parameterType="Long">
+ update service_subtask_preachform
+ <trim prefix="SET" suffixOverrides=",">
+ del_flag =1
+ </trim>
+ where subid = #{subid}
+ </delete>
+
+</mapper>
diff --git a/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskRecordMapper.xml b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskRecordMapper.xml
new file mode 100644
index 0000000..559e219
--- /dev/null
+++ b/ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskRecordMapper.xml
@@ -0,0 +1,179 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.task.mapper.ServiceSubtaskRecordMapper">
+
+ <resultMap type="com.ruoyi.task.domain.ServiceSubtaskRecord" id="ServiceSubtaskRecordResult">
+ <result property="id" column="id"/>
+ <result property="taskid" column="taskid"/>
+ <result property="subtaskId" column="subtask_id"/>
+ <result property="uuid" column="uuid"/>
+ <result property="tasktype" column="tasktype"/>
+ <result property="preachform" column="preachform"/>
+ <result property="recordtype" column="recordtype"/>
+ <result property="startTime" column="start_time"/>
+ <result property="endTime" column="end_time"/>
+ <result property="result" column="result"/>
+ <result property="delFlag" column="del_flag"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="updateTime" column="update_time"/>
+ <result property="createBy" column="create_by"/>
+ <result property="createTime" column="create_time"/>
+ <result property="isupload" column="isupload"/>
+ <result property="uploadTime" column="upload_time"/>
+ <result property="orgid" column="orgid"/>
+ <result property="pid" column="pid"/>
+ <result property="guid" column="guid"/>
+ <result property="remark" column="remark"/>
+ </resultMap>
+
+ <sql id="selectServiceSubtaskRecordVo">
+ select id,
+ taskid,
+ subtask_id,
+ uuid,
+ tasktype,
+ preachform,
+ recordtype,
+ start_time,
+ end_time,
+ result,
+ del_flag,
+ update_by,
+ update_time,
+ create_by,
+ create_time,
+ isupload,
+ upload_time,
+ orgid,
+ pid,
+ remark,
+ guid
+ from service_subtask_record
+ </sql>
+
+ <select id="selectServiceSubtaskRecordList" parameterType="com.ruoyi.task.domain.ServiceSubtaskRecord"
+ resultMap="ServiceSubtaskRecordResult">
+ <include refid="selectServiceSubtaskRecordVo"/>
+ where 1=1
+ <if test="taskid != null and taskid != ''">and taskid = #{taskid}</if>
+ <if test="subtaskId != null ">and subtask_id = #{subtaskId}</if>
+ <if test="uuid != null and uuid != ''">and uuid = #{uuid}</if>
+ <if test="tasktype != null and tasktype != ''">and tasktype = #{tasktype}</if>
+ <if test="preachform != null and preachform != ''">and preachform = #{preachform}</if>
+ <if test="recordtype != null and recordtype != ''">and recordtype = #{recordtype}</if>
+ <if test="startTime != null ">and start_time = #{startTime}</if>
+ <if test="endTime != null ">and end_time = #{endTime}</if>
+ <if test="result != null and result != ''">and result = #{result}</if>
+ <if test="isupload != null ">and isupload = #{isupload}</if>
+ <if test="uploadTime != null ">and upload_time = #{uploadTime}</if>
+ <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
+ <if test="pid != null ">and pid = #{pid}</if>
+ <if test="guid != null and guid != ''">and guid = #{guid}</if>
+ <if test="remark != null and remark != ''">and remark = #{remark}</if>
+ </select>
+
+ <select id="selectServiceSubtaskRecordBySubtaskIds" resultMap="ServiceSubtaskRecordResult">
+ <include refid="selectServiceSubtaskRecordVo"/>
+ where subtask_id IN
+ <foreach collection="list" item="subtaskId" open="(" separator="," close=")">
+ #{subtaskId}
+ </foreach>
+ </select>
+
+ <select id="selectServiceSubtaskRecordById" parameterType="Long" resultMap="ServiceSubtaskRecordResult">
+ <include refid="selectServiceSubtaskRecordVo"/>
+ where id = #{id}
+ </select>
+
+ <insert id="insertServiceSubtaskRecord" parameterType="com.ruoyi.task.domain.ServiceSubtaskRecord">
+ insert into service_subtask_record
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="id != null">id,</if>
+ <if test="taskid != null">taskid,</if>
+ <if test="uuid != null">uuid,</if>
+ <if test="tasktype != null">tasktype,</if>
+ <if test="preachform != null">preachform,</if>
+ <if test="recordtype != null">recordtype,</if>
+ <if test="startTime != null">start_time,</if>
+ <if test="endTime != null">end_time,</if>
+ <if test="result != null">result,</if>
+ <if test="delFlag != null">del_flag,</if>
+ <if test="updateBy != null">update_by,</if>
+ <if test="updateTime != null">update_time,</if>
+ <if test="createBy != null">create_by,</if>
+ <if test="createTime != null">create_time,</if>
+ <if test="isupload != null">isupload,</if>
+ <if test="uploadTime != null">upload_time,</if>
+ <if test="orgid != null">orgid,</if>
+ <if test="pid != null">pid,</if>
+ <if test="guid != null">guid,</if>
+ <if test="remark != null">remark,</if>
+ <if test="subtaskId != null ">subtask_id,</if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="id != null">#{id},</if>
+ <if test="taskid != null">#{taskid},</if>
+ <if test="uuid != null">#{uuid},</if>
+ <if test="tasktype != null">#{tasktype},</if>
+ <if test="preachform != null">#{preachform},</if>
+ <if test="recordtype != null">#{recordtype},</if>
+ <if test="startTime != null">#{startTime},</if>
+ <if test="endTime != null">#{endTime},</if>
+ <if test="result != null">#{result},</if>
+ <if test="delFlag != null">#{delFlag},</if>
+ <if test="updateBy != null">#{updateBy},</if>
+ <if test="updateTime != null">#{updateTime},</if>
+ <if test="createBy != null">#{createBy},</if>
+ <if test="createTime != null">#{createTime},</if>
+ <if test="isupload != null">#{isupload},</if>
+ <if test="uploadTime != null">#{uploadTime},</if>
+ <if test="orgid != null">#{orgid},</if>
+ <if test="pid != null">#{pid},</if>
+ <if test="guid != null">#{guid},</if>
+ <if test="remark != null">#{remark},</if>
+ <if test="subtaskId != null ">#{subtaskId},</if>
+ </trim>
+ </insert>
+
+ <update id="updateServiceSubtaskRecord" parameterType="com.ruoyi.task.domain.ServiceSubtaskRecord">
+ update service_subtask_record
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="taskid != null">taskid = #{taskid},</if>
+ <if test="uuid != null">uuid = #{uuid},</if>
+ <if test="tasktype != null">tasktype = #{tasktype},</if>
+ <if test="preachform != null">preachform = #{preachform},</if>
+ <if test="recordtype != null">recordtype = #{recordtype},</if>
+ <if test="startTime != null">start_time = #{startTime},</if>
+ <if test="endTime != null">end_time = #{endTime},</if>
+ <if test="result != null">result = #{result},</if>
+ <if test="delFlag != null">del_flag = #{delFlag},</if>
+ <if test="updateBy != null">update_by = #{updateBy},</if>
+ <if test="updateTime != null">update_time = #{updateTime},</if>
+ <if test="createBy != null">create_by = #{createBy},</if>
+ <if test="createTime != null">create_time = #{createTime},</if>
+ <if test="isupload != null">isupload = #{isupload},</if>
+ <if test="uploadTime != null">upload_time = #{uploadTime},</if>
+ <if test="orgid != null">orgid = #{orgid},</if>
+ <if test="pid != null">pid = #{pid},</if>
+ <if test="guid != null">guid = #{guid},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ <if test="subtaskId != null ">subtask_id = #{subtaskId},</if>
+ </trim>
+ where id = #{id}
+ </update>
+
+ <delete id="deleteServiceSubtaskRecordById" parameterType="Long">
+ delete
+ from service_subtask_record
+ where id = #{id}
+ </delete>
+
+ <delete id="deleteServiceSubtaskRecordByIds" parameterType="String">
+ delete from service_subtask_record where id in
+ <foreach item="id" collection="array" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </delete>
+</mapper>
diff --git a/smartor/src/main/java/com/smartor/service/IPatMedOuthospService.java b/smartor/src/main/java/com/smartor/service/IPatMedOuthospService.java
new file mode 100644
index 0000000..d6d891a
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/service/IPatMedOuthospService.java
@@ -0,0 +1,68 @@
+package com.smartor.service;
+
+import com.ruoyi.outpatientvisit.domain.PatMedOuthosp;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 鎮h�呴棬璇婅褰� Service 鈥斺�� <b>杩囨浮鎺ュ彛锛堟鍦ㄦ敹鍙o級</b>銆�
+ *
+ * <h3>鈿狅笍 鏈帴鍙g殑澶ч儴鍒嗘柟娉曞凡涓嶅湪鏈ā鍧楀疄鐜�</h3>
+ * 闂ㄦ�ヨ瘖闅忚妯″潡鍖栵紙O2~O4锛夊凡鎶婇棬璇婅褰曠殑鏈嶅姟绔兘鍔涙暣浣撹縼鍏�
+ * {@code ruoyi-outpatientvisit}锛�
+ * <ul>
+ * <li>鍩虹璇诲啓/缁熻/鍒嗚〃璺敱 鈫� 璇ユā鍧楃殑 {@code OuthospDataService}锛�</li>
+ * <li>闅忚缂栨帓锛堟壂鍏ㄩ噺锛夆啋 璇ユā鍧楃殑 {@code OuthospVisitTaskService}銆�</li>
+ * </ul>
+ * 鏈帴鍙d繚鐣欐槸涓轰簡璁�<b>鏃㈡湁璋冪敤鏂归浂鏀瑰姩</b>锛�10 涓枃浠讹紝璺� smartor / ruoyi-admin / ruoyi-quartz锛夛紝
+ * 鐢卞鎵樺疄鐜版妸宸茶縼鏂规硶杞彂鍒版ā鍧楅棬闈� 鈥斺��
+ * 涓庡鏁欏崟璺ㄦā鍧楁敹鍙o紙{@code ServiceSubtaskPreachformMapperBridge}锛夊悓涓�鎵嬫硶銆�
+ *
+ * <h3>鏈帴鍙e埢鎰忓彧淇濈暀銆岃皟鐢ㄦ柟瀹為檯鐢ㄥ埌鐨� 5 涓柟娉曘��</h3>
+ * 鍘熸帴鍙f湁 14 涓柟娉曪紝浣嗗疄娴嬪彧鏈変互涓� 5 涓澶栭儴璋冪敤锛�
+ * <pre>
+ * insertPatMedOuthosp(...) HNGatherPatArchive銆丆ollectHIS銆丼erviceExternal銆丼erviceSLTD鈥�
+ * updatePatMedOuthosp(...) CollectHIS銆丼erviceExternal銆丼erviceSubtask鈥�
+ * selectExistingSerialnums(...) ServiceSLTD鈥�
+ * dealPatMedOuthosp(...) ServiceExternal
+ * </pre>
+ * 鍏朵綑锛坽@code selectById} / {@code selectList} / {@code selectCount} / {@code getDeptCodeByPatId}
+ * / {@code delete*} / {@code boxedServiceSubtask} / {@code followUp*}锛�<b>鏃犲閮ㄨ皟鐢ㄦ柟</b>锛�
+ * 鏁呬笉鍦ㄦ澹版槑銆�
+ *
+ * <h3>灏嗘潵鍔ㄤ綔</h3>
+ * 璋冪敤鏂归�愪釜鏀逛负鐩存帴渚濊禆妯″潡闂ㄩ潰鍚庯紝鏈帴鍙d笌濮旀墭瀹炵幇鍗冲彲鏁翠綋鍒犻櫎銆�
+ * <b>鏂颁唬鐮佽鐩存帴鐢� {@code ruoyi-outpatientvisit} 鐨�
+ * {@code OuthospDataFacade} / {@code OuthospDataService}銆�</b>
+ *
+ * @deprecated 鐢� {@code com.ruoyi.outpatientvisit.api.OuthospDataFacade} 浠f浛銆�
+ * 淇濈暀浠呬负鍏煎鏃㈡湁璋冪敤鏂癸紝鏂颁唬鐮佷笉瑕佷娇鐢ㄣ��
+ */
+@Deprecated
+public interface IPatMedOuthospService {
+
+ /**
+ * 鏂板闂ㄨ瘖璁板綍锛堟寜灏辫瘖鏃堕棿璺敱鍒板垎琛級銆�
+ */
+ public int insertPatMedOuthosp(PatMedOuthosp patMedOuthosp);
+
+ /**
+ * 淇敼闂ㄨ瘖璁板綍锛堟煡涓嶅埌鍒欒浆鏂板锛夈��
+ */
+ public int updatePatMedOuthosp(PatMedOuthosp patMedOuthosp);
+
+ /**
+ * 鎵归噺鏌ュ凡鍏ュ簱鐨� serialnum锛堟寜灏辫瘖鏃ユ湡瀹氫綅鍒嗚〃锛屼竴娆� IN 鏌ヨ锛夈��
+ */
+ public Set<String> selectExistingSerialnums(String admitDateStr, Collection<String> serialnums);
+
+ /**
+ * 鍗曟偅鑰呮寜闇�闅忚锛堟櫙瀹佺珯鐐圭壒娈婇�昏緫 鈫� 棣栨闅忚鎴栧啀娆¢殢璁匡級銆�
+ * <p>
+ * 鈿狅笍 <b>鏈銆愭湭銆戣縼绉�</b>锛屼粛鐢� smartor 鍘熺敓瀹炵幇锛氬畠渚濊禆 {@code serviceSubtaskMapper}
+ * 涓� {@code followUpByPatMedOuthosp} / {@code followUpAgainByPatMedOuthosp} 涓や釜绉佹湁鏂规硶锛�
+ * 灞炲彟涓�鏉¢摼璺紙"鎸夐渶"鑰岄潪"鎵叏閲�"锛夈�傞殢璇ラ摼璺竴璧锋敹鍙c��
+ */
+ public Integer dealPatMedOuthosp(PatMedOuthosp patMedOuthosp, Integer visitTimeNum);
+}
diff --git a/smartor/src/main/java/com/smartor/service/impl/PatMedOuthospServiceDelegatingImpl.java b/smartor/src/main/java/com/smartor/service/impl/PatMedOuthospServiceDelegatingImpl.java
new file mode 100644
index 0000000..9d95429
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/service/impl/PatMedOuthospServiceDelegatingImpl.java
@@ -0,0 +1,423 @@
+package com.smartor.service.impl;
+
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.DtoConversionUtils;
+import com.ruoyi.outpatientvisit.api.OuthospDataFacade;
+import com.ruoyi.outpatientvisit.domain.PatMedOuthosp;
+import com.ruoyi.patarchive.mapper.PatArchiveMapper;
+import com.smartor.service.IPatMedOuthospService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.*;
+import java.util.stream.Collectors;
+import com.ruoyi.common.core.domain.entity.PatArchive;
+import com.ruoyi.task.domain.entity.ServiceSubtaskEntity;
+import com.ruoyi.task.domain.ServiceSubtask;
+import com.ruoyi.task.domain.ServiceTask;
+import com.ruoyi.task.domain.ServiceTaskdept;
+import com.ruoyi.task.mapper.ServiceSubtaskMapper;
+import com.ruoyi.task.mapper.ServiceTaskdeptMapper;
+import com.ruoyi.task.mapper.ServiceTaskdiagMapper;
+import com.ruoyi.task.mapper.ServiceTaskMapper;
+
+/**
+ * {@link IPatMedOuthospService} 鐨�<b>濮旀墭瀹炵幇</b> 鈥斺�� 闂ㄦ�ヨ瘖闅忚妯″潡鍖栫殑杩囨浮浠躲��
+ *
+ * <h3>瀹冨仛涓や欢浜�</h3>
+ * <ol>
+ * <li><b>宸茶縼鐨� 4 涓柟娉� 鈫� 濮旀墭妯″潡</b>锛�
+ * {@code insert} / {@code update} / {@code selectExistingSerialnums} / {@code dealOutpatientInfo}
+ * 杞彂鍒� {@link OuthospDataFacade}锛圫QL 鍞竴鏀舵暃鍦ㄦā鍧楅噷锛夛紱</li>
+ * <li><b>鏈縼鐨� 3 涓柟娉� 鈫� 淇濈暀鍘熺敓</b>锛歿@code dealPatMedOuthosp} /
+ * {@code followUpByPatMedOuthosp} / {@code followUpAgainByPatMedOuthosp}
+ * 鍙婂畠浠殑绉佹湁渚濊禆锛坽@code addDays} / {@code writeInSubTask} / {@code boxedServiceSubtask}锛夈��
+ * 杩欐潯鏄�"<b>鍗曟偅鑰呮寜闇�闅忚</b>"閾捐矾锛堜緷璧� {@code serviceSubtaskMapper}銆�
+ * 鏅畞绔欑偣鐧藉悕鍗曠瓑锛夛紝涓庡凡杩佺殑"鎵叏閲�"鏄袱鏉′笉鍚岀殑鍏ュ彛銆�</li>
+ * </ol>
+ *
+ * <h3>鈿狅笍 鏈縼閮ㄥ垎閫愬瓧鏉ヨ嚜鍩虹嚎 {@code b25c3b51}</h3>
+ * 鐢� {@code sql/_probe/gen_outhosp_delegating_impl.py} 浠庡熀绾胯嚜鍔ㄦ彁鍙栵紝
+ * <b>涓嶆槸鎵嬫妱</b> 鈥斺�� 杩欑被浠g爜鎵嬫妱鍑洪敊涓嶄細缂栬瘧鎶ラ敊锛屽彧浼氶潤榛樻敼鍙樹笟鍔¤涓恒��
+ * 鏀瑰姩鏈縼閮ㄥ垎鏃跺繀椤诲悓姝ユ洿鏂拌鎺㈤拡鐨勬湡鏈涖��
+ *
+ * <h3>灏嗘潵鍔ㄤ綔</h3>
+ * 璋冪敤鏂归�愪釜鏀逛负鐩存帴渚濊禆妯″潡闂ㄩ潰鍚庯紝鏈被涓� {@link IPatMedOuthospService} 涓�璧峰垹闄ゃ��
+ */
+@Slf4j
+@Service
+public class PatMedOuthospServiceDelegatingImpl implements IPatMedOuthospService {
+
+ /** 妯″潡闂ㄩ潰锛氬凡杩佹柟娉曠殑鍞竴鍑哄彛 */
+ @Autowired
+ private OuthospDataFacade outhospDataFacade;
+
+ // ==== 浠ヤ笅渚濊禆浠呬緵銆愭湭杩併�戠殑鍗曟偅鑰呮寜闇�闅忚閾捐矾浣跨敤 ====
+ @Autowired
+ private ServiceSubtaskMapper serviceSubtaskMapper;
+ @Autowired
+ private ServiceTaskMapper serviceTaskMapper;
+ @Autowired
+ private ServiceTaskdeptMapper serviceTaskdeptMapper;
+ @Autowired
+ private ServiceTaskdiagMapper serviceTaskdiagMapper;
+ @Autowired
+ private PatArchiveMapper patArchiveMapper;
+
+ /**
+ * 鍒楄〃鏌ヨ 鈥斺�� 渚涖�愭湭杩併�戠殑鍗曟偅鑰呮寜闇�闅忚閾捐矾鍐呴儴浣跨敤銆�
+ * <p>
+ * 鍘熷疄鐜伴噷瀹冩槸鏈被鐨� {@code selectPatMedOuthospList}锛涚幇宸茶縼鍏ユā鍧楃殑
+ * {@code OuthospDataService#selectList}锛屾晠杩欓噷鍙仛鍐呴儴杞彂銆�
+ * <p>
+ * 鈿狅笍 娉ㄦ剰瀹冧笌 Controller 鐢ㄧ殑鏄悓涓�涓柟娉� 鈥斺�� 鍚庤�呬細鍋氬睍绀哄瘜鍖栵紙浠呭綋 pageNum != null锛夈��
+ * 鏈摼璺笉璁� pageNum锛屾晠涓嶄細瀵屽寲锛屼笌鍘熷疄鐜颁竴鑷淬��
+ */
+ private List<PatMedOuthosp> selectPatMedOuthospList(PatMedOuthosp query) {
+ return outhospDataFacade.selectList(query);
+ }
+
+ // ======================================================================
+ // 宸茶縼锛氬鎵樻ā鍧�
+ // ======================================================================
+
+ @Override
+ public int insertPatMedOuthosp(PatMedOuthosp patMedOuthosp) {
+ return outhospDataFacade.insert(patMedOuthosp);
+ }
+
+ @Override
+ public int updatePatMedOuthosp(PatMedOuthosp patMedOuthosp) {
+ return outhospDataFacade.update(patMedOuthosp);
+ }
+
+ @Override
+ public Set<String> selectExistingSerialnums(String admitDateStr, Collection<String> serialnums) {
+ return outhospDataFacade.selectExistingSerialnums(admitDateStr, serialnums);
+ }
+
+
+ // ======================================================================
+ // 鏈縼锛氬崟鎮h�呮寜闇�闅忚锛堥�愬瓧鏉ヨ嚜鍩虹嚎 b25c3b51锛�
+ // ======================================================================
+
+ public Integer dealPatMedOuthosp(PatMedOuthosp patMedOuthosp, Integer visitTimeNum){
+ Integer num = 0;
+
+ //鏅畞 瀛樺湪鐩稿悓璇婃柇鐨勯棬璇婅褰曞垯鏂板鍐嶆闅忚,鍚﹀垯鏂板闅忚
+ if(ObjectUtils.isNotEmpty(patMedOuthosp.getOrgid()) &&
+ patMedOuthosp.getOrgid().equals("47255004333112711A1001")){
+ PatMedOuthosp patMedOuthospVo = new PatMedOuthosp();
+ List<PatMedOuthosp> patMedOuthosps = new ArrayList<>();
+ patMedOuthospVo.setOrgid(patMedOuthosp.getOrgid());
+ patMedOuthospVo.setPatid(patMedOuthosp.getPatid());
+ patMedOuthospVo.setIcd10code(patMedOuthosp.getIcd10code());
+ // 鍚屼竴涓偅鑰� + 鍚屼竴涓瘖鏂紝鍘嗗彶涓婂凡缁忔湁闂ㄨ瘖闅忚璁板綍锛堟帓闄ゆ湰娆″氨璇婏紝鏈鍦ㄨ皟鐢ㄥ墠宸茶惤搴擄級
+ patMedOuthosps = selectPatMedOuthospList(patMedOuthospVo);
+ Long currentId = patMedOuthosp.getId();
+ List<Long> ids = patMedOuthosps.stream().map(PatMedOuthosp::getId).filter(ObjectUtils::isNotEmpty)
+ .filter(id -> !id.equals(currentId))
+ .distinct()
+ .collect(Collectors.toList());
+ ServiceSubtaskEntity serviceSubtask = new ServiceSubtaskEntity();
+ //鏅畞 鍙瀛樺湪鐩稿悓璇婃柇銆佹偅鑰呯殑闂ㄨ瘖璁板綍鍒欏綋鍐嶆闅忚澶勭悊
+ serviceSubtask.setInhospids(ids);
+ serviceSubtask.setServiceType("3");
+ List<ServiceSubtask> serviceSubtasks = CollectionUtils.isEmpty(ids)
+ ? new ArrayList<>()
+ : serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtask);
+ if(CollectionUtils.isEmpty(serviceSubtasks)){
+ num = followUpByPatMedOuthosp(patMedOuthosp, visitTimeNum);
+ }else {
+ num = followUpAgainByPatMedOuthosp(patMedOuthosp, visitTimeNum, ids);
+ }
+ }else {
+ ServiceSubtaskEntity serviceSubtask = new ServiceSubtaskEntity();
+ serviceSubtask.setInhospid(patMedOuthosp.getId());
+ serviceSubtask.setServiceType("3");
+ serviceSubtask.setVisitCount(1);
+ List<ServiceSubtask> serviceSubtasks = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtask);
+ if(CollectionUtils.isEmpty(serviceSubtasks)){
+ num = followUpByPatMedOuthosp(patMedOuthosp, visitTimeNum);
+ }else {
+ num = followUpAgainByPatMedOuthosp(patMedOuthosp, visitTimeNum, null);
+ }
+ }
+ return num;
+ }
+
+ public Integer followUpByPatMedOuthosp(PatMedOuthosp patMedOuthosp, Integer visitTimeNum) {
+ // if(ObjectUtils.isEmpty(patMedOuthosp.getFudate())){
+ Date adminDate = patMedOuthosp.getAdmitdate();
+ Date fuDate = addDays(adminDate, visitTimeNum);
+ patMedOuthosp.setFudate(fuDate);
+ // }
+
+ PatArchive patArchive = patArchiveMapper.selectPatArchiveByPatid(patMedOuthosp.getPatid());
+
+ //鏍规嵁鎮h�呯瀹わ紝鑾峰彇璇ョ柧鐥呯殑闀挎湡浠诲姟
+ ServiceTaskdept serviceTaskdept = new ServiceTaskdept();
+ serviceTaskdept.setLongtask(1L);
+ serviceTaskdept.setDeptCode(patMedOuthosp.getDeptcode());
+ serviceTaskdept.setServiceType("3");
+ List<ServiceTaskdept> serviceTaskdeptList = serviceTaskdeptMapper.selectServiceTaskdeptList(serviceTaskdept);
+ if (CollectionUtils.isEmpty(serviceTaskdeptList) || serviceTaskdeptList.size() == 0) {
+ patMedOuthosp.setDeptcheckFlag("2");
+ patMedOuthosp.setRemark("閫氳繃閮ㄩ棬,娌℃湁鎵惧埌闂ㄨ瘖闅忚浠诲姟ID");
+ updatePatMedOuthosp(patMedOuthosp);
+ } else {
+ for (ServiceTaskdept serviceTaskdept1 : serviceTaskdeptList) {
+ writeInSubTask(serviceTaskdept1.getTaskId(), true, patMedOuthosp, patArchive, 1);
+ }
+ }
+
+ // 鏍规嵁鎮h�呯殑鐤剧梾锛岃幏鍙栬鐤剧梾鐨勯暱鏈熶换鍔�
+ // ServiceTaskdiag serviceTaskdiag = new ServiceTaskdiag();
+ // serviceTaskdiag.setLongtask(1L);
+ // serviceTaskdiag.setIcd10code(patMedOuthosp.getIcd10code());
+ // List<ServiceTaskdiag> serviceTaskdiags = serviceTaskdiagMapper.selectServiceTaskdiagList(serviceTaskdiag);
+ // //濡傛灉閮ㄩ棬妯℃澘涓虹┖锛堝皢deptIsNull璁剧疆涓簍rue锛�
+ // if (org.apache.commons.collections4.CollectionUtils.isEmpty(serviceTaskdiags) || serviceTaskdiags.size() == 0) {
+ // patMedOuthosp.setDiagcheckFlag("2");
+ // patMedOuthosp.setRemark("閫氳繃icd10,娌℃湁鎵惧埌闂ㄨ瘖闅忚浠诲姟ID");
+ // updatePatMedOuthosp(patMedOuthosp);
+ // } else {
+ // for (ServiceTaskdiag serviceTaskdept1 : serviceTaskdiags) {
+ // writeInSubTask(serviceTaskdept1.getTaskId(), true, patMedOuthosp, patArchive, 2);
+ // }
+ // }
+ return 1;
+ }
+
+ public Integer followUpAgainByPatMedOuthosp(PatMedOuthosp patMedOuthosp, Integer visitTimeNum, List<Long> inhospids) {
+ Date adminDate = patMedOuthosp.getAdmitdate();
+ Date newDate = addDays(adminDate, visitTimeNum);
+
+ Integer i = 0;
+ String deptcode = patMedOuthosp.getDeptcode();
+ Long patid = patMedOuthosp.getPatid();
+ //鏌ョ湅鏈夋棤杩涜涓殑浠诲姟
+ ServiceSubtaskEntity serviceSubtaskEntity0 = new ServiceSubtaskEntity();
+ serviceSubtaskEntity0.setOrgid(patMedOuthosp.getOrgid());
+ serviceSubtaskEntity0.setSendstates(new ArrayList<>(Arrays.asList(1L, 2L, 3L, 7L)));
+ serviceSubtaskEntity0.setPatid(patid);
+ //鏅畞鏍规嵁璇婃柇鍐嶆闅忚
+ if(ObjectUtils.isNotEmpty(patMedOuthosp.getOrgid()) &&
+ patMedOuthosp.getOrgid().equals("47255004333112711A1001") && !CollectionUtils.isEmpty(inhospids)){
+ serviceSubtaskEntity0.setInhospids(inhospids);
+ }else {
+ serviceSubtaskEntity0.setLeaveldeptcode(deptcode);
+ }
+
+ serviceSubtaskEntity0.setSort(0);
+ List<ServiceSubtask> serviceSubtaskList0 = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskEntity0);
+ if (!CollectionUtils.isEmpty(serviceSubtaskList0)) {
+ for (ServiceSubtask serviceSubtask0 : serviceSubtaskList0) {
+ serviceSubtask0.setSendstate(6L);
+ serviceSubtask0.setUpdateTime(new Date());
+ serviceSubtask0.setFinishtime(adminDate);
+ serviceSubtaskMapper.updateServiceSubtask(serviceSubtask0);
+
+ ServiceSubtask serviceSubtask1 = DtoConversionUtils.sourceToTarget(serviceSubtask0, ServiceSubtask.class);
+ serviceSubtask1.setId(null);
+ serviceSubtask1.setSendstate(2L);
+ serviceSubtask1.setUpid(serviceSubtask0.getId().intValue());
+ //鑰佹暟鎹殑visit_count鍙兘涓虹┖锛岄粯璁ゆ寜绗�1娆$畻
+ Integer visitCount = ObjectUtils.isEmpty(serviceSubtask0.getVisitCount()) ? 1 : serviceSubtask0.getVisitCount();
+ serviceSubtask1.setVisitCount(visitCount + 1);
+ serviceSubtask1.setVisitType(serviceSubtask0.getVisitType());
+ serviceSubtask1.setVisitDeptCode(serviceSubtask0.getVisitDeptCode());
+ serviceSubtask1.setVisitDeptName(serviceSubtask0.getVisitDeptName());
+ //鏂颁换鍔$瀹ゆ槸褰撳墠鍑洪櫌绉戝
+ serviceSubtask1.setLeaveldeptcode(patMedOuthosp.getDeptcode());
+ serviceSubtask1.setCreateTime(new Date());
+ serviceSubtask1.setUpdateTime(new Date());
+ serviceSubtask1.setFinishtime(null);
+ serviceSubtask1.setAdmindate(adminDate);
+
+ serviceSubtask1.setVisitTime(newDate);
+ serviceSubtask1.setLongSendTime(newDate);
+ i = i + serviceSubtaskMapper.insertServiceSubtask(serviceSubtask1);
+ }
+ } else {
+ //鏌ョ湅宸插畬鎴愮殑浠诲姟
+ // ServiceSubtaskEntity serviceSubtaskEntity = new ServiceSubtaskEntity();
+ // serviceSubtaskEntity0.setOrgid(patMedOuthosp.getOrgid());
+ // serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(6L)));
+ // serviceSubtaskEntity.setPatid(patid);
+ // serviceSubtaskEntity.setDeptcode(deptcode);
+ // serviceSubtaskEntity.setSort(0);
+ // List<ServiceSubtask> serviceSubtaskList = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskEntity);
+ // if(!CollectionUtils.isEmpty(serviceSubtaskList)){
+ // ServiceSubtask serviceSubtask = serviceSubtaskList.get(0);
+ // serviceSubtask.setSendstate(2L);
+ // serviceSubtask.setCreateTime(new Date());
+ // serviceSubtask.setUpdateTime(new Date());
+ //
+ // serviceSubtask.setVisitTime(newDate);
+ // serviceSubtask.setLongSendTime(newDate);
+ // i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtask);
+ // }
+ }
+ return i;
+ }
+
+ private void writeInSubTask(Long taskid, Boolean check, PatMedOuthosp patMedOuthosp, PatArchive patArchive, Integer type) {
+
+ ServiceTask st = new ServiceTask();
+ st.setTaskid(taskid);
+ st.setSendState(2L);
+ List<ServiceTask> serviceTasks = serviceTaskMapper.selectServiceTaskList(st);
+ if (org.apache.commons.collections4.CollectionUtils.isEmpty(serviceTasks)) {
+ log.info("璇ユ偅鑰呯柧鐥呴殢璁块暱鏈熶换鍔′笉瀛樺湪,浠诲姟ID涓猴細{}", taskid);
+ if (type == 1) patMedOuthosp.setDiagcheckFlag("2");
+ if (type == 2) patMedOuthosp.setDeptcheckFlag("2");
+ patMedOuthosp.setRemark("璇ユ偅鑰呴棬璇婇殢璁块暱鏈熶换鍔′笉瀛樺湪,浠诲姟ID涓�:" + taskid);
+ updatePatMedOuthosp(patMedOuthosp);
+ return;
+ }
+ ServiceTask serviceTask = serviceTasks.get(0);
+ //灏佽serviceSubtask
+ ServiceSubtask serviceSubtask = boxedServiceSubtask(serviceTask, patMedOuthosp, patArchive);
+ Integer i = 0;
+ //鍏堝垽鏂竴涓嬶紝鏄惁闇�瑕佹牎楠�
+ if (check) {
+ //鍦ㄦ柊澧炰箣鍓嶏紝鍏堥�氳繃鎮h�匢D锛宻endstate=2鏌ヨ涓�涓嬶紝鍦ㄦ墍鏈夐暱鏈熶换鍔′腑锛屾槸涓嶆槸杩樻湁璇ユ偅鑰呭緟鎵ц鐨勪换鍔★紝鏈夌殑璇�,姣旇緝涔嬪墠鐨別ndtime鏄惁灏忎簬褰撳墠鐨別ndtaime,濡傛灉涔嬪墠鐨勫皬浜庣幇鍦ㄧ殑锛屽垯鐩存帴灏嗕箣鍓嶇殑鍋滄帀锛堝師鍥犲啀鍏ラ櫌锛�
+ ServiceSubtaskEntity subtask = new ServiceSubtaskEntity();
+ subtask.setPatid(patArchive.getId());
+ subtask.setSendstate(2L);
+ subtask.setTaskid(taskid);
+ List<ServiceSubtask> selectServiceSubtaskList = serviceSubtaskMapper.selectServiceSubtaskList(subtask);
+ log.info("璇ユ偅鑰呭緟鎵ц鐨勪换鍔�:{}", CollectionUtils.isEmpty(selectServiceSubtaskList) ? null : selectServiceSubtaskList.size());
+ if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(selectServiceSubtaskList) && selectServiceSubtaskList.size() > 0) {
+ for (ServiceSubtask serviceSubtask1 : selectServiceSubtaskList) {
+ if (Objects.isNull(serviceSubtask1.getLongSendTime())) {
+ //涓嶆槸闀挎湡浠诲姟锛屼笉澶勭悊
+ continue;
+ }
+
+ //灏嗕箣鍓嶇殑鍋滄帀
+ serviceSubtask1.setSendstate(6L);
+ serviceSubtask1.setRemark("鎮h�呭凡缁忓洖闄㈠璇�");
+ serviceSubtask1.setResult("success");
+ serviceSubtask1.setFinishtime(new Date());
+ serviceSubtask1.setUpdateBy(serviceTask.getUpdateBy());
+ serviceSubtaskMapper.updateServiceSubtask(serviceSubtask1);
+ //閲嶆柊鏂板瀛愪换鍔�
+ i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtask);
+ }
+ } else {
+ if (StringUtils.isEmpty(serviceSubtask.getPhone())) {
+ serviceSubtask.setRemark("鎵嬫満鍙蜂负绌�");
+ serviceSubtask.setSendstate(4L);
+ serviceSubtask.setResult("error");
+ // serviceSubtask.setFinishtime(new Date());
+ }
+ serviceSubtask.setCreateBy(serviceTask.getCreateBy());
+ serviceSubtask.setCreateTime(new Date());
+ i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtask);
+ }
+ } else {
+ if (StringUtils.isEmpty(serviceSubtask.getPhone())) {
+ serviceSubtask.setRemark("鎵嬫満鍙蜂负绌�");
+ serviceSubtask.setSendstate(4L);
+ serviceSubtask.setResult("error");
+ // serviceSubtask.setFinishtime(new Date());
+
+ }
+ serviceSubtask.setCreateBy(serviceTask.getCreateBy());
+ serviceSubtask.setCreateTime(new Date());
+ i = serviceSubtaskMapper.insertServiceSubtask(serviceSubtask);
+ }
+ if (i == 1) {
+ //灏哻heck_flag鏀规垚1锛堝凡澶勭悊锛�
+ PatMedOuthosp patMedOuthosp1 = new PatMedOuthosp();
+ patMedOuthosp1.setId(patMedOuthosp.getId());
+ if (type == 1) patMedOuthosp1.setDiagcheckFlag("2");
+ if (type == 2) patMedOuthosp1.setDeptcheckFlag("2");
+ updatePatMedOuthosp(patMedOuthosp1);
+ } else {
+ //鐢熸垚瀛愪换鍔″け璐ワ紝
+ log.info("鐢熸垚瀛愪换鍔″け璐erviceSubtask鐨則askid涓猴細{},patid涓猴細{}", serviceSubtask.getTaskid(), serviceSubtask.getPatid());
+ PatMedOuthosp pmo = new PatMedOuthosp();
+ pmo.setGuid(patMedOuthosp.getGuid());
+ pmo.setSerialnum(patMedOuthosp.getSerialnum());
+ if (type == 1) pmo.setDiagcheckFlag("2");
+ if (type == 2) pmo.setDeptcheckFlag("2");
+ pmo.setRemark("鐢熸垚瀛愪换鍔″け璐�");
+ updatePatMedOuthosp(pmo);
+ }
+ }
+
+ public ServiceSubtask boxedServiceSubtask(ServiceTask serviceTask, PatMedOuthosp patMedOuthosp, PatArchive patArchive) {
+ ServiceSubtask serviceSubtask = DtoConversionUtils.sourceToTarget(serviceTask, ServiceSubtask.class);
+ serviceSubtask.setTaskid(serviceTask.getTaskid());
+ serviceSubtask.setOrgid(serviceTask.getOrgid());
+ serviceSubtask.setCampusid(serviceTask.getCampusid());
+ if (StringUtils.isNotEmpty(serviceTask.getLibtemplateid()))
+ serviceSubtask.setLibtemplateid(Long.valueOf(serviceTask.getLibtemplateid()));
+ serviceSubtask.setDrcode(patMedOuthosp.getDrcode());
+ serviceSubtask.setDrname(patMedOuthosp.getDrname());
+ serviceSubtask.setLeaveldeptcode(patMedOuthosp.getDeptcode());
+ serviceSubtask.setInhospid(patMedOuthosp.getId());
+ serviceSubtask.setHospno(patMedOuthosp.getOuthospno());
+ serviceSubtask.setLeaveldeptname(patMedOuthosp.getDeptname());
+ serviceSubtask.setTemplateid(serviceTask.getTemplateid());
+ serviceSubtask.setTemplatename(serviceTask.getTemplatename());
+ serviceSubtask.setPatid(patArchive.getId());
+ serviceSubtask.setSendname(patArchive.getName());
+ serviceSubtask.setSfzh(patArchive.getIdcardno());
+ serviceSubtask.setLeavediagname(patMedOuthosp.getDiagname());
+ serviceSubtask.setLeaveicd10code(patMedOuthosp.getIcd10code());
+ serviceSubtask.setSfzh(patArchive.getIdcardno());
+ serviceSubtask.setPhone(patArchive.getTelcode());
+ if (StringUtils.isBlank(patArchive.getTelcode())) serviceSubtask.setPhone(patArchive.getRelativetelcode());
+ serviceSubtask.setSex(patArchive.getSex());
+ serviceSubtask.setAge(patArchive.getAge());
+ serviceSubtask.setSendstate(2L);
+ serviceSubtask.setServiceType(serviceTask.getServiceType());
+ serviceSubtask.setPreachform(serviceTask.getPreachform());
+ serviceSubtask.setHospType("1");
+ serviceSubtask.setCreateTime(new Date());
+ serviceSubtask.setUpdateTime(new Date());
+ serviceSubtask.setUpdateBy(serviceTask.getUpdateBy());
+ serviceSubtask.setUpdateTime(new Date());
+ serviceSubtask.setVisitDeptCode(patMedOuthosp.getDeptcode());
+ serviceSubtask.setVisitDeptName(patMedOuthosp.getDeptname());
+ serviceSubtask.setUpdateTime(new Date());
+ serviceSubtask.setAdmindate(patMedOuthosp.getAdmitdate());
+ //璁剧疆鍙戦�佹椂闂�
+ if (serviceTask.getSendDay() == null) serviceTask.setSendDay(1L);
+ Date newDate = addDays(patMedOuthosp.getAdmitdate(), serviceTask.getSendDay().intValue());
+ if (patMedOuthosp.getFudate() != null) {
+ //濡傛灉闂ㄨ瘖琛ㄦ湁鎸囧畾闅忚鏃堕棿锛岄偅灏辩敤鎸囧畾鐨�
+ newDate = patMedOuthosp.getFudate();
+ }
+ serviceSubtask.setLongSendTime(newDate);
+ serviceSubtask.setVisitTime(newDate);
+ //鎮h�呭彂閫佹椂闂�
+ if (StringUtils.isNotEmpty(patArchive.getNotrequiredFlag()) && patArchive.getNotrequiredFlag().equals("1")) {
+ String remark = patArchive.getNotrequiredreason();
+ serviceSubtask.setRemark(remark);
+ serviceSubtask.setResult("error");
+ // serviceSubtask.setFinishtime(new Date());
+ //涓嶆墽琛�
+ serviceSubtask.setSendstate(4L);
+ }
+ return serviceSubtask;
+ }
+
+ private Date addDays(Date date, Integer days) {
+ if (days == null) {
+ days = 1;
+ }
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+ calendar.add(Calendar.DAY_OF_MONTH, days);
+ return calendar.getTime();
+ }
+}
diff --git a/smartor/src/main/java/com/smartor/service/impl/bridge/PublicityDataPortBridge.java b/smartor/src/main/java/com/smartor/service/impl/bridge/PublicityDataPortBridge.java
new file mode 100644
index 0000000..9943090
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/service/impl/bridge/PublicityDataPortBridge.java
@@ -0,0 +1,330 @@
+package com.smartor.service.impl.bridge;
+
+import com.ruoyi.common.core.service.PublicityDataPort;
+import com.ruoyi.common.core.service.dto.InHospPublicityRowDto;
+import com.ruoyi.common.core.service.dto.PublicityTaskMatchDto;
+import com.ruoyi.common.core.service.dto.VisitTaskRuleDto;
+import com.ruoyi.inhospvisit.domain.PatMedInhosp;
+import com.ruoyi.task.domain.ServiceTaskRule;
+import com.ruoyi.patarchive.mapper.PatArchiveMapper;
+import com.ruoyi.inhospvisit.api.InhospVisitFacade;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import com.ruoyi.common.core.domain.entity.PatArchive;
+import com.ruoyi.task.domain.ServiceTaskdept;
+import com.ruoyi.task.domain.ServiceTaskmedical;
+import com.ruoyi.task.mapper.ServiceTaskdeptMapper;
+import com.ruoyi.task.mapper.ServiceTaskmedicalMapper;
+
+/**
+ * 銆愯繃娓″疄鐜般�憑@link PublicityDataPort} 鍦� smartor 渚х殑妗ユ帴锛堝鏁欐ā鍧楃殑鏁版嵁鏉ユ簮锛夈��
+ *
+ * <h3>涓轰粈涔堥渶瑕佸畠</h3>
+ * {@code ruoyi-publicity} 瑕佽 {@code service_taskdept} / {@code service_taskmedical} /
+ * {@code pat_med_inhosp} / {@code pat_archive}锛屼絾杩欎簺琛ㄥ拰 Mapper 鍏ㄥ湪 smartor锛�
+ * 鑰� smartor 鍙堣渚濊禆 publicity锛堝畠璐熻矗瑙﹀彂瀹f暀锛夆啋 鐩存帴渚濊禆浼氬惊鐜��
+ * 鎵�浠ユ帴鍙d笅娌夊埌 ruoyi-common锛屽疄鐜板湪杩欓噷銆�
+ *
+ * <h3>鈿狅笍 鏈被蹇呴』淇濇寔"绾惉杩�"</h3>
+ * 鍙仛<b>瀛楁鏄犲皠</b>涓�<b>杞彂</b>锛屼笉寰楀姞鍏ュ幓閲嶃�佹帓搴忋�侀粯璁ゅ�艰ˉ榻愮瓑鏂伴�昏緫 鈥斺��
+ * 閭d簺璇箟鍦� {@code ruoyi-publicity} 鐨� {@code PublicityService} 閲岋紙閫愯鐓ф妱鍘熷疄鐜帮級銆�
+ *
+ * <h3>閫愭柟娉曟潵婧愶紙杩佺Щ鍓� {@code PatMedInhospServiceImpl#dealOutHospInfo}锛孈 b25c3b51锛�</h3>
+ * <table border="1">
+ * <tr><th>鏈被鏂规硶</th><th>鍘熷疄鐜颁綅缃�</th></tr>
+ * <tr><td>{@link #findInHospForPublicity}</td><td>L325-329锛堢瀹わ級銆丩376-379锛堢梾鍖猴級</td></tr>
+ * <tr><td>{@link #findDeptPublicityTaskIds}</td><td>L347-353锛坉eptType=1锛夈�丩390-396锛坉eptType=2锛�</td></tr>
+ * <tr><td>{@link #findMedicalPublicityTaskIds}</td><td>L424-434</td></tr>
+ * <tr><td>{@link #existsPatArchive}</td><td>L338-344銆丩382-388</td></tr>
+ * <tr><td>{@link #updatePublicityFlag}</td><td>L340-342 / L357-359 / L367-370锛堢瀹わ級銆丩384-386 / L400-402锛堢梾鍖猴級</td></tr>
+ * </table>
+ *
+ * <h3>灏嗘潵鍔ㄤ綔</h3>
+ * 鑻ュ皢鏉ュ鏁欎笌闅忚閮芥敹杩涘悓涓�涓�"闅忚骞冲彴妯″潡"锛屾垨 smartor 涓嶅啀渚濊禆 publicity锛�
+ * 鏈被鍙暣浣撳垹闄ゅ苟鎶婂疄鐜版尓杩涙柊妯″潡 鈥斺�� 鎺ュ彛涓嶅彉锛岃皟鐢ㄦ柟闆舵敼鍔ㄣ��
+ *
+ * @see PublicityDataPort
+ */
+@Slf4j
+@Component
+public class PublicityDataPortBridge implements PublicityDataPort {
+
+ /**
+ * 鍏佽鐨� check_flag 鍒楀悕锛堢櫧鍚嶅崟锛屾嫾杩� SQL 鐨勬槸甯搁噺锛屼笉鍋氬瓧绗︿覆鎷兼帴锛岄伩鍏嶆敞鍏ワ級
+ */
+ private static final Set<String> ALLOWED_CHECK_FLAG_COLUMNS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("in_deptcheck_flag", "in_wardcheck_flag")));
+
+ @Autowired
+ private InhospVisitFacade inhospVisitFacade;
+
+ @Autowired
+ private PatArchiveMapper patArchiveMapper;
+
+ @Autowired
+ private ServiceTaskdeptMapper serviceTaskdeptMapper;
+
+ @Autowired
+ private ServiceTaskmedicalMapper serviceTaskmedicalMapper;
+
+ /**
+ * 浠诲姟鎵ц瑙勫垯鐨勫彧璇绘煡璇紙鍘� {@code addSubTaskByRule} L1707 鐢級銆�
+ * <p>
+ * 铏界劧鏈鍙e悕涔変笂鏈嶅姟瀹f暀锛屼絾 {@link PublicityDataPort#findTaskRule} 鏈嶅姟鐨勬槸
+ * 鍑洪櫌闅忚鐨勮鍒欑紪鎺� 鈥斺�� 瑙佹帴鍙d笂鐨勮鏄庛��
+ */
+ @Autowired
+ private com.ruoyi.task.mapper.ServiceTaskRuleMapper serviceTaskRuleMapper;
+
+ /**
+ * 鎵湪闄㈡偅鑰呫��
+ * <p>
+ * 鍘熷疄鐜颁袱娈垫煡璇㈢殑鍏ュ弬锛�
+ * <pre>
+ * // 绉戝缁村害锛圠325-329锛�
+ * PatMedInhosp pmks = new PatMedInhosp();
+ * pmks.setDeptcheckFlag("0"); pmks.setInhospstate("1"); pmks.setFuflag("1");
+ *
+ * // 鐥呭尯缁村害锛圠376-379锛�
+ * pmks.setInDeptcheckFlag(null); pmks.setInWardcheckFlag("0"); pmks.setDeptcheckFlag(null);
+ * </pre>
+ * 鈿狅笍 娉ㄦ剰鐥呭尯缁村害閭f鏄�<b>澶嶇敤鍚屼竴涓� pmks 瀵硅薄</b>骞舵敼瀛楁锛屾墍浠�
+ * {@code inhospstate="1"} 涓� {@code fuflag="1"} 鏄竴鐩寸暀鐫�鐨勩��
+ * 杩欓噷鐢ㄧ櫧鍚嶅崟鍙傛暟鍖哄垎涓や釜缁村害锛屽苟淇濇寔"涓ゆ鐙珛鏌ヨ"銆�
+ */
+ @Override
+ public List<InHospPublicityRowDto> findInHospForPublicity(String checkFlagColumn) {
+ if (!ALLOWED_CHECK_FLAG_COLUMNS.contains(checkFlagColumn)) {
+ log.warn("銆愬鏁櫬疯繃娓℃ˉ銆慺indInHospForPublicity 鏀跺埌闈炴硶鍒楀悕銆寋}銆嶏紝鍙厑璁� {}锛岃繑鍥炵┖鍒楄〃", checkFlagColumn, ALLOWED_CHECK_FLAG_COLUMNS);
+ return Collections.emptyList();
+ }
+ PatMedInhosp query = new PatMedInhosp();
+ if ("in_wardcheck_flag".equals(checkFlagColumn)) {
+ // 鐥呭尯缁村害锛氬彧鎸� in_wardcheck_flag 杩囨护锛屽彟涓や釜缁村害缃� null锛堜笌鍘熷疄鐜颁竴鑷达級
+ query.setInDeptcheckFlag(null);
+ query.setInWardcheckFlag("0");
+ query.setDeptcheckFlag(null);
+ } else {
+ // 绉戝缁村害
+ query.setDeptcheckFlag("0");
+ }
+ query.setInhospstate("1");
+ query.setFuflag("1");
+
+ List<PatMedInhosp> rows = inhospVisitFacade.selectPatMedInhospList(query);
+ if (CollectionUtils.isEmpty(rows)) {
+ return Collections.emptyList();
+ }
+ List<InHospPublicityRowDto> out = new ArrayList<>(rows.size());
+ for (PatMedInhosp r : rows) {
+ out.add(toRow(r));
+ }
+ return out;
+ }
+
+ @Override
+ public List<PublicityTaskMatchDto> findDeptPublicityTaskIds(String deptCode, String deptType, String orgid, Long inhospid) {
+ ServiceTaskdept query = new ServiceTaskdept();
+ query.setLongtask(1L);
+ query.setDeptCode(deptCode);
+ query.setDeptType(deptType);
+ query.setServiceType("17");
+ query.setOrgid(orgid);
+ List<ServiceTaskdept> tasks = serviceTaskdeptMapper.selectServiceTaskdeptList(query);
+ if (CollectionUtils.isEmpty(tasks)) {
+ return Collections.emptyList();
+ }
+ List<PublicityTaskMatchDto> out = new ArrayList<>(tasks.size());
+ for (ServiceTaskdept t : tasks) {
+ PublicityTaskMatchDto dto = new PublicityTaskMatchDto();
+ dto.setTaskId(t.getTaskId());
+ dto.setInhospid(inhospid);
+ out.add(dto);
+ }
+ return out;
+ }
+
+ /**
+ * 鎸夎嵂鍝佺紪鐮� + 鍚嶇О + 鍏徃鏌ラ暱鏈熷鏁欎换鍔★紙鍘� L424-434锛夈��
+ * <p>
+ * 鈿狅笍 <b>涓変釜瀛楁閮界収鍘熸牱閫忎紶锛岀粷涓嶅仛 null/绌轰覆褰掍竴</b>锛�
+ * {@code ServiceTaskmedicalMapper.xml} 鐨勬潯浠舵槸
+ * {@code <if test="medicalName != null and medicalName != ''">} 涓�
+ * {@code <if test="medicalCompany != null and medicalCompany != ''">} 鈥斺��
+ * <b>绌轰覆涓� null 閮戒細璺宠繃璇ユ潯浠�</b>锛屼絾璇箟鏉ユ簮涓嶅悓锛堣秺鐣屽垎鏀紶绌轰覆銆佹甯稿垎鏀紶 null锛夛紝
+ * 杩欓噷淇濈暀鍘熸牱鎵嶈兘淇濊瘉"鍝簺鏉′欢鐢熸晥"涓庤縼绉诲墠瀹屽叏涓�鑷淬��
+ */
+ @Override
+ public List<PublicityTaskMatchDto> findMedicalPublicityTaskIds(String medicalCode, String medicalName, String medicalCompany, Long inhospid) {
+ ServiceTaskmedical query = new ServiceTaskmedical();
+ query.setMedicalCode(medicalCode);
+ query.setMedicalName(medicalName);
+ query.setMedicalCompany(medicalCompany);
+ List<ServiceTaskmedical> tasks = serviceTaskmedicalMapper.selectServiceTaskmedicalList(query);
+ if (CollectionUtils.isEmpty(tasks)) {
+ return Collections.emptyList();
+ }
+ List<PublicityTaskMatchDto> out = new ArrayList<>(tasks.size());
+ for (ServiceTaskmedical t : tasks) {
+ PublicityTaskMatchDto dto = new PublicityTaskMatchDto();
+ dto.setTaskId(t.getTaskId());
+ dto.setInhospid(inhospid);
+ out.add(dto);
+ }
+ return out;
+ }
+
+ /**
+ * 鎮h�呮。妗堟槸鍚﹀瓨鍦ㄣ��
+ * <p>
+ * 鈿狅笍 鍘熷疄鐜板彇鐨勬槸<b>瀹屾暣瀵硅薄</b>鐒跺悗鍒� null锛圠338-344 / L382-388锛夛紝
+ * 杩欓噷鍙垽瀛樺湪鎬� 鈥斺�� 瀹f暀灞傜‘瀹炲彧鐢ㄥ埌 null 鍒ゆ柇
+ * 锛堢湡姝g殑鎮h�呬俊鎭~鍏呭彂鐢熷湪 inhospvisit 缁勮瀛愪换鍔℃椂锛夈��
+ * 杩欐槸<b>鏈夋剰鐨勭瓑浠风畝鍖�</b>锛氭妸"鍙栧畬鏁村璞�"闄嶇骇涓�"鍙� existence"锛�
+ * 涓嶅奖鍝嶄换浣曞垎鏀蛋鍚戯紝浣嗙渷鎺変竴娆″ぇ瀛楁鏌ヨ銆�
+ * <p>
+ * 鑻ュ皢鏉ュ彂鐜� {@code selectPatArchiveByPatid} 鍐呴儴杩樻湁鍒殑鍓綔鐢紙渚嬪缂撳瓨鍐欏叆锛夛紝
+ * 闇�瑕佸湪 {@code verify_inhospvisit_semantics.py} 閲岃ˉ涓�鏉℃柇瑷�銆�
+ */
+ @Override
+ public boolean existsPatArchive(Long patid) {
+ if (patid == null) {
+ return false;
+ }
+ PatArchive archive;
+ try {
+ archive = patArchiveMapper.selectPatArchiveByPatid(patid);
+ } catch (Exception e) {
+ log.warn("銆愬鏁櫬疯繃娓℃ˉ銆戞煡鎮h�呮。妗堝け璐ワ紝鎸夈�屼笉瀛樺湪銆嶅鐞嗐�俻atid={}锛屽師鍥�={}", patid, e.toString());
+ return false;
+ }
+ return Objects.nonNull(archive);
+ }
+
+ /**
+ * 鍥炲啓瀹f暀鏍囧織浣� + 鎸夐渶鍐� long_task_reason銆�
+ * <p>
+ * 鈿狅笍 璇箟瑕佺偣锛堢収鎶勫師瀹炵幇锛屽埆"椤烘墜淇�"锛夛細
+ * <ol>
+ * <li>{@code appendMode=true} 鏃讹紝鍘熷疄鐜板湪鍐欎箣鍓嶄細<b>鍏堟寜 inhospid 閲嶆煡涓�娆¤褰�</b>
+ * 鎷� {@code long_task_reason} 鍐嶆嫾鎺ワ紝杩欓噷涔熺収鍋氾紙閬垮厤鐢ㄨ皟鐢ㄦ柟鎵嬮噷鍙兘杩囨湡鐨勫�硷級锛�</li>
+ * <li>鎷兼帴鏂瑰紡鏄� {@code 鏃у�� + 鏂版枃妗坿锛�<b>涓嶅垽鏂棫鍊兼槸鍚︿负 null</b>
+ * 鈥斺�� 鏃у�间负 null 鏃朵細鐪熺殑鎷煎嚭 {@code "null璇ユ偅鑰呮墍鍦ㄧ梾鍖�..."}锛岃繖鏄師琛屼负锛屼繚鐣欙紱</li>
+ * <li>{@code appendMode=false} 鏃剁洿鎺ヨ鐩栵紙瀵瑰簲銆屾偅鑰呭熀鏈俊鎭负绌恒�嶃�屼汉鍛�...澶勭悊鍑哄紓甯镐簡銆嶄袱涓垎鏀級锛�</li>
+ * <li>{@code reason=null} 鏃跺彧鍐� flag銆佷笉鍔� long_task_reason銆�</li>
+ * </ol>
+ */
+ @Override
+ public boolean updatePublicityFlag(Long inhospid, String flagColumn, String flagValue, String reason, boolean appendMode) {
+ if (!ALLOWED_CHECK_FLAG_COLUMNS.contains(flagColumn)) {
+ log.warn("銆愬鏁櫬疯繃娓℃ˉ銆憉pdatePublicityFlag 鏀跺埌闈炴硶鍒楀悕銆寋}銆嶏紝鍙厑璁� {}锛屾斁寮冩洿鏂般�俰nhospid={}", flagColumn, ALLOWED_CHECK_FLAG_COLUMNS, inhospid);
+ return false;
+ }
+ if (inhospid == null) {
+ log.warn("銆愬鏁櫬疯繃娓℃ˉ銆憉pdatePublicityFlag 缂哄皯 inhospid锛屾斁寮冩洿鏂般�俢olumn={}", flagColumn);
+ return false;
+ }
+
+ PatMedInhosp update = new PatMedInhosp();
+ update.setInhospid(inhospid);
+ if ("in_deptcheck_flag".equals(flagColumn)) {
+ update.setInDeptcheckFlag(flagValue);
+ } else {
+ update.setInWardcheckFlag(flagValue);
+ }
+
+ if (reason != null) {
+ if (appendMode) {
+ // 鍘熷疄鐜帮細鍏堥噸鏌ヤ竴娆℃嬁 long_task_reason锛屽啀鎷兼帴鍚庡啓鍥烇紙涓嶅垽 null锛�
+ PatMedInhosp existing = inhospVisitFacade.selectPatMedInhospByInhospid(inhospid);
+ String oldReason = existing == null ? null : existing.getLongTaskReason();
+ update.setLongTaskReason(oldReason + reason);
+ } else {
+ update.setLongTaskReason(reason);
+ }
+ }
+
+ return inhospVisitFacade.updatePatMedInhosp(update) > 0;
+ }
+
+ /**
+ * 鎸夊瓧娈垫洿鏂帮紙鍙竴娆″啓澶氫釜 flag锛夆�斺�� 渚涘嚭闄㈤殢璁跨紪鎺掑眰鐨� 3 涓� {@code *ForPatient} 浣跨敤銆�
+ * <p>
+ * 璇箟涓庡師瀹炵幇瀹屽叏涓�鑷达細鍘熶唬鐮佹槸"鍦ㄥ璞′笂 set 鍑犱釜瀛楁锛岀劧鍚�
+ * {@code inhospVisitFacade.updatePatMedInhosp(obj)}"锛�
+ * 鑰� {@code updatePatMedInhosp} 鐨� XML 瀵规瘡涓瓧娈靛悇鑷� {@code <if test="xxx != null">}锛�
+ * 鎵�浠�<b>鍙湁闈� null 瀛楁鐢熸晥</b>銆傝繖閲岄�愬瓧娈垫惉杩愶紝null 涓�寰嬩笉璁俱��
+ */
+ @Override
+ public boolean updateVisitInhosp(com.ruoyi.common.core.service.dto.VisitInhospUpdateDto u) {
+ if (u == null || u.getInhospid() == null) {
+ log.warn("銆愰殢璁柯疯繃娓℃ˉ銆憉pdateVisitInhosp 缂哄皯 inhospid锛屾斁寮冩洿鏂般�倁={}", u);
+ return false;
+ }
+ PatMedInhosp update = new PatMedInhosp();
+ update.setInhospid(u.getInhospid());
+ update.setDeptcheckFlag(u.getDeptcheckFlag());
+ update.setWardcheckFlag(u.getWardcheckFlag());
+ update.setDiagcheckFlag(u.getDiagcheckFlag());
+ update.setInDeptcheckFlag(u.getInDeptcheckFlag());
+ update.setInWardcheckFlag(u.getInWardcheckFlag());
+ update.setScheduleCheckFlag(u.getScheduleCheckFlag());
+ update.setMedcheckFlag(u.getMedcheckFlag());
+ update.setLongTaskReason(u.getLongTaskReason());
+ update.setRemark(u.getRemark());
+ return inhospVisitFacade.updatePatMedInhosp(update) > 0;
+ }
+
+ // ==========================================================================
+ // 瀛楁鏄犲皠
+ // ==========================================================================
+
+ /**
+ * 鎸夌闄㈢瀹�/鐥呭尯鏌ヤ换鍔℃墽琛岃鍒欙紙鍘� {@code addSubTaskByRule} L1704-1707锛夈��
+ * <p>
+ * 鈿狅笍 璇ユ煡璇㈡渶澶氳繑鍥炰竴鏉� 鈥斺�� 鍘熷疄鐜扮洿鎺ュ彇鍗曚釜瀵硅薄锛岃繖閲屼篃鍙栫涓�鏉°��
+ */
+ @Override
+ public VisitTaskRuleDto findTaskRule(String leaveldeptcode, String leavehospitaldistrictcode) {
+ ServiceTaskRule ruleQuery = new ServiceTaskRule();
+ ruleQuery.setDeptcode(leaveldeptcode);
+ ruleQuery.setWardcode(leavehospitaldistrictcode);
+ ServiceTaskRule rule = serviceTaskRuleMapper.selectServiceTaskRuleByDeptOrWard(ruleQuery);
+ if (rule == null) {
+ return null;
+ }
+ VisitTaskRuleDto dto = new VisitTaskRuleDto();
+ dto.setId(rule.getId());
+ dto.setDeptRule(rule.getDeptRule());
+ dto.setWradRule(rule.getWradRule());
+ dto.setDiagRule(rule.getDiagRule());
+ dto.setDeptcode(rule.getDeptcode());
+ dto.setWardcode(rule.getWardcode());
+ dto.setOrgid(rule.getOrgid());
+ return dto;
+ }
+
+ private InHospPublicityRowDto toRow(PatMedInhosp r) {
+ InHospPublicityRowDto dto = new InHospPublicityRowDto();
+ dto.setInhospid(r.getInhospid());
+ dto.setPatid(r.getPatid());
+ dto.setOrgid(r.getOrgid());
+ dto.setDeptcode(r.getDeptcode());
+ dto.setHospitaldistrictcode(r.getHospitaldistrictcode());
+ dto.setLongTaskReason(r.getLongTaskReason());
+ dto.setMedicalCode(r.getMedicalCode());
+ dto.setMedicalName(r.getMedicalName());
+ dto.setMedicalCompany(r.getMedicalCompany());
+ return dto;
+ }
+}
--
Gitblit v1.9.3