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
|
2026-01-20 11:57:56 +08:00
|
|
|
: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>
|