Files
his/openhis-ui-vue3/src/views/outpatient/doctor/examination/ExaminationApplication.vue
2026-05-27 00:37:23 +08:00

215 lines
5.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="examination-app-container">
<!-- 左侧检查项目分类 -->
<div class="left-panel">
<div class="panel-title">检查分类</div>
<el-tree
:data="categoryTree"
node-key="id"
highlight-current
@node-click="handleCategorySelect"
data-cy="category-tree"
/>
</div>
<!-- 中间检查项目列表 -->
<div class="middle-panel">
<div class="panel-title">检查项目</div>
<el-checkbox-group v-model="selectedItemIds" class="item-list">
<el-checkbox
v-for="item in currentCategoryItems"
:key="item.id"
:label="item.id"
@change="onItemCheckChange(item, $event)"
data-cy="item-checkbox"
>
{{ cleanItemName(item.name) }}
</el-checkbox>
</el-checkbox-group>
</div>
<!-- 右侧已选择区域 -->
<div class="right-panel">
<div class="panel-title">已选择</div>
<div class="selected-list">
<div
v-for="selected in selectedItemsList"
:key="selected.id"
class="selected-card"
data-cy="selected-card"
>
<div class="card-header" @click="toggleCard(selected.id)">
<span class="card-name" data-cy="selected-card-name" :title="selected.name">
{{ selected.name }}
</span>
<span class="expand-toggle" data-cy="expand-toggle">
{{ selected.expanded ? '收起' : '展开' }}
</span>
</div>
<!-- 明细/检查方法区域默认收起 -->
<div v-show="selected.expanded" class="card-details">
<!-- 已移除冗余的项目套餐明细标签 -->
<div
v-for="method in selected.methods"
:key="method.id"
class="method-row"
data-cy="method-row"
>
<el-checkbox
v-model="method.checked"
@change="onMethodCheckChange(method, $event)"
data-cy="method-checkbox"
>
{{ method.name }}
</el-checkbox>
</div>
</div>
</div>
<el-empty v-if="selectedItemsList.length === 0" description="暂无选择项目" />
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
// 模拟数据源实际应从API获取
const categoryTree = ref([])
const currentCategoryItems = ref([])
// 已选项目ID列表仅控制中间列表的项目勾选状态
const selectedItemIds = ref([])
// 已选项目列表(包含独立的方法状态与展开状态)
const selectedItemsList = reactive([])
// 清理名称:去除“套餐”前缀及冗余符号
const cleanItemName = (name) => {
if (!name) return ''
return name.replace(/^套餐[:]/, '').replace(/套餐$/, '')
}
// 选择分类
const handleCategorySelect = (node) => {
currentCategoryItems.value = node.items || []
}
// 项目勾选变化:严格解耦,不自动勾选关联方法
const onItemCheckChange = (item, checked) => {
if (checked) {
const exists = selectedItemsList.find(s => s.id === item.id)
if (!exists) {
selectedItemsList.push({
id: item.id,
name: cleanItemName(item.name),
expanded: false, // 默认收起
methods: (item.methods || []).map(m => ({
id: m.id,
name: m.name,
checked: false // 独立状态,初始不勾选
}))
})
}
} else {
const idx = selectedItemsList.findIndex(s => s.id === item.id)
if (idx !== -1) selectedItemsList.splice(idx, 1)
}
}
// 方法勾选变化:完全独立,不影响父级或其他方法
const onMethodCheckChange = (method, checked) => {
method.checked = checked
}
// 展开/收起卡片
const toggleCard = (id) => {
const target = selectedItemsList.find(s => s.id === id)
if (target) target.expanded = !target.expanded
}
</script>
<style scoped>
.examination-app-container {
display: flex;
gap: 16px;
height: 100%;
padding: 12px;
background: #f5f7fa;
}
.left-panel, .middle-panel, .right-panel {
flex: 1;
background: #fff;
border: 1px solid #ebeef5;
border-radius: 6px;
padding: 12px;
overflow-y: auto;
display: flex;
flex-direction: column;
}
.panel-title {
font-weight: 600;
margin-bottom: 12px;
color: #303133;
}
.item-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.selected-list {
flex: 1;
overflow-y: auto;
}
.selected-card {
border: 1px solid #dcdfe6;
border-radius: 6px;
margin-bottom: 10px;
background: #fafafa;
/* 宽度自适应,取消固定宽度导致的截断溢出 */
width: 100%;
min-width: 0;
box-sizing: border-box;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px;
cursor: pointer;
user-select: none;
background: #fff;
border-bottom: 1px solid transparent;
transition: all 0.2s;
}
.card-header:hover {
background: #f5f7fa;
}
.card-name {
font-weight: 500;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 85%;
color: #303133;
}
.expand-toggle {
color: #409eff;
font-size: 12px;
flex-shrink: 0;
}
.card-details {
padding: 8px 12px;
background: #fff;
}
.method-row {
padding: 6px 0;
display: flex;
align-items: center;
border-bottom: 1px dashed #ebeef5;
}
.method-row:last-child {
border-bottom: none;
}
</style>