liusheng
4 天以前 0bbbd746e8c39d91ad7b47a4e36e29ab972dc98c
ruoyi-task/src/main/java/com/ruoyi/task/api/contract/VisitTaskCreateApiImpl.java
@@ -12,6 +12,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.ruoyi.task.domain.entity.ServiceSubtaskEntity;
import com.ruoyi.task.domain.ServiceSubtask;
import com.ruoyi.task.domain.ServiceTask;
@@ -186,6 +187,28 @@
        return !CollectionUtils.isEmpty(list);
    }
    /**
     * 是否存在「同一患者 + 同一次出院记录 + 同一任务」的子任务({@code del_flag = 0})。
     * <p>
     * 直接用现成的 {@code selectServiceSubtaskList}(本身就带
     * {@code del_flag = 0} + {@code patid} + {@code inhospid} + {@code taskid} 三个条件),
     * 不新增 XML —— 避免为了一个"有没有"再写一条等价 SQL。
     * <p>
     * ⚠️ 不按 {@code sendstate} 过滤:已停用(sendstate=4)的历史行也算"生成过"。
     * 否则"停旧一条 + 再生成一条"会无限累积 —— 这正是 2026-10 同一患者几十条子任务的成因。
     */
    @Override
    public boolean existsSubtask(Long patid, Long inhospid, Long taskid) {
        if (patid == null || taskid == null) {
            return false;
        }
        ServiceSubtaskEntity q = new ServiceSubtaskEntity();
        q.setPatid(patid);
        q.setInhospid(inhospid);
        q.setTaskid(taskid);
        return !CollectionUtils.isEmpty(serviceSubtaskMapper.selectServiceSubtaskList(q));
    }
    // ==========================================================================
    // 字段搬运(逐字段对照,勿"顺手精简")
    // ==========================================================================
@@ -194,17 +217,27 @@
        VisitLongTaskDto dto = new VisitLongTaskDto();
        dto.setTaskid(t.getTaskid());
        dto.setTaskName(t.getTaskName());
        dto.setTaskDesc(t.getTaskDesc());
        dto.setType(t.getType());
        dto.setServiceType(t.getServiceType());
        dto.setTemplateid(t.getTemplateid());
        dto.setTemplatename(t.getTemplatename());
        dto.setLibtemplateid(t.getLibtemplateid());
        dto.setLibtemplatename(t.getLibtemplatename());
        dto.setSendDay(t.getSendDay());
        dto.setPreachform(t.getPreachform());
        dto.setPreachformDesc(t.getPreachformDesc());
        dto.setOrgid(t.getOrgid());
        dto.setCampusid(t.getCampusid());
        dto.setHosType(t.getHospType());
        // 原 boxedServiceSubtask 第一行的 DtoConversionUtils.sourceToTarget 会把这 6 个
        // 拷进子任务并随 insertServiceSubtask 落库;不搬就是静默丢列(见 VisitLongTaskDto 注释)
        dto.setGuid(t.getGuid());
        dto.setPid(t.getPid());
        dto.setSendType(t.getSendType());
        dto.setIsupload(t.getIsupload());
        dto.setTextParam(t.getTextParam());
        dto.setUploadTime(t.getUploadTime());
        dto.setUpdateBy(t.getUpdateBy());
        dto.setCreateBy(t.getCreateBy());
        return dto;
@@ -230,6 +263,7 @@
        e.setSex(d.getSex());
        e.setAge(d.getAge());
        e.setInhospid(d.getInhospid());
        e.setHospno(d.getHospno());
        e.setNurseId(d.getNurseId());
        e.setNurseName(d.getNurseName());
        e.setDrcode(d.getDrcode());
@@ -246,6 +280,7 @@
        e.setTemplateid(d.getTemplateid());
        e.setTemplatename(d.getTemplatename());
        e.setLibtemplateid(d.getLibtemplateid());
        e.setLibtemplatename(d.getLibtemplatename());
        e.setStarttime(d.getStarttime());
        e.setEndtime(d.getEndtime());
        e.setLongSendTime(d.getLongSendTime());
@@ -266,6 +301,29 @@
        e.setOperationItemId(d.getOperationItemId());
        e.setCreateBy(d.getCreateBy());
        e.setUpdateBy(d.getUpdateBy());
        // ⚠️ create_time / update_time 之前也是漏的:
        //    组装器(boxedServiceSubtask 原 L1157-1177)、writeInSubTask 的每个 insert 分支
        //    都在 setCreateTime/setUpdateTime,XML 也有对应条件列,但这里没映射 →
        //    两条时间列静默落 NULL(2026-10 实机发现)。
        e.setCreateTime(d.getCreateTime());
        e.setUpdateTime(d.getUpdateTime());
        // ------------------------------------------------------------------
        // 任务来源字段(原 boxedServiceSubtask 第一行 DtoConversionUtils 整批拷入)
        //
        // ⚠️ 这 8 个是"任务 → 子任务"的快照列。原先只搬了 taskid/serviceType 等,
        //    taskName/taskDesc/type/libtemplatename 以及 guid/pid/sendType/isupload/
        //    textParam/uploadTime 全部漏映射 → XML 的 <if test="xxx != null"> 直接跳过,
        //    service_subtask 上这些列静默为 NULL(2026-10 由 addSubTaskByRule 实机发现)。
        // ------------------------------------------------------------------
        e.setTaskName(d.getTaskName());
        e.setTaskDesc(d.getTaskDesc());
        e.setType(d.getType());
        e.setGuid(d.getGuid());
        e.setPid(d.getPid());
        e.setSendType(d.getSendType());
        e.setIsupload(d.getIsupload());
        e.setTextParam(d.getTextParam());
        e.setUploadTime(d.getUploadTime());
        // ------------------------------------------------------------------
        // 门急诊随访专用字段(OuthospSubtaskDraft)。
@@ -277,10 +335,9 @@
        //    见 OuthospSubtaskDraft 的类注释。
        // ------------------------------------------------------------------
        if (d instanceof com.ruoyi.common.core.service.dto.OuthospSubtaskDraft) {
            com.ruoyi.common.core.service.dto.OuthospSubtaskDraft o =
                    (com.ruoyi.common.core.service.dto.OuthospSubtaskDraft) d;
            com.ruoyi.common.core.service.dto.OuthospSubtaskDraft o = (com.ruoyi.common.core.service.dto.OuthospSubtaskDraft) d;
            // hospno 已上提到父类 VisitSubtaskDraft(上面统一映射过了),这里不再重复
            // 只有父类没有的字段才在这里补映射(其余如 sendname/sfzh/phone/sex/age 父类已有)
            e.setHospno(o.getHospno());
            e.setAdmindate(o.getAdmitdate());
            e.setFinishtime(o.getFinishtime());
            // ⚠️ 原实现硬编码 "1"(不读 serviceTask.getHospType()),此处保持一致