Переглянути джерело

新增
1、增加长期医嘱模块
2、增加短期医嘱模块
3、增加护士执行模块
4、机构模块增加上传账单公章功能
5、账单详情接口增加获取家属信息
修改
1、外出申请增加获取审批流程信息
BUGFIX
1、解决变更时特殊场景存在生成两个退补费用的问题
2、解决工作台搜索无法使用的问题

liangwenxuan 1 місяць тому
батько
коміт
106b550e67
49 змінених файлів з 2182 додано та 4 видалено
  1. 106 0
      sql/mysql/elderly_doctor_order.sql
  2. 9 0
      yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java
  3. 51 0
      yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmTaskRespDTO.java
  4. 14 0
      yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/UserSimpleBaseDTO.java
  5. 107 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java
  6. 3 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskPageReqVO.java
  7. 39 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
  8. 6 0
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
  9. 0 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmElderlyChangeApiImpl.java
  10. 4 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/biz/vo/ExpenseBillRespVO.java
  11. 53 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/DoctorOrderExecutionController.java
  12. 74 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/LongDoctorOrderController.java
  13. 66 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/ShortDoctorOrderController.java
  14. 31 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/DoctorOrderExecutionPageReqVO.java
  15. 63 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/DoctorOrderExecutionRespVO.java
  16. 56 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/DoctorOrderExecutionSaveReqVO.java
  17. 23 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/LongDoctorOrderPageReqVO.java
  18. 96 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/LongDoctorOrderRespVO.java
  19. 67 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/LongDoctorOrderSaveReqVO.java
  20. 22 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/ShortDoctorOrderPageReqVO.java
  21. 92 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/ShortDoctorOrderRespVO.java
  22. 61 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/ShortDoctorOrderSaveReqVO.java
  23. 0 2
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java
  24. 5 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java
  25. 6 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java
  26. 57 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/DoctorOrderExecutionDO.java
  27. 14 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/ElderlyAskLeaveDO.java
  28. 39 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/LongDoctorOrderDO.java
  29. 53 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/LongDoctorOrderEntryDO.java
  30. 39 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/ShortDoctorOrderDO.java
  31. 47 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/biz/ShortDoctorOrderEntryDO.java
  32. 5 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java
  33. 47 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/DoctorOrderExecutionMapper.java
  34. 24 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/LongDoctorOrderEntryMapper.java
  35. 25 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/LongDoctorOrderMapper.java
  36. 24 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/ShortDoctorOrderEntryMapper.java
  37. 25 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/biz/ShortDoctorOrderMapper.java
  38. 26 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/biz/DoctorOrderExecutionStatusEnum.java
  39. 24 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/biz/DoctorOrderTypeEnum.java
  40. 35 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/biz/LongOrderEntryStatusEnum.java
  41. 12 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyAskLeaveServiceImpl.java
  42. 6 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ExpenseOrderServiceImpl.java
  43. 28 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/DoctorOrderExecutionService.java
  44. 101 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/DoctorOrderExecutionServiceImpl.java
  45. 27 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/LongDoctorOrderService.java
  46. 235 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/LongDoctorOrderServiceImpl.java
  47. 25 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/ShortDoctorOrderService.java
  48. 209 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/ShortDoctorOrderServiceImpl.java
  49. 1 1
      yudao-server/src/main/resources/application-dev.yaml

+ 106 - 0
sql/mysql/elderly_doctor_order.sql

@@ -0,0 +1,106 @@
+-- ============================================================
+-- 医嘱模块(长期医嘱 / 临时医嘱 / 护士执行记录)
+-- 说明:业务表统一使用 elderly_ 前缀,与本项目其他业务表保持一致。
+-- 频次(frequency)/给药时间(medTime)/途径(route) 均以缩写存储,后端不翻译。
+-- ============================================================
+
+CREATE TABLE elderly_long_doctor_order (
+  id               BIGINT       NOT NULL AUTO_INCREMENT,
+  elder_id         BIGINT       NOT NULL,
+  elder_name       VARCHAR(64)  DEFAULT '',
+  gender           TINYINT      DEFAULT NULL,
+  gender_name      VARCHAR(16)  DEFAULT '',
+  bed_name         VARCHAR(64)  DEFAULT '',
+  nurse_level_name VARCHAR(64)  DEFAULT '',
+  tenant_id        BIGINT       DEFAULT NULL,
+  creator          VARCHAR(64)  DEFAULT '' COMMENT '创建者',
+  create_time      DATETIME     DEFAULT NULL COMMENT '创建时间',
+  updater          VARCHAR(64)  DEFAULT '' COMMENT '更新者',
+  update_time      DATETIME     DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (id)
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '长期医嘱主单';
+
+CREATE TABLE elderly_long_doctor_order_entry (
+  id                BIGINT       NOT NULL AUTO_INCREMENT,
+  long_doctor_order_id BIGINT    NOT NULL,
+  order_time        DATETIME     DEFAULT NULL COMMENT '开医嘱时间',
+  order_content     VARCHAR(512) DEFAULT '' COMMENT '医嘱内容',
+  frequency         VARCHAR(20)  DEFAULT '' COMMENT '给药频次缩写',
+  med_time          VARCHAR(20)  DEFAULT '' COMMENT '给药时间缩写',
+  route             VARCHAR(20)  DEFAULT '' COMMENT '给药途径缩写',
+  doctor_sign       VARCHAR(64)  DEFAULT '' COMMENT '医生签名',
+  nurse_sign        VARCHAR(64)  DEFAULT '' COMMENT '护士签名',
+  stop_time         DATETIME     DEFAULT NULL COMMENT '停止时间',
+  stop_doctor_sign  VARCHAR(64)  DEFAULT '' COMMENT '停止医生签名',
+  stop_nurse_sign   VARCHAR(64)  DEFAULT '' COMMENT '停止护士签名',
+  remark            VARCHAR(500) DEFAULT '' COMMENT '备注',
+  status            TINYINT      NOT NULL DEFAULT 0 COMMENT '0未开始 1在用 2已停止',
+  creator          VARCHAR(64)  DEFAULT '' COMMENT '创建者',
+  create_time      DATETIME     DEFAULT NULL COMMENT '创建时间',
+  updater          VARCHAR(64)  DEFAULT '' COMMENT '更新者',
+  update_time      DATETIME     DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (id),
+  KEY idx_long_order (long_doctor_order_id)
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '长期医嘱条目';
+
+CREATE TABLE elderly_short_doctor_order (
+  id               BIGINT       NOT NULL AUTO_INCREMENT,
+  elder_id         BIGINT       NOT NULL,
+  elder_name       VARCHAR(64)  DEFAULT '',
+  gender           TINYINT      DEFAULT NULL,
+  gender_name      VARCHAR(16)  DEFAULT '',
+  bed_name         VARCHAR(64)  DEFAULT '',
+  nurse_level_name VARCHAR(64)  DEFAULT '',
+  tenant_id        BIGINT       DEFAULT NULL,
+  creator          VARCHAR(64)  DEFAULT '' COMMENT '创建者',
+  create_time      DATETIME     DEFAULT NULL COMMENT '创建时间',
+  updater          VARCHAR(64)  DEFAULT '' COMMENT '更新者',
+  update_time      DATETIME     DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (id)
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '临时医嘱主单';
+
+CREATE TABLE elderly_short_doctor_order_entry (
+  id                BIGINT       NOT NULL AUTO_INCREMENT,
+  short_doctor_order_id BIGINT   NOT NULL,
+  order_time        DATETIME     DEFAULT NULL COMMENT '开医嘱时间',
+  order_content     VARCHAR(512) DEFAULT '' COMMENT '医嘱内容',
+  frequency         VARCHAR(20)  DEFAULT '' COMMENT '给药频次缩写',
+  med_time          VARCHAR(20)  DEFAULT '' COMMENT '给药时间缩写',
+  route             VARCHAR(20)  DEFAULT '' COMMENT '给药途径缩写',
+  doctor_sign       VARCHAR(64)  DEFAULT '' COMMENT '医生签名',
+  execute_time      DATETIME     DEFAULT NULL COMMENT '执行时间(临时医嘱即时执行)',
+  nurse_sign        VARCHAR(64)  DEFAULT '' COMMENT '护士签名',
+  remark            VARCHAR(500) DEFAULT '' COMMENT '备注',
+  creator          VARCHAR(64)  DEFAULT '' COMMENT '创建者',
+  create_time      DATETIME     DEFAULT NULL COMMENT '创建时间',
+  updater          VARCHAR(64)  DEFAULT '' COMMENT '更新者',
+  update_time      DATETIME     DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (id),
+  KEY idx_short_order (short_doctor_order_id)
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '临时医嘱条目';
+
+CREATE TABLE elderly_doctor_order_execution (
+  id              BIGINT       NOT NULL AUTO_INCREMENT,
+  order_type      TINYINT      NOT NULL COMMENT '1=长期医嘱 2=临时医嘱',
+  order_entry_id  BIGINT       NOT NULL COMMENT '关联 long/short_doctor_order_entry.id',
+  elder_id        BIGINT       DEFAULT NULL,
+  elder_name      VARCHAR(64)  DEFAULT '',
+  bed_name        VARCHAR(64)  DEFAULT '',
+  order_content   VARCHAR(512) DEFAULT '' COMMENT '医嘱内容冗余,便于打印',
+  frequency       VARCHAR(20)  DEFAULT '' COMMENT '频次缩写',
+  med_time        VARCHAR(20)  DEFAULT '' COMMENT '给药时间缩写',
+  route           VARCHAR(20)  DEFAULT '' COMMENT '给药途径缩写',
+  plan_time       DATETIME     DEFAULT NULL COMMENT '计划执行时间,前端生成 YYYY-MM-DD HH:mm',
+  exec_time       DATETIME     DEFAULT NULL COMMENT '实际执行时间',
+  exec_nurse_sign VARCHAR(64)  DEFAULT '' COMMENT '执行护士签名',
+  status          TINYINT      NOT NULL DEFAULT 0 COMMENT '0待执行 1已执行 2已跳过',
+  remark          VARCHAR(500) DEFAULT '' COMMENT '执行备注 / 跳过原因',
+  tenant_id       BIGINT       DEFAULT NULL,
+  creator          VARCHAR(64)  DEFAULT '' COMMENT '创建者',
+  create_time      DATETIME     DEFAULT NULL COMMENT '创建时间',
+  updater          VARCHAR(64)  DEFAULT '' COMMENT '更新者',
+  update_time      DATETIME     DEFAULT NULL COMMENT '更新时间',
+  PRIMARY KEY (id),
+  UNIQUE KEY uk_exec (order_type, order_entry_id, plan_time),
+  KEY idx_plan (plan_time, tenant_id)
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '护士执行记录';

+ 9 - 0
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApi.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.bpm.api.task;
 
 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
+import cn.iocoder.yudao.module.bpm.api.task.dto.BpmTaskRespDTO;
 
 import javax.validation.Valid;
 import java.util.List;
@@ -34,4 +35,12 @@ public interface BpmProcessInstanceApi {
 
     Integer insertBpmBusinessFormDO(Long businessId, Long businessId2, Long tenantId);
 
+    /**
+     * 基于流程实例的 id,获取审批任务的信息(参考 BpmTaskController#getTaskListByProcessInstanceId)
+     *
+     * @param processInstanceId 流程实例编号
+     * @return 审批任务列表
+     */
+    List<BpmTaskRespDTO> getTaskListByProcessInstanceId(String processInstanceId);
+
 }

+ 51 - 0
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/BpmTaskRespDTO.java

@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.bpm.api.task.dto;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class BpmTaskRespDTO {
+
+    private String id;
+
+    private String name;
+
+    private LocalDateTime createTime;
+
+    private LocalDateTime endTime;
+
+    private Long durationInMillis;
+
+    private Integer status; // 参见 BpmTaskStatusEnum 枚举
+
+    private String reason;
+
+    private Long owner;
+    /**
+     * 负责人的用户信息
+     */
+    private UserSimpleBaseDTO ownerUser;
+
+    private Long assignee;
+    /**
+     * 审核的用户信息
+     */
+    private UserSimpleBaseDTO assigneeUser;
+
+    private String taskDefinitionKey;
+
+    private String processInstanceId;
+
+    private String parentTaskId;
+    private List<BpmTaskRespDTO> children; // 由加签生成,包含多层子任务
+
+    private Long formId;
+    private String formName;
+    private String formConf;
+    private List<String> formFields;
+    private Map<String, Object> formVariables;
+
+}

+ 14 - 0
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/task/dto/UserSimpleBaseDTO.java

@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.bpm.api.task.dto;
+
+import lombok.Data;
+
+@Data
+public class UserSimpleBaseDTO {
+
+    private Long id;
+    private String nickname;
+
+    private Long deptId;
+    private String deptName;
+
+}

+ 107 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/api/task/BpmProcessInstanceApiImpl.java

@@ -1,17 +1,31 @@
 package cn.iocoder.yudao.module.bpm.api.task;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.map.MapUtil;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
+import cn.iocoder.yudao.module.bpm.api.task.dto.BpmTaskRespDTO;
+import cn.iocoder.yudao.module.bpm.api.task.dto.UserSimpleBaseDTO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCancelReqVO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.business.BpmBusinessFormDO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.business.BpmBusinessFormMapper;
 import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
+import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnVariableConstants;
 import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
+import cn.iocoder.yudao.module.bpm.service.definition.BpmFormService;
 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceCopyService;
 import cn.iocoder.yudao.module.bpm.service.business.BpmBusinessFormService;
 import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
+import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
 import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import cn.iocoder.yudao.module.system.api.bpm.BpmCheckInApi;
 import cn.iocoder.yudao.module.system.api.bpm.BpmElderlyApi;
 import cn.iocoder.yudao.module.system.api.bpm.BpmElderlyChangeApi;
@@ -37,7 +51,11 @@ import java.time.LocalDate;
 import java.time.temporal.TemporalAdjusters;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
 
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap;
 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
 /**
@@ -74,6 +92,18 @@ public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi {
     @Resource
     private NotifyMessageSendApi notifyMessageSendApi;
 
+    @Resource
+    private BpmTaskService bpmTaskService;
+
+    @Resource
+    private BpmFormService formService;
+
+    @Resource
+    private AdminUserApi adminUserApi;
+
+    @Resource
+    private DeptApi deptApi;
+
     @Resource
     private BpmElderlyChangeApi elderlyChangeApi;
 
@@ -245,4 +275,81 @@ public class BpmProcessInstanceApiImpl implements BpmProcessInstanceApi {
         businessFormDO.setType(1);
         return businessFormMapper.insert(businessFormDO);
     }
+
+    @Override
+    public List<BpmTaskRespDTO> getTaskListByProcessInstanceId(String processInstanceId) {
+        if (processInstanceId == null || processInstanceId.isEmpty()) {
+            return new ArrayList<>();
+        }
+        List<HistoricTaskInstance> taskList = bpmTaskService.getTaskListByProcessInstanceId(processInstanceId, true);
+        if (CollUtil.isEmpty(taskList)) {
+            return new ArrayList<>();
+        }
+
+        // 拼接用户信息、部门信息
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
+                convertSetByFlatMap(taskList, task ->
+                        Stream.of(NumberUtils.parseLong(task.getAssignee()), NumberUtils.parseLong(task.getOwner()))));
+        Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(
+                convertSet(userMap.values(), AdminUserRespDTO::getDeptId));
+        // 获得 Form Map
+        Map<Long, BpmFormDO> formMap = formService.getFormMap(
+                convertSet(taskList, task -> NumberUtils.parseLong(task.getFormKey())));
+
+        return CollectionUtils.convertList(taskList, task -> {
+            // 已取消的任务,不返回
+            Integer taskStatus = FlowableUtils.getTaskStatus(task);
+            if (BpmTaskStatusEnum.isCancelStatus(taskStatus)) {
+                return null;
+            }
+            BpmTaskRespDTO taskDTO = new BpmTaskRespDTO();
+            taskDTO.setId(task.getId());
+            taskDTO.setName(task.getName());
+            taskDTO.setCreateTime(task.getCreateTime() == null ? null : task.getCreateTime().toInstant()
+                    .atZone(java.time.ZoneId.systemDefault()).toLocalDateTime());
+            taskDTO.setEndTime(task.getEndTime() == null ? null : task.getEndTime().toInstant()
+                    .atZone(java.time.ZoneId.systemDefault()).toLocalDateTime());
+            taskDTO.setDurationInMillis(task.getDurationInMillis());
+            taskDTO.setStatus(taskStatus);
+            taskDTO.setReason(FlowableUtils.getTaskReason(task));
+            taskDTO.setOwner(NumberUtils.parseLong(task.getOwner()));
+            taskDTO.setAssignee(NumberUtils.parseLong(task.getAssignee()));
+            taskDTO.setTaskDefinitionKey(task.getTaskDefinitionKey());
+            taskDTO.setProcessInstanceId(task.getProcessInstanceId());
+            taskDTO.setParentTaskId(task.getParentTaskId());
+            // 表单信息
+            BpmFormDO form = MapUtil.get(formMap, NumberUtils.parseLong(task.getFormKey()), BpmFormDO.class);
+            if (form != null) {
+                taskDTO.setFormId(form.getId());
+                taskDTO.setFormName(form.getName());
+                taskDTO.setFormConf(form.getConf());
+                taskDTO.setFormFields(form.getFields());
+                taskDTO.setFormVariables(FlowableUtils.getTaskFormVariable(task));
+            }
+            // 用户信息
+            taskDTO.setAssigneeUser(buildUserSimple(task.getAssignee(), userMap, deptMap));
+            taskDTO.setOwnerUser(buildUserSimple(task.getOwner(), userMap, deptMap));
+            return taskDTO;
+        });
+    }
+
+    private UserSimpleBaseDTO buildUserSimple(String userIdStr, Map<Long, AdminUserRespDTO> userMap, Map<Long, DeptRespDTO> deptMap) {
+        if (userIdStr == null) {
+            return null;
+        }
+        Long userId = NumberUtils.parseLong(userIdStr);
+        AdminUserRespDTO user = userMap.get(userId);
+        if (user == null) {
+            return null;
+        }
+        UserSimpleBaseDTO userDTO = new UserSimpleBaseDTO();
+        userDTO.setId(user.getId());
+        userDTO.setNickname(user.getNickname());
+        userDTO.setDeptId(user.getDeptId());
+        DeptRespDTO dept = deptMap.get(user.getDeptId());
+        if (dept != null) {
+            userDTO.setDeptName(dept.getName());
+        }
+        return userDTO;
+    }
 }

+ 3 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmTaskPageReqVO.java

@@ -22,6 +22,9 @@ public class BpmTaskPageReqVO extends PageParam {
     @Schema(description = "流程分类", example = "1")
     private String category;
 
+    @Schema(description = "标题", example = "测试标题")
+    private String templateContent;
+
     @Schema(description = "创建时间")
     @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;

+ 39 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java

@@ -175,6 +175,14 @@ public class BpmTaskServiceImpl implements BpmTaskService {
             taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0]));
             taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1]));
         }
+        // 按标题(templateContent)/长者姓名模糊匹配过滤:长者姓名存储在业务表单,需先按流程实例维度过滤
+        if (StrUtil.isNotBlank(pageVO.getTemplateContent())) {
+            Set<String> matchedProcessInstanceIds = getMatchedProcessInstanceIdsByTemplateContent(userId, pageVO.getTemplateContent());
+            if (CollUtil.isEmpty(matchedProcessInstanceIds)) {
+                return PageResult.empty();
+            }
+            taskQuery.processInstanceIdIn(matchedProcessInstanceIds);
+        }
         long count = taskQuery.count();
         if (count == 0) {
             return PageResult.empty();
@@ -200,6 +208,37 @@ public class BpmTaskServiceImpl implements BpmTaskService {
         return bpmTaskRespVOPageResult;
     }
 
+    /**
+     * 根据标题(templateContent)/长者姓名模糊匹配,过滤出符合条件的流程实例ID集合
+     * <p>
+     * 长者姓名存储在业务表单中(通过 tenantMap 获取),Flowable 的 TaskQuery 无法直接过滤,
+     * 故先查出当前用户全部待办任务对应的流程实例,按长者姓名模糊匹配后再用 processInstanceIdIn 约束分页查询。
+     *
+     * @param userId          当前用户ID
+     * @param templateContent 模糊匹配关键字(长者姓名)
+     * @return 匹配到的流程实例ID集合
+     */
+    private Set<String> getMatchedProcessInstanceIdsByTemplateContent(Long userId, String templateContent) {
+        List<Task> allTasks = taskService.createTaskQuery()
+                .taskAssignee(String.valueOf(userId))
+                .active()
+                .list();
+        if (CollUtil.isEmpty(allTasks)) {
+            return Collections.emptySet();
+        }
+        Set<String> allProcessInstanceIds = convertSet(allTasks, Task::getProcessInstanceId);
+        Map<String, BpmTaskRespVO> tenantMap = businessFormService.getTenantMap(allProcessInstanceIds);
+        if (CollUtil.isEmpty(tenantMap)) {
+            return Collections.emptySet();
+        }
+        String keyword = templateContent.trim();
+        return tenantMap.values().stream()
+                .filter(vo -> StrUtil.isNotBlank(vo.getElderName()) && vo.getElderName().contains(keyword))
+                .map(BpmTaskRespVO::getProcessInstanceId)
+                .filter(StrUtil::isNotBlank)
+                .collect(Collectors.toSet());
+    }
+
     @Override
     public BpmTaskRespVO getFirstTodoTask(Long userId, String processInstanceId) {
         if (processInstanceId == null) {

+ 6 - 0
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java

@@ -329,4 +329,10 @@ public interface ErrorCodeConstants {
     // ========== 探访预约(家属小程序) 1-002-041-000 ==========
     ErrorCode VISIT_APPOINTMENT_NOT_FOUND = new ErrorCode(1_002_041_000, "探访预约记录不存在");
     ErrorCode VISIT_APPOINTMENT_CANCELED = new ErrorCode(1_002_041_001, "该预约已取消或已删除,无法重复取消");
+
+    // ========== 医嘱模块(长期/临时/执行) 1-008-024-000 ==========
+    ErrorCode ELDERLY_DOCTOR_ORDER_NOT_EXISTS = new ErrorCode(1_008_024_000, "医嘱单不存在");
+    ErrorCode ELDERLY_DOCTOR_ORDER_ENTRY_NOT_EXISTS = new ErrorCode(1_008_024_001, "医嘱条目不存在");
+    ErrorCode ELDERLY_DOCTOR_ORDER_EXEC_NOT_EXISTS = new ErrorCode(1_008_024_002, "护士执行记录不存在");
+    ErrorCode ELDERLY_DOCTOR_ORDER_ELDER_NOT_EXISTS = new ErrorCode(1_008_024_003, "长者信息不存在");
 }

+ 0 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/bpm/BpmElderlyChangeApiImpl.java

@@ -480,7 +480,6 @@ public class BpmElderlyChangeApiImpl implements BpmElderlyChangeApi {
             ExpenseOrderDO expenseOrder = expenseOrderMapper.selectOne(new LambdaQueryWrapperX<ExpenseOrderDO>()
                     .eq(ExpenseOrderDO::getElderId, elderlyId)
                     .eq(ExpenseOrderDO::getBillingMonth, changeBillingMonth)
-                    .eq(ExpenseOrderDO::getPayStatus,BooleanEnum.FALSE.getValue())
                     .ne(ExpenseOrderDO::getType,4));
             if(expenseOrder == null){
                 String targetBillingMonth = resolveAttributionBillMonth(changeBillingMonth, changeYearMonth, hysteresisYearMonth);

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

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.biz.vo;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ExpenseOrderItemDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ExpensePayOrderDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.biz.ExpenseSubsidyDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.RelativesDO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
 
@@ -109,4 +110,7 @@ public class ExpenseBillRespVO {
     @Schema(description = "账单结束日期(试住专用)")
     private LocalDate endDate;
 
+    @Schema(description = "长者家属(亲属)信息")
+    private List<RelativesDO> relatives;
+
 }

+ 53 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/DoctorOrderExecutionController.java

@@ -0,0 +1,53 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionSaveReqVO;
+import cn.iocoder.yudao.module.system.service.doctororder.DoctorOrderExecutionService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+/**
+ * 护士执行记录 Controller
+ *
+ * @author 系统
+ */
+@RestController
+@RequestMapping("/elderly/doctorOrderExecution")
+@Tag(name = "管理后台 - 护士执行记录")
+@Validated
+public class DoctorOrderExecutionController {
+
+    @Resource
+    private DoctorOrderExecutionService doctorOrderExecutionService;
+
+    @GetMapping("/page")
+    @Operation(summary = "护士执行记录分页(某日)")
+    public CommonResult<PageResult<DoctorOrderExecutionRespVO>> getDoctorOrderExecutionPage(@Valid DoctorOrderExecutionPageReqVO pageReqVO) {
+        return success(doctorOrderExecutionService.getDoctorOrderExecutionPage(pageReqVO));
+    }
+
+    @PostMapping("/execute")
+    @Operation(summary = "执行/跳过(upsert 幂等)")
+    public CommonResult<DoctorOrderExecutionRespVO> executeDoctorOrder(@Valid @RequestBody DoctorOrderExecutionSaveReqVO reqVO) {
+        return success(doctorOrderExecutionService.executeDoctorOrder(reqVO));
+    }
+
+    @PutMapping("/skip")
+    @Operation(summary = "按 id 跳过(可选)")
+    public CommonResult<Boolean> skipDoctorOrderExecution(@RequestParam("id") Long id) {
+        doctorOrderExecutionService.skipDoctorOrderExecution(id);
+        return success(true);
+    }
+
+}

+ 74 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/LongDoctorOrderController.java

@@ -0,0 +1,74 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderSaveReqVO;
+import cn.iocoder.yudao.module.system.service.doctororder.LongDoctorOrderService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+/**
+ * 长期医嘱 Controller
+ *
+ * @author 系统
+ */
+@RestController
+@RequestMapping("/elderly/longDoctorOrder")
+@Tag(name = "管理后台 - 长期医嘱")
+@Validated
+public class LongDoctorOrderController {
+
+    @Resource
+    private LongDoctorOrderService longDoctorOrderService;
+
+    @GetMapping("/page")
+    @Operation(summary = "长期医嘱分页列表")
+    public CommonResult<PageResult<LongDoctorOrderRespVO>> getLongDoctorOrderPage(@Valid LongDoctorOrderPageReqVO pageReqVO) {
+        return success(longDoctorOrderService.getLongDoctorOrderPage(pageReqVO));
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "长期医嘱详情(含条目)")
+    public CommonResult<LongDoctorOrderRespVO> getLongDoctorOrder(@RequestParam("id") Long id) {
+        return success(longDoctorOrderService.getLongDoctorOrder(id));
+    }
+
+    @PostMapping("/create")
+    @Operation(summary = "新增长期医嘱")
+    public CommonResult<Long> createLongDoctorOrder(@Valid @RequestBody LongDoctorOrderSaveReqVO reqVO) {
+        return success(longDoctorOrderService.createLongDoctorOrder(reqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新长期医嘱")
+    public CommonResult<Boolean> updateLongDoctorOrder(@Valid @RequestBody LongDoctorOrderSaveReqVO reqVO) {
+        longDoctorOrderService.updateLongDoctorOrder(reqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除长期医嘱")
+    public CommonResult<Boolean> deleteLongDoctorOrder(@RequestParam("id") Long id) {
+        longDoctorOrderService.deleteLongDoctorOrder(id);
+        return success(true);
+    }
+
+    @PutMapping("/entry/updateStatus")
+    @Operation(summary = "长期医嘱条目启用/停止")
+    public CommonResult<Boolean> updateLongDoctorOrderEntryStatus(@RequestParam("id") Long id,
+                                                                   @RequestParam("status") Integer status) {
+        longDoctorOrderService.updateLongDoctorOrderEntryStatus(id, status);
+        return success(true);
+    }
+
+}

+ 66 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/ShortDoctorOrderController.java

@@ -0,0 +1,66 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderSaveReqVO;
+import cn.iocoder.yudao.module.system.service.doctororder.ShortDoctorOrderService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+/**
+ * 临时医嘱 Controller
+ *
+ * @author 系统
+ */
+@RestController
+@RequestMapping("/elderly/shortDoctorOrder")
+@Tag(name = "管理后台 - 临时医嘱")
+@Validated
+public class ShortDoctorOrderController {
+
+    @Resource
+    private ShortDoctorOrderService shortDoctorOrderService;
+
+    @GetMapping("/page")
+    @Operation(summary = "临时医嘱分页列表")
+    public CommonResult<PageResult<ShortDoctorOrderRespVO>> getShortDoctorOrderPage(@Valid ShortDoctorOrderPageReqVO pageReqVO) {
+        return success(shortDoctorOrderService.getShortDoctorOrderPage(pageReqVO));
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "临时医嘱详情(含条目)")
+    public CommonResult<ShortDoctorOrderRespVO> getShortDoctorOrder(@RequestParam("id") Long id) {
+        return success(shortDoctorOrderService.getShortDoctorOrder(id));
+    }
+
+    @PostMapping("/create")
+    @Operation(summary = "新增临时医嘱")
+    public CommonResult<Long> createShortDoctorOrder(@Valid @RequestBody ShortDoctorOrderSaveReqVO reqVO) {
+        return success(shortDoctorOrderService.createShortDoctorOrder(reqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新临时医嘱")
+    public CommonResult<Boolean> updateShortDoctorOrder(@Valid @RequestBody ShortDoctorOrderSaveReqVO reqVO) {
+        shortDoctorOrderService.updateShortDoctorOrder(reqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除临时医嘱")
+    public CommonResult<Boolean> deleteShortDoctorOrder(@RequestParam("id") Long id) {
+        shortDoctorOrderService.deleteShortDoctorOrder(id);
+        return success(true);
+    }
+
+}

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

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+/**
+ * 护士执行记录分页请求 VO
+ *
+ * @author 系统
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DoctorOrderExecutionPageReqVO extends PageParam {
+
+    @Schema(description = "计划执行日期 YYYY-MM-DD,匹配 plan_time 的日期部分")
+    private String planDate;
+
+    @Schema(description = "医嘱类型 1长期 2临时")
+    private Integer orderType;
+
+    @Schema(description = "执行状态 0待执行 1已执行 2已跳过")
+    private Integer status;
+
+    @Schema(description = "长者姓名(模糊匹配)")
+    private String elderName;
+
+}

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

@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 护士执行记录返回 VO
+ *
+ * @author 系统
+ */
+@Data
+public class DoctorOrderExecutionRespVO {
+
+    @Schema(description = "主键")
+    private Long id;
+
+    @Schema(description = "医嘱类型 1长期 2临时")
+    private Integer orderType;
+    @Schema(description = "关联医嘱条目ID")
+    private Long orderEntryId;
+    @Schema(description = "长者ID")
+    private Long elderId;
+    @Schema(description = "长者姓名")
+    private String elderName;
+    @Schema(description = "长者年龄")
+    private Integer elderAge;
+    @Schema(description = "床位名称")
+    private String bedName;
+    @Schema(description = "医嘱内容")
+    private String orderContent;
+    @Schema(description = "频次缩写")
+    private String frequency;
+    @Schema(description = "给药时间缩写")
+    private String medTime;
+    @Schema(description = "给药途径缩写")
+    private String route;
+    @Schema(description = "计划执行时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime planTime;
+    @Schema(description = "实际执行时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime execTime;
+    @Schema(description = "执行护士签名")
+    private String execNurseSign;
+    @Schema(description = "状态 0待执行 1已执行 2已跳过")
+    private Integer status;
+    @Schema(description = "备注 / 跳过原因")
+    private String remark;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime createTime;
+
+}

+ 56 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/DoctorOrderExecutionSaveReqVO.java

@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 护士执行记录新增/执行请求 VO
+ *
+ * @author 系统
+ */
+@Data
+public class DoctorOrderExecutionSaveReqVO {
+
+    @Schema(description = "主键,更新已有记录时必传")
+    private Long id;
+
+    @Schema(description = "医嘱类型 1长期 2临时", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Integer orderType;
+    @Schema(description = "关联医嘱条目ID", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long orderEntryId;
+    @Schema(description = "长者ID")
+    private Long elderId;
+    @Schema(description = "长者姓名")
+    private String elderName;
+    @Schema(description = "床位名称")
+    private String bedName;
+    @Schema(description = "医嘱内容")
+    private String orderContent;
+    @Schema(description = "频次缩写")
+    private String frequency;
+    @Schema(description = "给药时间缩写")
+    private String medTime;
+    @Schema(description = "给药途径缩写")
+    private String route;
+    @Schema(description = "计划执行时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime planTime;
+    @Schema(description = "实际执行时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime execTime;
+    @Schema(description = "执行护士签名")
+    private String execNurseSign;
+    @Schema(description = "状态 0待执行 1已执行 2已跳过", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Integer status;
+    @Schema(description = "备注 / 跳过原因")
+    private String remark;
+
+}

+ 23 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/LongDoctorOrderPageReqVO.java

@@ -0,0 +1,23 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+/**
+ * 长期医嘱分页请求 VO
+ *
+ * @author 系统
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class LongDoctorOrderPageReqVO extends PageParam {
+
+
+    @Schema(description = "长者姓名(模糊匹配)")
+    private String elderName;
+
+}

+ 96 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/LongDoctorOrderRespVO.java

@@ -0,0 +1,96 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 长期医嘱详情/分页返回 VO
+ *
+ * @author 系统
+ */
+@Data
+public class LongDoctorOrderRespVO {
+
+    @Schema(description = "主键")
+    private Long id;
+
+    @Schema(description = "长者ID")
+    private Long elderId;
+    @Schema(description = "长者姓名")
+    private String elderName;
+    @Schema(description = "长者年龄")
+    private Integer elderAge;
+    @Schema(description = "性别 1男 2女")
+    private Integer gender;
+    @Schema(description = "性别名称")
+    private String genderName;
+    @Schema(description = "床位名称")
+    private String bedName;
+    @Schema(description = "护理等级名称")
+    private String nurseLevelName;
+    @Schema(description = "租户ID")
+    private Long tenantId;
+
+    @Schema(description = "条目总数(含已停止)")
+    private Integer entryCount;
+    @Schema(description = "最近开医嘱时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime latestOrderTime;
+    @Schema(description = "医嘱条目列表")
+    private List<Entry> entries;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime createTime;
+
+    @Data
+    @Schema(description = "长期医嘱条目")
+    public static class Entry {
+
+        @Schema(description = "主键")
+        private Long id;
+        @Schema(description = "长期医嘱主单ID")
+        private Long longDoctorOrderId;
+        @Schema(description = "开医嘱时间")
+        @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        private LocalDateTime orderTime;
+        @Schema(description = "医嘱内容")
+        private String orderContent;
+        @Schema(description = "给药频次缩写")
+        private String frequency;
+        @Schema(description = "给药时间缩写")
+        private String medTime;
+        @Schema(description = "给药途径缩写")
+        private String route;
+        @Schema(description = "医生签名")
+        private String doctorSign;
+        @Schema(description = "护士签名")
+        private String nurseSign;
+        @Schema(description = "停止时间")
+        @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        private LocalDateTime stopTime;
+        @Schema(description = "停止医生签名")
+        private String stopDoctorSign;
+        @Schema(description = "停止护士签名")
+        private String stopNurseSign;
+        @Schema(description = "备注")
+        private String remark;
+        @Schema(description = "状态 0未开始 1在用 2已停止")
+        private Integer status;
+        @Schema(description = "状态文本")
+        private String statusText;
+
+    }
+
+}

+ 67 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/LongDoctorOrderSaveReqVO.java

@@ -0,0 +1,67 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 长期医嘱新增/更新请求 VO
+ *
+ * @author 系统
+ */
+@Data
+public class LongDoctorOrderSaveReqVO {
+
+    @Schema(description = "主键,更新时必传")
+    private Long id;
+
+    @Schema(description = "长者ID", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long elderId;
+
+    @Schema(description = "医嘱条目列表")
+    private List<Entry> entries;
+
+    @Data
+    @Schema(description = "长期医嘱条目(新增/更新)")
+    public static class Entry {
+
+        @Schema(description = "主键,更新已有条目时必传")
+        private Long id;
+        @Schema(description = "开医嘱时间")
+        @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        private LocalDateTime orderTime;
+        @Schema(description = "医嘱内容")
+        private String orderContent;
+        @Schema(description = "给药频次缩写")
+        private String frequency;
+        @Schema(description = "给药时间缩写")
+        private String medTime;
+        @Schema(description = "给药途径缩写")
+        private String route;
+        @Schema(description = "医生签名")
+        private String doctorSign;
+        @Schema(description = "护士签名")
+        private String nurseSign;
+        @Schema(description = "停止时间")
+        @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        private LocalDateTime stopTime;
+        @Schema(description = "停止医生签名")
+        private String stopDoctorSign;
+        @Schema(description = "停止护士签名")
+        private String stopNurseSign;
+        @Schema(description = "备注")
+        private String remark;
+        @Schema(description = "状态 0未开始 1在用 2已停止")
+        private Integer status;
+
+    }
+
+}

+ 22 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/ShortDoctorOrderPageReqVO.java

@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.List;
+
+/**
+ * 临时医嘱分页请求 VO
+ *
+ * @author 系统
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ShortDoctorOrderPageReqVO extends PageParam {
+
+    @Schema(description = "长者姓名(模糊匹配)")
+    private String elderName;
+
+}

+ 92 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/doctororder/vo/ShortDoctorOrderRespVO.java

@@ -0,0 +1,92 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 临时医嘱详情/分页返回 VO
+ *
+ * @author 系统
+ */
+@Data
+public class ShortDoctorOrderRespVO {
+
+    @Schema(description = "主键")
+    private Long id;
+
+    @Schema(description = "长者ID")
+    private Long elderId;
+    @Schema(description = "长者姓名")
+    private String elderName;
+    @Schema(description = "长者年龄")
+    private Integer elderAge;
+    @Schema(description = "性别 1男 2女")
+    private Integer gender;
+    @Schema(description = "性别名称")
+    private String genderName;
+    @Schema(description = "床位名称")
+    private String bedName;
+    @Schema(description = "护理等级名称")
+    private String nurseLevelName;
+    @Schema(description = "租户ID")
+    private Long tenantId;
+
+    @Schema(description = "条目总数")
+    private Integer entryCount;
+    @Schema(description = "最近开医嘱时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime latestOrderTime;
+    @Schema(description = "最近执行时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime latestExecuteTime;
+    @Schema(description = "医嘱条目列表")
+    private List<Entry> entries;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime createTime;
+
+    @Data
+    @Schema(description = "临时医嘱条目")
+    public static class Entry {
+
+        @Schema(description = "主键")
+        private Long id;
+        @Schema(description = "临时医嘱主单ID")
+        private Long shortDoctorOrderId;
+        @Schema(description = "开医嘱时间")
+        @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        private LocalDateTime orderTime;
+        @Schema(description = "医嘱内容")
+        private String orderContent;
+        @Schema(description = "给药频次缩写")
+        private String frequency;
+        @Schema(description = "给药时间缩写")
+        private String medTime;
+        @Schema(description = "给药途径缩写")
+        private String route;
+        @Schema(description = "医生签名")
+        private String doctorSign;
+        @Schema(description = "执行时间")
+        @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        private LocalDateTime executeTime;
+        @Schema(description = "护士签名")
+        private String nurseSign;
+        @Schema(description = "备注")
+        private String remark;
+
+    }
+
+}

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

@@ -0,0 +1,61 @@
+package cn.iocoder.yudao.module.system.controller.admin.doctororder.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * 临时医嘱新增/更新请求 VO
+ *
+ * @author 系统
+ */
+@Data
+public class ShortDoctorOrderSaveReqVO {
+
+    @Schema(description = "主键,更新时必传")
+    private Long id;
+
+    @Schema(description = "长者ID", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Long elderId;
+
+    @Schema(description = "医嘱条目列表")
+    private List<Entry> entries;
+
+    @Data
+    @Schema(description = "临时医嘱条目(新增/更新)")
+    public static class Entry {
+
+        @Schema(description = "主键,更新已有条目时必传")
+        private Long id;
+        @Schema(description = "开医嘱时间")
+        @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        private LocalDateTime orderTime;
+        @Schema(description = "医嘱内容")
+        private String orderContent;
+        @Schema(description = "给药频次缩写")
+        private String frequency;
+        @Schema(description = "给药时间缩写")
+        private String medTime;
+        @Schema(description = "给药途径缩写")
+        private String route;
+        @Schema(description = "医生签名")
+        private String doctorSign;
+        @Schema(description = "执行时间")
+        @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+        private LocalDateTime executeTime;
+        @Schema(description = "护士签名")
+        private String nurseSign;
+        @Schema(description = "备注")
+        private String remark;
+
+    }
+
+}

+ 0 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java

@@ -64,7 +64,6 @@ public class TenantController {
 
     @PutMapping("/update")
     @Operation(summary = "更新租户")
-    @PreAuthorize("@ss.hasPermission('system:tenant:update')")
     public CommonResult<Boolean> updateTenant(@Valid @RequestBody TenantSaveReqVO updateReqVO) {
         tenantService.updateTenant(updateReqVO);
         return success(true);
@@ -82,7 +81,6 @@ public class TenantController {
     @GetMapping("/get")
     @Operation(summary = "获得租户")
     @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('system:tenant:query')")
     public CommonResult<TenantRespVO> getTenant(@RequestParam("id") Long id) {
         TenantDO tenant = tenantService.getTenant(id);
         return success(BeanUtils.toBean(tenant, TenantRespVO.class));

+ 5 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java

@@ -61,4 +61,9 @@ public class TenantRespVO {
     @ExcelProperty("创建时间")
     private LocalDateTime createTime;
 
+    /**
+     * 账单公章url
+     */
+    private String expenseCachetUrl;
+
 }

+ 6 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSaveReqVO.java

@@ -81,4 +81,10 @@ public class TenantSaveReqVO {
 
     @Schema(description = "系统类型")
     private Integer orgType;
+
+    /**
+     * 账单公章url
+     */
+    @Schema(description = "账单公章url")
+    private String expenseCachetUrl;
 }

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

@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.biz;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseNoDeleteDO;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 护士执行记录 DO
+ *
+ * @author 系统
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("elderly_doctor_order_execution")
+public class DoctorOrderExecutionDO extends BaseNoDeleteDO {
+
+    /** 主键 */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 医嘱类型 1=长期医嘱 2=临时医嘱 */
+    private Integer orderType;
+    /** 关联 long/short_doctor_order_entry.id */
+    private Long orderEntryId;
+    /** 长者ID */
+    private Long elderId;
+    /** 长者姓名 */
+    private String elderName;
+    /** 床位名称 */
+    private String bedName;
+    /** 医嘱内容冗余 */
+    private String orderContent;
+    /** 频次缩写 */
+    private String frequency;
+    /** 给药时间缩写 */
+    private String medTime;
+    /** 给药途径缩写 */
+    private String route;
+    /** 计划执行时间,前端生成 */
+    private LocalDateTime planTime;
+    /** 实际执行时间 */
+    private LocalDateTime execTime;
+    /** 执行护士签名 */
+    private String execNurseSign;
+    /** 状态 0待执行 1已执行 2已跳过 */
+    private Integer status;
+    /** 执行备注 / 跳过原因 */
+    private String remark;
+    /** 租户ID */
+    private Long tenantId;
+
+}

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

@@ -206,4 +206,18 @@ public class ElderlyAskLeaveDO implements Serializable {
     @TableField(exist = false)
     private Integer statusType;
 
+    /**
+     * 流程实例编号(非数据库字段,存在审批流程时赋值)
+     */
+    @Schema(description = "流程实例编号", example = "8888")
+    @TableField(exist = false)
+    private String processInstanceId;
+
+    /**
+     * 审批流程任务列表(非数据库字段,存在审批流程时赋值,参考 BpmTaskController#getTaskListByProcessInstanceId)
+     */
+    @Schema(description = "审批流程任务列表")
+    @TableField(exist = false)
+    private List<cn.iocoder.yudao.module.bpm.api.task.dto.BpmTaskRespDTO> taskList;
+
 }

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

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.biz;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseNoDeleteDO;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 长期医嘱主单 DO
+ *
+ * @author 系统
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("elderly_long_doctor_order")
+public class LongDoctorOrderDO extends BaseNoDeleteDO {
+
+    /** 主键 */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 长者ID */
+    private Long elderId;
+    /** 长者姓名 */
+    private String elderName;
+    /** 性别 1男 2女 */
+    private Integer gender;
+    /** 性别名称 */
+    private String genderName;
+    /** 床位名称 */
+    private String bedName;
+    /** 护理等级名称 */
+    private String nurseLevelName;
+    /** 租户ID */
+    private Long tenantId;
+
+}

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

@@ -0,0 +1,53 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.biz;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseNoDeleteDO;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 长期医嘱条目 DO
+ *
+ * @author 系统
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("elderly_long_doctor_order_entry")
+public class LongDoctorOrderEntryDO extends BaseNoDeleteDO {
+
+    /** 主键 */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 长期医嘱主单ID */
+    private Long longDoctorOrderId;
+    /** 开医嘱时间 */
+    private LocalDateTime orderTime;
+    /** 医嘱内容 */
+    private String orderContent;
+    /** 给药频次缩写 */
+    private String frequency;
+    /** 给药时间缩写 */
+    private String medTime;
+    /** 给药途径缩写 */
+    private String route;
+    /** 医生签名 */
+    private String doctorSign;
+    /** 护士签名 */
+    private String nurseSign;
+    /** 停止时间 */
+    private LocalDateTime stopTime;
+    /** 停止医生签名 */
+    private String stopDoctorSign;
+    /** 停止护士签名 */
+    private String stopNurseSign;
+    /** 备注 */
+    private String remark;
+    /** 状态 0未开始 1在用 2已停止 */
+    private Integer status;
+
+}

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

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.biz;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseNoDeleteDO;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 临时医嘱主单 DO
+ *
+ * @author 系统
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("elderly_short_doctor_order")
+public class ShortDoctorOrderDO extends BaseNoDeleteDO {
+
+    /** 主键 */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 长者ID */
+    private Long elderId;
+    /** 长者姓名 */
+    private String elderName;
+    /** 性别 1男 2女 */
+    private Integer gender;
+    /** 性别名称 */
+    private String genderName;
+    /** 床位名称 */
+    private String bedName;
+    /** 护理等级名称 */
+    private String nurseLevelName;
+    /** 租户ID */
+    private Long tenantId;
+
+}

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

@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.biz;
+
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseNoDeleteDO;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 临时医嘱条目 DO
+ *
+ * @author 系统
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("elderly_short_doctor_order_entry")
+public class ShortDoctorOrderEntryDO extends BaseNoDeleteDO {
+
+    /** 主键 */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /** 临时医嘱主单ID */
+    private Long shortDoctorOrderId;
+    /** 开医嘱时间 */
+    private LocalDateTime orderTime;
+    /** 医嘱内容 */
+    private String orderContent;
+    /** 给药频次缩写 */
+    private String frequency;
+    /** 给药时间缩写 */
+    private String medTime;
+    /** 给药途径缩写 */
+    private String route;
+    /** 医生签名 */
+    private String doctorSign;
+    /** 执行时间(临时医嘱即时执行) */
+    private LocalDateTime executeTime;
+    /** 护士签名 */
+    private String nurseSign;
+    /** 备注 */
+    private String remark;
+
+}

+ 5 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java

@@ -103,6 +103,11 @@ public class TenantDO extends BaseDO {
      */
     private Long chargeCategoryId;
 
+    /**
+     * 账单公章url
+     */
+    private String expenseCachetUrl;
+
 
     @Schema(description = "登陆标识, 0-企业登陆,1-集团登陆,2-企业和集团登陆")
     @TableField(exist = false)

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

@@ -0,0 +1,47 @@
+package cn.iocoder.yudao.module.system.dal.mysql.biz;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+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.doctororder.vo.DoctorOrderExecutionPageReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.DoctorOrderExecutionDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 护士执行记录 Mapper
+ *
+ * @author 系统
+ */
+@Mapper
+public interface DoctorOrderExecutionMapper extends BaseMapperX<DoctorOrderExecutionDO> {
+
+    default PageResult<DoctorOrderExecutionDO> selectPage(DoctorOrderExecutionPageReqVO reqVO) {
+        LambdaQueryWrapperX<DoctorOrderExecutionDO> query = new LambdaQueryWrapperX<DoctorOrderExecutionDO>()
+                .likeIfPresent(DoctorOrderExecutionDO::getElderName, reqVO.getElderName())
+                .eqIfPresent(DoctorOrderExecutionDO::getOrderType, reqVO.getOrderType())
+                .eqIfPresent(DoctorOrderExecutionDO::getStatus, reqVO.getStatus())
+                .inIfPresent(DoctorOrderExecutionDO::getTenantId, reqVO.getTenantIds())
+                .orderByDesc(DoctorOrderExecutionDO::getPlanTime);
+        // 按 plan_time 的日期部分匹配(YYYY-MM-DD)
+        if (reqVO.getPlanDate() != null && !reqVO.getPlanDate().isEmpty()) {
+            query.apply("DATE(plan_time) = {0}", reqVO.getPlanDate());
+        }
+        return selectPage(reqVO, query);
+    }
+
+    default DoctorOrderExecutionDO selectByUniqueKey(Integer orderType, Long orderEntryId, java.time.LocalDateTime planTime) {
+        return selectOne(new LambdaQueryWrapperX<DoctorOrderExecutionDO>()
+                .eq(DoctorOrderExecutionDO::getOrderType, orderType)
+                .eq(DoctorOrderExecutionDO::getOrderEntryId, orderEntryId)
+                .eq(DoctorOrderExecutionDO::getPlanTime, planTime));
+    }
+
+    default List<DoctorOrderExecutionDO> selectByEntryIds(Integer orderType, List<Long> orderEntryIds) {
+        return selectList(new LambdaQueryWrapperX<DoctorOrderExecutionDO>()
+                .eq(DoctorOrderExecutionDO::getOrderType, orderType)
+                .in(DoctorOrderExecutionDO::getOrderEntryId, orderEntryIds));
+    }
+
+}

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

@@ -0,0 +1,24 @@
+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.module.system.dal.dataobject.biz.LongDoctorOrderEntryDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 长期医嘱条目 Mapper
+ *
+ * @author 系统
+ */
+@Mapper
+public interface LongDoctorOrderEntryMapper extends BaseMapperX<LongDoctorOrderEntryDO> {
+
+    default List<LongDoctorOrderEntryDO> selectListByOrderId(Long longDoctorOrderId) {
+        return selectList(new LambdaQueryWrapperX<LongDoctorOrderEntryDO>()
+                .eq(LongDoctorOrderEntryDO::getLongDoctorOrderId, longDoctorOrderId)
+                .orderByAsc(LongDoctorOrderEntryDO::getId));
+    }
+
+}

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

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.system.dal.mysql.biz;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+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.doctororder.vo.LongDoctorOrderPageReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.LongDoctorOrderDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 长期医嘱主单 Mapper
+ *
+ * @author 系统
+ */
+@Mapper
+public interface LongDoctorOrderMapper extends BaseMapperX<LongDoctorOrderDO> {
+
+    default PageResult<LongDoctorOrderDO> selectPage(LongDoctorOrderPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<LongDoctorOrderDO>()
+                .likeIfPresent(LongDoctorOrderDO::getElderName, reqVO.getElderName())
+                .inIfPresent(LongDoctorOrderDO::getTenantId, reqVO.getTenantIds())
+                .orderByDesc(LongDoctorOrderDO::getCreateTime));
+    }
+
+}

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

@@ -0,0 +1,24 @@
+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.module.system.dal.dataobject.biz.ShortDoctorOrderEntryDO;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 临时医嘱条目 Mapper
+ *
+ * @author 系统
+ */
+@Mapper
+public interface ShortDoctorOrderEntryMapper extends BaseMapperX<ShortDoctorOrderEntryDO> {
+
+    default List<ShortDoctorOrderEntryDO> selectListByOrderId(Long shortDoctorOrderId) {
+        return selectList(new LambdaQueryWrapperX<ShortDoctorOrderEntryDO>()
+                .eq(ShortDoctorOrderEntryDO::getShortDoctorOrderId, shortDoctorOrderId)
+                .orderByAsc(ShortDoctorOrderEntryDO::getId));
+    }
+
+}

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

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.system.dal.mysql.biz;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+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.doctororder.vo.ShortDoctorOrderPageReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ShortDoctorOrderDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 临时医嘱主单 Mapper
+ *
+ * @author 系统
+ */
+@Mapper
+public interface ShortDoctorOrderMapper extends BaseMapperX<ShortDoctorOrderDO> {
+
+    default PageResult<ShortDoctorOrderDO> selectPage(ShortDoctorOrderPageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<ShortDoctorOrderDO>()
+                .likeIfPresent(ShortDoctorOrderDO::getElderName, reqVO.getElderName())
+                .inIfPresent(ShortDoctorOrderDO::getTenantId, reqVO.getTenantIds())
+                .orderByDesc(ShortDoctorOrderDO::getCreateTime));
+    }
+
+}

+ 26 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/biz/DoctorOrderExecutionStatusEnum.java

@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.system.enums.biz;
+
+import lombok.Getter;
+
+/**
+ * 护士执行记录状态枚举
+ * 0待执行 1已执行 2已跳过
+ *
+ * @author 系统
+ */
+@Getter
+public enum DoctorOrderExecutionStatusEnum {
+
+    PENDING(0, "待执行"),
+    DONE(1, "已执行"),
+    SKIPPED(2, "已跳过");
+
+    private final Integer status;
+    private final String name;
+
+    DoctorOrderExecutionStatusEnum(Integer status, String name) {
+        this.status = status;
+        this.name = name;
+    }
+
+}

+ 24 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/biz/DoctorOrderTypeEnum.java

@@ -0,0 +1,24 @@
+package cn.iocoder.yudao.module.system.enums.biz;
+
+import lombok.Getter;
+
+/**
+ * 医嘱类型枚举
+ *
+ * @author 系统
+ */
+@Getter
+public enum DoctorOrderTypeEnum {
+
+    LONG(1, "长期医嘱"),
+    SHORT(2, "临时医嘱");
+
+    private final Integer type;
+    private final String name;
+
+    DoctorOrderTypeEnum(Integer type, String name) {
+        this.type = type;
+        this.name = name;
+    }
+
+}

+ 35 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/biz/LongOrderEntryStatusEnum.java

@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.system.enums.biz;
+
+import lombok.Getter;
+
+/**
+ * 长期医嘱条目状态枚举
+ * 0未开始 1在用 2已停止
+ *
+ * @author 系统
+ */
+@Getter
+public enum LongOrderEntryStatusEnum {
+
+    NOT_STARTED(0, "未开始"),
+    IN_USE(1, "在用"),
+    STOPPED(2, "已停止");
+
+    private final Integer status;
+    private final String name;
+
+    LongOrderEntryStatusEnum(Integer status, String name) {
+        this.status = status;
+        this.name = name;
+    }
+
+    public static LongOrderEntryStatusEnum getByStatus(Integer status) {
+        for (LongOrderEntryStatusEnum value : values()) {
+            if (value.getStatus().equals(status)) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+}

+ 12 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ElderlyAskLeaveServiceImpl.java

@@ -843,6 +843,18 @@ public class ElderlyAskLeaveServiceImpl implements ElderlyAskLeaveService {
             // 计算状态展示类型:1-待出院,2-待回院,3-已完成
             elderlyAskLeaveDO.setStatusType(ElderlyAskLeaveDO.computeStatusType(
                     elderlyAskLeaveDO.getOutDate(), elderlyAskLeaveDO.getUpdateDate()));
+            // 如果存在审批流程(审批中),获取审批流程任务列表(参考 BpmTaskController#getTaskListByProcessInstanceId)
+            if (elderlyAskLeaveDO.getLeaveStatus() != null && ElderlyAskLeaveDO.LEAVE_STATUS_PENDING.equals(elderlyAskLeaveDO.getLeaveStatus())) {
+                try {
+                    String processInstanceId = processInstanceApi.getProcessInstanceId(String.valueOf(elderlyAskLeaveDO.getId()));
+                    if (processInstanceId != null && !processInstanceId.isEmpty()) {
+                        elderlyAskLeaveDO.setProcessInstanceId(processInstanceId);
+                        elderlyAskLeaveDO.setTaskList(processInstanceApi.getTaskListByProcessInstanceId(processInstanceId));
+                    }
+                } catch (Exception e) {
+                    log.warn("查询外出登记审批流程失败,askLeaveId={}", elderlyAskLeaveDO.getId(), e);
+                }
+            }
         }
         return elderlyAskLeaveDOPageResult;
     }

+ 6 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/biz/ExpenseOrderServiceImpl.java

@@ -482,6 +482,12 @@ public class ExpenseOrderServiceImpl implements ExpenseOrderService {
         }
         respVO.setPayInfos(payInfos);
         respVO.setExpenseSubsidyDO(expenseSubsidyList);
+
+        //查询家属(亲属)信息
+        List<RelativesDO> relatives = relativesMapper.selectList(new LambdaQueryWrapperX<RelativesDO>()
+                .eq(RelativesDO::getPeopleId, expenseOrder.getElderId())
+                .orderByDesc(RelativesDO::getIsBillSender));
+        respVO.setRelatives(relatives);
         return respVO;
     }
 

+ 28 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/DoctorOrderExecutionService.java

@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.system.service.doctororder;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionSaveReqVO;
+
+/**
+ * 护士执行记录 Service
+ *
+ * @author 系统
+ */
+public interface DoctorOrderExecutionService {
+
+    PageResult<DoctorOrderExecutionRespVO> getDoctorOrderExecutionPage(DoctorOrderExecutionPageReqVO reqVO);
+
+    /**
+     * 执行 / 跳过(upsert 幂等)
+     * 按唯一键 (orderType, orderEntryId, planTime) 存在则更新,不存在则插入。
+     */
+    DoctorOrderExecutionRespVO executeDoctorOrder(DoctorOrderExecutionSaveReqVO reqVO);
+
+    /**
+     * 按 id 跳过(可选,前端一般走 execute 带 status=2)
+     */
+    void skipDoctorOrderExecution(Long id);
+
+}

+ 101 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/DoctorOrderExecutionServiceImpl.java

@@ -0,0 +1,101 @@
+package cn.iocoder.yudao.module.system.service.doctororder;
+
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.DoctorOrderExecutionSaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.DoctorOrderExecutionDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.DoctorOrderExecutionMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
+import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.Period;
+import java.time.ZoneId;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 护士执行记录 Service 实现
+ *
+ * @author 系统
+ */
+@Service
+@Validated
+public class DoctorOrderExecutionServiceImpl implements DoctorOrderExecutionService {
+
+    @Resource
+    private DoctorOrderExecutionMapper doctorOrderExecutionMapper;
+    @Resource
+    private ElderlyInfoMapper elderlyInfoMapper;
+
+    @Override
+    public PageResult<DoctorOrderExecutionRespVO> getDoctorOrderExecutionPage(DoctorOrderExecutionPageReqVO reqVO) {
+        PageResult<DoctorOrderExecutionDO> pageResult = doctorOrderExecutionMapper.selectPage(reqVO);
+        List<DoctorOrderExecutionRespVO> list = pageResult.getList().stream()
+                .map(this::convertToResp)
+                .collect(Collectors.toList());
+        return new PageResult<>(list, pageResult.getTotal());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public DoctorOrderExecutionRespVO executeDoctorOrder(DoctorOrderExecutionSaveReqVO reqVO) {
+        // 幂等 upsert:按唯一键 (orderType, orderEntryId, planTime)
+        DoctorOrderExecutionDO exist = doctorOrderExecutionMapper.selectByUniqueKey(
+                reqVO.getOrderType(), reqVO.getOrderEntryId(), reqVO.getPlanTime());
+        if (exist != null) {
+            exist.setStatus(reqVO.getStatus());
+            exist.setExecTime(reqVO.getExecTime());
+            exist.setExecNurseSign(reqVO.getExecNurseSign());
+            exist.setRemark(reqVO.getRemark());
+            doctorOrderExecutionMapper.updateById(exist);
+            return convertToResp(exist);
+        }
+
+        DoctorOrderExecutionDO insert = new DoctorOrderExecutionDO();
+        org.springframework.beans.BeanUtils.copyProperties(reqVO, insert);
+        // 避免将请求中的 id 复制到新记录,确保自增主键生效
+        insert.setId(null);
+        insert.setTenantId(TenantContextHolder.getTenantId());
+        doctorOrderExecutionMapper.insert(insert);
+        return convertToResp(insert);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void skipDoctorOrderExecution(Long id) {
+        DoctorOrderExecutionDO exist = doctorOrderExecutionMapper.selectById(id);
+        if (exist == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_EXEC_NOT_EXISTS);
+        }
+        exist.setStatus(2);
+        doctorOrderExecutionMapper.updateById(exist);
+    }
+
+    private DoctorOrderExecutionRespVO convertToResp(DoctorOrderExecutionDO execDO) {
+        DoctorOrderExecutionRespVO respVO = new DoctorOrderExecutionRespVO();
+        org.springframework.beans.BeanUtils.copyProperties(execDO, respVO);
+        if (execDO.getElderId() != null) {
+            ElderlyInfoDO elder = elderlyInfoMapper.selectById(execDO.getElderId());
+            if (elder != null && elder.getBirthday() != null) {
+                respVO.setElderAge(calcAge(elder.getBirthday()));
+            }
+        }
+        return respVO;
+    }
+
+    private static int calcAge(Date birthday) {
+        LocalDate birth = birthday.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+        return Period.between(birth, LocalDate.now()).getYears();
+    }
+
+}

+ 27 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/LongDoctorOrderService.java

@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.system.service.doctororder;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderSaveReqVO;
+
+/**
+ * 长期医嘱 Service
+ *
+ * @author 系统
+ */
+public interface LongDoctorOrderService {
+
+    PageResult<LongDoctorOrderRespVO> getLongDoctorOrderPage(LongDoctorOrderPageReqVO reqVO);
+
+    LongDoctorOrderRespVO getLongDoctorOrder(Long id);
+
+    Long createLongDoctorOrder(LongDoctorOrderSaveReqVO reqVO);
+
+    void updateLongDoctorOrder(LongDoctorOrderSaveReqVO reqVO);
+
+    void deleteLongDoctorOrder(Long id);
+
+    void updateLongDoctorOrderEntryStatus(Long id, Integer status);
+
+}

+ 235 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/LongDoctorOrderServiceImpl.java

@@ -0,0 +1,235 @@
+package cn.iocoder.yudao.module.system.service.doctororder;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.LongDoctorOrderSaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.LongDoctorOrderDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.LongDoctorOrderEntryDO;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.LongDoctorOrderEntryMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.LongDoctorOrderMapper;
+import cn.iocoder.yudao.module.system.enums.biz.LongOrderEntryStatusEnum;
+import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
+import cn.iocoder.yudao.module.system.service.biz.BuildService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.Period;
+import java.time.ZoneId;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 长期医嘱 Service 实现
+ *
+ * @author 系统
+ */
+@Service
+@Validated
+public class LongDoctorOrderServiceImpl implements LongDoctorOrderService {
+
+    @Resource
+    private LongDoctorOrderMapper longDoctorOrderMapper;
+    @Resource
+    private LongDoctorOrderEntryMapper longDoctorOrderEntryMapper;
+    @Resource
+    private ElderlyInfoMapper elderlyInfoMapper;
+    @Resource
+    private BuildService buildService;
+
+    @Override
+    public PageResult<LongDoctorOrderRespVO> getLongDoctorOrderPage(LongDoctorOrderPageReqVO reqVO) {
+        PageResult<LongDoctorOrderDO> pageResult = longDoctorOrderMapper.selectPage(reqVO);
+        List<LongDoctorOrderRespVO> list = pageResult.getList().stream()
+                .map(this::convertToResp)
+                .collect(Collectors.toList());
+        return new PageResult<>(list, pageResult.getTotal());
+    }
+
+    @Override
+    public LongDoctorOrderRespVO getLongDoctorOrder(Long id) {
+        LongDoctorOrderDO orderDO = longDoctorOrderMapper.selectById(id);
+        if (orderDO == null) {
+            return null;
+        }
+        return convertToResp(orderDO);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createLongDoctorOrder(LongDoctorOrderSaveReqVO reqVO) {
+        ElderlyInfoDO elder = elderlyInfoMapper.selectById(reqVO.getElderId());
+        if (elder == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_ELDER_NOT_EXISTS);
+        }
+        LongDoctorOrderDO orderDO = new LongDoctorOrderDO();
+        fillOrderBase(orderDO, elder);
+        longDoctorOrderMapper.insert(orderDO);
+
+        if (CollUtil.isNotEmpty(reqVO.getEntries())) {
+            for (LongDoctorOrderSaveReqVO.Entry entry : reqVO.getEntries()) {
+                LongDoctorOrderEntryDO entryDO = new LongDoctorOrderEntryDO();
+                copyEntry(entryDO, entry);
+                if (entryDO.getStatus() == null) {
+                    entryDO.setStatus(LongOrderEntryStatusEnum.NOT_STARTED.getStatus());
+                }
+                entryDO.setLongDoctorOrderId(orderDO.getId());
+                longDoctorOrderEntryMapper.insert(entryDO);
+            }
+        }
+        return orderDO.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateLongDoctorOrder(LongDoctorOrderSaveReqVO reqVO) {
+        LongDoctorOrderDO orderDO = longDoctorOrderMapper.selectById(reqVO.getId());
+        if (orderDO == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_NOT_EXISTS);
+        }
+        ElderlyInfoDO elder = elderlyInfoMapper.selectById(reqVO.getElderId());
+        if (elder == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_ELDER_NOT_EXISTS);
+        }
+        fillOrderBase(orderDO, elder);
+        longDoctorOrderMapper.updateById(orderDO);
+
+        // 条目 新增/修改/删除
+        List<LongDoctorOrderEntryDO> existEntries = longDoctorOrderEntryMapper.selectListByOrderId(orderDO.getId());
+        Set<Long> existIds = existEntries.stream().map(LongDoctorOrderEntryDO::getId).collect(Collectors.toSet());
+        Set<Long> reqIds = new HashSet<>();
+        if (CollUtil.isNotEmpty(reqVO.getEntries())) {
+            for (LongDoctorOrderSaveReqVO.Entry entry : reqVO.getEntries()) {
+                if (entry.getId() != null) {
+                    reqIds.add(entry.getId());
+                    LongDoctorOrderEntryDO entryDO = longDoctorOrderEntryMapper.selectById(entry.getId());
+                    if (entryDO == null) {
+                        continue;
+                    }
+                    copyEntry(entryDO, entry);
+                    longDoctorOrderEntryMapper.updateById(entryDO);
+                } else {
+                    LongDoctorOrderEntryDO entryDO = new LongDoctorOrderEntryDO();
+                    copyEntry(entryDO, entry);
+                    if (entryDO.getStatus() == null) {
+                        entryDO.setStatus(LongOrderEntryStatusEnum.NOT_STARTED.getStatus());
+                    }
+                    entryDO.setLongDoctorOrderId(orderDO.getId());
+                    longDoctorOrderEntryMapper.insert(entryDO);
+                }
+            }
+        }
+        // 删除请求中不存在的旧条目
+        for (Long existId : existIds) {
+            if (!reqIds.contains(existId)) {
+                longDoctorOrderEntryMapper.deleteById(existId);
+            }
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteLongDoctorOrder(Long id) {
+        if (longDoctorOrderMapper.selectById(id) == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_NOT_EXISTS);
+        }
+        longDoctorOrderEntryMapper.delete(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<LongDoctorOrderEntryDO>()
+                .eq(LongDoctorOrderEntryDO::getLongDoctorOrderId, id));
+        longDoctorOrderMapper.deleteById(id);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateLongDoctorOrderEntryStatus(Long id, Integer status) {
+        LongDoctorOrderEntryDO entryDO = longDoctorOrderEntryMapper.selectById(id);
+        if (entryDO == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_ENTRY_NOT_EXISTS);
+        }
+        entryDO.setStatus(status);
+        if (LongOrderEntryStatusEnum.STOPPED.getStatus().equals(status)) {
+            if (entryDO.getStopTime() == null) {
+                entryDO.setStopTime(LocalDateTime.now());
+            }
+        }
+        longDoctorOrderEntryMapper.updateById(entryDO);
+    }
+
+    // ======================== 私有方法 ========================
+
+    private LongDoctorOrderRespVO convertToResp(LongDoctorOrderDO orderDO) {
+        LongDoctorOrderRespVO respVO = new LongDoctorOrderRespVO();
+        org.springframework.beans.BeanUtils.copyProperties(orderDO, respVO);
+        List<LongDoctorOrderEntryDO> entries = longDoctorOrderEntryMapper.selectListByOrderId(orderDO.getId());
+        respVO.setEntryCount(entries.size());
+        LocalDateTime latestOrderTime = entries.stream()
+                .map(LongDoctorOrderEntryDO::getOrderTime)
+                .filter(Objects::nonNull)
+                .max(LocalDateTime::compareTo)
+                .orElse(null);
+        respVO.setLatestOrderTime(latestOrderTime);
+        respVO.setEntries(entries.stream().map(this::convertEntry).collect(Collectors.toList()));
+        fillElderAge(respVO, orderDO.getElderId());
+        return respVO;
+    }
+
+    private void fillElderAge(LongDoctorOrderRespVO respVO, Long elderId) {
+        if (elderId != null) {
+            ElderlyInfoDO elder = elderlyInfoMapper.selectById(elderId);
+            if (elder != null && elder.getBirthday() != null) {
+                respVO.setElderAge(calcAge(elder.getBirthday()));
+            }
+        }
+    }
+
+    private static int calcAge(Date birthday) {
+        LocalDate birth = birthday.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+        return Period.between(birth, LocalDate.now()).getYears();
+    }
+
+    private LongDoctorOrderRespVO.Entry convertEntry(LongDoctorOrderEntryDO entryDO) {
+        LongDoctorOrderRespVO.Entry entry = new LongDoctorOrderRespVO.Entry();
+        org.springframework.beans.BeanUtils.copyProperties(entryDO, entry);
+        LongOrderEntryStatusEnum statusEnum = LongOrderEntryStatusEnum.getByStatus(entryDO.getStatus());
+        entry.setStatusText(statusEnum == null ? "" : statusEnum.getName());
+        return entry;
+    }
+
+    private void copyEntry(LongDoctorOrderEntryDO entryDO, LongDoctorOrderSaveReqVO.Entry entry) {
+        entryDO.setOrderTime(entry.getOrderTime());
+        entryDO.setOrderContent(entry.getOrderContent());
+        entryDO.setFrequency(entry.getFrequency());
+        entryDO.setMedTime(entry.getMedTime());
+        entryDO.setRoute(entry.getRoute());
+        entryDO.setDoctorSign(entry.getDoctorSign());
+        entryDO.setNurseSign(entry.getNurseSign());
+        entryDO.setStopTime(entry.getStopTime());
+        entryDO.setStopDoctorSign(entry.getStopDoctorSign());
+        entryDO.setStopNurseSign(entry.getStopNurseSign());
+        entryDO.setRemark(entry.getRemark());
+        if (entry.getStatus() != null) {
+            entryDO.setStatus(entry.getStatus());
+        }
+    }
+
+    private void fillOrderBase(LongDoctorOrderDO orderDO, ElderlyInfoDO elder) {
+        orderDO.setElderId(elder.getId());
+        orderDO.setElderName(elder.getElderName());
+        if (elder.getElderSex() != null) {
+            orderDO.setGender(elder.getElderSex());
+            orderDO.setGenderName(elder.getElderSex() == 1 ? "男" : elder.getElderSex() == 2 ? "女" : "");
+        }
+        orderDO.setBedName(buildService.getFullBedName(elder.getId()));
+        orderDO.setNurseLevelName(elder.getNurseLevelName());
+        orderDO.setTenantId(TenantContextHolder.getTenantId());
+    }
+
+}

+ 25 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/ShortDoctorOrderService.java

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.system.service.doctororder;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderSaveReqVO;
+
+/**
+ * 临时医嘱 Service
+ *
+ * @author 系统
+ */
+public interface ShortDoctorOrderService {
+
+    PageResult<ShortDoctorOrderRespVO> getShortDoctorOrderPage(ShortDoctorOrderPageReqVO reqVO);
+
+    ShortDoctorOrderRespVO getShortDoctorOrder(Long id);
+
+    Long createShortDoctorOrder(ShortDoctorOrderSaveReqVO reqVO);
+
+    void updateShortDoctorOrder(ShortDoctorOrderSaveReqVO reqVO);
+
+    void deleteShortDoctorOrder(Long id);
+
+}

+ 209 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/doctororder/ShortDoctorOrderServiceImpl.java

@@ -0,0 +1,209 @@
+package cn.iocoder.yudao.module.system.service.doctororder;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.doctororder.vo.ShortDoctorOrderSaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ShortDoctorOrderDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.biz.ShortDoctorOrderEntryDO;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ShortDoctorOrderEntryMapper;
+import cn.iocoder.yudao.module.system.dal.mysql.biz.ShortDoctorOrderMapper;
+import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
+import cn.iocoder.yudao.module.system.service.biz.BuildService;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.Period;
+import java.time.ZoneId;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 临时医嘱 Service 实现
+ *
+ * @author 系统
+ */
+@Service
+@Validated
+public class ShortDoctorOrderServiceImpl implements ShortDoctorOrderService {
+
+    @Resource
+    private ShortDoctorOrderMapper shortDoctorOrderMapper;
+    @Resource
+    private ShortDoctorOrderEntryMapper shortDoctorOrderEntryMapper;
+    @Resource
+    private ElderlyInfoMapper elderlyInfoMapper;
+    @Resource
+    private BuildService buildService;
+
+    @Override
+    public PageResult<ShortDoctorOrderRespVO> getShortDoctorOrderPage(ShortDoctorOrderPageReqVO reqVO) {
+        PageResult<ShortDoctorOrderDO> pageResult = shortDoctorOrderMapper.selectPage(reqVO);
+        List<ShortDoctorOrderRespVO> list = pageResult.getList().stream()
+                .map(this::convertToResp)
+                .collect(Collectors.toList());
+        return new PageResult<>(list, pageResult.getTotal());
+    }
+
+    @Override
+    public ShortDoctorOrderRespVO getShortDoctorOrder(Long id) {
+        ShortDoctorOrderDO orderDO = shortDoctorOrderMapper.selectById(id);
+        if (orderDO == null) {
+            return null;
+        }
+        return convertToResp(orderDO);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Long createShortDoctorOrder(ShortDoctorOrderSaveReqVO reqVO) {
+        ElderlyInfoDO elder = elderlyInfoMapper.selectById(reqVO.getElderId());
+        if (elder == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_ELDER_NOT_EXISTS);
+        }
+        ShortDoctorOrderDO orderDO = new ShortDoctorOrderDO();
+        fillOrderBase(orderDO, elder);
+        shortDoctorOrderMapper.insert(orderDO);
+
+        if (CollUtil.isNotEmpty(reqVO.getEntries())) {
+            for (ShortDoctorOrderSaveReqVO.Entry entry : reqVO.getEntries()) {
+                ShortDoctorOrderEntryDO entryDO = new ShortDoctorOrderEntryDO();
+                copyEntry(entryDO, entry);
+                entryDO.setShortDoctorOrderId(orderDO.getId());
+                shortDoctorOrderEntryMapper.insert(entryDO);
+            }
+        }
+        return orderDO.getId();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateShortDoctorOrder(ShortDoctorOrderSaveReqVO reqVO) {
+        ShortDoctorOrderDO orderDO = shortDoctorOrderMapper.selectById(reqVO.getId());
+        if (orderDO == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_NOT_EXISTS);
+        }
+        ElderlyInfoDO elder = elderlyInfoMapper.selectById(reqVO.getElderId());
+        if (elder == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_ELDER_NOT_EXISTS);
+        }
+        fillOrderBase(orderDO, elder);
+        shortDoctorOrderMapper.updateById(orderDO);
+
+        List<ShortDoctorOrderEntryDO> existEntries = shortDoctorOrderEntryMapper.selectListByOrderId(orderDO.getId());
+        Set<Long> existIds = existEntries.stream().map(ShortDoctorOrderEntryDO::getId).collect(Collectors.toSet());
+        Set<Long> reqIds = new HashSet<>();
+        if (CollUtil.isNotEmpty(reqVO.getEntries())) {
+            for (ShortDoctorOrderSaveReqVO.Entry entry : reqVO.getEntries()) {
+                if (entry.getId() != null) {
+                    reqIds.add(entry.getId());
+                    ShortDoctorOrderEntryDO entryDO = shortDoctorOrderEntryMapper.selectById(entry.getId());
+                    if (entryDO == null) {
+                        continue;
+                    }
+                    copyEntry(entryDO, entry);
+                    shortDoctorOrderEntryMapper.updateById(entryDO);
+                } else {
+                    ShortDoctorOrderEntryDO entryDO = new ShortDoctorOrderEntryDO();
+                    copyEntry(entryDO, entry);
+                    entryDO.setShortDoctorOrderId(orderDO.getId());
+                    shortDoctorOrderEntryMapper.insert(entryDO);
+                }
+            }
+        }
+        for (Long existId : existIds) {
+            if (!reqIds.contains(existId)) {
+                shortDoctorOrderEntryMapper.deleteById(existId);
+            }
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteShortDoctorOrder(Long id) {
+        if (shortDoctorOrderMapper.selectById(id) == null) {
+            throw new ServiceException(ErrorCodeConstants.ELDERLY_DOCTOR_ORDER_NOT_EXISTS);
+        }
+        shortDoctorOrderEntryMapper.delete(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ShortDoctorOrderEntryDO>()
+                .eq(ShortDoctorOrderEntryDO::getShortDoctorOrderId, id));
+        shortDoctorOrderMapper.deleteById(id);
+    }
+
+    // ======================== 私有方法 ========================
+
+    private ShortDoctorOrderRespVO convertToResp(ShortDoctorOrderDO orderDO) {
+        ShortDoctorOrderRespVO respVO = new ShortDoctorOrderRespVO();
+        org.springframework.beans.BeanUtils.copyProperties(orderDO, respVO);
+        List<ShortDoctorOrderEntryDO> entries = shortDoctorOrderEntryMapper.selectListByOrderId(orderDO.getId());
+        respVO.setEntryCount(entries.size());
+        LocalDateTime latestOrderTime = entries.stream()
+                .map(ShortDoctorOrderEntryDO::getOrderTime)
+                .filter(Objects::nonNull)
+                .max(LocalDateTime::compareTo)
+                .orElse(null);
+        respVO.setLatestOrderTime(latestOrderTime);
+        LocalDateTime latestExecuteTime = entries.stream()
+                .map(ShortDoctorOrderEntryDO::getExecuteTime)
+                .filter(Objects::nonNull)
+                .max(LocalDateTime::compareTo)
+                .orElse(null);
+        respVO.setLatestExecuteTime(latestExecuteTime);
+        respVO.setEntries(entries.stream().map(this::convertEntry).collect(Collectors.toList()));
+        fillElderAge(respVO, orderDO.getElderId());
+        return respVO;
+    }
+
+    private void fillElderAge(ShortDoctorOrderRespVO respVO, Long elderId) {
+        if (elderId != null) {
+            ElderlyInfoDO elder = elderlyInfoMapper.selectById(elderId);
+            if (elder != null && elder.getBirthday() != null) {
+                respVO.setElderAge(calcAge(elder.getBirthday()));
+            }
+        }
+    }
+
+    private static int calcAge(Date birthday) {
+        LocalDate birth = birthday.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+        return Period.between(birth, LocalDate.now()).getYears();
+    }
+
+    private ShortDoctorOrderRespVO.Entry convertEntry(ShortDoctorOrderEntryDO entryDO) {
+        ShortDoctorOrderRespVO.Entry entry = new ShortDoctorOrderRespVO.Entry();
+        org.springframework.beans.BeanUtils.copyProperties(entryDO, entry);
+        return entry;
+    }
+
+    private void copyEntry(ShortDoctorOrderEntryDO entryDO, ShortDoctorOrderSaveReqVO.Entry entry) {
+        entryDO.setOrderTime(entry.getOrderTime());
+        entryDO.setOrderContent(entry.getOrderContent());
+        entryDO.setFrequency(entry.getFrequency());
+        entryDO.setMedTime(entry.getMedTime());
+        entryDO.setRoute(entry.getRoute());
+        entryDO.setDoctorSign(entry.getDoctorSign());
+        entryDO.setExecuteTime(entry.getExecuteTime());
+        entryDO.setNurseSign(entry.getNurseSign());
+        entryDO.setRemark(entry.getRemark());
+    }
+
+    private void fillOrderBase(ShortDoctorOrderDO orderDO, ElderlyInfoDO elder) {
+        orderDO.setElderId(elder.getId());
+        orderDO.setElderName(elder.getElderName());
+        if (elder.getElderSex() != null) {
+            orderDO.setGender(elder.getElderSex());
+            orderDO.setGenderName(elder.getElderSex() == 1 ? "男" : elder.getElderSex() == 2 ? "女" : "");
+        }
+        orderDO.setBedName(buildService.getFullBedName(elder.getId()));
+        orderDO.setNurseLevelName(elder.getNurseLevelName());
+        orderDO.setTenantId(TenantContextHolder.getTenantId());
+    }
+
+}

+ 1 - 1
yudao-server/src/main/resources/application-dev.yaml

@@ -57,7 +57,7 @@ spring:
     host: 47.107.245.0 # 地址
     port: 6379 # 端口
     database: 9 # 数据库索引
-    password: kyjYn@2020lsj # 密码,建议生产环境开启
+    password: kyjYn2020lsj # 密码,建议生产环境开启
 
 --- #################### 定时任务相关配置 ####################