78 增加门诊医生开立检验申请单--对搜索项目区实现懒加载,以及动态搜索。
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<!-- 顶部操作按钮区 -->
|
||||
<el-header class="top-action-bar" height="50px">
|
||||
<el-row class="action-buttons" type="flex" justify="end" :gutter="10">
|
||||
<el-button type="success" size="large" @click="handleSave" class="save-btn">
|
||||
<el-button type="success" size="large" @click="handleSave" class="save-btn" :loading="saving">
|
||||
<el-icon><Document /></el-icon>
|
||||
保存
|
||||
</el-button>
|
||||
@@ -400,19 +400,35 @@
|
||||
<span class="card-title">检验项目选择</span>
|
||||
</template>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<el-input
|
||||
<!-- 搜索框(自动完成) -->
|
||||
<el-autocomplete
|
||||
v-model="searchKeyword"
|
||||
:fetch-suggestions="querySearchInspectionItems"
|
||||
placeholder="搜索检验项目..."
|
||||
size="small"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
@input="handleSearch"
|
||||
@select="handleSearchSelect"
|
||||
@clear="handleSearchClear"
|
||||
value-key="itemName"
|
||||
class="search-input"
|
||||
/>
|
||||
:debounce="300"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<div class="suggestion-item">
|
||||
<span class="suggestion-name">{{ item.itemName }}</span>
|
||||
<el-tag size="small" type="info" class="suggestion-category">{{ item.typeName || '检验' }}</el-tag>
|
||||
<span class="suggestion-price">¥{{ item.itemPrice }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
|
||||
<!-- 分类树 -->
|
||||
<el-scrollbar class="category-tree" style="max-height: 280px">
|
||||
<el-scrollbar
|
||||
class="category-tree"
|
||||
style="max-height: 280px"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<!-- 无数据提示 -->
|
||||
<el-empty v-if="!inspectionLoading && inspectionCategories.length === 0" description="暂无检验项目数据" :image-size="80" />
|
||||
<!-- 数据列表 -->
|
||||
@@ -427,9 +443,19 @@
|
||||
>
|
||||
<span class="category-tree-icon">{{ category.expanded ? '▼' : '▶' }}</span>
|
||||
<span>{{ category.label }}</span>
|
||||
<span class="category-count">({{ category.items.length }})</span>
|
||||
<span class="category-count">({{ category.total || category.items.length }})</span>
|
||||
<!-- 加载状态图标 -->
|
||||
<el-icon v-if="category.loading" class="is-loading" style="margin-left: 8px; color: #409eff;">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div v-if="category.expanded" class="category-tree-children">
|
||||
<!-- 加载中占位 -->
|
||||
<div v-if="category.loading && category.items.length === 0" class="loading-placeholder">
|
||||
<el-icon class="is-loading" style="margin-right: 8px;"><Loading /></el-icon>
|
||||
<span>加载中...</span>
|
||||
</div>
|
||||
<!-- 项目列表 -->
|
||||
<div
|
||||
v-for="item in getFilteredItems(category.key)"
|
||||
:key="item.itemId"
|
||||
@@ -444,6 +470,22 @@
|
||||
<span class="item-itemName">{{ item.itemName }}</span>
|
||||
<span class="item-price">¥{{ item.itemPrice }}</span>
|
||||
</div>
|
||||
<!-- 加载更多 -->
|
||||
<div v-if="category.hasMore && category.items.length > 0" class="load-more">
|
||||
<el-button
|
||||
link
|
||||
size="small"
|
||||
:loading="category.loading"
|
||||
@click.stop="loadMoreItems(category.key)"
|
||||
>
|
||||
{{ category.loading ? '加载中...' : '加载更多' }}
|
||||
</el-button>
|
||||
<span class="load-info">(已加载 {{ category.items.length }}/{{ category.total }} 条)</span>
|
||||
</div>
|
||||
<!-- 加载完成提示 -->
|
||||
<div v-if="!category.hasMore && category.items.length > 0" class="no-more">
|
||||
已全部加载 (共 {{ category.total }} 条)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
@@ -492,7 +534,7 @@
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref, watch, computed, getCurrentInstance} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import { DocumentChecked, Plus, Document, Printer, Delete, Check } from '@element-plus/icons-vue'
|
||||
import { DocumentChecked, Plus, Document, Printer, Delete, Check, Loading } from '@element-plus/icons-vue'
|
||||
import {
|
||||
checkInspectionApplicationNo,
|
||||
deleteInspectionApplication, getApplyList,
|
||||
@@ -504,6 +546,7 @@ import useUserStore from '@/store/modules/user.js'
|
||||
// 迁移到 hiprint
|
||||
import { previewPrint } from '@/utils/printUtils.js'
|
||||
import {storeToRefs} from 'pinia'
|
||||
import { debounce } from 'lodash-es'
|
||||
|
||||
// 获取当前组件实例和字典
|
||||
const { proxy } = getCurrentInstance()
|
||||
@@ -532,6 +575,7 @@ const emit = defineEmits(['save'])
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false)
|
||||
const saving = ref(false) // 保存状态
|
||||
const total = ref(0)
|
||||
const leftActiveTab = ref('application')
|
||||
const isGeneratingNewApplyNo = ref(false) // 标志:是否正在生成新申请单号
|
||||
@@ -624,7 +668,8 @@ const validationErrors = reactive({
|
||||
clinicDiag: false,
|
||||
medicalHistorySummary: false,
|
||||
purposeofInspection: false,
|
||||
labApplyItemList: false
|
||||
labApplyItemList: false,
|
||||
applyTime: false
|
||||
})
|
||||
|
||||
// 已选择的表格行
|
||||
@@ -639,15 +684,21 @@ const searchKeyword = ref('')
|
||||
// 活动分类
|
||||
const activeCategory = ref('')
|
||||
|
||||
// 检验项目分类(动态从API获取)
|
||||
// 检验项目分类(动态从API获取,支持懒加载和分页)
|
||||
const inspectionCategories = ref([])
|
||||
|
||||
// 检验项目加载状态
|
||||
// 检验项目加载状态(整体)
|
||||
const inspectionLoading = ref(false)
|
||||
|
||||
// 加载检验项目分类和项目
|
||||
// 每页加载条数
|
||||
const PAGE_SIZE = 50
|
||||
|
||||
// 搜索防抖时间(毫秒)
|
||||
const SEARCH_DEBOUNCE_TIME = 300
|
||||
|
||||
// 加载检验类型分类列表(只加载分类,项目懒加载)
|
||||
async function loadInspectionData() {
|
||||
// 如果已经加载过数据,直接返回(避免重复请求)
|
||||
// 如果已经加载过分类,直接返回
|
||||
if (inspectionCategories.value.length > 0) {
|
||||
return
|
||||
}
|
||||
@@ -655,194 +706,244 @@ async function loadInspectionData() {
|
||||
inspectionLoading.value = true
|
||||
|
||||
try {
|
||||
// 并行请求:同时获取检验类型列表和检验项目列表
|
||||
const [typeRes, itemRes] = await Promise.all([
|
||||
getInspectionTypeList().catch(error => {
|
||||
console.error('获取检验类型失败:', error)
|
||||
return { data: [] }
|
||||
}),
|
||||
getInspectionItemList({
|
||||
pageNo: 1,
|
||||
pageSize: 500,
|
||||
searchKey: '',
|
||||
categoryCode: inspectionCategoryCode.value
|
||||
}).catch(error => {
|
||||
console.error('获取检验项目失败:', error)
|
||||
return { data: { records: [] } }
|
||||
})
|
||||
])
|
||||
// 只获取检验类型列表
|
||||
const typeRes = await getInspectionTypeList().catch(error => {
|
||||
console.error('获取检验类型失败:', error)
|
||||
return { data: [] }
|
||||
})
|
||||
|
||||
const typeList = typeRes.data || []
|
||||
|
||||
// 解析检验项目数据
|
||||
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
|
||||
}
|
||||
|
||||
// 按分类组织数据(与检验项目设置维护保持一致的字段映射)
|
||||
// 创建分类结构,但不加载项目(懒加载)
|
||||
const categories = typeList
|
||||
.filter(type => type.validFlag === 1 || type.validFlag === undefined)
|
||||
.map((type, index) => {
|
||||
const categoryItems = allItems
|
||||
.filter(item => {
|
||||
// 转换为字符串进行比较,避免类型不匹配问题
|
||||
const itemTypeId = String(item.inspectionTypeId || '')
|
||||
const typeId = String(type.id || '')
|
||||
const itemTypeName = String(item.inspectionTypeId_dictText || item.typeName || '').trim()
|
||||
const typeName = String(type.name || '').trim()
|
||||
.map((type, index) => ({
|
||||
key: type.code || `type_${index}`,
|
||||
label: type.name || `分类${index + 1}`,
|
||||
typeId: type.id, // 保存类型ID用于分页查询
|
||||
expanded: index === 0, // 默认展开第一个
|
||||
loaded: false, // 是否已加载项目
|
||||
loading: false, // 是否正在加载
|
||||
items: [], // 项目列表
|
||||
pageNo: 1, // 当前页码
|
||||
pageSize: PAGE_SIZE, // 每页条数
|
||||
total: 0, // 总条数
|
||||
hasMore: true // 是否还有更多数据
|
||||
}))
|
||||
|
||||
// 按检验类型ID匹配(优先使用 inspectionTypeId)
|
||||
const matchById = itemTypeId && typeId && itemTypeId === typeId
|
||||
const matchByName = itemTypeName && typeName && itemTypeName === typeName
|
||||
const matchByCode = String(item.typeCode || '') === String(type.code || '')
|
||||
|
||||
return matchById || matchByName || matchByCode
|
||||
})
|
||||
.map(item => ({
|
||||
itemId: item.id || item.activityId || Math.random().toString(36).substring(2, 11),
|
||||
itemName: item.name || item.itemName || '',
|
||||
itemPrice: item.retailPrice || item.price || 0,
|
||||
itemAmount: item.retailPrice || item.price || 0,
|
||||
sampleType: item.specimenCode_dictText || item.sampleType || '血液',
|
||||
unit: item.unit || '',
|
||||
itemQty: 1,
|
||||
serviceFee: 0,
|
||||
type: type.name || item.inspectionTypeId_dictText || '检验',
|
||||
isSelfPay: false,
|
||||
activityId: item.activityId,
|
||||
code: item.busNo || item.code || item.activityCode,
|
||||
inspectionTypeId: item.inspectionTypeId || null
|
||||
}))
|
||||
|
||||
return {
|
||||
key: type.code || `type_${index}`,
|
||||
label: type.name || `分类${index + 1}`,
|
||||
expanded: index === 0,
|
||||
items: categoryItems
|
||||
}
|
||||
})
|
||||
|
||||
// 过滤掉没有项目的分类
|
||||
const validCategories = categories.filter(cat => cat.items.length > 0)
|
||||
|
||||
// 如果没有有效分类,但有项目数据,按项目自带的检验类型文本分组
|
||||
if (validCategories.length === 0 && allItems.length > 0) {
|
||||
// 按检验类型文本分组
|
||||
const typeMap = new Map()
|
||||
allItems.forEach(item => {
|
||||
const typeName = item.inspectionTypeId_dictText || '其他检验'
|
||||
if (!typeMap.has(typeName)) {
|
||||
typeMap.set(typeName, [])
|
||||
}
|
||||
typeMap.get(typeName).push(item)
|
||||
})
|
||||
|
||||
// 创建分类
|
||||
typeMap.forEach((items, typeName) => {
|
||||
const mappedItems = items.map(item => ({
|
||||
itemId: item.id || item.activityId || Math.random().toString(36).substring(2, 11),
|
||||
itemName: item.name || item.itemName || '',
|
||||
itemPrice: item.retailPrice || item.price || 0,
|
||||
itemAmount: item.retailPrice || item.price || 0,
|
||||
sampleType: item.specimenCode_dictText || item.sampleType || '血液',
|
||||
unit: item.unit || '',
|
||||
itemQty: 1,
|
||||
serviceFee: 0,
|
||||
type: typeName,
|
||||
isSelfPay: false,
|
||||
activityId: item.activityId,
|
||||
code: item.busNo || item.code || item.activityCode,
|
||||
inspectionTypeId: item.inspectionTypeId || null
|
||||
}))
|
||||
|
||||
validCategories.push({
|
||||
key: `type_${typeName}`,
|
||||
label: typeName,
|
||||
expanded: validCategories.length === 0,
|
||||
items: mappedItems
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (validCategories.length > 0) {
|
||||
inspectionCategories.value = validCategories
|
||||
activeCategory.value = validCategories[0].key
|
||||
if (categories.length > 0) {
|
||||
inspectionCategories.value = categories
|
||||
activeCategory.value = categories[0].key
|
||||
|
||||
// 预加载第一个分类的项目
|
||||
await loadCategoryItems(categories[0].key)
|
||||
} else {
|
||||
console.warn('未获取到有效的检验项目数据,使用备用数据')
|
||||
// 直接使用备用数据,不抛出错误
|
||||
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'
|
||||
console.warn('未获取到检验类型分类')
|
||||
}
|
||||
} 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'
|
||||
console.error('加载检验类型分类失败:', error)
|
||||
} finally {
|
||||
inspectionLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取过滤后的项目
|
||||
// 懒加载分类项目(分页)
|
||||
async function loadCategoryItems(categoryKey, loadMore = false) {
|
||||
const category = inspectionCategories.value.find(c => c.key === categoryKey)
|
||||
if (!category) return
|
||||
|
||||
// 已加载完成且不是加载更多,或正在加载中,跳过
|
||||
if ((category.loaded && !loadMore) || category.loading) return
|
||||
// 没有更多数据了,跳过
|
||||
if (loadMore && !category.hasMore) return
|
||||
|
||||
category.loading = true
|
||||
|
||||
try {
|
||||
const params = {
|
||||
pageNo: category.pageNo,
|
||||
pageSize: category.pageSize,
|
||||
categoryCode: inspectionCategoryCode.value,
|
||||
searchKey: searchKeyword.value || ''
|
||||
}
|
||||
|
||||
// 如果有类型ID,添加筛选条件
|
||||
if (category.typeId) {
|
||||
params.inspectionTypeId = category.typeId
|
||||
}
|
||||
|
||||
const res = await getInspectionItemList(params)
|
||||
|
||||
// 解析数据
|
||||
let records = []
|
||||
let total = 0
|
||||
if (res.data && res.data.records) {
|
||||
records = res.data.records
|
||||
total = res.data.total || 0
|
||||
} else if (res.data && Array.isArray(res.data)) {
|
||||
records = res.data
|
||||
total = records.length
|
||||
} else if (Array.isArray(res)) {
|
||||
records = res
|
||||
total = records.length
|
||||
}
|
||||
|
||||
// 映射数据格式
|
||||
const mappedItems = records.map(item => ({
|
||||
itemId: item.id || item.activityId || Math.random().toString(36).substring(2, 11),
|
||||
itemName: item.name || item.itemName || '',
|
||||
itemPrice: item.retailPrice || item.price || 0,
|
||||
itemAmount: item.retailPrice || item.price || 0,
|
||||
sampleType: item.specimenCode_dictText || item.sampleType || '血液',
|
||||
unit: item.unit || '',
|
||||
itemQty: 1,
|
||||
serviceFee: 0,
|
||||
type: category.label,
|
||||
isSelfPay: false,
|
||||
activityId: item.activityId,
|
||||
code: item.busNo || item.code || item.activityCode,
|
||||
inspectionTypeId: item.inspectionTypeId || null
|
||||
}))
|
||||
|
||||
// 更新分类数据
|
||||
if (loadMore) {
|
||||
// 追加数据
|
||||
category.items.push(...mappedItems)
|
||||
} else {
|
||||
// 首次加载
|
||||
category.items = mappedItems
|
||||
}
|
||||
|
||||
category.total = total
|
||||
category.hasMore = category.items.length < total
|
||||
category.loaded = true
|
||||
|
||||
} catch (error) {
|
||||
console.error(`加载分类 [${category.label}] 项目失败:`, error)
|
||||
// 加载失败时设置空数据
|
||||
if (!loadMore) {
|
||||
category.items = []
|
||||
category.total = 0
|
||||
category.hasMore = false
|
||||
category.loaded = true
|
||||
}
|
||||
} finally {
|
||||
category.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多项目
|
||||
function loadMoreItems(categoryKey) {
|
||||
const category = inspectionCategories.value.find(c => c.key === categoryKey)
|
||||
if (!category || !category.hasMore || category.loading) return
|
||||
|
||||
category.pageNo++
|
||||
loadCategoryItems(categoryKey, true)
|
||||
}
|
||||
|
||||
// 处理滚动事件(无限滚动)
|
||||
function handleScroll({ scrollTop, scrollHeight, clientHeight }) {
|
||||
// 距离底部 50px 时触发加载更多
|
||||
if (scrollHeight - scrollTop - clientHeight < 50) {
|
||||
const expandedCategory = inspectionCategories.value.find(c => c.expanded)
|
||||
if (expandedCategory && expandedCategory.hasMore && !expandedCategory.loading) {
|
||||
loadMoreItems(expandedCategory.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 防抖搜索处理
|
||||
const handleSearchDebounced = debounce(() => {
|
||||
// 重新加载当前展开分类的数据
|
||||
const expandedCategory = inspectionCategories.value.find(c => c.expanded)
|
||||
if (expandedCategory) {
|
||||
// 重置分页状态
|
||||
expandedCategory.pageNo = 1
|
||||
expandedCategory.loaded = false
|
||||
expandedCategory.hasMore = true
|
||||
expandedCategory.items = []
|
||||
// 重新加载
|
||||
loadCategoryItems(expandedCategory.key)
|
||||
}
|
||||
}, SEARCH_DEBOUNCE_TIME)
|
||||
|
||||
// 获取过滤后的项目(本地搜索)
|
||||
const getFilteredItems = (categoryKey) => {
|
||||
const category = inspectionCategories.value.find(cat => cat.key === categoryKey)
|
||||
if (!category) return []
|
||||
|
||||
if (!searchKeyword.value) {
|
||||
// 如果正在加载,返回现有数据
|
||||
if (category.loading) {
|
||||
return category.items
|
||||
}
|
||||
|
||||
return category.items.filter(item =>
|
||||
item.itemName.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
||||
)
|
||||
// 本地过滤(安全检查 itemName)
|
||||
if (searchKeyword.value) {
|
||||
const keyword = searchKeyword.value.toLowerCase()
|
||||
return category.items.filter(item =>
|
||||
item.itemName && item.itemName.toLowerCase().includes(keyword)
|
||||
)
|
||||
}
|
||||
|
||||
return category.items
|
||||
}
|
||||
|
||||
// 搜索建议查询(自动完成)
|
||||
async function querySearchInspectionItems(queryString, cb) {
|
||||
if (!queryString) {
|
||||
cb([])
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const params = {
|
||||
pageNo: 1,
|
||||
pageSize: 20, // 限制返回数量
|
||||
categoryCode: inspectionCategoryCode.value,
|
||||
searchKey: queryString
|
||||
}
|
||||
|
||||
const res = await getInspectionItemList(params)
|
||||
|
||||
let suggestions = []
|
||||
if (res.data && res.data.records) {
|
||||
// 映射数据格式,与 loadInspectionItemsByType 保持一致
|
||||
suggestions = res.data.records.map(item => ({
|
||||
itemId: item.id || item.activityId,
|
||||
itemName: item.name || item.itemName || '',
|
||||
itemPrice: item.retailPrice || item.price || 0,
|
||||
sampleType: item.specimenCode_dictText || item.sampleType || '血液',
|
||||
unit: item.unit || '',
|
||||
code: item.busNo || item.code || item.activityCode,
|
||||
activityId: item.activityId,
|
||||
inspectionTypeId: item.inspectionTypeId || null
|
||||
}))
|
||||
}
|
||||
|
||||
cb(suggestions)
|
||||
} catch (error) {
|
||||
console.error('搜索检验项目失败:', error)
|
||||
cb([])
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索选择处理
|
||||
function handleSearchSelect(item) {
|
||||
// 直接添加到已选列表
|
||||
if (!isItemSelected(item)) {
|
||||
selectedInspectionItems.value.push({
|
||||
...item,
|
||||
itemName: item.itemName
|
||||
})
|
||||
}
|
||||
// 清空搜索关键词
|
||||
searchKeyword.value = ''
|
||||
}
|
||||
|
||||
// 搜索框清空处理
|
||||
function handleSearchClear() {
|
||||
searchKeyword.value = ''
|
||||
}
|
||||
|
||||
// 获取检验申请单列表
|
||||
function getInspectionList() {
|
||||
@@ -1054,6 +1155,9 @@ async function resetForm() {
|
||||
|
||||
// 保存
|
||||
function handleSave() {
|
||||
// 如果正在保存,直接返回
|
||||
if (saving.value) return
|
||||
|
||||
// 重置验证错误状态
|
||||
Object.keys(validationErrors).forEach(key => {
|
||||
validationErrors[key] = false
|
||||
@@ -1061,29 +1165,28 @@ function handleSave() {
|
||||
|
||||
let hasErrors = false
|
||||
|
||||
// 检查必填字段
|
||||
// 检查必填字段,执行科室
|
||||
if (!formData.executeDepartment) {
|
||||
validationErrors.executeDepartment = true
|
||||
hasErrors = true
|
||||
}
|
||||
// 检查必填字段,诊断描述
|
||||
if (!formData.clinicDesc.trim()) {
|
||||
if (!formData.clinicDesc?.trim()) {
|
||||
validationErrors.clinicDesc = true
|
||||
hasErrors = true
|
||||
}
|
||||
// 检查必填字段,临床诊断
|
||||
if (!formData.clinicDiag.trim()) {
|
||||
if (!formData.clinicDiag?.trim()) {
|
||||
validationErrors.clinicDiag = true
|
||||
hasErrors = true
|
||||
}
|
||||
// 检查必填字段,病史摘要
|
||||
if (!formData.medicalHistorySummary.trim()) {
|
||||
if (!formData.medicalHistorySummary?.trim()) {
|
||||
validationErrors.medicalHistorySummary = true
|
||||
hasErrors = true
|
||||
}
|
||||
// 检查必填字段,检验目的
|
||||
if (!formData.purposeofInspection.trim()) {
|
||||
if (!formData.purposeofInspection?.trim()) {
|
||||
validationErrors.purposeofInspection = true
|
||||
hasErrors = true
|
||||
}
|
||||
@@ -1095,7 +1198,7 @@ function handleSave() {
|
||||
return
|
||||
}
|
||||
// 检查必填字段,申请日期
|
||||
if(!formData.applyTime || (typeof formData.applyTime === 'string' && !formData.applyTime.trim())) {
|
||||
if(!formData.applyTime || (typeof formData.applyTime === 'string' && !formData.applyTime?.trim())) {
|
||||
validationErrors.applyTime = true
|
||||
hasErrors = true
|
||||
}
|
||||
@@ -1182,9 +1285,11 @@ function handleSave() {
|
||||
|
||||
}
|
||||
const executeSave = (saveData) => {
|
||||
saving.value = true
|
||||
saveInspectionApplication(saveData).then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('保存成功')
|
||||
emit('save', res.data) // 通知父组件保存成功
|
||||
resetForm()
|
||||
// 生成新的申请单号
|
||||
generateApplicationNo().then((newApplyNo) => {
|
||||
@@ -1211,6 +1316,8 @@ const executeSave = (saveData) => {
|
||||
// 处理请求失败的其他错误
|
||||
console.error('保存检验申请单时发生错误:', error);
|
||||
ElMessage.error('保存失败,请稍后重试');
|
||||
}).finally(() => {
|
||||
saving.value = false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1222,10 +1329,10 @@ function handleView(row) {
|
||||
|
||||
// 根据检验项目名称找到对应的项目数据
|
||||
selectedInspectionItems.value = []
|
||||
const itemNames = row.inspectionItem.split('、')
|
||||
const itemNames = row.itemName?.split('、') || row.inspectionItem?.split('、') || []
|
||||
inspectionCategories.value.forEach(category => {
|
||||
category.items.forEach(item => {
|
||||
if (itemNames.includes(item.name)) {
|
||||
if (itemNames.includes(item.itemName)) {
|
||||
selectedInspectionItems.value.push(item)
|
||||
}
|
||||
})
|
||||
@@ -1234,7 +1341,7 @@ function handleView(row) {
|
||||
leftActiveTab.value = 'application'
|
||||
}
|
||||
|
||||
// 切换分类
|
||||
// 切换分类(修改为懒加载)
|
||||
function switchCategory(category) {
|
||||
if (activeCategory.value === category) {
|
||||
// 如果点击的是当前激活的分类,则收起
|
||||
@@ -1250,14 +1357,15 @@ function switchCategory(category) {
|
||||
inspectionCategories.value.forEach(cat => {
|
||||
cat.expanded = cat.key === category
|
||||
})
|
||||
|
||||
// 懒加载该分类的项目
|
||||
const targetCategory = inspectionCategories.value.find(c => c.key === category)
|
||||
if (targetCategory && !targetCategory.loaded) {
|
||||
loadCategoryItems(category)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理搜索
|
||||
function handleSearch() {
|
||||
// 搜索逻辑已在getFilteredItems中实现
|
||||
}
|
||||
|
||||
// 处理项目项点击(排除勾选框点击)
|
||||
function handleItemClick(item) {
|
||||
toggleInspectionItem(item)
|
||||
@@ -1409,8 +1517,8 @@ function handleCellClick(row, column) {
|
||||
|
||||
// 根据检验项目名称解析已选项目
|
||||
selectedInspectionItems.value = []
|
||||
if (row.inspectionItem) {
|
||||
const itemNames = row.inspectionItem.split('、')
|
||||
if (row.itemName || row.inspectionItem) {
|
||||
const itemNames = (row.itemName || row.inspectionItem).split('、')
|
||||
inspectionCategories.value.forEach(category => {
|
||||
category.items.forEach(item => {
|
||||
if (itemNames.includes(item.itemName)) {
|
||||
@@ -1956,6 +2064,39 @@ defineExpose({
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
/* 加载中占位样式 */
|
||||
.loading-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 加载更多样式 */
|
||||
.load-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border-top: 1px dashed #ebeef5;
|
||||
}
|
||||
|
||||
.load-info {
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 没有更多数据提示 */
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.inspection-tree-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in New Issue
Block a user