107 lines
3.4 KiB
Vue
107 lines
3.4 KiB
Vue
<template>
|
|
<div>
|
|
<div class="n-layout-page-header">
|
|
<n-card :bordered="false" title="数据概览">
|
|
<template #header-extra>
|
|
<n-space align="center">
|
|
<n-select
|
|
v-if="isPlatformAdmin"
|
|
v-model:value="tenantId"
|
|
:options="imQueryTenantOptions"
|
|
class="tenant-select"
|
|
placeholder="请选择商户"
|
|
/>
|
|
<n-select v-model:value="days" :options="dayOptions" class="days-select" />
|
|
<n-button type="primary" :loading="loading" @click="loadDashboard">刷新</n-button>
|
|
</n-space>
|
|
</template>
|
|
</n-card>
|
|
</div>
|
|
<n-card :bordered="false" class="proCard">
|
|
<n-grid cols="1 s:2 m:3" responsive="screen" :x-gap="12" :y-gap="12">
|
|
<n-grid-item v-for="item in metrics" :key="item.key">
|
|
<n-statistic :label="item.label" :value="overview[item.key] || 0" />
|
|
</n-grid-item>
|
|
</n-grid>
|
|
<n-divider />
|
|
<n-h3>最近 {{ days }} 天增长趋势</n-h3>
|
|
<n-data-table
|
|
:columns="trendColumns"
|
|
:data="trends"
|
|
:loading="loading"
|
|
:pagination="false"
|
|
:bordered="false"
|
|
/>
|
|
</n-card>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, onMounted, ref } from 'vue';
|
|
import { useMessage } from 'naive-ui';
|
|
import { useUserStore } from '@/store/modules/user';
|
|
import { Overview, Trends } from '@/api/imDashboard';
|
|
import { imQueryTenantOptions, loadImQueryTenantOptions } from '@/views/imAdminQueryShared';
|
|
|
|
const message = useMessage();
|
|
const userStore = useUserStore();
|
|
const isPlatformAdmin = computed(() => userStore.isCompanyDept);
|
|
const tenantId = ref(0);
|
|
const days = ref(7);
|
|
const loading = ref(false);
|
|
const overview = ref<Recordable>({});
|
|
const trends = ref<any[]>([]);
|
|
const dayOptions = [
|
|
{ label: '最近7天', value: 7 },
|
|
{ label: '最近14天', value: 14 },
|
|
{ label: '最近30天', value: 30 },
|
|
];
|
|
const metrics = [
|
|
{ key: 'totalUsers', label: '总用户数' },
|
|
{ key: 'activeUsers', label: '活跃用户' },
|
|
{ key: 'totalGroups', label: '总群组数' },
|
|
{ key: 'totalConversations', label: '总会话数' },
|
|
{ key: 'totalMessages', label: '总消息数' },
|
|
{ key: 'todayMessages', label: '今日消息' },
|
|
];
|
|
const trendColumns = [
|
|
{ title: '日期', key: 'date' },
|
|
{ title: '新增用户', key: 'userCount' },
|
|
{ title: '新增消息', key: 'messageCount' },
|
|
];
|
|
|
|
async function loadDashboard() {
|
|
if (isPlatformAdmin.value && !tenantId.value) {
|
|
message.warning('请选择商户');
|
|
return;
|
|
}
|
|
loading.value = true;
|
|
try {
|
|
const params = { tenantId: tenantId.value, days: days.value };
|
|
const [summary, trendRes] = await Promise.all([Overview(params), Trends(params)]);
|
|
overview.value = summary || {};
|
|
trends.value = trendRes?.list || [];
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
if (isPlatformAdmin.value) {
|
|
await loadImQueryTenantOptions();
|
|
tenantId.value = imQueryTenantOptions.value[0]?.value || 0;
|
|
if (!tenantId.value) message.warning('暂无可用商户');
|
|
}
|
|
if (!isPlatformAdmin.value || tenantId.value) await loadDashboard();
|
|
});
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.tenant-select {
|
|
width: 240px;
|
|
}
|
|
.days-select {
|
|
width: 120px;
|
|
}
|
|
</style>
|