Revert "Fix Bug #550: AI修复"

This reverts commit 16c42ca108.
This commit is contained in:
2026-05-27 08:59:07 +08:00
parent bd14563691
commit 9db5ced4e3
5432 changed files with 778638 additions and 171 deletions

View File

@@ -0,0 +1,49 @@
package com.openhis.web.document.appservice;
import com.core.common.core.domain.R;
import com.openhis.web.document.dto.DocDefinitionDto;
import com.openhis.web.document.dto.DocDefinitonParam;
/**
* 文书定义 应用Service
*/
public interface IDocDefinitionAppService {
/**
* 新增文书定义
*
* @param definitionDto
* @return
*/
R<?> addDefinition(DocDefinitionDto definitionDto);
/**
* 修改文书定义
*
* @param definitionDto
* @return
*/
R<?> updateDefinition(DocDefinitionDto definitionDto);
R<?> deleteDefinition(Long id);
/**
* 获取文书定义列表 树形结构
*
* @param param 条件参数
* @return
*/
R<?> getTreeList(DocDefinitonParam param);
R<?> getDefinitionDetailById(Long id);
DocDefinitionDto getDefinitionById(Long id);
/**
* 获取文书ID
*
* @param menuEnum 来源类型
* @return 文书列表
*/
R<?> getDefinitionId(Integer menuEnum);
}

View File

@@ -0,0 +1,39 @@
package com.openhis.web.document.appservice;
import com.core.common.core.domain.R;
import com.openhis.web.document.dto.DocDefinitionOrganizationDto;
/**
* 文书定义 应用Service
*/
public interface IDocDefinitionOrganizationAppService {
/**
* 新增文书分配科室列表
*
* @param organizationDto
* @return
*/
R<?> add(DocDefinitionOrganizationDto organizationDto);
/**
* 删除文书分配科室列表
*
* @param definitionId
* @param busNo
* @return
*/
R<?> delete(Long definitionId, String busNo);
/**
* 查询文书定义科室列表
*
* @param definitionId
* @param busNo
* @return
*/
R<?> getOrganizationIdlist(Long definitionId, String busNo);
R<?> updateOrganization(DocDefinitionOrganizationDto organizationDto);
}

View File

@@ -0,0 +1,97 @@
package com.openhis.web.document.appservice;
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.List;
/**
* 文书记录 应用Service
*/
public interface IDocRecordAppService {
// /**
// * 新增记录
// *
// * @param docRecordDto 文书记录信息
// * @return
// */
// R<?> createOrEditRecord(DocRecordDto docRecordDto);
R<?> addRecord(DocRecordDto docRecordDto);
R<?> updateRecord(DocRecordDto docRecordDto);
/**
* 根据患者ID或就诊ID获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理
*/
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);
/**
* 根据文书记录ID获取文书记录信息
*
* @param recordId 文书记录ID
* @return
*/
R<?> getRecordById(Long recordId);
R<?> setIsEdit(Long recordId);
/**
* 删除文书分配信息
*
* @param ids 删除文书分配信息ID列表
* @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);
}

View File

@@ -0,0 +1,42 @@
package com.openhis.web.document.appservice;
import com.core.common.core.domain.R;
import com.openhis.web.document.dto.DocStatisticsDto;
import com.openhis.web.document.dto.DocStatisticsQueryParam;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* 文档模板 业务接口
*/
public interface IDocStatisticsAppService {
public R<?> createOrUpdte(List<DocStatisticsDto> docStatisticsList);
public R<?> delete(List<Long> ids);
public R<?> queryByRecordId(Long recordId);
public R<?> queryByEncounterId(Long encounterId);
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);
}

View File

@@ -0,0 +1,57 @@
package com.openhis.web.document.appservice;
import com.core.common.core.domain.R;
import com.openhis.web.document.dto.DocStatisticsDefinitionDto;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* 文档模板 业务接口
*/
public interface IDocStatisticsDefinitionAppService {
/**
* 创建或更新文档模板
*
* @param docStatisticsDefinitionDto
*/
public R<?> createOrEdit(DocStatisticsDefinitionDto docStatisticsDefinitionDto);
public R<?> add(DocStatisticsDefinitionDto docStatisticsDefinitionDto);
public R<?> update(DocStatisticsDefinitionDto docStatisticsDefinitionDto);
/**
* 分页查询列表-不包含options 分页
*
* @return
*/
public R<?> getPageList(Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request);
/**
* 获取文档统计定义列表(不分页)
*
* @param isStatistics 是否统计
* @return 文档统计定义列表
*/
public List<DocStatisticsDefinitionDto> getList(Integer isStatistics);
List<DocStatisticsDefinitionDto> getListWithOptionList(Integer isStatistics);
/**
* 过时obsolete 获取文档统计定义选项列表并按指定格式返回 (key-value)
*
* @return 封装了处理结果的响应对象
*/
public R<?> getOptionList();
/**
* 删除文档模板
*
* @param id
*/
public R<?> deleteDocStatisticsDefinition(Long id);
}

View File

@@ -0,0 +1,25 @@
package com.openhis.web.document.appservice;
import com.core.common.core.domain.R;
import com.openhis.web.document.dto.DocTemplateDto;
import javax.servlet.http.HttpServletRequest;
/**
* 文书模板-一 业务接口
*/
public interface IDocTemplateAppService {
public R<?> add(DocTemplateDto docTemplateDto);
public R<?> delete(Long id);
public R<?> update(DocTemplateDto docTemplateDto);
public R<?> getById(Long id);
public R<?> getListByDefinitionId(Long definitionId);
public R<?> getPageList(Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request);
}

View File

@@ -0,0 +1,367 @@
package com.openhis.web.document.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.bean.BeanUtils;
import com.openhis.common.enums.AssignSeqEnum;
import com.openhis.common.enums.DocUseRangeEnum;
import com.openhis.document.domain.DocDefinition;
import com.openhis.document.domain.DocDefinitionOrganization;
import com.openhis.document.service.IDocDefinitionOrganizationService;
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.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;
@Slf4j
@Service
public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
@Resource
private IDocDefinitionService docDefinitionService;
@Resource
private IDocDefinitionOrganizationAppService docDefinitionOrganizationAppService;
@Resource
private IDocDefinitionOrganizationService docDefinitionOrganizationService;
@Resource
private DocDefinitionAppMapper docDefinitionAppMapper;
@Autowired(required = false)
private AssignSeqUtil assignSeqUtil;
/**
* 新增文书定义(含科室分配逻辑)
*/
@Override
public R<?> addDefinition(DocDefinitionDto definitionDto) {
// 1. 基础参数校验(按必填优先级排序)
if (definitionDto.getName() == null || definitionDto.getName().trim().isEmpty()) {
return R.fail("新增文书定义失败:文书名称不能为空(或不能为空白字符)");
}
if (definitionDto.getVersion() == null || definitionDto.getVersion().trim().isEmpty()) {
return R.fail("新增文书定义失败:文书版本号不能为空(或不能为空白字符)");
}
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) {
return R.fail("新增文书定义失败:科室分配时,科室不能为空");
}
// 2. 校验"名称+版本号"唯一性(避免重复创建)
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());
return R.fail("新增文书定义失败:相同名称和版本号的文书已存在,请修改后重试");
}
// 3. 补充默认值避免null字段插入数据库
if (definitionDto.getDisplayOrder() == null) {
definitionDto.setDisplayOrder(0);
}
if (definitionDto.getIsValid() == null) {
definitionDto.setIsValid(0); // 0-默认无效需根据业务确认是否改为1
}
// 4. 封装文书定义实体(生成业务编号)
DocDefinition docDefinition = new DocDefinition();
// 校验AssignSeqUtil是否注入避免空指针
if (assignSeqUtil == null) {
log.error("新增文书定义失败AssignSeqUtil工具类未注入无法生成业务编号");
return R.fail("新增文书定义失败:系统工具类异常,无法生成业务编号");
}
// 获取当前登录用户的医院ID
Long hospitalId = SecurityUtils.getLoginUser().getHospitalId();
if (hospitalId == null) {
log.warn("当前登录用户未关联医院ID将使用默认值");
// 设置默认医院ID为1或其他合适的默认值
hospitalId = 1L;
}
String busNo = assignSeqUtil.getSeq(AssignSeqEnum.PURCHASE_DOCUMENT.getPrefix(), 10);
docDefinition.setBusNo(busNo);
docDefinition.setName(definitionDto.getName().trim());
docDefinition.setVersion(definitionDto.getVersion().trim());
docDefinition.setDisplayOrder(definitionDto.getDisplayOrder());
docDefinition.setHospitalId(hospitalId);
docDefinition.setIsValid(definitionDto.getIsValid());
docDefinition.setVueRouter(definitionDto.getVueRouter().trim());
docDefinition.setPrimaryMenuEnum(definitionDto.getPrimaryMenuEnum());
docDefinition.setSubMenu(definitionDto.getSubMenu());
docDefinition.setUseRangeEnum(definitionDto.getUseRangeEnum());
docDefinition.setDoctorPermissionEnum(definitionDto.getDoctorPermissionEnum());
docDefinition.setNursingPermissionEnum(definitionDto.getNursingPermissionEnum());
docDefinition.setMedicalPermissionEnum(definitionDto.getMedicalPermissionEnum());
docDefinition.setPharmacistPermissionEnum(definitionDto.getPharmacistPermissionEnum());
// 5. 保存文书定义
boolean saveSuccess = docDefinitionService.save(docDefinition);
if (!saveSuccess) {
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()) {
DocDefinitionOrganizationDto orgDto = new DocDefinitionOrganizationDto();
orgDto.setBusNo(busNo);
orgDto.setDefinitionId(docDefinition.getId());
orgDto.setOrganizationIds(definitionDto.getOrganizationIds());
// 复用科室分配服务的新增逻辑,直接返回结果
return docDefinitionOrganizationAppService.add(orgDto);
}
return R.ok("新增文书定义成功");
}
/**
* 修改文书定义(版本号冲突时自动新增,含科室分配更新)
*/
@Override
public R<?> updateDefinition(DocDefinitionDto definitionDto) {
// 1. 基础参数校验(修改必传字段)
if (definitionDto.getId() == null) {
return R.fail("修改文书定义失败文书ID不能为空");
}
if (definitionDto.getName() == null || definitionDto.getName().trim().isEmpty()) {
return R.fail("修改文书定义失败:文书名称不能为空(或不能为空白字符)");
}
if (definitionDto.getVersion() == null || definitionDto.getVersion().trim().isEmpty()) {
return R.fail("修改文书定义失败:文书版本号不能为空(或不能为空白字符)");
}
if (definitionDto.getVueRouter() == null || definitionDto.getVueRouter().trim().isEmpty()) {
return R.fail("修改文书定义失败:文书路由不能为空(或不能为空白字符)");
}
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) {
return R.fail("修改文书定义失败:科室分配时,科室不能为空");
}
// 2. 校验文书是否存在
DocDefinition existingDoc = docDefinitionService.getById(definitionDto.getId());
if (existingDoc == null) {
log.warn("修改文书定义失败未找到ID={}的文书记录", definitionDto.getId());
return R.fail("修改文书定义失败:待修改的文书记录不存在");
}
// 3. 版本号冲突处理(版本号不一致时,转为新增逻辑)
if (!existingDoc.getVersion().trim().equals(definitionDto.getVersion().trim())) {
log.info("修改文书定义:版本号冲突(原版本={}, 新版本={}),自动执行新增逻辑", existingDoc.getVersion(), definitionDto.getVersion());
// 新增前清空ID避免覆盖原有记录
definitionDto.setId(null);
return addDefinition(definitionDto);
}
// 4. 补充默认值
if (definitionDto.getDisplayOrder() == null) {
definitionDto.setDisplayOrder(0);
}
if (definitionDto.getIsValid() == null) {
definitionDto.setIsValid(0);
}
// 5. 封装修改后的数据
existingDoc.setBusNo(definitionDto.getBusNo().trim());
existingDoc.setName(definitionDto.getName().trim());
existingDoc.setVersion(definitionDto.getVersion().trim());
existingDoc.setDisplayOrder(definitionDto.getDisplayOrder());
// 获取当前登录用户的医院ID
Long hospitalId = SecurityUtils.getLoginUser().getHospitalId();
if (hospitalId == null) {
log.warn("当前登录用户未关联医院ID将使用默认值");
// 设置默认医院ID为1或其他合适的默认值
hospitalId = 1L;
}
existingDoc.setHospitalId(hospitalId);
existingDoc.setIsValid(definitionDto.getIsValid());
existingDoc.setVueRouter(definitionDto.getVueRouter().trim());
existingDoc.setPrimaryMenuEnum(definitionDto.getPrimaryMenuEnum());
existingDoc.setSubMenu(definitionDto.getSubMenu());
existingDoc.setUseRangeEnum(definitionDto.getUseRangeEnum());
existingDoc.setDoctorPermissionEnum(definitionDto.getDoctorPermissionEnum());
existingDoc.setNursingPermissionEnum(definitionDto.getNursingPermissionEnum());
existingDoc.setMedicalPermissionEnum(definitionDto.getMedicalPermissionEnum());
existingDoc.setPharmacistPermissionEnum(definitionDto.getPharmacistPermissionEnum());
// 6. 执行修改
boolean updateSuccess = docDefinitionService.updateById(existingDoc);
if (!updateSuccess) {
log.error("修改文书定义失败数据库更新异常ID={}, 业务编号={}", definitionDto.getId(), definitionDto.getBusNo());
return R.fail("修改文书定义失败:数据库更新操作异常");
} else {
// 7. 更新科室分配(仅当使用范围为"科室级"时执行)
DocDefinitionOrganizationDto orgDto = new DocDefinitionOrganizationDto();
orgDto.setBusNo(existingDoc.getBusNo());
orgDto.setDefinitionId(existingDoc.getId());
orgDto.setOrganizationIds(definitionDto.getOrganizationIds());
// 复用科室分配服务的更新逻辑(先删后加,全量覆盖)
return docDefinitionOrganizationAppService.updateOrganization(orgDto);
}
}
@Override
public R<?> deleteDefinition(Long id) {
// 1. 参数校验
if (id == null) {
return R.fail("删除文书定义失败文书ID不能为空");
}
boolean result = docDefinitionService.removeById(id);
if (result) {
log.info("删除文书定义成功ID={}", id);
return R.ok("删除文书定义成功");
} else {
log.error("删除文书定义失败数据库删除异常ID={})", id);
return R.fail("删除文书定义失败:数据库删除操作异常");
}
}
/**
* 获取文书定义树形列表(按目录结构组织)
*/
@Override
public R<?> getTreeList(DocDefinitonParam param) {
// 1. 获取当前登录用户的医院ID避免跨医院查询
Long hospitalId = SecurityUtils.getLoginUser().getHospitalId();
Long organizationId = param.getOrganizationId();
List<Integer> useRanges = param.getUseRanges();
log.info("获取文书定义树形列表 - 请求参数: hospitalId={}, organizationId={}, useRanges={}, name={}, primaryMenuEnum={}",
hospitalId, organizationId, useRanges, param.getName(), param.getPrimaryMenuEnum());
if (hospitalId == null) {
log.warn("当前登录用户未关联医院ID将使用默认值");
// 设置默认医院ID为1或其他合适的默认值
hospitalId = 1L;
}
if (organizationId == null || organizationId == 0) {
log.warn("organizationId为空或0将跳过医院过滤和使用范围过滤");
}
if (useRanges == null || useRanges.isEmpty()) {
log.warn("useRanges为空可能返回所有使用范围的文书");
}
// 2. 数据库查询文书定义列表
List<DocDefinitionDto> docList = docDefinitionAppMapper.getDefinationList(useRanges,
organizationId, hospitalId, param.getName(), param.getPrimaryMenuEnum());
log.info("获取文书定义树形列表 - 查询结果: 记录数={}", docList != null ? docList.size() : 0);
if (docList != null && !docList.isEmpty()) {
for (DocDefinitionDto doc : docList) {
log.debug("文书: id={}, name={}, useRangeEnum={}, hospitalId={}",
doc.getId(), doc.getName(), doc.getUseRangeEnum(), doc.getHospitalId());
}
}
// 3. 构建树形结构(空列表时返回空树,避免空指针)
List<DirectoryNode> treeNodes = new ArrayList<>();
if (docList != null && !docList.isEmpty()) {
treeNodes = DocumentDirectoryProcessor.buildDocumentDirectory(docList);
log.info("获取文书定义树形列表成功医院ID={}, 文书数量={}, 树形节点数量={}", hospitalId, docList.size(), treeNodes.size());
} else {
log.info("获取文书定义树形列表成功医院ID={}, 暂无匹配的文书定义", hospitalId);
}
return R.ok(treeNodes, "获取文书定义树形列表成功");
}
/**
* 根据ID获取文书定义详情含已分配科室ID列表
*/
@Override
public R<?> getDefinitionDetailById(Long id) {
// 1. 参数校验
if (id == null) {
return R.fail("获取文书定义详情失败文书ID不能为空");
}
// 2. 调用私有方法获取详情含科室ID
DocDefinitionDto docDto = getDefinitionById(id);
if (docDto == null) {
log.warn("获取文书定义详情失败未找到ID={}的文书记录", id);
return R.fail("获取文书定义详情失败:未查询到对应的文书定义信息");
}
log.info("获取文书定义详情成功ID={}, 名称={}, 业务编号={}", id, docDto.getName(), docDto.getBusNo());
return R.ok(docDto, "获取文书定义详情成功");
}
/**
* 私有方法根据ID查询文书定义含已分配科室ID列表
*/
public DocDefinitionDto getDefinitionById(Long id) {
// 1. 查询文书定义主信息
DocDefinition doc = docDefinitionService.getById(id);
if (doc == null) {
log.debug("根据ID查询文书定义失败ID={}的文书不存在", id);
return null;
}
// 2. 查询该文书已分配的科室ID列表
LambdaQueryWrapper<DocDefinitionOrganization> orgWrapper = new LambdaQueryWrapper<>();
orgWrapper.eq(DocDefinitionOrganization::getDefinitionId, id).eq(DocDefinitionOrganization::getBusNo,
doc.getBusNo());
List<DocDefinitionOrganization> orgList = docDefinitionOrganizationService.list(orgWrapper);
// 3. 提取科室ID并封装DTO
List<Long> orgIdList = new ArrayList<>();
for (DocDefinitionOrganization org : orgList) {
orgIdList.add(org.getOrganizationId());
}
DocDefinitionDto docDto = new DocDefinitionDto();
BeanUtils.copyProperties(doc, docDto);
docDto.setOrganizationIds(orgIdList);
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);
}
}

View File

@@ -0,0 +1,174 @@
package com.openhis.web.document.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.core.common.core.domain.R;
import com.openhis.document.domain.DocDefinitionOrganization;
import com.openhis.document.service.IDocDefinitionOrganizationService;
import com.openhis.web.document.appservice.IDocDefinitionOrganizationAppService;
import com.openhis.web.document.dto.DocDefinitionOrganizationDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class DocDefinitionOrganizationAppServiceImpl implements IDocDefinitionOrganizationAppService {
@Resource
private IDocDefinitionOrganizationService docDefinitionOrganizationService;
/**
* 新增文书分配科室列表
* 注:新增前未删除原有分配,若需"覆盖新增"请使用updateOrganization方法
*/
@Override
public R<?> add(DocDefinitionOrganizationDto definitionOrganizationDto) {
// 1. 参数校验(明确错误原因,避免模糊提示)
if (definitionOrganizationDto == null) {
return R.fail("文书科室分配失败:请求参数不能为空");
}
if (definitionOrganizationDto.getOrganizationIds() == null || definitionOrganizationDto.getOrganizationIds().isEmpty()) {
return R.fail("文书科室分配失败科室ID列表不能为空");
}
if (definitionOrganizationDto.getDefinitionId() == null || definitionOrganizationDto.getDefinitionId() == 0) {
return R.fail("文书科室分配失败文书定义ID不能为空或不能为0");
}
if (definitionOrganizationDto.getBusNo() == null || definitionOrganizationDto.getBusNo().trim().isEmpty()) {
return R.fail("文书科室分配失败:业务编号不能为空(或不能为空白字符)");
}
// 2. DTO转实体批量封装科室分配关系
List<DocDefinitionOrganization> organizationList = new ArrayList<>();
for (Long orgId : definitionOrganizationDto.getOrganizationIds()) {
DocDefinitionOrganization docOrg = new DocDefinitionOrganization();
docOrg.setDefinitionId(definitionOrganizationDto.getDefinitionId());
docOrg.setBusNo(definitionOrganizationDto.getBusNo().trim()); // 去除业务编号前后空白
docOrg.setOrganizationId(orgId);
organizationList.add(docOrg);
}
// 3. 批量新增
boolean saveSuccess = docDefinitionOrganizationService.saveBatch(organizationList);
if (saveSuccess) {
return R.ok("文书科室分配成功");
} else {
log.error("文书科室分配新增失败文书定义ID={}, 业务编号={}",
definitionOrganizationDto.getDefinitionId(), definitionOrganizationDto.getBusNo());
return R.fail("文书科室分配失败:数据库新增操作异常");
}
}
/**
* 根据文书定义ID和业务编号删除对应的科室分配关系
*/
@Override
public R<?> delete(Long definitionId, String busNo) {
// 1. 参数校验
if (definitionId == null || definitionId == 0) {
return R.fail("文书科室分配删除失败文书定义ID不能为空或不能为0");
}
if (busNo == null || busNo.trim().isEmpty()) {
return R.fail("文书科室分配删除失败:业务编号不能为空(或不能为空白字符)");
}
// 2. 构建查询条件(精准匹配文书+业务编号)
LambdaQueryWrapper<DocDefinitionOrganization> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DocDefinitionOrganization::getDefinitionId, definitionId)
.eq(DocDefinitionOrganization::getBusNo, busNo.trim()); // 去除业务编号前后空白
// 3. 执行删除
boolean deleteSuccess = docDefinitionOrganizationService.remove(queryWrapper);
if (deleteSuccess) {
return R.ok("文书科室分配删除成功");
} else {
log.warn("文书科室分配删除失败未找到匹配的分配关系文书定义ID={}, 业务编号={}",
definitionId, busNo);
return R.fail("文书科室分配删除失败:未找到对应的科室分配记录");
}
}
/**
* 根据文书定义ID和业务编号查询已分配的科室ID列表
*/
@Override
public R<?> getOrganizationIdlist(Long definitionId, String busNo) {
// 1. 参数校验
if (definitionId == null || definitionId == 0) {
return R.fail("文书科室分配查询失败文书定义ID不能为空或不能为0");
}
if (busNo == null || busNo.trim().isEmpty()) {
return R.fail("文书科室分配查询失败:业务编号不能为空(或不能为空白字符)");
}
// 2. 构建查询条件
LambdaQueryWrapper<DocDefinitionOrganization> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DocDefinitionOrganization::getDefinitionId, definitionId)
.eq(DocDefinitionOrganization::getBusNo, busNo.trim());
// 3. 查询并提取科室ID避免返回冗余字段
List<DocDefinitionOrganization> orgList = docDefinitionOrganizationService.list(queryWrapper);
List<Long> orgIdList = new ArrayList<>();
for (DocDefinitionOrganization docOrg : orgList) {
orgIdList.add(docOrg.getOrganizationId());
}
log.info("文书科室分配查询成功文书定义ID={}, 业务编号={}, 分配科室数量={}",
definitionId, busNo, orgIdList.size());
return R.ok(orgIdList, "文书科室分配查询成功");
}
/**
* 更新文书科室分配(先删除原有分配,再新增新分配,实现"全量覆盖"
*/
@Override
public R<?> updateOrganization(DocDefinitionOrganizationDto definitionOrganizationDto) {
// 1. 参数校验与add方法保持一致的校验逻辑
if (definitionOrganizationDto == null) {
return R.fail("文书科室分配更新失败:请求参数不能为空");
}
if (definitionOrganizationDto.getDefinitionId() == null || definitionOrganizationDto.getDefinitionId() == 0) {
return R.fail("文书科室分配更新失败文书定义ID不能为空或不能为0");
}
if (definitionOrganizationDto.getBusNo() == null || definitionOrganizationDto.getBusNo().trim().isEmpty()) {
return R.fail("文书科室分配更新失败:业务编号不能为空(或不能为空白字符)");
}
// 2. 先删除原有分配关系
LambdaQueryWrapper<DocDefinitionOrganization> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(DocDefinitionOrganization::getDefinitionId, definitionOrganizationDto.getDefinitionId())
.eq(DocDefinitionOrganization::getBusNo, definitionOrganizationDto.getBusNo().trim());
Long count = docDefinitionOrganizationService.count(wrapper);
if (count > 0) {
boolean deleteSuccess = docDefinitionOrganizationService.remove(wrapper);
if (!deleteSuccess) {
log.error("文书科室分配更新失败删除原有分配记录异常文书定义ID={}, 业务编号={}",
definitionOrganizationDto.getDefinitionId(), definitionOrganizationDto.getBusNo());
return R.fail("文书科室分配更新失败:删除原有分配记录异常");
}
}
if (definitionOrganizationDto.getOrganizationIds() == null || definitionOrganizationDto.getOrganizationIds().isEmpty()) {
return R.ok("文书科室分配更新成功");
} else {
// 3. 再新增新的分配关系
List<DocDefinitionOrganization> newOrgList = new ArrayList<>();
for (Long orgId : definitionOrganizationDto.getOrganizationIds()) {
DocDefinitionOrganization docOrg = new DocDefinitionOrganization();
docOrg.setDefinitionId(definitionOrganizationDto.getDefinitionId());
docOrg.setBusNo(definitionOrganizationDto.getBusNo().trim());
docOrg.setOrganizationId(orgId);
newOrgList.add(docOrg);
}
boolean saveSuccess = docDefinitionOrganizationService.saveBatch(newOrgList);
if (saveSuccess) {
return R.ok("文书科室分配更新成功");
} else {
log.error("文书科室分配更新失败新增新分配记录异常文书定义ID={}, 业务编号={}",
definitionOrganizationDto.getDefinitionId(), definitionOrganizationDto.getBusNo());
return R.fail("文书科室分配更新失败:新增新分配记录异常");
}
}
}
}

View File

@@ -0,0 +1,206 @@
package com.openhis.web.document.appservice.impl;
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;
import com.openhis.document.mapper.DocStatisticsMapper;
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;
/**
* 文档模板 业务实现类
*/
@Slf4j
@Service
public class DocStatisticsAppServiceImpl implements IDocStatisticsAppService {
@Resource
private IDocStatisticsService docStatisticsService;
@Resource
private DocStatisticsMapper docStatisticsMapper;
@Override
public R<?> createOrUpdte(List<DocStatisticsDto> docStatisticsList) {
if (docStatisticsList.size() == 0) {
return R.ok();
}
// 根据recordId和statisticDefinitionId判断是否存在存在则更新不存在则新增
LambdaQueryWrapper<DocStatistics> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DocStatistics::getRecordId, docStatisticsList.get(0).getRecordId());
// 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());
docStatistics.setStatisticDefinitionId(docStatisticsDto.getStatisticDefinitionId());
docStatistics.setEncounterId(docStatisticsDto.getEncounterId());
docStatistics.setPatientId(docStatisticsDto.getPatientId());
docStatistics.setStatisticDefinitionCode(docStatisticsDto.getStatisticDefinitionCode());
docStatistics.setOrganizationId(SecurityUtils.getLoginUser().getOrgId());
docStatistics.setValue(docStatisticsDto.getValue());
docStatistics.setRecordTime(docStatisticsDto.getRecordTime());
docStatistics.setSource(docStatisticsDto.getSource());
docStatistics.setDefinitionId(docStatisticsDto.getDefinitionId());
docStatisticsInsertList.add(docStatistics);
}
boolean result = docStatisticsService.saveBatch(docStatisticsInsertList);
if (result) {
return R.ok();
} else {
return R.fail("新增或更新文档统计数据失败");
}
}
@Override
public R<?> delete(List<Long> ids) {
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
public R<?> queryByRecordId(Long recordId) {
return null;
}
@Override
public R<?> queryByEncounterId(Long encounterId) {
LambdaQueryWrapper<DocStatistics> queryWrapper = new LambdaQueryWrapper();
queryWrapper.eq(DocStatistics::getEncounterId, encounterId);
List<DocStatistics> docStatisticsList = docStatisticsService.list(queryWrapper);
List<DocStatisticsDto> docStatisticsDtoList = new ArrayList<>();
for (DocStatistics docStatistics : docStatisticsList) {
DocStatisticsDto docStatisticsDto = new DocStatisticsDto();
docStatisticsDto.setId(docStatistics.getId());
docStatisticsDto.setRecordId(docStatistics.getRecordId());
docStatisticsDto.setStatisticDefinitionId(docStatistics.getStatisticDefinitionId());
docStatisticsDto.setEncounterId(docStatistics.getEncounterId());
docStatisticsDto.setPatientId(docStatistics.getPatientId());
docStatisticsDto.setStatisticDefinitionCode(docStatistics.getStatisticDefinitionCode());
docStatisticsDto.setOrganizationId(docStatistics.getOrganizationId());
docStatisticsDto.setValue(docStatistics.getValue());
docStatisticsDto.setRecordTime(docStatistics.getRecordTime());
docStatisticsDto.setSource(docStatistics.getSource());
docStatisticsDtoList.add(docStatisticsDto);
}
return R.ok(docStatisticsDtoList);
}
@Override
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.lambda().orderByDesc(DocStatistics::getRecordTime);
Page<DocStatisticsDto> recordPage =
HisPageUtils.selectPage(docStatisticsMapper, queryWrapper, pageNo, pageSize, DocStatisticsDto.class);
return R.ok(recordPage, "获取患者文书统计数据成功");
}
// 2. 不分页查询逻辑
else {
LambdaQueryWrapper<DocStatistics> queryWrapper = new LambdaQueryWrapper<>();
// 患者ID查询条件
if (queryParam.getPatientId() != null) {
queryWrapper.eq(DocStatistics::getPatientId, queryParam.getPatientId());
}
// 就诊ID查询条件修复原逻辑原代码字段匹配错误用EncounterId匹配DefinitionBusNo
if (queryParam.getEncounterId() != null) {
queryWrapper.eq(DocStatistics::getEncounterId, queryParam.getEncounterId());
}
// 科室ID查询条件修复原逻辑原代码字段匹配错误用OrganizationId匹配EncounterId
if (queryParam.getOrganizationId() != null) {
queryWrapper.eq(DocStatistics::getOrganizationId, queryParam.getOrganizationId());
}
if (queryParam.getStatisticsDefinitionCode() != null) {
queryWrapper.eq(DocStatistics::getStatisticDefinitionCode, queryParam.getStatisticsDefinitionCode());
}
// 实体转DTO
List<DocStatisticsDto> dtoList = new ArrayList<>();
List<DocStatistics> statisticsList = docStatisticsService.list(queryWrapper);
for (DocStatistics statistics : statisticsList) {
DocStatisticsDto dto = new DocStatisticsDto();
BeanUtils.copyProperties(statistics, dto);
dtoList.add(dto);
}
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);
}
}

View File

@@ -0,0 +1,308 @@
package com.openhis.web.document.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.constant.CacheConstants;
import com.core.common.core.domain.R;
import com.core.common.core.domain.entity.SysDictData;
import com.core.common.core.redis.RedisCache;
import com.core.common.utils.bean.BeanUtils;
import com.openhis.common.utils.HisPageUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.document.domain.DocStatisticsDefinition;
import com.openhis.document.mapper.DocStatisticsDefinitionMapper;
import com.openhis.document.service.IDocStatisticsDefinitionService;
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;
/**
* 文档模板 业务实现类
*/
@Slf4j
@Service
public class DocStatisticsDefinitionAppServiceImpl implements IDocStatisticsDefinitionAppService {
@Resource
private IDocStatisticsDefinitionService iDocStatisticsDefinitionService;
@Resource
private DocStatisticsDefinitionMapper docStatisticsDefinitionMapper;
@Resource
private DocStatisticsDefinitionAppMapper docStatisticsDefinitionAppMapper;
@Autowired
private RedisCache redisCache;
@Override
public R<?> createOrEdit(DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
if (docStatisticsDefinitionDto == null) {
return R.fail("新增/编辑文档统计定义,参数不能为空");
}
if (docStatisticsDefinitionDto.getName() == null || docStatisticsDefinitionDto.getName().trim().length() == 0) {
return R.fail("新增/编辑文档统计定义,名称不能为空");
}
if (docStatisticsDefinitionDto.getTypeEnum() == null) {
return R.fail("新增/编辑文档统计定义,类型不能为空");
}
if (docStatisticsDefinitionDto.getCode() == null) {
return R.fail("新增/编辑文档统计定义,代码不能为空");
}
DocStatisticsDefinition docStatisticsDefinition = new DocStatisticsDefinition();
BeanUtils.copyProperties(docStatisticsDefinitionDto, docStatisticsDefinition);
// 新增时校验代码唯一性
if (!docStatisticsDefinitionDto.getCode().isEmpty() && docStatisticsDefinitionDto.getId() == null) {
LambdaQueryWrapper<DocStatisticsDefinition> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DocStatisticsDefinition::getCode, docStatisticsDefinitionDto.getCode());
docStatisticsDefinition = iDocStatisticsDefinitionService.getOne(queryWrapper);
if (docStatisticsDefinition != null) {
return R.fail("文档统计定义代码已存在,请更换代码");
}
}
// 区分新增/编辑逻辑
return docStatisticsDefinitionDto.getId() == null ? add(docStatisticsDefinitionDto)
: update(docStatisticsDefinitionDto);
}
@Override
public R<?> add(DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
String checkResult = initCheck(docStatisticsDefinitionDto);
DocStatisticsDefinition docStatisticsDefinition = new DocStatisticsDefinition();
if (checkResult != null) {
return R.fail(checkResult);
}
if (!docStatisticsDefinitionDto.getCode().isEmpty()) {
LambdaQueryWrapper<DocStatisticsDefinition> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DocStatisticsDefinition::getCode, docStatisticsDefinitionDto.getCode());
Long count = iDocStatisticsDefinitionService.count(queryWrapper);
if (count > 0) {
return R.fail("文档统计定义代码已存在,请更换代码");
}
}
// 赋值新增字段
docStatisticsDefinition.setName(docStatisticsDefinitionDto.getName());
docStatisticsDefinition.setCode(docStatisticsDefinitionDto.getCode());
docStatisticsDefinition.setTypeEnum(docStatisticsDefinitionDto.getTypeEnum());
docStatisticsDefinition.setRequired(docStatisticsDefinitionDto.getRequired());
docStatisticsDefinition.setRemark(docStatisticsDefinitionDto.getRemark());
docStatisticsDefinition.setIsStatistics(docStatisticsDefinitionDto.getIsStatistics());
docStatisticsDefinition.setDisplayOrder(docStatisticsDefinitionDto.getDisplayOrder());
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("文档统计定义新增成功");
} else {
return R.fail("文档统计定义新增失败");
}
}
@Override
public R<?> update(DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
String checkResult = initCheck(docStatisticsDefinitionDto);
if (checkResult != null) {
return R.fail(checkResult);
}
// 校验待更新数据是否存在
DocStatisticsDefinition existingData =
iDocStatisticsDefinitionService.getById(docStatisticsDefinitionDto.getId());
if (existingData == null) {
return R.fail("更新文档统计定义失败,目标数据不存在");
}
// 赋值更新字段
existingData.setName(docStatisticsDefinitionDto.getName());
existingData.setCode(docStatisticsDefinitionDto.getCode());
existingData.setTypeEnum(docStatisticsDefinitionDto.getTypeEnum());
existingData.setRequired(docStatisticsDefinitionDto.getRequired());
existingData.setRemark(docStatisticsDefinitionDto.getRemark());
existingData.setIsStatistics(docStatisticsDefinitionDto.getIsStatistics());
existingData.setDisplayOrder(docStatisticsDefinitionDto.getDisplayOrder());
existingData.setUnit(docStatisticsDefinitionDto.getUnit());
existingData.setDictType(docStatisticsDefinitionDto.getDictType());
existingData.setDictName(docStatisticsDefinitionDto.getDictName());
existingData.setTypeCode(docStatisticsDefinitionDto.getTypeCode());
boolean updateResult = iDocStatisticsDefinitionService.updateById(existingData);
if (updateResult) {
// 同步更新选项列表
return R.ok("文档统计定义更新成功");
} else {
return R.fail("文档统计定义更新失败");
}
}
private String initCheck(DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
if (docStatisticsDefinitionDto == null) {
return "新增/编辑文档统计定义,参数不能为空";
}
if (docStatisticsDefinitionDto.getName() == null || docStatisticsDefinitionDto.getName().trim().length() == 0) {
return "新增/编辑文档统计定义,名称不能为空";
}
if (docStatisticsDefinitionDto.getTypeEnum() == null) {
return "新增/编辑文档统计定义,类型不能为空";
}
if (docStatisticsDefinitionDto.getCode() == null) {
return "新增/编辑文档统计定义,代码不能为空";
}
return null;
}
/**
* 分页查询列表-不包含options分页
*
* @param pageNo 页码
* @param pageSize 每页条数
* @param searchKey 搜索关键词
* @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);
// 构建查询条件(支持多字段搜索)
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);
// 转换为分页结果
return R.ok(recordPage, "文档统计定义列表获取成功");
}
/**
* 获取文档统计定义列表(不分页,不包含options
*
* @param isStatistics 是否统计
* @return 文档统计定义列表
*/
@Override
public List<DocStatisticsDefinitionDto> getList(Integer isStatistics) {
Map<String, Object> keyMap = redisCache.getAllDictDataWithKeys(CacheConstants.SYS_DICT_KEY);
LambdaQueryWrapper<DocStatisticsDefinition> queryWrapper = new LambdaQueryWrapper<>();
if (isStatistics != null) {
queryWrapper.eq(DocStatisticsDefinition::getIsStatistics, isStatistics);
}
List<DocStatisticsDefinition> dataList = iDocStatisticsDefinitionService.list(queryWrapper);
List<DocStatisticsDefinitionDto> resultList = new ArrayList<>();
for (DocStatisticsDefinition data : dataList) {
DocStatisticsDefinitionDto dto = new DocStatisticsDefinitionDto();
BeanUtils.copyProperties(data, dto);
resultList.add(dto);
}
return resultList;
}
@Override
public List<DocStatisticsDefinitionDto> getListWithOptionList(Integer isStatistics) {
// 从redis中获取所有字典数据
Map<String, Object> keyMap = redisCache.getAllDictDataWithKeys(CacheConstants.SYS_DICT_KEY);
LambdaQueryWrapper<DocStatisticsDefinition> queryWrapper = new LambdaQueryWrapper<>();
if (isStatistics != null) {
queryWrapper.eq(DocStatisticsDefinition::getIsStatistics, isStatistics);
}
List<DocStatisticsDefinition> dataList = iDocStatisticsDefinitionService.list(queryWrapper);
List<DocStatisticsDefinitionDto> resultList = new ArrayList<>();
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());
dto.setOptionList(dictData);
}
resultList.add(dto);
}
return resultList;
}
/**
* 获取文档统计定义选项列表并按指定格式返回
*
* @return 封装了处理结果的响应对象
*/
@Override
public R<?> getOptionList() {
// 1. 从数据库查询所有选项数据
List<OptionDto> optionDtoList = docStatisticsDefinitionAppMapper.getOptionList(null, null, null);
// 2. 处理空数据场景
if (optionDtoList == null || optionDtoList.isEmpty()) {
return R.ok(new ArrayList<>(), "文档统计定义选项列表获取成功,查询结果为空");
}
// 3. 按code字段分组
Map<String, List<OptionDto>> groupCodeMap =
optionDtoList.stream().collect(Collectors.groupingBy(OptionDto::getCode));
// 4. 准备最终返回的结果列表
List<Map<String, Object>> resultList = new ArrayList<>();
// 5. 遍历每个code分组
for (Map.Entry<String, List<OptionDto>> entry : groupCodeMap.entrySet()) {
String code = entry.getKey();
List<OptionDto> optionDtos = entry.getValue();
Map<String, Object> resultMap = new HashMap<>();
// 设置名称和code
if (!optionDtos.isEmpty()) {
resultMap.put("name", optionDtos.get(0).getName());
}
resultMap.put("code", code);
// 动态生成列表键名
String listKey = code + "List";
// 检查分组中是否存在任何optionId为null的元素
boolean hasNullOptionId = optionDtos.stream().anyMatch(dto -> dto.getOptionId() == null);
// 如果存在null的optionId返回空集合否则正常处理
List<Map<String, Object>> optionList;
if (hasNullOptionId) {
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());
}
// 添加列表到结果中(即使是空集合)
resultMap.put(listKey, optionList);
resultList.add(resultMap);
}
return R.ok(resultList, "文档统计定义选项列表获取成功");
}
@Override
public R<?> deleteDocStatisticsDefinition(Long id) {
if (id == null) {
return R.fail("删除文档统计定义参数ID不能为空");
}
boolean deleteResult = iDocStatisticsDefinitionService.removeById(id);
if (deleteResult) {
return R.ok("文档统计定义删除成功");
} else {
return R.fail("文档统计定义删除失败");
}
}
}

View File

@@ -0,0 +1,189 @@
package com.openhis.web.document.appservice.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.utils.SecurityUtils;
import com.openhis.common.enums.DocUseRangeEnum;
import com.openhis.common.utils.HisPageUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.document.domain.DocTemplate;
import com.openhis.document.mapper.DocTemplateMapper;
import com.openhis.document.service.IDocTemplateService;
import com.openhis.web.document.appservice.IDocTemplateAppService;
import com.openhis.web.document.dto.DocTemplateDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
/**
* 文档模板 业务实现类
*/
@Slf4j
@Service
public class DocTemplateAppServiceImpl implements IDocTemplateAppService {
@Resource
private IDocTemplateService docTemplateService;
@Resource
private DocTemplateMapper docTemplateMapper;
@Override
public R<?> add(DocTemplateDto docTemplateDto) {
String msg = initCheck(docTemplateDto);
if (msg != null) {
return R.fail(msg);
}
DocTemplate docTemplate = new DocTemplate();
docTemplate.setName(docTemplateDto.getName());
docTemplate.setDisplayOrder(docTemplateDto.getDisplayOrder());
docTemplate.setContextJson(docTemplateDto.getContextJson());
docTemplate.setDefinitionId(docTemplateDto.getDefinitionId());
if (docTemplateDto.getUseRange() == null) {
docTemplate.setUseRange(DocUseRangeEnum.ALL_HOSPITAL_USE.getValue());
}
if (docTemplateDto.getUseRange() == DocUseRangeEnum.DEPT_USE.getValue()) {
docTemplateDto.setOrganizationId(SecurityUtils.getLoginUser().getOrgId());
}
if (docTemplateDto.getUseRange() == DocUseRangeEnum.USE_BY_SELF.getValue()) {
docTemplateDto.setUserId(SecurityUtils.getLoginUser().getUserId());
}
docTemplate.setOrganizationId(docTemplateDto.getOrganizationId());
docTemplate.setUserId(docTemplateDto.getUserId());
docTemplate.setUseRange(docTemplateDto.getUseRange());
docTemplate.setRemark(docTemplateDto.getRemark());
docTemplateService.save(docTemplate);
return R.ok(" 添加成功");
}
private String initCheck(DocTemplateDto docTemplateDto) {
if (docTemplateDto == null) {
return "参数不能为空";
}
if (docTemplateDto.getName().isEmpty()) {
return "名称不能为空";
}
if (docTemplateDto.getContextJson().isEmpty()) {
return "内容不能为空";
}
if (docTemplateDto.getDefinitionId() == null) {
return "模板定义不能为空";
}
if (docTemplateDto.getUseRange() == null) {
return "使用范围不能为空";
}
if (docTemplateDto.getId() == null) {
//根据名称+定义查询模板是否存在
LambdaQueryWrapper<DocTemplate> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DocTemplate::getName, docTemplateDto.getName());
queryWrapper.eq(DocTemplate::getDefinitionId, docTemplateDto.getDefinitionId());
DocTemplate docTemplate = docTemplateService.getOne(queryWrapper);
if (docTemplate != null) {
return "该模板已存在,请勿重复添加";
}
}
return null;
}
@Override
public R<?> delete(Long id) {
if (id == null) {
return R.fail("模板ID不能为空");
}
boolean result = docTemplateService.removeById(id);
if (result) {
return R.ok("删除成功");
}
return R.fail("模板不存在");
}
@Override
public R<?> update(DocTemplateDto docTemplateDto) {
String msg = initCheck(docTemplateDto);
if (msg != null) {
return R.fail(msg);
}
if (docTemplateDto.getId() == null) {
return R.fail("模板ID不能为空");
}
DocTemplate docTemplate = docTemplateService.getById(docTemplateDto.getId());
if (docTemplate == null) {
return R.fail("模板不存在");
}
if (docTemplateDto.getUseRange() == DocUseRangeEnum.ALL_HOSPITAL_USE.getValue() || docTemplateDto.getUseRange() == DocUseRangeEnum.NO_IN_USE.getValue()) {
docTemplateDto.setOrganizationId(null);
docTemplateDto.setUserId(null);
}
if (docTemplateDto.getUseRange() == DocUseRangeEnum.DEPT_USE.getValue()) {
docTemplateDto.setOrganizationId(SecurityUtils.getLoginUser().getOrgId());
docTemplateDto.setUserId(null);
}
if (docTemplateDto.getUseRange() == DocUseRangeEnum.USE_BY_SELF.getValue()) {
docTemplate.setUserId(SecurityUtils.getLoginUser().getUserId());
docTemplateDto.setOrganizationId(null);
}
docTemplate.setName(docTemplateDto.getName());
docTemplate.setDisplayOrder(docTemplateDto.getDisplayOrder());
docTemplate.setContextJson(docTemplateDto.getContextJson());
docTemplate.setDefinitionId(docTemplateDto.getDefinitionId());
docTemplate.setUseRange(docTemplateDto.getUseRange());
docTemplate.setOrganizationId(docTemplateDto.getOrganizationId());
docTemplate.setUserId(docTemplateDto.getUserId());
docTemplate.setRemark(docTemplateDto.getRemark());
docTemplateService.updateById(docTemplate);
return R.ok("更新成功");
}
@Override
public R<?> getById(Long id) {
if (id == null) {
return R.fail("模板ID不能为空");
}
DocTemplateDto templateDto = new DocTemplateDto();
DocTemplate result = docTemplateService.getById(id);
BeanUtils.copyProperties(result, templateDto);
return R.ok(templateDto);
}
@Override
public R<?> getListByDefinitionId(Long definitionId) {
if (definitionId == null) {
return R.fail("模板定义ID不能为空");
}
LambdaQueryWrapper<DocTemplate> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DocTemplate::getDefinitionId, definitionId);
queryWrapper.orderByAsc(DocTemplate::getDisplayOrder);
List<DocTemplate> docTemplates = docTemplateService.list(queryWrapper);
List<DocTemplateDto> templateDtos = new ArrayList<>();
for (DocTemplate docTemplate : docTemplates) {
DocTemplateDto templateDto = new DocTemplateDto();
BeanUtils.copyProperties(docTemplate, templateDto);
templateDtos.add(templateDto);
}
return R.ok(templateDtos);
}
@Override
public R<?> getPageList(Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request) {
// 构建查询条件(支持多字段搜索)
QueryWrapper<DocTemplate> queryWrapper = HisQueryUtils.buildQueryWrapper(
null, searchKey, new HashSet<>(Arrays.asList("name")), request);
// 按记录时间倒序(最新记录在前)
queryWrapper.lambda().orderByDesc(DocTemplate::getDisplayOrder);
Page<DocTemplateDto> page = HisPageUtils.selectPage(
docTemplateMapper, queryWrapper, pageNo, pageSize, DocTemplateDto.class);
// 转换为分页结果
return R.ok(page, "获取成功");
}
}

View File

@@ -0,0 +1,126 @@
package com.openhis.web.document.controller;
import com.core.common.core.domain.R;
import com.openhis.common.enums.DocPermissionEnum;
import com.openhis.common.enums.DocTypeEnum;
import com.openhis.common.enums.DocUseRangeEnum;
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;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 文书定义 controller
*
* @author wanghaiming
* @date 2025-08-12
*/
@RestController
@RequestMapping("/document/definition")
@Slf4j
@AllArgsConstructor
public class DocDefinitionController {
private final IDocDefinitionAppService iDocDefinitionAppService;
/**
* 初始化文书定义
*
* @return
*/
@GetMapping("/init")
public R<?> init() {
Map<String, Object> map = new HashMap<>();
// 获取文档类型枚举列表
map.put("docTypes", EnumUtil.toMapList(DocTypeEnum.class));
// 获取权限枚举列表
map.put("permissions", EnumUtil.toMapList(DocPermissionEnum.class));
// 使用范围枚举
List<String> noInUseCodes = new ArrayList<>();
noInUseCodes.add(DocUseRangeEnum.USE_BY_SELF.getCode());
map.put("useRanges", EnumUtil.toMapListFilter(DocUseRangeEnum.class, noInUseCodes));
return R.ok(map);
}
/**
* 新增文书定义
*
* @param definitionDto
* @return
*/
@PostMapping("/add")
public R<?> addDefinition(@RequestBody DocDefinitionDto definitionDto) {
return iDocDefinitionAppService.addDefinition(definitionDto);
}
/**
* 修改文书定义
*
* @param definitionDto
* @return
*/
@PostMapping("/update")
public R<?> updateDefinition(@RequestBody DocDefinitionDto definitionDto) {
return iDocDefinitionAppService.updateDefinition(definitionDto);
}
/**
* 获取文书定义详情
*
* @param id 文书定义ID
* @return 文书定义详情
*/
@GetMapping("/{id}")
public R<?> getDefinitionDetailById(@PathVariable Long id) {
log.info("获取文书定义详情 ID={}", id);
return iDocDefinitionAppService.getDefinitionDetailById(id);
}
/**
* 删除文书定义
*
* @param id 文书定义ID
* @return 文书定义详情
*/
@DeleteMapping("/delete/{id}")
public R<?> deleteDefinition(@PathVariable("id") Long id) {
log.info("删除文书定义ID={}", id);
// 调用删除服务注意方法名应改为删除相关如removeById
return iDocDefinitionAppService.deleteDefinition(id);
}
/**
* 查询获取文书定义列表 树形结构
*
* @return
*/
@GetMapping("/treeList")
public R<?> getTreeList(DocDefinitonParam docDefinitonParam,
@RequestParam(value = "useRanges", required = false) List<Integer> useRanges) {
docDefinitonParam.setUseRanges(useRanges);
return iDocDefinitionAppService.getTreeList(docDefinitonParam);
}
/**
* 获取文书ID
*
* @param menuEnum 来源类型
* @return 文书列表
*/
@GetMapping("/getDefinitionId")
public R<?> getDefinitionId(@RequestParam("menuEnum") Integer menuEnum) {
return iDocDefinitionAppService.getDefinitionId(menuEnum);
}
}

View File

@@ -0,0 +1,58 @@
package com.openhis.web.document.controller;
import com.core.common.core.domain.R;
import com.openhis.web.document.appservice.IDocDefinitionOrganizationAppService;
import com.openhis.web.document.dto.DocDefinitionOrganizationDto;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
/**
* 文书定义 - 科室分配 controller
*
* @author wanghaiming
* @date 2025-08-12
*/
@RestController
@RequestMapping("/document/definition/Organization")
@Slf4j
@AllArgsConstructor
public class DocDefinitionOrganizationController {
private final IDocDefinitionOrganizationAppService docDefinitionOrganizationAppService;
/**
* 新增文书分配科室列表
*
* @param organizationDto
* @return
*/
@PostMapping("/add")
public R<?> add(@RequestBody DocDefinitionOrganizationDto organizationDto) {
return docDefinitionOrganizationAppService.add(organizationDto);
}
/**
* 删除文书分配科室列表
*
* @param definitionId
* @param busNo
* @return
*/
@DeleteMapping("/delete")
public R<?> delete(@RequestParam("definitionId") Long definitionId, @RequestParam("busNo") String busNo) {
return docDefinitionOrganizationAppService.delete(definitionId, busNo);
}
/**
* 查询文书定义科室列表
*
* @param definitionId
* @param busNo
* @return
*/
@GetMapping("/getOrganizationIdlist")
public R<?> getOrganizationIdlist(@RequestParam("definitionId") Long definitionId, @RequestParam("busNo") String busNo) {
return docDefinitionOrganizationAppService.getOrganizationIdlist(definitionId, busNo);
}
}

View File

@@ -0,0 +1,198 @@
package com.openhis.web.document.controller;
import com.core.common.core.domain.R;
import com.openhis.common.enums.DocStatusEnum;
import com.openhis.common.enums.DocTypeEnum;
import com.openhis.web.document.appservice.IDocRecordAppService;
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
*
* @author wanghaiming
*/
@RestController
@RequestMapping("/document/record")
@Slf4j
@AllArgsConstructor
public class DocRecordController {
private final IDocRecordAppService docRecordAppService;
/**
* 初始化文书定义
*/
@GetMapping("/init")
public R<?> init() {
Map<String, Object> map = new HashMap<>();
// 获取文档状态枚举
map.put("doc_status_enums", EnumUtil.toMapList(DocStatusEnum.class));
map.put("doc_type_enums", EnumUtil.toMapList(DocTypeEnum.class));
return R.ok(map);
}
/**
* 新增记录
*
* @param docRecordDto 文书记录信息
* @return R
*/
@PostMapping("/addRecord")
public R<?> addRecord(@RequestBody DocRecordDto docRecordDto) {
return docRecordAppService.addRecord(docRecordDto);
}
/**
* 编辑记录 修改前先设置文书为编辑状态
*
* @param docRecordDto 文书记录信息
* @return R
*/
@PostMapping("/updateRecord")
public R<?> updateRecord(@RequestBody DocRecordDto docRecordDto) {
return docRecordAppService.updateRecord(docRecordDto);
}
/**
* 新增或编辑记录
*
* @param docRecordDto 文书记录信息
* @return R
*/
@PostMapping("/saveOrUpdateRecord")
public R<?> saveOrUpdateRecord(@RequestBody DocRecordDto docRecordDto) {
return docRecordAppService.saveOrUpdateRecord(docRecordDto);
}
/**
* 设置文书为编辑状态
*
* @param recordId 文书记录ID
* @return R
*/
@PostMapping("/setIsEdit")
public R<?> setIsEdit(Long recordId) {
return docRecordAppService.setIsEdit(recordId);
}
/**
* 根据患者ID或就诊ID获取文书记录列表,只针对不需返回患者具体信息的列表,体温单除外,单独处理 需返回患者具体信息的列表请使用getPatientRecordList
*
* @param docRecordQueryParam 文书记录查询参数
* @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);
}
/**
* 根据患者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 请求
* @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);
}
/**
* 根据文书记录ID获取文书记录信息
*
* @param recordId 文书记录ID
*/
@GetMapping("/getRecordById")
R<?> getRecordById(@RequestParam(value = "recordId") Long recordId) {
return docRecordAppService.getRecordById(recordId);
}
/**
* 删除文书分配信息
*
* @param ids 删除文书分配信息ID列表
*/
@DeleteMapping("/deleteRecord")
R<?> deleteRecord(@RequestBody List<Long> ids) {
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);
}
}

View File

@@ -0,0 +1,58 @@
package com.openhis.web.document.controller;
import com.core.common.core.domain.R;
import com.openhis.web.document.appservice.IDocStatisticsAppService;
import com.openhis.web.document.dto.DocStatisticsDto;
import com.openhis.web.document.dto.DocStatisticsQueryParam;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* DocStatistics文书统计 controller
*
* @author wanghaiming
* @date 2025-08-12
*/
@RestController
@RequestMapping("/document/statistics")
@Slf4j
@AllArgsConstructor
public class DocStatisticsController {
private final IDocStatisticsAppService docStatisticsAppService;
@PostMapping("/createOrUpdte")
public R<?> createOrUpdte(List<DocStatisticsDto> docStatisticsList) {
return docStatisticsAppService.createOrUpdte(docStatisticsList);
}
@DeleteMapping("/delete")
public R<?> delete(List<Long> ids) {
return docStatisticsAppService.delete(ids);
}
@GetMapping("/queryByRecordId")
public R<?> queryByRecordId(Long recordId) {
return docStatisticsAppService.queryByRecordId(recordId);
}
@GetMapping("/queryByEncounterId")
public R<?> queryByEncounterId(Long encounterId) {
return docStatisticsAppService.queryByEncounterId(encounterId);
}
@GetMapping("/getStatisticsList")
R<?> getStatisticsList(DocStatisticsQueryParam queryParam,
@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 docStatisticsAppService.getStatisticsList(queryParam, isPage, pageNo, pageSize, searchKey, request);
}
}

View File

@@ -0,0 +1,128 @@
package com.openhis.web.document.controller;
import com.core.common.core.domain.R;
import com.openhis.common.enums.DocStatisticsDefinitionTypeEnum;
import com.openhis.web.document.appservice.IDocStatisticsDefinitionAppService;
import com.openhis.web.document.dto.DocStatisticsDefinitionDto;
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
*
* @author wanghaiming
* @date 2025-08-12
*/
@RestController
@RequestMapping("/document/statistics/definition")
@Slf4j
@AllArgsConstructor
public class DocStatisticsDefinitionController {
private final IDocStatisticsDefinitionAppService docStatisticsDefinitionAppService;
/**
* 初始化页面数据
*
* @return
*/
@GetMapping("/init")
public R<?> init() {
Map<String, Object> map = new HashMap<>();
// 获取文档状态枚举
map.put("doc_statistics_definition_type_enums", EnumUtil.toMapList(DocStatisticsDefinitionTypeEnum.class));
return R.ok(map);
}
// @PostMapping("/createOrEdit")
// public R<?> createOrEdit(@RequestBody DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
// return docStatisticsDefinitionAppService.createOrEdit(docStatisticsDefinitionDto);
// }
/**
* 新增统计定义
*
* @param docStatisticsDefinitionDto
* @return
*/
@PostMapping("/add")
public R<?> add(@RequestBody DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
return docStatisticsDefinitionAppService.add(docStatisticsDefinitionDto);
}
/**
* 修改统计定义
*
* @param docStatisticsDefinitionDto
* @return
*/
@PostMapping("/update")
public R<?> update(@RequestBody DocStatisticsDefinitionDto docStatisticsDefinitionDto) {
return docStatisticsDefinitionAppService.update(docStatisticsDefinitionDto);
}
/**
* 删除统计定义
*
* @param id
*/
@DeleteMapping("/deleteDocStatisticsDefinition")
public R<?> deleteDocStatisticsDefinition(Long id) {
return docStatisticsDefinitionAppService.deleteDocStatisticsDefinition(id);
}
/**
* 分页查询列表-不包含options
*
* @param pageNo
* @param pageSize
* @param searchKey
* @param request
* @return
*/
@GetMapping("/getPageList")
public R<?> getPageList(@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "searchKey", required = false) String searchKey, HttpServletRequest request) {
return docStatisticsDefinitionAppService.getPageList(pageNo, pageSize, searchKey, request);
}
/**
* 获取文档统计定义列表-不包含options即字典数据
*
* @param isStatistics 文档统计定义是否启用 0不统计 1统计 可不传
* @return
*/
@GetMapping("/getList")
public R<?> getList(Integer isStatistics){
List<DocStatisticsDefinitionDto> list = docStatisticsDefinitionAppService.getList(isStatistics);
return R.ok(list);
}
/**
* 获取文档统计定义列表(包含options即字典数据)
*
* @param isStatistics 文档统计定义是否启用 0不统计 1统计 可不传
* @return
*/
@GetMapping("/getListWithOptionList")
public R<?>getListWithOptionList(Integer isStatistics){
List<DocStatisticsDefinitionDto> list = docStatisticsDefinitionAppService.getListWithOptionList(isStatistics);
return R.ok(list);
}
/**
* 获取文档统计定义选项列表并按指定格式返回-已作废
*
* @return
*/
@GetMapping("/getOptionList")
public R<?> getOptionList() {
return docStatisticsDefinitionAppService.getOptionList();
}
}

View File

@@ -0,0 +1,79 @@
package com.openhis.web.document.controller;
import com.core.common.core.domain.R;
import com.openhis.common.enums.DocTypeEnum;
import com.openhis.common.enums.DocUseRangeEnum;
import com.openhis.web.document.appservice.IDocTemplateAppService;
import com.openhis.web.document.dto.DocTemplateDto;
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.Map;
/**
* 文书模板/病历模板 controller
*
* @author wanghaiming
* @date 2025-08-12
*/
@RestController
@RequestMapping("/document/template")
@Slf4j
@AllArgsConstructor
public class DocTemplateController {
private final IDocTemplateAppService docTemplateAppService;
/**
* 初始化文书定义
*
* @return
*/
@GetMapping("/init")
public R<?> init() {
Map<String, Object> map = new HashMap<>();
// 获取文档类型枚举列表
map.put("docTypes", EnumUtil.toMapList(DocTypeEnum.class));
// 使用范围枚举
map.put("useRanges", EnumUtil.toMapList(DocUseRangeEnum.class));
return R.ok(map);
}
@PostMapping("/add")
public R<?> add(@RequestBody DocTemplateDto docTemplateDto) {
return docTemplateAppService.add(docTemplateDto);
}
@DeleteMapping("/delete")
public R<?> delete(Long id) {
return docTemplateAppService.delete(id);
}
@PutMapping("/update")
public R<?> update(@RequestBody DocTemplateDto docTemplateDto) {
return docTemplateAppService.update(docTemplateDto);
}
@GetMapping("/getById")
public R<?> getById(Long id) {
return docTemplateAppService.getById(id);
}
@GetMapping("/getListByDefinitionId")
public R<?> getListByDefinitionId(Long definitionId) {
return docTemplateAppService.getListByDefinitionId(definitionId);
}
@GetMapping("/getPageList")
public R<?> getPageList(@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "searchKey", required = false) String searchKey, HttpServletRequest request) {
return docTemplateAppService.getPageList(pageNo, pageSize, searchKey, request);
}
}

View File

@@ -0,0 +1,21 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.List;
@Data
@Accessors(chain = true)
public class DirectoryNode {
private String name;
private int level;
private DocDefinitionDto document;
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
private List<DirectoryNode> children = new ArrayList<>();
}

View File

@@ -0,0 +1,86 @@
package com.openhis.web.document.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class DocDefinitionDto {
/**
* ID
*/
@TableId(type = IdType.ASSIGN_ID)
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 文书名称
*/
private String name;
/**
* 文书的版本号
*/
private String version;
/**
* 文书类型 一级菜单 ,从枚举中获取 DocTypeEnum
*/
private Integer primaryMenuEnum;
/**
* 文书类型 二级菜单,自定义
*/
private String subMenu;
/**
* 文书编码 busNo在新建时由系统自动生成
*/
private String busNo;
/**
* vue路由地址
*/
private String vueRouter;
/**
* 医院ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long hospitalId;
/**
* 是否有效 0-有效 1-无效
*/
private Integer isValid;
/**
* 显示顺序
*/
private Integer displayOrder;
/**
* 使用范围 0-暂不使用 1-全院使用 2-指定科室使用
*/
private Integer useRangeEnum;
/**
* 医生权限 DocPermissionEnum
* 文书权限 0-不限制 1-查看 2- 编辑
*/
private Integer doctorPermissionEnum;
/**
* 护士权限 DocPermissionEnum
* 文书权限 0-不限制 1-查看 2- 编辑
*/
private Integer nursingPermissionEnum;
/**
* 医技权限 DocPermissionEnum
* 文书权限 0-不限制 1-查看 2- 编辑
*/
private Integer medicalPermissionEnum;
/**
* 药剂师权限 DocPermissionEnum
* 文书权限 0-不限制 1-查看 2- 编辑
*/
private Integer pharmacistPermissionEnum;
// 关键通过contentUsing指定集合中元素的序列化器
@JsonSerialize(contentUsing = ToStringSerializer.class)
private List<Long> organizationIds;
}

View File

@@ -0,0 +1,24 @@
package com.openhis.web.document.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class DocDefinitionOrganizationDto {
@TableId(type = IdType.ASSIGN_ID)
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@JsonSerialize(using = ToStringSerializer.class)
private Long definitionId;
private String busNo;
@JsonSerialize(contentUsing = ToStringSerializer.class)
private List<Long> organizationIds;
}

View File

@@ -0,0 +1,20 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class DocDefinitonParam {
// 文书类型 一级菜单 ,从枚举中获取 DocTypeEnum
private Integer primaryMenuEnum;
@JsonSerialize(using = ToStringSerializer.class)
private Long organizationId;
private String name;
private List<Integer> useRanges;
}

View File

@@ -0,0 +1,66 @@
package com.openhis.web.document.dto;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@Accessors(chain = true)
public class DocRecordDto {
@TableId(type = IdType.ASSIGN_ID)
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 文书定义ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long definitionId;
private String definitionBusNo;
/**
* 文档内容 存储为JSON格式
*/
private String contentJson;
/**
* 记录状态 0草稿/暂存 1提交 2归档 3修改 DocStatusEnum 枚举类
* 0草稿/暂存 1提交 2归档 3修改
*/
private Integer statusEnum;
/**
* 记录科室ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long organizationId;
/**
* 就诊id
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long encounterId;
/**
* patientId 病人id
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long patientId;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date recordTime;
private String createBy;
private String source;
/**
* 记录名称
*/
private String name;
private String version;
/**
* 打印次数
*/
private Integer printCount = 0;
}

View File

@@ -0,0 +1,72 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@Accessors(chain = true)
public class DocRecordPatientDto extends DocRecordDto {
/**
* 科室ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long organizationId;
/**
* 病人住院号、门诊号(病历号)
*/
private String busNo;
private String patientName;
private Integer gender;
private String genderValue;
private String age;
private String IdCard;
private String phone;
private String address;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthDate;
/**
* 入院 接诊时间/门诊 接诊时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date receptionTime;
/**
* 开始时间 encounter 入院登记时间/ 门诊 挂号时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
* 结束时间 encounter 住院 出院登记时间/ 门诊就诊结束时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**
* 就诊类型 encounter 就诊类型 1:门诊 2:住院
*/
private Integer classEnum;
private String classEnumValue;
/**
* 病历名称
*/
private String name;
/**
* 主菜单枚举值/病历类型
*/
private Integer primaryMenuEnum;
/**
* 主菜单名称 主菜单枚举值/病历类型名称
*/
private String primaryMenuEnumValue;
}

View File

@@ -0,0 +1,36 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@Accessors(chain = true)
public class DocRecordPatientQueryParam {
/**
* 书写文书的组织机构ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long organizationId;
/**
* 文书状态
*/
private Integer statusEnum;
/**
* 对应 EncounterClass 枚举 | 就诊类型, 默认 2:门诊 1住院
*/
private Integer classEnum;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date recordTime;
}

View File

@@ -0,0 +1,24 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 查询单个患者的文档记录参数
*/
@Data
@Accessors(chain = true)
public class DocRecordQueryParam {
@JsonSerialize(using = ToStringSerializer.class)
private Long organizationId;
@JsonSerialize(using = ToStringSerializer.class)
private Long definitionId;
@JsonSerialize(using = ToStringSerializer.class)
private Long patientId;
@JsonSerialize(using = ToStringSerializer.class)
private Long encounterId;
}

View File

@@ -0,0 +1,68 @@
package com.openhis.web.document.dto;
import com.core.common.core.domain.entity.SysDictData;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class DocStatisticsDefinitionDto {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/*
属性名称
*/
private String name;
/*
属性类型 Input 、 Date 、 Checkbox 、Radio 、 Select 、 Textarea
*/
private Integer typeEnum;
/*
属性代码
*/
private String code;
/*
是否必填 1必填 0 不必填
*/
private Integer required;
/*
备注
*/
private String remark;
/*
单位
*/
private String unit;
/*
是否统计 0不统计 1统计
*/
private Integer isStatistics;
/*
显示顺序
*/
private Integer displayOrder;
private String defaultValue;
// /*
// 统计类型定义选项值
// */
private List<SysDictData> optionList;
/** 字典名称 */
private String dictName;
/** 字典类型 */
private String dictType;
/**
* 类型代码 例 003:体温
*/
private String typeCode;
}

View File

@@ -0,0 +1,21 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class DocStatisticsDefinitionOptionDto {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/*
* 统计项编码
*/
// private String busNo;
private String option;
private Integer displayOrder;
}

View File

@@ -0,0 +1,23 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
@Data
@Accessors(chain = true)
public class DocStatisticsDefinitionOptionList {
/*
* 统计定义ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long docStatisticsDefinitionId;
List<DocStatisticsDefinitionOptionDto> options;
}

View File

@@ -0,0 +1,60 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@Accessors(chain = true)
public class DocStatisticsDto {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 记录ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long recordId;
/**
* 统计项定义ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long statisticDefinitionId;
@JsonSerialize(using = ToStringSerializer.class)
private Long encounterId;
@JsonSerialize(using = ToStringSerializer.class)
private Long patientId;
/**
* 统计项编码
*/
private String statisticDefinitionCode;
/**
* 记录科室ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long organizationId;
/**
* 统计值
*/
private String value;
/**
* 记录时间
*/
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date recordTime;
/**
* 记录来源
*/
private String source;
/**
* 文书ID
*/
private Long definitionId;
}

View File

@@ -0,0 +1,30 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Date;
/**
* 查询单个患者的文档记录参数
*/
@Data
@Accessors(chain = true)
public class DocStatisticsQueryParam {
@JsonSerialize(using = ToStringSerializer.class)
private Long definitionId;
@JsonSerialize(using = ToStringSerializer.class)
private Long patientId;
@JsonSerialize(using = ToStringSerializer.class)
private Long encounterId;
@JsonSerialize(using = ToStringSerializer.class)
private Long organizationId;
private String statisticsDefinitionCode;
/**
* 记录时间 yyyy-MM-dd HH:mm:ss
*/
private Date recordTime;
}

View File

@@ -0,0 +1,52 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class DocTemplateDto {
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 模板名称
*/
private String name;
/**
* 排序
*/
private Integer displayOrder;
/**
* 模板内容
*/
private String contextJson;
/**
* 文书定义ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long definitionId;
/**
* 使用范围 0-全院 1-指定机构 2-指定用户
*/
private Integer useRange;
/**
* 当useRange=1时指定机构ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long organizationId;
/**
* 当useRange=2时指定用户ID
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
/**
* 备注
*/
private String remark;
}

View File

@@ -0,0 +1,24 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* 查询单个患者的文档记录参数
*/
@Data
@Accessors(chain = true)
public class DocTemplateQueryParam {
@JsonSerialize(using = ToStringSerializer.class)
private Integer useRang;
@JsonSerialize(using = ToStringSerializer.class)
private Long definitionId;
@JsonSerialize(using = ToStringSerializer.class)
private Long patientId;
@JsonSerialize(using = ToStringSerializer.class)
private Long encounterId;
}

View File

@@ -0,0 +1,48 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
public class OptionDto {
@JsonSerialize(using = ToStringSerializer.class)
private Long optionId;
private String option;
private Integer displayOrder;
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/*
属性名称
*/
private String name;
/*
属性类型 Input 、 Date 、 Checkbox 、Radio 、 Select 、 Textarea
*/
private Integer typeEnum;
/*
属性代码
*/
private String code;
/*
是否必填 1必填 0 不必填
*/
private Integer required;
/*
备注
*/
private String remark;
/*
是否统计 0不统计 1统计
*/
private Integer isStatistics;
private String unit;
}

View File

@@ -0,0 +1,31 @@
package com.openhis.web.document.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.ArrayList;
import java.util.List;
/**
* 温度、脉搏等生命体征信息
*
* @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;
}

View File

@@ -0,0 +1,51 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import java.util.List;
/**
* 体温单
*
* @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;
}

View File

@@ -0,0 +1,59 @@
package com.openhis.web.document.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* 图表信息
*
* @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;
}

View File

@@ -0,0 +1,27 @@
package com.openhis.web.document.mapper;
import com.openhis.web.document.dto.DocDefinitionDto;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 文书分配信息Mapper
*
* @author wanghaiming
* @since 2025/04/08
*/
@Repository
public interface DocDefinitionAppMapper {
/**
* 根据useRangeEnum获取文书分配信息列表
*
* @return 文书分配信息
*/
List<DocDefinitionDto> getDefinationList(@Param("useRanges") List<Integer> useRanges, @Param("organizationId") Long organizationId,
@Param("hospitalId") Long hospitalId, @Param("name") String name, @Param("primaryMenuEnum") Integer primaryMenuEnum);
}

View File

@@ -0,0 +1,30 @@
package com.openhis.web.document.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.openhis.web.document.dto.DocRecordDto;
import com.openhis.web.document.dto.DocRecordPatientDto;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 文书分配信息Mapper
*
* @author wanghaiming
* @since 2025/04/08
*/
@Repository
public interface DocRecordAppMapper {
IPage<DocRecordPatientDto> getRecordPageList(@Param("page") Page<DocRecordPatientDto> page,
@Param("primaryMenuEnumList") List<Integer> primaryMenuEnumList,
@Param(Constants.WRAPPER) QueryWrapper<DocRecordPatientDto> queryWrapper);
IPage<DocRecordDto> getRecordPageListByEncounterId(@Param("page") Page<DocRecordPatientDto> page,
@Param(Constants.WRAPPER) QueryWrapper<DocRecordDto> queryWrapper);
}

View File

@@ -0,0 +1,34 @@
package com.openhis.web.document.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.openhis.web.document.dto.DocStatisticsDefinitionDto;
import com.openhis.web.document.dto.OptionDto;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 文书分配信息Mapper
*
* @author wanghaiming
* @since 2025/04/08
*/
@Repository
public interface DocStatisticsDefinitionAppMapper {
/**
* 获取统计定义列表
*
* @return 文书分配信息
*/
IPage<DocStatisticsDefinitionDto> getDocStatisticsDefinitionPageList(@Param("page") Page<DocStatisticsDefinitionDto> page,
@Param(Constants.WRAPPER) QueryWrapper<DocStatisticsDefinitionDto> queryWrapper);
List<OptionDto> getOptionList(@Param("id") Long id, @Param("code") String code, @Param("name") String name);
}

View File

@@ -0,0 +1,233 @@
package com.openhis.web.document.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.core.common.utils.StringUtils;
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;
import org.springframework.stereotype.Component;
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;
@Component
public class ConvertToDocStatistics {
@Resource
IDocStatisticsDefinitionAppService docStatisticsDefinitionAppService;
/**
* 解析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) {
// 初始化返回的统计DTO列表
List<DocStatisticsDto> statisticsDtoList = new ArrayList<>();
// 防御性判断:如果文档记录为空,直接返回空列表
if (docRecordDto == null) {
return statisticsDtoList;
}
// 获取JSON格式的内容字符串待解析的原始数据
String contentJson = docRecordDto.getContentJson();
// 获取系统中定义的统计项列表需要解析的目标code集合
List<DocStatisticsDefinitionDto> definitionList = docStatisticsDefinitionAppService.getList(1);
// 防御性判断:如果统计项定义为空,直接返回空列表
if (definitionList == null || definitionList.isEmpty()) {
return statisticsDtoList;
}
// 解析JSON字符串为JSONObject方便操作嵌套结构
JSONObject contentJsonObj = parseJson(contentJson);
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();
// 场景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);
}
} catch (Exception e) {
e.printStackTrace();
}
// 创建DTO并添加到结果列表
addSingleDto(statisticsDtoList, definition, docRecordDto, value, recordTime);
// 处理完当前统计项,继续下一个
continue;
}
// 场景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);
}
}
}
return statisticsDtoList;
}
/**
* 工具方法解析JSON字符串为JSONObject
*
* @param jsonStr 原始JSON字符串
* @return 解析后的JSONObject失败则返回null
*/
private JSONObject parseJson(String jsonStr) {
// 如果JSON字符串为空直接返回null
if (jsonStr == null) {
return null;
}
try {
// 解析JSON字符串
return JSON.parseObject(jsonStr);
} catch (Exception e) {
// 记录解析异常日志
log.error("JSON解析失败原始字符串: {}", jsonStr, e);
return null;
}
}
/**
* 工具方法创建单个统计DTO并添加到列表
*
* @param dtoList 目标DTO列表
* @param definition 统计项定义
* @param docRecordDto 文档记录DTO
* @param value 解析出的统计值
* @param recordTime 记录时间
*/
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);
}
}
}

View File

@@ -0,0 +1,162 @@
package com.openhis.web.document.util;
import com.openhis.common.enums.DocTypeEnum;
import com.openhis.web.document.dto.DirectoryNode;
import com.openhis.web.document.dto.DocDefinitionDto;
import java.util.*;
public class DocumentDirectoryProcessor {
private static Long id;
/**
* 构建文档目录树
*
* @param documents 文档定义列表
* @return 目录节点列表(树形结构)
*/
public static List<DirectoryNode> buildDocumentDirectory(List<DocDefinitionDto> documents) {
// 第一步按一级菜单分组使用LinkedHashMap保持插入顺序
id = 1L;
Map<Object, List<DocDefinitionDto>> level1Groups = new LinkedHashMap<>();
for (DocDefinitionDto doc : documents) {
Object key = doc.getPrimaryMenuEnum() != null ? doc.getPrimaryMenuEnum() : doc.getName();
level1Groups.computeIfAbsent(key, k -> new ArrayList<>()).add(doc);
}
// 对一级节点进行排序,确保输出顺序符合预期
List<Object> sortedKeys = new ArrayList<>(level1Groups.keySet());
sortedKeys.sort((k1, k2) -> {
// 处理数字类型的键primaryMenuEnum
if (k1 instanceof Integer && k2 instanceof Integer) {
return Integer.compare((Integer) k1, (Integer) k2);
}
// 数字键排在前面,非数字键(如体温单)排在后面
if (k1 instanceof Integer) {
return -1;
}
if (k2 instanceof Integer) {
return 1;
}
// 都是非数字键,按名称排序
return k1.toString().compareTo(k2.toString());
});
// 按排序后的键重新组织分组
Map<Object, List<DocDefinitionDto>> sortedLevel1Groups = new LinkedHashMap<>();
for (Object key : sortedKeys) {
sortedLevel1Groups.put(key, level1Groups.get(key));
}
List<DirectoryNode> result = new ArrayList<>();
for (Map.Entry<Object, List<DocDefinitionDto>> entry : sortedLevel1Groups.entrySet()) {
Object level1Key = entry.getKey();
List<DocDefinitionDto> level1Docs = entry.getValue();
DirectoryNode level1Node = new DirectoryNode();
if (level1Key instanceof Integer) {
level1Node.setName(getMenuName((Integer) level1Key));
} else {
level1Node.setName(level1Key.toString());
}
level1Node.setId(id++);
level1Node.setLevel(1);
buildSubNodes(level1Node, level1Docs);
result.add(level1Node);
}
return result;
}
private static void buildSubNodes(DirectoryNode parentNode, List<DocDefinitionDto> documents) {
if (documents == null || documents.isEmpty()) {
return;
}
// 按下一级分组键分组处理null键
Map<String, List<DocDefinitionDto>> groups = new HashMap<>();
for (DocDefinitionDto doc : documents) {
String key = getNextLevelKey(parentNode, doc);
// 统一使用空字符串处理null键避免分组异常
key = (key == null) ? "" : key;
groups.computeIfAbsent(key, k -> new ArrayList<>()).add(doc);
}
// 对分组键进行排序,确保子节点顺序一致
List<String> sortedGroupKeys = new ArrayList<>(groups.keySet());
sortedGroupKeys.sort(String::compareTo);
for (String groupKey : sortedGroupKeys) {
List<DocDefinitionDto> groupDocs = groups.get(groupKey);
if (groupKey.isEmpty()) {
// 分组键为空,直接添加文档节点
for (DocDefinitionDto doc : groupDocs) {
parentNode.getChildren().add(createDocumentNode(doc));
}
} else {
// 创建目录节点
DirectoryNode childNode = new DirectoryNode();
childNode.setName(groupKey);
childNode.setLevel(parentNode.getLevel() + 1);
childNode.setId(id++);
// 递归构建子节点
buildSubNodes(childNode, groupDocs);
// 添加子节点到父节点
parentNode.getChildren().add(childNode);
}
}
}
/**
* 获取下一级节点的分组键
* 关键优化:二级节点(level=2)不再进行分组直接返回null
*/
private static String getNextLevelKey(DirectoryNode parentNode, DocDefinitionDto doc) {
int parentLevel = parentNode.getLevel();
if (parentLevel == 1) {
return doc.getSubMenu(); // 一级节点的下一级是subMenu(二级菜单)
} else if (parentLevel == 2) {
return null; // 二级节点的下一级直接是文档,不进行分组
}
return null;
}
private static DirectoryNode createDocumentNode(DocDefinitionDto doc) {
DirectoryNode node = new DirectoryNode();
node.setName(doc.getName() + " (" + doc.getVersion() + ")");
node.setLevel(3);
node.setId(id++);
node.setDocument(doc);
return node;
}
private static String getMenuName(Integer menuEnum) {
DocTypeEnum docType = DocTypeEnum.getByValue(menuEnum);
if (docType != null) {
return docType.getInfo();
}
return "其他文书";
}
/**
* 打印目录结构(优化缩进格式)
*
* @param nodes 节点列表
* @param indent 缩进级别0表示无缩进
*/
public static void printDirectory(List<DirectoryNode> nodes, int indent) {
for (DirectoryNode node : nodes) {
// 打印缩进和节点信息
System.out.println(" ".repeat(indent) + node.getName() + " (" + node.getLevel() + ")");
// 递归打印子节点,缩进+1
printDirectory(node.getChildren(), indent + 1);
}
}
}

View File

@@ -0,0 +1,156 @@
package com.openhis.web.document.util;
import com.openhis.common.enums.HisEnumInterface;
import java.util.*;
import java.util.stream.Collectors;
/**
* 枚举工具类
*/
public class EnumUtil {
/**
* 将枚举转换为包含 value、code、info 的 Map 列表
*
* @param enumClass 枚举类
* @return 包含枚举属性的 Map 列表
*/
public static List<Map<String, Object>> toMapList(Class<? extends HisEnumInterface> enumClass) {
if (enumClass == null || !enumClass.isEnum()) {
return Collections.emptyList();
}
return Arrays.stream(enumClass.getEnumConstants())
.map(EnumUtil::convertEnumToMap)
.collect(Collectors.toList());
}
/**
* 将枚举转换为包含 value、code、info 的 Map 列表
*
* @param enumClass 枚举类
* @param filterCodes 接收 code 集合(如 List<String>
* @return 包含枚举属性的 Map 列表
*/
public static List<Map<String, Object>> toMapListFilter(
Class<? extends HisEnumInterface> enumClass,
Collection<String> filterCodes // 接收 code 集合(如 List<String>
) {
// 入参校验enumClass 非法 或 filterCodes 为 null/空,直接返回空列表(或原枚举列表,按需调整)
if (enumClass == null || !enumClass.isEnum()) {
return Collections.emptyList();
}
// 若过滤集合为 null/空,返回所有枚举项(避免误过滤)
if (filterCodes == null || filterCodes.isEmpty()) {
return Arrays.stream(enumClass.getEnumConstants())
.map(EnumUtil::convertEnumToMap)
.collect(Collectors.toList());
}
// 核心逻辑:过滤掉 code 在 filterCodes 中的枚举项
return Arrays.stream(enumClass.getEnumConstants())
// 过滤条件:枚举的 code 不在过滤集合中
.filter(item -> !filterCodes.contains(item.getCode()))
// 转换为 Map
.map(EnumUtil::convertEnumToMap)
// 收集为 List
.collect(Collectors.toList());
}
/**
* 将枚举项转换为 Map
*
* @param enumItem 枚举项
* @return 包含 value、code、info 的 Map
*/
private static Map<String, Object> convertEnumToMap(HisEnumInterface enumItem) {
Map<String, Object> map = new HashMap<>(3);
map.put("value", enumItem.getValue());
map.put("code", enumItem.getCode());
map.put("info", enumItem.getInfo());
return map;
}
/**
* 获取枚举的所有 value 列表
*
* @param enumClass 枚举类
* @return value 列表
*/
public static List<Object> getValues(Class<? extends HisEnumInterface> enumClass) {
if (enumClass == null || !enumClass.isEnum()) {
return Collections.emptyList();
}
return Arrays.stream(enumClass.getEnumConstants())
.map(HisEnumInterface::getValue)
.collect(Collectors.toList());
}
/**
* 获取枚举的所有 code 列表
*
* @param enumClass 枚举类
* @return code 列表
*/
public static List<String> getCodes(Class<? extends HisEnumInterface> enumClass) {
if (enumClass == null || !enumClass.isEnum()) {
return Collections.emptyList();
}
return Arrays.stream(enumClass.getEnumConstants())
.map(HisEnumInterface::getCode)
.collect(Collectors.toList());
}
/**
* 获取枚举的所有 info 列表
*
* @param enumClass 枚举类
* @return info 列表
*/
public static List<String> getInfos(Class<? extends HisEnumInterface> enumClass) {
if (enumClass == null || !enumClass.isEnum()) {
return Collections.emptyList();
}
return Arrays.stream(enumClass.getEnumConstants())
.map(HisEnumInterface::getInfo)
.collect(Collectors.toList());
}
/**
* 根据 value 获取枚举项
*
* @param enumClass 枚举类
* @param value 枚举值
* @return 枚举项,未找到返回 null
*/
public static <T extends HisEnumInterface> T getByValue(Class<T> enumClass, Object value) {
if (enumClass == null || !enumClass.isEnum() || value == null) {
return null;
}
return Arrays.stream(enumClass.getEnumConstants())
.filter(item -> value.equals(item.getValue()))
.findFirst()
.orElse(null);
}
/**
* 根据 code 获取枚举项
*
* @param enumClass 枚举类
* @param code 枚举编码
* @return 枚举项,未找到返回 null
*/
public static <T extends HisEnumInterface> T getByCode(Class<T> enumClass, String code) {
if (enumClass == null || !enumClass.isEnum() || code == null) {
return null;
}
return Arrays.stream(enumClass.getEnumConstants())
.filter(item -> code.equals(item.getCode()))
.findFirst()
.orElse(null);
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,34 @@
package com.openhis.web.document.util;
import com.core.common.core.domain.entity.SysRole;
import com.core.common.utils.SecurityUtils;
import com.openhis.common.enums.DocPermissionEnum;
import com.openhis.web.document.dto.DocDefinitionDto;
import java.util.List;
public class PermissionProcessor {
public static boolean hasPermission(DocDefinitionDto docDefinitionDto) {
//肯定还得改
List<SysRole> roleList = SecurityUtils.getLoginUser().getRoleList();
boolean result = false;
for (SysRole role : roleList) {
if (role.getRoleKey().equals("admin")) {
return true;
}
if (role.getRoleKey().equals("doctor") && docDefinitionDto.getDoctorPermissionEnum() != DocPermissionEnum.VIEW.getValue()) {
return true;
}
if (role.getRoleKey().equals("nurse") && docDefinitionDto.getNursingPermissionEnum() != DocPermissionEnum.VIEW.getValue()) {
return true;
}
if (role.getRoleKey().equals("medicalSkill") && docDefinitionDto.getMedicalPermissionEnum() != DocPermissionEnum.VIEW.getValue()) {
return true;
}
if (role.getRoleKey().equals("pharmacist") && docDefinitionDto.getPharmacistPermissionEnum() != DocPermissionEnum.VIEW.getValue()) {
return true;
}
}
return result;
}
}