Files
ChatLab/src/components/charts/ListPro.vue
T
2025-11-28 17:34:47 +08:00

79 lines
2.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed, ref } from 'vue'
const props = withDefaults(
defineProps<{
/** 完整数据列表 */
items: any[]
/** 标题 */
title: string
/** 描述(可选) */
description?: string
/** 默认显示数量,默认 10 */
topN?: number
/** 弹窗中的总数描述模板,如 "共 {count} 位成员" */
countTemplate?: string
}>(),
{
topN: 10,
countTemplate: '共 {count} 项',
}
)
// 控制弹窗
const isOpen = ref(false)
// Top N 数据
const topNData = computed(() => props.items.slice(0, props.topN))
// 是否显示"查看完整"按钮
const showViewAll = computed(() => props.items.length > props.topN)
// 格式化总数描述
const formattedCount = computed(() => props.countTemplate.replace('{count}', String(props.items.length)))
</script>
<template>
<div class="rounded-xl border border-gray-200 bg-white shadow-sm dark:border-gray-800 dark:bg-gray-900">
<div class="flex items-center justify-between border-b border-gray-200 px-5 py-4 dark:border-gray-800">
<div>
<h3 class="font-semibold text-gray-900 dark:text-white">{{ title }}</h3>
<p v-if="description" class="mt-1 text-sm text-gray-500 dark:text-gray-400">{{ description }}</p>
</div>
<div class="flex items-center gap-2">
<!-- 自定义头部右侧内容 -->
<slot name="headerRight" />
<!-- 完整列表弹窗 -->
<UModal v-model:open="isOpen" :ui="{ content: 'md:w-full max-w-4xl' }">
<UButton v-if="showViewAll" icon="i-heroicons-list-bullet" color="gray" variant="ghost">查看完整列表</UButton>
<template #header>
<div class="flex items-center justify-between">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">{{ title }}</h3>
<span class="text-sm text-gray-500">{{ formattedCount }}</span>
</div>
</template>
<template #body>
<div class="max-h-[60vh] divide-y divide-gray-100 overflow-y-auto dark:divide-gray-800">
<div v-for="(item, index) in items" :key="index" class="px-5 py-4">
<slot name="item" :item="item" :index="index" />
</div>
</div>
</template>
</UModal>
</div>
</div>
<!-- 默认显示 Top N -->
<div class="divide-y divide-gray-100 dark:divide-gray-800">
<div v-for="(item, index) in topNData" :key="index" class="px-5 py-4">
<slot name="item" :item="item" :index="index" />
</div>
</div>
<!-- 空状态 -->
<div v-if="items.length === 0" class="px-5 py-8 text-center text-sm text-gray-400">暂无数据</div>
</div>
</template>