From 27cd042df9aca0383a49f3514bc21958dd890912 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 29 六月 2026 15:42:23 +0800
Subject: [PATCH] 银川 1.联调产品维护页面 2.添加IM即时通讯模块

---
 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