fixbug326,329,334,368: 门诊医生站检验申请模块多项缺陷修复
Bug #326: 检验申请单套餐项目回充数据不完整 - 后端回充时查询 LabActivityDefinition 补全套餐信 - DTO 新增 activityId、feePackageId、isPackage、sampleType、unit 字段 - 前端实现套餐项目树形展开,懒加载套餐明细 Bug #329: 检验申请执行科室默认值设置错误 - 后端移除默认执行科室逻辑,添加未匹配科室警告日志 - 前端从 Organization 表获取执行科室,自动根据检验类型设置默认值 Bug #334: 检验申请界面顶部操作栏占用空间过大 - 隐藏顶部操作栏,保存/新增按钮移至卡片头部 Bug #368: 门诊医生站待写病历标签页功能冗余 - 屏蔽待写病历标签页(左侧导航栏已有独立菜单)
This commit is contained in:
@@ -11,10 +11,12 @@ import com.openhis.lab.domain.InspectionLabApply;
|
|||||||
import com.openhis.lab.domain.InspectionLabApplyItem;
|
import com.openhis.lab.domain.InspectionLabApplyItem;
|
||||||
import com.openhis.lab.domain.BarCode;
|
import com.openhis.lab.domain.BarCode;
|
||||||
import com.openhis.lab.domain.InspectionPackage;
|
import com.openhis.lab.domain.InspectionPackage;
|
||||||
|
import com.openhis.lab.domain.LabActivityDefinition;
|
||||||
import com.openhis.lab.service.IInspectionLabApplyItemService;
|
import com.openhis.lab.service.IInspectionLabApplyItemService;
|
||||||
import com.openhis.lab.service.IInspectionLabApplyService;
|
import com.openhis.lab.service.IInspectionLabApplyService;
|
||||||
import com.openhis.lab.service.IInspectionLabBarCodeService;
|
import com.openhis.lab.service.IInspectionLabBarCodeService;
|
||||||
import com.openhis.lab.service.IInspectionPackageService;
|
import com.openhis.lab.service.IInspectionPackageService;
|
||||||
|
import com.openhis.lab.service.ILabActivityDefinitionService;
|
||||||
import com.openhis.workflow.domain.ServiceRequest;
|
import com.openhis.workflow.domain.ServiceRequest;
|
||||||
import com.openhis.workflow.service.IServiceRequestService;
|
import com.openhis.workflow.service.IServiceRequestService;
|
||||||
import com.openhis.web.doctorstation.appservice.IDoctorStationAdviceAppService;
|
import com.openhis.web.doctorstation.appservice.IDoctorStationAdviceAppService;
|
||||||
@@ -45,6 +47,9 @@ import java.util.Date;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据检验申请单开单信息系统自动插入门诊医嘱表(与检验申请主表申请单号进行关联),
|
* 根据检验申请单开单信息系统自动插入门诊医嘱表(与检验申请主表申请单号进行关联),
|
||||||
@@ -88,6 +93,10 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
|||||||
@Autowired
|
@Autowired
|
||||||
private IInspectionPackageService inspectionPackageService;
|
private IInspectionPackageService inspectionPackageService;
|
||||||
|
|
||||||
|
// Bug #326: 检验项目定义服务(用于回充时获取套餐信息)
|
||||||
|
@Autowired
|
||||||
|
private ILabActivityDefinitionService labActivityDefinitionService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存检验申请单信息
|
* 保存检验申请单信息
|
||||||
* @param doctorStationLabApplyDto
|
* @param doctorStationLabApplyDto
|
||||||
@@ -160,6 +169,28 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
|||||||
InspectionLabApplyItem inspectionLabApplyItem = new InspectionLabApplyItem();
|
InspectionLabApplyItem inspectionLabApplyItem = new InspectionLabApplyItem();
|
||||||
BeanUtils.copyProperties(doctorStationLabApplyItemDto, inspectionLabApplyItem);
|
BeanUtils.copyProperties(doctorStationLabApplyItemDto, inspectionLabApplyItem);
|
||||||
|
|
||||||
|
// 前端选择检验项目时已携带完整的关联信息(activityId、feePackageId、itemCode等)
|
||||||
|
// Bug #326修复: 只使用 activityId 直接查询,不使用名称反查
|
||||||
|
Long activityId = doctorStationLabApplyItemDto.getActivityId();
|
||||||
|
if (activityId != null) {
|
||||||
|
// 使用 activityId 直接查询检验项目定义
|
||||||
|
LabActivityDefinition labActivityDefinition = labActivityDefinitionService.getById(activityId);
|
||||||
|
if (labActivityDefinition != null && DelFlag.NO.getCode().equals(labActivityDefinition.getDeleteFlag())) {
|
||||||
|
// 补充编码(如果前端未传或为空)
|
||||||
|
if (inspectionLabApplyItem.getItemCode() == null || inspectionLabApplyItem.getItemCode().isEmpty()) {
|
||||||
|
inspectionLabApplyItem.setItemCode(labActivityDefinition.getBusNo());
|
||||||
|
}
|
||||||
|
// 补充套餐ID(如果前端未传)
|
||||||
|
if (inspectionLabApplyItem.getFeePackageId() == null) {
|
||||||
|
inspectionLabApplyItem.setFeePackageId(labActivityDefinition.getFeePackageId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 没有 activityId 时记录警告,不使用名称反查
|
||||||
|
log.warn("检验项目 [{}] 未传入 activityId,无法获取完整关联信息",
|
||||||
|
doctorStationLabApplyItemDto.getItemName());
|
||||||
|
}
|
||||||
|
|
||||||
// 后端重新计算金额:金额 = 单价 × 数量
|
// 后端重新计算金额:金额 = 单价 × 数量
|
||||||
java.math.BigDecimal itemPrice = doctorStationLabApplyItemDto.getItemPrice();
|
java.math.BigDecimal itemPrice = doctorStationLabApplyItemDto.getItemPrice();
|
||||||
java.math.BigDecimal itemQty = doctorStationLabApplyItemDto.getItemQty();
|
java.math.BigDecimal itemQty = doctorStationLabApplyItemDto.getItemQty();
|
||||||
@@ -241,13 +272,16 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
|||||||
);
|
);
|
||||||
if (organization != null) {
|
if (organization != null) {
|
||||||
positionId = organization.getId();
|
positionId = organization.getId();
|
||||||
|
} else {
|
||||||
|
// Bug #329: 执行科室代码无法匹配到科室,记录警告日志
|
||||||
|
log.warn("执行科室代码 [{}] 在科室表中未找到对应记录", performDeptCode);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Bug #329: 未指定执行科室,记录警告日志
|
||||||
|
log.warn("检验项目 [{}] 未指定执行科室", itemName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有指定执行科室,使用当前医生所在的科室作为默认执行科室
|
// Bug #329: 移除默认执行科室逻辑,必须由前端明确指定执行科室
|
||||||
if (positionId == null) {
|
|
||||||
positionId = SecurityUtils.getDeptId();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 创建医嘱保存对象
|
// 4. 创建医嘱保存对象
|
||||||
AdviceSaveDto adviceSaveDto = new AdviceSaveDto();
|
AdviceSaveDto adviceSaveDto = new AdviceSaveDto();
|
||||||
@@ -324,7 +358,6 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
|||||||
throw new RuntimeException("套餐项目 '" + itemName + "' 未设置有效价格,请先配置套餐金额");
|
throw new RuntimeException("套餐项目 '" + itemName + "' 未设置有效价格,请先配置套餐金额");
|
||||||
}
|
}
|
||||||
unitPrice = packageInfo.getPackageAmount();
|
unitPrice = packageInfo.getPackageAmount();
|
||||||
log.info("套餐项目 '{}' 使用套餐价格: {}", itemName, unitPrice);
|
|
||||||
} else {
|
} else {
|
||||||
// 普通项目:使用前端传入的价格
|
// 普通项目:使用前端传入的价格
|
||||||
unitPrice = labApplyItemDto.getItemPrice();
|
unitPrice = labApplyItemDto.getItemPrice();
|
||||||
@@ -367,30 +400,84 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Object getInspectionApplyByApplyNo(String applyNo) {
|
public Object getInspectionApplyByApplyNo(String applyNo) {
|
||||||
// 查询主表数据
|
// 使用MyBatis-Plus查询主表数据
|
||||||
DoctorStationLabApplyDto applyDto = (DoctorStationLabApplyDto) doctorStationLabApplyMapper.getInspectionApplyByApplyNo(applyNo);
|
InspectionLabApply mainEntity = inspectionLabApplyService.getOne(
|
||||||
if (applyDto == null) {
|
new QueryWrapper<InspectionLabApply>()
|
||||||
|
.eq("apply_no", applyNo)
|
||||||
|
.eq("delete_flag", DelFlag.NO.getCode())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (mainEntity == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 使用BeanUtils进行基础字段映射
|
||||||
|
DoctorStationLabApplyDto applyDto = new DoctorStationLabApplyDto();
|
||||||
|
BeanUtils.copyProperties(mainEntity, applyDto);
|
||||||
|
// 由于字段名称映射关系(如 id -> applicationId),需要单独设置
|
||||||
|
applyDto.setApplicationId(mainEntity.getId());
|
||||||
|
|
||||||
// 查询检验项目明细
|
// 查询检验项目明细
|
||||||
List<InspectionLabApplyItem> itemList = inspectionLabApplyItemService.list(
|
List<InspectionLabApplyItem> itemList = inspectionLabApplyItemService.list(
|
||||||
new QueryWrapper<InspectionLabApplyItem>()
|
new QueryWrapper<InspectionLabApplyItem>()
|
||||||
.eq("apply_no", applyNo)
|
.eq("apply_no", applyNo)
|
||||||
.eq("delete_flag", "0")
|
.eq("delete_flag", DelFlag.NO.getCode())
|
||||||
.orderByAsc("item_seq")
|
.orderByAsc("item_seq")
|
||||||
);
|
);
|
||||||
|
|
||||||
// 转换为 DTO 列表
|
// 转换为 DTO 列表
|
||||||
List<DoctorStationLabApplyItemDto> itemDtoList = new ArrayList<>();
|
List<DoctorStationLabApplyItemDto> itemDtoList = new ArrayList<>();
|
||||||
if (itemList != null && !itemList.isEmpty()) {
|
if (itemList != null && !itemList.isEmpty()) {
|
||||||
|
// 提取所有不同的 itemCode,用于批量查询
|
||||||
|
Set<String> itemCodes = itemList.stream()
|
||||||
|
.filter(item -> item.getItemCode() != null && !item.getItemCode().isEmpty())
|
||||||
|
.map(InspectionLabApplyItem::getItemCode)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
// 批量查询所有关联的检验项目定义(使用MyBatis-Plus)
|
||||||
|
Map<String, LabActivityDefinition> definitionMap = new HashMap<>();
|
||||||
|
if (!itemCodes.isEmpty()) {
|
||||||
|
List<LabActivityDefinition> labActivityDefinitions = labActivityDefinitionService.list(
|
||||||
|
new QueryWrapper<LabActivityDefinition>()
|
||||||
|
.in("bus_no", itemCodes)
|
||||||
|
.eq("delete_flag", DelFlag.NO.getCode())
|
||||||
|
);
|
||||||
|
// 构建 itemCode 到定义的映射
|
||||||
|
definitionMap = labActivityDefinitions.stream()
|
||||||
|
.collect(Collectors.toMap(LabActivityDefinition::getBusNo, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理每个明细项
|
||||||
for (InspectionLabApplyItem item : itemList) {
|
for (InspectionLabApplyItem item : itemList) {
|
||||||
DoctorStationLabApplyItemDto itemDto = new DoctorStationLabApplyItemDto();
|
DoctorStationLabApplyItemDto itemDto = new DoctorStationLabApplyItemDto();
|
||||||
|
// 使用BeanUtils进行基础字段映射
|
||||||
BeanUtils.copyProperties(item, itemDto);
|
BeanUtils.copyProperties(item, itemDto);
|
||||||
|
|
||||||
|
// feePackageId 在保存时已存储,直接使用
|
||||||
|
itemDto.setFeePackageId(item.getFeePackageId());
|
||||||
|
// 判断是否是套餐项目(根据 feePackageId 是否存在)
|
||||||
|
itemDto.setIsPackage(item.getFeePackageId() != null);
|
||||||
|
|
||||||
|
// 从批量查询结果中获取关联信息
|
||||||
|
if (item.getItemCode() != null && !item.getItemCode().isEmpty()) {
|
||||||
|
LabActivityDefinition labActivityDefinition = definitionMap.get(item.getItemCode());
|
||||||
|
if (labActivityDefinition != null) {
|
||||||
|
itemDto.setActivityId(labActivityDefinition.getId());
|
||||||
|
itemDto.setSampleType(labActivityDefinition.getSpecimenCode());
|
||||||
|
itemDto.setUnit(labActivityDefinition.getPermittedUnitCode());
|
||||||
|
// 补充检验类型ID,用于前端自动设置执行科室
|
||||||
|
itemDto.setInspectionTypeId(labActivityDefinition.getInspectionTypeId());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("检验项目 [{}] 未存储 itemCode,无法获取完整关联信息", item.getItemName());
|
||||||
|
}
|
||||||
|
|
||||||
itemDtoList.add(itemDto);
|
itemDtoList.add(itemDto);
|
||||||
}
|
}
|
||||||
// 从第一个明细项获取执行科室代码
|
// 从第一个明细项获取执行科室代码
|
||||||
applyDto.setExecuteDepartment(itemList.get(0).getPerformDeptCode());
|
if (!itemList.isEmpty() && itemList.get(0).getPerformDeptCode() != null) {
|
||||||
|
applyDto.setExecuteDepartment(itemList.get(0).getPerformDeptCode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
applyDto.setLabApplyItemList(itemDtoList);
|
applyDto.setLabApplyItemList(itemDtoList);
|
||||||
|
|
||||||
@@ -409,8 +496,9 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
|||||||
// 使用 PageHelper 进行分页查询
|
// 使用 PageHelper 进行分页查询
|
||||||
PageHelper.startPage(pageNo, pageSize);
|
PageHelper.startPage(pageNo, pageSize);
|
||||||
|
|
||||||
// 查询检验申请单列表
|
// 使用MyBatis-Plus查询检验申请单列表
|
||||||
log.debug("查询申请单数据前");
|
// 需要关联adm_encounter表,仍使用原Mapper方法或重构为MyBatis-Plus方式
|
||||||
|
// 为保持一致性和考虑到复杂的关联查询,暂时保留原有实现方式
|
||||||
List<DoctorStationLabApplyDto> list = doctorStationLabApplyMapper.getInspectionApplyListPage(encounterId);
|
List<DoctorStationLabApplyDto> list = doctorStationLabApplyMapper.getInspectionApplyListPage(encounterId);
|
||||||
log.debug("查询申请单数据后");
|
log.debug("查询申请单数据后");
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.openhis.web.doctorstation.dto;
|
package com.openhis.web.doctorstation.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
@@ -67,4 +69,42 @@ public class DoctorStationLabApplyItemDto {
|
|||||||
*/
|
*/
|
||||||
@NotNull(message = "行状态不能为空")
|
@NotNull(message = "行状态不能为空")
|
||||||
private Long itemStatus;
|
private Long itemStatus;
|
||||||
|
|
||||||
|
// ========== Bug #326: 套餐相关字段(回充时需要) ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 活动定义ID(检验项目定义ID)
|
||||||
|
* 用于回充时关联到原始检验项目定义
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long activityId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 套餐ID(如果该项目是套餐,则关联套餐表)
|
||||||
|
* 对应 InspectionPackage.basicInformationId
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long feePackageId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否是套餐项目
|
||||||
|
*/
|
||||||
|
private Boolean isPackage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 样本类型
|
||||||
|
*/
|
||||||
|
private String sampleType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单位
|
||||||
|
*/
|
||||||
|
private String unit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检验类型ID(关联 inspection_type 大类)
|
||||||
|
* 用于前端自动设置执行科室
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long inspectionTypeId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,41 +4,6 @@
|
|||||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
<mapper namespace="com.openhis.web.doctorstation.mapper.DoctorStationLabApplyMapper">
|
<mapper namespace="com.openhis.web.doctorstation.mapper.DoctorStationLabApplyMapper">
|
||||||
|
|
||||||
<!-- 根据申请单号查询检验申请单(返回完整字段) -->
|
|
||||||
<select id="getInspectionApplyByApplyNo" resultType="com.openhis.web.doctorstation.dto.DoctorStationLabApplyDto">
|
|
||||||
SELECT
|
|
||||||
id AS applicationId,
|
|
||||||
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'
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<!-- 分页查询检验申请单列表(根据就诊ID查询,按申请时间降序)
|
<!-- 分页查询检验申请单列表(根据就诊ID查询,按申请时间降序)
|
||||||
从明细表聚合项目名称和金额-->
|
从明细表聚合项目名称和金额-->
|
||||||
|
|||||||
@@ -74,4 +74,9 @@ public class InspectionLabApplyItem extends HisBaseEntity {
|
|||||||
*/
|
*/
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
private Long itemStatus;
|
private Long itemStatus;
|
||||||
|
/**
|
||||||
|
* 套餐ID
|
||||||
|
*/
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long feePackageId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-container class="inspection-application-container">
|
<el-container class="inspection-application-container">
|
||||||
|
|
||||||
<!-- 顶部操作按钮区 - Bug#334: 优化垂直空间利用率 -->
|
|
||||||
<el-header class="top-action-bar" height="48px">
|
<el-header class="top-action-bar" height="48px">
|
||||||
<el-row class="action-buttons" type="flex" justify="end" :gutter="8">
|
<el-row class="action-buttons" type="flex" justify="end" :gutter="8">
|
||||||
<el-button type="primary" size="default" @click="handleSave" class="save-btn" :loading="saving">
|
<el-button type="primary" size="default" @click="handleSave" class="save-btn" :loading="saving">
|
||||||
@@ -19,10 +17,22 @@
|
|||||||
<el-main class="inspection-section" style="width: 100%; max-width: 100%">
|
<el-main class="inspection-section" style="width: 100%; max-width: 100%">
|
||||||
<el-card class="table-card" style="width: 100%">
|
<el-card class="table-card" style="width: 100%">
|
||||||
<template #header>
|
<template #header>
|
||||||
<el-row class="card-header" type="flex" align="middle">
|
<div class="card-header-flex">
|
||||||
<el-icon><DocumentChecked /></el-icon>
|
<div class="header-title">
|
||||||
<span>检验信息</span>
|
<el-icon><DocumentChecked /></el-icon>
|
||||||
</el-row>
|
<span>检验信息</span>
|
||||||
|
</div>
|
||||||
|
<div class="header-actions">
|
||||||
|
<el-button type="primary" size="default" @click="handleSave" class="save-btn" :loading="saving">
|
||||||
|
<el-icon><Document /></el-icon>
|
||||||
|
保存
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" size="default" @click="handleNewApplication" class="new-btn">
|
||||||
|
<el-icon><Plus /></el-icon>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-table
|
<el-table
|
||||||
ref="inspectionTableRef"
|
ref="inspectionTableRef"
|
||||||
@@ -41,7 +51,6 @@
|
|||||||
@current-change="handleRowClick"
|
@current-change="handleRowClick"
|
||||||
@cell-click="handleCellClick"
|
@cell-click="handleCellClick"
|
||||||
>
|
>
|
||||||
<!-- Bug #326: 添加展开列 -->
|
|
||||||
<el-table-column type="expand" width="50" align="center" header-align="center">
|
<el-table-column type="expand" width="50" align="center" header-align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div v-if="scope.row.children && scope.row.children.length > 0" class="expand-content">
|
<div v-if="scope.row.children && scope.row.children.length > 0" class="expand-content">
|
||||||
@@ -114,7 +123,7 @@
|
|||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-row type="flex" align="middle" justify="center" :gutter="8">
|
<el-row type="flex" align="middle" justify="center" :gutter="8">
|
||||||
<el-button link size="default" @click="handlePrint(scope.row)" :icon="Printer" title="打印" style="font-size: 16px"></el-button>
|
<el-button link size="default" @click="handlePrint(scope.row)" :icon="Printer" title="打印" style="font-size: 16px"></el-button>
|
||||||
<el-button link size="default" @click="handleDelete(scope.row)" :icon="Delete" style="color: #f56c6c; font-size: 16px" title="删除"></el-button>
|
<el-button link size="default" @click.stop="handleDelete(scope.row)" :icon="Delete" style="color: #f56c6c; font-size: 16px" title="删除"></el-button>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -406,7 +415,6 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<h4 style="margin: 0; font-weight: bold">检验信息详情</h4>
|
<h4 style="margin: 0; font-weight: bold">检验信息详情</h4>
|
||||||
</template>
|
</template>
|
||||||
<!-- Bug #326: 添加树形展开功能,支持套餐明细展示 -->
|
|
||||||
<el-table
|
<el-table
|
||||||
:data="selectedInspectionItems"
|
:data="selectedInspectionItems"
|
||||||
border
|
border
|
||||||
@@ -414,12 +422,12 @@
|
|||||||
style="width: 100%; min-width: 100%"
|
style="width: 100%; min-width: 100%"
|
||||||
max-height="250"
|
max-height="250"
|
||||||
row-key="itemId"
|
row-key="itemId"
|
||||||
|
lazy
|
||||||
|
:load="loadPackageDetailsForTable"
|
||||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||||
default-expand-all
|
|
||||||
>
|
>
|
||||||
<el-table-column label="项目名称" prop="itemName" min-width="180">
|
<el-table-column label="项目名称" prop="itemName" min-width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<!-- BugFix#326: 套餐项目添加标识和加粗显示 -->
|
|
||||||
<el-tag v-if="scope.row.isPackage" size="small" type="warning" style="margin-right: 4px">套餐</el-tag>
|
<el-tag v-if="scope.row.isPackage" size="small" type="warning" style="margin-right: 4px">套餐</el-tag>
|
||||||
<span :style="{ fontWeight: scope.row.isPackage ? 'bold' : 'normal' }">
|
<span :style="{ fontWeight: scope.row.isPackage ? 'bold' : 'normal' }">
|
||||||
{{ scope.row.itemName }}
|
{{ scope.row.itemName }}
|
||||||
@@ -538,7 +546,6 @@
|
|||||||
@change="toggleInspectionItem(item)"
|
@change="toggleInspectionItem(item)"
|
||||||
@click.stop
|
@click.stop
|
||||||
/>
|
/>
|
||||||
<!-- BugFix#326: 套餐项目添加标识 -->
|
|
||||||
<el-tag v-if="item.isPackage" size="small" type="warning" style="margin-right: 4px">套餐</el-tag>
|
<el-tag v-if="item.isPackage" size="small" type="warning" style="margin-right: 4px">套餐</el-tag>
|
||||||
<span class="item-itemName">{{ item.itemName }}</span>
|
<span class="item-itemName">{{ item.itemName }}</span>
|
||||||
<span class="item-price">¥{{ item.itemPrice }}</span>
|
<span class="item-price">¥{{ item.itemPrice }}</span>
|
||||||
@@ -659,7 +666,7 @@ import { debounce } from 'lodash-es'
|
|||||||
|
|
||||||
// 获取当前组件实例和字典
|
// 获取当前组件实例和字典
|
||||||
const { proxy } = getCurrentInstance()
|
const { proxy } = getCurrentInstance()
|
||||||
const { inspection_lab_dept } = proxy.useDict('inspection_lab_dept')
|
// Bug #329: 移除 inspection_lab_dept 字典,执行科室数据从 Organization 表获取
|
||||||
|
|
||||||
// 动态获取的检验类型缓存(用于缓存不在 inspectionCategories 中的检验类型)
|
// 动态获取的检验类型缓存(用于缓存不在 inspectionCategories 中的检验类型)
|
||||||
const dynamicInspectionTypesCache = ref([])
|
const dynamicInspectionTypesCache = ref([])
|
||||||
@@ -785,9 +792,123 @@ const loading = ref(false)
|
|||||||
const saving = ref(false) // 保存状态
|
const saving = ref(false) // 保存状态
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const leftActiveTab = ref('application')
|
const leftActiveTab = ref('application')
|
||||||
// Bug #326: 展开的行
|
|
||||||
const expandedRowKeys = ref([])
|
const expandedRowKeys = ref([])
|
||||||
|
|
||||||
|
const isExpanded = (applicationId) => {
|
||||||
|
return expandedRowKeys.value.includes(applicationId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleExpand = async (row) => {
|
||||||
|
const applicationId = row.applicationId
|
||||||
|
const isCurrentlyExpanded = isExpanded(applicationId)
|
||||||
|
|
||||||
|
if (isCurrentlyExpanded) {
|
||||||
|
// 收起
|
||||||
|
expandedRowKeys.value = expandedRowKeys.value.filter(id => id !== applicationId)
|
||||||
|
} else {
|
||||||
|
// 展开 - 先检查是否需要加载明细数据
|
||||||
|
if (row.hasChildren && (!row.children || row.children.length === 0)) {
|
||||||
|
// 加载套餐明细
|
||||||
|
await loadPackageDetails(row)
|
||||||
|
}
|
||||||
|
expandedRowKeys.value = [...expandedRowKeys.value, applicationId]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleExpandChange = (row, expandedRows) => {
|
||||||
|
expandedRowKeys.value = expandedRows.map(r => r.applicationId)
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadPackageDetails = async (row) => {
|
||||||
|
try {
|
||||||
|
const packageId = row.feePackageId || row.packageId
|
||||||
|
if (!packageId) return
|
||||||
|
|
||||||
|
const res = await getInspectionPackageDetails(packageId)
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
row.children = res.data.map(detail => ({
|
||||||
|
itemId: detail.detailId || detail.id || detail.itemId,
|
||||||
|
itemName: detail.itemName || detail.name,
|
||||||
|
sampleType: detail.sampleType || '',
|
||||||
|
unit: detail.unit || '',
|
||||||
|
itemPrice: detail.unitPrice || detail.itemPrice || detail.price || 0,
|
||||||
|
itemQty: detail.quantity || detail.itemQty || detail.qty || 1,
|
||||||
|
itemAmount: (detail.unitPrice || detail.itemPrice || 0) * (detail.quantity || detail.itemQty || 1)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载套餐明细失败:', error)
|
||||||
|
row.children = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadPackageDetailsForTable = async (row, treeNode, resolve) => {
|
||||||
|
if (!row.isPackage) {
|
||||||
|
resolve([])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const packageId = row.feePackageId || row.packageId
|
||||||
|
if (!packageId) {
|
||||||
|
resolve([])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await getInspectionPackageDetails(packageId)
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
// 构建明细数据结构
|
||||||
|
// BugFix: 后端返回字段为 unitPrice 和 quantity,需正确映射
|
||||||
|
const children = res.data.map(detail => ({
|
||||||
|
itemId: detail.detailId || detail.id || detail.itemId,
|
||||||
|
itemName: detail.itemName || detail.name,
|
||||||
|
sampleType: detail.sampleType || '',
|
||||||
|
unit: detail.unit || '',
|
||||||
|
itemPrice: detail.unitPrice || detail.itemPrice || detail.price || 0,
|
||||||
|
itemQty: detail.quantity || detail.itemQty || detail.qty || 1,
|
||||||
|
itemAmount: (detail.unitPrice || detail.itemPrice || 0) * (detail.quantity || detail.itemQty || 1)
|
||||||
|
}))
|
||||||
|
resolve(children)
|
||||||
|
} else {
|
||||||
|
resolve([])
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载套餐明细失败:', error)
|
||||||
|
resolve([])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const togglePackageExpand = async (item) => {
|
||||||
|
if (!item.isPackage) return
|
||||||
|
|
||||||
|
item.expanded = !item.expanded
|
||||||
|
|
||||||
|
if (item.expanded && (!item.children || item.children.length === 0)) {
|
||||||
|
item.loading = true
|
||||||
|
try {
|
||||||
|
const packageId = item.feePackageId || item.packageId
|
||||||
|
if (packageId) {
|
||||||
|
const res = await getInspectionPackageDetails(packageId)
|
||||||
|
if (res.code === 200 && res.data) {
|
||||||
|
item.children = res.data.map(detail => ({
|
||||||
|
detailId: detail.detailId || detail.id || detail.itemId,
|
||||||
|
itemName: detail.itemName || detail.name,
|
||||||
|
unit: detail.unit || '',
|
||||||
|
quantity: detail.quantity || detail.itemQty || detail.qty || 1,
|
||||||
|
unitPrice: detail.unitPrice || detail.itemPrice || detail.price || 0,
|
||||||
|
itemPrice: detail.unitPrice || detail.itemPrice || detail.price || 0
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载套餐明细失败:', error)
|
||||||
|
item.children = []
|
||||||
|
} finally {
|
||||||
|
item.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 申请日期实时更新定时器
|
// 申请日期实时更新定时器
|
||||||
let applyTimeTimer = null
|
let applyTimeTimer = null
|
||||||
|
|
||||||
@@ -856,6 +977,9 @@ const executeDepartmentOptions = ref([])
|
|||||||
// 执行科室加载完成标志(BugFix#CodeReview: 防止竞态条件)
|
// 执行科室加载完成标志(BugFix#CodeReview: 防止竞态条件)
|
||||||
const isExecuteDepartmentLoaded = ref(false)
|
const isExecuteDepartmentLoaded = ref(false)
|
||||||
|
|
||||||
|
// 删除操作标志,用于避免删除时触发数据填充
|
||||||
|
const isDeleting = ref(false)
|
||||||
|
|
||||||
// 表单数据
|
// 表单数据
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
applyOrganizationId: '',
|
applyOrganizationId: '',
|
||||||
@@ -1544,17 +1668,27 @@ const handleSave = () => {
|
|||||||
|
|
||||||
// 准备保存数据
|
// 准备保存数据
|
||||||
const prepareSaveData = () => {
|
const prepareSaveData = () => {
|
||||||
// 将执行科室代码赋值给每个检验项目
|
|
||||||
const labApplyItemList = selectedInspectionItems.value.map(item => ({
|
const labApplyItemList = selectedInspectionItems.value.map(item => ({
|
||||||
...item,
|
itemSeq: item.itemSeq || 1,
|
||||||
performDeptCode: formData.executeDepartment // 从字典获取的执行科室代码
|
itemCode: item.code || '',
|
||||||
|
itemName: item.itemName || '',
|
||||||
|
itemPrice: item.itemPrice || 0,
|
||||||
|
itemQty: item.itemQty || 1,
|
||||||
|
itemAmount: item.itemAmount || 0,
|
||||||
|
itemStatus: formData.applyStatus || 0,
|
||||||
|
performDeptCode: formData.executeDepartment,
|
||||||
|
// Bug #326修复: 传入 activityId,后端直接使用 ID 关联,避免用名称反查
|
||||||
|
activityId: item.activityId || item.itemId || null,
|
||||||
|
feePackageId: item.feePackageId || null,
|
||||||
|
isPackage: item.isPackage || false,
|
||||||
|
sampleType: item.sampleType || '',
|
||||||
|
unit: item.unit || ''
|
||||||
}))
|
}))
|
||||||
return {
|
return {
|
||||||
...formData,
|
...formData,
|
||||||
labApplyItemList,
|
labApplyItemList,
|
||||||
physicalExamination: formData.physicalExam, // 字段名映射:前端 physicalExam -> 后端 physicalExamination
|
physicalExamination: formData.physicalExam,
|
||||||
inspectionItemsText: selectedInspectionItems.value.map(item => item.itemName).join('+')
|
inspectionItemsText: selectedInspectionItems.value.map(item => item.itemName).join('+')
|
||||||
// 金额由后端计算,前端不传递
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1563,6 +1697,7 @@ const handleSave = () => {
|
|||||||
executeSave(saveData);
|
executeSave(saveData);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const executeSave = (saveData) => {
|
const executeSave = (saveData) => {
|
||||||
saveInspectionApplication(saveData).then((res) => {
|
saveInspectionApplication(saveData).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
@@ -1725,6 +1860,8 @@ const handlePrint = (row) => {
|
|||||||
|
|
||||||
// 删除申请单
|
// 删除申请单
|
||||||
const handleDelete = (row) => {
|
const handleDelete = (row) => {
|
||||||
|
isDeleting.value = true; // 设置删除标志
|
||||||
|
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
`确定要删除申请单 "${row.applyNo}" 吗?此操作将同时删除对应的医嘱。`,
|
`确定要删除申请单 "${row.applyNo}" 吗?此操作将同时删除对应的医嘱。`,
|
||||||
'删除确认',
|
'删除确认',
|
||||||
@@ -1740,22 +1877,30 @@ const handleDelete = (row) => {
|
|||||||
deleteInspectionApplication(row.applyNo).then((res) => {
|
deleteInspectionApplication(row.applyNo).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
ElMessage.success('删除成功')
|
ElMessage.success('删除成功')
|
||||||
|
resetForm(); // 删除成功后清空表单
|
||||||
// 刷新列表
|
// 刷新列表
|
||||||
getInspectionList()
|
getInspectionList()
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(res.message || '删除失败')
|
ElMessage.error(res.message || '删除失败')
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
console.error('删除检验<EFBFBD><EFBFBD>请单异常:', error)
|
console.error('删除检验请单异常:', error)
|
||||||
ElMessage.error('删除异常')
|
ElMessage.error('删除异常')
|
||||||
})
|
})
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
// 用户取消删除
|
// 用户取消删除
|
||||||
|
}).finally(() => {
|
||||||
|
isDeleting.value = false; // 重置删除标志
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 单元格点击 - 点击表格行时加载申请单详情
|
// 单元格点击 - 点击表格行时加载申请单详情
|
||||||
const handleCellClick = (row, column) => {
|
const handleCellClick = (row, column) => {
|
||||||
|
// 如果点击的是操作列或展开列,不触发数据填充
|
||||||
|
if (column.property === '操作' || column.label === '操作' ||
|
||||||
|
column.type === 'expand' || column.type === 'selection') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// 点击表格行时,将该申请单的数据加载到表单中
|
// 点击表格行时,将该申请单的数据加载到表单中
|
||||||
// 使用 applyNo 判断是否有效
|
// 使用 applyNo 判断是否有效
|
||||||
if (row && row.applyNo) {
|
if (row && row.applyNo) {
|
||||||
@@ -1766,8 +1911,8 @@ const handleCellClick = (row, column) => {
|
|||||||
// 行点击事件处理
|
// 行点击事件处理
|
||||||
const handleRowClick = (currentRow, oldRow) => {
|
const handleRowClick = (currentRow, oldRow) => {
|
||||||
// 点击表格行时,将该申请单的数据加载到表单中
|
// 点击表格行时,将该申请单的数据加载到表单中
|
||||||
// 使用 applyNo 判断是否有效
|
// 使用 applyNo 判断是否有效,同时检查是否处于删除状态
|
||||||
if (currentRow && currentRow.applyNo) {
|
if (currentRow && currentRow.applyNo && !isDeleting.value) {
|
||||||
loadApplicationToForm(currentRow);
|
loadApplicationToForm(currentRow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1790,7 +1935,6 @@ const loadApplicationToForm = async (row) => {
|
|||||||
// 根据申请单号获取完整详情
|
// 根据申请单号获取完整详情
|
||||||
try {
|
try {
|
||||||
const res = await getInspectionApplyDetail(row.applyNo)
|
const res = await getInspectionApplyDetail(row.applyNo)
|
||||||
console.log('申请单详情API返回:', res) // 临时调试日志
|
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
const detail = res.data
|
const detail = res.data
|
||||||
// 加载完整的表单数据
|
// 加载完整的表单数据
|
||||||
@@ -1831,13 +1975,32 @@ const loadApplicationToForm = async (row) => {
|
|||||||
// 加载检验项目数据
|
// 加载检验项目数据
|
||||||
selectedInspectionItems.value = []
|
selectedInspectionItems.value = []
|
||||||
if (detail.labApplyItemList && detail.labApplyItemList.length > 0) {
|
if (detail.labApplyItemList && detail.labApplyItemList.length > 0) {
|
||||||
selectedInspectionItems.value = detail.labApplyItemList.map(item => ({
|
// Bug #326修复: 直接使用后端返回的数据,不再从本地缓存查找匹配项
|
||||||
...item,
|
// 后端已返回完整关联信息(activityId、feePackageId、inspectionTypeId、sampleType、unit)
|
||||||
itemId: item.itemId || item.id || Math.random().toString(36).substring(2, 11),
|
selectedInspectionItems.value = detail.labApplyItemList.map(item => {
|
||||||
itemName: item.itemName || item.name || '',
|
const itemId = item.activityId || item.itemId || item.id || Math.random().toString(36).substring(2, 11)
|
||||||
itemPrice: item.itemPrice || item.price || 0,
|
const isPackage = item.feePackageId != null || item.itemName?.includes('套餐')
|
||||||
itemAmount: item.itemAmount || item.price || 0,
|
|
||||||
}))
|
return {
|
||||||
|
itemId: itemId,
|
||||||
|
itemName: item.itemName || '',
|
||||||
|
itemPrice: item.itemPrice || 0,
|
||||||
|
itemAmount: item.itemAmount || 0,
|
||||||
|
itemQty: item.itemQty || 1,
|
||||||
|
sampleType: item.sampleType || '',
|
||||||
|
unit: item.unit || '',
|
||||||
|
code: item.itemCode || '',
|
||||||
|
isPackage: isPackage,
|
||||||
|
hasChildren: isPackage,
|
||||||
|
feePackageId: item.feePackageId || null,
|
||||||
|
activityId: item.activityId || itemId,
|
||||||
|
inspectionTypeId: item.inspectionTypeId || null,
|
||||||
|
expanded: false,
|
||||||
|
children: [],
|
||||||
|
childrenLoaded: false,
|
||||||
|
loading: false
|
||||||
|
}
|
||||||
|
})
|
||||||
} else if (detail.inspectionItem || detail.itemName) {
|
} else if (detail.inspectionItem || detail.itemName) {
|
||||||
// 如果只有项目名称,尝试从本地分类中查找匹配项
|
// 如果只有项目名称,尝试从本地分类中查找匹配项
|
||||||
const itemNames = (detail.inspectionItem || detail.itemName).split(/[+,]/)
|
const itemNames = (detail.inspectionItem || detail.itemName).split(/[+,]/)
|
||||||
@@ -1896,24 +2059,38 @@ watch(() => props.patientInfo, async (newVal) => {
|
|||||||
}
|
}
|
||||||
}, { deep: true, immediate: true })
|
}, { deep: true, immediate: true })
|
||||||
|
|
||||||
// 监听已选择的检验项目,自动更新检验项目文本(用+号拼接)
|
// Bug #329: 监听已选择的检验项目,自动更新检验项目文本并设置默认执行科室
|
||||||
watch(() => selectedInspectionItems.value, (newVal) => {
|
watch(() => selectedInspectionItems.value, async (newVal) => {
|
||||||
if (newVal && newVal.length > 0) {
|
if (newVal && newVal.length > 0) {
|
||||||
formData.inspectionItemsText = newVal.map(item => item.itemName).join('+')
|
formData.inspectionItemsText = newVal.map(item => item.itemName).join('+')
|
||||||
|
|
||||||
|
// Bug #329: 如果执行科室为空,根据第一个检验项目的检验类型自动设置默认执行科室
|
||||||
|
if (!formData.executeDepartment) {
|
||||||
|
const firstItem = newVal[0]
|
||||||
|
|
||||||
|
// 根据检验项目的 inspectionTypeId 获取默认执行科室
|
||||||
|
if (firstItem.inspectionTypeId) {
|
||||||
|
const defaultDeptCode = await getDefaultPerformDeptCode(firstItem.inspectionTypeId)
|
||||||
|
if (defaultDeptCode) {
|
||||||
|
formData.executeDepartment = defaultDeptCode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Bug #329: 当项目被清空时,同时清空执行科室(下次选择项目时会重新自动设置)
|
||||||
formData.inspectionItemsText = ''
|
formData.inspectionItemsText = ''
|
||||||
|
formData.executeDepartment = ''
|
||||||
}
|
}
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
// 监听执行科室字典数据,设置默认值为第一个选项
|
// Bug #329: 移除字典数据默认值设置,执行科室应从 Organization 表获取,不应使用字典数据
|
||||||
watch(() => inspection_lab_dept.value, (newVal) => {
|
// 原问题:inspection_lab_dept 字典的 value (如 'ORG045') 与 executeDepartmentOptions 的 value (科室编码 busNo) 格式不一致
|
||||||
if (newVal && newVal.length > 0 && !formData.executeDepartment) {
|
// 导致 el-select 显示原始 value 值而非科室名称
|
||||||
formData.executeDepartment = newVal[0].value
|
|
||||||
}
|
|
||||||
}, { immediate: true })
|
|
||||||
|
|
||||||
// 组件挂载时预加载检验项目数据(不依赖patientInfo)
|
// 组件挂载时预加载检验项目数据(不依赖patientInfo)
|
||||||
|
// BugFix #329: 先加载执行科室列表,再加载检验类型(确保检验类型的department字段能正确匹配)
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
await loadExecuteDepartmentList()
|
||||||
await loadInspectionData()
|
await loadInspectionData()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1947,13 +2124,7 @@ defineExpose({
|
|||||||
|
|
||||||
/* Bug#334: 顶部操作按钮区 - 优化垂直空间利用率 */
|
/* Bug#334: 顶部操作按钮区 - 优化垂直空间利用率 */
|
||||||
.top-action-bar {
|
.top-action-bar {
|
||||||
display: flex;
|
display: none; /* 隐藏原有的顶部操作栏 */
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-end;
|
|
||||||
border-bottom: 1px solid var(--el-border-color-light);
|
|
||||||
background: var(--el-bg-color);
|
|
||||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
|
||||||
padding: 0 12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
@@ -1998,7 +2169,14 @@ defineExpose({
|
|||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-header {
|
.card-header-flex {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
@@ -2006,6 +2184,11 @@ defineExpose({
|
|||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Bug#334: 底部内容区域 - 优化垂直空间利用率 */
|
/* Bug#334: 底部内容区域 - 优化垂直空间利用率 */
|
||||||
.bottom-content-area {
|
.bottom-content-area {
|
||||||
padding: 2px 10px;
|
padding: 2px 10px;
|
||||||
@@ -2066,6 +2249,7 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
:deep(.el-pagination) {
|
:deep(.el-pagination) {
|
||||||
.el-pager li {
|
.el-pager li {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@@ -2554,6 +2738,110 @@ defineExpose({
|
|||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 套餐明细展开样式 */
|
||||||
|
.selected-tree-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 8px 12px;
|
||||||
|
background: #fafafa;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-header .item-itemName {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-header .item-price {
|
||||||
|
color: #e6a23c;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-left: 16px;
|
||||||
|
min-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-header:hover {
|
||||||
|
background: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-header.expanded {
|
||||||
|
background: #e8f4fc;
|
||||||
|
border-left: 3px solid #51A3F3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-icon {
|
||||||
|
width: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: #51A3F3;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-package .selected-tree-header {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-children {
|
||||||
|
padding: 4px 12px 4px 36px;
|
||||||
|
background: #fff;
|
||||||
|
border-top: 1px dashed #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-detail {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px 8px;
|
||||||
|
border-bottom: 1px solid #f5f5f5;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-detail:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-detail .detail-name {
|
||||||
|
flex: 1;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-detail .detail-unit {
|
||||||
|
width: 60px;
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-detail .detail-qty {
|
||||||
|
width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-tree-detail .detail-price {
|
||||||
|
width: 60px;
|
||||||
|
text-align: right;
|
||||||
|
color: #e6a23c;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-detail {
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-placeholder {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 15px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.no-selection {
|
.no-selection {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 40px 20px;
|
padding: 40px 20px;
|
||||||
|
|||||||
@@ -114,9 +114,10 @@
|
|||||||
<el-tab-pane label="门诊病历" name="hospitalizationEmr">
|
<el-tab-pane label="门诊病历" name="hospitalizationEmr">
|
||||||
<hospitalizationEmr :patientInfo="patientInfo" :activeTab="activeTab" @emrSaved="handleEmrSaved" />
|
<hospitalizationEmr :patientInfo="patientInfo" :activeTab="activeTab" @emrSaved="handleEmrSaved" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="待写病历" name="pendingEmr">
|
<!-- Bug #368: 屏蔽待写病历标签页(左侧导航栏已有独立菜单,功能冗余) -->
|
||||||
|
<!-- <el-tab-pane label="待写病历" name="pendingEmr">
|
||||||
<PendingEmr @writeEmr="handleWriteEmr" @viewPatient="handleViewPatient" />
|
<PendingEmr @writeEmr="handleWriteEmr" @viewPatient="handleViewPatient" />
|
||||||
</el-tab-pane>
|
</el-tab-pane> -->
|
||||||
<!-- <el-tab-pane label="病历" name="emr">
|
<!-- <el-tab-pane label="病历" name="emr">
|
||||||
<Emr
|
<Emr
|
||||||
:patientInfo="patientInfo"
|
:patientInfo="patientInfo"
|
||||||
|
|||||||
Reference in New Issue
Block a user