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

229 lines
6.2 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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">
<div class="exam-layout">
<!-- 左侧检查项目分类与项目树 -->
<div class="tree-section">
<el-tree
ref="itemTreeRef"
:data="itemTreeData"
node-key="id"
show-checkbox
:check-strictly="true"
:default-expand-all="false"
:props="itemTreeProps"
@check="handleTreeCheck"
/>
</div>
<!-- 右侧已选项目与明细 -->
<div class="selected-section">
<div class="section-title">已选择</div>
<div class="selected-tags">
<el-tag
v-for="group in selectedGroups"
:key="group.id"
closable
size="default"
show-overflow-tooltip
:title="group.fullName"
@close="removeGroup(group.id)"
>
{{ group.displayName }}
</el-tag>
</div>
<el-collapse v-model="activePanels" class="details-collapse">
<el-collapse-item
v-for="group in selectedGroups"
:key="group.id"
:name="group.id"
>
<template #title>
<span class="collapse-title">{{ group.displayName }}</span>
</template>
<div class="method-container">
<el-checkbox-group v-model="group.checkedMethods">
<el-checkbox
v-for="method in group.methods"
:key="method.id"
:label="method.id"
@change="onMethodChange(group, method)"
>
{{ method.name }}
</el-checkbox>
</el-checkbox-group>
</div>
</el-collapse-item>
</el-collapse>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { ElMessage } from 'element-plus';
import type { TreeNode } from 'element-plus/lib/components/tree/src/tree.type';
// --------------------
// 数据结构定义(简化示例)
// --------------------
interface Method {
id: number;
name: string;
}
interface Group {
id: number;
name: string; // 原始名称,可能带 “套餐” 前缀
methods: Method[];
}
/**
* 1⃣ 读取树形数据(这里假设已经通过接口获取并赋值)
* itemTreeData 的每个节点对应一个检查项目Group
* 其 children 为检查方法Method
*/
const itemTreeData = ref<TreeNode[]>([]);
/**
* Tree 组件的属性映射
*/
const itemTreeProps = {
label: 'name',
children: 'children',
};
/**
* 已选中的项目Group集合
* 结构:
* id, displayName去掉 “套餐” 前缀的名称fullName原始完整名称用于 tooltip
* methods所有可选方法checkedMethods已勾选的方法 id 列表)
*/
const selectedGroups = ref<Array<{
id: number;
displayName: string;
fullName: string;
methods: Method[];
checkedMethods: number[];
}>>([]);
/**
* 当前展开的 Collapse 面板(使用 group.id
*/
const activePanels = ref<number[]>([]);
/**
* 处理树节点勾选
*
* 需求:
* - 勾选项目节点时,只把项目本身加入 selectedGroups**不**自动勾选其下的检查方法。
* - 取消勾选时,移除对应的项目及其所有方法的选中状态。
*
* 通过 `check-strictly` 已经阻止了父子自动关联,但在业务层仍需要把
* 勾选的节点(只保留叶子为方法的情况)过滤掉,只保留项目节点。
*/
function handleTreeCheck(
data: any,
checkedNodes: any[],
indeterminateNodes: any[]
) {
// 1. 过滤出真正的项目节点(即没有 children或 children 为方法列表的父节点)
const projectNodes = checkedNodes.filter((node: any) => {
// 项目节点的 children 为方法数组,且 node.type === 'group'(业务自行约定)
// 为了兼容后端未返回 type 字段,这里判断是否存在 children 即可。
return node.children && node.children.length > 0;
});
// 2. 重新构建 selectedGroups仅保留项目层级信息
const newGroups = projectNodes.map((node: any) => {
const originalName: string = node.name || '';
// 去掉 “套餐” 前缀(如果有),并去除首尾空格
const displayName = originalName.replace(/^套餐\s*/, '').trim();
// 已经存在的 group用于保留已勾选的方法
const existed = selectedGroups.value.find(g => g.id === node.id);
return {
id: node.id,
displayName,
fullName: originalName, // 用于 tooltip
methods: (node.children || []).map((m: any) => ({
id: m.id,
name: m.name,
})),
// 保留之前已勾选的方法(若之前已存在),否则空数组
checkedMethods: existed ? existed.checkedMethods : [],
};
});
selectedGroups.value = newGroups;
}
/**
* 移除已选项目
*/
function removeGroup(groupId: number) {
selectedGroups.value = selectedGroups.value.filter(g => g.id !== groupId);
}
/**
* 检查方法勾选变化
* - 只更新对应 group 的 checkedMethods。
* - 不会影响其他 group也不会触发项目自动勾选。
*/
function onMethodChange(group: any, method: any) {
// 方法的勾选状态已经由 v-model 自动同步到 group.checkedMethods
// 这里仅做业务校验(如需要限制同一项目只能选择一种方法等),
// 目前保持空实现以避免副作用。
}
/**
* 初始化(示例:从后端获取树形数据)
*/
async function loadTreeData() {
// 这里使用 mock 数据,实际请调用接口
const mockData = [
{
id: 1,
name: '套餐 彩超',
children: [
{ id: 101, name: '128线排' },
{ id: 102, name: '多普勒' },
],
},
{
id: 2,
name: '普通 X 光',
children: [{ id: 201, name: '胸片' }],
},
];
itemTreeData.value = mockData;
}
loadTreeData();
</script>
<style scoped>
.exam-apply {
padding: 20px;
}
.exam-layout {
display: flex;
}
.tree-section {
width: 30%;
margin-right: 20px;
}
.selected-section {
flex: 1;
}
.selected-tags {
margin-bottom: 10px;
}
.method-container {
padding: 10px;
}
.collapse-title {
font-weight: 500;
}
</style>