Fix Bug #550: AI修复

This commit is contained in:
2026-05-27 03:34:29 +08:00
parent 4e0a8dfd94
commit 7d7153735d
2 changed files with 249 additions and 41 deletions

View File

@@ -0,0 +1,168 @@
<template>
<div class="examination-apply-container">
<el-row :gutter="16" style="height: 100%;">
<!-- 左侧检查项目分类 -->
<el-col :span="6" class="panel">
<div class="panel-header">检查项目分类</div>
<el-tree
:data="categories"
:props="{ label: 'name', children: 'children' }"
highlight-current
@node-click="handleCategorySelect"
data-cy="category-tree"
/>
</el-col>
<!-- 中间检查项目列表 -->
<el-col :span="9" class="panel">
<div class="panel-header">检查项目</div>
<div class="item-list" data-cy="item-list">
<div v-for="item in currentCategoryItems" :key="item.id" class="item-row">
<el-checkbox
:label="item.id"
v-model="selectedItemIds"
@change="handleItemToggle(item)"
>
{{ item.name }}
</el-checkbox>
</div>
</div>
</el-col>
<!-- 右侧已选择区域 -->
<el-col :span="9" class="panel">
<div class="panel-header">已选择</div>
<div class="selected-list">
<div v-for="group in selectedGroups" :key="group.id" class="selected-group">
<!-- 项目卡片自适应宽度悬停提示完整名称点击展开/收起 -->
<div
class="selected-card"
:class="{ 'is-expanded': group.expanded }"
@click="toggleGroupExpand(group.id)"
data-cy="selected-card"
>
<el-tooltip :content="group.originalName" placement="top" :show-after="300">
<span class="card-name">{{ group.displayName }}</span>
</el-tooltip>
<el-icon class="expand-icon">
<ArrowDown v-if="group.expanded" />
<ArrowRight v-else />
</el-icon>
</div>
<!-- 检查方法明细默认收起独立勾选严格遵循 项目 > 方法 层级 -->
<div v-if="group.expanded" class="method-list" data-cy="method-list">
<div v-for="method in group.methods" :key="method.id" class="method-item" data-cy="method-item">
<el-checkbox
v-model="method.checked"
@change="handleMethodToggle(method)"
data-cy="method-checkbox"
>
{{ method.name }}
</el-checkbox>
</div>
</div>
</div>
<el-empty v-if="selectedGroups.length === 0" description="暂无已选项目" />
</div>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import { ArrowDown, ArrowRight } from '@element-plus/icons-vue'
// 数据结构定义
interface ExamMethod { id: string; name: string; checked: boolean }
interface ExamItem { id: string; name: string; methods: ExamMethod[] }
interface Category { id: string; name: string; children: ExamItem[] }
// 模拟分类与项目数据实际应从API获取
const categories = ref<Category[]>([
{ 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 currentCategoryId = ref<string>('')
const selectedItemIds = ref<string[]>([])
const selectedItemsMap = ref<Map<string, { item: ExamItem; expanded: boolean }>>(new Map())
const currentCategoryItems = computed(() => {
const cat = categories.value.find(c => c.id === currentCategoryId.value)
return cat ? cat.children : []
})
// 结构化展示:将已选项按 项目 > 检查方法 层级组织
const selectedGroups = computed(() => {
return Array.from(selectedItemsMap.value.entries()).map(([id, data]) => ({
id,
originalName: data.item.name,
displayName: formatName(data.item.name),
expanded: data.expanded,
methods: data.item.methods.map(m => ({ ...m }))
}))
})
// 修复:清理“套餐”前缀及冗余文案
const formatName = (name: string) => name.replace(/^套餐[:]/, '').trim()
const handleCategorySelect = (node: Category) => {
currentCategoryId.value = node.id
}
// 修复1项目勾选与检查方法完全解耦移除原有自动联动逻辑
const handleItemToggle = (item: ExamItem) => {
if (selectedItemIds.value.includes(item.id)) {
// 新增时默认收起明细,避免界面拥挤
selectedItemsMap.value.set(item.id, { item, expanded: false })
} else {
selectedItemsMap.value.delete(item.id)
}
}
// 修复2检查方法独立控制不随父项目状态联动
const handleMethodToggle = (method: ExamMethod) => {
// 仅更新当前方法勾选状态,不影响其他项
console.log(`方法 ${method.name} 状态变更为: ${method.checked}`)
}
// 修复3点击卡片展开/收起明细
const toggleGroupExpand = (id: string) => {
const data = selectedItemsMap.value.get(id)
if (data) {
data.expanded = !data.expanded
}
}
</script>
<style scoped>
.examination-apply-container { padding: 16px; height: 100%; background: #f5f7fa; }
.panel { height: 600px; background: #fff; border-radius: 4px; padding: 12px; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
.panel-header { font-weight: 600; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid #ebeef5; color: #303133; }
.item-list { flex: 1; overflow-y: auto; }
.item-row { padding: 10px 0; border-bottom: 1px dashed #f0f0f0; }
.selected-list { flex: 1; overflow-y: auto; }
.selected-group { margin-bottom: 12px; }
/* 修复:卡片宽度自适应,文本溢出省略,悬停提示 */
.selected-card {
display: flex; justify-content: space-between; align-items: center;
padding: 10px 12px; background: #ecf5ff; border: 1px solid #d9ecff; border-radius: 4px; cursor: pointer;
width: auto; max-width: 100%; box-sizing: border-box; transition: background 0.2s;
}
.selected-card:hover { background: #d9ecff; }
.card-name {
flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
margin-right: 8px; font-size: 14px; color: #409eff; font-weight: 500;
}
.expand-icon { font-size: 14px; color: #909399; flex-shrink: 0; }
/* 修复:明细区域层级缩进,视觉区分 */
.method-list { padding: 8px 0 8px 24px; background: #fafafa; border-left: 2px solid #409eff; margin-top: 4px; border-radius: 0 0 4px 4px; }
.method-item { padding: 6px 0; font-size: 13px; color: #606266; }
.method-item .el-checkbox { margin-left: 0; }
</style>