From 283d25642ac5a4e2246c30373b3654173221b265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E4=BA=91?= <赵云@gentronhealth.com> Date: Sun, 10 May 2026 11:01:17 +0800 Subject: [PATCH] =?UTF-8?q?Fix=20Bug=20#500:=20=E3=80=90=E9=97=A8=E8=AF=8A?= =?UTF-8?q?=E5=8C=BB=E7=94=9F=E7=AB=99=E3=80=91=E6=A3=80=E6=9F=A5=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E5=8F=B3=E4=BE=A7"=E6=A3=80=E6=9F=A5=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=88=86=E7=B1=BB"=E5=88=87=E6=8D=A2=E6=97=B6?= =?UTF-8?q?=EF=BC=8C=E7=95=8C=E9=9D=A2=E5=87=BA=E7=8E=B0=E6=98=8E=E6=98=BE?= =?UTF-8?q?=E6=8A=96=E5=8A=A8/=E9=97=AA=E7=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- .../examination/examinationApplication.vue | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/openhis-ui-vue3/src/views/doctorstation/components/examination/examinationApplication.vue b/openhis-ui-vue3/src/views/doctorstation/components/examination/examinationApplication.vue index d0d34308..7c763f07 100755 --- a/openhis-ui-vue3/src/views/doctorstation/components/examination/examinationApplication.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/examination/examinationApplication.vue @@ -314,6 +314,7 @@ >
¥{{ item.price }}/{{ item.unit || "次" }}
+
+ 加载中... +
@@ -517,6 +521,7 @@ const rules = { const categoryList = ref([]); // 原始分类+项目数据 const dictSearchKey = ref(''); const activeNames = ref(''); // 当前展开的折叠项 +const categoryLoadingSet = ref(new Set()); // Bug #500: 正在加载方法的分类集合 const allMethods = ref([]); @@ -632,16 +637,21 @@ const availableMethods = computed(() => { // 当可选方法列表改变时,如果当前选中的方法不在新列表中,则清空 // #428: 分类展开时联动加载检查方法 +// Bug #500: 使用 categoryLoadingSet 替代 dictLoading,避免切换分类时整个区域闪烁 async function handleCategoryExpand(cat) { if (!cat || !cat.typeName) return; - + + // 如果已加载过或正在加载中,跳过 + if ((cat.methods && cat.methods.length > 0) || categoryLoadingSet.value.has(cat.typeId)) return; + + categoryLoadingSet.value.add(cat.typeId); try { const res = await searchCheckMethod({ checkType: cat.typeName }); let data = res?.data?.data || res?.data || res?.rows || res; if (!Array.isArray(data) && res?.data && Array.isArray(res.data.data)) { data = res.data.data; } - + if (Array.isArray(data) && data.length > 0) { cat.methods = data.map(m => ({ id: m.id, @@ -655,14 +665,16 @@ async function handleCategoryExpand(cat) { } } catch (err) { console.error('加载分类检查方法失败', err); + } finally { + categoryLoadingSet.value.delete(cat.typeId); } } -async function handleCollapseChange(activeName) { - // 当折叠面板展开时,加载对应分类的检查方法 +// Bug #500: 改为非 async 函数,避免 el-collapse 的 @change 等待异步完成导致抖动 +function handleCollapseChange(activeName) { if (activeName) { const cat = filteredCategoryList.value.find(c => c.typeId == activeName); if (cat && (!cat.methods || cat.methods.length === 0)) { - await handleCategoryExpand(cat); + handleCategoryExpand(cat); // 异步加载,不 await } } } @@ -1309,6 +1321,20 @@ defineExpose({ getList }); font-weight: 500; color: #303133; } +/* Bug #500: 分类加载中的小圆点动画 */ +.loading-dot { + display: inline-block; + width: 6px; + height: 6px; + border-radius: 50%; + background: #409eff; + margin-left: 6px; + animation: dotPulse 1s ease-in-out infinite; +} +@keyframes dotPulse { + 0%, 100% { opacity: 0.3; transform: scale(0.8); } + 50% { opacity: 1; transform: scale(1.2); } +} .item-row { display: flex; align-items: center; @@ -1448,10 +1474,24 @@ defineExpose({ getList }); height: auto; line-height: 1.5; } +/* Bug #500: 折叠内容添加平滑过渡动画,避免切换时高度跳变 */ :deep(.el-collapse-item__content) { padding-bottom: 4px; + transition: all 0.3s ease; } +/* Bug #500: 折叠面板展开/收起动画使用 will-change 优化性能 */ :deep(.el-collapse-item__wrap) { border: none; + will-change: height; +} +:deep(.el-collapse-item) { + transition: margin 0.2s ease; +} +/* Bug #500: 分类加载中提示样式 */ +.category-loading-hint { + color: #909399; + font-size: 12px; + text-align: center; + padding: 8px 0; }