<template>
|
<div v-if="displayItems.length" class="tag-cell" @click="dialogVisible = true">
|
<ElTag v-for="item in previewItems" :key="item.key" effect="plain" size="small">
|
{{ item.label }}
|
</ElTag>
|
<ElTag v-if="hiddenCount > 0" effect="plain" size="small"> +{{ hiddenCount }} </ElTag>
|
</div>
|
<span v-else>{{ emptyText }}</span>
|
|
<ElDialog v-model="dialogVisible" :title="title" width="720px" append-to-body destroy-on-close>
|
<div v-if="displayItems.length" class="tag-cell__dialog-list">
|
<ElTag v-for="item in displayItems" :key="item.key" effect="plain">
|
{{ item.label }}
|
</ElTag>
|
</div>
|
<ElEmpty v-else :description="emptyText" :image-size="88" />
|
</ElDialog>
|
</template>
|
|
<script setup>
|
import { computed, ref } from 'vue'
|
|
const props = defineProps({
|
items: { type: Array, default: () => [] },
|
title: { type: String, default: '' },
|
emptyText: { type: String, default: '--' },
|
previewCount: { type: Number, default: 1 }
|
})
|
|
const dialogVisible = ref(false)
|
|
const displayItems = computed(() =>
|
(Array.isArray(props.items) ? props.items : [])
|
.map((item, index) => {
|
if (!item || typeof item !== 'object') {
|
return null
|
}
|
const rawLabel = item.label ?? item.name ?? item.text ?? item.value ?? item.id
|
const label = String(rawLabel ?? '').trim()
|
if (!label) {
|
return null
|
}
|
return {
|
key: item.key ?? item.id ?? item.value ?? `${label}-${index}`,
|
label
|
}
|
})
|
.filter(Boolean)
|
)
|
|
const previewItems = computed(() => displayItems.value.slice(0, props.previewCount))
|
const hiddenCount = computed(() =>
|
Math.max(displayItems.value.length - previewItems.value.length, 0)
|
)
|
</script>
|
|
<style scoped>
|
.tag-cell {
|
display: flex;
|
flex-wrap: wrap;
|
align-items: center;
|
gap: 6px;
|
cursor: pointer;
|
}
|
|
.tag-cell__dialog-list {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 8px;
|
}
|
</style>
|