@@ -395,7 +395,7 @@
<!-- 右侧 : 项目选择区 ( 35 % ) -- >
< el-col :span = "9" class = "selection-area" >
<!-- 检验项目选择区 ( 上部50 % ) -- >
< el-card class = "inspection-selector" >
< el-card class = "inspection-selector" v-loading = "inspectionLoading" element-loading-text="正在加载检验项目..." >
< template # header >
< span class = "card-title" > 检验项目选择 < / span >
< / template >
@@ -413,6 +413,9 @@
<!-- 分类树 -- >
< el-scrollbar class = "category-tree" style = "max-height: 280px" >
<!-- 无数据提示 -- >
< el-empty v-if = "!inspectionLoading && inspectionCategories.length === 0" description="暂无检验项目数据" :image-size="80" / >
<!-- 数据列表 -- >
< div
v-for = "category in inspectionCategories"
:key = "category.key"
@@ -487,22 +490,19 @@
< / template >
< script setup >
import { onMounted , reactive , ref , watch } from 'vue'
import { onMounted , reactive , ref , watch , nextTick } from 'vue'
import { ElMessage , ElMessageBox } from 'element-plus'
import { DocumentChecked , Plus , Document , Printer , Delete , Check } from '@element-plus/icons-vue'
import {
checkInspectionApplicationNo ,
deleteInspectionApplication , getApplyList ,
saveInspectionApplication
saveInspectionApplication ,
getInspectionTypeList ,
getInspectionItemList
} from '../api'
import useUserStore from '@/store/modules/user.js'
import { storeToRefs } from 'pinia'
// 在 onMounted 中调用初始化函数
onMounted ( ( ) => {
initData ( ) ;
} )
// Props
const props = defineProps ( {
patientInfo : {
@@ -529,9 +529,12 @@ const userStore = useUserStore()
const { id : userId , name : userName , nickName : userNickName } = storeToRefs ( userStore )
// 修改 initData 函数
function initData ( ) {
// 然后执行原有的初始化逻辑
if ( props . patientInfo ) {
async function initData ( ) {
console . log ( '【检验】开始初始化数据, 当前patientInfo:' , props . patientInfo )
// 先初始化患者信息(如果有)
if ( props . patientInfo && props . patientInfo . encounterId ) {
console . log ( '【检验】初始化患者信息' )
queryParams . encounterId = props . patientInfo . encounterId
formData . visitNo = props . patientInfo . busNo || ''
formData . patientId = props . patientInfo . patientId || ''
@@ -544,14 +547,21 @@ function initData() {
formData . applyDeptCode = props . patientInfo . organizationName || ''
formData . applyOrganizationId = props . patientInfo . orgId || ''
formData . encounterId = props . patientInfo . encounterId
console . log ( '【检验】患者信息初始化完成, formData:' , JSON . stringify ( {
patientName : formData . patientName ,
medicalrecordNumber : formData . medicalrecordNumber ,
applyDepartment : formData . applyDepartment ,
applyDocName : formData . applyDocName
} , null , 2 ) )
// 生成申请单号
generateApplicationNo ( ) . then ( ( newApplyNo ) => {
formData . applyNo = newApplyNo ;
console . log ( '【检验】申请单号生成:' , newApplyNo )
} ) ;
}
// 只有在存在 encounterId 时才调用接口
if ( queryParams . encounterId ) {
getInspectionList ( )
} else {
console . log ( '【检验】没有有效的patientInfo, 跳过患者信息初始化' )
}
}
@@ -567,10 +577,10 @@ const inspectionList = ref([])
// 表单数据
const formData = reactive ( {
applyOrganizationId : props . patientInfo . orgId ,
applyOrganizationId : '' ,
applicationId : null ,
applyNo : '' ,
patientId : '' ,
patientId : '' ,
patientName : '' ,
medicalrecordNumber : '' ,
natureofCost : 'self' ,
@@ -596,10 +606,10 @@ const formData = reactive({
auditDoctor : '' ,
auditTime : null ,
visitNo : '' ,
applyDocCode : '' ,
applyDeptCode : props . patientInfo . organizationName ,
applyDocCode : '' ,
applyDeptCode : '' ,
specimenName : '血液' ,
encounterId : props . patientInfo . encounterId
encounterId : ''
} )
// 表单验证规则
@@ -640,47 +650,173 @@ const selectedInspectionItems = ref([])
const searchKeyword = ref ( '' )
// 活动分类
const activeCategory = ref ( 'biochemical ' )
const activeCategory = ref ( '' )
// 检验项目分类(树形结构 )
le t inspectionCategories = ref ( [
{
key : 'biochemical' ,
label : '生化' ,
expanded : true ,
items : [
{ itemId : 1 , itemName : '肝功能' , itemPrice : 31 , itemAmount : 31 , sampleType : '血清' , unit : 'U/L' , itemQty : 1 , serviceFee : 0 , type : '生化' , isSelfPay : false } ,
{ itemId : 2 , itemName : '肾功能' , itemPrice : 28 , itemAmount : 28 , sampleType : '血清' , unit : 'U/L' , itemQty : 1 , serviceFee : 0 , type : '生化' , isSelfPay : false } ,
{ itemId : 3 , itemName : '血糖' , itemPrice : 15 , itemAmount : 15 , sampleType : '血清' , unit : 'mmol/L' , itemQty : 1 , serviceFee : 0 , type : '生化' , isSelfPay : false }
]
} ,
{
key : 'blood' ,
label : '临检' ,
expanded : false ,
items : [
{ itemId : 4 , itemName : '血常规+crp' , itemPrice : 50 , itemAmount : 50 , sampleType : '全血' , unit : '× 10^9/L' , itemQty : 1 , serviceFee : 0 , type : '血液' , isSelfPay : false } ,
{ itemId : 5 , itemName : '血常规(五分类)' , itemPrice : 15 , itemAmount : 15 , sampleType : '全血' , unit : '× 10^9/L' , itemQty : 1 , serviceFee : 0 , type : '血液' , isSelfPay : false }
]
} ,
{
key : 'urine' ,
label : '尿液' ,
expanded : false ,
items : [
{ itemId : 6 , itemName : '尿常规' , itemPrice : 20 , itemAmount : 20 , sampleType : '尿液' , unit : '细胞/μl' , itemQty : 1 , serviceFee : 0 , type : '尿液' , isSelfPay : false }
]
} ,
{
key : 'immunity' ,
label : '免疫' ,
expanded : false ,
items : [
{ itemId : 7 , itemName : '总IgE测定' , itemPrice : 30 , itemAmount : 30 , sampleType : '血清' , unit : 'IU/ml' , itemQty : 1 , serviceFee : 0 , type : '免疫' , isSelfPay : false } ,
{ itemId : 8 , itemName : '风湿' , itemPrice : 119 , itemAmount : 119 , sampleType : '血清' , unit : 'U/ml' , itemQty : 1 , serviceFee : 0 , type : '免疫' , isSelfPay : false }
]
// 检验项目分类(动态从API获取 )
cons t inspectionCategories = ref ( [ ] )
// 检验项目加载状态
const inspectionLoading = ref ( false )
// 加载检验项目分类和项目
async function loadInspectionData ( ) {
// 如果已经加载过数据,直接返回(避免重复请求)
if ( inspectionCategories . value . length > 0 ) {
console . log ( '【检验】数据已缓存,跳过重复加载' )
return
}
] )
inspectionLoading . value = true
const startTime = Date . now ( ) // 性能监控开始时间
try {
console . log ( '【检验】开始并行请求数据' )
// 并行请求:同时获取检验类型列表和检验项目列表
const [ typeRes , itemRes ] = await Promise . all ( [
// 添加错误处理和重试机制
getInspectionTypeList ( ) . catch ( error => {
console . error ( '【检验】获取检验类型失败:' , error )
return { data : [ ] } // 返回空数据作为降级方案
} ) ,
getInspectionItemList ( {
pageNo : 1 ,
pageSize : 200 , // 进一步优化:减少数据量,按需加载
searchKey : '' , // 添加搜索关键词参数
categoryCode : 'inspection' // 明确指定检验类别
} ) . catch ( error => {
console . error ( '【检验】获取检验项目失败:' , error )
return { data : { records : [ ] } } // 返回空数据作为降级方案
} )
] )
const endTime = Date . now ( )
console . log ( ` 【检验】API请求完成, 耗时: ${ endTime - startTime } ms ` )
const typeList = typeRes . data || [ ]
console . log ( '【检验】获取到检验类型数量:' , typeList . length )
// 解析检验项目数据
let allItems = [ ]
if ( itemRes . data && itemRes . data . records ) {
allItems = itemRes . data . records
} else if ( itemRes . data && Array . isArray ( itemRes . data ) ) {
allItems = itemRes . data
} else if ( Array . isArray ( itemRes ) ) {
allItems = itemRes
}
console . log ( '【检验】获取到检验项目数量:' , allItems . length )
// 按分类组织数据
const categories = typeList
. filter ( type => type . validFlag === 1 || type . validFlag === undefined )
. map ( ( type , index ) => {
const categoryItems = allItems
. filter ( item => {
const isInspection = item . categoryCode _dictText === '检验' ||
item . categoryName === '检验' ||
item . categoryCode === 'inspection'
const matchType = item . typeName === type . name ||
item . inspectionTypeName === type . name ||
item . bigClassName === type . name ||
item . typeCode === type . code
return isInspection && ( matchType || typeList . length === 1 )
} )
. map ( item => ( {
itemId : item . id || item . activityId || Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) ,
itemName : item . name || item . itemName || '' ,
itemPrice : item . retailPrice || item . price || 0 ,
itemAmount : item . retailPrice || item . price || 0 ,
sampleType : item . sampleType || '血液' ,
unit : item . unit || '' ,
itemQty : 1 ,
serviceFee : 0 ,
type : type . name ,
isSelfPay : false ,
activityId : item . activityId ,
code : item . code || item . activityCode
} ) )
return {
key : type . code || ` type_ ${ index } ` ,
label : type . name || ` 分类 ${ index + 1 } ` ,
expanded : index === 0 ,
items : categoryItems
}
} )
// 如果没有分类数据,但有项目数据,创建一个默认分类
if ( categories . length === 0 && allItems . length > 0 ) {
const defaultItems = allItems
. filter ( item => item . categoryCode _dictText === '检验' ||
item . categoryName === '检验' ||
item . categoryCode === 'inspection' ||
true )
. slice ( 0 , 50 ) // 优化:增加默认显示数量
. map ( item => ( {
itemId : item . id || item . activityId || Math . random ( ) . toString ( 36 ) . substr ( 2 , 9 ) ,
itemName : item . name || item . itemName || '' ,
itemPrice : item . retailPrice || item . price || 0 ,
itemAmount : item . retailPrice || item . price || 0 ,
sampleType : item . sampleType || '血液' ,
unit : item . unit || '' ,
itemQty : 1 ,
serviceFee : 0 ,
type : '检验' ,
isSelfPay : false ,
activityId : item . activityId ,
code : item . code || item . activityCode
} ) )
if ( defaultItems . length > 0 ) {
categories . push ( {
key : 'default' ,
label : '检验项目' ,
expanded : true ,
items : defaultItems
} )
}
}
// 过滤掉没有项目的分类
const validCategories = categories . filter ( cat => cat . items . length > 0 )
if ( validCategories . length > 0 ) {
inspectionCategories . value = validCategories
activeCategory . value = validCategories [ 0 ] . key
} else {
throw new Error ( '未获取到有效的检验项目数据' )
}
} catch ( error ) {
console . error ( '加载检验项目数据失败:' , error )
// 加载失败时使用静态数据作为备用
inspectionCategories . value = [
{
key : 'biochemical' ,
label : '生化' ,
expanded : true ,
items : [
{ itemId : 1 , itemName : '肝功能' , itemPrice : 31 , itemAmount : 31 , sampleType : '血清' , unit : 'U/L' , itemQty : 1 , serviceFee : 0 , type : '生化' , isSelfPay : false } ,
{ itemId : 2 , itemName : '肾功能' , itemPrice : 28 , itemAmount : 28 , sampleType : '血清' , unit : 'U/L' , itemQty : 1 , serviceFee : 0 , type : '生化' , isSelfPay : false } ,
{ itemId : 3 , itemName : '血糖' , itemPrice : 15 , itemAmount : 15 , sampleType : '血清' , unit : 'mmol/L' , itemQty : 1 , serviceFee : 0 , type : '生化' , isSelfPay : false }
]
} ,
{
key : 'blood' ,
label : '临检' ,
expanded : false ,
items : [
{ itemId : 4 , itemName : '血常规+crp' , itemPrice : 50 , itemAmount : 50 , sampleType : '全血' , unit : '× 10^9/L' , itemQty : 1 , serviceFee : 0 , type : '血液' , isSelfPay : false } ,
{ itemId : 5 , itemName : '血常规(五分类)' , itemPrice : 15 , itemAmount : 15 , sampleType : '全血' , unit : '× 10^9/L' , itemQty : 1 , serviceFee : 0 , type : '血液' , isSelfPay : false }
]
}
]
activeCategory . value = 'biochemical'
} finally {
inspectionLoading . value = false
}
}
// 获取过滤后的项目
const getFilteredItems = ( categoryKey ) => {
@@ -1374,23 +1510,30 @@ function handleCellClick(row, column) {
watch ( ( ) => props . activeTab , async ( newVal ) => {
if ( newVal === 'inspection' ) {
await initData ( )
// 默认展开生化分类
a ctive Category . value = 'biochemical'
inspectionCategories . value . forEach ( cat => {
cat . expanded = cat . key === 'biochemical'
} )
// 根据动态加载的分类设置 默认展开
if ( inspe ction Categories . value . length > 0 ) {
// 展开第一个分类
activeCategory . value = inspectionCategories . value [ 0 ] . key
inspectionCategories . value . forEach ( ( cat , index ) => {
cat . expanded = index === 0
} )
}
}
} )
// 监听patientInfo变化,确保encounterId及时更新并重新加载数据
watch ( ( ) => props . patientInfo , async ( newVal ) => {
// console.log( '【检验】patientInfo变化:', newVal)
console. log ( '【检验】patientInfo变化:', newVal)
console . log ( '【检验】接收到的完整patientInfo:' , JSON . stringify ( newVal , null , 2 ) )
if ( newVal && newVal . encounterId ) {
const oldEncounterId = queryParams . encounterId
queryParams . encounterId = newVal . encounterId
// console.log( '【检验】更新encounterId:', queryParams. encounterId)
console. log ( '【检验】更新encounterId:', queryParams. encounterId)
// 初始化数据
await initData ( ) ;
// 如果encounterId发生变化, 重新加载检验申请单列表
if ( oldEncounterId !== newVal . encounterId ) {
getInspectionList ( )
@@ -1411,10 +1554,11 @@ watch(() => selectedInspectionItems.value, (newVal) => {
}
} , { deep : true } )
// 初始化
// 组件挂载时预加载检验项目数据( 不依赖patientInfo)
onMounted ( async ( ) => {
await initData ( ) ;
get InspectionList ( ) ;
console . log ( '【检验】组件挂载,开始预加载检验项目数据' )
await load InspectionData ( )
console . log ( '【检验】检验项目数据预加载完成' )
} )
// 暴露方法
@@ -1523,6 +1667,7 @@ defineExpose({
border - top : 1 px solid var ( -- el - border - color - light ) ;
}
: deep ( . el - pagination ) {
. el - pager li {
border - radius : 4 px ;