From cb9cd49627b65a4c0e137e08063271a8cefe1826 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 23 七月 2026 17:48:49 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_pro2.0' into dev_pro2.0
---
src/views/im/manager/statistics/components/overview-cards.vue | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 105 insertions(+), 0 deletions(-)
diff --git a/src/views/im/manager/statistics/components/overview-cards.vue b/src/views/im/manager/statistics/components/overview-cards.vue
new file mode 100644
index 0000000..f757953
--- /dev/null
+++ b/src/views/im/manager/statistics/components/overview-cards.vue
@@ -0,0 +1,105 @@
+<script lang="ts" setup>
+import type { ImManagerStatisticsApi } from '#/api/im/manager/statistics';
+
+import { computed } from 'vue';
+
+import { IconifyIcon } from '#/packages/icons/src';
+
+import { Card } from 'ant-design-vue';
+
+defineOptions({ name: 'ImManagerStatisticsOverviewCards' });
+
+const props = defineProps<{
+ overview: ImManagerStatisticsApi.Overview;
+}>();
+
+/** 璁$畻鐜瘮 */
+function calcRatio(today: number, yesterday: number) {
+ if (!yesterday) {
+ return { label: '鏃犳槰鏃ユ暟鎹�', className: 'text-gray-400' };
+ }
+ const diff = ((today - yesterday) / yesterday) * 100;
+ const sign = diff >= 0 ? '+' : '';
+ return {
+ label: `${sign}${diff.toFixed(1)}%`,
+ className: diff >= 0 ? 'text-green-500' : 'text-red-500',
+ };
+}
+
+const cards = computed(() => {
+ const overview = props.overview;
+ const totalMsgToday =
+ (overview.privateMessageToday || 0) + (overview.groupMessageToday || 0);
+ const totalMsgYesterday =
+ (overview.privateMessageYesterday || 0) +
+ (overview.groupMessageYesterday || 0);
+ const msgRatio = calcRatio(totalMsgToday, totalMsgYesterday);
+ return [
+ {
+ title: '鎬荤敤鎴�',
+ value: overview.totalUser || 0,
+ icon: 'lucide:user',
+ color: '#2f7df6',
+ metaLabel: '浠婃棩鏂板',
+ metaValue: `+${overview.newUserToday || 0}`,
+ metaClass: 'text-green-500',
+ },
+ {
+ title: '鎬荤兢缁�',
+ value: overview.totalGroup || 0,
+ icon: 'lucide:messages-square',
+ color: '#18a058',
+ metaLabel: '浠婃棩鏂板',
+ metaValue: `+${overview.newGroupToday || 0}`,
+ metaClass: 'text-green-500',
+ },
+ {
+ title: '鏃ユ椿鐢ㄦ埛',
+ value: overview.activeUserDaily || 0,
+ icon: 'lucide:timer',
+ color: '#f59e0b',
+ metaLabel: '鍛�/鏈堟椿',
+ metaValue: `${overview.activeUserWeekly || 0} / ${overview.activeUserMonthly || 0}`,
+ metaClass: 'text-gray-500',
+ },
+ {
+ title: '浠婃棩娑堟伅',
+ value: totalMsgToday,
+ suffix: `锛圥 ${overview.privateMessageToday}/G ${overview.groupMessageToday}锛塦,
+ icon: 'lucide:message-circle',
+ color: '#64748b',
+ metaLabel: '鐜瘮鏄ㄦ棩',
+ metaValue: msgRatio.label,
+ metaClass: msgRatio.className,
+ },
+ ];
+});
+</script>
+
+<template>
+ <div class="grid grid-cols-4 gap-4 max-xl:grid-cols-2 max-md:grid-cols-1">
+ <Card v-for="card in cards" :key="card.title" :body-style="{ padding: '16px' }">
+ <div class="flex items-center">
+ <div
+ class="mr-3 flex size-12 shrink-0 items-center justify-center rounded"
+ :style="{ backgroundColor: card.color }"
+ >
+ <IconifyIcon :icon="card.icon" class="size-6 text-white" />
+ </div>
+ <div class="min-w-0 flex-1">
+ <div class="mb-1 text-sm text-muted-foreground">{{ card.title }}</div>
+ <div class="truncate text-2xl font-semibold leading-none">
+ {{ card.value }}
+ <span v-if="card.suffix" class="ml-1 text-xs font-normal text-gray-400">
+ {{ card.suffix }}
+ </span>
+ </div>
+ <div class="mt-2 text-xs text-gray-400">
+ {{ card.metaLabel }}锛�
+ <span :class="card.metaClass">{{ card.metaValue }}</span>
+ </div>
+ </div>
+ </div>
+ </Card>
+ </div>
+</template>
--
Gitblit v1.9.3