feat(检验申请): 新增检验申请单号生成功能并优化执行科室选择

refactor(检验申请): 重构申请单详情加载逻辑,使用后端接口获取完整数据
fix(检验申请): 修复执行科室默认值设置问题
fix(会诊): 修复就诊卡号取值错误和表格选中状态问题
perf(检验申请): 使用Redis实现并发安全的申请单号生成
docs(检验申请): 补充相关接口和方法注释
This commit is contained in:
wangjian963
2026-03-31 15:47:56 +08:00
parent b7993885bb
commit 5678535d88
10 changed files with 331 additions and 175 deletions

View File

@@ -186,6 +186,14 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
public R<?> getDiseaseTreatmentPage(DiagnosisTreatmentSelParam DiagnosisTreatmentSelParam, String searchKey,
Integer pageNo, Integer pageSize, HttpServletRequest request) {
// 如果没有指定状态默认只查询启用状态status_enum=2避免显示未启用的项目导致保存失败
if (DiagnosisTreatmentSelParam == null) {
DiagnosisTreatmentSelParam = new DiagnosisTreatmentSelParam();
}
if (DiagnosisTreatmentSelParam.getStatusEnum() == null) {
DiagnosisTreatmentSelParam.setStatusEnum(PublicationStatus.ACTIVE.getValue());
}
// 临时保存ybType值并从参数对象中移除避免HisQueryUtils构建yb_type条件
String ybTypeValue = null;
if (DiagnosisTreatmentSelParam != null && StringUtils.isNotEmpty(DiagnosisTreatmentSelParam.getYbType())) {

View File

@@ -19,4 +19,11 @@ public interface IDoctorStationInspectionLabApplyService {
* @return 删除结果
*/
R<?> deleteInspectionLabApply(String applyNo);
/**
* 生成检验申请单号
* 规则LS + YYYYMMDD + 5位流水号每日从1开始递增
* @return 申请单号
*/
String generateApplyNo();
}

View File

@@ -1,6 +1,7 @@
package com.openhis.web.doctorstation.appservice.impl;
import com.core.common.core.domain.R;
import com.core.common.core.redis.RedisCache;
import com.core.common.enums.DelFlag;
import com.core.common.utils.SecurityUtils;
import com.openhis.common.enums.DbOpType;
@@ -35,6 +36,8 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -76,6 +79,9 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
@Autowired
private IServiceRequestService serviceRequestService;
@Autowired
private RedisCache redisCache;
/**
* 保存检验申请单信息
* @param doctorStationLabApplyDto
@@ -116,8 +122,8 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
//设置从表申请单明细的申请单号
inspectionLabApplyItem.setApplyNo(doctorStationLabApplyDto.getApplyNo());
//检验科代码,取值于检验申请单
inspectionLabApplyItem.setPerformDeptCode(doctorStationLabApplyDto.getApplyDeptCode());
//执行科室代码,取值于检验申请单明细(前端传递的字典值)
inspectionLabApplyItem.setPerformDeptCode(doctorStationLabApplyItemDto.getPerformDeptCode());
//同主表状态,可单独回写
inspectionLabApplyItem.setItemStatus(doctorStationLabApplyDto.getApplyStatus());
// 设置项目序号 (打印顺序),按照遍历序号进行排序
@@ -194,6 +200,12 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
}
}
// 如果没有指定执行科室,使用当前医生所在的科室作为默认执行科室
if (positionId == null) {
positionId = SecurityUtils.getDeptId();
log.debug("检验项目未指定执行科室,使用当前科室:{}", positionId);
}
// 4. 创建医嘱保存对象
AdviceSaveDto adviceSaveDto = new AdviceSaveDto();
// 设置医嘱操作类型
@@ -279,14 +291,41 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
}
/**
* 根据申请单号查询检验申请单
* 根据申请单号查询检验申请单(包含检验项目明细)
*
* @param applyNo
* @return
*/
@Override
public Object getInspectionApplyByApplyNo(String applyNo) {
return doctorStationLabApplyMapper.getInspectionApplyByApplyNo(applyNo);
// 查询主表数据
DoctorStationLabApplyDto applyDto = (DoctorStationLabApplyDto) doctorStationLabApplyMapper.getInspectionApplyByApplyNo(applyNo);
if (applyDto == null) {
return null;
}
// 查询检验项目明细
List<InspectionLabApplyItem> itemList = inspectionLabApplyItemService.list(
new QueryWrapper<InspectionLabApplyItem>()
.eq("apply_no", applyNo)
.eq("delete_flag", "0")
.orderByAsc("item_seq")
);
// 转换为 DTO 列表
List<DoctorStationLabApplyItemDto> itemDtoList = new ArrayList<>();
if (itemList != null && !itemList.isEmpty()) {
for (InspectionLabApplyItem item : itemList) {
DoctorStationLabApplyItemDto itemDto = new DoctorStationLabApplyItemDto();
BeanUtils.copyProperties(item, itemDto);
itemDtoList.add(itemDto);
}
// 从第一个明细项获取执行科室代码
applyDto.setExecuteDepartment(itemList.get(0).getPerformDeptCode());
}
applyDto.setLabApplyItemList(itemDtoList);
return applyDto;
}
/**
@@ -502,7 +541,7 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
);
if (deleteResult) {
log.debug("成功删除申请单号 [{}] 的条码数据,更新人:{},更新时间:{}",
log.debug("成功删除申请单号 [{}] 的条码数据,更新人:{},更新时间:{}",
applyNo, currentUsername, currentTime);
} else {
log.warn("删除申请单号 [{}] 的条码数据失败", applyNo);
@@ -514,4 +553,38 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
}
}
/**
* 生成检验申请单号
* 规则LS + YYYYMMDD + 5位流水号每日从1开始递增
* 支持并发安全:使用 Redis 原子递增保证唯一性
* @return 申请单号
*/
@Override
public String generateApplyNo() {
// 获取当前日期
LocalDate today = LocalDate.now();
String dateStr = today.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
// 生成前缀LS + 日期
String prefix = "LS" + dateStr;
// Redis key 用于存储当天的流水号
String redisKey = "lab_apply_no:" + dateStr;
// 使用 Redis 原子递增获取流水号(并发安全)
long sequence = redisCache.incr(redisKey, 1);
// 设置 Redis key 过期时间为 2 天,避免数据积累
redisCache.expire(redisKey, 2 * 24 * 60 * 60);
// 格式化流水号为5位不足前补0
String sequenceStr = String.format("%05d", sequence);
// 生成完整的申请单号
String applyNo = prefix + sequenceStr;
log.debug("生成检验申请单号:{}", applyNo);
return applyNo;
}
}

View File

@@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import org.springframework.validation.annotation.Validated;
import java.util.HashMap;
import java.util.Map;
/**
* 门诊医生站-检验控制器
@@ -62,4 +64,18 @@ public class DoctorStationInspectionLabApplyController {
log.debug("删除检验申请单:{}", applyNo);
return R.ok(iDoctorStationInspectionLabApplyService.deleteInspectionLabApply(applyNo));
}
/**
* 生成检验申请单号
* 规则LS + YYYYMMDD + 5位流水号每日从1开始递增
* @return 申请单号
*/
@GetMapping(value = "/generate-apply-no")
public R<?> generateApplyNo(){
log.debug("生成检验申请单号");
String applyNo = iDoctorStationInspectionLabApplyService.generateApplyNo();
Map<String, String> result = new HashMap<>();
result.put("applyNo", applyNo);
return R.ok(result);
}
}

View File

@@ -135,6 +135,10 @@ public class DoctorStationLabApplyDto {
* 就诊id
*/
private Long encounterId;
/**
* 执行科室代码(从明细项获取)
*/
private String executeDepartment;
/**
* 检验项目数据列表
*/

View File

@@ -11,6 +11,11 @@ import java.util.List;
*/
@Repository
public interface DoctorStationLabApplyMapper {
/**
* 根据申请单号查询检验申请单
* @param applyNo 申请单号
* @return 检验申请单DTO
*/
Object getInspectionApplyByApplyNo(String applyNo);
/**

View File

@@ -4,9 +4,36 @@
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.openhis.web.doctorstation.mapper.DoctorStationLabApplyMapper">
<!-- 根据申请单号查询检验申请单 -->
<!-- 根据申请单号查询检验申请单(返回完整字段) -->
<select id="getInspectionApplyByApplyNo" resultType="com.openhis.web.doctorstation.dto.DoctorStationLabApplyDto">
SELECT apply_no AS applyNo
SELECT
apply_no AS applyNo,
patient_id AS patientId,
patient_name AS patientName,
medicalrecord_number AS medicalrecordNumber,
natureof_cost AS natureofCost,
visit_no AS visitNo,
apply_dept_code AS applyDeptCode,
apply_department AS applyDepartment,
apply_doc_code AS applyDocCode,
apply_doc_name AS applyDocName,
apply_time AS applyTime,
clinic_diag AS clinicDiag,
clinic_desc AS clinicDesc,
contraindication AS contraindication,
medical_history_summary AS medicalHistorySummary,
purposeof_inspection AS purposeofInspection,
physical_examination AS physicalExamination,
inspection_item AS inspectionItem,
specimen_type_code AS specimenTypeCode,
specimen_name AS specimenName,
priority_code AS priorityCode,
apply_status AS applyStatus,
apply_remark AS applyRemark,
create_time AS createTime,
operator_id AS operatorId,
create_by AS createBy,
tenant_id AS tenantId
FROM lab_apply
WHERE apply_no = #{applyNo}
AND delete_flag = '0'