From bdd60f01fcf55ae9392fe20412ad5d723e50259c Mon Sep 17 00:00:00 2001 From: zhaoyun Date: Wed, 27 May 2026 07:43:12 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#550:=20fallback=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/outpatient/exam/ExamApply.vue | 350 +++++++----------- 1 file changed, 124 insertions(+), 226 deletions(-) diff --git a/openhis-ui-vue3/src/views/outpatient/exam/ExamApply.vue b/openhis-ui-vue3/src/views/outpatient/exam/ExamApply.vue index 70578f0d1..6a370b0ca 100644 --- a/openhis-ui-vue3/src/views/outpatient/exam/ExamApply.vue +++ b/openhis-ui-vue3/src/views/outpatient/exam/ExamApply.vue @@ -1,72 +1,55 @@ @@ -74,200 +57,115 @@ import { ref, computed } from 'vue' import { ArrowDown, ArrowRight } from '@element-plus/icons-vue' -// 状态定义 -const categoryTree = ref([]) -const currentItems = ref([]) -const currentMethods = ref([]) +/** + * 说明 + * ----- + * 本组件原有的交互存在以下问题(Bug #550): + * 1. 勾选检查项目后会自动勾选同属项目的检查方法,导致“项目‑方法”耦合。 + * 2. 已选项目区域默认展开,页面高度占用过大。 + * 3. 项目名称若带有 “套餐” 前缀,会直接展示,影响视觉。 + * + * 为了解耦、优化交互并兼容旧数据,做了以下改动: + * - 项目卡片点击仅切换 `item.checked`,不再自动勾选关联的检查方法。 + * - 已选区域默认收起(`selectedGroupExpanded = false`),用户点击标题后才展开。 + * - 在展示名称时统一去除 “套餐” 前缀,并在名称过长时通过 `title` 属性提供完整提示。 + * - 为已选项目提供“一键清空”功能,提升用户体验。 + * - 方法的勾选仍然保持双向绑定,业务层可根据 `method.checked` 进行后续处理。 + */ -// 修复 #550-1:项目与方法独立存储,彻底解耦联动冲突 -const selectedProjects = ref([]) -const selectedMethods = ref([]) +/* ---------- 数据模型 ---------- */ +const currentItems = ref([]) // [{id, name, checked}] +const currentMethods = ref([]) // [{id, name, projectId, checked}] -// 分类点击加载数据(模拟接口) -const handleCategoryClick = (node) => { - // 实际项目中此处调用 API 获取 currentItems 和 currentMethods - // 保持独立加载,不自动勾选 -} +/* ---------- 选中状态 ---------- */ +// 已选项目(仅保留 checked 为 true 的项目) +const selectedItems = computed(() => + currentItems.value.filter(i => i.checked) +) -// 修复 #550-1:独立切换项目,不触发方法联动 -const toggleItem = (item) => { - item.checked = !item.checked - if (item.checked) { - if (!selectedProjects.value.find(p => p.id === item.id)) { - selectedProjects.value.push({ ...item }) - } - } else { - selectedProjects.value = selectedProjects.value.filter(p => p.id !== item.id) - // 移除关联的已选方法(可选,根据业务需求保留或清除,此处保持独立不强制清除) - } -} - -// 修复 #550-1:独立切换方法,不触发项目联动 -const toggleMethod = (method) => { - method.checked = !method.checked - if (method.checked) { - if (!selectedMethods.value.find(m => m.id === method.id)) { - selectedMethods.value.push({ ...method }) - } - } else { - selectedMethods.value = selectedMethods.value.filter(m => m.id !== method.id) - } -} - -const onMethodCheckChange = (method) => { - // 同步回右侧列表状态 - const target = currentMethods.value.find(m => m.id === method.id) - if (target) target.checked = method.checked -} - -// 修复 #550-2 & #550-3:结构化分组、默认收起、清理冗余文案 -const selectedGroups = computed(() => { - const groups = [] - const methodMap = new Map() - - // 1. 构建项目节点 - selectedProjects.value.forEach(proj => { - groups.push({ - id: proj.id, - name: proj.name, - displayName: cleanPackageName(proj.name), - collapsed: true, // 修复 #550-2:默认收起 - methods: [] - }) - }) - - // 2. 将方法挂载到对应项目下(若无关联则独立展示) - selectedMethods.value.forEach(m => { - const parent = groups.find(g => g.id === m.projectId) - const cleanMethod = { ...m, name: m.name } - if (parent) { - parent.methods.push(cleanMethod) - } else { - // 游离方法作为独立组展示 - groups.push({ - id: `method_${m.id}`, - name: m.name, - displayName: cleanPackageName(m.name), - collapsed: true, - methods: [] - }) - } - }) - - return groups +// 已选项目对应的检查方法(仅展示已选项目下的所有方法,保持独立勾选状态) +const selectedMethods = computed(() => { + const itemIds = selectedItems.value.map(i => i.id) + return currentMethods.value.filter(m => itemIds.includes(m.projectId)) }) -// 清理“套餐”前缀及冗余符号 -const cleanPackageName = (name) => { +// 已选区域标题(去除 “套餐” 前缀并拼接项目名称) +const selectedGroupTitle = computed(() => { + const names = selectedItems.value.map(i => formatItemName(i.name)) + return names.join('、') +}) + +// 已选区域展开/收起状态(默认收起) +const selectedGroupExpanded = ref(false) + +/* ---------- 方法 ---------- */ +// 项目卡片点击:仅切换项目本身的选中状态 +function onItemCardClick(item) { + item.checked = !item.checked +} + +// 检查方法勾选变化(业务层可监听 method.checked) +function onMethodCheckChange(method) { + // 此处仅保留业务钩子,若有额外业务需求可在此处补充 +} + +// 切换已选区域展开/收起 +function toggleSelectedGroup() { + selectedGroupExpanded.value = !selectedGroupExpanded.value +} + +// 清空所有已选项目及方法 +function clearAllSelection() { + currentItems.value.forEach(i => (i.checked = false)) + currentMethods.value.forEach(m => (m.checked = false)) +} + +// 名称格式化:去除 “套餐” 前缀并返回原始名称(用于内部逻辑) +// UI 展示时使用 `formatItemName`,并在 `title` 中保留完整名称 +function formatItemName(name) { if (!name) return '' - return name.replace(/^(套餐|项目套餐)[::]\s*/g, '').trim() + // 去除所有以 “套餐” 开头的前缀(可能出现 “套餐-” 或 “套餐 ” 等情况) + return name.replace(/^套餐[\s-]*/, '') }