Просмотр исходного кода

新增
1、家属沟通记录列表增加合同号、导入功能
2、医疗护理记录列表增加合同号、导入功能
3、医疗记录列表增加合同号、导入功能
4、营养记录列表增加合同号、导入功能
5、康复评估记录列表增加合同号、导入功能
6、康复训练记录列表增加合同号、导入功能
7、长者信息分页增加按特殊字段进行升降序排序

liangwenxuan 2 месяцев назад
Родитель
Сommit
3261289d64
39 измененных файлов с 1398 добавлено и 47 удалено
  1. 21 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/FamilyCommunicationRecordController.java
  2. 26 2
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/MedicalCareRecordsController.java
  3. 23 2
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/MedicalRecordsController.java
  4. 24 2
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/NutritionRecordController.java
  5. 21 2
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/RehabilitationAssessmentsController.java
  6. 24 2
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/TrainingRecordsController.java
  7. 3 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/CommunicationRecordRespVO.java
  8. 7 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyInfoPageReqVO.java
  9. 46 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/FamilyCommunicationRecordImportExcelVO.java
  10. 31 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ImportResultVO.java
  11. 38 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/MedicalCareRecordsImportExcelVO.java
  12. 55 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/MedicalCareRecordsRespVO.java
  13. 46 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/MedicalRecordsImportExcelVO.java
  14. 63 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/MedicalRecordsRespVO.java
  15. 34 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/NutritionRecordImportExcelVO.java
  16. 46 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/NutritionRecordRespVO.java
  17. 3 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/RecordsPageReqVO.java
  18. 49 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/RehabilitationAssessmentsImportExcelVO.java
  19. 61 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/RehabilitationAssessmentsRespVO.java
  20. 34 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/TrainingRecordsImportExcelVO.java
  21. 51 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/TrainingRecordsRespVO.java
  22. 15 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/MedicalRecordsDO.java
  23. 12 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/ElderlyContractMapper.java
  24. 21 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/MedicalRecordsMapper.java
  25. 22 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyInfoServiceImpl.java
  26. 9 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/FamilyCommunicationRecordService.java
  27. 81 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/FamilyCommunicationRecordServiceImpl.java
  28. 13 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/MedicalCareRecordsService.java
  29. 89 6
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/MedicalCareRecordsServiceImpl.java
  30. 11 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/MedicalRecordsService.java
  31. 79 5
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/MedicalRecordsServiceImpl.java
  32. 11 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/NutritionRecordService.java
  33. 82 5
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/NutritionRecordServiceImpl.java
  34. 11 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/RehabilitationAssessmentsService.java
  35. 88 5
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/RehabilitationAssessmentsServiceImpl.java
  36. 10 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/TrainingRecordsService.java
  37. 75 6
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/TrainingRecordsServiceImpl.java
  38. 59 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/util/ImportUtil.java
  39. 4 1
      yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/ElderlyInfoMapper.xml

+ 21 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/FamilyCommunicationRecordController.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.biz;
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CommunicationRecordPageReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CommunicationRecordRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.FamilyCommunicationRecordDO;
 import cn.iocoder.yudao.module.system.service.biz.FamilyCommunicationRecordService;
 import org.springframework.web.bind.annotation.*;
@@ -14,12 +15,16 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Operation;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.constraints.*;
 import javax.validation.*;
 
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
@@ -75,6 +80,22 @@ public class FamilyCommunicationRecordController {
         return success(pageResult);
     }
 
+    @GetMapping("/import-template")
+    @Operation(summary = "下载家属沟通记录导入模板")
+    @TenantIgnore
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        communicationRecordService.exportImportTemplate(response);
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "导入家属沟通记录")
+    @TenantIgnore
+    public CommonResult<ImportResultVO> importCareRecords(
+            @RequestParam("file") MultipartFile file) throws Exception {
+        ImportResultVO result = communicationRecordService.importFamilyCommunicationRecord(file);
+        return success(result);
+    }
+
 //    @GetMapping("/export-excel")
 //    @Operation(summary = "导出家属沟通记录 Excel")
 //    @ApiAccessLog(operateType = EXPORT)

+ 26 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/MedicalCareRecordsController.java

@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.system.controller.admin.biz;
 
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CareRecordsPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.MedicalCareRecordsRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.MedicalCareRecordsDO;
 import cn.iocoder.yudao.module.system.service.biz.MedicalCareRecordsService;
 import org.springframework.web.bind.annotation.*;
@@ -12,12 +14,18 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Operation;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.*;
 
 
 import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.text.ParseException;
+
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
 
@@ -67,11 +75,27 @@ public class MedicalCareRecordsController {
     @GetMapping("/page")
     @Operation(summary = "获得医疗护理记录分页")
     @TenantIgnore
-    public CommonResult<PageResult<MedicalCareRecordsDO>> getCareRecordsPage(@Valid CareRecordsPageReqVO pageReqVO) {
-        PageResult<MedicalCareRecordsDO> pageResult = careRecordsService.getCareRecordsPage(pageReqVO);
+    public CommonResult<PageResult<MedicalCareRecordsRespVO>> getCareRecordsPage(@Valid CareRecordsPageReqVO pageReqVO) {
+        PageResult<MedicalCareRecordsRespVO> pageResult = careRecordsService.getCareRecordsPage(pageReqVO);
         return success(pageResult);
     }
 
+
+    @GetMapping("/import-template")
+    @Operation(summary = "下载医疗护理记录导入模板")
+    @TenantIgnore
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        careRecordsService.exportImportTemplate(response);
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "导入医疗护理记录")
+    @TenantIgnore
+    public CommonResult<ImportResultVO> importCareRecords(
+            @RequestParam("file") MultipartFile file) throws IOException {
+        ImportResultVO result = careRecordsService.importCareRecords(file);
+        return success(result);
+    }
 //    @GetMapping("/export-excel")
 //    @Operation(summary = "导出医疗护理记录主 Excel")
 //    @ApiAccessLog(operateType = EXPORT)

+ 23 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/MedicalRecordsController.java

@@ -1,6 +1,8 @@
 package cn.iocoder.yudao.module.system.controller.admin.biz;
 
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.MedicalRecordsRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.RecordsPageReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.MedicalRecordsDO;
 import cn.iocoder.yudao.module.system.service.biz.MedicalRecordsService;
@@ -13,12 +15,16 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Operation;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.constraints.*;
 import javax.validation.*;
 
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
@@ -69,11 +75,26 @@ public class MedicalRecordsController {
     @GetMapping("/page")
     @Operation(summary = "获得医疗记录分页")
     @TenantIgnore
-    public CommonResult<PageResult<MedicalRecordsDO>> getRecordsPage(@Valid RecordsPageReqVO pageReqVO) {
-        PageResult<MedicalRecordsDO> pageResult = recordsService.getRecordsPage(pageReqVO);
+    public CommonResult<PageResult<MedicalRecordsRespVO>> getRecordsPage(@Valid RecordsPageReqVO pageReqVO) {
+        PageResult<MedicalRecordsRespVO> pageResult = recordsService.getRecordsPage(pageReqVO);
         return success(pageResult);
     }
 
+    @GetMapping("/import-template")
+    @Operation(summary = "下载医疗记录导入模板")
+    @TenantIgnore
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        recordsService.exportImportTemplate(response);
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "导入医疗记录")
+    @TenantIgnore
+    public CommonResult<ImportResultVO> importCareRecords(
+            @RequestParam("file") MultipartFile file) throws Exception {
+        ImportResultVO result = recordsService.importMedicalRecords(file);
+        return success(result);
+    }
 //    @GetMapping("/export-excel")
 //    @Operation(summary = "导出医疗记录主 Excel")
 //    @PreAuthorize("@ss.hasPermission('medical:records:export')")

+ 24 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/NutritionRecordController.java

@@ -1,7 +1,9 @@
 package cn.iocoder.yudao.module.system.controller.admin.biz;
 
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.NutritionRecordPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.NutritionRecordRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.NutritionRecordDO;
 import cn.iocoder.yudao.module.system.service.biz.NutritionRecordService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -14,11 +16,16 @@ import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Operation;
 
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.*;
 
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
 
@@ -69,11 +76,26 @@ public class NutritionRecordController {
     @GetMapping("/page")
     @Operation(summary = "获得营养记录分页")
     @TenantIgnore
-    public CommonResult<PageResult<NutritionRecordDO>> getRecordPage(@Valid NutritionRecordPageReqVO pageReqVO) {
-        PageResult<NutritionRecordDO> pageResult = recordService.getRecordPage(pageReqVO);
+    public CommonResult<PageResult<NutritionRecordRespVO>> getRecordPage(@Valid NutritionRecordPageReqVO pageReqVO) {
+        PageResult<NutritionRecordRespVO> pageResult = recordService.getRecordPage(pageReqVO);
         return success(pageResult);
     }
 
+    @GetMapping("/import-template")
+    @Operation(summary = "下载营养记录导入模板")
+    @TenantIgnore
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        recordService.exportImportTemplate(response);
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "导入营养记录")
+    @TenantIgnore
+    public CommonResult<ImportResultVO> importCareRecords(
+            @RequestParam("file") MultipartFile file) throws Exception {
+        ImportResultVO result = recordService.importNutritionRecord(file);
+        return success(result);
+    }
 //    @GetMapping("/export-excel")
 //    @Operation(summary = "导出营养记录 Excel")
 //    @PreAuthorize("@ss.hasPermission('nutrition:record:export')")

+ 21 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/RehabilitationAssessmentsController.java

@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.system.controller.admin.biz;
 
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.AssessmentsPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.RehabilitationAssessmentsRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.RehabilitationAssessmentsDO;
 import cn.iocoder.yudao.module.system.service.biz.RehabilitationAssessmentsService;
 import org.springframework.web.bind.annotation.*;
@@ -28,6 +30,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 
 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import org.springframework.web.multipart.MultipartFile;
 
 import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
 
@@ -77,11 +80,27 @@ public class RehabilitationAssessmentsController {
     @GetMapping("/page")
     @Operation(summary = "获得康复评估记录分页")
     @TenantIgnore
-    public CommonResult<PageResult<RehabilitationAssessmentsDO>> getAssessmentsPage(@Valid AssessmentsPageReqVO pageReqVO) {
-        PageResult<RehabilitationAssessmentsDO> pageResult = assessmentsService.getAssessmentsPage(pageReqVO);
+    public CommonResult<PageResult<RehabilitationAssessmentsRespVO>> getAssessmentsPage(@Valid AssessmentsPageReqVO pageReqVO) {
+        PageResult<RehabilitationAssessmentsRespVO> pageResult = assessmentsService.getAssessmentsPage(pageReqVO);
         return success(pageResult);
     }
 
+    @GetMapping("/import-template")
+    @Operation(summary = "下载康复评估记录导入模板")
+    @TenantIgnore
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        assessmentsService.exportImportTemplate(response);
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "导入康复评估记录")
+    @TenantIgnore
+    public CommonResult<ImportResultVO> importCareRecords(
+            @RequestParam("file") MultipartFile file) throws Exception {
+        ImportResultVO result = assessmentsService.importRehabilitationAssessments(file);
+        return success(result);
+    }
+
 //    @GetMapping("/export-excel")
 //    @Operation(summary = "导出康复评估记录 Excel")
 //    @ApiAccessLog(operateType = EXPORT)

+ 24 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/TrainingRecordsController.java

@@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.system.controller.admin.biz;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.TrainingRecordsPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.TrainingRecordsRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.TrainingRecordsDO;
 import cn.iocoder.yudao.module.system.service.biz.TrainingRecordsService;
 import org.springframework.web.bind.annotation.*;
@@ -12,9 +14,14 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.Operation;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.*;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
 
@@ -66,11 +73,26 @@ public class TrainingRecordsController {
     @GetMapping("/page")
     @Operation(summary = "获得康复训练记录分页")
     @TenantIgnore
-    public CommonResult<PageResult<TrainingRecordsDO>> getRecordsPage(@Valid TrainingRecordsPageReqVO pageReqVO) {
-        PageResult<TrainingRecordsDO> pageResult = recordsService.getRecordsPage(pageReqVO);
+    public CommonResult<PageResult<TrainingRecordsRespVO>> getRecordsPage(@Valid TrainingRecordsPageReqVO pageReqVO) {
+        PageResult<TrainingRecordsRespVO> pageResult = recordsService.getRecordsPage(pageReqVO);
         return success(pageResult);
     }
 
+    @GetMapping("/import-template")
+    @Operation(summary = "下载康复训练记录导入模板")
+    @TenantIgnore
+    public void importTemplate(HttpServletResponse response) throws IOException {
+        recordsService.exportImportTemplate(response);
+    }
+
+    @PostMapping("/import")
+    @Operation(summary = "导入康复训练记录")
+    @TenantIgnore
+    public CommonResult<ImportResultVO> importCareRecords(
+            @RequestParam("file") MultipartFile file) throws Exception {
+        ImportResultVO result = recordsService.importTrainingRecords(file);
+        return success(result);
+    }
 //    @GetMapping("/export-excel")
 //    @Operation(summary = "导出康复训练记录 Excel")
 //    @PreAuthorize("@ss.hasPermission('training:records:export')")

+ 3 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/CommunicationRecordRespVO.java

@@ -59,4 +59,7 @@ public class CommunicationRecordRespVO {
     @Schema(description = "床位信息")
     private String bedInfo;
 
+    @Schema(description = "合同编号")
+    private String contractNumber;
+
 }

+ 7 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ElderlyInfoPageReqVO.java

@@ -69,7 +69,13 @@ public class ElderlyInfoPageReqVO extends PageParam {
     private String telPhone;
 
     @Schema(description = "排序字段")
-    private String orderField;
+    private String prop;
+
+    @Schema(description = "排序方式")
+    private String order;
+
+    @Schema(description = "排序")
+    private String orderByClause;
 }
 
 

+ 46 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/FamilyCommunicationRecordImportExcelVO.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false)
+public class FamilyCommunicationRecordImportExcelVO {
+    @ExcelProperty("长者姓名")
+    private String elderName;
+
+    @ExcelProperty("合同号")
+    private String contractNumber;
+
+    @ExcelProperty("沟通时间")
+    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
+    private Date communicationTime;
+
+    @ExcelProperty("沟通方式")
+    private String communicationMethod;
+
+    @ExcelProperty("服务人")
+    private String servicePerson;
+
+    @ExcelProperty("家属姓名")
+    private String familyName;
+
+    @ExcelProperty("与长者关系")
+    private String relationshipWithElder;
+
+    @ExcelProperty("沟通内容")
+    private String communicationContent;
+
+    @ExcelProperty("解决效果")
+    private String solutionEffect;
+}

+ 31 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ImportResultVO.java

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import lombok.Data;
+
+import java.util.List;
+@Data
+public class ImportResultVO {
+
+    private Integer successCount;
+
+    private Integer failureCount;
+
+    private List<RowError> failures;
+
+    @Data
+    public static class RowError {
+        private Integer rowNum;
+
+        /** 业务定位字段:合同号(本次统一使用) */
+        private String contractNumber;
+
+        /** 业务展示字段:长者姓名(可选) */
+        private String elderName;
+
+        /** 失败原因(给前端展示) */
+        private String reason;
+
+        /** 可选:原始异常简述(便于排查,不建议给前端太多) */
+        private String exception;
+    }
+}

+ 38 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/MedicalCareRecordsImportExcelVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false)
+public class MedicalCareRecordsImportExcelVO {
+
+    @ExcelProperty("长者姓名")
+    private String elderName;
+
+    @ExcelProperty("合同号")
+    private String contractNumber;
+
+    @ExcelProperty("情况发现时间")
+    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
+    private Date discoveryTime;
+
+    @ExcelProperty("情况发现人")
+    private String discoverer;
+
+    @ExcelProperty("情况描述")
+    private String conditionDesc;
+
+    @ExcelProperty("处理说明")
+    private String handlingNote;
+}

+ 55 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/MedicalCareRecordsRespVO.java

@@ -0,0 +1,55 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.AttachmentsDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+@Schema(description = "管理后台 - 医疗护理记录 Response VO")
+@Data
+public class MedicalCareRecordsRespVO {
+
+    @Schema(description = "记录ID(主键)")
+    private Integer recordId;
+
+    @Schema(description = "长者ID")
+    private Integer elderId;
+
+    @Schema(description = "长者姓名")
+    private String elderName;
+
+    @Schema(description = "合同编号")
+    private String contractNumber;
+
+    @Schema(description = "情况发现时间")
+    private Date discoveryTime;
+
+    @Schema(description = "情况发现人")
+    private String discoverer;
+
+    @Schema(description = "情况描述")
+    private String conditionDesc;
+
+    @Schema(description = "处理说明")
+    private String handlingNote;
+
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "最后更新时间")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "长者信息")
+    private ElderlyInfoDO elderlyInfo;
+
+    @Schema(description = "附件")
+    private List<AttachmentsDO> attachments;
+
+    @Schema(description = "床位信息")
+    private String bedInfo;
+}
+

+ 46 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/MedicalRecordsImportExcelVO.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false)
+public class MedicalRecordsImportExcelVO {
+    @ExcelProperty("长者姓名")
+    private String elderName;
+
+    @ExcelProperty("合同号")
+    private String contractNumber;
+
+    @ExcelProperty("情况发现时间")
+    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
+    private Date discoveryTime;
+
+    @ExcelProperty("情况发现人")
+    private String discoverer;
+
+    @ExcelProperty("情况描述")
+    private String conditionDesc;
+
+    @ExcelProperty("处理说明")
+    private String handlingNote;
+
+    @ExcelProperty("沟通的长者家属")
+    private String communicateFamilyMember;
+
+    @ExcelProperty("沟通方式")
+    private String communicateType;
+
+    @ExcelProperty("电话")
+    private String phone;
+}

+ 63 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/MedicalRecordsRespVO.java

@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.AttachmentsDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+@Schema(description = "管理后台 - 医疗记录 Response VO")
+@Data
+public class MedicalRecordsRespVO {
+
+    @Schema(description = "记录ID(主键)")
+    private Integer recordId;
+
+    @Schema(description = "长者ID")
+    private Integer elderId;
+
+    @Schema(description = "长者姓名")
+    private String elderName;
+
+    @Schema(description = "合同编号")
+    private String contractNumber;
+
+    @Schema(description = "情况发现时间")
+    private Date discoveryTime;
+
+    @Schema(description = "情况发现人")
+    private String discoverer;
+
+    @Schema(description = "情况描述")
+    private String conditionDesc;
+
+    @Schema(description = "处理说明")
+    private String handlingNote;
+
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "最后更新时间")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "长者信息")
+    private ElderlyInfoDO elderlyInfo;
+
+    @Schema(description = "附件列表")
+    private List<AttachmentsDO> attachments;
+
+    @Schema(description = "床位信息")
+    private String bedInfo;
+
+    @Schema(description = "沟通的长者家属")
+    private String communicateFamilyMember;
+
+    @Schema(description = "沟通方式")
+    private String communicateType;
+
+    @Schema(description = "电话")
+    private String phone;
+}

+ 34 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/NutritionRecordImportExcelVO.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false)
+public class NutritionRecordImportExcelVO {
+    @ExcelProperty("长者姓名")
+    private String elderName;
+
+    @ExcelProperty("合同号")
+    private String contractNumber;
+
+    @ExcelProperty("记录时间")
+    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
+    private Date recordTime;
+
+    @ExcelProperty("营养师")
+    private String dietitian;
+
+    @ExcelProperty("记录内容")
+    private String recordContent;
+}

+ 46 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/NutritionRecordRespVO.java

@@ -0,0 +1,46 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Schema(description = "管理后台 - 营养记录 Response VO")
+@Data
+public class NutritionRecordRespVO {
+
+    @Schema(description = "训练记录ID(主键,自增)")
+    private Integer recordId;
+
+    @Schema(description = "长者ID")
+    private Integer elderId;
+
+    @Schema(description = "长者姓名")
+    private String elderName;
+
+    @Schema(description = "合同编号")
+    private String contractNumber;
+
+    @Schema(description = "记录时间")
+    private Date recordTime;
+
+    @Schema(description = "营养师")
+    private String dietitian;
+
+    @Schema(description = "记录内容")
+    private String recordContent;
+
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "最后更新时间")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "床位信息")
+    private String bedInfo;
+
+    @Schema(description = "长者信息")
+    private ElderlyInfoDO elderlyInfo;
+}

+ 3 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/RecordsPageReqVO.java

@@ -38,4 +38,7 @@ public class RecordsPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
+    @Schema(description = "是否沟通 0 是全部。1 是沟通过,2 是没沟通")
+    private Integer isCommunication;
+
 }

+ 49 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/RehabilitationAssessmentsImportExcelVO.java

@@ -0,0 +1,49 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false)
+public class RehabilitationAssessmentsImportExcelVO {
+    @ExcelProperty("长者姓名")
+    private String elderName;
+
+    @ExcelProperty("合同号")
+    private String contractNumber;
+
+    @ExcelProperty("评估时间")
+    @DateTimeFormat("yyyy-MM-dd")
+    private Date assessmentTime;
+
+    @ExcelProperty("评估次数")
+    private Integer assessmentTimes;
+
+    @ExcelProperty("康复师")
+    private String therapist;
+
+    @ExcelProperty("入住情况")
+    private String admissionCondition;
+
+    @ExcelProperty("功能障碍")
+    private String dysfunction;
+
+    @ExcelProperty("康复方式")
+    private String rehabilitationMethod;
+
+    @ExcelProperty("康复计划")
+    private String rehabilitationPlan;
+
+    @ExcelProperty("预期效果")
+    private String expectedEffect;
+}

+ 61 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/RehabilitationAssessmentsRespVO.java

@@ -0,0 +1,61 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Schema(description = "管理后台 - 康复评估记录 Response VO")
+@Data
+public class RehabilitationAssessmentsRespVO {
+
+    @Schema(description = "评估记录ID(主键,自增)")
+    private Integer assessmentId;
+
+    @Schema(description = "长者ID")
+    private Integer elderId;
+
+    @Schema(description = "长者姓名")
+    private String elderName;
+
+    @Schema(description = "合同编号")
+    private String contractNumber;
+
+    @Schema(description = "评估时间")
+    private Date assessmentTime;
+
+    @Schema(description = "评估次数")
+    private Integer assessmentTimes;
+
+    @Schema(description = "康复师")
+    private String therapist;
+
+    @Schema(description = "入住情况")
+    private String admissionCondition;
+
+    @Schema(description = "功能障碍")
+    private String dysfunction;
+
+    @Schema(description = "康复方式")
+    private String rehabilitationMethod;
+
+    @Schema(description = "康复计划")
+    private String rehabilitationPlan;
+
+    @Schema(description = "预期效果")
+    private String expectedEffect;
+
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "最后更新时间")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "床位信息")
+    private String bedInfo;
+
+    @Schema(description = "长者信息")
+    private ElderlyInfoDO elderlyInfo;
+}

+ 34 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/TrainingRecordsImportExcelVO.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.format.DateTimeFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Accessors(chain = false)
+public class TrainingRecordsImportExcelVO {
+    @ExcelProperty("长者姓名")
+    private String elderName;
+
+    @ExcelProperty("合同号")
+    private String contractNumber;
+
+    @ExcelProperty("训练时间")
+    @DateTimeFormat("yyyy-MM-dd")
+    private Date trainingTime;
+
+    @ExcelProperty("康复师")
+    private String therapist;
+
+    @ExcelProperty("记录内容")
+    private String recordContent;
+}

+ 51 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/TrainingRecordsRespVO.java

@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
+
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.AttachmentsDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+@Schema(description = "管理后台 - 康复训练记录 Response VO")
+@Data
+public class TrainingRecordsRespVO {
+
+    @Schema(description = "训练记录ID(主键,自增)")
+    private Integer recordId;
+
+    @Schema(description = "长者ID")
+    private Integer elderId;
+
+    @Schema(description = "长者姓名")
+    private String elderName;
+
+    @Schema(description = "合同编号")
+    private String contractNumber;
+
+    @Schema(description = "训练时间")
+    private Date trainingTime;
+
+    @Schema(description = "康复师")
+    private String therapist;
+
+    @Schema(description = "记录内容")
+    private String recordContent;
+
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "最后更新时间")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "长者信息")
+    private ElderlyInfoDO elderlyInfo;
+
+    @Schema(description = "附件")
+    private List<AttachmentsDO> attachments;
+
+    @Schema(description = "床位信息")
+    private String bedInfo;
+}

+ 15 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/MedicalRecordsDO.java

@@ -62,6 +62,21 @@ public class MedicalRecordsDO {
      */
     @Schema(description = "处理说明")
     private String handlingNote;
+    /**
+     * 沟通的长者家属
+     */
+    @Schema(description = "沟通的长者家属")
+    private String communicateFamilyMember;
+    /**
+     * 沟通方式
+     */
+    @Schema(description = "沟通方式")
+    private String communicateType;
+    /**
+     * 电话
+     */
+    @Schema(description = "电话")
+    private String phone;
 
     @Schema(description = "创建时间")
     private LocalDateTime createTime;

+ 12 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/ElderlyContractMapper.java

@@ -1,6 +1,8 @@
 package cn.iocoder.yudao.module.system.dal.mysql.biz;
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ContractPageReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyContractDO;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -28,4 +30,14 @@ public interface ElderlyContractMapper extends BaseMapperX<ElderlyContractDO> {
     int batchUpdateStatusToNotStarted(@Param("tenantId") Long tenantId, @Param("nowDate") Date nowDate);
 
     int batchUpdateStatusToExpired(@Param("tenantId") Long tenantId, @Param("nowDate") Date nowDate);
+
+    default ElderlyContractDO selectValidContract(String contractNumber) {
+        return selectOne(new LambdaQueryWrapperX<ElderlyContractDO>()
+                        .eq(ElderlyContractDO::getContractNumber, contractNumber)
+                        .eq(ElderlyContractDO::getTenantId, TenantContextHolder.getTenantId())
+                        .eq(ElderlyContractDO::getStatus, 1)
+                        .orderByDesc(ElderlyContractDO::getCreatedTime)
+                        .last("LIMIT 1")
+        );
+    }
 }

+ 21 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/MedicalRecordsMapper.java

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.RecordsPageReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.MedicalRecordsDO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
 
@@ -18,15 +19,32 @@ import org.apache.ibatis.annotations.Mapper;
 public interface MedicalRecordsMapper extends BaseMapperX<MedicalRecordsDO> {
 
     default PageResult<MedicalRecordsDO> selectPage(RecordsPageReqVO reqVO) {
-        return selectPage(reqVO, new LambdaQueryWrapperX<MedicalRecordsDO>()
+        LambdaQueryWrapper<MedicalRecordsDO> medicalRecordsDOLambdaQueryWrapper = new LambdaQueryWrapperX<MedicalRecordsDO>()
                 .eqIfPresent(MedicalRecordsDO::getElderId, reqVO.getElderId())
                 .betweenIfPresent(MedicalRecordsDO::getDiscoveryTime, reqVO.getDiscoveryTime())
                 .eqIfPresent(MedicalRecordsDO::getDiscoverer, reqVO.getDiscoverer())
                 .eqIfPresent(MedicalRecordsDO::getConditionDesc, reqVO.getConditionDesc())
                 .eqIfPresent(MedicalRecordsDO::getHandlingNote, reqVO.getHandlingNote())
                 .eqIfPresent(MedicalRecordsDO::getTenantId, reqVO.getTenantId())
-                .likeIfPresent(MedicalRecordsDO::getElderName, reqVO.getElderName())
-                .orderByDesc(MedicalRecordsDO::getDiscoveryTime,MedicalRecordsDO::getUpdateTime,MedicalRecordsDO::getCreateTime));
+                .likeIfPresent(MedicalRecordsDO::getElderName, reqVO.getElderName());
+        if(reqVO.getIsCommunication() == 1){
+            medicalRecordsDOLambdaQueryWrapper = medicalRecordsDOLambdaQueryWrapper.isNotNull(MedicalRecordsDO::getCommunicateFamilyMember)
+                    .isNotNull(MedicalRecordsDO::getCommunicateType)
+                    .ne(MedicalRecordsDO::getCommunicateFamilyMember,"")
+                    .ne(MedicalRecordsDO::getCommunicateType,"");
+        }else if(reqVO.getIsCommunication() == 2){
+            medicalRecordsDOLambdaQueryWrapper = medicalRecordsDOLambdaQueryWrapper.and(wrapper ->
+                    wrapper.isNull(MedicalRecordsDO::getCommunicateFamilyMember)
+                            .or()
+                            .eq(MedicalRecordsDO::getCommunicateFamilyMember, "")
+                            .or()
+                            .isNull(MedicalRecordsDO::getCommunicateType)
+                            .or()
+                            .eq(MedicalRecordsDO::getCommunicateType, "")
+            );
+        }
+        return selectPage(reqVO, medicalRecordsDOLambdaQueryWrapper
+                .orderByDesc(MedicalRecordsDO::getDiscoveryTime, MedicalRecordsDO::getUpdateTime, MedicalRecordsDO::getCreateTime));
     }
 
 }

+ 22 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyInfoServiceImpl.java

@@ -191,9 +191,19 @@ public class ElderlyInfoServiceImpl implements ElderlyInfoService {
     private static final ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(10);
     private static final long TIMEOUT_DURATION = 5; // 设置超时时间为5秒
 
+    private static final Map<String, String> SORT_FIELD_MAP;
+
+    static {
+        Map<String, String> tempMap = new HashMap<>();
+        tempMap.put("checkInTime", "ei.check_in_time");
+        tempMap.put("contractNumber", "ec.contract_number");
+        SORT_FIELD_MAP = Collections.unmodifiableMap(tempMap);
+    }
+
     @Override
     public PageResult<ElderlyInfoDO> findPage(ElderlyInfoPageReqVO pageVO) {
         Page<ElderlyInfoDO> page = new Page<>(pageVO.getPageNo(), pageVO.getPageSize());
+        pageVO.setOrderByClause(buildOrderBy(pageVO.getProp(), pageVO.getOrder()));
         List<ElderlyInfoDO> list = elderlyInfoMapper.findPage(page, pageVO);
         for (ElderlyInfoDO elderlyInfoDO : list) {
             elderlyInfoDO.setBedName(buildService.getFullBedName(elderlyInfoDO.getId()));
@@ -2517,6 +2527,18 @@ public class ElderlyInfoServiceImpl implements ElderlyInfoService {
         }
     }
 
+
+    private String buildOrderBy(String prop, String order) {
+        if (prop == null) return "ei.update_time desc"; // 默认排序
+        String field = SORT_FIELD_MAP.get(prop);
+        if (field == null) {
+            return "ei.update_time desc"; // 非法字段用默认
+        }
+        if (!"asc".equalsIgnoreCase(order) && !"desc".equalsIgnoreCase(order)) {
+            order = "asc";
+        }
+        return field + " " + order + ", ei.update_time desc";
+    }
 }
 
 

+ 9 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/FamilyCommunicationRecordService.java

@@ -4,7 +4,12 @@ package cn.iocoder.yudao.module.system.service.biz;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CommunicationRecordPageReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CommunicationRecordRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.FamilyCommunicationRecordDO;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 
 /**
  * 家属沟通记录 Service 接口
@@ -51,4 +56,8 @@ public interface FamilyCommunicationRecordService {
      */
     PageResult<CommunicationRecordRespVO> getCommunicationRecordPage(CommunicationRecordPageReqVO pageReqVO);
 
+    void exportImportTemplate(HttpServletResponse response) throws IOException;
+
+    ImportResultVO importFamilyCommunicationRecord(MultipartFile file) throws Exception;
+
 }

+ 81 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/FamilyCommunicationRecordServiceImpl.java

@@ -1,19 +1,34 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CommunicationRecordPageReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CommunicationRecordRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.FamilyCommunicationRecordImportExcelVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyContractDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.FamilyCommunicationRecordDO;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyContractMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.FamilyCommunicationRecordMapper;
+import cn.iocoder.yudao.module.system.util.ImportUtil;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
 import org.springframework.validation.annotation.Validated;
 
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 
 /**
@@ -32,6 +47,9 @@ public class FamilyCommunicationRecordServiceImpl implements FamilyCommunication
     @Resource
     private ElderlyInfoMapper elderlyInfoMapper;
 
+    @Resource
+    private ElderlyContractMapper elderlyContractMapper;
+
     @Override
     public void createCommunicationRecord(FamilyCommunicationRecordDO createReqVO) {
 
@@ -68,8 +86,71 @@ public class FamilyCommunicationRecordServiceImpl implements FamilyCommunication
         PageResult<CommunicationRecordRespVO> pageResult = BeanUtils.toBean(result, CommunicationRecordRespVO.class);
         for (CommunicationRecordRespVO communicationRecordRespVO : pageResult.getList()) {
             communicationRecordRespVO.setBedInfo(buildService.getFullBedName(communicationRecordRespVO.getElderId()));
+            ElderlyContractDO contract = elderlyContractMapper.selectOne(new LambdaQueryWrapperX<ElderlyContractDO>()
+                    .eq(ElderlyContractDO::getElderId, communicationRecordRespVO.getElderId())
+                    .eq(ElderlyContractDO::getStatus, 1)
+                    .orderByDesc(ElderlyContractDO::getCreatedTime)
+                    .last("LIMIT 1"));
+            if (contract != null) {
+                communicationRecordRespVO.setContractNumber(contract.getContractNumber());
+            }
         }
         return pageResult;
     }
 
+    @Override
+    public void exportImportTemplate(HttpServletResponse response) throws IOException {
+        ExcelUtils.write(response, "家属沟通记录导入模板.xlsx", "模板",
+                FamilyCommunicationRecordImportExcelVO.class, java.util.Collections.emptyList());
+    }
+
+    @Override
+    public ImportResultVO importFamilyCommunicationRecord(MultipartFile file) throws Exception {
+        List<FamilyCommunicationRecordImportExcelVO> list = ExcelUtils.read(file, FamilyCommunicationRecordImportExcelVO.class);
+
+        int rowNum = 1;
+        int success = 0;
+        List<ImportResultVO.RowError> failures = new ArrayList<>();
+
+        for (FamilyCommunicationRecordImportExcelVO row : list) {
+            rowNum++;
+
+            if (StrUtil.isEmpty(row.getContractNumber())) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同号不能为空");
+                continue;
+            }
+
+            ElderlyContractDO contract = elderlyContractMapper.selectValidContract(row.getContractNumber());
+            if (contract == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "未找到对应合同或合同状态无效");
+                continue;
+            }
+            if (contract.getElderId() == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同未关联长者");
+                continue;
+            }
+
+            FamilyCommunicationRecordDO record = new FamilyCommunicationRecordDO();
+            record.setElderId(contract.getElderId()); // Long
+            record.setElderName(StrUtil.blankToDefault(row.getElderName(), contract.getElderName()));
+            record.setCommunicationTime(row.getCommunicationTime());
+            record.setCommunicationMethod(row.getCommunicationMethod());
+            record.setServicePerson(row.getServicePerson());
+            record.setFamilyName(row.getFamilyName());
+            record.setRelationshipWithElder(row.getRelationshipWithElder());
+            record.setCommunicationContent(row.getCommunicationContent());
+            record.setSolutionEffect(row.getSolutionEffect());
+            record.setTenantId(TenantContextHolder.getTenantId());
+
+            try {
+                communicationRecordMapper.insert(record);
+                success++;
+            } catch (Exception e) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "插入数据库失败", e);
+            }
+        }
+
+        return ImportUtil.buildResult(success, failures);
+    }
+
 }

+ 13 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/MedicalCareRecordsService.java

@@ -1,9 +1,16 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.*;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CareRecordsPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.MedicalCareRecordsRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.MedicalCareRecordsDO;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.text.ParseException;
 
 /**
  * 医疗护理记录主 Service 接口
@@ -48,6 +55,11 @@ public interface MedicalCareRecordsService {
      * @param pageReqVO 分页查询
      * @return 医疗护理记录主分页
      */
-    PageResult<MedicalCareRecordsDO> getCareRecordsPage(CareRecordsPageReqVO pageReqVO);
+    PageResult<MedicalCareRecordsRespVO> getCareRecordsPage(CareRecordsPageReqVO pageReqVO);
+
+
+    // 新增:
+    void exportImportTemplate(HttpServletResponse response) throws IOException;
 
+    ImportResultVO importCareRecords(MultipartFile file) throws IOException;
 }

+ 89 - 6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/MedicalCareRecordsServiceImpl.java

@@ -1,24 +1,42 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.CareRecordsPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.MedicalCareRecordsImportExcelVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.MedicalCareRecordsRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.AttachmentsDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyContractDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.MedicalCareRecordsDO;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.AttachmentsMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyContractMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.MedicalCareRecordsMapper;
 import cn.iocoder.yudao.module.system.enums.AttachmentsConstants;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import cn.iocoder.yudao.module.system.util.ImportUtil;
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.alibaba.excel.metadata.data.ReadCellData;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
 import org.springframework.validation.annotation.Validated;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
 import java.time.LocalDateTime;
-import java.util.List;
+import java.util.*;
+
+import static org.apache.commons.lang3.time.DateUtils.parseDate;
 
 
 /**
@@ -37,6 +55,8 @@ public class MedicalCareRecordsServiceImpl implements MedicalCareRecordsService
     @Resource
     private ElderlyInfoMapper elderlyInfoMapper;
     @Resource
+    private ElderlyContractMapper elderlyContractMapper;
+    @Resource
     private BuildService buildService;
 
     @Override
@@ -102,12 +122,75 @@ public class MedicalCareRecordsServiceImpl implements MedicalCareRecordsService
     }
 
     @Override
-    public PageResult<MedicalCareRecordsDO> getCareRecordsPage(CareRecordsPageReqVO pageReqVO) {
+    public PageResult<MedicalCareRecordsRespVO> getCareRecordsPage(CareRecordsPageReqVO pageReqVO) {
         PageResult<MedicalCareRecordsDO> pageResult = careRecordsMapper.selectPage(pageReqVO);
-        for (MedicalCareRecordsDO medicalCareRecordsDO : pageResult.getList()) {
-            medicalCareRecordsDO.setBedInfo(buildService.getFullBedName(Long.valueOf(medicalCareRecordsDO.getElderId())));
+        PageResult<MedicalCareRecordsRespVO> resp = BeanUtils.toBean(pageResult, MedicalCareRecordsRespVO.class);
+        for (MedicalCareRecordsRespVO vo : resp.getList()) {
+            vo.setBedInfo(buildService.getFullBedName(Long.valueOf(vo.getElderId())));
+            ElderlyContractDO contract = elderlyContractMapper.selectOne(new LambdaQueryWrapperX<ElderlyContractDO>()
+                    .eq(ElderlyContractDO::getElderId, vo.getElderId())
+                    .eq(ElderlyContractDO::getStatus, 1)
+                    .orderByDesc(ElderlyContractDO::getCreatedTime)
+                    .last("LIMIT 1"));
+            if (contract != null) {
+                vo.setContractNumber(contract.getContractNumber());
+            }
         }
-        return pageResult;
+        return resp;
     }
 
+    @Override
+    public void exportImportTemplate(HttpServletResponse response) throws IOException {
+        List<MedicalCareRecordsImportExcelVO> list = Collections.emptyList();
+        // 假设你们有 ExcelUtils;如果没有,就用 EasyExcel.write(response.getOutputStream(), MedicalCareRecordsImportExcelVO.class)...
+        ExcelUtils.write(response, "医疗护理记录导入模板.xlsx", "模板",
+                MedicalCareRecordsImportExcelVO.class, list);
+    }
+    @Override
+    public ImportResultVO importCareRecords(MultipartFile file) throws IOException {
+        List<MedicalCareRecordsImportExcelVO> list = ExcelUtils.read(file, MedicalCareRecordsImportExcelVO.class);
+
+        int rowNum = 1; // 如果第一行是表头,则数据从第 2 行开始,按你实际偏移
+        int success = 0;
+        List<ImportResultVO.RowError> failures = new ArrayList<>();
+
+        for (MedicalCareRecordsImportExcelVO row : list) {
+            rowNum++;
+
+            // 1. 简单校验
+            if (StrUtil.isEmpty(row.getContractNumber())) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(),"合同编号不能为空");
+                continue;
+            }
+            // 2. 用合同号找长者(只匹配当前租户 + 有效合同 + 最新一条)
+            ElderlyContractDO contract = elderlyContractMapper.selectValidContract(row.getContractNumber());
+            if (contract == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(),"未找到对应合同或合同状态无效");
+                continue;
+            }
+
+            if (contract.getElderId() == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(),"合同未关联长者");
+                continue;
+            }
+
+            // 3. 组装 DO
+            MedicalCareRecordsDO record = new MedicalCareRecordsDO();
+            record.setElderId(contract.getElderId().intValue());
+            record.setElderName(row.getElderName() != null ? row.getElderName() : contract.getElderName());
+            record.setDiscoveryTime(row.getDiscoveryTime());
+            record.setDiscoverer(row.getDiscoverer());
+            record.setConditionDesc(row.getConditionDesc());
+            record.setHandlingNote(row.getHandlingNote());
+            record.setTenantId(TenantContextHolder.getTenantId());
+
+            try {
+                careRecordsMapper.insert(record);
+                success++;
+            } catch (Exception e) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(),"插入数据库失败:" + e.getMessage());
+            }
+        }
+        return ImportUtil.buildResult(success,failures);
+    }
 }

+ 11 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/MedicalRecordsService.java

@@ -1,8 +1,14 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.MedicalRecordsRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.RecordsPageReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.MedicalRecordsDO;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 
 /**
  * 医疗记录主 Service 接口
@@ -47,6 +53,10 @@ public interface MedicalRecordsService {
      * @param pageReqVO 分页查询
      * @return 医疗记录主分页
      */
-    PageResult<MedicalRecordsDO> getRecordsPage(RecordsPageReqVO pageReqVO);
+    PageResult<MedicalRecordsRespVO> getRecordsPage(RecordsPageReqVO pageReqVO);
+
+    void exportImportTemplate(HttpServletResponse response) throws IOException;
+
+    ImportResultVO importMedicalRecords(MultipartFile file) throws Exception;
 
 }

+ 79 - 5
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/MedicalRecordsServiceImpl.java

@@ -1,26 +1,38 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.MedicalRecordsImportExcelVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.MedicalRecordsRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.RecordsPageReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.AttachmentsDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyContractDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.MedicalRecordsDO;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.AttachmentsMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyContractMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.MedicalRecordsMapper;
 import cn.iocoder.yudao.module.system.enums.AttachmentsConstants;
+import cn.iocoder.yudao.module.system.util.ImportUtil;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
 
 import org.springframework.validation.annotation.Validated;
+import org.springframework.web.multipart.MultipartFile;
 
 
-
+import java.io.IOException;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.List;
 
 
@@ -42,6 +54,8 @@ public class MedicalRecordsServiceImpl implements MedicalRecordsService {
     @Resource
     private ElderlyInfoMapper elderlyInfoMapper;
     @Resource
+    private ElderlyContractMapper elderlyContractMapper;
+    @Resource
     private BuildService buildService;
 
     @Override
@@ -107,12 +121,72 @@ public class MedicalRecordsServiceImpl implements MedicalRecordsService {
     }
 
     @Override
-    public PageResult<MedicalRecordsDO> getRecordsPage(RecordsPageReqVO pageReqVO) {
+    public PageResult<MedicalRecordsRespVO> getRecordsPage(RecordsPageReqVO pageReqVO) {
         PageResult<MedicalRecordsDO> pageResult = recordsMapper.selectPage(pageReqVO);
-        for (MedicalRecordsDO medicalRecordsDO : pageResult.getList()) {
-            medicalRecordsDO.setBedInfo(buildService.getFullBedName(Long.valueOf(medicalRecordsDO.getElderId())));
+        PageResult<MedicalRecordsRespVO> resp = BeanUtils.toBean(pageResult, MedicalRecordsRespVO.class);
+        for (MedicalRecordsRespVO vo : resp.getList()) {
+            vo.setBedInfo(buildService.getFullBedName(Long.valueOf(vo.getElderId())));
+            ElderlyContractDO contract = elderlyContractMapper.selectOne(new LambdaQueryWrapperX<ElderlyContractDO>()
+                    .eq(ElderlyContractDO::getElderId, vo.getElderId())
+                    .eq(ElderlyContractDO::getStatus, 1)
+                    .orderByDesc(ElderlyContractDO::getCreatedTime)
+                    .last("LIMIT 1"));
+            if (contract != null) {
+                vo.setContractNumber(contract.getContractNumber());
+            }
         }
-        return pageResult;
+        return resp;
+    }
+
+    @Override
+    public void exportImportTemplate(HttpServletResponse response) throws IOException {
+        ExcelUtils.write(response, "医疗记录导入模板.xlsx", "模板",
+                MedicalRecordsImportExcelVO.class, java.util.Collections.emptyList());
     }
 
+    @Override
+    public ImportResultVO importMedicalRecords(MultipartFile file) throws Exception {
+        List<MedicalRecordsImportExcelVO> list = ExcelUtils.read(file, MedicalRecordsImportExcelVO.class);
+
+        int rowNum = 1;
+        int success = 0;
+        List<ImportResultVO.RowError> failures = new ArrayList<>();
+
+        for (MedicalRecordsImportExcelVO row : list) {
+            rowNum++;
+
+            if (StrUtil.isEmpty(row.getContractNumber())) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同号不能为空");
+                continue;
+            }
+
+            ElderlyContractDO contract = elderlyContractMapper.selectValidContract(row.getContractNumber());
+            if (contract == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "未找到对应合同或合同状态无效");
+                continue;
+            }
+            if (contract.getElderId() == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同未关联长者");
+                continue;
+            }
+
+            MedicalRecordsDO record = new MedicalRecordsDO();
+            record.setElderId(contract.getElderId().intValue());
+            record.setElderName(StrUtil.blankToDefault(row.getElderName(), contract.getElderName()));
+            record.setDiscoveryTime(row.getDiscoveryTime());
+            record.setDiscoverer(row.getDiscoverer());
+            record.setConditionDesc(row.getConditionDesc());
+            record.setHandlingNote(row.getHandlingNote());
+            record.setTenantId(TenantContextHolder.getTenantId());
+
+            try {
+                recordsMapper.insert(record);
+                success++;
+            } catch (Exception e) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "插入数据库失败", e);
+            }
+        }
+
+        return ImportUtil.buildResult(success, failures);
+    }
 }

+ 11 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/NutritionRecordService.java

@@ -2,8 +2,14 @@ package cn.iocoder.yudao.module.system.service.biz;
 
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.NutritionRecordPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.NutritionRecordRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.NutritionRecordDO;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
 
 /**
  * 营养记录 Service 接口
@@ -48,6 +54,10 @@ public interface NutritionRecordService {
      * @param pageReqVO 分页查询
      * @return 营养记录分页
      */
-    PageResult<NutritionRecordDO> getRecordPage(NutritionRecordPageReqVO pageReqVO);
+    PageResult<NutritionRecordRespVO> getRecordPage(NutritionRecordPageReqVO pageReqVO);
+
+    void exportImportTemplate(HttpServletResponse response) throws IOException;
+
+    ImportResultVO importNutritionRecord(MultipartFile file) throws Exception;
 
 }

+ 82 - 5
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/NutritionRecordServiceImpl.java

@@ -1,15 +1,30 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
-import cn.iocoder.yudao.module.system.controller.admin.biz.vo.NutritionRecordPageReqVO;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyContractDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.NutritionRecordDO;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyContractMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.NutritionRecordMapper;
+import cn.iocoder.yudao.module.system.util.ImportUtil;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
 import org.springframework.validation.annotation.Validated;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 
 /**
@@ -28,6 +43,9 @@ public class NutritionRecordServiceImpl implements NutritionRecordService {
     @Resource
     private BuildService buildService;
 
+    @Resource
+    private ElderlyContractMapper elderlyContractMapper;
+
     @Override
     public void createRecord(NutritionRecordDO createReqVO) {
         // 插入
@@ -58,12 +76,71 @@ public class NutritionRecordServiceImpl implements NutritionRecordService {
     }
 
     @Override
-    public PageResult<NutritionRecordDO> getRecordPage(NutritionRecordPageReqVO pageReqVO) {
+    public PageResult<NutritionRecordRespVO> getRecordPage(NutritionRecordPageReqVO pageReqVO) {
         PageResult<NutritionRecordDO> pageResult = recordMapper.selectPage(pageReqVO);
-        for (NutritionRecordDO nutritionRecordDO : pageResult.getList()) {
-            nutritionRecordDO.setBedInfo(buildService.getFullBedName(Long.valueOf(nutritionRecordDO.getElderId())));
+        PageResult<NutritionRecordRespVO> resp = BeanUtils.toBean(pageResult, NutritionRecordRespVO.class);
+        for (NutritionRecordRespVO vo : resp.getList()) {
+            vo.setBedInfo(buildService.getFullBedName(Long.valueOf(vo.getElderId())));
+            ElderlyContractDO contract = elderlyContractMapper.selectOne(new LambdaQueryWrapperX<ElderlyContractDO>()
+                    .eq(ElderlyContractDO::getElderId, vo.getElderId())
+                    .eq(ElderlyContractDO::getStatus, 1)
+                    .orderByDesc(ElderlyContractDO::getCreatedTime)
+                    .last("LIMIT 1"));
+            if (contract != null) {
+                vo.setContractNumber(contract.getContractNumber());
+            }
         }
-        return pageResult;
+        return resp;
     }
 
+    @Override
+    public void exportImportTemplate(HttpServletResponse response) throws IOException {
+        ExcelUtils.write(response, "营养记录导入模板.xlsx", "模板",
+                NutritionRecordImportExcelVO.class, java.util.Collections.emptyList());
+    }
+
+    @Override
+    public ImportResultVO importNutritionRecord(MultipartFile file) throws Exception {
+        List<NutritionRecordImportExcelVO> list = ExcelUtils.read(file, NutritionRecordImportExcelVO.class);
+
+        int rowNum = 1;
+        int success = 0;
+        List<ImportResultVO.RowError> failures = new ArrayList<>();
+
+        for (NutritionRecordImportExcelVO row : list) {
+            rowNum++;
+
+            if (StrUtil.isEmpty(row.getContractNumber())) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同号不能为空");
+                continue;
+            }
+
+            ElderlyContractDO contract = elderlyContractMapper.selectValidContract(row.getContractNumber());
+            if (contract == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "未找到对应合同或合同状态无效");
+                continue;
+            }
+            if (contract.getElderId() == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同未关联长者");
+                continue;
+            }
+
+            NutritionRecordDO record = new NutritionRecordDO();
+            record.setElderId(contract.getElderId().intValue());
+            record.setElderName(StrUtil.blankToDefault(row.getElderName(), contract.getElderName()));
+            record.setRecordTime(row.getRecordTime());
+            record.setDietitian(row.getDietitian());
+            record.setRecordContent(row.getRecordContent());
+            record.setTenantId(TenantContextHolder.getTenantId());
+
+            try {
+                recordMapper.insert(record);
+                success++;
+            } catch (Exception e) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "插入数据库失败", e);
+            }
+        }
+
+        return ImportUtil.buildResult(success, failures);
+    }
 }

+ 11 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/RehabilitationAssessmentsService.java

@@ -1,9 +1,15 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.*;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.AssessmentsPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.RehabilitationAssessmentsRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.RehabilitationAssessmentsDO;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
 
 /**
  * 康复评估记录 Service 接口
@@ -48,6 +54,10 @@ public interface RehabilitationAssessmentsService {
      * @param pageReqVO 分页查询
      * @return 康复评估记录分页
      */
-    PageResult<RehabilitationAssessmentsDO> getAssessmentsPage(AssessmentsPageReqVO pageReqVO);
+    PageResult<RehabilitationAssessmentsRespVO> getAssessmentsPage(AssessmentsPageReqVO pageReqVO);
+
+    void exportImportTemplate(HttpServletResponse response) throws IOException;
+
+    ImportResultVO importRehabilitationAssessments(MultipartFile file) throws Exception;
 
 }

+ 88 - 5
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/RehabilitationAssessmentsServiceImpl.java

@@ -1,15 +1,30 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
-import cn.iocoder.yudao.module.system.controller.admin.biz.vo.AssessmentsPageReqVO;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyContractDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.RehabilitationAssessmentsDO;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyContractMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.RehabilitationAssessmentsMapper;
+import cn.iocoder.yudao.module.system.util.ImportUtil;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
 import org.springframework.validation.annotation.Validated;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 
 /**
@@ -28,6 +43,9 @@ public class RehabilitationAssessmentsServiceImpl implements RehabilitationAsses
     @Resource
     private BuildService buildService;
 
+    @Resource
+    private ElderlyContractMapper elderlyContractMapper;
+
     @Override
     public Integer createAssessments(RehabilitationAssessmentsDO createReqVO) {
         // 插入
@@ -59,12 +77,77 @@ public class RehabilitationAssessmentsServiceImpl implements RehabilitationAsses
     }
 
     @Override
-    public PageResult<RehabilitationAssessmentsDO> getAssessmentsPage(AssessmentsPageReqVO pageReqVO) {
+    public PageResult<RehabilitationAssessmentsRespVO> getAssessmentsPage(AssessmentsPageReqVO pageReqVO) {
         PageResult<RehabilitationAssessmentsDO> pageResult = assessmentsMapper.selectPage(pageReqVO);
-        for (RehabilitationAssessmentsDO rehabilitationAssessmentsDO : pageResult.getList()) {
-            rehabilitationAssessmentsDO.setBedInfo(buildService.getFullBedName(Long.valueOf(rehabilitationAssessmentsDO.getElderId())));
+        PageResult<RehabilitationAssessmentsRespVO> resp = BeanUtils.toBean(pageResult, RehabilitationAssessmentsRespVO.class);
+        for (RehabilitationAssessmentsRespVO vo : resp.getList()) {
+            vo.setBedInfo(buildService.getFullBedName(Long.valueOf(vo.getElderId())));
+            ElderlyContractDO contract = elderlyContractMapper.selectOne(new LambdaQueryWrapperX<ElderlyContractDO>()
+                    .eq(ElderlyContractDO::getElderId, vo.getElderId())
+                    .eq(ElderlyContractDO::getStatus, 1)
+                    .orderByDesc(ElderlyContractDO::getCreatedTime)
+                    .last("LIMIT 1"));
+            if (contract != null) {
+                vo.setContractNumber(contract.getContractNumber());
+            }
+        }
+        return resp;
+    }
+
+    @Override
+    public void exportImportTemplate(HttpServletResponse response) throws IOException {
+        ExcelUtils.write(response, "康复评估记录导入模板.xlsx", "模板",
+                RehabilitationAssessmentsImportExcelVO.class, java.util.Collections.emptyList());
+    }
+
+    @Override
+    public ImportResultVO importRehabilitationAssessments(MultipartFile file) throws Exception {
+        List<RehabilitationAssessmentsImportExcelVO> list = ExcelUtils.read(file, RehabilitationAssessmentsImportExcelVO.class);
+
+        int rowNum = 1;
+        int success = 0;
+        List<ImportResultVO.RowError> failures = new ArrayList<>();
+
+        for (RehabilitationAssessmentsImportExcelVO row : list) {
+            rowNum++;
+
+            if (StrUtil.isEmpty(row.getContractNumber())) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同号不能为空");
+                continue;
+            }
+
+            ElderlyContractDO contract = elderlyContractMapper.selectValidContract(row.getContractNumber());
+            if (contract == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "未找到对应合同或合同状态无效");
+                continue;
+            }
+            if (contract.getElderId() == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同未关联长者");
+                continue;
+            }
+
+            RehabilitationAssessmentsDO record = new RehabilitationAssessmentsDO();
+            record.setElderId(contract.getElderId().intValue());
+            record.setElderName(StrUtil.blankToDefault(row.getElderName(), contract.getElderName()));
+            record.setAssessmentTime(row.getAssessmentTime());
+            record.setAssessmentTimes(row.getAssessmentTimes());
+            record.setTherapist(row.getTherapist());
+            record.setAdmissionCondition(row.getAdmissionCondition());
+            record.setDysfunction(row.getDysfunction());
+            record.setRehabilitationMethod(row.getRehabilitationMethod());
+            record.setRehabilitationPlan(row.getRehabilitationPlan());
+            record.setExpectedEffect(row.getExpectedEffect());
+            record.setTenantId(TenantContextHolder.getTenantId());
+
+            try {
+                assessmentsMapper.insert(record);
+                success++;
+            } catch (Exception e) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "插入数据库失败", e);
+            }
         }
-        return pageResult;
+
+        return ImportUtil.buildResult(success, failures);
     }
 
 }

+ 10 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/TrainingRecordsService.java

@@ -1,10 +1,16 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
+import javax.servlet.http.HttpServletResponse;
 import javax.validation.*;
 
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
 import cn.iocoder.yudao.module.system.controller.admin.biz.vo.TrainingRecordsPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.TrainingRecordsRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.TrainingRecordsDO;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
 
 /**
  * 康复训练记录 Service 接口
@@ -49,6 +55,9 @@ public interface TrainingRecordsService {
      * @param pageReqVO 分页查询
      * @return 康复训练记录分页
      */
-    PageResult<TrainingRecordsDO> getRecordsPage(TrainingRecordsPageReqVO pageReqVO);
+    PageResult<TrainingRecordsRespVO> getRecordsPage(TrainingRecordsPageReqVO pageReqVO);
+
+    void exportImportTemplate(HttpServletResponse response) throws IOException;
+    ImportResultVO importTrainingRecords(MultipartFile file) throws Exception;
 
 }

+ 75 - 6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/TrainingRecordsServiceImpl.java

@@ -1,26 +1,35 @@
 package cn.iocoder.yudao.module.system.service.biz;
 
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
-import cn.iocoder.yudao.module.system.controller.admin.biz.vo.RecordsPageReqVO;
-import cn.iocoder.yudao.module.system.controller.admin.biz.vo.TrainingRecordsPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.AttachmentsDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyContractDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.TrainingRecordsDO;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.AttachmentsMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyContractMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.biz.TrainingRecordsMapper;
 import cn.iocoder.yudao.module.system.enums.AttachmentsConstants;
+import cn.iocoder.yudao.module.system.util.ImportUtil;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
 import org.springframework.validation.annotation.Validated;
 
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import org.springframework.web.multipart.MultipartFile;
 
 
+import java.io.IOException;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
 import java.util.List;
 
 
@@ -43,6 +52,8 @@ public class TrainingRecordsServiceImpl implements TrainingRecordsService {
     private AttachmentsMapper attachmentsMapper;
     @Resource
     private BuildService buildService;
+    @Resource
+    private ElderlyContractMapper elderlyContractMapper;
 
     @Override
     public void createRecords(TrainingRecordsDO createReqVO) {
@@ -106,12 +117,70 @@ public class TrainingRecordsServiceImpl implements TrainingRecordsService {
     }
 
     @Override
-    public PageResult<TrainingRecordsDO> getRecordsPage(TrainingRecordsPageReqVO pageReqVO) {
+    public PageResult<TrainingRecordsRespVO> getRecordsPage(TrainingRecordsPageReqVO pageReqVO) {
         PageResult<TrainingRecordsDO> pageResult = recordsMapper.selectPage(pageReqVO);
-        for (TrainingRecordsDO trainingRecordsDO : pageResult.getList()) {
-            trainingRecordsDO.setBedInfo(buildService.getFullBedName(Long.valueOf(trainingRecordsDO.getElderId())));
+        PageResult<TrainingRecordsRespVO> resp = BeanUtils.toBean(pageResult, TrainingRecordsRespVO.class);
+        for (TrainingRecordsRespVO vo : resp.getList()) {
+            vo.setBedInfo(buildService.getFullBedName(Long.valueOf(vo.getElderId())));
+            ElderlyContractDO contract = elderlyContractMapper.selectOne(new LambdaQueryWrapperX<ElderlyContractDO>()
+                    .eq(ElderlyContractDO::getElderId, vo.getElderId())
+                    .eq(ElderlyContractDO::getStatus, 1)
+                    .orderByDesc(ElderlyContractDO::getCreatedTime)
+                    .last("LIMIT 1"));
+            if (contract != null) {
+                vo.setContractNumber(contract.getContractNumber());
+            }
         }
-        return pageResult;
+        return resp;
+    }
+    @Override
+    public void exportImportTemplate(HttpServletResponse response) throws IOException {
+        ExcelUtils.write(response, "康复训练记录导入模板.xlsx", "模板",
+                TrainingRecordsImportExcelVO.class, java.util.Collections.emptyList());
     }
 
+    @Override
+    public ImportResultVO importTrainingRecords(MultipartFile file) throws Exception {
+        List<TrainingRecordsImportExcelVO> list = ExcelUtils.read(file, TrainingRecordsImportExcelVO.class);
+
+        int rowNum = 1;
+        int success = 0;
+        List<ImportResultVO.RowError> failures = new ArrayList<>();
+
+        for (TrainingRecordsImportExcelVO row : list) {
+            rowNum++;
+
+            if (StrUtil.isEmpty(row.getContractNumber())) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同号不能为空");
+                continue;
+            }
+
+            ElderlyContractDO contract = elderlyContractMapper.selectValidContract(row.getContractNumber());
+            if (contract == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "未找到对应合同或合同状态无效");
+                continue;
+            }
+            if (contract.getElderId() == null) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "合同未关联长者");
+                continue;
+            }
+
+            TrainingRecordsDO record = new TrainingRecordsDO();
+            record.setElderId(contract.getElderId().intValue());
+            record.setElderName(StrUtil.blankToDefault(row.getElderName(), contract.getElderName()));
+            record.setTrainingTime(row.getTrainingTime());
+            record.setTherapist(row.getTherapist());
+            record.setRecordContent(row.getRecordContent());
+            record.setTenantId(TenantContextHolder.getTenantId());
+
+            try {
+                recordsMapper.insert(record);
+                success++;
+            } catch (Exception e) {
+                ImportUtil.addFailure(failures, rowNum, row.getElderName(), row.getContractNumber(), "插入数据库失败", e);
+            }
+        }
+
+        return ImportUtil.buildResult(success, failures);
+    }
 }

+ 59 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/util/ImportUtil.java

@@ -0,0 +1,59 @@
+package cn.iocoder.yudao.module.system.util;
+
+import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ImportResultVO;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ImportUtil {
+    public static void addFailure(List<ImportResultVO.RowError> failures,
+                                   Integer rowNum,
+                                   String elderName,
+                                   String contractNumber,
+                                   String reason) {
+        addFailure(failures, rowNum, elderName, contractNumber, reason, null);
+    }
+
+    public static void addFailure(List<ImportResultVO.RowError> failures,
+                                   Integer rowNum,
+                                   String elderName,
+                                   String contractNumber,
+                                   String reason,
+                                   Exception ex) {
+        if (failures == null) {
+            throw new IllegalArgumentException("failures 不能为空");
+        }
+        ImportResultVO.RowError error = new ImportResultVO.RowError();
+        error.setRowNum(rowNum);
+        error.setElderName(trimToNull(elderName));
+        error.setContractNumber(trimToNull(contractNumber));
+        error.setReason(trimToNull(reason) == null ? "未知错误" : reason);
+
+        // 避免把超长堆栈直接返回前端:只放简述
+        if (ex != null) {
+            error.setException(ex.getClass().getSimpleName() + ": " + safeMsg(ex.getMessage()));
+        }
+        failures.add(error);
+    }
+
+    public static ImportResultVO buildResult(int successCount,
+                                              List<ImportResultVO.RowError> failures) {
+        ImportResultVO result = new ImportResultVO();
+        result.setSuccessCount(Math.max(successCount, 0));
+        result.setFailures(failures == null ? new ArrayList<>() : failures);
+        result.setFailureCount(result.getFailures().size());
+        return result;
+    }
+
+    private static String trimToNull(String s) {
+        if (s == null) return null;
+        String t = s.trim();
+        return t.isEmpty() ? null : t;
+    }
+
+    private static String safeMsg(String msg) {
+        if (msg == null) return null;
+        // 你也可以限制长度,避免数据库异常信息过长
+        return msg.length() > 500 ? msg.substring(0, 500) : msg;
+    }
+}

+ 4 - 1
yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/ElderlyInfoMapper.xml

@@ -108,7 +108,10 @@
                 #{id}
             </foreach>
         </if>
-        order by (ec.contract_number is null) asc, ec.contract_number desc, ei.update_time desc
+        <if test="pageVO.orderByClause != null and pageVO.orderByClause != ''">
+            ORDER BY ${pageVO.orderByClause}
+        </if>
+
     </select>
 
     <select id="findBpmPage" resultType="cn.iocoder.yudao.module.system.api.bpm.vo.ElderlyCheckinInfoRespVO">