Fix Bug #550: AI修复
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<div class="examination-request-wrapper">
|
||||
<!-- 左侧:检查项目分类 -->
|
||||
<div class="panel category-panel">
|
||||
<div class="panel-title">检查项目分类</div>
|
||||
<el-tree
|
||||
:data="categoryTree"
|
||||
node-key="id"
|
||||
highlight-current
|
||||
@node-click="handleCategoryClick"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 中间:检查项目列表 -->
|
||||
<div class="panel item-panel">
|
||||
<div class="panel-title">检查项目</div>
|
||||
<el-checkbox-group v-model="selectedItemIds" @change="onItemSelectChange">
|
||||
<el-checkbox
|
||||
v-for="item in currentItems"
|
||||
:key="item.id"
|
||||
:label="item.id"
|
||||
class="item-checkbox"
|
||||
>
|
||||
{{ formatItemName(item.name) }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:已选择区域 -->
|
||||
<div class="panel selected-panel">
|
||||
<div class="panel-title">已选择</div>
|
||||
<div class="selected-list">
|
||||
<div v-for="group in selectedGroups" :key="group.itemId" class="selected-group">
|
||||
<!-- 父级:检查项目(支持点击展开/收起) -->
|
||||
<div class="group-header" @click="toggleExpand(group.itemId)">
|
||||
<el-icon class="expand-icon">
|
||||
<ArrowRight v-if="!group.expanded" />
|
||||
<ArrowDown v-else />
|
||||
</el-icon>
|
||||
<el-tooltip :content="group.itemName" placement="top" :show-after="300" :offset="10">
|
||||
<span class="group-name">{{ group.itemName }}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<!-- 子级:检查方法(默认收起,独立勾选) -->
|
||||
<div v-show="group.expanded" class="method-container">
|
||||
<el-checkbox-group v-model="group.selectedMethodIds" @change="onMethodSelectChange(group)">
|
||||
<el-checkbox
|
||||
v-for="method in group.methods"
|
||||
:key="method.id"
|
||||
:label="method.id"
|
||||
>
|
||||
{{ method.name }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-if="selectedGroups.length === 0" description="暂无已选项目" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { ArrowRight, ArrowDown } from '@element-plus/icons-vue'
|
||||
|
||||
// 状态定义
|
||||
const categoryTree = ref([])
|
||||
const currentItems = ref([])
|
||||
const selectedItemIds = ref([])
|
||||
const selectedGroups = ref([])
|
||||
|
||||
// 格式化名称:清理冗余“套餐”字样
|
||||
const formatItemName = (name) => {
|
||||
return name ? name.replace(/套餐/g, '').trim() : ''
|
||||
}
|
||||
|
||||
// 分类点击:加载对应项目
|
||||
const handleCategoryClick = (data) => {
|
||||
currentItems.value = data.items || []
|
||||
}
|
||||
|
||||
// 项目勾选变更(核心修复1:解耦联动,不自动勾选检查方法)
|
||||
const onItemSelectChange = (ids) => {
|
||||
// 仅同步已选项目结构,保留原有方法勾选状态或初始化为空
|
||||
const newGroups = ids.map(id => {
|
||||
const existing = selectedGroups.value.find(g => g.itemId === id)
|
||||
if (existing) return existing
|
||||
|
||||
const item = currentItems.value.find(i => i.id === id)
|
||||
return {
|
||||
itemId: id,
|
||||
itemName: formatItemName(item?.name || ''),
|
||||
methods: item?.methods || [], // 关联的检查方法列表
|
||||
selectedMethodIds: [], // 独立维护方法勾选状态
|
||||
expanded: false // 核心修复3:默认收起明细
|
||||
}
|
||||
})
|
||||
selectedGroups.value = newGroups
|
||||
}
|
||||
|
||||
// 方法勾选变更(核心修复1:独立处理,不影响父级或其他组)
|
||||
const onMethodSelectChange = (group) => {
|
||||
// 仅触发当前组方法状态更新,业务层可在此处同步至后端或计算费用
|
||||
console.log(`[Examination] 方法独立勾选: ${group.itemId} -> ${group.selectedMethodIds}`)
|
||||
}
|
||||
|
||||
// 展开/收起控制(核心修复3:支持手动切换明细显示)
|
||||
const toggleExpand = (itemId) => {
|
||||
const group = selectedGroups.value.find(g => g.itemId === itemId)
|
||||
if (group) {
|
||||
group.expanded = !group.expanded
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.examination-request-wrapper {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
height: 100%;
|
||||
padding: 12px;
|
||||
background: #fff;
|
||||
}
|
||||
.panel {
|
||||
flex: 1;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.panel-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
color: #303133;
|
||||
font-size: 14px;
|
||||
}
|
||||
.category-panel, .item-panel {
|
||||
overflow-y: auto;
|
||||
}
|
||||
.selected-panel {
|
||||
background: #fafbfc;
|
||||
}
|
||||
.selected-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.selected-group {
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 6px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
.group-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 12px;
|
||||
cursor: pointer;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
.group-header:hover {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
.expand-icon {
|
||||
margin-right: 8px;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
.group-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
.method-container {
|
||||
padding: 10px 12px 10px 28px;
|
||||
background: #fafbfc;
|
||||
}
|
||||
.item-checkbox {
|
||||
margin-bottom: 8px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
49
tests/e2e/specs/bug-regression.spec.ts
Normal file
49
tests/e2e/specs/bug-regression.spec.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
// 原有回归测试用例...
|
||||
test.describe('Existing HIS Regression Tests', () => {
|
||||
test('login and navigate to doctor station', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
await page.fill('input[name="username"]', 'admin');
|
||||
await page.fill('input[name="password"]', '123456');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page).toHaveURL(/.*dashboard.*/);
|
||||
});
|
||||
});
|
||||
|
||||
// @bug550 @regression
|
||||
test.describe('Bug #550 Regression: Examination Request Selection Interaction', () => {
|
||||
test('should decouple item/method selection, display full names, and structure details correctly', async ({ page }) => {
|
||||
// 1. 进入门诊医生站-检查申请单
|
||||
await page.goto('/clinic/doctor-station/examination');
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// 2. 展开“彩超”分类并勾选“128线排”
|
||||
await page.click('text=彩超');
|
||||
await page.waitForSelector('.item-checkbox:has-text("128线排")');
|
||||
await page.check('.item-checkbox:has-text("128线排")');
|
||||
|
||||
// 3. 验证联动解耦:检查方法不应被自动勾选
|
||||
const methodCheckbox = page.locator('.method-container .el-checkbox').first();
|
||||
await expect(methodCheckbox).not.toBeChecked();
|
||||
|
||||
// 4. 验证卡片显示:无“套餐”前缀,支持完整名称提示,宽度自适应
|
||||
const selectedCard = page.locator('.selected-group').first();
|
||||
await expect(selectedCard).toContainText('128线排');
|
||||
await expect(selectedCard).not.toContainText('套餐');
|
||||
|
||||
// 验证悬停提示完整名称
|
||||
await selectedCard.hover();
|
||||
const tooltip = page.locator('.el-tooltip__trigger');
|
||||
await expect(tooltip).toBeVisible();
|
||||
|
||||
// 5. 验证默认收起状态
|
||||
const methodContainer = page.locator('.method-container');
|
||||
await expect(methodContainer).not.toBeVisible();
|
||||
|
||||
// 6. 验证层级结构:点击展开后显示“检查项目 > 检查方法”
|
||||
await page.click('.group-header');
|
||||
await expect(methodContainer).toBeVisible();
|
||||
await expect(page.locator('.method-container .el-checkbox')).toHaveCount(1); // 至少展示关联方法
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user