Files
reader-star/apps/admin/src/views/admin-home/modules/card-data.vue

113 lines
2.6 KiB
Vue
Raw Normal View History

2026-01-16 13:06:44 +08:00
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
import { computed } from 'vue'
import { $t } from '@/locales'
import { useThemeStore } from '@/store/modules/theme'
defineOptions({
name: 'CardData',
})
interface CardData {
key: string
title: string
value: number
unit: string
color: {
start: string
end: string
}
icon: string
}
const cardData = computed<CardData[]>(() => [
{
key: 'visitCount',
title: $t('page.home.visitCount'),
value: 9725,
unit: '',
color: {
start: '#ec4786',
end: '#b955a4',
},
icon: 'ant-design:bar-chart-outlined',
},
{
key: 'turnover',
title: $t('page.home.turnover'),
value: 1026,
unit: '$',
color: {
start: '#865ec0',
end: '#5144b4',
},
icon: 'ant-design:money-collect-outlined',
},
{
key: 'downloadCount',
title: $t('page.home.downloadCount'),
value: 970925,
unit: '',
color: {
start: '#56cdf3',
end: '#719de3',
},
icon: 'carbon:document-download',
},
{
key: 'dealCount',
title: $t('page.home.dealCount'),
value: 9527,
unit: '',
color: {
start: '#fcbc25',
end: '#f68057',
},
icon: 'ant-design:trademark-circle-outlined',
},
])
interface GradientBgProps {
gradientColor: string
}
const [DefineGradientBg, GradientBg] = createReusableTemplate<GradientBgProps>()
const themeStore = useThemeStore()
function getGradientColor(color: CardData['color']) {
return `linear-gradient(to bottom right, ${color.start}, ${color.end})`
}
</script>
<template>
<NCard :bordered="false" size="small" class="card-wrapper">
<DefineGradientBg v-slot="{ $slots, gradientColor }">
<div
class="px-16px pb-4px pt-8px text-white"
:style="{ backgroundImage: gradientColor, borderRadius: `${themeStore.themeRadius}px` }"
>
<component :is="$slots.default" />
</div>
</DefineGradientBg>
<NGrid cols="s:1 m:2 l:4" responsive="screen" :x-gap="16" :y-gap="16">
<NGi v-for="item in cardData" :key="item.key">
<GradientBg :gradient-color="getGradientColor(item.color)" class="flex-1">
<h3 class="text-16px">
{{ item.title }}
</h3>
<div class="flex justify-between pt-12px">
<SvgIcon :icon="item.icon" class="text-32px" />
<CountTo
:prefix="item.unit" :start-value="1" :end-value="item.value"
2026-01-16 13:06:44 +08:00
class="text-30px text-white dark:text-dark"
/>
</div>
</GradientBg>
</NGi>
</NGrid>
</NCard>
</template>
<style scoped></style>