liusheng
2026-11-03 7191c6d38f03f2e1baf39f959227ce9c038e4e96
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/CollectHISServiceImpl.java
@@ -1,5 +1,7 @@
package com.ruoyi.quartz.service.impl;
import com.ruoyi.othervisit.api.OtherVisitFacade;
import com.ruoyi.inhospvisit.api.InhospVisitFacade;
import com.google.gson.Gson;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
@@ -10,7 +12,6 @@
import com.ruoyi.quartz.mapper.CollectHISMapper;
import com.ruoyi.quartz.service.ICollectHISService;
import com.smartor.domain.*;
import com.smartor.domain.entity.ServiceSubtaskEntity;
import com.smartor.mapper.*;
import com.smartor.service.IPatMedOuthospService;
import lombok.extern.slf4j.Slf4j;
@@ -26,14 +27,38 @@
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.ruoyi.othervisit.domain.PatMedOperationItem;
import com.ruoyi.outpatientvisit.mapper.PatMedOuthospMapper;
import com.ruoyi.othervisit.domain.PatMedOperation;
import com.ruoyi.outpatientvisit.domain.PatMedOuthosp;
import com.ruoyi.inhospvisit.domain.PatMedInhosp;
import com.ruoyi.common.core.domain.entity.PatArchive;
import com.ruoyi.task.domain.entity.ServiceSubtaskEntity;
import com.ruoyi.task.domain.ServiceSubtask;
import com.ruoyi.task.mapper.ServiceSubtaskMapper;
import com.ruoyi.patarchive.mapper.PatArchiveMapper;
import com.ruoyi.common.core.domain.entity.Icd10;
import com.ruoyi.common.mapper.Icd10Mapper;
import com.ruoyi.system.mapper.ext.SysUser2Mapper;
import com.ruoyi.system.mapper.ext.SysDept2Mapper;
import com.ruoyi.system.mapper.ext.SysUserDeptMapper;
import com.ruoyi.patarchive.mapper.ShardingMapper;
import com.ruoyi.datacollection.domain.HnDataGatherVO;
@Slf4j
@Service
public class CollectHISServiceImpl implements ICollectHISService {
    @Autowired
    private CollectHISMapper chMapper;
    /**
     * 手术数据一律经 ruoyi-othervisit 的门面取用(跨模块数据访问原则)。
     */
    @Autowired
    private OtherVisitFacade otherVisitFacade;
    @Autowired
    private SysUser2Mapper sysUser2Mapper;
@@ -57,7 +82,7 @@
    private PatMedOuthospMapper patMedOuthospMapper;
    @Autowired
    private PatMedInhospMapper patMedInhospMapper;
    private InhospVisitFacade inhospVisitFacade;
    @Autowired
    private PatArchiveMapper patArchiveMapper;
@@ -77,17 +102,18 @@
    @Autowired
    private RedisCache redisCache;
    /**
     * 用户同步任务运行标记,避免重复点击/重复调用并发跑全量同步
     */
    private final AtomicBoolean userSyncRunning = new AtomicBoolean(false);
    private static final long SHARDING_THRESHOLD = 5_000_000L;
    private static final String PAT_ARCHIVE_TABLE = "pat_archive";
    private static final String PAT_MED_INHOSP_TABLE = "pat_med_inhosp";
    @Value("${spring.profiles.active}")
    private String active;
    @Autowired
    private PatMedOperationMapper patMedOperationMapper;
    @Autowired
    private PatMedOperationItemMapper patMedOperationItemMapper;
    @Override
    public List<PatArchive> selectPatArchiveList(PatArchive patArchive) {
@@ -238,7 +264,7 @@
                //同步出入院
                PatMedInhosp pmi = new PatMedInhosp();
                pmi.setSerialnum(pm.getSerialnum());
                List<PatMedInhosp> patMedInhospList1 = patMedInhospMapper.selectPatMedInhospListBySerialnum(pmi);
                List<PatMedInhosp> patMedInhospList1 = inhospVisitFacade.selectPatMedInhospListBySerialnum(pmi);
                if (patMedInhospList1.size() == 0) {
                    pm.setCreateTime(new Date());
                    //市一 院区id对应orgid,机构id为默认的1
@@ -246,7 +272,7 @@
                        pm.setCampusid(pm.getOrgid());
                        pm.setOrgid("1");
                    }
                    count += patMedInhospMapper.insertPatMedInhosp(pm);
                    count += inhospVisitFacade.insertPatMedInhosp(pm);
                } else {
                    pm.setInhospid(patMedInhospList1.get(0).getInhospid());
                    pm.setUpdateTime(new Date());
@@ -255,7 +281,7 @@
                        pm.setCampusid(pm.getOrgid());
                        pm.setOrgid("1");
                    }
                    count += patMedInhospMapper.updatePatMedInhosp(pm);
                    count += inhospVisitFacade.updatePatMedInhosp(pm);
                }
            } catch (Exception ex) {
                log.info("同步出入院:" + ex.getMessage());
@@ -366,15 +392,15 @@
                }
                PatMedOperation oper = new PatMedOperation();
                oper.setOpreqid(operation.getOpreqid());
                List<PatMedOperation> patMedOperations1 = patMedOperationMapper.selectPatMedOperationList(oper);
                List<PatMedOperation> patMedOperations1 = otherVisitFacade.selectOperationList(oper);
                if (CollectionUtils.isNotEmpty(patMedOperations1)) {
                    operation.setId(patMedOperations1.get(0).getId());
                    operation.setUpdateTime(new Date());
                    count += patMedOperationMapper.updatePatMedOperation(operation);
                    count += otherVisitFacade.updateOperation(operation);
                    syncOperItem(operation);
                } else {
                    operation.setCreateTime(new Date());
                    count += patMedOperationMapper.insertPatMedOperation(operation);
                    count += otherVisitFacade.insertOperation(operation);
                    syncOperItem(operation);
                }
            } catch (Exception ex) {
@@ -387,7 +413,7 @@
    private Integer cancelOper(PatMedOperation oper){
        PatMedOperation operationVo = new PatMedOperation();
        operationVo.setOpreqid(oper.getOpreqid());
        List<PatMedOperation> operations = patMedOperationMapper.selectPatMedOperationList(operationVo);
        List<PatMedOperation> operations = otherVisitFacade.selectOperationList(operationVo);
        PatMedOperation operation = new PatMedOperation();
        if(CollectionUtils.isEmpty(operations)){
            return 0;
@@ -399,7 +425,7 @@
        //获取需要出院手术随访,未处理的数据
        pmoi.setOpid(operation.getId().toString());
        List<PatMedOperationItem> patMedOperationItems
                = patMedOperationItemMapper.selectOperationItemList(pmoi);
                = otherVisitFacade.selectOperationItemListByCondition(pmoi);
        List<Long> operationItemIds = patMedOperationItems.stream()
                .map(PatMedOperationItem::getId)
                .filter(Objects::nonNull)
@@ -432,8 +458,8 @@
            }
        }
        operation.setUpdateTime(new Date());
        patMedOperationMapper.updatePatMedOperation(operation);
        patMedOperationItemMapper.deleteSoftPatMedOperationItemByOpId(operation.getOpid());
        otherVisitFacade.updateOperation(operation);
        otherVisitFacade.deleteSoftOperationItemByOpId(operation.getOpid());
        return 1;
    }
@@ -448,7 +474,7 @@
            operation.setOpid(operation.getId().toString());
        }
        operation.setUpdateTime(new Date());
        patMedOperationMapper.updatePatMedOperation(operation);
        otherVisitFacade.updateOperation(operation);
        Integer count = 0;
        if(StringUtils.isNotEmpty(operation.getOpid())){
@@ -465,7 +491,7 @@
            PatMedOperationItem operItem = new PatMedOperationItem();
            operItem.setOperationid(operation.getOpreqid());
            List<PatMedOperationItem> patMedOperationItems1 = patMedOperationItemMapper.selectPatMedOperationItemList(operItem);
            List<PatMedOperationItem> patMedOperationItems1 = otherVisitFacade.selectOperationItemList(operItem);
            Map<String, List<PatMedOperationItem>> maps = ArrayListUtils.splitListsById(patMedOperationItems,
                    patMedOperationItems1, PatMedOperationItem::getOperationid);
@@ -486,12 +512,12 @@
                    operationItem.setOperationid(operation.getOpreqid());
                    operationItem.setOpercheckFlag("0");
                    operationItem.setCreateTime(new Date());
                    count += patMedOperationItemMapper.insertPatMedOperationItem(operationItem);
                    count += otherVisitFacade.insertOperationItem(operationItem);
                }
                for (PatMedOperationItem operationItem : delItems) {
                    operationItem.setUpdateTime(new Date());
                    count += patMedOperationItemMapper.deletePatMedOperationItemByOperationid(operationItem.getOperationid());
                    count += otherVisitFacade.deleteOperationItemByOperationid(operationItem.getOperationid());
                }
                for (PatMedOperationItem operationItem : editItems) {
@@ -500,7 +526,7 @@
                    operationItem.setOpid(operation.getId().toString());
                    operationItem.setOperationid(operation.getOpreqid());
                    operationItem.setUpdateTime(new Date());
                    count += patMedOperationItemMapper.updatePatMedOperationItemByOperationid(operationItem);
                    count += otherVisitFacade.updateOperationItemByOperationid(operationItem);
                }
                log.info("同步手术id={}详情信息数量, 新增{}条,删除{}条,修改{}条", operation.getId(), addItems.size(), delItems.size(), editItems.size());
            } catch (Exception ex) {
@@ -508,8 +534,8 @@
            }
//            try {
//                patMedOperationItemMapper.deleteHardPatMedOperationItemByOpId(operation.getOpid());
//                count += patMedOperationItemMapper.insertPatMedOperationItems(patMedOperationItems);
//                otherVisitFacade.deleteHardOperationItemByOpId(operation.getOpid());
//                count += otherVisitFacade.insertOperationItems(patMedOperationItems);
//            }catch (Exception ex) {
//                log.info("同步手术详情信息:" + ex.getMessage());
//            }
@@ -593,20 +619,20 @@
                //入院
                pm.setInhospstate("0");
                pm.setCreateTime(new Date());
                patMedInhospMapper.insertPatMedInhosp(pm);
                inhospVisitFacade.insertPatMedInhosp(pm);
            } else if (!Objects.isNull(patMedInhosp.getStartOutHospTime()) && !Objects.isNull(patMedInhosp.getEndOutHospTime())) {
                //出院
                pm.setInhospstate("1");
                pm.setUpdateTime(new Date());
                PatMedInhosp pmi = new PatMedInhosp();
                pmi.setSerialnum(pm.getSerialnum());
                List<PatMedInhosp> patMedInhospList1 = patMedInhospMapper.selectPatMedInhospList(pmi);
                List<PatMedInhosp> patMedInhospList1 = inhospVisitFacade.selectPatMedInhospList(pmi);
                if (CollectionUtils.isEmpty(patMedInhospList1)) {
                    pm.setCreateTime(new Date());
                    patMedInhospMapper.insertPatMedInhosp(pm);
                    inhospVisitFacade.insertPatMedInhosp(pm);
                } else {
                    pm.setInhospid(patMedInhospList1.get(0).getInhospid());
                    patMedInhospMapper.updatePatMedInhosp(pm);
                    inhospVisitFacade.updatePatMedInhosp(pm);
                }
            }
@@ -701,6 +727,39 @@
            size += icd10Mapper.batchIcd10(icd10s);
        }
        return size;
    }
    /**
     * 异步同步用户信息:接口立即返回,实际同步交给线程池后台执行。
     * 使用 AtomicBoolean 防止重复提交导致多个全量同步任务并发执行。
     */
    @Override
    public boolean selectUserListAsync(SysUser sysUser) {
        if (!userSyncRunning.compareAndSet(false, true)) {
            log.warn("用户信息同步任务正在执行中,忽略本次提交");
            return false;
        }
        try {
            taskExecutor.execute(() -> {
                long start = System.currentTimeMillis();
                log.info("用户信息异步同步任务开始执行");
                try {
                    Integer count = selectUserList(sysUser);
                    log.info("用户信息异步同步任务执行完成,处理数量:{},耗时:{}ms",
                            count, System.currentTimeMillis() - start);
                } catch (Throwable e) {
                    log.error("用户信息异步同步任务执行失败,耗时:{}ms",
                            System.currentTimeMillis() - start, e);
                } finally {
                    userSyncRunning.set(false);
                }
            });
            return true;
        } catch (RuntimeException e) {
            userSyncRunning.set(false);
            log.error("用户信息异步同步任务提交失败", e);
            return false;
        }
    }
    @Override
@@ -817,7 +876,12 @@
        log.info("selectDeptList的采集到的数量为:{}", sysDepts.size());
        // count = sysDept2Mapper.batchDept(sysDepts);
        for (SysDept row : sysDepts) {
            SysDept sysDeptTemp = sysDept2Mapper.selectDeptByCode(row.getDeptCode(), null);
            // 科室和病区可能共用同一个 dept_code,必须按 dept_type + orgid 精确定位,否则 selectOne 会返回多条
            if (StringUtils.isEmpty(row.getDeptCode())) {
                log.warn("selectDeptList跳过deptCode为空的记录:{}", row);
                continue;
            }
            SysDept sysDeptTemp = sysDept2Mapper.selectDeptByCodeAndType(row.getDeptCode(), row.getOrgid(), row.getDeptType());
            if (sysDeptTemp != null && sysDeptTemp.getDeptName() != null) {
                row.setDeptId(sysDeptTemp.getDeptId());
                count += sysDept2Mapper.updateDept(row);