package com.smartor.service.impl;
|
|
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.google.gson.Gson;
|
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.http.HttpUtils;
|
import com.smartor.domain.Icd10;
|
import com.smartor.mapper.Icd10Mapper;
|
import com.smartor.service.IIcd10Service;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* 疾病Service业务层处理
|
*
|
* @author ruoyi
|
* @date 2023-12-21
|
*/
|
@Slf4j
|
@Service
|
public class Icd10ServiceImpl implements IIcd10Service {
|
|
@Autowired
|
private Icd10Mapper icd10Mapper;
|
|
@Value("${sltd_pub_path}")
|
private String sltdPubPath;
|
|
@Value("${lwl_app_key}")
|
private String APP_KEY;
|
|
/**
|
* 固定 orgId
|
*/
|
private static final long ORG_ID = 20001001L;
|
/**
|
* 每页拉取条数(接口最大允许 1000)
|
*/
|
private static final int PAGE_SIZE = 1000;
|
/**
|
* 批量写入单批最大条数
|
*/
|
private static final int BATCH_SIZE = 500;
|
|
/**
|
* 查询疾病
|
*
|
* @param icdid 疾病主键
|
* @return 疾病
|
*/
|
@Override
|
public Icd10 selectIcd10ByIcdid(Long icdid) {
|
return icd10Mapper.selectIcd10ByIcdid(icdid);
|
}
|
|
/**
|
* 查询疾病列表
|
*
|
* @param icd10 疾病
|
* @return 疾病
|
*/
|
@Override
|
public List<Icd10> selectIcd10List(Icd10 icd10) {
|
return icd10Mapper.selectIcd10List(icd10);
|
}
|
|
/**
|
* 新增疾病
|
*
|
* @param icd10 疾病
|
* @return 结果
|
*/
|
@Override
|
public int insertIcd10(Icd10 icd10) {
|
icd10.setCreateTime(DateUtils.getNowDate());
|
return icd10Mapper.insertIcd10(icd10);
|
}
|
|
/**
|
* 修改疾病
|
*
|
* @param icd10 疾病
|
* @return 结果
|
*/
|
@Override
|
public int updateIcd10(Icd10 icd10) {
|
icd10.setUpdateTime(DateUtils.getNowDate());
|
return icd10Mapper.updateIcd10(icd10);
|
}
|
|
/**
|
* 批量删除疾病
|
*
|
* @param icdids 需要删除的疾病主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteIcd10ByIcdids(Long[] icdids) {
|
return icd10Mapper.deleteIcd10ByIcdids(icdids);
|
}
|
|
/**
|
* 删除疾病信息
|
*
|
* @param icdid 疾病主键
|
* @return 结果
|
*/
|
@Override
|
public int deleteIcd10ByIcdid(Long icdid) {
|
return icd10Mapper.deleteIcd10ByIcdid(icdid);
|
}
|
|
/**
|
* 从远程接口(来未来)分页拉取并增量写入 icd10 表。
|
* <p>
|
* 优化要点:
|
* 1. 每页最大拉取 1000 条,减少请求次数。
|
* 2. 每页把当前页所有 icdcode 用一条 IN SQL 一次批量查库,避免循环 N 次单条查询。
|
* 3. 将不存在的记录收集后分批(每批 500 条)批量插入。
|
* </p>
|
*
|
* @return 本次运行新增总条数
|
*/
|
@Override
|
public int queryAddIcd10() {
|
int totalInserted = 0;
|
long current = 1;
|
long totalPages = 1; // 首次循环前先执行一次
|
|
log.info("[开始] 从来未来拉取 ICD10 增量数据,orgId={}", ORG_ID);
|
|
do {
|
// 构建请求体
|
Map<String, Object> requestBody = new HashMap<>();
|
requestBody.put("orgId", ORG_ID);
|
requestBody.put("searchText", "");
|
requestBody.put("size", PAGE_SIZE);
|
requestBody.put("current", current);
|
|
String responseStr;
|
try {
|
Map<String, String> headers = buildRequestHeaders();
|
responseStr = HttpUtils.sendPostByHeader(sltdPubPath + "/hbos-thirdparty-integration/standard/base/dtc/pageDiagnosisDict", new Gson().toJson(requestBody), headers);
|
|
} catch (Exception e) {
|
log.error("[第{}页] 请求来未来接口失败", current, e);
|
break;
|
}
|
|
if (responseStr == null || responseStr.isEmpty()) {
|
log.warn("[第{}页] 接口返回空,停止采集", current);
|
break;
|
}
|
|
JSONObject resp = JSON.parseObject(responseStr);
|
if (resp == null || !Boolean.TRUE.equals(resp.getBoolean("success"))) {
|
log.error("[第{}页] 接口返回失败:{}", current, responseStr);
|
break;
|
}
|
|
JSONObject data = resp.getJSONObject("data");
|
if (data == null) {
|
break;
|
}
|
|
// 计算总页数
|
long total = data.getLongValue("total");
|
long pageSize = data.getLongValue("size");
|
if (pageSize <= 0) {
|
break;
|
}
|
totalPages = (total + pageSize - 1) / pageSize;
|
|
JSONArray records = data.getJSONArray("records");
|
if (records == null || records.isEmpty()) {
|
break;
|
}
|
|
log.info("[第{}/{}页] 获取 {} 条记录,总{}条", current, totalPages, records.size(), total);
|
|
// 解析当前页数据
|
List<String> pageNames = new ArrayList<>();
|
List<Icd10> pageList = new ArrayList<>();
|
for (int i = 0; i < records.size(); i++) {
|
JSONObject rec = records.getJSONObject(i);
|
String icdCode = rec.getString("icdCode");
|
if (icdCode == null || icdCode.isEmpty()) {
|
continue;
|
}
|
String icdName = StringUtils.isEmpty(rec.getString("name")) ? null : rec.getString("name").trim();
|
if (icdName == null || icdName.isEmpty()) {
|
continue;
|
}
|
pageNames.add(icdName);
|
|
Icd10 icd10 = new Icd10();
|
icd10.setIcdcode(icdCode);
|
icd10.setIcdname(icdName);
|
icd10.setIcdpym(rec.getString("pinyin"));
|
icd10.setHisIcdid(rec.getString("his_icdid"));
|
icd10.setOrgid(String.valueOf(ORG_ID));
|
icd10.setDelFlag("0");
|
icd10.setCreateTime(DateUtils.getNowDate());
|
pageList.add(icd10);
|
}
|
|
if (pageNames.isEmpty()) {
|
current++;
|
continue;
|
}
|
|
// 一次 IN 查库,获取已存在的 icdname(核心去重优化点)南华附一的icdname不会重复,icd10code会重复
|
Set<String> existingNames = new HashSet<>(icd10Mapper.selectExistingIcdcodes(pageNames));
|
|
// 过滤出不存在的记录
|
List<Icd10> newList = pageList.stream().filter(item -> !existingNames.contains(item.getIcdname())).collect(Collectors.toList());
|
|
log.info("[第{}/{}页] 当前页共 {} 条,已存在 {} 条,需新入库 {} 条", current, totalPages, pageList.size(), existingNames.size(), newList.size());
|
|
// 分批批量插入
|
int inserted = batchInsert(newList);
|
totalInserted += inserted;
|
|
current++;
|
} while (current <= totalPages);
|
|
log.info("[完成] ICD10 增量采集结束,本次共新增 {} 条", totalInserted);
|
return totalInserted;
|
}
|
|
/**
|
* 分批批量插入,每批最大 BATCH_SIZE 条
|
*/
|
private int batchInsert(List<Icd10> list) {
|
if (list == null || list.isEmpty()) {
|
return 0;
|
}
|
int total = 0;
|
int size = list.size();
|
for (int start = 0; start < size; start += BATCH_SIZE) {
|
int end = Math.min(start + BATCH_SIZE, size);
|
total += icd10Mapper.batchIcd10(list.subList(start, end));
|
}
|
return total;
|
}
|
|
private Map<String, String> buildRequestHeaders() {
|
Map<String, String> headers = new HashMap<>();
|
headers.put("Content-Type", "application/json");
|
headers.put("app-key", APP_KEY);
|
return headers;
|
}
|
}
|