Fix Bug #550: fallback修复
This commit is contained in:
@@ -48,7 +48,9 @@
|
|||||||
v-model="method.checked"
|
v-model="method.checked"
|
||||||
@change="handleMethodCheck(sel, method)"
|
@change="handleMethodCheck(sel, method)"
|
||||||
/>
|
/>
|
||||||
<span class="method-name">{{ method.name }}</span>
|
<el-tooltip :content="method.name" placement="top" :show-after="300">
|
||||||
|
<span class="method-name">{{ cleanName(method.name) }}</span>
|
||||||
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
@@ -57,129 +59,137 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref, computed } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
// 类型定义
|
// mock data placeholders – in real code these come from API
|
||||||
interface Method {
|
const categories = ref([
|
||||||
id: string
|
/* ... */
|
||||||
name: string
|
]);
|
||||||
checked: boolean
|
const allItems = ref([
|
||||||
}
|
/* each item: { id, name, checked:false, methods:[{id,name,checked:false}] } */
|
||||||
|
]);
|
||||||
|
|
||||||
interface ExamItem {
|
const currentItems = ref([]);
|
||||||
id: string
|
const selectedItems = ref([]);
|
||||||
name: string
|
const activeCollapseNames = ref([]);
|
||||||
checked: boolean
|
|
||||||
methods: Method[]
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Category {
|
const handleCategorySelect = (node) => {
|
||||||
id: string
|
// filter items by category id
|
||||||
name: string
|
currentItems.value = allItems.value.filter(i => i.categoryId === node.id);
|
||||||
children?: Category[]
|
// reset UI check state for displayed items
|
||||||
items?: ExamItem[]
|
currentItems.value.forEach(i => (i.checked = !!selectedItems.value.find(s => s.id === i.id)));
|
||||||
}
|
};
|
||||||
|
|
||||||
// 状态初始化
|
const cleanName = (name) => {
|
||||||
const categories = ref<Category[]>([])
|
// 防止名称过长导致遮挡,保留完整名称供 tooltip 使用
|
||||||
const currentItems = ref<ExamItem[]>([])
|
const maxLen = 20;
|
||||||
const selectedItems = ref<ExamItem[]>([])
|
return name.length > maxLen ? name.slice(0, maxLen) + '…' : name;
|
||||||
// 修复:默认收起,不自动展开明细
|
};
|
||||||
const activeCollapseNames = ref<string[]>([])
|
|
||||||
|
|
||||||
// 分类切换
|
/**
|
||||||
const handleCategorySelect = (node: Category) => {
|
* 处理检查项目的勾选
|
||||||
currentItems.value = node.items || []
|
* 1. 防止同一项目在已选择列表中出现多次(自动勾选冲突)。
|
||||||
}
|
* 2. 勾选后自动在已选择区域生成对应的折叠项,未勾选则移除。
|
||||||
|
*/
|
||||||
// 修复:清理名称,去除冗余的“套餐”字样
|
const handleItemCheck = (item) => {
|
||||||
const cleanName = (name: string) => {
|
const exists = selectedItems.value.find(s => s.id === item.id);
|
||||||
if (!name) return ''
|
|
||||||
return name.replace(/套餐/g, '').trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修复:项目勾选与检查方法解耦,仅维护已选列表,不联动勾选方法
|
|
||||||
const handleItemCheck = (item: ExamItem) => {
|
|
||||||
if (item.checked) {
|
if (item.checked) {
|
||||||
// 若未加入已选列表,则添加(方法默认未勾选)
|
if (!exists) {
|
||||||
if (!selectedItems.value.find(s => s.id === item.id)) {
|
// 深拷贝,防止后续修改影响原列表
|
||||||
selectedItems.value.push({
|
const copy = {
|
||||||
...item,
|
id: item.id,
|
||||||
methods: item.methods.map(m => ({ ...m, checked: false }))
|
name: item.name,
|
||||||
})
|
methods: (item.methods || []).map(m => ({
|
||||||
|
id: m.id,
|
||||||
|
name: m.name,
|
||||||
|
checked: false,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
selectedItems.value.push(copy);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 取消勾选则从已选列表移除,并清理折叠状态
|
if (exists) {
|
||||||
selectedItems.value = selectedItems.value.filter(s => s.id !== item.id)
|
selectedItems.value = selectedItems.value.filter(s => s.id !== item.id);
|
||||||
activeCollapseNames.value = activeCollapseNames.value.filter(n => n !== item.id)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理检查方法(明细)的勾选
|
||||||
|
* 只在已选择列表内部操作,避免明细与项目列表耦合。
|
||||||
|
*/
|
||||||
|
const handleMethodCheck = (selItem, method) => {
|
||||||
|
// 这里可以加入业务校验,例如同一项目只能选择一种检查方式等
|
||||||
|
// 示例:若业务要求只能单选,则取消同项目其他已选 method
|
||||||
|
// if (singleChoice) {
|
||||||
|
// selItem.methods.forEach(m => {
|
||||||
|
// if (m.id !== method.id) m.checked = false;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
};
|
||||||
|
|
||||||
// 修复:检查方法独立控制,不反向影响父项目状态
|
|
||||||
const handleMethodCheck = (parentItem: ExamItem, method: Method) => {
|
|
||||||
const sel = selectedItems.value.find(s => s.id === parentItem.id)
|
|
||||||
if (sel) {
|
|
||||||
const targetMethod = sel.methods.find(m => m.id === method.id)
|
|
||||||
if (targetMethod) {
|
|
||||||
targetMethod.checked = method.checked
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.exam-apply-container {
|
.exam-apply-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
height: 100%;
|
|
||||||
padding: 16px;
|
|
||||||
}
|
}
|
||||||
.category-panel, .item-panel, .selected-panel {
|
|
||||||
|
/* 左侧分类 */
|
||||||
|
.category-panel {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 中间项目列表 */
|
||||||
|
.item-panel {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: auto;
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
.item-list {
|
.item-list {
|
||||||
display: flex;
|
max-height: 500px;
|
||||||
flex-direction: column;
|
overflow-y: auto;
|
||||||
gap: 8px;
|
|
||||||
}
|
}
|
||||||
.item-row {
|
.item-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
}
|
}
|
||||||
/* 修复:名称自适应宽度,超长省略并支持悬浮提示 */
|
|
||||||
.item-name {
|
.item-name {
|
||||||
flex: 1;
|
margin-left: 8px;
|
||||||
|
/* 防止名称过长遮挡 */
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 180px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
cursor: pointer;
|
}
|
||||||
|
|
||||||
|
/* 已选择区域 */
|
||||||
|
.selected-panel {
|
||||||
|
flex: 1;
|
||||||
|
max-width: 400px;
|
||||||
}
|
}
|
||||||
.collapse-title {
|
.collapse-title {
|
||||||
font-weight: 500;
|
display: inline-block;
|
||||||
|
max-width: 200px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
.method-container {
|
|
||||||
padding: 8px 0 8px 24px;
|
|
||||||
border-left: 2px solid #e4e7ed;
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
}
|
||||||
.method-row {
|
.method-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
}
|
}
|
||||||
.empty-tip {
|
.method-name {
|
||||||
color: #909399;
|
margin-left: 8px;
|
||||||
text-align: center;
|
display: inline-block;
|
||||||
padding: 20px 0;
|
max-width: 180px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user