| | |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.common.utils.reflect.ReflectUtils; |
| | | import com.ruoyi.common.core.service.TaskOpsTriggerApi; |
| | | import com.ruoyi.task.api.spi.TaskSysConfigPort; |
| | | import com.ruoyi.task.api.spi.TaskSysUserDeptPort; |
| | | import com.ruoyi.satisfaction.api.SatisfactionExportBundle; |
| | | import com.ruoyi.satisfaction.api.SatisfactionFacade; |
| | | import com.ruoyi.task.api.spi.TaskSubtaskRecordPort; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import com.ruoyi.task.domain.ServiceSubtaskStatistic; |
| | | import com.ruoyi.task.domain.ServiceTask; |
| | | import com.ruoyi.task.domain.VO.ServiceSubtaskCotinueCountVO; |
| | | import com.ruoyi.task.service.IServiceSubtaskRecordService; |
| | | import com.ruoyi.task.service.IServiceSubtaskService; |
| | | import com.ruoyi.task.service.IServiceTaskService; |
| | | import com.ruoyi.task.domain.PatArchiveSrmVO; |
| | |
| | | import com.ruoyi.task.domain.VO.ServiceSubtaskVO; |
| | | import com.ruoyi.task.domain.VO.TransferDeptVO; |
| | | import com.ruoyi.task.domain.ServiceSubtaskExport; |
| | | import com.ruoyi.system.service.ISysConfigService; |
| | | import com.ruoyi.system.service.ISysUserDeptService; |
| | | |
| | | /** |
| | | * 单一任务(随访)Controller |
| | |
| | | private IServiceTaskService serviceTaskService; |
| | | |
| | | @Autowired |
| | | private TaskSysUserDeptPort taskSysUserDeptPort; |
| | | private ISysUserDeptService sysUserDeptService; |
| | | |
| | | @Autowired |
| | | private TaskSubtaskRecordPort serviceSubtaskRecordService; |
| | | private IServiceSubtaskRecordService serviceSubtaskRecordService; |
| | | |
| | | @Autowired |
| | | private TaskSysConfigPort taskSysConfigPort; |
| | | private ISysConfigService sysConfigService; |
| | | |
| | | /** |
| | | * 任务运维触发能力。 |
| | |
| | | @ApiOperation("查询患者随访信息") |
| | | @PostMapping("/patItem") |
| | | public Map<String, Object> patItem(@RequestBody ServiceSubtaskVO serviceSubtaskVO) { |
| | | // ==== 临时诊断计时:确认慢在哪一段后整段删除即可(只加日志,不改逻辑)==== |
| | | long tTotal = System.currentTimeMillis(); |
| | | long tMark = tTotal; |
| | | |
| | | serviceSubtaskVO.setPageNum(PageUtils.getOffset(serviceSubtaskVO.getPageNum(), serviceSubtaskVO.getPageSize())); |
| | | List<ServiceSubtaskRes> serviceSubtaskList = null; |
| | | LoginUser loginUser = getLoginUser(); |
| | | SysUser user = loginUser.getUser(); |
| | | serviceSubtaskVO.setOrgid(user.getOrgid()); |
| | | // 院区取登录会话里的值(登录页选择的院区,见 SysLoginService#login) |
| | | serviceSubtaskVO.setCampusid(user.getCampusid()); |
| | | ServiceSubtaskEntity serviceSubtaskEntity = null; |
| | | if (serviceSubtaskVO != null) { |
| | |
| | | serviceSubtaskEntity.setContinueContent(ObjectUtils.isNotEmpty(serviceSubtaskVO.getContinueContent()) ? serviceSubtaskVO.getContinueContent().toString() : null); |
| | | serviceSubtaskList = serviceSubtaskService.patItem(serviceSubtaskEntity); |
| | | } |
| | | log.info("[patItem耗时] 1.列表页(两阶段分页)={}ms,行数={}", System.currentTimeMillis() - tMark, |
| | | serviceSubtaskList == null ? -1 : serviceSubtaskList.size()); |
| | | tMark = System.currentTimeMillis(); |
| | | |
| | | // 批量查 subtask_record,1次SQL替代循环中N次单独查 |
| | | List<Long> subtaskIds = serviceSubtaskList.stream().map(ServiceSubtaskRes::getId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()); |
| | | Map<Long, List<ServiceSubtaskRecord>> recordMap = serviceSubtaskRecordService.selectRecordMapBySubtaskIds(subtaskIds); |
| | | |
| | | for (ServiceSubtaskRes serviceSubtask : serviceSubtaskList) { |
| | | serviceSubtask.setServiceSubtaskRecordList(recordMap.getOrDefault(serviceSubtask.getId(), new ArrayList<>())); |
| | | } |
| | | // List<Long> subtaskIds = serviceSubtaskList.stream().map(ServiceSubtaskRes::getId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()); |
| | | // Map<Long, List<ServiceSubtaskRecord>> recordMap = serviceSubtaskRecordService.selectRecordMapBySubtaskIds(subtaskIds); |
| | | // log.info("[patItem耗时] 2.subtask_record批量={}ms,入参id数={}", System.currentTimeMillis() - tMark, subtaskIds.size()); |
| | | // tMark = System.currentTimeMillis(); |
| | | // |
| | | // for (ServiceSubtaskRes serviceSubtask : serviceSubtaskList) { |
| | | // serviceSubtask.setServiceSubtaskRecordList(recordMap.getOrDefault(serviceSubtask.getId(), new ArrayList<>())); |
| | | // } |
| | | log.info("[patItem耗时] 3.记录回填={}ms", System.currentTimeMillis() - tMark); |
| | | tMark = System.currentTimeMillis(); |
| | | |
| | | // patItemCount 走Redis缓存版,避免每次全表聚合扫描 |
| | | Map<String, Object> map = getPatItemCountWithCache(serviceSubtaskEntity); |
| | | log.info("[patItem耗时] 4.统计patItemCount(含缓存)={}ms", System.currentTimeMillis() - tMark); |
| | | tMark = System.currentTimeMillis(); |
| | | map.put("serviceSubtaskList", serviceSubtaskList); |
| | | List<Map<String, Object>> list = new ArrayList<>(); |
| | | list.add(map); |
| | |
| | | total = CollectionUtils.isNotEmpty(serviceSubtasks) ? serviceSubtasks.size() : 0L; |
| | | } |
| | | |
| | | log.info("[patItem耗时] 5.组装返回total={}={}ms,整体合计={}ms", total, |
| | | System.currentTimeMillis() - tMark, System.currentTimeMillis() - tTotal); |
| | | return getDataTable3(total, list); |
| | | } |
| | | |
| | |
| | | sysUserWard.setOrgid(user.getOrgid()); |
| | | sysUserWard.setCampusid(user.getCampusid()); |
| | | sysUserWard.setDeptType("2"); |
| | | List<SysUserDept> wardList = taskSysUserDeptPort.selectSysUserDeptList(sysUserWard); |
| | | List<SysUserDept> wardList = sysUserDeptService.selectSysUserDeptList(sysUserWard); |
| | | if (CollectionUtils.isNotEmpty(wardList)) { |
| | | leavehospitaldistrictcodes = wardList.stream().map(SysUserDept::getDeptCode).collect(Collectors.toList()); |
| | | } |
| | |
| | | sysUserDept.setOrgid(user.getOrgid()); |
| | | sysUserDept.setCampusid(user.getCampusid()); |
| | | sysUserDept.setDeptType("1"); |
| | | List<SysUserDept> deptList = taskSysUserDeptPort.selectSysUserDeptList(sysUserDept); |
| | | List<SysUserDept> deptList = sysUserDeptService.selectSysUserDeptList(sysUserDept); |
| | | if (CollectionUtils.isNotEmpty(deptList)) { |
| | | deptCodes = deptList.stream().map(SysUserDept::getDeptCode).collect(Collectors.toList()); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | String followUpCountStyle = taskSysConfigPort.selectConfigValue("followUpCountStyle", serviceSubtaskCountReq.getOrgid()); |
| | | String followUpCountStyle = sysConfigService.selectConfigByKey("followUpCountStyle", serviceSubtaskCountReq.getOrgid()); |
| | | if (ObjectUtils.isNotEmpty(followUpCountStyle)) { |
| | | serviceSubtaskCountReq.setFollowUpCountStyle(followUpCountStyle); |
| | | } else { |
| | |
| | | Integer offset = PageUtils.getOffset(serviceSubtaskCountReq.getPageNum(), serviceSubtaskCountReq.getPageSize()); |
| | | serviceSubtaskCountReq.setPageNum(offset); |
| | | |
| | | String followUpCountStyle = taskSysConfigPort.selectConfigValue("followUpCountStyle", serviceSubtaskCountReq.getOrgid()); |
| | | String followUpCountStyle = sysConfigService.selectConfigByKey("followUpCountStyle", serviceSubtaskCountReq.getOrgid()); |
| | | if (ObjectUtils.isNotEmpty(followUpCountStyle)) { |
| | | serviceSubtaskCountReq.setFollowUpCountStyle(followUpCountStyle); |
| | | } else { |
| | |
| | | String orgid = loginUser.getUser().getOrgid(); |
| | | String configKey = serviceSubtaskCountReq.getConfigKey(); |
| | | if (StringUtils.isNotEmpty(configKey)) { |
| | | String configValue = taskSysConfigPort.selectConfigValue(configKey, orgid); |
| | | String configValue = sysConfigService.selectConfigByKey(configKey, orgid); |
| | | serviceSubtaskCountReq.setConfigValue(configValue); |
| | | if (StringUtils.isEmpty(configValue)) { |
| | | String logInfo = "getSfStatisticsCount-参数 " + configKey + " 未配置, 请配置好后重试"; |
| | |
| | | } |
| | | } |
| | | |
| | | String followUpCountStyle = taskSysConfigPort.selectConfigValue("followUpCountStyle", orgid); |
| | | String followUpCountStyle = sysConfigService.selectConfigByKey("followUpCountStyle", orgid); |
| | | if (ObjectUtils.isNotEmpty(followUpCountStyle)) { |
| | | serviceSubtaskCountReq.setFollowUpCountStyle(followUpCountStyle); |
| | | } else { |
| | |
| | | } |
| | | String configKey = serviceSubtaskCountReq.getConfigKey(); |
| | | if (StringUtils.isNotEmpty(configKey)) { |
| | | String configValue = taskSysConfigPort.selectConfigValue(configKey, serviceSubtaskCountReq.getOrgid()); |
| | | String configValue = sysConfigService.selectConfigByKey(configKey, serviceSubtaskCountReq.getOrgid()); |
| | | serviceSubtaskCountReq.setConfigValue(configValue); |
| | | if (StringUtils.isEmpty(configValue)) { |
| | | String logInfo = "getSfStatisticsCount-参数 " + configKey + " 未配置, 请配置好后重试"; |
| | |
| | | @AddOrgId(field = "orgid", paramIndex = 0, campusField = "campusid") |
| | | @PostMapping("/getSfStatisticsCountDetails") |
| | | public AjaxResult getSfStatisticsCountDetails(@RequestBody ServiceSubtaskCountReq serviceSubtaskCountReq) { |
| | | if (serviceSubtaskCountReq.getLeavehospitaldistrictcodes().size() == 0 && serviceSubtaskCountReq.getDeptcodes().size() == 0) { |
| | | boolean noDeptOrDistrict = CollectionUtils.isEmpty(serviceSubtaskCountReq.getLeavehospitaldistrictcodes()) |
| | | && CollectionUtils.isEmpty(serviceSubtaskCountReq.getDeptcodes()) |
| | | && CollectionUtils.isEmpty(serviceSubtaskCountReq.getLeaveldeptcodes()) |
| | | && CollectionUtils.isEmpty(serviceSubtaskCountReq.getHospitaldeptcodes()) |
| | | && CollectionUtils.isEmpty(serviceSubtaskCountReq.getHospitaldistrictcodes()); |
| | | if (noDeptOrDistrict) { |
| | | return error("科室或病区不能为空"); |
| | | } |
| | | //复诊统计 |
| | | String configKey = serviceSubtaskCountReq.getConfigKey(); |
| | | if (StringUtils.isNotEmpty(configKey)) { |
| | | String configValue = taskSysConfigPort.selectConfigValue(configKey, serviceSubtaskCountReq.getOrgid()); |
| | | String configValue = sysConfigService.selectConfigByKey(configKey, serviceSubtaskCountReq.getOrgid()); |
| | | if (StringUtils.isEmpty(configValue)) { |
| | | String logInfo = "getSfStatisticsCountDetails-参数 " + configKey + " 未配置, 请配置好后重试"; |
| | | log.error(logInfo); |
| | |
| | | sysUserDept.setOrgid(sysUser.getOrgid()); |
| | | sysUserDept.setCampusid(sysUser.getCampusid()); |
| | | sysUserDept.setDeptType("1"); |
| | | List<SysUserDept> sysUserDepts = taskSysUserDeptPort.selectSysUserDeptList(sysUserDept); |
| | | List<SysUserDept> sysUserDepts = sysUserDeptService.selectSysUserDeptList(sysUserDept); |
| | | SysUserDept sysUserWard = new SysUserDept(); |
| | | sysUserWard.setUserId(sysUser.getUserId()); |
| | | sysUserWard.setOrgid(sysUser.getOrgid()); |
| | | sysUserWard.setCampusid(sysUser.getCampusid()); |
| | | sysUserWard.setDeptType("2"); |
| | | List<SysUserDept> sysUserWards = taskSysUserDeptPort.selectSysUserDeptList(sysUserWard); |
| | | List<SysUserDept> sysUserWards = sysUserDeptService.selectSysUserDeptList(sysUserWard); |
| | | List<String> deptCodes = sysUserDepts.stream().map(SysUserDept::getDeptCode).collect(Collectors.toList()); |
| | | List<String> wardCodes = sysUserWards.stream().map(SysUserDept::getDeptCode).collect(Collectors.toList()); |
| | | ServiceSubtaskEntity entity = new ServiceSubtaskEntity(); |
| | |
| | | } |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * 当前登录人待处理随访任务统计(按出院年月分组,出院随访、门诊随访分开计数) |
| | | * <p> |
| | | * 口径:service_subtask 中 |
| | | * service_type = '2' 出院随访 / '3' 门诊随访 |
| | | * + 待随访状态(sendstate in 1,2,3,5,7) |
| | | * + 出院满 7 天(含「7 天前那一天」出院的患者) |
| | | * + 只看最近 4 个出院月份(含当月); |
| | | * 科室/病区权限取 OR(与随访列表 deptOrDistrict=2 一致)。 |
| | | * |
| | | * @return { userName, nickName, total, months: [{ month: 'yyyy-MM', dischargeCount, outpatientCount }] } |
| | | * 只返回有数据的月份,没有数据的月份由前端补 0 |
| | | */ |
| | | @ApiOperation("获取当前登录人待处理随访任务统计(按出院年月)") |
| | | @PostMapping("/pendingTaskMonthStats") |
| | | public Map<String, Object> pendingTaskMonthStats() { |
| | | LoginUser loginUser = getLoginUser(); |
| | | SysUser sysUser = loginUser.getUser(); |
| | | Map<String, Object> result = new LinkedHashMap<>(); |
| | | result.put("userName", sysUser.getUserName()); |
| | | result.put("nickName", sysUser.getNickName()); |
| | | result.put("total", 0L); |
| | | result.put("months", new ArrayList<>()); |
| | | |
| | | // 注意:不要用 sys_user_dept.campusid 过滤——这张表的 campusid 大量为 NULL, |
| | | // 带上它会直接查不出权限,统计结果永远是 0。院区权限由 orgid + userId + deptType 已能定位。 |
| | | SysUserDept deptQuery = new SysUserDept(); |
| | | deptQuery.setUserId(sysUser.getUserId()); |
| | | deptQuery.setOrgid(sysUser.getOrgid()); |
| | | deptQuery.setDeptType("1"); |
| | | List<SysUserDept> sysUserDepts = sysUserDeptService.selectSysUserDeptList(deptQuery); |
| | | |
| | | SysUserDept wardQuery = new SysUserDept(); |
| | | wardQuery.setUserId(sysUser.getUserId()); |
| | | wardQuery.setOrgid(sysUser.getOrgid()); |
| | | wardQuery.setDeptType("2"); |
| | | List<SysUserDept> sysUserWards = sysUserDeptService.selectSysUserDeptList(wardQuery); |
| | | |
| | | boolean isAdmin = "admin".equals(sysUser.getUserName()); |
| | | if (!isAdmin && CollectionUtils.isEmpty(sysUserDepts) && CollectionUtils.isEmpty(sysUserWards)) { |
| | | // 既没有科室也没有病区权限时不统计,避免越权看到全机构数据 |
| | | return result; |
| | | } |
| | | |
| | | // sys_user_dept 里同一科室/病区会重复很多行,去重后再拼 IN,避免 SQL 参数过多 |
| | | List<String> deptCodes = sysUserDepts.stream() |
| | | .map(SysUserDept::getDeptCode) |
| | | .filter(Objects::nonNull) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | List<String> wardCodes = sysUserWards.stream() |
| | | .map(SysUserDept::getDeptCode) |
| | | .filter(Objects::nonNull) |
| | | .distinct() |
| | | .collect(Collectors.toList()); |
| | | |
| | | ServiceSubtaskEntity entity = new ServiceSubtaskEntity(); |
| | | entity.setOrgid(sysUser.getOrgid()); |
| | | entity.setLeaveldeptcodes(deptCodes); |
| | | entity.setLeavehospitaldistrictcodes(wardCodes); |
| | | |
| | | Map<String, Object> stats = serviceSubtaskService.getPendingManualTaskMonthStats(entity); |
| | | if (stats != null) { |
| | | result.putAll(stats); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | @ApiOperation("获取当前用户宣教数量统计") |
| | |
| | | serviceSubtaskEntity.setSendstates(new ArrayList<>(Arrays.asList(4L))); |
| | | } |
| | | if (ObjectUtils.isNotEmpty(userId)) { |
| | | long tRedis = System.currentTimeMillis(); |
| | | Map<String, Object> redisMap = redisCache.getCacheObject(userId + "patItemCount"); |
| | | log.info("[patItem耗时] 4.1 Redis取count缓存={}ms", System.currentTimeMillis() - tRedis); |
| | | Boolean redisFlag = false; |
| | | if (MapUtils.isNotEmpty(redisMap)) { |
| | | long tCmp = System.currentTimeMillis(); |
| | | ServiceSubtaskEntity oldCondition = (ServiceSubtaskEntity) redisMap.get("searchCondition"); |
| | | if (ObjectUtils.isNotEmpty(oldCondition) && isSameCondition(oldCondition, serviceSubtaskEntity)) { |
| | | redisFlag = true; |
| | | map = redisMap; |
| | | redisCache.setCacheObject(userId + "patItemCount", map, 60, TimeUnit.MINUTES); |
| | | } |
| | | log.info("[patItem耗时] 4.2 条件比对={}ms,命中={}", System.currentTimeMillis() - tCmp, redisFlag); |
| | | } |
| | | if (!redisFlag) { |
| | | long tCalc = System.currentTimeMillis(); |
| | | map = serviceSubtaskService.patItemCount(serviceSubtaskEntity); |
| | | log.info("[patItem耗时] 4.3 count聚合(未命中缓存,走库)={}ms", System.currentTimeMillis() - tCalc); |
| | | map.put("searchCondition", serviceSubtaskEntity); |
| | | redisCache.setCacheObject(userId + "patItemCount", map, 120, TimeUnit.MINUTES); |
| | | } |
| | | } else { |
| | | long tCalc = System.currentTimeMillis(); |
| | | map = serviceSubtaskService.patItemCount(serviceSubtaskEntity); |
| | | log.info("[patItem耗时] 4.3 count聚合(无登录人,走库)={}ms", System.currentTimeMillis() - tCalc); |
| | | } |
| | | return map; |
| | | } |