提交merge1.3
This commit is contained in:
@@ -17,7 +17,6 @@ public interface IDocDefinitionAppService {
|
||||
*/
|
||||
R<?> addDefinition(DocDefinitionDto definitionDto);
|
||||
|
||||
|
||||
/**
|
||||
* 修改文书定义
|
||||
*
|
||||
@@ -39,4 +38,12 @@ public interface IDocDefinitionAppService {
|
||||
R<?> getDefinitionDetailById(Long id);
|
||||
|
||||
DocDefinitionDto getDefinitionById(Long id);
|
||||
|
||||
/**
|
||||
* 获取文书ID
|
||||
*
|
||||
* @param menuEnum 来源类型
|
||||
* @return 文书列表
|
||||
*/
|
||||
R<?> getDefinitionId(Integer menuEnum);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
package com.openhis.web.document.appservice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.web.document.dto.DocRecordDto;
|
||||
import com.openhis.web.document.dto.DocRecordPatientQueryParam;
|
||||
import com.openhis.web.document.dto.DocRecordQueryParam;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文书记录 应用Service
|
||||
*/
|
||||
public interface IDocRecordAppService {
|
||||
|
||||
// /**
|
||||
// * 新增记录
|
||||
// *
|
||||
// * @param docRecordDto 文书记录信息
|
||||
// * @return
|
||||
// */
|
||||
// R<?> createOrEditRecord(DocRecordDto docRecordDto);
|
||||
// /**
|
||||
// * 新增记录
|
||||
// *
|
||||
// * @param docRecordDto 文书记录信息
|
||||
// * @return
|
||||
// */
|
||||
// R<?> createOrEditRecord(DocRecordDto docRecordDto);
|
||||
R<?> addRecord(DocRecordDto docRecordDto);
|
||||
|
||||
R<?> updateRecord(DocRecordDto docRecordDto);
|
||||
@@ -28,9 +28,11 @@ public interface IDocRecordAppService {
|
||||
/**
|
||||
* 根据患者ID或就诊ID获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理
|
||||
*/
|
||||
R<?> getRecordByEncounterIdList(DocRecordQueryParam docRecordQueryParam, Integer isPage, Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request);
|
||||
R<?> getRecordByEncounterIdList(DocRecordQueryParam docRecordQueryParam, Integer isPage, Integer pageNo,
|
||||
Integer pageSize, String searchKey, HttpServletRequest request);
|
||||
|
||||
R<?> getRecordPageList(DocRecordPatientQueryParam docRecordPatientQueryParam, List<Integer> primaryMenuEnumList, Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request);
|
||||
R<?> getRecordPageList(DocRecordPatientQueryParam docRecordPatientQueryParam, List<Integer> primaryMenuEnumList,
|
||||
Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 根据文书记录ID获取文书记录信息
|
||||
@@ -50,4 +52,47 @@ public interface IDocRecordAppService {
|
||||
* @return
|
||||
*/
|
||||
R<?> deleteRecord(List<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据患者ID或就诊ID以及时间获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理 需返回患者具体信息的列表,请使用getPatientRecordList
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @param recordTime 时间
|
||||
* @return R
|
||||
*/
|
||||
R<?> getRecordByEncounterIdAndTimeList(DocRecordQueryParam docRecordQueryParam, String recordTime);
|
||||
|
||||
/**
|
||||
* 根据文书记录ID打印文书记录
|
||||
*
|
||||
* @param recordId 文书记录ID
|
||||
* @return R
|
||||
*/
|
||||
R<?> recordPrint(Long recordId);
|
||||
|
||||
/**
|
||||
* 新增或编辑记录
|
||||
*
|
||||
* @param docRecordDto 文书记录信息
|
||||
* @return R
|
||||
*/
|
||||
R<?> saveOrUpdateRecord(DocRecordDto docRecordDto);
|
||||
|
||||
/**
|
||||
* 根据病历ID、病人ID和温度单ID获取温度单信息
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @return 温度单信息
|
||||
*/
|
||||
R<?> temperatureChart(DocRecordQueryParam docRecordQueryParam);
|
||||
|
||||
/**
|
||||
* 护理记录总结
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 护理记录总结
|
||||
*/
|
||||
R<?> summaryNursingRecords(DocRecordQueryParam docRecordQueryParam, String startTime, String endTime);
|
||||
}
|
||||
@@ -1,20 +1,18 @@
|
||||
package com.openhis.web.document.appservice;
|
||||
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.document.domain.DocStatistics;
|
||||
import com.openhis.web.document.dto.DocRecordQueryParam;
|
||||
import com.openhis.web.document.dto.DocStatisticsDto;
|
||||
import com.openhis.web.document.dto.DocStatisticsQueryParam;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.web.document.dto.DocStatisticsDto;
|
||||
import com.openhis.web.document.dto.DocStatisticsQueryParam;
|
||||
|
||||
/**
|
||||
* 文档模板 业务接口
|
||||
*/
|
||||
public interface IDocStatisticsAppService {
|
||||
|
||||
|
||||
public R<?> createOrUpdte(List<DocStatisticsDto> docStatisticsList);
|
||||
|
||||
public R<?> delete(List<Long> ids);
|
||||
@@ -23,6 +21,23 @@ public interface IDocStatisticsAppService {
|
||||
|
||||
public R<?> queryByEncounterId(Long encounterId);
|
||||
|
||||
R<?> getStatisticsList(DocStatisticsQueryParam queryParam, Integer isPage, Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request);
|
||||
R<?> getStatisticsList(DocStatisticsQueryParam queryParam, Integer isPage, Integer pageNo, Integer pageSize,
|
||||
String searchKey, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 根据病人ID和病例ID获取温度单信息
|
||||
*
|
||||
* @param encounterId 病例ID
|
||||
* @param patientId 病人ID
|
||||
* @param tempId 体温单ID
|
||||
* @return 体温单信息
|
||||
*/
|
||||
List<DocStatisticsDto> getStatisticsListByEncounterIdAndPatientId(Long encounterId, Long patientId, Long tempId);
|
||||
|
||||
/**
|
||||
* 保存/更新入院体征
|
||||
*
|
||||
* @param docStatisticsDtoList 入院体征list
|
||||
*/
|
||||
void saveOrUpdateAdmissionSigns(List<DocStatisticsDto> docStatisticsDtoList);
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
package com.openhis.web.document.appservice.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.core.common.utils.AssignSeqUtil;
|
||||
@@ -14,18 +22,13 @@ import com.openhis.document.service.IDocDefinitionService;
|
||||
import com.openhis.web.document.appservice.IDocDefinitionAppService;
|
||||
import com.openhis.web.document.appservice.IDocDefinitionOrganizationAppService;
|
||||
import com.openhis.web.document.dto.DirectoryNode;
|
||||
import com.openhis.web.document.dto.DocDefinitionOrganizationDto;
|
||||
import com.openhis.web.document.dto.DocDefinitionDto;
|
||||
import com.openhis.web.document.dto.DocDefinitionOrganizationDto;
|
||||
import com.openhis.web.document.dto.DocDefinitonParam;
|
||||
import com.openhis.web.document.mapper.DocDefinitionAppMapper;
|
||||
import com.openhis.web.document.util.DocumentDirectoryProcessor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -39,7 +42,6 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
@Resource
|
||||
private DocDefinitionAppMapper docDefinitionAppMapper;
|
||||
|
||||
|
||||
@Autowired(required = false)
|
||||
private AssignSeqUtil assignSeqUtil;
|
||||
|
||||
@@ -58,18 +60,18 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
if (definitionDto.getVueRouter() == null || definitionDto.getVueRouter().trim().isEmpty()) {
|
||||
return R.fail("新增文书定义失败:文书路由不能为空(或不能为空白字符)");
|
||||
}
|
||||
if (definitionDto.getUseRangeEnum() != null && DocUseRangeEnum.DEPT_USE.getValue().equals(definitionDto.getUseRangeEnum()) && definitionDto.getOrganizationIds() == null) {
|
||||
if (definitionDto.getUseRangeEnum() != null
|
||||
&& DocUseRangeEnum.DEPT_USE.getValue().equals(definitionDto.getUseRangeEnum())
|
||||
&& definitionDto.getOrganizationIds() == null) {
|
||||
return R.fail("新增文书定义失败:科室分配时,科室不能为空");
|
||||
}
|
||||
|
||||
// 2. 校验"名称+版本号"唯一性(避免重复创建)
|
||||
long duplicateCount = docDefinitionService.lambdaQuery()
|
||||
.eq(DocDefinition::getName, definitionDto.getName().trim())
|
||||
.eq(DocDefinition::getVersion, definitionDto.getVersion().trim())
|
||||
.count();
|
||||
long duplicateCount =
|
||||
docDefinitionService.lambdaQuery().eq(DocDefinition::getName, definitionDto.getName().trim())
|
||||
.eq(DocDefinition::getVersion, definitionDto.getVersion().trim()).count();
|
||||
if (duplicateCount > 0) {
|
||||
log.warn("新增文书定义失败:名称={}、版本号={}的文书已存在",
|
||||
definitionDto.getName(), definitionDto.getVersion());
|
||||
log.warn("新增文书定义失败:名称={}、版本号={}的文书已存在", definitionDto.getName(), definitionDto.getVersion());
|
||||
return R.fail("新增文书定义失败:相同名称和版本号的文书已存在,请修改后重试");
|
||||
}
|
||||
|
||||
@@ -116,15 +118,14 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
// 5. 保存文书定义
|
||||
boolean saveSuccess = docDefinitionService.save(docDefinition);
|
||||
if (!saveSuccess) {
|
||||
log.error("新增文书定义失败:数据库保存异常(名称={}, 版本号={}, 业务编号={}",
|
||||
definitionDto.getName(), definitionDto.getVersion(), busNo);
|
||||
log.error("新增文书定义失败:数据库保存异常(名称={}, 版本号={}, 业务编号={}", definitionDto.getName(), definitionDto.getVersion(),
|
||||
busNo);
|
||||
return R.fail("新增文书定义失败:数据库保存操作异常");
|
||||
}
|
||||
|
||||
// 6. 科室分配(仅当使用范围为"科室级"时执行)
|
||||
if (DocUseRangeEnum.DEPT_USE.getValue().equals(definitionDto.getUseRangeEnum())
|
||||
&& definitionDto.getOrganizationIds() != null
|
||||
&& !definitionDto.getOrganizationIds().isEmpty()) {
|
||||
&& definitionDto.getOrganizationIds() != null && !definitionDto.getOrganizationIds().isEmpty()) {
|
||||
DocDefinitionOrganizationDto orgDto = new DocDefinitionOrganizationDto();
|
||||
orgDto.setBusNo(busNo);
|
||||
orgDto.setDefinitionId(docDefinition.getId());
|
||||
@@ -136,7 +137,6 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
return R.ok("新增文书定义成功");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改文书定义(版本号冲突时自动新增,含科室分配更新)
|
||||
*/
|
||||
@@ -158,7 +158,9 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
if (definitionDto.getBusNo() == null || definitionDto.getBusNo().trim().isEmpty()) {
|
||||
return R.fail("修改文书定义失败:文书业务编号不能为空(或不能为空白字符)");
|
||||
}
|
||||
if (definitionDto.getUseRangeEnum() != null && DocUseRangeEnum.DEPT_USE.getValue().equals(definitionDto.getUseRangeEnum()) && definitionDto.getOrganizationIds() == null) {
|
||||
if (definitionDto.getUseRangeEnum() != null
|
||||
&& DocUseRangeEnum.DEPT_USE.getValue().equals(definitionDto.getUseRangeEnum())
|
||||
&& definitionDto.getOrganizationIds() == null) {
|
||||
return R.fail("修改文书定义失败:科室分配时,科室不能为空");
|
||||
}
|
||||
// 2. 校验文书是否存在
|
||||
@@ -170,8 +172,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
|
||||
// 3. 版本号冲突处理(版本号不一致时,转为新增逻辑)
|
||||
if (!existingDoc.getVersion().trim().equals(definitionDto.getVersion().trim())) {
|
||||
log.info("修改文书定义:版本号冲突(原版本={}, 新版本={}),自动执行新增逻辑",
|
||||
existingDoc.getVersion(), definitionDto.getVersion());
|
||||
log.info("修改文书定义:版本号冲突(原版本={}, 新版本={}),自动执行新增逻辑", existingDoc.getVersion(), definitionDto.getVersion());
|
||||
// 新增前清空ID,避免覆盖原有记录
|
||||
definitionDto.setId(null);
|
||||
return addDefinition(definitionDto);
|
||||
@@ -211,8 +212,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
// 6. 执行修改
|
||||
boolean updateSuccess = docDefinitionService.updateById(existingDoc);
|
||||
if (!updateSuccess) {
|
||||
log.error("修改文书定义失败:数据库更新异常(ID={}, 业务编号={}",
|
||||
definitionDto.getId(), definitionDto.getBusNo());
|
||||
log.error("修改文书定义失败:数据库更新异常(ID={}, 业务编号={}", definitionDto.getId(), definitionDto.getBusNo());
|
||||
return R.fail("修改文书定义失败:数据库更新操作异常");
|
||||
} else {
|
||||
// 7. 更新科室分配(仅当使用范围为"科室级"时执行)
|
||||
@@ -255,20 +255,14 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
}
|
||||
|
||||
// 2. 数据库查询文书定义列表
|
||||
List<DocDefinitionDto> docList = docDefinitionAppMapper.getDefinationList(
|
||||
param.getUseRanges(),
|
||||
param.getOrganizationId(),
|
||||
hospitalId,
|
||||
param.getName(),
|
||||
param.getPrimaryMenuEnum()
|
||||
);
|
||||
List<DocDefinitionDto> docList = docDefinitionAppMapper.getDefinationList(param.getUseRanges(),
|
||||
param.getOrganizationId(), hospitalId, param.getName(), param.getPrimaryMenuEnum());
|
||||
|
||||
// 3. 构建树形结构(空列表时返回空树,避免空指针)
|
||||
List<DirectoryNode> treeNodes = new ArrayList<>();
|
||||
if (docList != null && !docList.isEmpty()) {
|
||||
treeNodes = DocumentDirectoryProcessor.buildDocumentDirectory(docList);
|
||||
log.info("获取文书定义树形列表成功:医院ID={}, 文书数量={}, 树形节点数量={}",
|
||||
hospitalId, docList.size(), treeNodes.size());
|
||||
log.info("获取文书定义树形列表成功:医院ID={}, 文书数量={}, 树形节点数量={}", hospitalId, docList.size(), treeNodes.size());
|
||||
} else {
|
||||
log.info("获取文书定义树形列表成功:医院ID={}, 暂无匹配的文书定义", hospitalId);
|
||||
}
|
||||
@@ -293,8 +287,7 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
return R.fail("获取文书定义详情失败:未查询到对应的文书定义信息");
|
||||
}
|
||||
|
||||
log.info("获取文书定义详情成功:ID={}, 名称={}, 业务编号={}",
|
||||
id, docDto.getName(), docDto.getBusNo());
|
||||
log.info("获取文书定义详情成功:ID={}, 名称={}, 业务编号={}", id, docDto.getName(), docDto.getBusNo());
|
||||
return R.ok(docDto, "获取文书定义详情成功");
|
||||
}
|
||||
|
||||
@@ -311,8 +304,8 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
|
||||
// 2. 查询该文书已分配的科室ID列表
|
||||
LambdaQueryWrapper<DocDefinitionOrganization> orgWrapper = new LambdaQueryWrapper<>();
|
||||
orgWrapper.eq(DocDefinitionOrganization::getDefinitionId, id)
|
||||
.eq(DocDefinitionOrganization::getBusNo, doc.getBusNo());
|
||||
orgWrapper.eq(DocDefinitionOrganization::getDefinitionId, id).eq(DocDefinitionOrganization::getBusNo,
|
||||
doc.getBusNo());
|
||||
List<DocDefinitionOrganization> orgList = docDefinitionOrganizationService.list(orgWrapper);
|
||||
|
||||
// 3. 提取科室ID并封装DTO
|
||||
@@ -327,4 +320,29 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
|
||||
return docDto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文书ID
|
||||
*
|
||||
* @param menuEnum 来源类型(DocDefinitionEnum)
|
||||
* @return 文书列表
|
||||
*/
|
||||
@Override
|
||||
public R<?> getDefinitionId(Integer menuEnum) {
|
||||
// 1. 获取当前登录用户的医院ID(避免跨医院查询)
|
||||
Long hospitalId = SecurityUtils.getLoginUser().getHospitalId();
|
||||
if (hospitalId == null) {
|
||||
log.warn("获取文书定义树形列表失败:当前登录用户未关联医院ID");
|
||||
return R.fail("获取文书定义树形列表失败:当前用户未关联医院,请重新登录");
|
||||
}
|
||||
if (menuEnum == null) {
|
||||
return R.fail("来源类型不能为空");
|
||||
}
|
||||
// 2. 数据库查询文书定义列表
|
||||
LambdaQueryWrapper<DocDefinition> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(DocDefinition::getHospitalId, hospitalId);
|
||||
queryWrapper.eq(DocDefinition::getPrimaryMenuEnum, menuEnum);
|
||||
List<DocDefinition> docList = docDefinitionService.list(queryWrapper);
|
||||
return R.ok(docList);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,27 @@
|
||||
package com.openhis.web.document.appservice.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
@@ -10,16 +30,15 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.core.common.utils.AgeCalculatorUtil;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.common.utils.bean.BeanUtils;
|
||||
import com.openhis.common.enums.AdministrativeGender;
|
||||
import com.openhis.common.enums.DocStatusEnum;
|
||||
import com.openhis.common.enums.DocTypeEnum;
|
||||
import com.openhis.common.enums.EncounterClass;
|
||||
import com.openhis.common.utils.HisPageUtils;
|
||||
import com.openhis.common.enums.*;
|
||||
import com.openhis.common.utils.HisQueryUtils;
|
||||
import com.openhis.document.domain.DocRecord;
|
||||
import com.openhis.document.domain.DocStatistics;
|
||||
import com.openhis.document.mapper.DocRecordMapper;
|
||||
import com.openhis.document.service.IDocRecordService;
|
||||
import com.openhis.document.service.IDocStatisticsService;
|
||||
import com.openhis.web.document.appservice.IDocDefinitionAppService;
|
||||
import com.openhis.web.document.appservice.IDocRecordAppService;
|
||||
import com.openhis.web.document.appservice.IDocStatisticsAppService;
|
||||
@@ -27,23 +46,10 @@ import com.openhis.web.document.appservice.IDocStatisticsDefinitionAppService;
|
||||
import com.openhis.web.document.dto.*;
|
||||
import com.openhis.web.document.mapper.DocRecordAppMapper;
|
||||
import com.openhis.web.document.util.ConvertToDocStatistics;
|
||||
import com.openhis.web.document.util.OperationDayCalculator;
|
||||
import com.openhis.web.document.util.PermissionProcessor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@@ -62,11 +68,12 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
@Resource
|
||||
private IDocStatisticsAppService docStatisticsAppService;
|
||||
@Resource
|
||||
private IDocStatisticsService docStatisticsService;
|
||||
@Resource
|
||||
ConvertToDocStatistics convertToDocStatistics;
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate; // 使用 JdbcTemplate 执行 SQL
|
||||
|
||||
|
||||
/**
|
||||
* 插入单条文档操作日志
|
||||
*
|
||||
@@ -80,29 +87,19 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
}
|
||||
|
||||
try {
|
||||
String sql = "INSERT INTO doc_record_log(" +
|
||||
"record_id, definition_id, definition_bus_no, content_json, " +
|
||||
"status_enum, organization_id, encounter_id, patient_id, record_time, " +
|
||||
"create_by, create_time, update_by, update_time, delete_flag, tenant_id" +
|
||||
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
String sql = "INSERT INTO doc_record_log(" + "record_id, definition_id, definition_bus_no, content_json, "
|
||||
+ "status_enum, organization_id, encounter_id, patient_id, record_time, "
|
||||
+ "create_by, create_time, update_by, update_time, delete_flag, tenant_id"
|
||||
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
Object[] params = {
|
||||
docRecord.getId(),
|
||||
docRecord.getDefinitionId(),
|
||||
docRecord.getDefinitionBusNo(),
|
||||
docRecord.getContentJson(),
|
||||
docRecord.getStatusEnum(),
|
||||
docRecord.getOrganizationId(),
|
||||
docRecord.getEncounterId(),
|
||||
docRecord.getPatientId(),
|
||||
new Timestamp(docRecord.getRecordTime().getTime()),
|
||||
SecurityUtils.getUsername(),
|
||||
new Timestamp(new Date().getTime()),
|
||||
null, // update_by
|
||||
null, // update_time
|
||||
0, // delete_flag(未删除)
|
||||
docRecord.getTenantId()
|
||||
};
|
||||
Object[] params = {docRecord.getId(), docRecord.getDefinitionId(), docRecord.getDefinitionBusNo(),
|
||||
docRecord.getContentJson(), docRecord.getStatusEnum(), docRecord.getOrganizationId(),
|
||||
docRecord.getEncounterId(), docRecord.getPatientId(),
|
||||
new Timestamp(docRecord.getRecordTime().getTime()), SecurityUtils.getUsername(),
|
||||
new Timestamp(new Date().getTime()), null, // update_by
|
||||
null, // update_time
|
||||
0, // delete_flag(未删除)
|
||||
docRecord.getTenantId()};
|
||||
|
||||
int rowsAffected = jdbcTemplate.update(sql, params);
|
||||
return rowsAffected > 0;
|
||||
@@ -125,11 +122,10 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
}
|
||||
|
||||
try {
|
||||
String sql = "INSERT INTO doc_record_log(" +
|
||||
"record_id, definition_id, definition_bus_no, content_json, " +
|
||||
"status_enum, organization_id, encounter_id, patient_id, record_time, " +
|
||||
"create_by, create_time, update_by, update_time, delete_flag, tenant_id" +
|
||||
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
String sql = "INSERT INTO doc_record_log(" + "record_id, definition_id, definition_bus_no, content_json, "
|
||||
+ "status_enum, organization_id, encounter_id, patient_id, record_time, "
|
||||
+ "create_by, create_time, update_by, update_time, delete_flag, tenant_id"
|
||||
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
int[] results = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
|
||||
@Override
|
||||
@@ -210,7 +206,6 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 文书统计 - 新增、编辑记录
|
||||
*
|
||||
@@ -246,7 +241,8 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
docRecord.setDefinitionId(docRecordDto.getDefinitionId());
|
||||
docRecord.setDefinitionBusNo(docRecordDto.getDefinitionBusNo());
|
||||
docRecord.setContentJson(docRecordDto.getContentJson());
|
||||
docRecord.setStatusEnum(docRecordDto.getStatusEnum() == null ? DocStatusEnum.DRAFT.getValue() : docRecordDto.getStatusEnum());
|
||||
docRecord.setStatusEnum(
|
||||
docRecordDto.getStatusEnum() == null ? DocStatusEnum.DRAFT.getValue() : docRecordDto.getStatusEnum());
|
||||
docRecord.setOrganizationId(SecurityUtils.getLoginUser().getOrgId());
|
||||
docRecord.setEncounterId(docRecordDto.getEncounterId());
|
||||
docRecord.setPatientId(docRecordDto.getPatientId());
|
||||
@@ -269,9 +265,16 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
* @return 返回结果 R对象
|
||||
*/
|
||||
public R<?> updateRecord(DocRecordDto docRecordDto) {
|
||||
String checkMsg = initRecordCheck(docRecordDto);
|
||||
if (!checkMsg.isEmpty()) {
|
||||
return R.fail(checkMsg);
|
||||
Integer printCount = docRecordDto.getPrintCount();
|
||||
if (printCount > 0) {
|
||||
return R.fail("已打印的文书记录,禁止修改");
|
||||
}
|
||||
List<String> sourceCodes = Arrays.stream(DocDefinitionEnum.values()).map(DocDefinitionEnum::getValue).toList();
|
||||
if (!sourceCodes.contains(StringUtils.isBlank(docRecordDto.getSource()) ? "" : docRecordDto.getSource())) {
|
||||
String checkMsg = initRecordCheck(docRecordDto);
|
||||
if (!checkMsg.isEmpty()) {
|
||||
return R.fail(checkMsg);
|
||||
}
|
||||
}
|
||||
// 1. 查询原文书记录
|
||||
DocRecord docRecord = docRecordService.getById(docRecordDto.getId());
|
||||
@@ -312,7 +315,8 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
* 根据患者ID/就诊ID获取文书记录列表(支持分页)
|
||||
*/
|
||||
@Override
|
||||
public R<?> getRecordByEncounterIdList(DocRecordQueryParam docRecordQueryParam, Integer isPage, Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request) {
|
||||
public R<?> getRecordByEncounterIdList(DocRecordQueryParam docRecordQueryParam, Integer isPage, Integer pageNo,
|
||||
Integer pageSize, String searchKey, HttpServletRequest request) {
|
||||
// 1. 参数校验
|
||||
if (docRecordQueryParam == null) {
|
||||
return R.fail("患者文书记录:查询参数不能为空");
|
||||
@@ -326,10 +330,10 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
|
||||
// 2. 分页查询逻辑
|
||||
if (isPage != null && isPage == 1) {
|
||||
QueryWrapper<DocRecordDto> queryWrapper = HisQueryUtils.buildQueryWrapper(
|
||||
docRecordQueryParam, null, null, request);
|
||||
IPage<DocRecordDto> pageResult = docRecordAppMapper.getRecordPageListByEncounterId(
|
||||
new Page<>(pageNo, pageSize), queryWrapper);
|
||||
QueryWrapper<DocRecordDto> queryWrapper =
|
||||
HisQueryUtils.buildQueryWrapper(docRecordQueryParam, null, null, request);
|
||||
IPage<DocRecordDto> pageResult =
|
||||
docRecordAppMapper.getRecordPageListByEncounterId(new Page<>(pageNo, pageSize), queryWrapper);
|
||||
return R.ok(pageResult, "获取患者文书记录列表成功");
|
||||
}
|
||||
// 3. 不分页查询逻辑
|
||||
@@ -350,15 +354,16 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
queryWrapper.eq(DocRecord::getOrganizationId, docRecordQueryParam.getOrganizationId());
|
||||
}
|
||||
|
||||
DocDefinitionDto docDefinitionDto = docDefinitionAppService.getDefinitionById(docRecordQueryParam.getDefinitionId());
|
||||
DocDefinitionDto docDefinitionDto =
|
||||
docDefinitionAppService.getDefinitionById(docRecordQueryParam.getDefinitionId());
|
||||
// 实体转DTO
|
||||
List<DocRecordDto> dtoList = new ArrayList<>();
|
||||
List<DocRecord> recordList = docRecordService.list(queryWrapper);
|
||||
for (DocRecord record : recordList) {
|
||||
DocRecordDto dto = new DocRecordDto();
|
||||
BeanUtils.copyProperties(record, dto);
|
||||
dto.setName(docDefinitionDto!=null?docDefinitionDto.getName():"");
|
||||
dto.setVersion(docDefinitionDto!=null?docDefinitionDto.getVersion():"");
|
||||
dto.setName(docDefinitionDto != null ? docDefinitionDto.getName() : "");
|
||||
dto.setVersion(docDefinitionDto != null ? docDefinitionDto.getVersion() : "");
|
||||
dtoList.add(dto);
|
||||
}
|
||||
return R.ok(dtoList, "获取患者文书记录列表成功");
|
||||
@@ -369,18 +374,20 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
* 查询患者文书记录列表(携带患者信息,支持分页)
|
||||
*/
|
||||
@Override
|
||||
public R<?> getRecordPageList(DocRecordPatientQueryParam docRecordPatientQueryParam, List<Integer> primaryMenuEnumList, Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request) {
|
||||
public R<?> getRecordPageList(DocRecordPatientQueryParam docRecordPatientQueryParam,
|
||||
List<Integer> primaryMenuEnumList, Integer pageNo, Integer pageSize, String searchKey,
|
||||
HttpServletRequest request) {
|
||||
if (docRecordPatientQueryParam == null) {
|
||||
return R.fail("文书记录:查询参数不能为空");
|
||||
}
|
||||
|
||||
// 构建查询条件(支持患者姓名搜索)
|
||||
QueryWrapper<DocRecordPatientDto> queryWrapper = HisQueryUtils.buildQueryWrapper(
|
||||
docRecordPatientQueryParam, searchKey, new HashSet<>(Arrays.asList("patient_name", "bus_no")), request);
|
||||
QueryWrapper<DocRecordPatientDto> queryWrapper = HisQueryUtils.buildQueryWrapper(docRecordPatientQueryParam,
|
||||
searchKey, new HashSet<>(Arrays.asList("patient_name", "bus_no")), request);
|
||||
|
||||
// 分页查询
|
||||
IPage<DocRecordPatientDto> pageResult = docRecordAppMapper.getRecordPageList(
|
||||
new Page<>(pageNo, pageSize), primaryMenuEnumList, queryWrapper);
|
||||
IPage<DocRecordPatientDto> pageResult =
|
||||
docRecordAppMapper.getRecordPageList(new Page<>(pageNo, pageSize), primaryMenuEnumList, queryWrapper);
|
||||
|
||||
// 处理返回结果:枚举值转中文描述、计算患者年龄
|
||||
if (pageResult != null && !pageResult.getRecords().isEmpty()) {
|
||||
@@ -477,6 +484,7 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
// 4. 执行删除
|
||||
boolean deleteSuccess = docRecordService.removeByIds(ids);
|
||||
if (deleteSuccess) {
|
||||
docStatisticsAppService.delete(ids);
|
||||
// 5. 批量插入删除日志
|
||||
boolean logSuccess = insertBatchLog(logRecordList);
|
||||
if (!logSuccess) {
|
||||
@@ -487,4 +495,538 @@ public class DocRecordAppServiceImpl implements IDocRecordAppService {
|
||||
return R.fail("删除患者文书记录失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据患者ID或就诊ID以及时间获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理 需返回患者具体信息的列表,请使用getPatientRecordList
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @param recordTime 时间
|
||||
* @return R
|
||||
*/
|
||||
@Override
|
||||
public R<?> getRecordByEncounterIdAndTimeList(DocRecordQueryParam docRecordQueryParam, String recordTime) {
|
||||
// 参数校验
|
||||
if (docRecordQueryParam == null) {
|
||||
return R.fail("患者文书记录:查询参数不能为空");
|
||||
}
|
||||
if (docRecordQueryParam.getPatientId() == null && docRecordQueryParam.getEncounterId() == null) {
|
||||
return R.fail("患者文书记录:患者ID和就诊ID不能同时为空");
|
||||
}
|
||||
if (docRecordQueryParam.getDefinitionId() == null) {
|
||||
return R.fail("患者文书记录:文书类型(定义)ID不能为空");
|
||||
}
|
||||
// 未传时间,按照当前时间
|
||||
Date recordDate = StringUtils.isBlank(recordTime) ? new Date()
|
||||
: Date.from(LocalDate.parse(recordTime, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay()
|
||||
.atZone(ZoneId.systemDefault()).toInstant());
|
||||
// 患者ID查询条件
|
||||
LambdaQueryWrapper<DocRecord> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (docRecordQueryParam.getPatientId() != null) {
|
||||
queryWrapper.eq(DocRecord::getPatientId, docRecordQueryParam.getPatientId())
|
||||
.eq(DocRecord::getEncounterId, docRecordQueryParam.getEncounterId())
|
||||
.ge(DocRecord::getRecordTime, recordDate).lt(DocRecord::getRecordTime,
|
||||
Date.from(recordDate.toInstant().atZone(ZoneId.systemDefault()).plusDays(1).toInstant()));
|
||||
}
|
||||
// 文书类型ID(必传)
|
||||
queryWrapper.eq(DocRecord::getDefinitionId, docRecordQueryParam.getDefinitionId());
|
||||
// 就诊ID查询条件(修复原逻辑:原代码字段匹配错误,用EncounterId匹配DefinitionBusNo)
|
||||
// if (docRecordQueryParam.getEncounterId() != null) {
|
||||
// queryWrapper.eq(DocRecord::getEncounterId, docRecordQueryParam.getEncounterId());
|
||||
// }
|
||||
// 科室ID查询条件(修复原逻辑:原代码字段匹配错误,用OrganizationId匹配EncounterId)
|
||||
if (docRecordQueryParam.getOrganizationId() != null) {
|
||||
queryWrapper.eq(DocRecord::getOrganizationId, docRecordQueryParam.getOrganizationId());
|
||||
}
|
||||
DocDefinitionDto docDefinitionDto =
|
||||
docDefinitionAppService.getDefinitionById(docRecordQueryParam.getDefinitionId());
|
||||
// 实体转DTO
|
||||
List<DocRecordDto> dtoList = new ArrayList<>();
|
||||
List<DocRecord> recordList = docRecordService.list(queryWrapper);
|
||||
for (DocRecord record : recordList) {
|
||||
DocRecordDto dto = new DocRecordDto();
|
||||
BeanUtils.copyProperties(record, dto);
|
||||
dto.setName(docDefinitionDto != null ? docDefinitionDto.getName() : "");
|
||||
dto.setVersion(docDefinitionDto != null ? docDefinitionDto.getVersion() : "");
|
||||
dtoList.add(dto);
|
||||
}
|
||||
return R.ok(dtoList, "获取患者文书记录列表成功");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据文书记录ID打印文书记录
|
||||
*
|
||||
* @param recordId 文书记录ID
|
||||
* @return R
|
||||
*/
|
||||
@Override
|
||||
public R<?> recordPrint(Long recordId) {
|
||||
LambdaQueryWrapper<DocRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DocRecord::getId, recordId);
|
||||
DocRecord record = docRecordService.getOne(wrapper);
|
||||
if (record != null) {
|
||||
record.setPrintCount(record.getPrintCount() + 1);
|
||||
docRecordService.updateById(record);
|
||||
}
|
||||
return R.ok(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增或编辑记录(根据id是否为空判断新增或编辑)
|
||||
*
|
||||
* @param docRecordDto 文书记录信息
|
||||
* @return R
|
||||
*/
|
||||
@Override
|
||||
public R<?> saveOrUpdateRecord(DocRecordDto docRecordDto) {
|
||||
Long id = docRecordDto.getId();
|
||||
if (id == null) {
|
||||
return addRecord(docRecordDto);
|
||||
} else {
|
||||
return updateRecord(docRecordDto);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据病历ID、病人ID和体温单ID获取温度单信息
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @return 体温单信息
|
||||
*/
|
||||
@Override
|
||||
public R<?> temperatureChart(DocRecordQueryParam docRecordQueryParam) {
|
||||
// 参数校验
|
||||
if (docRecordQueryParam == null) {
|
||||
return R.fail("患者文书记录:查询参数不能为空");
|
||||
}
|
||||
Long encounterId = docRecordQueryParam.getEncounterId();
|
||||
Long patientId = docRecordQueryParam.getPatientId();
|
||||
Long tempId = docRecordQueryParam.getDefinitionId();
|
||||
if (encounterId == null) {
|
||||
return R.fail("患者文书记录:就诊ID不能为空");
|
||||
}
|
||||
if (patientId == null) {
|
||||
return R.fail("患者文书记录:患者ID不能为空");
|
||||
}
|
||||
if (tempId == null) {
|
||||
return R.fail("患者文书记录:文书类型(定义)ID不能为空");
|
||||
}
|
||||
// 根据病历ID和患者ID获取住院、出院时间
|
||||
Map<String, Date> dateMap = getDateByEncounterId(encounterId, patientId);
|
||||
Date hospDate = dateMap.get("hospDate");
|
||||
Date outDate = dateMap.get("outDate");
|
||||
// 所有的chartsSmalls
|
||||
List<TrendChartsSmall> allTrendChartsSmalls = new ArrayList<>();
|
||||
// 获取体温单信息
|
||||
List<DocStatisticsDto> statisticsList =
|
||||
docStatisticsAppService.getStatisticsListByEncounterIdAndPatientId(encounterId, patientId, tempId);
|
||||
// 过滤出血压
|
||||
List<DocStatisticsDto> bloodPressureList = statisticsList.stream().filter(item -> {
|
||||
String code = item.getStatisticDefinitionCode();
|
||||
if (code != null) {
|
||||
return TemperatureChartEnum.BLOOD_PRESSURE.getCode().equals(code);
|
||||
}
|
||||
return false;
|
||||
}).toList();
|
||||
// 移除血压
|
||||
statisticsList.removeAll(bloodPressureList);
|
||||
// 获取每一天 上下午 各最新一条的数据
|
||||
bloodPressureList = getLatestRecordsPerPeriod(bloodPressureList);
|
||||
// 添加血压list
|
||||
statisticsList.addAll(bloodPressureList);
|
||||
// 先排序 按时间分组,确保同一组的数据应该在一组
|
||||
statisticsList.sort(Comparator.comparing(DocStatisticsDto::getRecordTime));
|
||||
// 转换为TrendChartsSmall集合
|
||||
for (DocStatisticsDto docStatisticsDto : statisticsList) {
|
||||
// typeCode
|
||||
String typeCode = docStatisticsDto.getStatisticDefinitionCode();
|
||||
// typeValue
|
||||
String typeValue = docStatisticsDto.getValue();
|
||||
// 如果typeValue为空,数据不添加进list
|
||||
if (StringUtils.isBlank(typeValue)) {
|
||||
continue;
|
||||
}
|
||||
// date
|
||||
Date date = docStatisticsDto.getRecordTime();
|
||||
// times
|
||||
String times = formatDate(date, "HH:mm:ss");
|
||||
// weekNo
|
||||
Integer weekNo = calculateWeek(hospDate, date);
|
||||
// orderByDateTimes 暂时不用
|
||||
String orderByDateTimes = null;
|
||||
// id 暂时不用
|
||||
String id = null;
|
||||
// collectionMode 体温(003)、脉搏(002)、呼吸(001)、疼痛等级(016)为 1,其余为null
|
||||
Integer collectionMode = null;
|
||||
List<String> temperatureChartCodes =
|
||||
Arrays.asList(TemperatureChartEnum.TEMPERATURE.getCode(), TemperatureChartEnum.PULSE.getCode(),
|
||||
TemperatureChartEnum.BREATH.getCode(), TemperatureChartEnum.PAIN_SCORE.getCode());
|
||||
if (temperatureChartCodes.contains(typeCode)) {
|
||||
collectionMode = 1;
|
||||
if (isChineseWithSpace(typeValue)) {
|
||||
typeCode = TemperatureChartEnum.TEMPERATURE_CHINESE.getCode();
|
||||
}
|
||||
}
|
||||
TrendChartsSmall trendChartsSmall =
|
||||
new TrendChartsSmall(collectionMode, date, times, typeCode, typeValue, weekNo, orderByDateTimes, id);
|
||||
allTrendChartsSmalls.add(trendChartsSmall);
|
||||
}
|
||||
// 体温单信息
|
||||
TrendChartsOutput trendChartsOutput = returnTrendChartsOutput(allTrendChartsSmalls, encounterId, hospDate);
|
||||
trendChartsOutput.setOutDate(outDate);
|
||||
// 术后天数
|
||||
calculatePostopDay(trendChartsOutput, getPostopDate(encounterId, patientId));
|
||||
return R.ok(trendChartsOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* 护理记录总结
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 护理记录总结
|
||||
*/
|
||||
@Override
|
||||
public R<?> summaryNursingRecords(DocRecordQueryParam docRecordQueryParam, String startTime, String endTime) {
|
||||
// 参数校验
|
||||
if (docRecordQueryParam == null) {
|
||||
return R.fail("患者文书记录:查询参数不能为空");
|
||||
}
|
||||
Long encounterId = docRecordQueryParam.getEncounterId();
|
||||
Long patientId = docRecordQueryParam.getPatientId();
|
||||
Long definitionId = docRecordQueryParam.getDefinitionId();
|
||||
if (encounterId == null) {
|
||||
return R.fail("患者文书记录:就诊ID不能为空");
|
||||
}
|
||||
if (patientId == null) {
|
||||
return R.fail("患者文书记录:患者ID不能为空");
|
||||
}
|
||||
if (definitionId == null) {
|
||||
return R.fail("患者文书记录:文书类型(定义)ID不能为空");
|
||||
}
|
||||
List<DocRecordDto> docRecordList = new ArrayList<>();
|
||||
// 查询所有
|
||||
LambdaQueryWrapper<DocRecord> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.eq(DocRecord::getEncounterId, encounterId);
|
||||
wrapper.eq(DocRecord::getPatientId, patientId);
|
||||
wrapper.eq(DocRecord::getDefinitionId, definitionId);
|
||||
// 有时间就按时间条件查询
|
||||
if (StringUtils.isNotBlank(startTime)) {
|
||||
wrapper.ge(DocRecord::getRecordTime, LocalDate.parse(startTime));
|
||||
}
|
||||
if (StringUtils.isNotBlank(endTime)) {
|
||||
wrapper.lt(StringUtils.isNotBlank(endTime), DocRecord::getRecordTime, LocalDate.parse(endTime).plusDays(1));
|
||||
}
|
||||
// 时间最新数据在前面
|
||||
wrapper.orderByDesc(DocRecord::getRecordTime);
|
||||
List<DocRecord> recordList = docRecordService.list(wrapper);
|
||||
recordList.forEach(record -> {
|
||||
DocRecordDto dto = new DocRecordDto();
|
||||
BeanUtils.copyProperties(record, dto);
|
||||
docRecordList.add(dto);
|
||||
});
|
||||
// 有时间则会总结出入量
|
||||
List<Long> recordIds = docRecordList.stream().map(DocRecordDto::getId).toList();
|
||||
if (StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime) && !recordIds.isEmpty()) {
|
||||
// 查询出入量
|
||||
LambdaQueryWrapper<DocStatistics> statisticsWrapper = new LambdaQueryWrapper<>();
|
||||
if (docRecordQueryParam.getDefinitionId() != null) {
|
||||
statisticsWrapper.eq(DocStatistics::getDefinitionId, docRecordQueryParam.getDefinitionId());
|
||||
}
|
||||
statisticsWrapper.eq(DocStatistics::getSource, DocDefinitionEnum.NURSING_RECORD.getValue());
|
||||
statisticsWrapper.in(DocStatistics::getRecordId, recordIds);
|
||||
statisticsWrapper.in(DocStatistics::getStatisticDefinitionCode,
|
||||
Arrays.asList(TemperatureChartEnum.OUTPUT.getTypeCode(), TemperatureChartEnum.INPUT.getTypeCode()));
|
||||
// 获取出、入量数据
|
||||
List<DocStatistics> nursingRecordList = docStatisticsService.list(statisticsWrapper);
|
||||
if (!nursingRecordList.isEmpty()) {
|
||||
// 总出量
|
||||
BigDecimal totalOutput = BigDecimal.ZERO;
|
||||
// 总入量
|
||||
BigDecimal totalInput = BigDecimal.ZERO;
|
||||
for (DocStatistics statistics : nursingRecordList) {
|
||||
BigDecimal value = new BigDecimal(statistics.getValue());
|
||||
if (statistics.getStatisticDefinitionCode().equals(TemperatureChartEnum.OUTPUT.getTypeCode())) {
|
||||
// 计算总出量
|
||||
totalOutput = totalOutput.add(value);
|
||||
} else {
|
||||
// 计算总入量
|
||||
totalInput = totalInput.add(value);
|
||||
}
|
||||
}
|
||||
// 将总出、入量添加要返回的数据中
|
||||
DocRecordDto dto = new DocRecordDto();
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
map.put(TemperatureChartEnum.OUTPUT.getTypeCode(), totalOutput.toString());
|
||||
map.put(TemperatureChartEnum.INPUT.getTypeCode(), totalInput.toString());
|
||||
dto.setContentJson(JSONObject.toJSONString(map));
|
||||
docRecordList.add(dto);
|
||||
}
|
||||
}
|
||||
return R.ok(docRecordList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回封装好的体温单
|
||||
*
|
||||
* @param allTrendChartsSmalls 所有的chartsSmalls
|
||||
* @return 封装好的体温单
|
||||
*/
|
||||
private TrendChartsOutput returnTrendChartsOutput(List<TrendChartsSmall> allTrendChartsSmalls, Long encounterId,
|
||||
Date hospDate) {
|
||||
allTrendChartsSmalls.sort(Comparator.comparing(TrendChartsSmall::getDate));
|
||||
// temperaturePulses 集合
|
||||
List<TrendChartsBig> temperaturePulses = new ArrayList<>();
|
||||
// temperaturePulses中的chartsSmalls集合
|
||||
List<TrendChartsSmall> bigSmalls = null;
|
||||
// 获取others数据
|
||||
List<TrendChartsSmall> others = new ArrayList<>(allTrendChartsSmalls.stream()
|
||||
.filter(item -> (item.getCollectionMode() == null || item.getCollectionMode() != 1)).toList());
|
||||
// 尿量、大便次数、小便次数、入量、其他 记录的是前一天的,时间要减一天
|
||||
// isOneDayInAdvance(others);
|
||||
// 移除others数据
|
||||
allTrendChartsSmalls.removeAll(others);
|
||||
// 根据病历ID获取入科时间
|
||||
Date admissionDate = getDateByEncounterId(encounterId);
|
||||
// 为入科 TrendChartsSmall 准备数据
|
||||
int weekNo = calculateWeek(hospDate, admissionDate);
|
||||
// 入科 TrendChartsSmall
|
||||
TrendChartsSmall admissionSmall = new TrendChartsSmall(null, admissionDate,
|
||||
formatDate(admissionDate, "HH:mm:ss"), TemperatureChartEnum.WARD_ADMISSION.getCode(),
|
||||
TemperatureChartEnum.WARD_ADMISSION.getDescription() + "," + formatDate(admissionDate, "HH:mm"), weekNo,
|
||||
formatDate(admissionDate, "yyyy-MM-dd HH:mm:ss"), "");
|
||||
ArrayList<TrendChartsSmall> admissionBig = new ArrayList<>();
|
||||
admissionBig.add(admissionSmall);
|
||||
// 先添加入科
|
||||
temperaturePulses.add(new TrendChartsBig(admissionBig, weekNo));
|
||||
// 根据记录时间分组
|
||||
long compareTime = 0L;
|
||||
for (TrendChartsSmall trendChartsSmall : allTrendChartsSmalls) {
|
||||
// 获取当前项的时间[date]
|
||||
long smallTime = trendChartsSmall.getDate().getTime();
|
||||
// 时间相同的分一组
|
||||
if (compareTime == smallTime && bigSmalls != null) {
|
||||
bigSmalls.add(trendChartsSmall);
|
||||
} else {
|
||||
// 当时间与上一条的时间不同时创建新集合并添加进temperaturePulses
|
||||
// 1.创建TrendChartsSmall集合
|
||||
bigSmalls = new ArrayList<>();
|
||||
// 1.1 将trendChartsSmall添加进TrendChartsSmall集合
|
||||
bigSmalls.add(trendChartsSmall);
|
||||
// 2.创建新的TrendChartsBig 并传入 chartsSmalls、weekNo
|
||||
TrendChartsBig trendChartsBig = new TrendChartsBig(bigSmalls, trendChartsSmall.getWeekNo());
|
||||
// 2.2 temperaturePulses 添加 TrendChartsBig
|
||||
temperaturePulses.add(trendChartsBig);
|
||||
// 将新的时间赋值给进行比较的时间
|
||||
compareTime = smallTime;
|
||||
}
|
||||
}
|
||||
return new TrendChartsOutput(hospDate, null, null, temperaturePulses, others);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验是否为汉字
|
||||
*
|
||||
* @param content 待校验字符串
|
||||
* @return 校验结果
|
||||
*/
|
||||
public static boolean isChineseWithSpace(String content) {
|
||||
Pattern regex = Pattern.compile("^[\\u4E00-\\u9FA5\\s]+$");
|
||||
if (StringUtils.isBlank(content)) {
|
||||
return false;
|
||||
} else {
|
||||
return regex.matcher(content).matches();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 提前一天
|
||||
*
|
||||
* @param others others集合
|
||||
*/
|
||||
private void isOneDayInAdvance(List<TrendChartsSmall> others) {
|
||||
List<String> tiqian = Arrays.asList(TemperatureChartEnum.INPUT.getCode(),
|
||||
TemperatureChartEnum.BOWEL_MOVEMENT_FREQUENCY.getCode(), TemperatureChartEnum.URINATION_FREQUENCY.getCode(),
|
||||
TemperatureChartEnum.URINE_VOLUME.getCode(), TemperatureChartEnum.OTHERS.getCode());
|
||||
others.forEach(item -> {
|
||||
if (StringUtils.isBlank(item.getTypeCode()) && tiqian.contains(item.getTypeCode())) {
|
||||
LocalDate date = item.getDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
date = date.plusDays(-1);
|
||||
item.setDate(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 每一天的血压取上下午各最新的一条
|
||||
*
|
||||
* @param list 血压集合
|
||||
* @return 每天上下午各最新一条的血压数据的集合
|
||||
*/
|
||||
private List<DocStatisticsDto> getLatestRecordsPerPeriod(List<DocStatisticsDto> list) {
|
||||
// 安全校验:列表为空或null时直接返回空列表
|
||||
if (list == null || list.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 按上午(AM)/下午(PM)分组,获取每组符合规则的最新数据
|
||||
Map<String, Optional<DocStatisticsDto>> latestByAmPm =
|
||||
list.stream().filter(item -> item.getValue() != null && !"/".equals(item.getValue().trim())) // 过滤无效值
|
||||
.collect(Collectors.groupingBy(
|
||||
// 按时间判断上下午:12点前为上午,12点及以后为下午
|
||||
dto -> {
|
||||
LocalTime time = dto.getRecordTime().toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
|
||||
return time.isBefore(LocalTime.NOON) ? "AM" : "PM";
|
||||
}, Collectors.collectingAndThen(Collectors.toList(), groupList -> {
|
||||
// 第一步:筛选出数值型数据(非汉字)
|
||||
List<DocStatisticsDto> numericData = groupList.stream()
|
||||
.filter(dto -> !isChineseWithSpace(dto.getValue())).collect(Collectors.toList());
|
||||
// 第二步:如果有数值型数据,取最新的;否则取分组内最新的汉字数据
|
||||
List<DocStatisticsDto> targetData = numericData.isEmpty() ? groupList : numericData;
|
||||
return targetData.stream().max(Comparator.comparing(DocStatisticsDto::getRecordTime));
|
||||
})));
|
||||
// 提取有效数据并按时间排序
|
||||
List<DocStatisticsDto> validData = latestByAmPm.values().stream().filter(Optional::isPresent).map(Optional::get)
|
||||
.sorted(Comparator.comparing(DocStatisticsDto::getRecordTime)).toList();
|
||||
// 拼接上下午数据(上午值 + 逗号 + 下午值)
|
||||
List<DocStatisticsDto> result = new ArrayList<>();
|
||||
if (validData.size() == 1) {
|
||||
// 只有单条数据(上午/下午),直接保留
|
||||
result.add(validData.get(0));
|
||||
} else if (validData.size() >= 2) {
|
||||
// 取前两条(上午+下午)拼接,上午作为主数据
|
||||
DocStatisticsDto amDto = validData.get(0);
|
||||
DocStatisticsDto pmDto = validData.get(1);
|
||||
amDto.setValue(amDto.getValue() + "," + pmDto.getValue());
|
||||
result.add(amDto);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算weekNo 例:开始日期:2025-11-08 当前日期:2025-11-17 -> 2
|
||||
*
|
||||
* @param startDate 开始日期
|
||||
* @param endDate 结束日期
|
||||
* @return endDate是距startDate的第几周
|
||||
*/
|
||||
private int calculateWeek(Date startDate, Date endDate) {
|
||||
LocalDate start = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
LocalDate end = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
if (start.isAfter(end)) {
|
||||
throw new IllegalArgumentException("开始日期不能晚于结束日期");
|
||||
}
|
||||
// 计算出的相差天数要加1
|
||||
long days = ChronoUnit.DAYS.between(start, end) + 1;
|
||||
return (int)Math.ceil(days / 7.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算术后天数 [斜线(/)前是最新的术后天数]
|
||||
*
|
||||
* @param trendChartsOutput 体温单
|
||||
* @param postopDateList 手术时间list
|
||||
*
|
||||
*/
|
||||
private void calculatePostopDay(TrendChartsOutput trendChartsOutput, List<LocalDateTime> postopDateList) {
|
||||
if (!postopDateList.isEmpty()) {
|
||||
// 统计术后天数的截至日期
|
||||
LocalDate endDate;
|
||||
if (trendChartsOutput.getOutDate() == null) {
|
||||
endDate = LocalDate.now();
|
||||
} else {
|
||||
endDate = trendChartsOutput.getOutDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
}
|
||||
// 添加手术信息
|
||||
for (LocalDateTime dateTime : postopDateList) {
|
||||
// 手术时间
|
||||
Date postopDate = Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
|
||||
String times = formatDate(postopDate, "HH:mm:ss");
|
||||
String typeValue =
|
||||
TemperatureChartEnum.OPERATION.getDescription() + "," + formatDate(postopDate, "HH:mm");
|
||||
// 封装手术信息
|
||||
TrendChartsSmall postopSmall =
|
||||
new TrendChartsSmall(null, postopDate, times, TemperatureChartEnum.OPERATION.getCode(), typeValue,
|
||||
calculateWeek(trendChartsOutput.getHospDate(), postopDate), null, null);
|
||||
// 将收入信息添加到有入科信息的集合中
|
||||
trendChartsOutput.getTemperaturePulses().get(0).getChartsSmalls().add(postopSmall);
|
||||
}
|
||||
// 计算术后天数
|
||||
for (LocalDate currentDate = postopDateList.get(0).toLocalDate(); !currentDate.isAfter(endDate);
|
||||
currentDate = currentDate.plusDays(1)) {
|
||||
// 获取术后天数
|
||||
String typeValue = OperationDayCalculator.calculateOperationDay(
|
||||
postopDateList.stream().map(LocalDateTime::toLocalDate).toList(), currentDate);
|
||||
// 封装[术后天数]信息
|
||||
Date date = Date.from(currentDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
|
||||
TrendChartsSmall postopSmall =
|
||||
new TrendChartsSmall(null, date, null, TemperatureChartEnum.POSTOP_DAYS.getCode(), typeValue,
|
||||
calculateWeek(trendChartsOutput.getHospDate(), date), null, null);
|
||||
trendChartsOutput.getOthers().add(postopSmall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取住院、出院时间
|
||||
*
|
||||
* @param encounterId 病历ID
|
||||
* @param patientId 患者ID
|
||||
* @return 住院时间
|
||||
*/
|
||||
private Map<String, Date> getDateByEncounterId(Long encounterId, Long patientId) {
|
||||
String sql =
|
||||
"SELECT start_time,end_time FROM adm_encounter WHERE id = ? AND patient_id = ? AND status_enum = ? AND class_enum = ?";
|
||||
Object[] params = {encounterId, patientId, EncounterZyStatus.ADMITTED_TO_THE_HOSPITAL.getValue(),
|
||||
EncounterClass.IMP.getValue()};
|
||||
Map<String, Object> result = jdbcTemplate.queryForMap(sql, params);
|
||||
HashMap<String, Date> map = new HashMap<>();
|
||||
map.put("hospDate", (Timestamp)result.get("start_time"));
|
||||
map.put("outTime", (Timestamp)result.get("end_time"));
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取入科时间
|
||||
*
|
||||
* @param encounterId 病历ID
|
||||
* @return 入科时间
|
||||
*/
|
||||
private Date getDateByEncounterId(Long encounterId) {
|
||||
String sql =
|
||||
"SELECT ael.start_time FROM adm_encounter ae INNER JOIN adm_encounter_location ael ON ae.ID=ael.encounter_id AND ael.form_enum=? AND ael.status_enum=? AND ael.delete_flag='0' AND ael.tenant_id=1 LEFT JOIN adm_location al ON ael.location_id=al.ID AND al.delete_flag='0' AND al.tenant_id=1 WHERE ae.ID=? AND ae.delete_flag='0' AND ae.tenant_id=1";
|
||||
Object[] params = {LocationForm.BED.getValue(), EncounterActivityStatus.ACTIVE.getValue(), encounterId};
|
||||
Timestamp timestamp = jdbcTemplate.queryForObject(sql, params, Timestamp.class);
|
||||
return Date.from(timestamp.toInstant());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手术时间
|
||||
*
|
||||
* @param encounterId 病历ID
|
||||
* @param patientId 患者ID
|
||||
* @return 手术时间列表
|
||||
*/
|
||||
private List<LocalDateTime> getPostopDate(Long encounterId, Long patientId) {
|
||||
String sql =
|
||||
"SELECT cpp.start_time FROM cli_procedure_performer cpp LEFT JOIN cli_procedure cp ON cpp.procedure_id=cp.ID LEFT JOIN adm_encounter ae ON ae.patient_id=cp.patient_id AND ae.ID=cp.encounter_id AND ae.status_enum=? AND ae.class_enum=? WHERE cp.patient_id=? AND cp.status_enum=? AND cp.encounter_id=? AND cpp.start_time> ae.start_time AND cpp.end_time <= ae.end_time ORDER BY cpp.start_time";
|
||||
Object[] params = {EncounterZyStatus.ADMITTED_TO_THE_HOSPITAL.getValue(), EncounterClass.IMP.getValue(),
|
||||
patientId, 5, encounterId};
|
||||
List<Timestamp> dates = jdbcTemplate.queryForList(sql, Timestamp.class, params);
|
||||
|
||||
return dates.stream().map(date -> date.toLocalDateTime()).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Date转字符串
|
||||
*
|
||||
* @param date 时间
|
||||
* @param pattern 解析格式
|
||||
* @return 转后后的时间字符串
|
||||
*/
|
||||
private String formatDate(Date date, String pattern) {
|
||||
LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
|
||||
return localDateTime.format(formatter);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,21 @@
|
||||
package com.openhis.web.document.appservice.impl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import com.core.common.utils.bean.BeanUtils;
|
||||
import com.openhis.common.enums.DocDefinitionEnum;
|
||||
import com.openhis.common.utils.HisPageUtils;
|
||||
import com.openhis.common.utils.HisQueryUtils;
|
||||
import com.openhis.document.domain.DocStatistics;
|
||||
@@ -14,13 +24,8 @@ import com.openhis.document.service.IDocStatisticsService;
|
||||
import com.openhis.web.document.appservice.IDocStatisticsAppService;
|
||||
import com.openhis.web.document.dto.DocStatisticsDto;
|
||||
import com.openhis.web.document.dto.DocStatisticsQueryParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 文档模板 业务实现类
|
||||
@@ -34,23 +39,23 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
|
||||
@Resource
|
||||
private DocStatisticsMapper docStatisticsMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public R<?> createOrUpdte(List<DocStatisticsDto> docStatisticsList) {
|
||||
if (docStatisticsList.size() == 0) {
|
||||
return R.ok();
|
||||
}
|
||||
//根据recordId和statisticDefinitionId判断是否存在,存在则更新,不存在则新增
|
||||
// 根据recordId和statisticDefinitionId判断是否存在,存在则更新,不存在则新增
|
||||
LambdaQueryWrapper<DocStatistics> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(DocStatistics::getRecordId, docStatisticsList.get(0).getRecordId());
|
||||
// queryWrapper.eq(DocStatistics::getStatisticDefinitionId, docStatisticsList.get(0).getStatisticDefinitionId());
|
||||
// queryWrapper.eq(DocStatistics::getStatisticDefinitionId,
|
||||
// docStatisticsList.get(0).getStatisticDefinitionId());
|
||||
List<DocStatistics> docStatisticsOldList = docStatisticsService.list(queryWrapper);
|
||||
if (docStatisticsOldList.size() > 0) {
|
||||
//批量删除
|
||||
// 批量删除
|
||||
docStatisticsService.removeByIds(docStatisticsOldList.stream().map(DocStatistics::getId).toList());
|
||||
}
|
||||
List<DocStatistics> docStatisticsInsertList = new ArrayList<>();
|
||||
//批量新增
|
||||
// 批量新增
|
||||
for (DocStatisticsDto docStatisticsDto : docStatisticsList) {
|
||||
DocStatistics docStatistics = new DocStatistics();
|
||||
docStatistics.setRecordId(docStatisticsDto.getRecordId());
|
||||
@@ -62,6 +67,7 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
|
||||
docStatistics.setValue(docStatisticsDto.getValue());
|
||||
docStatistics.setRecordTime(docStatisticsDto.getRecordTime());
|
||||
docStatistics.setSource(docStatisticsDto.getSource());
|
||||
docStatistics.setDefinitionId(docStatisticsDto.getDefinitionId());
|
||||
docStatisticsInsertList.add(docStatistics);
|
||||
}
|
||||
boolean result = docStatisticsService.saveBatch(docStatisticsInsertList);
|
||||
@@ -74,7 +80,15 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
|
||||
|
||||
@Override
|
||||
public R<?> delete(List<Long> ids) {
|
||||
return null;
|
||||
LambdaUpdateWrapper<DocStatistics> wrapper = new LambdaUpdateWrapper<>();
|
||||
wrapper.in(DocStatistics::getRecordId, ids);
|
||||
wrapper.set(DocStatistics::getDeleteFlag, "1");
|
||||
boolean update = docStatisticsService.update(wrapper);
|
||||
if (update) {
|
||||
return R.ok();
|
||||
} else {
|
||||
return R.fail("删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -106,19 +120,19 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<?> getStatisticsList(DocStatisticsQueryParam queryParam, Integer isPage, Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request) {
|
||||
public R<?> getStatisticsList(DocStatisticsQueryParam queryParam, Integer isPage, Integer pageNo, Integer pageSize,
|
||||
String searchKey, HttpServletRequest request) {
|
||||
// 1. 分页查询逻辑
|
||||
if (isPage != null && isPage == 1) {
|
||||
QueryWrapper<DocStatistics> queryWrapper = HisQueryUtils.buildQueryWrapper(
|
||||
queryParam, null, null, request);
|
||||
QueryWrapper<DocStatistics> queryWrapper = HisQueryUtils.buildQueryWrapper(queryParam, null, null, request);
|
||||
// 按记录时间倒序(最新记录在前)
|
||||
queryWrapper.lambda().orderByDesc(DocStatistics::getRecordTime);
|
||||
|
||||
Page<DocStatisticsDto> recordPage = HisPageUtils.selectPage(
|
||||
docStatisticsMapper, queryWrapper, pageNo, pageSize, DocStatisticsDto.class);
|
||||
Page<DocStatisticsDto> recordPage =
|
||||
HisPageUtils.selectPage(docStatisticsMapper, queryWrapper, pageNo, pageSize, DocStatisticsDto.class);
|
||||
return R.ok(recordPage, "获取患者文书统计数据成功");
|
||||
}
|
||||
//2. 不分页查询逻辑
|
||||
// 2. 不分页查询逻辑
|
||||
else {
|
||||
LambdaQueryWrapper<DocStatistics> queryWrapper = new LambdaQueryWrapper<>();
|
||||
// 患者ID查询条件
|
||||
@@ -148,4 +162,48 @@ public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
|
||||
return R.ok(dtoList, "获取患者文书统计数据成功");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据病历ID、病人ID和体温单ID获取温度单信息
|
||||
*
|
||||
* @param encounterId 病历ID
|
||||
* @param patientId 病人ID
|
||||
* @param tempId 体温单ID
|
||||
* @return 体温单信息
|
||||
*/
|
||||
@Override
|
||||
public List<DocStatisticsDto> getStatisticsListByEncounterIdAndPatientId(Long encounterId, Long patientId,
|
||||
Long tempId) {
|
||||
List<DocStatistics> statisticsList =
|
||||
docStatisticsMapper.getTempList(encounterId, patientId, tempId, DocDefinitionEnum.TEMPERATURE.getValue());
|
||||
// 实体转DTO
|
||||
List<DocStatisticsDto> dtoList = new ArrayList<>();
|
||||
for (DocStatistics statistics : statisticsList) {
|
||||
DocStatisticsDto dto = new DocStatisticsDto();
|
||||
BeanUtils.copyProperties(statistics, dto);
|
||||
dtoList.add(dto);
|
||||
}
|
||||
return dtoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存/更新入院体征
|
||||
*
|
||||
* @param docStatisticsDtoList 入院体征list
|
||||
*/
|
||||
@Override
|
||||
public void saveOrUpdateAdmissionSigns(List<DocStatisticsDto> docStatisticsDtoList) {
|
||||
// 实体类 转换
|
||||
List<DocStatistics> docStatisticsList = docStatisticsDtoList.stream().map(item -> {
|
||||
DocStatistics statistics = new DocStatistics();
|
||||
BeanUtils.copyProperties(item, statistics);
|
||||
return statistics;
|
||||
}).toList();
|
||||
// 需要删除的
|
||||
List<DocStatistics> removeList = docStatisticsList.stream().filter(item -> item.getId() != null).toList();
|
||||
// 需要新增的
|
||||
List<DocStatistics> addList = docStatisticsList.stream().filter(item -> item.getId() == null).toList();
|
||||
docStatisticsService.removeBatchByIds(removeList.stream().map(DocStatistics::getId).toList());
|
||||
docStatisticsService.saveBatch(addList);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
package com.openhis.web.document.appservice.impl;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
@@ -17,14 +26,8 @@ import com.openhis.web.document.appservice.IDocStatisticsDefinitionAppService;
|
||||
import com.openhis.web.document.dto.DocStatisticsDefinitionDto;
|
||||
import com.openhis.web.document.dto.OptionDto;
|
||||
import com.openhis.web.document.mapper.DocStatisticsDefinitionAppMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 文档模板 业务实现类
|
||||
@@ -41,6 +44,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
private DocStatisticsDefinitionAppMapper docStatisticsDefinitionAppMapper;
|
||||
@Autowired
|
||||
private RedisCache redisCache;
|
||||
|
||||
@Override
|
||||
public R<?> createOrEdit(DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
|
||||
if (docStatisticsDefinitionDto == null) {
|
||||
@@ -67,7 +71,8 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
}
|
||||
}
|
||||
// 区分新增/编辑逻辑
|
||||
return docStatisticsDefinitionDto.getId() == null ? add(docStatisticsDefinitionDto) : update(docStatisticsDefinitionDto);
|
||||
return docStatisticsDefinitionDto.getId() == null ? add(docStatisticsDefinitionDto)
|
||||
: update(docStatisticsDefinitionDto);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,6 +102,8 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
docStatisticsDefinition.setUnit(docStatisticsDefinitionDto.getUnit());
|
||||
docStatisticsDefinition.setDictType(docStatisticsDefinitionDto.getDictType());
|
||||
docStatisticsDefinition.setDictName(docStatisticsDefinitionDto.getDictName());
|
||||
// 新增字段:类型代码 例:003-体温
|
||||
docStatisticsDefinition.setTypeCode(docStatisticsDefinitionDto.getTypeCode());
|
||||
boolean saveResult = iDocStatisticsDefinitionService.save(docStatisticsDefinition);
|
||||
if (saveResult) {
|
||||
return R.ok("文档统计定义新增成功");
|
||||
@@ -113,7 +120,8 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
return R.fail(checkResult);
|
||||
}
|
||||
// 校验待更新数据是否存在
|
||||
DocStatisticsDefinition existingData = iDocStatisticsDefinitionService.getById(docStatisticsDefinitionDto.getId());
|
||||
DocStatisticsDefinition existingData =
|
||||
iDocStatisticsDefinitionService.getById(docStatisticsDefinitionDto.getId());
|
||||
if (existingData == null) {
|
||||
return R.fail("更新文档统计定义失败,目标数据不存在");
|
||||
}
|
||||
@@ -128,6 +136,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
existingData.setUnit(docStatisticsDefinitionDto.getUnit());
|
||||
existingData.setDictType(docStatisticsDefinitionDto.getDictType());
|
||||
existingData.setDictName(docStatisticsDefinitionDto.getDictName());
|
||||
existingData.setTypeCode(docStatisticsDefinitionDto.getTypeCode());
|
||||
boolean updateResult = iDocStatisticsDefinitionService.updateById(existingData);
|
||||
if (updateResult) {
|
||||
// 同步更新选项列表
|
||||
@@ -157,22 +166,22 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
/**
|
||||
* 分页查询列表-不包含options(分页)
|
||||
*
|
||||
* @param pageNo 页码
|
||||
* @param pageSize 每页条数
|
||||
* @param pageNo 页码
|
||||
* @param pageSize 每页条数
|
||||
* @param searchKey 搜索关键词
|
||||
* @param request 请求对象
|
||||
* @param request 请求对象
|
||||
* @return 分页结果
|
||||
*/
|
||||
@Override
|
||||
public R<?> getPageList(Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request) {
|
||||
// Map<String, Object> keyMap = redisCache.getAllDictDataWithKeys(CacheConstants.SYS_DICT_KEY);
|
||||
// Map<String, Object> keyMap = redisCache.getAllDictDataWithKeys(CacheConstants.SYS_DICT_KEY);
|
||||
// 构建查询条件(支持多字段搜索)
|
||||
QueryWrapper<DocStatisticsDefinition> queryWrapper = HisQueryUtils.buildQueryWrapper(
|
||||
null, searchKey, new HashSet<>(Arrays.asList("name", "code")), request);
|
||||
QueryWrapper<DocStatisticsDefinition> queryWrapper =
|
||||
HisQueryUtils.buildQueryWrapper(null, searchKey, new HashSet<>(Arrays.asList("name", "code")), request);
|
||||
// 按记录时间倒序(最新记录在前)
|
||||
queryWrapper.lambda().orderByDesc(DocStatisticsDefinition::getDisplayOrder);
|
||||
Page<DocStatisticsDefinitionDto> recordPage = HisPageUtils.selectPage(
|
||||
docStatisticsDefinitionMapper, queryWrapper, pageNo, pageSize, DocStatisticsDefinitionDto.class);
|
||||
Page<DocStatisticsDefinitionDto> recordPage = HisPageUtils.selectPage(docStatisticsDefinitionMapper,
|
||||
queryWrapper, pageNo, pageSize, DocStatisticsDefinitionDto.class);
|
||||
// 转换为分页结果
|
||||
return R.ok(recordPage, "文档统计定义列表获取成功");
|
||||
}
|
||||
@@ -185,7 +194,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
*/
|
||||
@Override
|
||||
public List<DocStatisticsDefinitionDto> getList(Integer isStatistics) {
|
||||
Map<String, Object> keyMap = redisCache.getAllDictDataWithKeys(CacheConstants.SYS_DICT_KEY);
|
||||
Map<String, Object> keyMap = redisCache.getAllDictDataWithKeys(CacheConstants.SYS_DICT_KEY);
|
||||
LambdaQueryWrapper<DocStatisticsDefinition> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (isStatistics != null) {
|
||||
queryWrapper.eq(DocStatisticsDefinition::getIsStatistics, isStatistics);
|
||||
@@ -199,10 +208,11 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DocStatisticsDefinitionDto> getListWithOptionList(Integer isStatistics) {
|
||||
//从redis中获取所有字典数据
|
||||
Map<String, Object> keyMap = redisCache.getAllDictDataWithKeys(CacheConstants.SYS_DICT_KEY);
|
||||
// 从redis中获取所有字典数据
|
||||
Map<String, Object> keyMap = redisCache.getAllDictDataWithKeys(CacheConstants.SYS_DICT_KEY);
|
||||
LambdaQueryWrapper<DocStatisticsDefinition> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (isStatistics != null) {
|
||||
queryWrapper.eq(DocStatisticsDefinition::getIsStatistics, isStatistics);
|
||||
@@ -212,15 +222,16 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
for (DocStatisticsDefinition data : dataList) {
|
||||
DocStatisticsDefinitionDto dto = new DocStatisticsDefinitionDto();
|
||||
BeanUtils.copyProperties(data, dto);
|
||||
if(keyMap.containsKey(CacheConstants.SYS_DICT_KEY+data.getDictType()))
|
||||
{
|
||||
List<SysDictData> dictData = (List<SysDictData>) keyMap.get(CacheConstants.SYS_DICT_KEY+data.getDictType());
|
||||
if (keyMap.containsKey(CacheConstants.SYS_DICT_KEY + data.getDictType())) {
|
||||
List<SysDictData> dictData =
|
||||
(List<SysDictData>)keyMap.get(CacheConstants.SYS_DICT_KEY + data.getDictType());
|
||||
dto.setOptionList(dictData);
|
||||
}
|
||||
resultList.add(dto);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文档统计定义选项列表并按指定格式返回
|
||||
*
|
||||
@@ -237,8 +248,8 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
}
|
||||
|
||||
// 3. 按code字段分组
|
||||
Map<String, List<OptionDto>> groupCodeMap = optionDtoList.stream()
|
||||
.collect(Collectors.groupingBy(OptionDto::getCode));
|
||||
Map<String, List<OptionDto>> groupCodeMap =
|
||||
optionDtoList.stream().collect(Collectors.groupingBy(OptionDto::getCode));
|
||||
|
||||
// 4. 准备最终返回的结果列表
|
||||
List<Map<String, Object>> resultList = new ArrayList<>();
|
||||
@@ -260,8 +271,7 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
String listKey = code + "List";
|
||||
|
||||
// 检查分组中是否存在任何optionId为null的元素
|
||||
boolean hasNullOptionId = optionDtos.stream()
|
||||
.anyMatch(dto -> dto.getOptionId() == null);
|
||||
boolean hasNullOptionId = optionDtos.stream().anyMatch(dto -> dto.getOptionId() == null);
|
||||
|
||||
// 如果存在null的optionId,返回空集合;否则正常处理
|
||||
List<Map<String, Object>> optionList;
|
||||
@@ -269,14 +279,12 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
optionList = new ArrayList<>(); // 返回空集合
|
||||
} else {
|
||||
// 正常转换有效元素
|
||||
optionList = optionDtos.stream()
|
||||
.map(dto -> {
|
||||
Map<String, Object> optionMap = new HashMap<>();
|
||||
optionMap.put("id", dto.getOptionId().toString());
|
||||
optionMap.put("option", dto.getOption());
|
||||
return optionMap;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
optionList = optionDtos.stream().map(dto -> {
|
||||
Map<String, Object> optionMap = new HashMap<>();
|
||||
optionMap.put("id", dto.getOptionId().toString());
|
||||
optionMap.put("option", dto.getOption());
|
||||
return optionMap;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// 添加列表到结果中(即使是空集合)
|
||||
@@ -287,7 +295,6 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
return R.ok(resultList, "文档统计定义选项列表获取成功");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public R<?> deleteDocStatisticsDefinition(Long id) {
|
||||
if (id == null) {
|
||||
@@ -301,6 +308,4 @@ public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
package com.openhis.web.document.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.common.enums.DocPermissionEnum;
|
||||
import com.openhis.common.enums.DocTypeEnum;
|
||||
@@ -8,8 +15,10 @@ import com.openhis.web.document.appservice.IDocDefinitionAppService;
|
||||
import com.openhis.web.document.dto.DocDefinitionDto;
|
||||
import com.openhis.web.document.dto.DocDefinitonParam;
|
||||
import com.openhis.web.document.util.EnumUtil;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
<<<<<<< HEAD
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -17,9 +26,11 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
=======
|
||||
>>>>>>> v1.3
|
||||
|
||||
/**
|
||||
* 文书定义 controller
|
||||
* 文书定义 controller
|
||||
*
|
||||
* @author wanghaiming
|
||||
* @date 2025-08-12
|
||||
@@ -45,8 +56,13 @@ public class DocDefinitionController {
|
||||
|
||||
// 获取权限枚举列表
|
||||
map.put("permissions", EnumUtil.toMapList(DocPermissionEnum.class));
|
||||
<<<<<<< HEAD
|
||||
//使用范围枚举
|
||||
List<String> noInUseCodes=new ArrayList<>();
|
||||
=======
|
||||
// 使用范围枚举
|
||||
List<String> noInUseCodes = new ArrayList<>();
|
||||
>>>>>>> v1.3
|
||||
noInUseCodes.add(DocUseRangeEnum.USE_BY_SELF.getCode());
|
||||
map.put("useRanges", EnumUtil.toMapListFilter(DocUseRangeEnum.class, noInUseCodes));
|
||||
return R.ok(map);
|
||||
@@ -110,4 +126,15 @@ public class DocDefinitionController {
|
||||
return iDocDefinitionAppService.getTreeList(docDefinitonParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文书ID
|
||||
*
|
||||
* @param menuEnum 来源类型
|
||||
* @return 文书列表
|
||||
*/
|
||||
@GetMapping("/getDefinitionId")
|
||||
public R<?> getDefinitionId(@RequestParam("menuEnum") Integer menuEnum) {
|
||||
return iDocDefinitionAppService.getDefinitionId(menuEnum);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
package com.openhis.web.document.controller;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.common.enums.DocStatusEnum;
|
||||
import com.openhis.common.enums.DocTypeEnum;
|
||||
@@ -8,17 +16,12 @@ import com.openhis.web.document.dto.DocRecordDto;
|
||||
import com.openhis.web.document.dto.DocRecordPatientQueryParam;
|
||||
import com.openhis.web.document.dto.DocRecordQueryParam;
|
||||
import com.openhis.web.document.util.EnumUtil;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 文书记录 controller
|
||||
* 文书记录 controller
|
||||
*
|
||||
* @author wanghaiming
|
||||
*/
|
||||
@@ -65,6 +68,17 @@ public class DocRecordController {
|
||||
return docRecordAppService.updateRecord(docRecordDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增或编辑记录
|
||||
*
|
||||
* @param docRecordDto 文书记录信息
|
||||
* @return R
|
||||
*/
|
||||
@PostMapping("/saveOrUpdateRecord")
|
||||
public R<?> saveOrUpdateRecord(@RequestBody DocRecordDto docRecordDto) {
|
||||
return docRecordAppService.saveOrUpdateRecord(docRecordDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文书为编辑状态
|
||||
*
|
||||
@@ -77,44 +91,56 @@ public class DocRecordController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据患者ID或就诊ID获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理
|
||||
* 需返回患者具体信息的列表,请使用getPatientRecordList
|
||||
* 根据患者ID或就诊ID获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理 需返回患者具体信息的列表,请使用getPatientRecordList
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @param pageNo 页码
|
||||
* @param pageSize 页大小
|
||||
* @param searchKey 搜索关键字
|
||||
* @param request 请求
|
||||
* 1.IsPage 是否分页 0:不分页 1:分页
|
||||
* @param pageNo 页码
|
||||
* @param pageSize 页大小
|
||||
* @param searchKey 搜索关键字
|
||||
* @param request 请求 1.IsPage 是否分页 0:不分页 1:分页
|
||||
* @return R
|
||||
*/
|
||||
@GetMapping("/getRecordByEncounterIdList")
|
||||
R<?> getRecordByEncounterIdList(DocRecordQueryParam docRecordQueryParam,
|
||||
@RequestParam(value = "isPage", defaultValue = "1") Integer isPage,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(name = "searchKey", required = false) String searchKey, HttpServletRequest request) {
|
||||
return docRecordAppService.getRecordByEncounterIdList(docRecordQueryParam, isPage, pageNo, pageSize, searchKey, request);
|
||||
@RequestParam(value = "isPage", defaultValue = "1") Integer isPage,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(name = "searchKey", required = false) String searchKey, HttpServletRequest request) {
|
||||
return docRecordAppService.getRecordByEncounterIdList(docRecordQueryParam, isPage, pageNo, pageSize, searchKey,
|
||||
request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据患者ID或就诊ID以及时间获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理 需返回患者具体信息的列表,请使用getPatientRecordList
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @param recordTime 时间
|
||||
* @return R
|
||||
*/
|
||||
@GetMapping("/getRecordByEncounterIdAndTimeList")
|
||||
R<?> getRecordByEncounterIdAndTimeList(DocRecordQueryParam docRecordQueryParam,
|
||||
@RequestParam(value = "recordTime", required = false) String recordTime) {
|
||||
return docRecordAppService.getRecordByEncounterIdAndTimeList(docRecordQueryParam, recordTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 文书记录列表
|
||||
*
|
||||
* @param docRecordPatientQueryParam 文书记录查询参数
|
||||
* @param pageNo 页码
|
||||
* @param pageSize 页大小
|
||||
* @param searchKey 搜索关键字
|
||||
* @param request 请求
|
||||
* @param pageNo 页码
|
||||
* @param pageSize 页大小
|
||||
* @param searchKey 搜索关键字
|
||||
* @param request 请求
|
||||
* @return R
|
||||
*/
|
||||
@GetMapping("/getRecordPageList")
|
||||
R<?> getRecordPageList(DocRecordPatientQueryParam docRecordPatientQueryParam,
|
||||
@RequestParam(value = "primaryMenuEnumList", required = false) List<Integer> primaryMenuEnumList,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(name = "searchKey", required = false) String searchKey,
|
||||
HttpServletRequest request) {
|
||||
return docRecordAppService.getRecordPageList(docRecordPatientQueryParam, primaryMenuEnumList, pageNo, pageSize, searchKey, request);
|
||||
@RequestParam(value = "primaryMenuEnumList", required = false) List<Integer> primaryMenuEnumList,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(name = "searchKey", required = false) String searchKey, HttpServletRequest request) {
|
||||
return docRecordAppService.getRecordPageList(docRecordPatientQueryParam, primaryMenuEnumList, pageNo, pageSize,
|
||||
searchKey, request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,4 +163,39 @@ public class DocRecordController {
|
||||
return docRecordAppService.deleteRecord(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印
|
||||
*
|
||||
* @param recordId 文书分配信息ID列表
|
||||
*/
|
||||
@GetMapping("/record-print")
|
||||
R<?> print(@RequestParam Long recordId) {
|
||||
return docRecordAppService.recordPrint(recordId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据病历ID、病人ID和温度单ID获取体温单信息
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @return 体温单信息
|
||||
*/
|
||||
@GetMapping("/temperature-chart")
|
||||
R<?> temperatureChart(DocRecordQueryParam docRecordQueryParam) {
|
||||
return docRecordAppService.temperatureChart(docRecordQueryParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* 护理记录总结
|
||||
*
|
||||
* @param docRecordQueryParam 文书记录查询参数
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @return 护理记录总结
|
||||
*/
|
||||
@GetMapping("/summary")
|
||||
R<?> summaryNursingRecords(DocRecordQueryParam docRecordQueryParam,
|
||||
@RequestParam(value = "startTime", required = false, defaultValue = "") String startTime,
|
||||
@RequestParam(value = "endTime", required = false, defaultValue = "") String endTime) {
|
||||
return docRecordAppService.summaryNursingRecords(docRecordQueryParam, startTime, endTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,4 +59,8 @@ public class DocRecordDto {
|
||||
*/
|
||||
private String name;
|
||||
private String version;
|
||||
/**
|
||||
* 打印次数
|
||||
*/
|
||||
private Integer printCount = 0;
|
||||
}
|
||||
|
||||
@@ -61,5 +61,9 @@ public class DocStatisticsDefinitionDto {
|
||||
|
||||
/** 字典类型 */
|
||||
private String dictType;
|
||||
/**
|
||||
* 类型代码 例 003:体温
|
||||
*/
|
||||
private String typeCode;
|
||||
|
||||
}
|
||||
|
||||
@@ -52,5 +52,9 @@ public class DocStatisticsDto {
|
||||
* 记录来源
|
||||
*/
|
||||
private String source;
|
||||
/**
|
||||
* 文书ID
|
||||
*/
|
||||
private Long definitionId;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.openhis.web.document.dto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 温度、脉搏等生命体征信息
|
||||
*
|
||||
* @author swb
|
||||
* @date 2025-11-19
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class TrendChartsBig {
|
||||
/**
|
||||
* 图表信息
|
||||
* 体温,脉搏:有数据 其他:空
|
||||
*/
|
||||
private List<TrendChartsSmall> chartsSmalls = new ArrayList<TrendChartsSmall>();
|
||||
/**
|
||||
* 当前数据日期-住院日期 算出第几周(画面筛选上一周下一周用)
|
||||
*/
|
||||
private Integer weekNo;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.openhis.web.document.dto;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 体温单
|
||||
*
|
||||
* @author swb
|
||||
* @date 2025-11-19
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class TrendChartsOutput {
|
||||
/**
|
||||
* 住院日期 例:2024-09-04
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date hospDate;
|
||||
/**
|
||||
* 手术日期 例:2024-09-04
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date operaDate;
|
||||
/**
|
||||
* 出院日 例:2024-09-04
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date outDate;
|
||||
/**
|
||||
* 体温(003)、脉搏(002)
|
||||
*/
|
||||
private List<TrendChartsBig> temperaturePulses;
|
||||
/**
|
||||
* typeCode: '004':尿量 typeCode: '005':大便次数 typeCode: '006':摄入液量 typeCode: '007':排除液量 typeCode: '008':血压 typeCode:
|
||||
* '009':体重 typeCode: '010':术后天数
|
||||
*/
|
||||
private List<TrendChartsSmall> others;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.openhis.web.document.dto;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 图表信息
|
||||
*
|
||||
* @author swb
|
||||
* @date 2025-11-19
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = true)
|
||||
public class TrendChartsSmall {
|
||||
/**
|
||||
* 体温,脉搏:1(固定) 其他:null
|
||||
*/
|
||||
private Integer collectionMode;
|
||||
/**
|
||||
* 查询的日期 例:2024-09-06
|
||||
*/
|
||||
// 日期格式
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date date;
|
||||
/**
|
||||
* 每隔n小时测量的时间点 例:10:00:00
|
||||
*/
|
||||
private String times;
|
||||
/**
|
||||
* typeCode: '002':脉搏 typeCode: '003':体温 typeCode: '004':尿量 typeCode: '005':大便次数 typeCode: '006':摄入液量 typeCode:
|
||||
* '007':排除液量 typeCode: '008':血压 typeCode: '009':体重 typeCode: '010':术后天数
|
||||
*/
|
||||
private String typeCode;
|
||||
/**
|
||||
* 测量出的数据
|
||||
*/
|
||||
private String typeValue;
|
||||
/**
|
||||
* 当前数据日期-住院日期 算出第几周
|
||||
*/
|
||||
private Integer weekNo;
|
||||
/**
|
||||
* 其他项录入排序用,不参与任何计算与画面显示
|
||||
*/
|
||||
private String orderByDateTimes;
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
private String id;
|
||||
}
|
||||
@@ -1,22 +1,26 @@
|
||||
package com.openhis.web.document.util;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.openhis.web.document.appservice.IDocStatisticsDefinitionAppService;
|
||||
import com.openhis.web.document.dto.DocRecordDto;
|
||||
import com.openhis.web.document.dto.DocStatisticsDefinitionDto;
|
||||
import com.openhis.web.document.dto.DocStatisticsDto;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.stereotype.Component;
|
||||
import static com.core.framework.datasource.DynamicDataSourceContextHolder.log;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.core.framework.datasource.DynamicDataSourceContextHolder.log;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import com.core.common.utils.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.openhis.common.enums.TemperatureChartEnum;
|
||||
import com.openhis.web.document.appservice.IDocStatisticsDefinitionAppService;
|
||||
import com.openhis.web.document.dto.DocRecordDto;
|
||||
import com.openhis.web.document.dto.DocStatisticsDefinitionDto;
|
||||
import com.openhis.web.document.dto.DocStatisticsDto;
|
||||
|
||||
@Component
|
||||
public class ConvertToDocStatistics {
|
||||
@@ -24,12 +28,58 @@ public class ConvertToDocStatistics {
|
||||
IDocStatisticsDefinitionAppService docStatisticsDefinitionAppService;
|
||||
|
||||
/**
|
||||
* 将文档记录转换为统计DTO列表的工具方法
|
||||
* 支持两种JSON结构:
|
||||
* 1. 简单键值对:{"目标code": 值, "recordTime": "yyyy-MM-dd HH:mm:ss"}
|
||||
* 2. 嵌套Item列表:{"目标code+Item": [{"目标code": 值1}, {"目标code": 值2}],"recordTime": "yyyy-MM-dd HH:mm:ss"}
|
||||
* 3. 记录 Time 字段:{"目标code+Item": [{"目标code": 值1, "recordTime": "yyyy-MM-dd HH:mm:ss"}, {"目标code": 值2, "recordTime": "yyyy-MM-dd HH:mm:ss"}]}
|
||||
* 4. 记录 Time 字段:{"目标code": 值, "recordTime": "yyyy-MM-dd HH:mm:ss", "目标code+Item": [{"目标code": 值1, "recordTime": "yyyy-MM-dd HH:mm:ss"}, {"目标code": 值2, "recordTime": "yyyy-MM-dd HH:mm:ss"}]}
|
||||
* 解析jsonObject中的数组(一层)
|
||||
* 若要多层解析,会存在key相同覆盖数据
|
||||
*
|
||||
* @param jsonObject jsonObject
|
||||
* @return JSONObject列表
|
||||
*/
|
||||
public List<JSONObject> convertToJSONObjList(JSONObject jsonObject) {
|
||||
List<JSONObject> jsonObjectList = new ArrayList<>();
|
||||
List<String> keys = new ArrayList<>();
|
||||
// 取出所有key
|
||||
Set<String> keySet = jsonObject.keySet();
|
||||
for (String key : keySet) {
|
||||
// 取出key对应的数据
|
||||
Object obj = jsonObject.get(key);
|
||||
// 如果obj是数组并且是JSONObject数组,数组遍历添加到List
|
||||
if (obj instanceof JSONArray) {
|
||||
if ((!((JSONArray)obj).isEmpty()) && (((JSONArray)obj).get(0) instanceof JSONObject)) {
|
||||
List<JSONObject> javaList = ((JSONArray)obj).toJavaList(JSONObject.class);
|
||||
jsonObjectList.addAll(javaList);
|
||||
keys.add(key);
|
||||
}
|
||||
}
|
||||
// 如果是对象,添加到jsonObjectList
|
||||
if (obj instanceof JSONObject) {
|
||||
jsonObjectList.add((JSONObject)obj);
|
||||
keys.add(key);
|
||||
}
|
||||
}
|
||||
// 移除 对象和数组
|
||||
keys.forEach(jsonObject::remove);
|
||||
// 将原本JSONObject添加到集合
|
||||
jsonObjectList.add(jsonObject);
|
||||
// 格式化时间点
|
||||
for (JSONObject object : jsonObjectList) {
|
||||
if (object.containsKey(TemperatureChartEnum.TIME_POINT.getTypeCode())) {
|
||||
// 前端传来的时间点格式 0200,转换为02:00:00
|
||||
String timePointValue = (String)object.get(TemperatureChartEnum.TIME_POINT.getTypeCode());
|
||||
if (timePointValue != null && timePointValue.matches("\\d{4}")) {
|
||||
object.put(TemperatureChartEnum.TIME_POINT.getTypeCode(),
|
||||
timePointValue.substring(0, 2) + ":00:00");
|
||||
}
|
||||
}
|
||||
}
|
||||
return jsonObjectList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文档记录转换为统计DTO列表的工具方法 支持两种JSON结构: 1. 简单键值对:{"目标code": 值, "recordTime": "yyyy-MM-dd HH:mm:ss"} 2.
|
||||
* 嵌套Item列表:{"目标code+Item": [{"目标code": 值1}, {"目标code": 值2}],"recordTime": "yyyy-MM-dd HH:mm:ss"} 3.
|
||||
* 记录Time字段:{"目标code+Item": [{"目标code": 值1, "recordTime": "yyyy-MM-dd HH:mm:ss"}, {"目标code": 值2, "recordTime":
|
||||
* "yyyy-MM-dd HH:mm:ss"}]} 4. 记录Time字段:{"目标code": 值, "recordTime": "yyyy-MM-dd HH:mm:ss", "目标code+Item":
|
||||
* [{"目标code": 值1, "recordTime": "yyyy-MM-dd HH:mm:ss"}, {"目标code": 值2, "recordTime": "yyyy-MM-dd HH:mm:ss"}]}
|
||||
* 日期类型使用java.util.Date
|
||||
*/
|
||||
public List<DocStatisticsDto> convertToStatisticsDtoList(DocRecordDto docRecordDto) {
|
||||
@@ -53,66 +103,79 @@ public class ConvertToDocStatistics {
|
||||
|
||||
// 解析JSON字符串为JSONObject(方便操作嵌套结构)
|
||||
JSONObject contentJsonObj = parseJson(contentJson);
|
||||
// 如果JSON解析失败(返回null),直接返回空列表
|
||||
if (contentJsonObj == null) {
|
||||
return statisticsDtoList;
|
||||
}
|
||||
|
||||
// 遍历每个统计项定义,解析对应的值
|
||||
for (DocStatisticsDefinitionDto definition : definitionList) {
|
||||
// 当前需要解析的目标字段code(如"BQ"、"DrugCode")
|
||||
String targetCode = definition.getCode();
|
||||
|
||||
// 场景1:先尝试解析顶级键值对结构(如{"BQ": 123})
|
||||
if (contentJsonObj.containsKey(targetCode)) {
|
||||
// 提取值并转换为字符串
|
||||
String value = String.valueOf(contentJsonObj.get(targetCode));
|
||||
Date recordTime = docRecordDto.getRecordTime();
|
||||
// 创建DTO并添加到结果列表
|
||||
addSingleDto(statisticsDtoList, definition, docRecordDto, value,
|
||||
recordTime);
|
||||
// 处理完当前统计项,继续下一个
|
||||
continue;
|
||||
for (JSONObject jsonObject : convertToJSONObjList(contentJsonObj)) {
|
||||
contentJsonObj = jsonObject;
|
||||
// 如果JSON解析失败(返回null),直接返回空列表
|
||||
if (contentJsonObj == null) {
|
||||
return statisticsDtoList;
|
||||
}
|
||||
// 遍历每个统计项定义,解析对应的值
|
||||
for (DocStatisticsDefinitionDto definition : definitionList) {
|
||||
// 当前需要解析的目标字段code(如"BQ"、"DrugCode")
|
||||
String targetCode = definition.getCode();
|
||||
|
||||
// 场景2:如果顶级键不存在,尝试解析嵌套的Item列表
|
||||
// 列表字段名规则:目标code + "Item"(如code=BQ → 列表字段名=BQItem)
|
||||
String itemListKey = targetCode + "Item";
|
||||
// 从JSON中获取对应的列表
|
||||
JSONArray itemArray = contentJsonObj.getJSONArray(itemListKey);
|
||||
|
||||
// 判断列表是否存在且不为空
|
||||
if (itemArray != null && !itemArray.isEmpty()) {
|
||||
// 遍历列表中的每个元素(每个元素是一个JSONObject)
|
||||
for (int i = 0; i < itemArray.size(); i++) {
|
||||
JSONObject itemObj = itemArray.getJSONObject(i);
|
||||
// 检查元素是否包含目标code
|
||||
if (itemObj != null && itemObj.containsKey(targetCode)) {
|
||||
// 提取当前元素的目标值
|
||||
String value = String.valueOf(itemObj.get(targetCode));
|
||||
Date recordTime = new Date();
|
||||
if (itemObj.containsKey("recordTime")) {
|
||||
recordTime = itemObj.getDate("recordTime");
|
||||
} else if (contentJsonObj.containsKey("recordTime")) {
|
||||
recordTime = contentJsonObj.getDate("recordTime");
|
||||
} else {
|
||||
recordTime = docRecordDto.getRecordTime();
|
||||
// 场景1:先尝试解析顶级键值对结构(如{"BQ": 123})
|
||||
if (contentJsonObj.containsKey(targetCode)) {
|
||||
// 提取值并转换为字符串
|
||||
String value = String.valueOf(contentJsonObj.get(targetCode));
|
||||
Date recordTime = docRecordDto.getRecordTime();
|
||||
// 判断jsonObject中是否有timePoint、recordTime字段以及值,有则取出与拼接
|
||||
try {
|
||||
boolean timePoint = contentJsonObj.containsKey("timePoint");
|
||||
boolean date = contentJsonObj.containsKey("recordTime");
|
||||
String dateValue = (String)contentJsonObj.get("recordTime");
|
||||
String timePointValue = (String)contentJsonObj.get("timePoint");
|
||||
if (timePoint && date && !dateValue.isEmpty() && !timePointValue.isEmpty()) {
|
||||
// 格式化 例:2025-11-20 13:34:56
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
recordTime = format.parse(dateValue + " " + timePointValue);
|
||||
}
|
||||
// 创建DTO并添加到结果列表
|
||||
addSingleDto(statisticsDtoList, definition, docRecordDto, value,
|
||||
recordTime);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 创建DTO并添加到结果列表
|
||||
addSingleDto(statisticsDtoList, definition, docRecordDto, value, recordTime);
|
||||
// 处理完当前统计项,继续下一个
|
||||
continue;
|
||||
}
|
||||
// 日志提示:如果列表存在但未找到匹配的code
|
||||
if (statisticsDtoList.isEmpty()) {
|
||||
log.warn("列表{}中未找到包含{}的元素,可能数据格式不匹配", itemListKey, targetCode);
|
||||
|
||||
// 场景2:如果顶级键不存在,尝试解析嵌套的Item列表
|
||||
// 列表字段名规则:目标code + "Item"(如code=BQ → 列表字段名=BQItem)
|
||||
String itemListKey = targetCode + "Item";
|
||||
// 从JSON中获取对应的列表
|
||||
JSONArray itemArray = contentJsonObj.getJSONArray(itemListKey);
|
||||
|
||||
// 判断列表是否存在且不为空
|
||||
if (itemArray != null && !itemArray.isEmpty()) {
|
||||
// 遍历列表中的每个元素(每个元素是一个JSONObject)
|
||||
for (int i = 0; i < itemArray.size(); i++) {
|
||||
JSONObject itemObj = itemArray.getJSONObject(i);
|
||||
// 检查元素是否包含目标code
|
||||
if (itemObj != null && itemObj.containsKey(targetCode)) {
|
||||
// 提取当前元素的目标值
|
||||
String value = String.valueOf(itemObj.get(targetCode));
|
||||
Date recordTime = new Date();
|
||||
if (itemObj.containsKey("recordTime")) {
|
||||
recordTime = itemObj.getDate("recordTime");
|
||||
} else if (contentJsonObj.containsKey("recordTime")) {
|
||||
recordTime = contentJsonObj.getDate("recordTime");
|
||||
} else {
|
||||
recordTime = docRecordDto.getRecordTime();
|
||||
}
|
||||
// 创建DTO并添加到结果列表
|
||||
addSingleDto(statisticsDtoList, definition, docRecordDto, value, recordTime);
|
||||
}
|
||||
}
|
||||
// 日志提示:如果列表存在但未找到匹配的code
|
||||
if (statisticsDtoList.isEmpty()) {
|
||||
log.warn("列表{}中未找到包含{}的元素,可能数据格式不匹配", itemListKey, targetCode);
|
||||
}
|
||||
} else {
|
||||
// 日志提示:未找到对应的Item列表或列表为空
|
||||
log.error("未找到列表{}或列表为空,无法解析统计项: {}", itemListKey, targetCode);
|
||||
}
|
||||
} else {
|
||||
// 日志提示:未找到对应的Item列表或列表为空
|
||||
log.error("未找到列表{}或列表为空,无法解析统计项: {}", itemListKey, targetCode);
|
||||
}
|
||||
}
|
||||
|
||||
return statisticsDtoList;
|
||||
}
|
||||
|
||||
@@ -140,32 +203,33 @@ public class ConvertToDocStatistics {
|
||||
/**
|
||||
* 工具方法:创建单个统计DTO并添加到列表
|
||||
*
|
||||
* @param dtoList 目标DTO列表
|
||||
* @param definition 统计项定义
|
||||
* @param dtoList 目标DTO列表
|
||||
* @param definition 统计项定义
|
||||
* @param docRecordDto 文档记录DTO
|
||||
* @param value 解析出的统计值
|
||||
* @param recordTime 记录时间
|
||||
* @param value 解析出的统计值
|
||||
* @param recordTime 记录时间
|
||||
*/
|
||||
private void addSingleDto(List<DocStatisticsDto> dtoList,
|
||||
DocStatisticsDefinitionDto definition,
|
||||
DocRecordDto docRecordDto,
|
||||
String value,
|
||||
Date recordTime) {
|
||||
// 创建统计DTO对象
|
||||
DocStatisticsDto dto = new DocStatisticsDto();
|
||||
// 设置统计值和关联的统计项定义信息
|
||||
dto.setValue(value);
|
||||
dto.setStatisticDefinitionCode(definition.getCode());
|
||||
dto.setStatisticDefinitionId(definition.getId());
|
||||
// 设置关联的文档记录信息
|
||||
dto.setRecordId(docRecordDto.getId());
|
||||
dto.setEncounterId(docRecordDto.getEncounterId());
|
||||
dto.setPatientId(docRecordDto.getPatientId());
|
||||
dto.setOrganizationId(docRecordDto.getOrganizationId());
|
||||
dto.setRecordTime(recordTime);
|
||||
dto.setSource(docRecordDto.getSource());
|
||||
// 将创建好的DTO添加到结果列表
|
||||
dtoList.add(dto);
|
||||
private void addSingleDto(List<DocStatisticsDto> dtoList, DocStatisticsDefinitionDto definition,
|
||||
DocRecordDto docRecordDto, String value, Date recordTime) {
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
// 创建统计DTO对象
|
||||
DocStatisticsDto dto = new DocStatisticsDto();
|
||||
// 设置统计值和关联的统计项定义信息
|
||||
dto.setValue(value);
|
||||
dto.setStatisticDefinitionCode(definition.getCode());
|
||||
dto.setStatisticDefinitionId(definition.getId());
|
||||
// 设置关联的文档记录信息
|
||||
dto.setRecordId(docRecordDto.getId());
|
||||
dto.setEncounterId(docRecordDto.getEncounterId());
|
||||
dto.setPatientId(docRecordDto.getPatientId());
|
||||
dto.setOrganizationId(docRecordDto.getOrganizationId());
|
||||
dto.setRecordTime(recordTime);
|
||||
dto.setSource(docRecordDto.getSource());
|
||||
// 文书ID
|
||||
dto.setDefinitionId(docRecordDto.getDefinitionId());
|
||||
// 将创建好的DTO添加到结果列表
|
||||
dtoList.add(dto);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.openhis.web.document.util;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 体温单手术日计算工具类 依据国家最新护理文件书写规范
|
||||
*
|
||||
* @author swb
|
||||
* @date 2025-11-22
|
||||
*/
|
||||
public class OperationDayCalculator {
|
||||
|
||||
/**
|
||||
* 计算指定日期对应的手术日记录
|
||||
*
|
||||
* @param operationDates 手术日期列表(按时间顺序排列)
|
||||
* @param targetDate 要计算的目标日期
|
||||
* @return 手术日记录字符串,如 "0", "3", "14+", "2/3"
|
||||
*/
|
||||
public static String calculateOperationDay(List<LocalDate> operationDates, LocalDate targetDate) {
|
||||
if (operationDates == null || operationDates.isEmpty()) {
|
||||
// 无手术记录
|
||||
return "";
|
||||
}
|
||||
|
||||
// 过滤出在目标日期之前或当天的手术
|
||||
List<LocalDate> validOperations =
|
||||
operationDates.stream().filter(date -> !date.isAfter(targetDate)).collect(Collectors.toList());
|
||||
|
||||
if (validOperations.isEmpty()) {
|
||||
// 目标日期前无手术
|
||||
return "";
|
||||
}
|
||||
|
||||
// 多次手术情况(14天内进行第二次及以上手术)
|
||||
if (validOperations.size() >= 2) {
|
||||
LocalDate lastOperation = validOperations.get(validOperations.size() - 1);
|
||||
LocalDate prevOperation = validOperations.get(validOperations.size() - 2);
|
||||
|
||||
// 检查最后两次手术是否在14天内
|
||||
long daysBetween = ChronoUnit.DAYS.between(prevOperation, lastOperation);
|
||||
if (daysBetween <= 14) {
|
||||
return calculateMultipleOperations(validOperations, targetDate);
|
||||
}
|
||||
}
|
||||
|
||||
// 单次手术情况
|
||||
LocalDate operationDate = validOperations.get(validOperations.size() - 1);
|
||||
return calculateSingleOperation(operationDate, targetDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算单次手术的日期
|
||||
*/
|
||||
private static String calculateSingleOperation(LocalDate operationDate, LocalDate targetDate) {
|
||||
long days = ChronoUnit.DAYS.between(operationDate, targetDate);
|
||||
|
||||
if (days < 0) {
|
||||
// 手术前
|
||||
return "";
|
||||
} else if (days == 0) {
|
||||
// 手术当天
|
||||
return "0";
|
||||
} else if (days <= 14) {
|
||||
// 术后1-14天
|
||||
return String.valueOf(days);
|
||||
} else {
|
||||
// 术后超过14天
|
||||
return "14+";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算多次手术的日期
|
||||
*/
|
||||
private static String calculateMultipleOperations(List<LocalDate> operationDates, LocalDate targetDate) {
|
||||
List<String> dayParts = new ArrayList<>();
|
||||
|
||||
for (LocalDate opDate : operationDates) {
|
||||
long days = ChronoUnit.DAYS.between(opDate, targetDate);
|
||||
if (days >= 0) {
|
||||
dayParts.add(String.valueOf(days));
|
||||
}
|
||||
}
|
||||
|
||||
// 按规则:最近的手术天数作为分子,依次排列
|
||||
// 反转列表,使最新的手术天数在最前面
|
||||
List<String> reversedParts = new ArrayList<>();
|
||||
for (int i = dayParts.size() - 1; i >= 0; i--) {
|
||||
reversedParts.add(dayParts.get(i));
|
||||
}
|
||||
|
||||
return String.join("/", reversedParts);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user