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

224 lines
5.7 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">
<!-- 左侧检查项目分类 -->
<div class="panel category-panel">
<h3 class="panel-title">检查项目分类</h3>
<el-tree
:data="categoryTree"
:props="{ label: 'name', children: 'children' }"
node-key="id"
highlight-current
@node-click="handleCategoryClick"
/>
</div>
<!-- 中间检查项目列表 -->
<div class="panel item-panel">
<h3 class="panel-title">检查项目</h3>
<el-checkbox-group v-model="selectedItemIds" @change="handleItemSelect">
<el-checkbox
v-for="item in currentItems"
:key="item.id"
:label="item.id"
class="item-checkbox"
>
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</div>
<!-- 右侧已选择区域 -->
<div class="panel selected-panel">
<h3 class="panel-title">已选择</h3>
<div v-if="selectedGroups.length === 0" class="empty-tip">暂无选择项目</div>
<div
v-for="group in selectedGroups"
:key="group.itemId"
class="selected-item-card"
>
<!-- 卡片头部名称自适应/提示 + 展开收起控制 -->
<div class="card-header" @click="toggleDetail(group.itemId)">
<el-tooltip :content="group.itemName" placement="top" :show-after="300">
<span class="item-name">{{ truncateName(group.itemName) }}</span>
</el-tooltip>
<el-icon class="toggle-icon">
<ArrowDown v-if="group.expanded" />
<ArrowRight v-else />
</el-icon>
</div>
<!-- 明细区域默认收起严格遵循 项目 > 检查方法 层级 -->
<div v-show="group.expanded" class="detail-panel">
<div v-for="method in group.methods" :key="method.id" class="method-row">
<el-checkbox
v-model="method.checked"
@change="handleMethodChange(group.itemId, method)"
>
{{ method.name }}
</el-checkbox>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
import { ElTree, ElCheckbox, ElCheckboxGroup, ElTooltip, ElIcon } from 'element-plus';
import { ArrowDown, ArrowRight } from '@element-plus/icons-vue';
// 模拟分类数据
const categoryTree = ref([
{ id: 'c1', name: '彩超', children: [
{ id: 'i1', name: '128线排', methods: [{ id: 'm1', name: '常规检查', checked: false }, { id: 'm2', name: '血管多普勒', checked: false }] },
{ id: 'i2', name: '套餐-腹部彩超', methods: [{ id: 'm3', name: '肝胆脾胰', checked: false }] }
]}
]);
const currentItems = ref([]);
const selectedItemIds = ref([]);
const selectedGroups = ref([]);
// 点击分类加载对应项目
const handleCategoryClick = (data) => {
if (data.children) {
currentItems.value = data.children;
}
};
// 修复1项目勾选与检查方法解耦。仅更新已选列表不联动修改方法状态
const handleItemSelect = (ids) => {
// 过滤掉已取消的项目
const validGroups = selectedGroups.value.filter(g => ids.includes(g.itemId));
// 新增勾选的项目
const newIds = ids.filter(id => !validGroups.some(g => g.itemId === id));
newIds.forEach(id => {
const item = findItemById(id);
if (item) {
validGroups.push({
itemId: item.id,
// 修复2去除“套餐”前缀避免冗余显示
itemName: item.name.replace(/^套餐[-]?/, ''),
expanded: false, // 修复3默认收起状态
methods: item.methods.map(m => ({ ...m, checked: false })) // 修复1方法默认不勾选保持独立
});
}
});
selectedGroups.value = validGroups;
};
// 修复3点击展开/收起明细
const toggleDetail = (itemId) => {
const group = selectedGroups.value.find(g => g.itemId === itemId);
if (group) group.expanded = !group.expanded;
};
// 检查方法独立勾选逻辑
const handleMethodChange = (itemId, method) => {
// 仅更新当前方法状态,不影响项目或其他方法
console.log(`方法 ${method.name} 状态变更为: ${method.checked}`);
};
// 辅助:查找项目
const findItemById = (id) => {
for (const cat of categoryTree.value) {
if (cat.children) {
const found = cat.children.find(i => i.id === id);
if (found) return found;
}
}
return null;
};
// 修复2名称截断与提示
const truncateName = (name) => {
return name.length > 12 ? name.slice(0, 12) + '...' : name;
};
</script>
<style scoped>
.exam-apply-container {
display: flex;
gap: 16px;
padding: 16px;
height: 100%;
}
.panel {
background: #fff;
border: 1px solid #ebeef5;
border-radius: 4px;
padding: 12px;
}
.category-panel { width: 20%; }
.item-panel { width: 35%; }
.selected-panel { width: 45%; }
.panel-title {
margin: 0 0 12px;
font-size: 14px;
font-weight: 600;
color: #303133;
}
.item-checkbox {
display: block;
margin-bottom: 8px;
}
.selected-item-card {
border: 1px solid #dcdfe6;
border-radius: 4px;
margin-bottom: 10px;
overflow: hidden;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px;
background: #f5f7fa;
cursor: pointer;
user-select: none;
}
.item-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
color: #303133;
}
.toggle-icon {
margin-left: 8px;
color: #909399;
}
.detail-panel {
padding: 8px 12px;
background: #fff;
border-top: 1px solid #ebeef5;
}
.method-row {
padding: 6px 0;
font-size: 13px;
color: #606266;
}
.empty-tip {
text-align: center;
color: #909399;
padding: 20px 0;
font-size: 13px;
}
</style>