From d9281d43e27ab6c510d390ddb26eaffc8ccc1add Mon Sep 17 00:00:00 2001
From: 陈昶聿 <chychen@nbjetron.com>
Date: 星期三, 11 十一月 2026 14:04:52 +0800
Subject: [PATCH] 妇幼-补充住院随访档案生成日志、完成事件及自检文件

---
 smartor/src/main/java/com/smartor/listener/InhospFollowupArchiveListener.java                |   42 +
 sql/pat_specific_archive_generate_log_and_source_20261111.sql                                |  105 ++++
 smartor/src/main/resources/mapper/smartor/PatSpecificArchiveGenerateLogMapper.xml            |   94 ++++
 doc/api/妇保接口文档.md                                                                            |  646 ++++++++++++++++++++++++++++
 smartor/src/main/java/com/smartor/domain/PatSpecificArchiveGenerateLog.java                  |   90 +++
 smartor/src/test/java/com/smartor/service/InhospFollowupArchiveLogicCheck.java               |  130 +++++
 ruoyi-common/src/main/java/com/ruoyi/common/core/event/FollowupCompletedEvent.java           |   46 ++
 ruoyi-task/src/main/java/com/ruoyi/task/event/FollowupCompletedEventPublisher.java           |   37 +
 smartor/src/main/java/com/smartor/mapper/PatSpecificArchiveGenerateLogMapper.java            |   41 +
 smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateLogServiceImpl.java |   74 +++
 smartor/src/main/java/com/smartor/service/IPatSpecificArchiveGenerateLogService.java         |   18 
 11 files changed, 1,323 insertions(+), 0 deletions(-)

diff --git "a/doc/api/\345\246\207\344\277\235\346\216\245\345\217\243\346\226\207\346\241\243.md" "b/doc/api/\345\246\207\344\277\235\346\216\245\345\217\243\346\226\207\346\241\243.md"
new file mode 100644
index 0000000..5724f39
--- /dev/null
+++ "b/doc/api/\345\246\207\344\277\235\346\216\245\345\217\243\346\226\207\346\241\243.md"
@@ -0,0 +1,646 @@
+# 濡囦繚鎺ュ彛鏂囨。锛堝绉� / 鍎跨妗f锛�
+
+> 鏈枃妗d粎鍖呭惈浠ヤ笅 8 涓帴鍙o細
+
+| 搴忓彿 | 妯″潡 | 鎺ュ彛 | 鏂规硶 | 璇存槑 |
+| --- | --- | --- | --- | --- |
+| 1 | 濡囩妗f | `/smartor/maternityArchive/selectPatMaternityArchiveList` | POST | 鏌ヨ濡囩妗f鍒楄〃 |
+| 2 | 濡囩妗f | `/smartor/maternityArchive/insertOrUpdateMaternityArchive` | POST | 鏂板鎴栦慨鏀瑰绉戞。妗� |
+| 3 | 濡囩妗f | `/smartor/maternityArchive/batchDelete` | POST | 鎵归噺鍒犻櫎濡囩妗f锛堝惈璇︽儏锛� |
+| 4 | 濡囩妗f璇︽儏 | `/smartor/maternityArchiveDetail/getInfo/{archiveid}` | GET | 鑾峰彇濡囩妗f璇︽儏 |
+| 5 | 鍎跨妗f | `/smartor/childArchive/selectPatChildArchiveList` | POST | 鏌ヨ鍎跨妗f鍒楄〃 |
+| 6 | 鍎跨妗f | `/smartor/childArchive/insertOrUpdateChildArchive` | POST | 鏂板鎴栦慨鏀瑰効绉戞。妗� |
+| 7 | 鍎跨妗f | `/smartor/childArchive/batchDelete` | POST | 鎵归噺鍒犻櫎鍎跨妗f锛堝惈璇︽儏锛� |
+| 8 | 鍎跨妗f璇︽儏 | `/smartor/childArchiveDetail/getInfo/{archiveid}` | GET | 鑾峰彇鍎跨妗f璇︽儏 |
+
+---
+
+## 涓�銆侀�氱敤璇存槑
+
+### 1.1 鏈嶅姟鍦板潃
+
+- 鍓嶇紑锛歚http://鏈嶅姟IP:绔彛`锛堥粯璁ゅ紑鍙戠幆澧冧负 `http://localhost:8080`锛�
+
+### 1.2 璁よ瘉鏂瑰紡
+
+- 鎵�鏈夋帴鍙e潎闇�鐧诲綍鍚庤皟鐢ㄣ��
+- 璇锋眰澶存惡甯︼細`Authorization: Bearer {token}`
+
+### 1.3 璇锋眰涓庡搷搴旀牸寮�
+
+- 璇锋眰浣擄細`Content-Type: application/json`
+- 鍒楄〃鎺ュ彛鍝嶅簲缁撴瀯锛圱ableDataInfo锛夛細
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+| --- | --- | --- |
+| total | long | 鎬昏褰曟暟 |
+| rows | array | 鏁版嵁鍒楄〃 |
+| code | int | 鐘舵�佺爜锛�200 涓烘垚鍔� |
+| msg | string | 鎻愮ず淇℃伅锛屽鈥滄煡璇㈡垚鍔熲�� |
+
+- 闈炲垪琛ㄦ帴鍙e搷搴旂粨鏋勶紙AjaxResult锛夛細
+
+| 瀛楁 | 绫诲瀷 | 璇存槑 |
+| --- | --- | --- |
+| code | int | 鐘舵�佺爜锛�200 涓烘垚鍔燂紝500 涓哄け璐� |
+| msg | string | 鎻愮ず淇℃伅锛屽鈥滄搷浣滄垚鍔熲�濄�佲�滄搷浣滃け璐モ�� |
+| data | object | 涓氬姟鏁版嵁锛堝彲鑳戒负绌猴級 |
+
+---
+
+## 浜屻�佸绉戞。妗堟帴鍙�
+
+### 2.1 鏌ヨ濡囩妗f鍒楄〃
+
+- **URL**锛歚POST /smartor/maternityArchive/selectPatMaternityArchiveList`
+- **璇存槑**锛氬垎椤垫煡璇㈠绉戞。妗堜富琛ㄥ垪琛紙鏈垹闄ゆ暟鎹� `del_flag = '0'`锛夈��
+
+**璇锋眰浣擄紙JSON锛屽叏閮ㄥ彲閫夛級**
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| pageNum | Integer | 鍚� | 椤电爜锛堝垎椤垫椂蹇呭~锛� |
+| pageSize | Integer | 鍚� | 姣忛〉鏉℃暟锛堝垎椤垫椂蹇呭~锛� |
+| archiveType | String | 鍚� | 妗f绫诲瀷锛�1 鏃╁瓡鍏崇埍锛�2 鍥寸粷缁忔湡MHI |
+| outhospno | String | 鍚� | 闂ㄨ瘖缂栧彿锛堢簿纭尮閰嶏級 |
+| inhospno | String | 鍚� | 浣忛櫌缂栧彿锛堢簿纭尮閰嶏級 |
+| serialnum | String | 鍚� | 娴佹按鍙凤紙绮剧‘鍖归厤锛� |
+| patid | Long | 鍚� | 鎮h�匢D |
+| patname | String | 鍚� | 鎮h�呭鍚嶏紙妯$硦鍖归厤锛� |
+| parentname | String | 鍚� | 瀹堕暱濮撳悕锛堟ā绯婂尮閰嶏級 |
+| birthdate | Date | 鍚� | 鍑虹敓鏃ユ湡 |
+| idcardno | String | 鍚� | 璇佷欢鍙风爜锛堢簿纭尮閰嶏級 |
+| phone | String | 鍚� | 鑱旂郴鐢佃瘽锛堢簿纭尮閰嶏級 |
+| diagTime | Date | 鍚� | 璇婃柇鏃堕棿 |
+| plannedFollowTime | Date | 鍚� | 鎷熼殢璁挎椂闂� |
+| followupCycleTimes | String | 鍚� | 闅忚鍛ㄦ湡(娆℃暟) |
+| sex | Long | 鍚� | 鎬у埆锛�1 鐢凤紝2 濂� |
+| doctorCode | String | 鍚� | 涓绘不鍖荤敓锛堢簿纭尮閰嶏級 |
+| doctorName | String | 鍚� | 涓绘不鍖荤敓濮撳悕锛堟ā绯婂尮閰嶏級 |
+| managementDoctorCode | String | 鍚� | 缁忕鍖荤敓锛堢簿纭尮閰嶏級 |
+| managementDoctorName | String | 鍚� | 缁忕鍖荤敓濮撳悕锛堟ā绯婂尮閰嶏級 |
+| deptcode | String | 鍚� | 绉戝缂栧彿锛堢簿纭尮閰嶏級 |
+| deptname | String | 鍚� | 绉戝鍚嶇О锛堟ā绯婂尮閰嶏級 |
+| wardcode | String | 鍚� | 鐥呭尯缂栧彿锛堢簿纭尮閰嶏級 |
+| wardname | String | 鍚� | 鐥呭尯鍚嶇О锛堟ā绯婂尮閰嶏級 |
+| icd10code | String | 鍚� | 璇婃柇ID锛堢簿纭尮閰嶏級 |
+| diagname | String | 鍚� | 璇婃柇鍚嶇О锛堟ā绯婂尮閰嶏級 |
+| pregnancySituation | String | 鍚� | 濡婂鎯呭喌 |
+| closeStatus | String | 鍚� | 缁撴鐘舵�� |
+| registerUser | String | 鍚� | 鐧昏浜哄憳 |
+| orgid | String | 鍚� | 鍖婚櫌鏈烘瀯ID锛堝悗绔寜鐧诲綍鐢ㄦ埛鑷姩娉ㄥ叆锛� |
+| campusid | String | 鍚� | 闄㈠尯ID锛堝悗绔寜鐧诲綍鐢ㄦ埛鑷姩娉ㄥ叆锛� |
+| params.beginTime | String | 鍚� | 寤烘。鏃堕棿鑼冨洿寮�濮嬶紝鏍煎紡 yyyy-MM-dd |
+| params.endTime | String | 鍚� | 寤烘。鏃堕棿鑼冨洿缁撴潫锛屾牸寮� yyyy-MM-dd |
+
+**璇锋眰绀轰緥**
+
+```json
+{
+  "pageNum": 1,
+  "pageSize": 10,
+  "patname": "寮�",
+  "archiveType": "1"
+}
+```
+
+**鍝嶅簲绀轰緥**
+
+```json
+{
+  "code": 200,
+  "msg": "鏌ヨ鎴愬姛",
+  "total": 1,
+  "rows": [
+    {
+      "id": 1001,
+      "archiveType": "1",
+      "outhospno": "MZ20261001001",
+      "inhospno": null,
+      "serialnum": "LS20261001001",
+      "patid": 9001,
+      "patname": "寮犱笁",
+      "parentname": null,
+      "birthdate": "1995-06-01 00:00:00",
+      "idcardno": "330102199506010022",
+      "phone": "13800000000",
+      "diagTime": "2026-10-01 09:30:00",
+      "archiveTime": "2026-10-01 10:00:00",
+      "plannedFollowTime": "2026-11-01 00:00:00",
+      "followupCycleTimes": "4",
+      "sex": 2,
+      "doctorCode": "D001",
+      "doctorName": "鏉庡尰鐢�",
+      "managementDoctorCode": "D002",
+      "managementDoctorName": "鐜嬪尰鐢�",
+      "deptcode": "FK",
+      "deptname": "濡囩",
+      "wardcode": null,
+      "wardname": null,
+      "icd10code": "O20.0",
+      "diagname": "鍏堝厗娴佷骇",
+      "pregnancySituation": "瀛�12鍛�",
+      "closeStatus": "0",
+      "registerUser": "鏉庡尰鐢�",
+      "orgid": "1",
+      "campusid": "1",
+      "delFlag": "0"
+    }
+  ]
+}
+```
+
+---
+
+### 2.2 鏂板鎴栦慨鏀瑰绉戞。妗�
+
+- **URL**锛歚POST /smartor/maternityArchive/insertOrUpdateMaternityArchive`
+- **璇存槑**锛氬悓鏃剁淮鎶ゅ绉戞。妗堜富琛ㄤ笌璇︽儏琛ㄣ��
+  - 涓昏〃鏈� `archiveid`锛堟垨璇︽儏鏈� `id` 涓旇兘鍙嶆煡锛変笖瀛樺湪鏃舵洿鏂帮紝鍚﹀垯鏂板銆�
+  - 杩斿洖 `data` 涓哄绉戞。妗堜富琛↖D銆�
+
+**璇锋眰浣擄紙JSON锛�**
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| id | Long | 鍚� | 濡囩妗f璇︽儏涓婚敭ID锛堟洿鏂拌鎯呮椂浼犲叆锛� |
+| archiveid | Long | 鍚� | 濡囩妗f涓昏〃ID锛堟洿鏂颁富琛ㄦ椂浼犲叆锛� |
+| archiveType | String | 鍚� | 妗f绫诲瀷锛�1 鏃╁瓡鍏崇埍锛�2 鍥寸粷缁忔湡MHI |
+| sourceType | String | 鍚� | 鏉ユ簮绫诲瀷锛�1 闂ㄨ瘖鎺ヨ瘖锛�2 浣忛櫌闅忚锛�3 鎵嬪伐鏂板 |
+| sourceBizId | Long | 鍚� | 鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID |
+| sourceBizNo | String | 鍚� | 鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙� |
+| sourceSubId | Long | 鍚� | 鏉ユ簮闅忚瀛愪换鍔D锛氫綇闄㈤殢璁跨敓鎴愭椂涓� service_subtask.id |
+| outhospno | String | 鍚� | 闂ㄨ瘖缂栧彿 |
+| inhospno | String | 鍚� | 浣忛櫌缂栧彿 |
+| serialnum | String | 鍚� | 娴佹按鍙� |
+| patid | Long | 鍚� | 鎮h�匢D |
+| patname | String | 鍚� | 鎮h�呭鍚� |
+| birthdate | Date | 鍚� | 鍑虹敓鏃ユ湡锛屾牸寮� yyyy-MM-dd HH:mm:ss |
+| idcardno | String | 鍚� | 璇佷欢鍙风爜 |
+| phone | String | 鍚� | 鑱旂郴鐢佃瘽 |
+| diagTime | Date | 鍚� | 璇婃柇鏃堕棿 |
+| archiveTime | Date | 鍚� | 寤烘。鏃堕棿 |
+| plannedFollowTime | Date | 鍚� | 鎷熼殢璁挎椂闂� |
+| sex | Long | 鍚� | 鎬у埆锛�1 鐢凤紝2 濂� |
+| doctorCode | String | 鍚� | 涓绘不鍖荤敓 |
+| doctorName | String | 鍚� | 涓绘不鍖荤敓濮撳悕 |
+| managementDoctorCode | String | 鍚� | 缁忕鍖荤敓 |
+| managementDoctorName | String | 鍚� | 缁忕鍖荤敓濮撳悕 |
+| deptcode | String | 鍚� | 绉戝缂栧彿 |
+| deptname | String | 鍚� | 绉戝鍚嶇О |
+| wardcode | String | 鍚� | 鐥呭尯缂栧彿 |
+| wardname | String | 鍚� | 鐥呭尯鍚嶇О |
+| icd10code | String | 鍚� | 璇婃柇ID |
+| diagname | String | 鍚� | 璇婃柇鍚嶇О |
+| pregnancySituation | String | 鍚� | 濡婂鎯呭喌 |
+| specificSituation | String | 鍚� | 鍏蜂綋鎯呭喌 |
+| handleSuggestion | String | 鍚� | 澶勭悊寤鸿 |
+| closeStatus | String | 鍚� | 缁撴鐘舵�� |
+| isRecordEstablished | String | 鍚� | 鏄惁寤哄唽锛�0 鍚︼紝1 鏄� |
+| dueDate | Date | 鍚� | 棰勪骇鏈� |
+| registerUser | String | 鍚� | 鐧昏浜哄憳 |
+| followupPeriod | String | 鍚� | 闅忚鍛ㄦ湡 |
+| followupCycleTimes | String | 鍚� | 闅忚鍛ㄦ湡(娆℃暟) |
+| lastMenstrualTime | Date | 鍚� | 鏈鏈堢粡 |
+| firstDoctorCode | String | 鍚� | 棣栬瘖鍖荤敓 |
+| firstDoctorName | String | 鍚� | 棣栬瘖鍖荤敓濮撳悕 |
+| contactPhone | String | 鍚� | 鑱旂郴浜鸿仈绯荤數璇� |
+| address | String | 鍚� | 灞呬綇鍦板潃 |
+| epEarlyPregnancyFollowupForm | String | 鍚� | 鏃╁瓡鍏崇埍-鏃╁瓡闅忚琛� |
+| mhiMenopauseFollowupSystemIssuesForm | String | 鍚� | 鍥寸粷缁忔湡MHI-鏇村勾鏈熼殢璁跨郴缁熼棶棰樿〃 |
+| mhiMhtInitialVisitMedicalRecordForm | String | 鍚� | 鍥寸粷缁忔湡MHI-MHT棣栬瘖鐥呭巻琛� |
+| mhiMhtFollowUpMedicalRecordForm | String | 鍚� | 鍥寸粷缁忔湡MHI-MHT澶嶈瘖鐥呭巻琛� |
+| mhiModifiedKuppermanScoringScaleForm | String | 鍚� | 鍥寸粷缁忔湡MHI-鏀硅壇Kupperman璇勫垎鏍囧噯琛� |
+| mhiMenopauseRatingScaleForm | String | 鍚� | 鍥寸粷缁忔湡MHI-鏇村勾鏈熻瘎瀹氶噺琛紙MRS锛� |
+| mhiPittsburghSleepQualityIndexForm | String | 鍚� | 鍥寸粷缁忔湡MHI-鍖瑰吂鍫$潯鐪犺川閲忔寚鏁伴噺琛紙PSQI锛� |
+| remark | String | 鍚� | 澶囨敞 |
+| orgid | String | 鍚� | 鍖婚櫌鏈烘瀯ID锛堝悗绔寜鐧诲綍鐢ㄦ埛鑷姩瑕嗙洊锛� |
+| campusid | String | 鍚� | 闄㈠尯ID锛堝悗绔寜鐧诲綍鐢ㄦ埛鑷姩瑕嗙洊锛� |
+| delFlag | String | 鍚� | 鍒犻櫎鏍囧織锛�0 鏈垹闄わ紝1 宸插垹闄わ紙榛樿 0锛� |
+
+**璇锋眰绀轰緥锛堟柊澧烇級**
+
+```json
+{
+  "archiveType": "1",
+  "patid": 9001,
+  "patname": "寮犱笁",
+  "birthdate": "1995-06-01 00:00:00",
+  "idcardno": "330102199506010022",
+  "phone": "13800000000",
+  "diagTime": "2026-10-01 09:30:00",
+  "archiveTime": "2026-10-01 10:00:00",
+  "sex": 2,
+  "deptcode": "FK",
+  "deptname": "濡囩",
+  "pregnancySituation": "瀛�12鍛�",
+  "closeStatus": "0"
+}
+```
+
+**鍝嶅簲绀轰緥**
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": 1001
+}
+```
+
+---
+
+### 2.3 鎵归噺鍒犻櫎濡囩妗f
+
+- **URL**锛歚POST /smartor/maternityArchive/batchDelete`
+- **璇存槑**锛氭寜涓昏〃ID鎵归噺鍒犻櫎濡囩妗f锛屽悓鏃堕�昏緫鍒犻櫎瀵瑰簲鐨勫绉戞。妗堣鎯呰〃鏁版嵁锛坄del_flag` 缃负 1锛夛紝涓ゆ鍦ㄥ悓涓�浜嬪姟涓��
+
+**璇锋眰浣擄紙JSON锛�**
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| ids | Long[] | 鏄� | 濡囩妗f涓昏〃ID鏁扮粍 |
+
+**璇锋眰绀轰緥**
+
+```json
+[1001, 1002, 1003]
+```
+
+**鍝嶅簲绀轰緥**
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛"
+}
+```
+
+---
+
+### 2.4 鑾峰彇濡囩妗f璇︽儏
+
+- **URL**锛歚GET /smartor/maternityArchiveDetail/getInfo/{archiveid}`
+- **璇存槑**锛氭寜妗f涓昏〃ID鏌ヨ濡囩妗f璇︽儏锛堟湭鍒犻櫎鏁版嵁 `del_flag = '0'`锛夛紝杩斿洖绗竴鏉¤鎯呰褰曪紱鏃犳暟鎹椂 `data` 涓� `null`銆�
+
+**璺緞鍙傛暟**
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| archiveid | Long | 鏄� | 濡囩妗f涓昏〃ID锛坄pat_maternity_archive.id`锛� |
+
+**鍝嶅簲绀轰緥**
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "id": 5001,
+    "archiveid": 1001,
+    "archiveType": "1",
+    "sourceType": "1",
+    "outhospno": "MZ20261001001",
+    "inhospno": null,
+    "serialnum": "LS20261001001",
+    "patid": 9001,
+    "patname": "寮犱笁",
+    "birthdate": "1995-06-01 00:00:00",
+    "idcardno": "330102199506010022",
+    "phone": "13800000000",
+    "diagTime": "2026-10-01 09:30:00",
+    "archiveTime": "2026-10-01 10:00:00",
+    "plannedFollowTime": "2026-11-01 00:00:00",
+    "sex": 2,
+    "doctorCode": "D001",
+    "doctorName": "鏉庡尰鐢�",
+    "managementDoctorCode": "D002",
+    "managementDoctorName": "鐜嬪尰鐢�",
+    "deptcode": "FK",
+    "deptname": "濡囩",
+    "wardcode": null,
+    "wardname": null,
+    "icd10code": "O20.0",
+    "diagname": "鍏堝厗娴佷骇",
+    "pregnancySituation": "瀛�12鍛�",
+    "specificSituation": "鍏蜂綋鎯呭喌",
+    "handleSuggestion": "娉ㄦ剰浼戞伅",
+    "closeStatus": "0",
+    "isRecordEstablished": "1",
+    "dueDate": "2027-03-20 00:00:00",
+    "registerUser": "鏉庡尰鐢�",
+    "followupPeriod": "姣忔湀",
+    "followupCycleTimes": "4",
+    "lastMenstrualTime": "2026-06-10 00:00:00",
+    "firstDoctorCode": "D001",
+    "firstDoctorName": "鏉庡尰鐢�",
+    "contactPhone": "13900000000",
+    "address": "鏉窞甯傝タ婀栧尯",
+    "orgid": "1",
+    "campusid": "1",
+    "delFlag": "0"
+  }
+}
+```
+
+> 杩斿洖瀵硅薄 `data` 涓哄绉戞。妗堣鎯呭璞★紝瀛楁璇存槑鍚� 2.2 璇锋眰浣撳瓧娈点��
+
+---
+
+## 涓夈�佸効绉戞。妗堟帴鍙�
+
+### 3.1 鏌ヨ鍎跨妗f鍒楄〃
+
+- **URL**锛歚POST /smartor/childArchive/selectPatChildArchiveList`
+- **璇存槑**锛氬垎椤垫煡璇㈠効绉戞。妗堜富琛ㄥ垪琛紙鏈垹闄ゆ暟鎹� `del_flag = '0'`锛夈��
+
+**璇锋眰浣擄紙JSON锛屽叏閮ㄥ彲閫夛級**
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| pageNum | Integer | 鍚� | 椤电爜锛堝垎椤垫椂蹇呭~锛� |
+| pageSize | Integer | 鍚� | 姣忛〉鏉℃暟锛堝垎椤垫椂蹇呭~锛� |
+| archiveType | String | 鍚� | 妗f绫诲瀷锛�1 钀ュ吇鎬х柧鐥咃紝2 瀛︿範鍥伴毦锛�3 楂樺嵄鍎夸笓妗� |
+| outhospno | String | 鍚� | 闂ㄨ瘖缂栧彿锛堢簿纭尮閰嶏級 |
+| inhospno | String | 鍚� | 浣忛櫌缂栧彿锛堢簿纭尮閰嶏級 |
+| serialnum | String | 鍚� | 娴佹按鍙凤紙绮剧‘鍖归厤锛� |
+| patid | Long | 鍚� | 鎮h�匢D |
+| patname | String | 鍚� | 鎮h�呭鍚嶏紙妯$硦鍖归厤锛� |
+| parentname | String | 鍚� | 瀹堕暱濮撳悕锛堟ā绯婂尮閰嶏級 |
+| birthdate | Date | 鍚� | 鍑虹敓鏃ユ湡 |
+| idcardno | String | 鍚� | 璇佷欢鍙风爜锛堢簿纭尮閰嶏級 |
+| phone | String | 鍚� | 鑱旂郴鐢佃瘽锛堢簿纭尮閰嶏級 |
+| diagTime | Date | 鍚� | 璇婃柇鏃堕棿 |
+| plannedFollowTime | Date | 鍚� | 鎷熼殢璁挎椂闂� |
+| followupCycleTimes | String | 鍚� | 闅忚鍛ㄦ湡(娆℃暟) |
+| sex | Long | 鍚� | 鎬у埆锛�1 鐢凤紝2 濂� |
+| doctorCode | String | 鍚� | 涓绘不鍖荤敓锛堢簿纭尮閰嶏級 |
+| doctorName | String | 鍚� | 涓绘不鍖荤敓濮撳悕锛堟ā绯婂尮閰嶏級 |
+| managementDoctorCode | String | 鍚� | 缁忕鍖荤敓锛堢簿纭尮閰嶏級 |
+| managementDoctorName | String | 鍚� | 缁忕鍖荤敓濮撳悕锛堟ā绯婂尮閰嶏級 |
+| deptcode | String | 鍚� | 绉戝缂栧彿锛堢簿纭尮閰嶏級 |
+| deptname | String | 鍚� | 绉戝鍚嶇О锛堟ā绯婂尮閰嶏級 |
+| wardcode | String | 鍚� | 鐥呭尯缂栧彿锛堢簿纭尮閰嶏級 |
+| wardname | String | 鍚� | 鐥呭尯鍚嶇О锛堟ā绯婂尮閰嶏級 |
+| icd10code | String | 鍚� | 璇婃柇ID锛堢簿纭尮閰嶏級 |
+| diagname | String | 鍚� | 璇婃柇鍚嶇О锛堟ā绯婂尮閰嶏級 |
+| closeStatus | String | 鍚� | 缁撴鐘舵�� |
+| registerUser | String | 鍚� | 鐧昏浜哄憳 |
+| orgid | String | 鍚� | 鍖婚櫌鏈烘瀯ID锛堝悗绔寜鐧诲綍鐢ㄦ埛鑷姩娉ㄥ叆锛� |
+| campusid | String | 鍚� | 闄㈠尯ID锛堝悗绔寜鐧诲綍鐢ㄦ埛鑷姩娉ㄥ叆锛� |
+| params.beginTime | String | 鍚� | 寤烘。鏃堕棿鑼冨洿寮�濮嬶紝鏍煎紡 yyyy-MM-dd |
+| params.endTime | String | 鍚� | 寤烘。鏃堕棿鑼冨洿缁撴潫锛屾牸寮� yyyy-MM-dd |
+
+**璇锋眰绀轰緥**
+
+```json
+{
+  "pageNum": 1,
+  "pageSize": 10,
+  "patname": "鐜�",
+  "archiveType": "1"
+}
+```
+
+**鍝嶅簲绀轰緥**
+
+```json
+{
+  "code": 200,
+  "msg": "鏌ヨ鎴愬姛",
+  "total": 1,
+  "rows": [
+    {
+      "id": 2001,
+      "archiveType": "1",
+      "outhospno": "MZ20261001002",
+      "inhospno": null,
+      "serialnum": "LS20261001002",
+      "patid": 9002,
+      "patname": "鐜嬪皬瀹�",
+      "parentname": "鐜嬪己",
+      "birthdate": "2023-01-15 00:00:00",
+      "idcardno": null,
+      "phone": "13800000001",
+      "diagTime": "2026-10-01 09:00:00",
+      "archiveTime": "2026-10-01 09:30:00",
+      "plannedFollowTime": "2026-11-01 00:00:00",
+      "followupCycleTimes": "3",
+      "sex": 1,
+      "doctorCode": "D003",
+      "doctorName": "璧靛尰鐢�",
+      "managementDoctorCode": "D004",
+      "managementDoctorName": "瀛欏尰鐢�",
+      "deptcode": "EK",
+      "deptname": "鍎跨",
+      "wardcode": null,
+      "wardname": null,
+      "icd10code": "E44.0",
+      "diagname": "涓害钀ュ吇涓嶈壇",
+      "closeStatus": "0",
+      "registerUser": "璧靛尰鐢�",
+      "orgid": "1",
+      "campusid": "1",
+      "delFlag": "0"
+    }
+  ]
+}
+```
+
+---
+
+### 3.2 鏂板鎴栦慨鏀瑰効绉戞。妗�
+
+- **URL**锛歚POST /smartor/childArchive/insertOrUpdateChildArchive`
+- **璇存槑**锛氬悓鏃剁淮鎶ゅ効绉戞。妗堜富琛ㄤ笌璇︽儏琛ㄣ��
+  - 涓昏〃鏈� `archiveid`锛堟垨璇︽儏鏈� `id` 涓旇兘鍙嶆煡锛変笖瀛樺湪鏃舵洿鏂帮紝鍚﹀垯鏂板銆�
+  - 杩斿洖 `data` 涓哄効绉戞。妗堜富琛↖D銆�
+
+**璇锋眰浣擄紙JSON锛�**
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| id | Long | 鍚� | 鍎跨妗f璇︽儏涓婚敭ID锛堟洿鏂拌鎯呮椂浼犲叆锛� |
+| archiveid | Long | 鍚� | 鍎跨妗f涓昏〃ID锛堟洿鏂颁富琛ㄦ椂浼犲叆锛� |
+| archiveType | String | 鍚� | 妗f绫诲瀷锛�1 钀ュ吇鎬х柧鐥咃紝2 瀛︿範鍥伴毦锛�3 楂樺嵄鍎夸笓妗� |
+| sourceType | String | 鍚� | 鏉ユ簮绫诲瀷锛�1 闂ㄨ瘖鎺ヨ瘖锛�2 浣忛櫌闅忚锛�3 鎵嬪伐鏂板 |
+| sourceBizId | Long | 鍚� | 鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID |
+| sourceBizNo | String | 鍚� | 鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙� |
+| sourceSubId | Long | 鍚� | 鏉ユ簮闅忚瀛愪换鍔D锛氫綇闄㈤殢璁跨敓鎴愭椂涓� service_subtask.id |
+| outhospno | String | 鍚� | 闂ㄨ瘖缂栧彿 |
+| inhospno | String | 鍚� | 浣忛櫌缂栧彿 |
+| serialnum | String | 鍚� | 娴佹按鍙� |
+| patid | Long | 鍚� | 鎮h�匢D |
+| patname | String | 鍚� | 鎮h�呭鍚� |
+| parentname | String | 鍚� | 瀹堕暱濮撳悕 |
+| parentRelation | String | 鍚� | 瀹堕暱涓庡効绔ュ叧绯� |
+| parentPhone | String | 鍚� | 瀹堕暱鑱旂郴鐢佃瘽 |
+| parentIdcardno | String | 鍚� | 瀹堕暱璇佷欢鍙风爜 |
+| parentAddress | String | 鍚� | 瀹堕暱鑱旂郴鍦板潃 |
+| birthdate | Date | 鍚� | 鍑虹敓鏃ユ湡锛屾牸寮� yyyy-MM-dd HH:mm:ss |
+| idcardno | String | 鍚� | 璇佷欢鍙风爜 |
+| phone | String | 鍚� | 鑱旂郴鐢佃瘽 |
+| diagTime | Date | 鍚� | 璇婃柇鏃堕棿 |
+| archiveTime | Date | 鍚� | 寤烘。鏃堕棿 |
+| sex | Long | 鍚� | 鎬у埆锛�1 鐢凤紝2 濂� |
+| doctorCode | String | 鍚� | 涓绘不鍖荤敓 |
+| doctorName | String | 鍚� | 涓绘不鍖荤敓濮撳悕 |
+| managementDoctorCode | String | 鍚� | 缁忕鍖荤敓 |
+| managementDoctorName | String | 鍚� | 缁忕鍖荤敓濮撳悕 |
+| deptcode | String | 鍚� | 绉戝缂栧彿 |
+| deptname | String | 鍚� | 绉戝鍚嶇О |
+| wardcode | String | 鍚� | 鐥呭尯缂栧彿 |
+| wardname | String | 鍚� | 鐥呭尯鍚嶇О |
+| icd10code | String | 鍚� | 璇婃柇ID |
+| diagname | String | 鍚� | 璇婃柇鍚嶇О |
+| nutritionIcd10Code | String | 鍚� | 钀ュ吇鎬х柧鐥匢D |
+| nutritionDiagName | String | 鍚� | 钀ュ吇鎬х柧鐥呭悕绉� |
+| ndPhysicalMeasurements | String | 鍚� | 钀ュ吇鎬х柧鐥�-浣撴牸娴嬮噺 |
+| ndDietaryAssessment | String | 鍚� | 钀ュ吇鎬х柧鐥�-鑶抽璇勪及 |
+| ndInterventionProgram | String | 鍚� | 钀ュ吇鎬х柧鐥�-骞查鏂规 |
+| appointmentSituation | String | 鍚� | 瀛︿範鍥伴毦-棰勭害鎯呭喌 |
+| ldLearningAbilityAssessment | String | 鍚� | 瀛︿範鍥伴毦-瀛︿範鑳藉姏璇勪及 |
+| ldBehavioralAssessment | String | 鍚� | 瀛︿範鍥伴毦-琛屼负璇勪及 |
+| ldInterventionTrainingRecord | String | 鍚� | 瀛︿範鍥伴毦-骞查璁粌璁板綍 |
+| highRiskChildType | String | 鍚� | 楂樺嵄鍎夸笓妗�-楂樺嵄鍎垮垎绫� |
+| highRiskChildName | String | 鍚� | 楂樺嵄鍎夸笓妗�-楂樺嵄鍎垮悕绉� |
+| plannedFollowTime | Date | 鍚� | 楂樺嵄鍎夸笓妗�-鎷熼殢璁挎椂闂� |
+| hrcGrowthDevelopmentMonitoring | String | 鍚� | 楂樺嵄鍎夸笓妗�-鐢熼暱鍙戣偛妫�娴� |
+| hrcNeurologicalEvaluation | String | 鍚� | 楂樺嵄鍎夸笓妗�-绁炵粡绯荤粺璇勪及 |
+| hrcInterventionRecords | String | 鍚� | 楂樺嵄鍎夸笓妗�-骞查璁板綍 |
+| closeStatus | String | 鍚� | 缁撴鐘舵�� |
+| gestationalWeek | BigDecimal | 鍚� | 鍑虹敓瀛曞懆 |
+| birthWeight | BigDecimal | 鍚� | 鍑虹敓浣撻噸(kg) |
+| registerUser | String | 鍚� | 鐧昏浜哄憳 |
+| remark | String | 鍚� | 澶囨敞 |
+| orgid | String | 鍚� | 鍖婚櫌鏈烘瀯ID锛堝悗绔寜鐧诲綍鐢ㄦ埛鑷姩瑕嗙洊锛� |
+| campusid | String | 鍚� | 闄㈠尯ID锛堝悗绔寜鐧诲綍鐢ㄦ埛鑷姩瑕嗙洊锛� |
+| delFlag | String | 鍚� | 鍒犻櫎鏍囧織锛�0 鏈垹闄わ紝1 宸插垹闄わ紙榛樿 0锛� |
+
+**璇锋眰绀轰緥锛堟柊澧烇級**
+
+```json
+{
+  "archiveType": "1",
+  "patid": 9002,
+  "patname": "鐜嬪皬瀹�",
+  "parentname": "鐜嬪己",
+  "parentRelation": "鐖跺瓙",
+  "parentPhone": "13900000001",
+  "birthdate": "2023-01-15 00:00:00",
+  "phone": "13800000001",
+  "diagTime": "2026-10-01 09:00:00",
+  "archiveTime": "2026-10-01 09:30:00",
+  "sex": 1,
+  "deptcode": "EK",
+  "deptname": "鍎跨",
+  "icd10code": "E44.0",
+  "diagname": "涓害钀ュ吇涓嶈壇",
+  "nutritionIcd10Code": "E44.0",
+  "nutritionDiagName": "涓害钀ュ吇涓嶈壇",
+  "closeStatus": "0"
+}
+```
+
+**鍝嶅簲绀轰緥**
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": 2001
+}
+```
+
+---
+
+### 3.3 鎵归噺鍒犻櫎鍎跨妗f
+
+- **URL**锛歚POST /smartor/childArchive/batchDelete`
+- **璇存槑**锛氭寜涓昏〃ID鎵归噺鍒犻櫎鍎跨妗f锛屽悓鏃堕�昏緫鍒犻櫎瀵瑰簲鐨勫効绉戞。妗堣鎯呰〃鏁版嵁锛坄del_flag` 缃负 1锛夛紝涓ゆ鍦ㄥ悓涓�浜嬪姟涓��
+
+**璇锋眰浣擄紙JSON锛�**
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| ids | Long[] | 鏄� | 鍎跨妗f涓昏〃ID鏁扮粍 |
+
+**璇锋眰绀轰緥**
+
+```json
+[2001, 2002, 2003]
+```
+
+**鍝嶅簲绀轰緥**
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛"
+}
+```
+
+---
+
+### 3.4 鑾峰彇鍎跨妗f璇︽儏
+
+- **URL**锛歚GET /smartor/childArchiveDetail/getInfo/{archiveid}`
+- **璇存槑**锛氭寜妗f涓昏〃ID鏌ヨ鍎跨妗f璇︽儏锛堟湭鍒犻櫎鏁版嵁 `del_flag = '0'`锛夛紝杩斿洖绗竴鏉¤鎯呰褰曪紱鏃犳暟鎹椂 `data` 涓� `null`銆�
+
+**璺緞鍙傛暟**
+
+| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
+| --- | --- | --- | --- |
+| archiveid | Long | 鏄� | 鍎跨妗f涓昏〃ID锛坄pat_child_archive.id`锛� |
+
+**鍝嶅簲绀轰緥**
+
+```json
+{
+  "code": 200,
+  "msg": "鎿嶄綔鎴愬姛",
+  "data": {
+    "id": 6001,
+    "archiveid": 2001,
+    "archiveType": "1",
+    "sourceType": "1",
+    "outhospno": "MZ20261001002",
+    "inhospno": null,
+    "serialnum": "LS20261001002",
+    "patid": 9002,
+    "patname": "鐜嬪皬瀹�",
+    "parentname": "鐜嬪己",
+    "parentRelation": "鐖跺瓙",
+    "parentPhone": "13900000001",
+    "parentIdcardno": null,
+    "parentAddress": "鏉窞甯傛嫳澧呭尯",
+    "birthdate": "2023-01-15 00:00:00",
+    "idcardno": null,
+    "phone": "13800000001",
+    "diagTime": "2026-10-01 09:00:00",
+    "archiveTime": "2026-10-01 09:30:00",
+    "sex": 1,
+    "doctorCode": "D003",
+    "doctorName": "璧靛尰鐢�",
+    "managementDoctorCode": "D004",
+    "managementDoctorName": "瀛欏尰鐢�",
+    "deptcode": "EK",
+    "deptname": "鍎跨",
+    "wardcode": null,
+    "wardname": null,
+    "icd10code": "E44.0",
+    "diagname": "涓害钀ュ吇涓嶈壇",
+    "nutritionIcd10Code": "E44.0",
+    "nutritionDiagName": "涓害钀ュ吇涓嶈壇",
+    "closeStatus": "0",
+    "gestationalWeek": 39.5,
+    "birthWeight": 3.2,
+    "registerUser": "璧靛尰鐢�",
+    "orgid": "1",
+    "campusid": "1",
+    "delFlag": "0"
+  }
+}
+```
+
+> 杩斿洖瀵硅薄 `data` 涓哄効绉戞。妗堣鎯呭璞★紝瀛楁璇存槑鍚� 3.2 璇锋眰浣撳瓧娈点��
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/event/FollowupCompletedEvent.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/event/FollowupCompletedEvent.java
new file mode 100644
index 0000000..43ad2c9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/event/FollowupCompletedEvent.java
@@ -0,0 +1,46 @@
+package com.ruoyi.common.core.event;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 闅忚瀹屾垚浜嬩欢銆�
+ *
+ * <p>浠呮惡甯﹀瓙浠诲姟ID锛屾秷璐规柟鎸塈D閲嶆柊鍔犺浇鏈�鏂版暟鎹紝閬垮厤浜嬩欢鍐呭涓庡簱鍐呯姸鎬佷笉涓�鑷淬��</p>
+ *
+ * @author ruoyi
+ * @date 2026-11-11
+ */
+public class FollowupCompletedEvent implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 闅忚瀛愪换鍔D */
+    private Long subId;
+
+    /** 瀹屾垚鏃堕棿 */
+    private Date finishTime;
+
+    public FollowupCompletedEvent() {
+    }
+
+    public FollowupCompletedEvent(Long subId, Date finishTime) {
+        this.subId = subId;
+        this.finishTime = finishTime;
+    }
+
+    public Long getSubId() {
+        return subId;
+    }
+
+    public void setSubId(Long subId) {
+        this.subId = subId;
+    }
+
+    public Date getFinishTime() {
+        return finishTime;
+    }
+
+    public void setFinishTime(Date finishTime) {
+        this.finishTime = finishTime;
+    }
+}
diff --git a/ruoyi-task/src/main/java/com/ruoyi/task/event/FollowupCompletedEventPublisher.java b/ruoyi-task/src/main/java/com/ruoyi/task/event/FollowupCompletedEventPublisher.java
new file mode 100644
index 0000000..aefaebe
--- /dev/null
+++ b/ruoyi-task/src/main/java/com/ruoyi/task/event/FollowupCompletedEventPublisher.java
@@ -0,0 +1,37 @@
+package com.ruoyi.task.event;
+
+import com.ruoyi.common.core.event.FollowupCompletedEvent;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+/**
+ * 闅忚瀹屾垚浜嬩欢鍙戝竷鍣ㄣ��
+ *
+ * <p>浠诲姟妯″潡鍦ㄥ瓙浠诲姟鐘舵�佹洿鏂颁负宸插畬鎴愶紙sendstate=6锛夊悗鍙戝竷浜嬩欢锛�
+ * 妗f绛変笅娓告ā鍧楅�氳繃 {@code @TransactionalEventListener} 寮傛娑堣垂銆�</p>
+ *
+ * @author ruoyi
+ * @date 2026-11-11
+ */
+@Slf4j
+@Component
+public class FollowupCompletedEventPublisher {
+
+    @Autowired
+    private ApplicationEventPublisher applicationEventPublisher;
+
+    public void publish(Long subId) {
+        if (subId == null) {
+            return;
+        }
+        try {
+            applicationEventPublisher.publishEvent(new FollowupCompletedEvent(subId, new Date()));
+        } catch (Exception e) {
+            log.error("鍙戝竷闅忚瀹屾垚浜嬩欢澶辫触锛宻ubId={}", subId, e);
+        }
+    }
+}
diff --git a/smartor/src/main/java/com/smartor/domain/PatSpecificArchiveGenerateLog.java b/smartor/src/main/java/com/smartor/domain/PatSpecificArchiveGenerateLog.java
new file mode 100644
index 0000000..fcdf5c5
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/domain/PatSpecificArchiveGenerateLog.java
@@ -0,0 +1,90 @@
+package com.smartor.domain;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 涓撶妗f鐢熸垚鏃ュ織瀵硅薄 pat_specific_archive_generate_log銆�
+ *
+ * <p>鐢ㄤ簬浣忛櫌闅忚瀹屾垚鍚庣殑骞傜瓑鎺у埗銆佹潵婧愯拷婧拰琛ュ伩浠诲姟绛涢�夈��</p>
+ *
+ * @author ruoyi
+ * @date 2026-11-11
+ */
+@Data
+@ApiModel(value = "涓撶妗f鐢熸垚鏃ュ織瀵硅薄")
+public class PatSpecificArchiveGenerateLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /** 涓婚敭ID */
+    @ApiModelProperty(value = "涓婚敭ID")
+    private Long id;
+
+    /** 鏉ユ簮绫诲瀷锛�1闂ㄨ瘖鎺ヨ瘖 2浣忛櫌闅忚 */
+    @ApiModelProperty(value = "鏉ユ簮绫诲瀷锛�1闂ㄨ瘖鎺ヨ瘖 2浣忛櫌闅忚")
+    private String sourceType;
+
+    /** 鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID */
+    @ApiModelProperty(value = "鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID")
+    private Long sourceBizId;
+
+    /** 鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙� */
+    @ApiModelProperty(value = "鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙�")
+    private String sourceBizNo;
+
+    /** 鏉ユ簮闅忚瀛愪换鍔D锛氳Е鍙戞。妗堢敓鎴愮殑 service_subtask.id */
+    @ApiModelProperty(value = "鏉ユ簮闅忚瀛愪换鍔D锛氳Е鍙戞。妗堢敓鎴愮殑 service_subtask.id")
+    private Long sourceSubId;
+
+    /** 鎮h�匢D */
+    @ApiModelProperty(value = "鎮h�匢D")
+    private Long patid;
+
+    /** 鏈烘瀯ID */
+    @ApiModelProperty(value = "鏈烘瀯ID")
+    private String orgid;
+
+    /** 闄㈠尯ID */
+    @ApiModelProperty(value = "闄㈠尯ID")
+    private String campusid;
+
+    /** 閮ㄩ棬鍒嗙被锛�1濡囩 2鍎跨 */
+    @ApiModelProperty(value = "閮ㄩ棬鍒嗙被锛�1濡囩 2鍎跨")
+    private String deptCategory;
+
+    /** 妗f绫诲瀷 */
+    @ApiModelProperty(value = "妗f绫诲瀷")
+    private String archiveType;
+
+    /** 鍛戒腑鐨勯厤缃甀D锛涙湭鍛戒腑閰嶇疆鏃朵负0 */
+    @ApiModelProperty(value = "鍛戒腑鐨勯厤缃甀D锛涙湭鍛戒腑閰嶇疆鏃朵负0")
+    private Integer configId;
+
+    /** 鐢熸垚鎴栧懡涓殑妗f涓昏〃ID */
+    @ApiModelProperty(value = "鐢熸垚鎴栧懡涓殑妗f涓昏〃ID")
+    private Long archiveId;
+
+    /** 澶勭悊缁撴灉锛�1鐢熸垚 2宸插瓨鍦ㄨ烦杩� 3鏈尮閰� 4澶辫触 */
+    @ApiModelProperty(value = "澶勭悊缁撴灉锛�1鐢熸垚 2宸插瓨鍦ㄨ烦杩� 3鏈尮閰� 4澶辫触")
+    private String processResult;
+
+    /** 澶勭悊璇存槑 */
+    @ApiModelProperty(value = "澶勭悊璇存槑")
+    private String processMsg;
+
+    /** 閲嶈瘯娆℃暟 */
+    @ApiModelProperty(value = "閲嶈瘯娆℃暟")
+    private Integer retryCount;
+
+    /** 鍒涘缓鏃堕棿 */
+    @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+    private Date createTime;
+
+    /** 鏇存柊鏃堕棿 */
+    @ApiModelProperty(value = "鏇存柊鏃堕棿")
+    private Date updateTime;
+}
diff --git a/smartor/src/main/java/com/smartor/listener/InhospFollowupArchiveListener.java b/smartor/src/main/java/com/smartor/listener/InhospFollowupArchiveListener.java
new file mode 100644
index 0000000..b9f2bbd
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/listener/InhospFollowupArchiveListener.java
@@ -0,0 +1,42 @@
+package com.smartor.listener;
+
+import com.ruoyi.common.core.event.FollowupCompletedEvent;
+import com.smartor.service.IPatSpecificArchiveGenerateService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.event.TransactionPhase;
+import org.springframework.transaction.event.TransactionalEventListener;
+
+/**
+ * 闅忚瀹屾垚鐢熸垚涓撶妗f鐩戝惉鍣ㄣ��
+ *
+ * <p>浣跨敤 AFTER_COMMIT 淇濊瘉闅忚瀹屾垚鐘舵�佸凡钀藉簱锛涘紓甯稿彧璁板綍鏃ュ織锛屼笉褰卞搷闅忚涓绘祦绋嬨��</p>
+ *
+ * @author ruoyi
+ * @date 2026-11-11
+ */
+@Slf4j
+@Component
+public class InhospFollowupArchiveListener {
+
+    @Autowired
+    private IPatSpecificArchiveGenerateService patSpecificArchiveGenerateService;
+
+    @Async("threadPoolTaskExecutor")
+    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
+    public void onFollowupCompleted(FollowupCompletedEvent event) {
+        if (event == null || event.getSubId() == null) {
+            return;
+        }
+        try {
+            int generated = patSpecificArchiveGenerateService.generateByInhospFollowup(event.getSubId());
+            if (generated > 0) {
+                log.info("浣忛櫌闅忚瀹屾垚鐢熸垚涓撶妗f鎴愬姛锛宻ubId={}锛岀敓鎴愭暟閲�={}", event.getSubId(), generated);
+            }
+        } catch (Throwable e) {
+            log.error("浣忛櫌闅忚瀹屾垚鐢熸垚涓撶妗f澶辫触锛宻ubId={}", event.getSubId(), e);
+        }
+    }
+}
diff --git a/smartor/src/main/java/com/smartor/mapper/PatSpecificArchiveGenerateLogMapper.java b/smartor/src/main/java/com/smartor/mapper/PatSpecificArchiveGenerateLogMapper.java
new file mode 100644
index 0000000..e5971c8
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/mapper/PatSpecificArchiveGenerateLogMapper.java
@@ -0,0 +1,41 @@
+package com.smartor.mapper;
+
+import com.smartor.domain.PatSpecificArchiveGenerateLog;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 涓撶妗f鐢熸垚鏃ュ織Mapper鎺ュ彛銆�
+ *
+ * @author ruoyi
+ * @date 2026-11-11
+ */
+@Mapper
+public interface PatSpecificArchiveGenerateLogMapper {
+
+    /**
+     * 鎸夋潵婧� + 闅忚瀛愪换鍔� + 閰嶇疆鏌ヨ鏃ュ織銆�
+     *
+     * @param sourceType  鏉ユ簮绫诲瀷
+     * @param sourceSubId 鏉ユ簮闅忚瀛愪换鍔D
+     * @param configId    閰嶇疆ID锛屾湭鍛戒腑閰嶇疆浼�0
+     * @return 鏃ュ織璁板綍锛屼笉瀛樺湪杩斿洖 null
+     */
+    PatSpecificArchiveGenerateLog selectBySourceSubAndConfig(@Param("sourceType") String sourceType,
+                                                             @Param("sourceSubId") Long sourceSubId,
+                                                             @Param("configId") Integer configId);
+
+    /**
+     * 鏌ヨ鏉ユ簮闅忚瀛愪换鍔′笅鏄惁宸叉湁鎴愬姛/璺宠繃/鏈尮閰嶇殑缁撴灉銆�
+     *
+     * @param sourceType  鏉ユ簮绫诲瀷
+     * @param sourceSubId 鏉ユ簮闅忚瀛愪换鍔D
+     * @return 宸插鐞嗘潯鏁�
+     */
+    int countProcessedBySourceSub(@Param("sourceType") String sourceType,
+                                  @Param("sourceSubId") Long sourceSubId);
+
+    int insertPatSpecificArchiveGenerateLog(PatSpecificArchiveGenerateLog log);
+
+    int updatePatSpecificArchiveGenerateLog(PatSpecificArchiveGenerateLog log);
+}
diff --git a/smartor/src/main/java/com/smartor/service/IPatSpecificArchiveGenerateLogService.java b/smartor/src/main/java/com/smartor/service/IPatSpecificArchiveGenerateLogService.java
new file mode 100644
index 0000000..47f812a
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/service/IPatSpecificArchiveGenerateLogService.java
@@ -0,0 +1,18 @@
+package com.smartor.service;
+
+import com.smartor.domain.PatSpecificArchiveGenerateLog;
+
+/**
+ * 涓撶妗f鐢熸垚鏃ュ織Service鎺ュ彛銆�
+ *
+ * @author ruoyi
+ * @date 2026-11-11
+ */
+public interface IPatSpecificArchiveGenerateLogService {
+
+    PatSpecificArchiveGenerateLog selectBySourceSubAndConfig(String sourceType, Long sourceSubId, Integer configId);
+
+    boolean existsProcessedBySourceSub(String sourceType, Long sourceSubId);
+
+    int saveOrUpdate(PatSpecificArchiveGenerateLog log);
+}
diff --git a/smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateLogServiceImpl.java b/smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateLogServiceImpl.java
new file mode 100644
index 0000000..7071a9e
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/service/impl/PatSpecificArchiveGenerateLogServiceImpl.java
@@ -0,0 +1,74 @@
+package com.smartor.service.impl;
+
+import com.smartor.domain.PatSpecificArchiveGenerateLog;
+import com.smartor.mapper.PatSpecificArchiveGenerateLogMapper;
+import com.smartor.service.IPatSpecificArchiveGenerateLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+
+/**
+ * 涓撶妗f鐢熸垚鏃ュ織Service涓氬姟灞傚鐞嗐��
+ *
+ * @author ruoyi
+ * @date 2026-11-11
+ */
+@Service
+public class PatSpecificArchiveGenerateLogServiceImpl implements IPatSpecificArchiveGenerateLogService {
+
+    @Autowired
+    private PatSpecificArchiveGenerateLogMapper logMapper;
+
+    @Override
+    public PatSpecificArchiveGenerateLog selectBySourceSubAndConfig(String sourceType, Long sourceSubId, Integer configId) {
+        return logMapper.selectBySourceSubAndConfig(sourceType, sourceSubId,
+                configId == null ? 0 : configId);
+    }
+
+    @Override
+    public boolean existsProcessedBySourceSub(String sourceType, Long sourceSubId) {
+        return logMapper.countProcessedBySourceSub(sourceType, sourceSubId) > 0;
+    }
+
+    @Override
+    public int saveOrUpdate(PatSpecificArchiveGenerateLog log) {
+        if (log == null) {
+            return 0;
+        }
+        if (log.getSourceType() == null) {
+            log.setSourceType("2");
+        }
+        if (log.getConfigId() == null) {
+            log.setConfigId(0);
+        }
+        if (log.getRetryCount() == null) {
+            log.setRetryCount(0);
+        }
+        Date now = new Date();
+        log.setUpdateTime(now);
+        PatSpecificArchiveGenerateLog old = logMapper.selectBySourceSubAndConfig(
+                log.getSourceType(), log.getSourceSubId(), log.getConfigId());
+        if (old == null) {
+            log.setCreateTime(now);
+            try {
+                return logMapper.insertPatSpecificArchiveGenerateLog(log);
+            } catch (DuplicateKeyException e) {
+                // 骞跺彂涓嬪彟涓�涓嚎绋嬪凡鍐欏叆锛岃浆涓烘洿鏂帮紝淇濊瘉骞傜瓑
+                old = logMapper.selectBySourceSubAndConfig(
+                        log.getSourceType(), log.getSourceSubId(), log.getConfigId());
+                if (old == null) {
+                    throw e;
+                }
+                log.setId(old.getId());
+                return logMapper.updatePatSpecificArchiveGenerateLog(log);
+            }
+        }
+        log.setId(old.getId());
+        if (log.getCreateTime() == null) {
+            log.setCreateTime(old.getCreateTime());
+        }
+        return logMapper.updatePatSpecificArchiveGenerateLog(log);
+    }
+}
diff --git a/smartor/src/main/resources/mapper/smartor/PatSpecificArchiveGenerateLogMapper.xml b/smartor/src/main/resources/mapper/smartor/PatSpecificArchiveGenerateLogMapper.xml
new file mode 100644
index 0000000..ddcfef9
--- /dev/null
+++ b/smartor/src/main/resources/mapper/smartor/PatSpecificArchiveGenerateLogMapper.xml
@@ -0,0 +1,94 @@
+<?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.smartor.mapper.PatSpecificArchiveGenerateLogMapper">
+
+    <resultMap type="com.smartor.domain.PatSpecificArchiveGenerateLog" id="PatSpecificArchiveGenerateLogResult">
+        <result property="id" column="id"/>
+        <result property="sourceType" column="source_type"/>
+        <result property="sourceBizId" column="source_biz_id"/>
+        <result property="sourceBizNo" column="source_biz_no"/>
+        <result property="sourceSubId" column="source_sub_id"/>
+        <result property="patid" column="patid"/>
+        <result property="orgid" column="orgid"/>
+        <result property="campusid" column="campusid"/>
+        <result property="deptCategory" column="dept_category"/>
+        <result property="archiveType" column="archive_type"/>
+        <result property="configId" column="config_id"/>
+        <result property="archiveId" column="archive_id"/>
+        <result property="processResult" column="process_result"/>
+        <result property="processMsg" column="process_msg"/>
+        <result property="retryCount" column="retry_count"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateTime" column="update_time"/>
+    </resultMap>
+
+    <sql id="selectPatSpecificArchiveGenerateLogVo">
+        select id,
+               source_type,
+               source_biz_id,
+               source_biz_no,
+               source_sub_id,
+               patid,
+               orgid,
+               campusid,
+               dept_category,
+               archive_type,
+               config_id,
+               archive_id,
+               process_result,
+               process_msg,
+               retry_count,
+               create_time,
+               update_time
+        from pat_specific_archive_generate_log
+    </sql>
+
+    <select id="selectBySourceSubAndConfig" resultMap="PatSpecificArchiveGenerateLogResult">
+        <include refid="selectPatSpecificArchiveGenerateLogVo"/>
+        where source_type = #{sourceType}
+          and source_sub_id = #{sourceSubId}
+          and config_id = #{configId}
+        limit 1
+    </select>
+
+    <select id="countProcessedBySourceSub" resultType="int">
+        select count(1)
+        from pat_specific_archive_generate_log
+        where source_type = #{sourceType}
+          and source_sub_id = #{sourceSubId}
+          and process_result in ('1', '2', '3')
+    </select>
+
+    <insert id="insertPatSpecificArchiveGenerateLog" parameterType="com.smartor.domain.PatSpecificArchiveGenerateLog"
+            useGeneratedKeys="true" keyProperty="id">
+        insert into pat_specific_archive_generate_log
+        (source_type, source_biz_id, source_biz_no, source_sub_id, patid, orgid, campusid,
+         dept_category, archive_type, config_id, archive_id, process_result,
+         process_msg, retry_count, create_time, update_time)
+        values
+        (#{sourceType}, #{sourceBizId}, #{sourceBizNo}, #{sourceSubId}, #{patid}, #{orgid}, #{campusid},
+         #{deptCategory}, #{archiveType}, #{configId}, #{archiveId}, #{processResult},
+         #{processMsg}, #{retryCount}, #{createTime}, #{updateTime})
+    </insert>
+
+    <update id="updatePatSpecificArchiveGenerateLog" parameterType="com.smartor.domain.PatSpecificArchiveGenerateLog">
+        update pat_specific_archive_generate_log
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="sourceBizNo != null">source_biz_no = #{sourceBizNo},</if>
+            <if test="sourceSubId != null">source_sub_id = #{sourceSubId},</if>
+            <if test="patid != null">patid = #{patid},</if>
+            <if test="orgid != null">orgid = #{orgid},</if>
+            <if test="campusid != null">campusid = #{campusid},</if>
+            <if test="deptCategory != null">dept_category = #{deptCategory},</if>
+            <if test="archiveType != null">archive_type = #{archiveType},</if>
+            <if test="archiveId != null">archive_id = #{archiveId},</if>
+            <if test="processResult != null">process_result = #{processResult},</if>
+            <if test="processMsg != null">process_msg = #{processMsg},</if>
+            <if test="retryCount != null">retry_count = #{retryCount},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+</mapper>
diff --git a/smartor/src/test/java/com/smartor/service/InhospFollowupArchiveLogicCheck.java b/smartor/src/test/java/com/smartor/service/InhospFollowupArchiveLogicCheck.java
new file mode 100644
index 0000000..a14ad68
--- /dev/null
+++ b/smartor/src/test/java/com/smartor/service/InhospFollowupArchiveLogicCheck.java
@@ -0,0 +1,130 @@
+package com.smartor.service;
+
+import com.ruoyi.patarchive.domain.PatSpecificArchiveGenerateConfig;
+import com.ruoyi.task.domain.ServiceSubtask;
+import com.smartor.service.impl.PatSpecificArchiveGenerateServiceImpl;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * 浣忛櫌闅忚鐢熸垚涓撶妗f閫昏緫鑷锛堢函 main锛屼笉渚濊禆 JUnit / Spring / 鏁版嵁搴擄級銆�
+ *
+ * <p>瑕嗙洊锛氫綇闄㈤殢璁胯寖鍥村垽鏂�佺瀹�/鐥呭尯/璇婃柇閰嶇疆鍖归厤銆丣SON/閫楀彿閰嶇疆瑙f瀽銆丮apper XML 鍙В鏋愭�с��</p>
+ */
+public final class InhospFollowupArchiveLogicCheck {
+
+    private static int passed = 0;
+    private static int failed = 0;
+
+    private static void check(String key, Object expected, Object actual) {
+        boolean ok = expected == null ? actual == null : expected.equals(actual);
+        if (ok) {
+            passed++;
+            System.out.println("  [OK]   " + key + " = " + actual);
+        } else {
+            failed++;
+            System.out.println("  [FAIL] " + key + " 鏈熸湜=" + expected + " 瀹為檯=" + actual);
+        }
+    }
+
+    private static void setField(Object target, String name, Object value) throws Exception {
+        Field field = target.getClass().getDeclaredField(name);
+        field.setAccessible(true);
+        field.set(target, value);
+    }
+
+    private static ServiceSubtask subtask(String hospType, String serviceType) {
+        ServiceSubtask subtask = new ServiceSubtask();
+        subtask.setId(1001L);
+        subtask.setHospType(hospType);
+        subtask.setServiceType(serviceType);
+        return subtask;
+    }
+
+    private static PatSpecificArchiveGenerateConfig config(String deptType, String archiveType,
+                                                           String deptCodes, String icd10Codes) {
+        PatSpecificArchiveGenerateConfig config = new PatSpecificArchiveGenerateConfig();
+        config.setId(1L);
+        config.setDeptType(deptType);
+        config.setDeptCategory("2");
+        config.setArchiveType(archiveType);
+        config.setDeptCodes(deptCodes);
+        config.setIcd10Codes(icd10Codes);
+        return config;
+    }
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("========== 浣忛櫌闅忚鐢熸垚涓撶妗f閫昏緫鑷 ==========");
+
+        PatSpecificArchiveGenerateServiceImpl service = new PatSpecificArchiveGenerateServiceImpl();
+        setField(service, "inhospFollowupServiceTypes", "2,13,18,19");
+
+        Method isInhosp = PatSpecificArchiveGenerateServiceImpl.class
+                .getDeclaredMethod("isInhospFollowup", ServiceSubtask.class);
+        isInhosp.setAccessible(true);
+
+        System.out.println("-- 1) 浣忛櫌闅忚鑼冨洿 --");
+        check("鍑洪櫌闅忚 serviceType=2", true, isInhosp.invoke(service, subtask("2", "2")));
+        check("鍏ラ櫌闅忚 serviceType=18", true, isInhosp.invoke(service, subtask("6", "18")));
+        check("闂ㄨ瘖浠诲姟 hospType=1", false, isInhosp.invoke(service, subtask("1", "3")));
+        check("瀹f暀浠诲姟 serviceType=4", false, isInhosp.invoke(service, subtask("2", "4")));
+        check("serviceType 涓虹┖", false, isInhosp.invoke(service, subtask("2", null)));
+
+        Method match = PatSpecificArchiveGenerateServiceImpl.class.getDeclaredMethod(
+                "matchConfig", PatSpecificArchiveGenerateConfig.class,
+                String.class, String.class, String.class, String.class);
+        match.setAccessible(true);
+
+        System.out.println("-- 2) 绉戝鍖归厤 --");
+        PatSpecificArchiveGenerateConfig deptConfig = config("1", "1", "[\"D001\"]", null);
+        check("绉戝 D001 鍛戒腑", true, match.invoke(service, deptConfig, "D001", null, null, null));
+        check("绉戝 D002 涓嶅懡涓�", false, match.invoke(service, deptConfig, "D002", null, null, null));
+
+        System.out.println("-- 3) 鐥呭尯鍖归厤 --");
+        PatSpecificArchiveGenerateConfig wardConfig = config("2", "3", "[\"W001\"]", null);
+        check("鐥呭尯 W001 鍛戒腑", true, match.invoke(service, wardConfig, "D001", "W001", null, null));
+        check("绉戝 D001 瀵圭梾鍖洪厤缃笉鍛戒腑", false,
+                match.invoke(service, wardConfig, "D001", "D001", null, null));
+
+        System.out.println("-- 4) 璇婃柇鍖归厤 --");
+        PatSpecificArchiveGenerateConfig diagConfig = config("1", "1", null, "[\"E46.x00x003\"]");
+        check("璇婃柇鐮佸懡涓�", true, match.invoke(service, diagConfig, "D001", null, "E46.x00x003", "钀ュ吇涓嶈壇"));
+        check("鏃犺瘖鏂爜鏃舵寜璇婃柇鍚嶇О鍏滃簳", true,
+                match.invoke(service, diagConfig, "D001", null, null, "E46.x00x003"));
+        check("璇婃柇涓嶅懡涓�", false, match.invoke(service, diagConfig, "D001", null, "R00", "鍏朵粬"));
+
+        System.out.println("-- 5) 閰嶇疆涓虹┖ / 闈炴硶 JSON --");
+        PatSpecificArchiveGenerateConfig emptyConfig = config("1", "1", null, null);
+        check("绉戝鍜岃瘖鏂兘涓虹┖", false, match.invoke(service, emptyConfig, "D001", null, null, null));
+        PatSpecificArchiveGenerateConfig commaConfig = config("1", "1", "D001,D002", null);
+        check("閫楀彿鍒嗛殧閰嶇疆鍏滃簳", true, match.invoke(service, commaConfig, "D002", null, null, null));
+
+        System.out.println("-- 6) Mapper XML 鍙В鏋愭�� --");
+        String[] xmlFiles = new String[]{
+                "smartor/src/main/resources/mapper/smartor/PatMaternityArchiveMapper.xml",
+                "smartor/src/main/resources/mapper/smartor/PatChildArchiveMapper.xml",
+                "smartor/src/main/resources/mapper/smartor/PatMaternityArchiveDetailMapper.xml",
+                "smartor/src/main/resources/mapper/smartor/PatChildArchiveDetailMapper.xml",
+                "smartor/src/main/resources/mapper/smartor/PatSpecificArchiveGenerateLogMapper.xml",
+                "ruoyi-task/src/main/resources/mapper/task/ServiceSubtaskMapper.xml"
+        };
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+        for (String xmlFile : xmlFiles) {
+            try {
+                factory.newDocumentBuilder().parse(new File(xmlFile));
+                check(xmlFile, "OK", "OK");
+            } catch (Exception e) {
+                check(xmlFile, "OK", e.getClass().getSimpleName() + ":" + e.getMessage());
+            }
+        }
+
+        System.out.println("========== 缁撴灉锛歅ASS=" + passed + "锛孎AIL=" + failed + " ==========");
+        if (failed > 0) {
+            System.exit(1);
+        }
+    }
+}
diff --git a/sql/pat_specific_archive_generate_log_and_source_20261111.sql b/sql/pat_specific_archive_generate_log_and_source_20261111.sql
new file mode 100644
index 0000000..c94af5c
--- /dev/null
+++ b/sql/pat_specific_archive_generate_log_and_source_20261111.sql
@@ -0,0 +1,105 @@
+-- =============================================================================
+-- 浣忛櫌闅忚瀹屾垚鐢熸垚濡囩/鍎跨涓撶妗f
+-- 1. 妗f涓昏〃/璇︽儏琛ㄥ鍔犳潵婧愬瓧娈�
+-- 2. 鏂板涓撶妗f鐢熸垚鏃ュ織琛紙骞傜瓑 + 琛ュ伩 + 杩芥函锛�
+-- 3. 澧炲姞鎮h�呮。妗堟煡璇㈢储寮�
+-- 鏃ユ湡锛�2026-11-11
+-- =============================================================================
+
+-- -----------------------------------------------------------------------------
+-- 1. 妗f涓昏〃鏉ユ簮瀛楁
+-- -----------------------------------------------------------------------------
+ALTER TABLE pat_maternity_archive
+    ADD COLUMN source_type CHAR(1) DEFAULT NULL COMMENT '鏉ユ簮绫诲瀷锛�1闂ㄨ瘖鎺ヨ瘖 2浣忛櫌闅忚 3鎵嬪伐鏂板',
+    ADD COLUMN source_biz_id BIGINT DEFAULT NULL COMMENT '鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID',
+    ADD COLUMN source_biz_no VARCHAR(64) DEFAULT NULL COMMENT '鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙�',
+    ADD COLUMN source_sub_id BIGINT DEFAULT NULL COMMENT '鏉ユ簮闅忚瀛愪换鍔D锛歴ervice_subtask.id';
+
+ALTER TABLE pat_child_archive
+    ADD COLUMN source_type CHAR(1) DEFAULT NULL COMMENT '鏉ユ簮绫诲瀷锛�1闂ㄨ瘖鎺ヨ瘖 2浣忛櫌闅忚 3鎵嬪伐鏂板',
+    ADD COLUMN source_biz_id BIGINT DEFAULT NULL COMMENT '鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID',
+    ADD COLUMN source_biz_no VARCHAR(64) DEFAULT NULL COMMENT '鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙�',
+    ADD COLUMN source_sub_id BIGINT DEFAULT NULL COMMENT '鏉ユ簮闅忚瀛愪换鍔D锛歴ervice_subtask.id';
+
+-- -----------------------------------------------------------------------------
+-- 2. 妗f璇︽儏琛ㄨˉ鍏呮潵婧愪笟鍔D/缂栧彿锛坰ource_type 鍘熻〃宸叉湁锛�
+-- -----------------------------------------------------------------------------
+ALTER TABLE pat_maternity_archive_detail
+    ADD COLUMN source_biz_id BIGINT DEFAULT NULL COMMENT '鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID',
+    ADD COLUMN source_biz_no VARCHAR(64) DEFAULT NULL COMMENT '鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙�',
+    ADD COLUMN source_sub_id BIGINT DEFAULT NULL COMMENT '鏉ユ簮闅忚瀛愪换鍔D锛歴ervice_subtask.id';
+
+ALTER TABLE pat_child_archive_detail
+    ADD COLUMN source_biz_id BIGINT DEFAULT NULL COMMENT '鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID',
+    ADD COLUMN source_biz_no VARCHAR(64) DEFAULT NULL COMMENT '鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙�',
+    ADD COLUMN source_sub_id BIGINT DEFAULT NULL COMMENT '鏉ユ簮闅忚瀛愪换鍔D锛歴ervice_subtask.id';
+
+-- -----------------------------------------------------------------------------
+-- 3. 鐢熸垚鏃ュ織琛�
+-- -----------------------------------------------------------------------------
+CREATE TABLE IF NOT EXISTS pat_specific_archive_generate_log
+(
+    id            BIGINT        NOT NULL AUTO_INCREMENT COMMENT '涓婚敭ID',
+    source_type   CHAR(1)       NOT NULL DEFAULT '2' COMMENT '鏉ユ簮绫诲瀷锛�1闂ㄨ瘖鎺ヨ瘖 2浣忛櫌闅忚',
+    source_biz_id BIGINT        DEFAULT NULL COMMENT '鏉ユ簮涓氬姟ID锛氶棬璇婅褰旾D/浣忛櫌璁板綍ID',
+    source_biz_no VARCHAR(64)   DEFAULT NULL COMMENT '鏉ユ簮涓氬姟缂栧彿锛氶棬璇婂彿/浣忛櫌鍙�',
+    source_sub_id BIGINT        DEFAULT NULL COMMENT '鏉ユ簮闅忚瀛愪换鍔D锛歴ervice_subtask.id',
+    patid         BIGINT        DEFAULT NULL COMMENT '鎮h�匢D',
+    orgid         VARCHAR(64)   DEFAULT NULL COMMENT '鏈烘瀯ID',
+    campusid      VARCHAR(64)   DEFAULT NULL COMMENT '闄㈠尯ID',
+    dept_category CHAR(1)       DEFAULT NULL COMMENT '閮ㄩ棬鍒嗙被锛�1濡囩 2鍎跨',
+    archive_type  VARCHAR(32)   DEFAULT NULL COMMENT '妗f绫诲瀷',
+    config_id     INT           NOT NULL DEFAULT 0 COMMENT '鍛戒腑鐨勯厤缃甀D锛涙湭鍛戒腑閰嶇疆鏃朵负0',
+    archive_id    BIGINT        DEFAULT NULL COMMENT '鐢熸垚鎴栧懡涓殑妗f涓昏〃ID',
+    process_result CHAR(1)      NOT NULL COMMENT '澶勭悊缁撴灉锛�1鐢熸垚 2宸插瓨鍦ㄨ烦杩� 3鏈尮閰� 4澶辫触',
+    process_msg   VARCHAR(1000) DEFAULT NULL COMMENT '澶勭悊璇存槑',
+    retry_count   INT           NOT NULL DEFAULT 0 COMMENT '閲嶈瘯娆℃暟',
+    create_time   DATETIME      DEFAULT CURRENT_TIMESTAMP COMMENT '鍒涘缓鏃堕棿',
+    update_time   DATETIME      DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '鏇存柊鏃堕棿',
+    PRIMARY KEY (id),
+    UNIQUE KEY uk_pasgl_source_sub_config (source_type, source_sub_id, config_id),
+    KEY idx_pasgl_biz_id (source_biz_id),
+    KEY idx_pasgl_patid (patid, dept_category, archive_type),
+    KEY idx_pasgl_archive (archive_id)
+) ENGINE = InnoDB
+  DEFAULT CHARSET = utf8mb4 COMMENT ='涓撶妗f鐢熸垚鏃ュ織琛�';
+
+-- -----------------------------------------------------------------------------
+-- 4. 鎮h�呭凡鏈夋。妗堟煡璇㈢储寮�
+-- -----------------------------------------------------------------------------
+ALTER TABLE pat_maternity_archive
+    ADD INDEX idx_pma_patid_type (orgid, patid, archive_type, del_flag);
+
+ALTER TABLE pat_child_archive
+    ADD INDEX idx_pca_patid_type (orgid, patid, archive_type, del_flag);
+
+-- -----------------------------------------------------------------------------
+-- 5. 鏉ユ簮绫诲瀷瀛楀吀锛堝瀛楀吀琛ㄥ凡鏈夊悓绫诲瀷鏁版嵁锛屽彲璺宠繃锛�
+-- -----------------------------------------------------------------------------
+INSERT INTO sys_dict_type (dict_name, dict_type, status, create_by, create_time, remark)
+SELECT '涓撶妗f鏉ユ簮', 'pat_archive_source_type', '0', 'system', NOW(), '涓撶妗f鐢熸垚鏉ユ簮'
+FROM DUAL
+WHERE NOT EXISTS (
+    SELECT 1 FROM sys_dict_type WHERE dict_type = 'pat_archive_source_type'
+);
+
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, is_default, status, create_by, create_time, remark)
+SELECT 1, '闂ㄨ瘖鎺ヨ瘖', '1', 'pat_archive_source_type', 'N', '0', 'system', NOW(), '闂ㄨ瘖鎺ヨ瘖瀹屾垚鐢熸垚'
+FROM DUAL
+WHERE NOT EXISTS (
+    SELECT 1 FROM sys_dict_data WHERE dict_type = 'pat_archive_source_type' AND dict_value = '1'
+);
+
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, is_default, status, create_by, create_time, remark)
+SELECT 2, '浣忛櫌闅忚', '2', 'pat_archive_source_type', 'N', '0', 'system', NOW(), '浣忛櫌闅忚瀹屾垚鐢熸垚'
+FROM DUAL
+WHERE NOT EXISTS (
+    SELECT 1 FROM sys_dict_data WHERE dict_type = 'pat_archive_source_type' AND dict_value = '2'
+);
+
+INSERT INTO sys_dict_data (dict_sort, dict_label, dict_value, dict_type, is_default, status, create_by, create_time, remark)
+SELECT 3, '鎵嬪伐鏂板', '3', 'pat_archive_source_type', 'N', '0', 'system', NOW(), '鎵嬪伐鏂板/瀵煎叆'
+FROM DUAL
+WHERE NOT EXISTS (
+    SELECT 1 FROM sys_dict_data WHERE dict_type = 'pat_archive_source_type' AND dict_value = '3'
+);

--
Gitblit v1.9.3