演示效果
实现分项多选功能,原始数据格式如下(来自 国内直连GPT/Claude ):
javascript
originalData: [
{
devName: "21321",
devNo: "23892819302",
segments: ["锅 炉标", "拆卸 汽缸 清洗", "油压 清洗"]
},
{
devName: "23211321",
devNo: "432423892819302",
segments: ["1锅 2炉标", "2拆卸 2汽缸 清洗", "油压 清洗"]
}
],
实现代码(基于vue2),如果想实现Vue3或者React或者svelete等其他框架
可以使用 国内直连GPT/Claude 让AI直接转换即可,正确率99%
下面直接上代码:
javascript
<template>
<div class="container">
<div v-for="(item, index) in processedData" :key="index" class="device-item">
<h3>设备名称: {{ item.devName }}</h3>
<p>设备编号: {{ item.devNo }}</p>
<div class="segments-container">
<div
v-for="(segment, segIndex) in item.processedSegments"
:key="segIndex"
:class="[
'segment-group',
{
'active-segment': isActiveSegment(index, segIndex)
}
]"
>
<!-- 显示原始分段作为标题 -->
<div class="segment-title">{{ item.segments[segIndex] }}</div>
<!-- 显示拆分后的词语 -->
<div class="segment-words">
<span
v-for="(word, wordIndex) in segment"
:key="wordIndex"
:class="['word', { 'selected': isWordSelected(index, segIndex, wordIndex) }]"
@click="toggleWordSelection(index, segIndex, wordIndex, word)"
>
{{ word }}
</span>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SegmentsSelector',
data() {
return {
originalData: [
{
devName: "21321",
devNo: "23892819302",
segments: ["锅 炉标", "拆卸 汽缸 清洗", "油压 清洗"]
},
{
devName: "23211321",
devNo: "432423892819302",
segments: ["1锅 2炉标", "2拆卸 2汽缸 清洗", "油压 清洗"]
}
],
currentDeviceIndex: null, // 当前操作的设备索引
currentSegmentIndex: null, // 当前操作的分组索引
selectedWords: {},
}
},
computed: {
processedData() {
return this.originalData.map(item => ({
...item,
processedSegments: item.segments.map(segment => segment.split(' '))
}));
}
},
methods: {
// 判断当前分组是否激活
isActiveSegment(deviceIndex, segmentIndex) {
return this.currentDeviceIndex === deviceIndex &&
this.currentSegmentIndex === segmentIndex;
},
initDeviceSelection(deviceIndex) {
if (!this.selectedWords[deviceIndex]) {
this.$set(this.selectedWords, deviceIndex, {});
}
},
initSegmentSelection(deviceIndex, segmentIndex) {
if (!this.selectedWords[deviceIndex][segmentIndex]) {
this.$set(this.selectedWords[deviceIndex], segmentIndex, []);
}
},
isWordSelected(deviceIndex, segmentIndex, wordIndex) {
if (!this.selectedWords[deviceIndex] ||
!this.selectedWords[deviceIndex][segmentIndex]) {
return false;
}
return this.selectedWords[deviceIndex][segmentIndex].some(
selection => selection.wordIndex === wordIndex
);
},
toggleWordSelection(deviceIndex, segmentIndex, wordIndex, word) {
// 如果切换到新设备,清空所有选择
if (this.currentDeviceIndex !== deviceIndex) {
this.selectedWords = {};
this.currentDeviceIndex = deviceIndex;
this.currentSegmentIndex = segmentIndex;
}
// 如果在同一设备内切换到新分组,清空当前设备的其他分组选择
else if (this.currentSegmentIndex !== segmentIndex) {
this.$set(this.selectedWords, deviceIndex, {});
this.currentSegmentIndex = segmentIndex;
}
// 初始化数据结构
this.initDeviceSelection(deviceIndex);
this.initSegmentSelection(deviceIndex, segmentIndex);
const segmentSelections = this.selectedWords[deviceIndex][segmentIndex];
const selectionIndex = segmentSelections.findIndex(
selection => selection.wordIndex === wordIndex
);
if (selectionIndex === -1) {
// 添加选中
segmentSelections.push({
wordIndex,
word
});
} else {
// 取消选中
segmentSelections.splice(selectionIndex, 1);
}
// 触发选择变化事件
this.emitSelectionChange();
},
getCurrentSelections() {
if (this.currentDeviceIndex !== null && this.currentSegmentIndex !== null) {
return {
deviceIndex: this.currentDeviceIndex,
segmentIndex: this.currentSegmentIndex,
selections: this.selectedWords[this.currentDeviceIndex]?.[this.currentSegmentIndex] || []
};
}
return null;
},
emitSelectionChange() {
const currentSelections = this.getCurrentSelections();
if (currentSelections) {
this.$emit('selection-change', {
deviceIndex: currentSelections.deviceIndex,
segmentIndex: currentSelections.segmentIndex,
selections: currentSelections.selections,
deviceName: this.originalData[currentSelections.deviceIndex].devName,
segmentOriginal: this.originalData[currentSelections.deviceIndex].segments[currentSelections.segmentIndex]
});
}
}
},
watch: {
selectedWords: {
handler(newVal) {
console.log('选择状态更新:', newVal);
},
deep: true
}
}
}
</script>
<style scoped>
.container {
padding: 20px;
}
.device-item {
margin-bottom: 20px;
padding: 15px;
border: 1px solid #eee;
border-radius: 4px;
}
.segments-container {
margin-top: 10px;
}
.segment-group {
margin-bottom: 15px;
padding: 12px;
border: 2px solid transparent;
border-radius: 4px;
background-color: #fafafa;
transition: all 0.3s ease;
}
/* 当前激活的分组样式 */
.segment-group.active-segment {
border-color: #409EFF;
background-color: #fff;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
}
.segment-title {
font-weight: bold;
margin-bottom: 8px;
color: #666;
padding-bottom: 5px;
border-bottom: 1px solid #eee;
}
.segment-words {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.word {
padding: 5px 10px;
border: 1px solid #ddd;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
background-color: white;
}
.word:hover {
background-color: #f5f5f5;
}
.word.selected {
background-color: #409EFF;
color: white;
border-color: #409EFF;
}
/* 激活分组内的词语hover效果增强 */
.active-segment .word:hover {
background-color: #f0f7ff;
border-color: #409EFF;
}
</style>