Bug #384: 检查方法联动功能完善,增加套餐价格查询和项目卡片展开选择
Bug #386: 检验申请删除时同步删除关联收费项目 Bug #382: 选择项目后保持当前页签状态 Bug #380,381: 临床诊断获取主诊断字段名修正 Bug #387: 套餐项目回充默认展开并自动加载明细
This commit is contained in:
@@ -45,35 +45,10 @@
|
||||
class="inspection-table"
|
||||
highlight-current-row
|
||||
row-key="applicationId"
|
||||
:expand-row-keys="expandedRowKeys"
|
||||
@expand-change="handleExpandChange"
|
||||
@selection-change="handleSelectionChange"
|
||||
@current-change="handleRowClick"
|
||||
@cell-click="handleCellClick"
|
||||
>
|
||||
<el-table-column type="expand" width="50" align="center" header-align="center">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.children && scope.row.children.length > 0" class="expand-content">
|
||||
<el-table :data="scope.row.children" border size="small" style="width: 100%">
|
||||
<el-table-column label="明细项目" prop="itemName" min-width="150" />
|
||||
<el-table-column label="样本类型" prop="sampleType" width="100" />
|
||||
<el-table-column label="单位" prop="unit" width="80" />
|
||||
<el-table-column label="单价" prop="itemPrice" width="80" align="right">
|
||||
<template #default="itemScope">
|
||||
¥{{ formatAmount(itemScope.row.itemPrice) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="数量" prop="itemQty" width="80" align="center" />
|
||||
<el-table-column label="金额" prop="itemAmount" width="80" align="right">
|
||||
<template #default="itemScope">
|
||||
¥{{ formatAmount(itemScope.row.itemAmount) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div v-else class="expand-empty">无明细项目</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column type="selection" width="55" align="center" header-align="center" />
|
||||
<el-table-column label="申请 ID" prop="applicationId" width="80" align="center" header-align="center">
|
||||
<template #default="scope">
|
||||
@@ -83,14 +58,7 @@
|
||||
<el-table-column label="申请单号" prop="applyNo" min-width="160" align="center" header-align="center" />
|
||||
<el-table-column label="检验项目" prop="itemName" min-width="170px" align="center" header-align="center">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.hasChildren" style="color: #409EFF; cursor: pointer" @click.stop="toggleExpand(scope.row)">
|
||||
<el-icon style="vertical-align: middle; margin-right: 4px">
|
||||
<Right v-if="!isExpanded(scope.row.applicationId)" />
|
||||
<Bottom v-else />
|
||||
</el-icon>
|
||||
{{ scope.row.itemName }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.itemName }}</span>
|
||||
<span>{{ scope.row.itemName }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="申请医生" prop="applyDocName" width="120" align="center" header-align="center" />
|
||||
@@ -645,7 +613,7 @@
|
||||
<script setup>
|
||||
import {onMounted, onUnmounted, reactive, ref, watch, computed, getCurrentInstance} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import { DocumentChecked, Plus, Document, Printer, Delete, Check, Loading, Right, Bottom } from '@element-plus/icons-vue'
|
||||
import { DocumentChecked, Plus, Document, Printer, Delete, Check, Loading } from '@element-plus/icons-vue'
|
||||
import {
|
||||
deleteInspectionApplication, getApplyList,
|
||||
saveInspectionApplication,
|
||||
@@ -792,53 +760,39 @@ const loading = ref(false)
|
||||
const saving = ref(false) // 保存状态
|
||||
const total = ref(0)
|
||||
const leftActiveTab = ref('application')
|
||||
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) => {
|
||||
/**
|
||||
* 加载套餐明细(公共函数)
|
||||
* @param {string|number} packageId 套餐ID
|
||||
* @returns {Promise<Array>} 明细数组
|
||||
*/
|
||||
const fetchPackageDetails = async (packageId) => {
|
||||
if (!packageId) return []
|
||||
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)
|
||||
}))
|
||||
return res.data.map(detail => {
|
||||
const detailId = detail.detailId || detail.id || detail.itemId
|
||||
const qty = detail.quantity || detail.itemQty || detail.qty || 1
|
||||
const price = detail.unitPrice || detail.itemPrice || detail.price || 0
|
||||
return {
|
||||
detailId: detailId,
|
||||
itemId: detailId, // 兼容表格 row-key
|
||||
itemName: detail.itemName || detail.name,
|
||||
sampleType: detail.sampleType || '',
|
||||
unit: detail.unit || '',
|
||||
quantity: qty,
|
||||
itemQty: qty, // 兼容表格"总量"列
|
||||
unitPrice: price,
|
||||
itemPrice: price, // 兼容表格"单价"列
|
||||
itemAmount: price * qty
|
||||
}
|
||||
})
|
||||
}
|
||||
return []
|
||||
} catch (error) {
|
||||
console.error('加载套餐明细失败:', error)
|
||||
row.children = []
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,35 +801,9 @@ const loadPackageDetailsForTable = async (row, treeNode, resolve) => {
|
||||
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 packageId = row.feePackageId || row.packageId
|
||||
const children = await fetchPackageDetails(packageId)
|
||||
resolve(children)
|
||||
}
|
||||
|
||||
const togglePackageExpand = async (item) => {
|
||||
@@ -885,27 +813,9 @@ const togglePackageExpand = async (item) => {
|
||||
|
||||
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
|
||||
}
|
||||
const packageId = item.feePackageId || item.packageId
|
||||
item.children = await fetchPackageDetails(packageId)
|
||||
item.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1822,6 +1732,26 @@ const clearAllSelected = () => {
|
||||
selectedInspectionItems.value = []
|
||||
}
|
||||
|
||||
// Bug #387修复: 同步分类勾选状态
|
||||
const syncCategoryChecked = () => {
|
||||
// 重置所有分类项目的勾选状态
|
||||
inspectionCategories.value.forEach(category => {
|
||||
category.items.forEach(item => {
|
||||
item.checked = false
|
||||
})
|
||||
})
|
||||
// 获取已选项目的ID集合
|
||||
const ids = new Set(selectedInspectionItems.value.map(s => s.itemId))
|
||||
// 同步勾选状态
|
||||
for (const cat of inspectionCategories.value) {
|
||||
for (const item of cat.items) {
|
||||
if (ids.has(item.itemId)) {
|
||||
item.checked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分页大小改变
|
||||
const handleSizeChange = (size) => {
|
||||
queryParams.pageSize = size
|
||||
@@ -1977,6 +1907,7 @@ const loadApplicationToForm = async (row) => {
|
||||
if (detail.labApplyItemList && detail.labApplyItemList.length > 0) {
|
||||
// Bug #326修复: 直接使用后端返回的数据,不再从本地缓存查找匹配项
|
||||
// 后端已返回完整关联信息(activityId、feePackageId、inspectionTypeId、sampleType、unit)
|
||||
// Bug #387修复: 套餐项目默认展开,并自动加载明细
|
||||
selectedInspectionItems.value = detail.labApplyItemList.map(item => {
|
||||
const itemId = item.activityId || item.itemId || item.id || Math.random().toString(36).substring(2, 11)
|
||||
const isPackage = item.feePackageId != null || item.itemName?.includes('套餐')
|
||||
@@ -1995,12 +1926,25 @@ const loadApplicationToForm = async (row) => {
|
||||
feePackageId: item.feePackageId || null,
|
||||
activityId: item.activityId || itemId,
|
||||
inspectionTypeId: item.inspectionTypeId || null,
|
||||
expanded: false,
|
||||
expanded: isPackage, // Bug #387: 套餐默认展开
|
||||
children: [],
|
||||
childrenLoaded: false,
|
||||
childrenLoaded: !isPackage, // Bug #387: 套餐需加载明细
|
||||
loading: false
|
||||
}
|
||||
})
|
||||
|
||||
// Bug #387修复: 自动加载套餐明细
|
||||
for (const pkgItem of selectedInspectionItems.value) {
|
||||
if (pkgItem.isPackage && pkgItem.feePackageId) {
|
||||
pkgItem.loading = true
|
||||
pkgItem.children = await fetchPackageDetails(pkgItem.feePackageId)
|
||||
pkgItem.childrenLoaded = true
|
||||
pkgItem.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// Bug #387修复: 同步分类勾选状态
|
||||
syncCategoryChecked()
|
||||
} else if (detail.inspectionItem || detail.itemName) {
|
||||
// 如果只有项目名称,尝试从本地分类中查找匹配项
|
||||
const itemNames = (detail.inspectionItem || detail.itemName).split(/[+,]/)
|
||||
|
||||
Reference in New Issue
Block a user