Fix Bug #550: AI修复

This commit is contained in:
2026-05-27 02:08:50 +08:00
parent f214a137f7
commit 3fd04450a0
5 changed files with 232 additions and 37 deletions

View File

@@ -0,0 +1,195 @@
<template>
<div class="check-apply-container">
<!-- 左侧检查项目分类 -->
<div class="panel category-panel">
<h3 class="panel-title">检查项目分类</h3>
<el-tree
:data="categories"
: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-table :data="currentItems" border style="width: 100%" @selection-change="handleItemSelection">
<el-table-column type="selection" width="55" />
<el-table-column prop="name" label="项目名称" show-overflow-tooltip />
<el-table-column label="操作" width="80" align="center">
<template #default="{ row }">
<el-button size="small" type="primary" link @click="toggleItemExpand(row)">
{{ row.expanded ? '收起' : '展开' }}
</el-button>
</template>
</el-table-column>
</el-table>
</div>
<!-- 右侧已选择 & 方法明细 -->
<div class="panel selected-panel">
<h3 class="panel-title">已选择</h3>
<div class="selected-list">
<div v-for="item in selectedItems" :key="item.id" class="selected-card">
<div class="card-header" @click="item.expanded = !item.expanded">
<el-checkbox
v-model="item.checked"
@change="onItemCheckChange(item)"
@click.stop
/>
<span class="item-name" :title="item.name">{{ cleanName(item.name) }}</span>
<el-icon class="expand-icon">
<ArrowDown v-if="item.expanded" />
<ArrowRight v-else />
</el-icon>
</div>
<div v-show="item.expanded" class="method-list">
<div v-for="method in item.methods" :key="method.id" class="method-item">
<el-checkbox v-model="method.checked" @change="onMethodCheckChange(item, method)" />
<span class="method-name" :title="method.name">{{ method.name }}</span>
</div>
</div>
</div>
<el-empty v-if="selectedItems.length === 0" description="暂无已选项目" :image-size="60" />
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ArrowDown, ArrowRight } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
// 模拟数据结构(实际应从 API 获取)
interface Method { id: string; name: string; checked: boolean }
interface CheckItem { id: string; name: string; checked: boolean; expanded: boolean; methods: Method[] }
interface Category { id: string; name: string; children: CheckItem[] }
const categories = ref<Category[]>([
{
id: 'c1', name: '彩超', children: [
{ id: 'i1', name: '128线排彩超', checked: false, expanded: false, methods: [
{ id: 'm1', name: '常规腹部', checked: false },
{ id: 'm2', name: '心脏彩超', checked: false }
]},
{ id: 'i2', name: '套餐-甲状腺彩超', checked: false, expanded: false, methods: [
{ id: 'm3', name: '双侧甲状腺', checked: false }
]}
]
}
])
const currentItems = ref<CheckItem[]>([])
const selectedItems = reactive<CheckItem[]>([])
const handleCategoryClick = (data: Category) => {
currentItems.value = data.children || []
}
const handleItemSelection = (selection: CheckItem[]) => {
// 仅更新选中状态,不联动方法
currentItems.value.forEach(item => {
item.checked = selection.includes(item)
if (item.checked && !selectedItems.find(s => s.id === item.id)) {
selectedItems.push({ ...item, expanded: false })
}
})
// 移除未选中的
const selectedIds = selection.map(i => i.id)
for (let i = selectedItems.length - 1; i >= 0; i--) {
if (!selectedIds.includes(selectedItems[i].id)) {
selectedItems.splice(i, 1)
}
}
}
const toggleItemExpand = (item: CheckItem) => {
item.expanded = !item.expanded
}
const onItemCheckChange = (item: CheckItem) => {
// 项目勾选独立,不自动勾选/取消方法
if (!item.checked) {
const idx = selectedItems.findIndex(s => s.id === item.id)
if (idx !== -1) selectedItems.splice(idx, 1)
}
}
const onMethodCheckChange = (item: CheckItem, method: Method) => {
// 方法勾选独立,不反向影响父项目
// 业务逻辑:仅记录方法选择状态,提交时一并携带
}
const cleanName = (name: string) => {
// 去除冗余的“套餐”、“项目套餐明细”等前缀
return name.replace(/^(套餐|项目套餐明细)[-:]?/g, '')
}
</script>
<style scoped>
.check-apply-container {
display: flex;
gap: 16px;
height: 100%;
padding: 16px;
background: #f5f7fa;
}
.panel {
background: #fff;
border-radius: 8px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
display: flex;
flex-direction: column;
}
.category-panel { flex: 1; min-width: 200px; }
.item-panel { flex: 2; min-width: 300px; }
.selected-panel { flex: 2; min-width: 300px; }
.panel-title { margin: 0 0 12px; font-size: 16px; font-weight: 600; color: #303133; }
.selected-list { flex: 1; overflow-y: auto; padding-right: 4px; }
.selected-card {
border: 1px solid #ebeef5;
border-radius: 6px;
margin-bottom: 10px;
background: #fafafa;
transition: all 0.2s;
}
.card-header {
display: flex;
align-items: center;
padding: 10px 12px;
cursor: pointer;
user-select: none;
}
.card-header:hover { background: #f0f2f5; }
.item-name {
flex: 1;
margin: 0 8px;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0; /* 关键:配合 flex 实现自适应截断 */
}
.expand-icon { color: #909399; font-size: 14px; }
.method-list {
padding: 8px 12px 12px 36px;
border-top: 1px dashed #dcdfe6;
}
.method-item {
display: flex;
align-items: center;
padding: 6px 0;
color: #606266;
}
.method-name {
margin-left: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
</style>