|
@@ -1,25 +1,154 @@
|
|
|
<script setup lang="ts">
|
|
|
-import { ElRow, ElCol, ElCard } from 'element-plus'
|
|
|
+import { ElRow, ElCol, ElCard, ElSkeleton } from 'element-plus'
|
|
|
import { CountTo } from '@/components/CountTo'
|
|
|
+import { useDesign } from '@/hooks/web/useDesign'
|
|
|
+import { useI18n } from '@/hooks/web/useI18n'
|
|
|
+import { ref, reactive } from 'vue'
|
|
|
+import { getCountApi } from '@/api/dashboard/analysis'
|
|
|
+import type { AnalysisTotalTypes } from '@/api/dashboard/analysis/types'
|
|
|
+
|
|
|
+const { t } = useI18n()
|
|
|
+
|
|
|
+const { getPrefixCls } = useDesign()
|
|
|
+
|
|
|
+const prefixCls = getPrefixCls('panel')
|
|
|
+
|
|
|
+const loading = ref(true)
|
|
|
+
|
|
|
+let totalState = reactive<AnalysisTotalTypes>({
|
|
|
+ users: 0,
|
|
|
+ messages: 0,
|
|
|
+ moneys: 0,
|
|
|
+ shoppings: 0
|
|
|
+})
|
|
|
+
|
|
|
+const getCount = async () => {
|
|
|
+ const res = await getCountApi()
|
|
|
+ .catch(() => {})
|
|
|
+ .finally(() => {
|
|
|
+ loading.value = false
|
|
|
+ })
|
|
|
+ totalState = Object.assign(totalState, res?.data || {})
|
|
|
+}
|
|
|
+
|
|
|
+getCount()
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
- <ElRow :gutter="20" class="v-panel">
|
|
|
- <ElCol :xl="6" :lg="6" :md="6" :sm="6" :xs="1">
|
|
|
- <ElCard shadow="hover">
|
|
|
- <div class="v-panel-item flex justify-between">
|
|
|
- <div>
|
|
|
- <div
|
|
|
- class="v-panel-item__icon v-panel-item__icon--peoples p-16px inline-block rounded-6px"
|
|
|
- >
|
|
|
- <Icon icon="svg-icon:peoples" :size="40" />
|
|
|
+ <ElRow :gutter="20" justify="space-between" :class="prefixCls">
|
|
|
+ <ElCol :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
|
|
|
+ <ElCard shadow="hover" class="mb-20px">
|
|
|
+ <ElSkeleton :loading="loading" animated :rows="2">
|
|
|
+ <template #default>
|
|
|
+ <div :class="`${prefixCls}__item flex justify-between`">
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ :class="`${prefixCls}__item--icon ${prefixCls}__item--peoples p-16px inline-block rounded-6px`"
|
|
|
+ >
|
|
|
+ <Icon icon="svg-icon:peoples" :size="40" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col justify-between">
|
|
|
+ <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{
|
|
|
+ t('analysis.newUser')
|
|
|
+ }}</div>
|
|
|
+ <CountTo
|
|
|
+ class="text-20px font-700 text-right"
|
|
|
+ :start-val="0"
|
|
|
+ :end-val="102400"
|
|
|
+ :duration="2600"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- <div class="flex flex-col justify-between">
|
|
|
- <div class="v-panel-item__text">新增用户</div>
|
|
|
- <CountTo :start-val="0" :end-val="102400" :duration="2600" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
+ </template>
|
|
|
+ </ElSkeleton>
|
|
|
+ </ElCard>
|
|
|
+ </ElCol>
|
|
|
+
|
|
|
+ <ElCol :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
|
|
|
+ <ElCard shadow="hover" class="mb-20px">
|
|
|
+ <ElSkeleton :loading="loading" animated :rows="2">
|
|
|
+ <template #default>
|
|
|
+ <div :class="`${prefixCls}__item flex justify-between`">
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ :class="`${prefixCls}__item--icon ${prefixCls}__item--message p-16px inline-block rounded-6px`"
|
|
|
+ >
|
|
|
+ <Icon icon="svg-icon:message" :size="40" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col justify-between">
|
|
|
+ <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{
|
|
|
+ t('analysis.unreadInformation')
|
|
|
+ }}</div>
|
|
|
+ <CountTo
|
|
|
+ class="text-20px font-700 text-right"
|
|
|
+ :start-val="0"
|
|
|
+ :end-val="81212"
|
|
|
+ :duration="2600"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </ElSkeleton>
|
|
|
+ </ElCard>
|
|
|
+ </ElCol>
|
|
|
+
|
|
|
+ <ElCol :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
|
|
|
+ <ElCard shadow="hover" class="mb-20px">
|
|
|
+ <ElSkeleton :loading="loading" animated :rows="2">
|
|
|
+ <template #default>
|
|
|
+ <div :class="`${prefixCls}__item flex justify-between`">
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ :class="`${prefixCls}__item--icon ${prefixCls}__item--money p-16px inline-block rounded-6px`"
|
|
|
+ >
|
|
|
+ <Icon icon="svg-icon:money" :size="40" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col justify-between">
|
|
|
+ <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{
|
|
|
+ t('analysis.transactionAmount')
|
|
|
+ }}</div>
|
|
|
+ <CountTo
|
|
|
+ class="text-20px font-700 text-right"
|
|
|
+ :start-val="0"
|
|
|
+ :end-val="9280"
|
|
|
+ :duration="2600"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </ElSkeleton>
|
|
|
+ </ElCard>
|
|
|
+ </ElCol>
|
|
|
+
|
|
|
+ <ElCol :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
|
|
|
+ <ElCard shadow="hover" class="mb-20px">
|
|
|
+ <ElSkeleton :loading="loading" animated :rows="2">
|
|
|
+ <template #default>
|
|
|
+ <div :class="`${prefixCls}__item flex justify-between`">
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ :class="`${prefixCls}__item--icon ${prefixCls}__item--shopping p-16px inline-block rounded-6px`"
|
|
|
+ >
|
|
|
+ <Icon icon="svg-icon:shopping" :size="40" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="flex flex-col justify-between">
|
|
|
+ <div :class="`${prefixCls}__item--text text-16px text-gray-500 text-right`">{{
|
|
|
+ t('analysis.totalShopping')
|
|
|
+ }}</div>
|
|
|
+ <CountTo
|
|
|
+ class="text-20px font-700 text-right"
|
|
|
+ :start-val="0"
|
|
|
+ :end-val="13600"
|
|
|
+ :duration="2600"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </ElSkeleton>
|
|
|
</ElCard>
|
|
|
</ElCol>
|
|
|
</ElRow>
|
|
@@ -29,17 +158,41 @@ import { CountTo } from '@/components/CountTo'
|
|
|
@prefix-cls: ~'@{namespace}-panel';
|
|
|
|
|
|
.@{prefix-cls} {
|
|
|
- &-item {
|
|
|
+ &__item {
|
|
|
+ &--peoples {
|
|
|
+ color: #40c9c6;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--message {
|
|
|
+ color: #36a3f7;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--money {
|
|
|
+ color: #f4516c;
|
|
|
+ }
|
|
|
+
|
|
|
+ &--shopping {
|
|
|
+ color: #34bfa3;
|
|
|
+ }
|
|
|
+
|
|
|
&:hover {
|
|
|
- :deep(.v-icon) {
|
|
|
+ :deep(.@{namespace}-icon) {
|
|
|
color: #fff !important;
|
|
|
}
|
|
|
- .@{prefix-cls}-item__icon {
|
|
|
+ .@{prefix-cls}__item--icon {
|
|
|
transition: all 0.38s ease-out;
|
|
|
-
|
|
|
- &--peoples {
|
|
|
- background: #40c9c6;
|
|
|
- }
|
|
|
+ }
|
|
|
+ .@{prefix-cls}__item--peoples {
|
|
|
+ background: #40c9c6;
|
|
|
+ }
|
|
|
+ .@{prefix-cls}__item--message {
|
|
|
+ background: #36a3f7;
|
|
|
+ }
|
|
|
+ .@{prefix-cls}__item--money {
|
|
|
+ background: #f4516c;
|
|
|
+ }
|
|
|
+ .@{prefix-cls}__item--shopping {
|
|
|
+ background: #34bfa3;
|
|
|
}
|
|
|
}
|
|
|
}
|