feat: 佛山三院首页编目队列生成

master
wyb 10 months ago
parent 6ae6691a91
commit 166a62ed1f

@ -0,0 +1,7 @@
{
"lastDate": "2024-08-13 00:00:00",
"jobIntervalSeconds": 300,
"sysCodes":"catalog",
"open": 1,
"where":"AND CYRQ >=TO_DATE('2024-07-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') "
}

@ -0,0 +1,162 @@
package com.docus.server.archivemysql.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author jiashi
* @since 2021-04-14
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "TBasic对象", description = "病案基本信息")
public class TBasic implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "病案主键")
private String patientId;
@ApiModelProperty(value = "住院次数")
private Integer admissTimes;
@ApiModelProperty(value = "病案号")
private String inpatientNo;
@ApiModelProperty(value = "住院ID号")
private String admissId;
@ApiModelProperty(value = "患者姓名")
private String name;
@ApiModelProperty(value = "盘号")
private String ph;
@ApiModelProperty(value = "性别")
private String sex;
@ApiModelProperty(value = "年龄_岁")
private Integer age;
@ApiModelProperty(value = "年龄_月")
private Integer ageMonth;
@ApiModelProperty(value = "年龄_天")
private Integer ageDay;
@ApiModelProperty(value = "身份证")
private String idCard;
@ApiModelProperty(value = "手机号码")
private String telphone;
@ApiModelProperty(value = "住院日期")
private Date admissDate;
@ApiModelProperty(value = "住院科室")
private String admissDept;
@ApiModelProperty(value = "住院科室名称")
private String admissDeptName;
@ApiModelProperty(value = "出院日期")
private Date disDate;
@ApiModelProperty(value = "出院科室")
private String disDept;
@ApiModelProperty(value = "出院科室名称")
private String disDeptName;
@ApiModelProperty(value = "实际住院天数")
private Integer admissDays;
@ApiModelProperty(value = "主管医生")
private String attending;
@ApiModelProperty(value = "主管医生名称")
private String attendingName;
@ApiModelProperty(value = "主要诊断编码")
private String mainDiagCode;
@ApiModelProperty(value = "主要诊断名称")
private String mainDiagName;
@ApiModelProperty(value = "主要手术编码")
private String mainOperateCode;
@ApiModelProperty(value = "主要手术名称")
private String mainOperateName;
@ApiModelProperty(value = "是否死亡")
private Integer isDead;
@ApiModelProperty(value = "是否作废(01是)")
private Integer isCancel;
@ApiModelProperty(value = "创建时间")
private Date createTime;
@ApiModelProperty(value = "修改时间")
private Date updateTime;
@ApiModelProperty(value = "是否归档 1已归档0未归档")
private Integer isArchive;
@ApiModelProperty(value = "归档时间")
private Date archiveTime;
@ApiModelProperty(value = "文件来源 1:af_archive_detail,2:t_scan_assort")
private Integer fileSource;
@ApiModelProperty(value = "完整性描述")
private String integrityDesc;
private String bColumn1;
private String bColumn2;
private String bColumn3;
private String bColumn4;
private String bColumn5;
private Integer bColumn6;
private Integer bColumn7;
private Integer bColumn8;
private Integer bColumn9;
private Integer bColumn10;
@ApiModelProperty(value = "姓名缩写(内部构成)")
private String nameSpell;
@ApiModelProperty(value = "性别名称")
private String sexName;
@ApiModelProperty(value = "记账号")
private String jzh;
@ApiModelProperty(value = "外部id")
private String externalId;
@ApiModelProperty(value = "档案文件存储类型1pdf默认2图片")
private Integer archiveFileStorageType;
@ApiModelProperty(value = "是否标记编码 0否1是")
private Integer is_coder;
}

@ -0,0 +1,23 @@
package com.docus.server.archivemysql.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.docus.server.archivemysql.entity.TBasic;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* mapper
*
* @author wyb
*/
@DS("archive-mysql")
public interface TBasicMapper {
/**
*
*
* @param jzhList
* @return
*/
List<TBasic> findTbasicByJzhs(@Param("jzhList") List<String> jzhList);
}

@ -0,0 +1,34 @@
package com.docus.server.fssyjhemr.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
*
*
* @author YongBin Wen
* @date 2024/9/13 14:52
*/
@ApiModel("佛山三院嘉时无纸化编目状态电子病历视图")
@Data
public class FsSyJswzhBmztEmrView {
@ApiModelProperty("记账号,和归档匹配")
private String jzh;
@ApiModelProperty("住院号")
private String zyh;
private String kh;
@ApiModelProperty("住院次数")
private Integer zycs;
private String bmr;
private String bmgh;
@ApiModelProperty("入院时间")
private Date ryrq;
@ApiModelProperty("出院时间")
private Date cyrq;
@ApiModelProperty("编目时间")
private Date bmsj;
}

@ -0,0 +1,32 @@
package com.docus.server.fssyjhemr.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.docus.server.fssyjhemr.entity.FsSyJswzhBmztEmrView;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
/**
* @author YongBin Wen
* @date 2024/8/13 16:13
*/
@DS("fssy-jhemr-oracle")
public interface FsSyJswzhBmztEmrViewMapper {
/**
*
*
* @return java.util.Date
*/
Date maxBmsj();
/**
* startDate <= catalog_date < endDate
*
* @param startDate yyyy-MM-dd HH:mm:ss
* @param endDate yyyy-MM-dd HH:mm:ss
* @param where
* @return
*/
List<FsSyJswzhBmztEmrView> listByBmsjRange(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("where")String where);
}

@ -1,8 +1,11 @@
package com.docus.server.jobadmin.config;
import com.docus.server.archivemysql.mapper.TBasicMapper;
import com.docus.server.archivesqlserver.mapper.ArchiveMasterMapper;
import com.docus.server.fssyjhemr.mapper.FsSyJswzhBmztEmrViewMapper;
import com.docus.server.jobadmin.scheduler.JobScheduler;
import com.docus.server.rpc.V2ViewTaskCollectService;
import com.docus.server.rpc.V3ViewTaskCollectService;
import com.docus.server.zjfsjhemr.mapper.ZjFsPatIndexViewMapper;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
@ -53,6 +56,18 @@ public class JobAdminConfig implements InitializingBean, DisposableBean {
@Resource
private V2ViewTaskCollectService v2ViewTaskCollectService;
@Resource
private FsSyJswzhBmztEmrViewMapper fsSyJswzhBmztEmrViewMapper;
@Resource
private TBasicMapper tBasicMapper;
@Resource
private V3ViewTaskCollectService v3ViewTaskCollectService;
public ZjFsPatIndexViewMapper getZjFsPatIndexViewMapper() {
return zjFsPatIndexViewMapper;
}
@ -64,4 +79,16 @@ public class JobAdminConfig implements InitializingBean, DisposableBean {
public V2ViewTaskCollectService getV2ViewTaskCollectService() {
return v2ViewTaskCollectService;
}
public FsSyJswzhBmztEmrViewMapper getFsSyJswzhBmztEmrViewMapper() {
return fsSyJswzhBmztEmrViewMapper;
}
public TBasicMapper gettBasicMapper() {
return tBasicMapper;
}
public V3ViewTaskCollectService getV3ViewTaskCollectService() {
return v3ViewTaskCollectService;
}
}

@ -1,5 +1,6 @@
package com.docus.server.jobadmin.scheduler;
import com.docus.server.jobadmin.thread.FsSyCatalogCollectTaskHelper;
import com.docus.server.jobadmin.thread.ZjFsCatalogCollectTaskHelper;
import com.docus.server.jobadmin.thread.ZjFsCostListCollectTaskHelper;
import org.slf4j.Logger;
@ -17,7 +18,7 @@ public class JobScheduler {
public void init() throws Exception {
ZjFsCatalogCollectTaskHelper.getInstance().start();
ZjFsCostListCollectTaskHelper.getInstance().start();
FsSyCatalogCollectTaskHelper.getInstance().start();
logger.info(">>>>>>>>> init job admin success.");
}
@ -25,5 +26,6 @@ public class JobScheduler {
public void destroy() {
ZjFsCatalogCollectTaskHelper.getInstance().toStop();
ZjFsCostListCollectTaskHelper.getInstance().toStop();
FsSyCatalogCollectTaskHelper.getInstance().toStop();
}
}

@ -0,0 +1,131 @@
package com.docus.server.jobadmin.thread;
import com.alibaba.fastjson.JSONObject;
import com.docus.core.util.Func;
import com.docus.infrastructure.core.utils.TableJsonRead;
import com.docus.infrastructure.web.api.CommonResult;
import com.docus.server.archivemysql.entity.TBasic;
import com.docus.server.archivemysql.mapper.TBasicMapper;
import com.docus.server.fssyjhemr.entity.FsSyJswzhBmztEmrView;
import com.docus.server.fssyjhemr.mapper.FsSyJswzhBmztEmrViewMapper;
import com.docus.server.jobadmin.config.JobAdminConfig;
import com.docus.server.rpc.V3ViewTaskCollectService;
import com.docus.server.rpc.dto.CompensateTaskDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* job
*
* @author YongBin Wen
* @date 2024/1/23 10:59
*/
public class FsSyCatalogCollectTaskHelper {
private static final Logger logger = LoggerFactory.getLogger(FsSyCatalogCollectTaskHelper.class);
private static final FsSyCatalogCollectTaskHelper instance = new FsSyCatalogCollectTaskHelper();
public static FsSyCatalogCollectTaskHelper getInstance() {
return instance;
}
private Thread fsSyCatalogCollectTaskThread;
private volatile boolean toStop = false;
public void start() {
fsSyCatalogCollectTaskThread = new Thread(() -> {
TableJsonRead tableJsonRead = new TableJsonRead();
FsSyJswzhBmztEmrViewMapper fsSyJswzhBmztEmrViewMapper = JobAdminConfig.getJobAdminConfig().getFsSyJswzhBmztEmrViewMapper();
TBasicMapper tBasicMapper = JobAdminConfig.getJobAdminConfig().gettBasicMapper();
V3ViewTaskCollectService v3ViewTaskCollectService = JobAdminConfig.getJobAdminConfig().getV3ViewTaskCollectService();
String configPath = "data-config\\jobconfig";
String configFileName = "FsSyCatalogCollectTask";
while (!toStop) {
try {
// 读取配置,实时观察配置文件状况
JSONObject jobConfig = tableJsonRead.Read(configPath, configFileName, JSONObject.class);
int jobIntervalSeconds = jobConfig.getIntValue("jobIntervalSeconds");
String lastDate = jobConfig.getString("lastDate");
String sysCodes = jobConfig.getString("sysCodes");
String where = jobConfig.getString("where");
if (where == null) {
where = "";
}
int open = jobConfig.getIntValue("open");
if (open == 0) {
TimeUnit.SECONDS.sleep(60);
continue;
}
Date maxBmsj = fsSyJswzhBmztEmrViewMapper.maxBmsj();
String maxBmsjStr = Func.formatDateTime(maxBmsj);
// 查询视图数据视图数据查询患者信息id进行任务生成
List<FsSyJswzhBmztEmrView> fsSyJswzhBmztEmrViews = fsSyJswzhBmztEmrViewMapper.listByBmsjRange(lastDate, maxBmsjStr, where);
if (Func.isNotEmpty(fsSyJswzhBmztEmrViews)) {
logger.info("首页编目数据查询,根据最后编目时间查询(不包含截止时间),开始时间:{},截止时间:{},额外条件:{},视图数据:{} 条,数据为:{}", lastDate, maxBmsjStr, where, fsSyJswzhBmztEmrViews.size(), Func.toJson(fsSyJswzhBmztEmrViews));
for (FsSyJswzhBmztEmrView view : fsSyJswzhBmztEmrViews) {
String jzh = view.getJzh();
List<TBasic> tbasic = tBasicMapper.findTbasicByJzhs(Collections.singletonList(jzh));
if (Func.isEmpty(tbasic)) {
logger.warn("首页编目数据查询,记账号:{} 未找到患者主表数据!", jzh);
continue;
}
// 生成采集任务
List<String> patientIds = tbasic.stream().map(TBasic::getPatientId).collect(Collectors.toList());
CompensateTaskDTO compensateTaskDTO = new CompensateTaskDTO();
compensateTaskDTO.setPatientIds(patientIds);
compensateTaskDTO.setCollectorIds(Arrays.asList(sysCodes.split(",")));
compensateTaskDTO.setPriority(3);
logger.info("首页编目生成队列参数:{}", Func.toJson(compensateTaskDTO));
CommonResult<String> result = v3ViewTaskCollectService.compensateTask(compensateTaskDTO);
logger.info("首页编目生成队列返回结果:{}", Func.toJson(result));
}
// 刷新配置
jobConfig.put("lastDate", maxBmsjStr);
tableJsonRead.Save(configPath, configFileName, jobConfig.toJSONString());
}
TimeUnit.SECONDS.sleep(jobIntervalSeconds);
} catch (Exception ex) {
if (!toStop) {
logger.error(">>>>>>>>>>> fsSy Catalog CollectTask Thread error:" + ex.getMessage(), ex);
try {
TimeUnit.SECONDS.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
logger.info(">>>>>>>>>>> fsSy Catalog CollectTask Thread stop");
});
fsSyCatalogCollectTaskThread.setDaemon(true);
fsSyCatalogCollectTaskThread.setName("fsSyCatalogCollectTaskHelper");
fsSyCatalogCollectTaskThread.start();
}
public void toStop() {
toStop = false;
fsSyCatalogCollectTaskThread.interrupt();
try {
fsSyCatalogCollectTaskThread.join();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
public static void main(String[] args) {
TableJsonRead tableJsonRead = new TableJsonRead();
JSONObject config = tableJsonRead.Read("data-config\\jobconfig", "fsSyCatalogCollectTask", JSONObject.class);
System.out.println(config);
}
}

@ -0,0 +1,18 @@
package com.docus.server.rpc;
import com.docus.infrastructure.web.api.CommonResult;
import com.docus.server.rpc.dto.CompensateTaskDTO;
/**
* @author YongBin Wen
* @date 2024/8/13 17:40
*/
public interface V3ViewTaskCollectService {
/**
*
*
* @param dto
* @return
*/
CommonResult<String> compensateTask(CompensateTaskDTO dto);
}

@ -0,0 +1,33 @@
package com.docus.server.rpc.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
*
*
* @author wyb
*/
@Data
@ApiModel("任务补偿下发参数")
public class CompensateTaskDTO {
/**
*
*/
@ApiModelProperty(value = "病案主键",required = true)
private List<String> patientIds;
/**
*
*/
@ApiModelProperty(value = "采集器id",required = true)
private List<String> collectorIds;
/**
*
*/
@ApiModelProperty(value = "队列优先级",required = true)
private Integer priority;
}

@ -0,0 +1,34 @@
package com.docus.server.rpc.impl;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.docus.core.util.Func;
import com.docus.infrastructure.web.api.CommonResult;
import com.docus.server.rpc.V3ViewTaskCollectService;
import com.docus.server.rpc.dto.CompensateTaskDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* @author YongBin Wen
* @date 2024/8/13 17:41
*/
@Service
@Slf4j
public class V3ViewTaskCollectServiceImpl implements V3ViewTaskCollectService {
@Value("${docus.url.viewtask-v3:}")
private String v3ViewTaskServerUrl;
@Override
public CommonResult<String> compensateTask(CompensateTaskDTO dto) {
String uri = "api/NoViewCollect/compensateTask";
String url = v3ViewTaskServerUrl + uri;
String body = Func.toJson(dto);
log.info("3.0任务生成,地址:{},参数:{}", url, body);
String result = HttpUtil.post(url, body);
return JSONObject.parseObject(result, new TypeReference<CommonResult<String>>() {
});
}
}

@ -8,10 +8,10 @@ spring:
active: test
datasource:
dynamic:
primary: master #设置默认的数据源默认值为master
primary: archive-mysql #设置默认的数据源默认值为archive-mysql
strict: false #是否用严格模式,如果启用在味匹配到指定数据源时抛出异常
datasource:
master:
archive-mysql:
url: jdbc:log4jdbc:mysql://db.docus.cn:3306/docus_medicalrecord?autoReconnect=true&allowMultiQueries=true&useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: docus
password: docus702
@ -77,6 +77,28 @@ spring:
test-on-borrow: false
test-on-return: false
validation-query: select 1
fssy-jhemr-oracle:
url: jdbc:oracle:thin:@//10.100.23.128:31521/jhemr
username: BAWZH
password: BAWZH@123
driver-class-name: oracle.jdbc.driver.OracleDriver
type: com.alibaba.druid.pool.DruidDataSource
# 初始化配置
initial-size: 3
# 最小连接数
min-idle: 3
# 最大连接数
max-active: 5
# 获取连接超 时时间
max-wait: 5000
# 连接有效性检测时间
time-between-eviction-runs-millis: 90000
# 最大空闲时间
min-evictable-idle-time-millis: 1800000
test-while-idle: true
test-on-borrow: false
test-on-return: false
validation-query: select 1 from dual
redis:
host: redis.docus.cn
password: JSdocus@702
@ -85,6 +107,8 @@ docus:
url:
# 2.0视图采集服务地址
viewtask-v2: http://localhost:9295/
# 3.0视图采集服务地址
viewtask-v3: http://localhost:9295/
dbtype: mysql

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.docus.server.fssyjhemr.mapper.FsSyJswzhBmztEmrViewMapper">
<select id="listByBmsjRange" resultType="com.docus.server.fssyjhemr.entity.FsSyJswzhBmztEmrView">
select jzh,zyh,zycs,kh,bmr,bmgh,ryrq,cyrq,bmsj
from jhemr.v_jswzh_bmzt_emr
where bmsj >= TO_DATE(#{startDate}, 'yyyy-mm-dd hh24:mi:ss')
and bmsj <![CDATA[<]]> TO_DATE(#{endDate}, 'yyyy-mm-dd hh24:mi:ss')
${where}
order by bmsj
</select>
<select id="maxBmsj" resultType="java.util.Date">
select max(bmsj) from jhemr.v_jswzh_bmzt_emr
</select>
</mapper>

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.docus.server.archivemysql.mapper.TBasicMapper">
<sql id="basicInfoColumns">
patient_id as patientId,
admiss_times as admissTimes,
inpatient_no as inpatientNo,
admiss_id as admissId,
admiss_date as admissDate,
dis_date as disDate,
admiss_dept_name as admissDeptName,
dis_dept_name as disDeptName ,
jzh,
name,
emp_id as empId
</sql>
<select id="findTbasicByJzhs" resultType="com.docus.server.archivemysql.entity.TBasic">
select
<include refid="basicInfoColumns"></include>
from
docus_medicalrecord.t_basic
where
jzh in
<foreach collection="jzhList" item="jzh" separator="," open="(" close=")">
#{jzh}
</foreach>
</select>
</mapper>
Loading…
Cancel
Save