Files
his/openhis-ui-vue3/src/views/outpatient/exam/ExamApply.vue
2026-05-27 05:58:42 +08:00

172 lines
4.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="exam-apply-container">
<!-- 左侧检查项目分类 -->
<el-card class="category-panel" shadow="never">
<template #header>检查项目分类</template>
<el-tree
:data="categories"
node-key="id"
highlight-current
@node-click="handleCategorySelect"
/>
</el-card>
<!-- 中间检查项目列表 -->
<el-card class="item-panel" shadow="never">
<template #header>检查项目</template>
<div class="item-list">
<div v-for="item in currentItems" :key="item.id" class="item-row">
<el-checkbox
v-model="item.checked"
@change="handleItemCheck(item)"
/>
<el-tooltip :content="item.name" placement="top" :show-after="300">
<span class="item-name">{{ cleanName(item.name) }}</span>
</el-tooltip>
</div>
</div>
</el-card>
<!-- 下方已选择区域 -->
<el-card class="selected-panel" shadow="never">
<template #header>已选择</template>
<div v-if="selectedItems.length === 0" class="empty-tip">暂无已选项目</div>
<el-collapse v-else v-model="activeCollapseNames">
<el-collapse-item
v-for="sel in selectedItems"
:key="sel.id"
:name="sel.id"
>
<template #title>
<el-tooltip :content="sel.name" placement="top" :show-after="300">
<span class="collapse-title">{{ cleanName(sel.name) }}</span>
</el-tooltip>
</template>
<div class="method-container">
<div v-for="method in sel.methods" :key="method.id" class="method-row">
<el-checkbox
v-model="method.checked"
@change="handleMethodCheck(sel, method)"
/>
<el-tooltip :content="method.name" placement="top" :show-after="300">
<span class="method-name">{{ cleanName(method.name) }}</span>
</el-tooltip>
</div>
</div>
</el-collapse-item>
</el-collapse>
</el-card>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
interface ExamMethod {
id: number | string
name: string
checked: boolean
}
interface ExamItem {
id: number | string
name: string
checked: boolean
methods: ExamMethod[]
}
const categories = ref<any[]>([])
const currentItems = ref<ExamItem[]>([])
const selectedItems = ref<ExamItem[]>([])
// 默认收起状态:不自动展开任何明细面板
const activeCollapseNames = ref<(number | string)[]>([])
const handleCategorySelect = (node: any) => {
// 实际项目中此处应调用 API 获取对应分类下的项目
currentItems.value = node.items || []
}
/**
* 清理名称:去除“套餐”等冗余标识,避免遮挡
*/
const cleanName = (name: string): string => {
if (!name) return ''
return name.replace(/套餐/g, '').trim()
}
/**
* 处理项目勾选:严格解耦,不联动勾选下属检查方法
*/
const handleItemCheck = (item: ExamItem) => {
if (item.checked) {
// 若未加入已选列表,则添加,并强制重置其方法为未勾选状态
if (!selectedItems.value.find(s => s.id === item.id)) {
selectedItems.value.push({
...item,
methods: item.methods.map(m => ({ ...m, checked: false }))
})
}
} else {
// 取消勾选则从已选列表移除
selectedItems.value = selectedItems.value.filter(s => s.id !== item.id)
}
}
/**
* 处理检查方法勾选:独立控制,不影响父级项目状态
*/
const handleMethodCheck = (sel: ExamItem, method: ExamMethod) => {
// 仅更新当前方法状态,保持父子级独立
// 可根据后续业务需求扩展:如所有方法取消时是否自动移除父项目
}
</script>
<style scoped>
.exam-apply-container {
display: flex;
flex-direction: column;
gap: 16px;
padding: 16px;
height: 100%;
}
.category-panel,
.item-panel,
.selected-panel {
width: 100%;
}
.item-list,
.method-container {
display: flex;
flex-direction: column;
gap: 10px;
padding: 8px 0;
}
.item-row,
.method-row {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 0;
}
.item-name,
.method-name,
.collapse-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 320px;
cursor: default;
}
.empty-tip {
color: #909399;
text-align: center;
padding: 24px 0;
font-size: 14px;
}
</style>