|
@@ -1,90 +1,173 @@
|
|
|
-<script lang="ts" setup>
|
|
|
|
|
-import type { AnalysisOverviewItem } from '@vben/common-ui';
|
|
|
|
|
-import type { TabOption } from '@vben/types';
|
|
|
|
|
-
|
|
|
|
|
|
|
+<script setup>
|
|
|
import {
|
|
import {
|
|
|
- AnalysisChartCard,
|
|
|
|
|
- AnalysisChartsTabs,
|
|
|
|
|
- AnalysisOverview,
|
|
|
|
|
|
|
+ Page,
|
|
|
|
|
+ AnalysisOverview,
|
|
|
} from '@vben/common-ui';
|
|
} from '@vben/common-ui';
|
|
|
-import {
|
|
|
|
|
- SvgBellIcon,
|
|
|
|
|
- SvgCakeIcon,
|
|
|
|
|
- SvgCardIcon,
|
|
|
|
|
- SvgDownloadIcon,
|
|
|
|
|
-} from '@vben/icons';
|
|
|
|
|
|
|
+import {ref, reactive, computed} from "vue";
|
|
|
|
|
+import {getOverviewDashboard} from "#/api/dashboard/analytics.js";
|
|
|
|
|
+import {Button, Card, Tag, Avatar, Switch, TypographyTitle} from "ant-design-vue";
|
|
|
|
|
+
|
|
|
|
|
+import { preferences } from '@vben/preferences';
|
|
|
|
|
+
|
|
|
|
|
+import { createIconifyIcon } from '@vben-core/icons';
|
|
|
|
|
+import {useUserStore} from "@vben/stores";
|
|
|
|
|
+import {$t} from "@vben/locales";
|
|
|
|
|
+const IconResultAmount = createIconifyIcon('streamline-ultimate-color:cash-payment-coin-dollar');
|
|
|
|
|
+const IconBetUsers = createIconifyIcon('streamline-ultimate-color:user-cash-scale');
|
|
|
|
|
+const IconBetCount = createIconifyIcon('streamline-ultimate-color:monetization-touch-coin');
|
|
|
|
|
+const IconBetAmount = createIconifyIcon('streamline-ultimate-color:saving-money-flower');
|
|
|
|
|
+const IconGameProfit = createIconifyIcon('streamline-ultimate-color:accounting-coins');
|
|
|
|
|
+const IconLoginUsers = createIconifyIcon('streamline-ultimate-color:network-user');
|
|
|
|
|
+const IconRegisterUsers = createIconifyIcon('streamline-ultimate-color:programming-user-chat');
|
|
|
|
|
+const IconOnlineUsers = createIconifyIcon('streamline-ultimate-color:multiple-users-network');
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
|
|
|
-import AnalyticsTrends from './analytics-trends.vue';
|
|
|
|
|
-import AnalyticsVisitsData from './analytics-visits-data.vue';
|
|
|
|
|
-import AnalyticsVisitsSales from './analytics-visits-sales.vue';
|
|
|
|
|
-import AnalyticsVisitsSource from './analytics-visits-source.vue';
|
|
|
|
|
-import AnalyticsVisits from './analytics-visits.vue';
|
|
|
|
|
|
|
+const overviewItems = reactive( [
|
|
|
|
|
+ {
|
|
|
|
|
+ icon: IconResultAmount,
|
|
|
|
|
+ title: $t('dashboard.analytics.commission'),
|
|
|
|
|
+ totalTitle: $t('dashboard.analytics.yesterday'),
|
|
|
|
|
+ totalValue: 0,
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ key: 'commission',
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ icon: IconBetUsers,
|
|
|
|
|
+ title: $t('dashboard.analytics.bet_users'),
|
|
|
|
|
+ totalTitle: $t('dashboard.analytics.yesterday'),
|
|
|
|
|
+ totalValue: 0,
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ key: 'bet_users'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ icon: IconBetCount,
|
|
|
|
|
+ title: $t('dashboard.analytics.bet_count'),
|
|
|
|
|
+ totalTitle: $t('dashboard.analytics.yesterday'),
|
|
|
|
|
+ totalValue: 0,
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ key: 'bet_count'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ icon: IconBetAmount,
|
|
|
|
|
+ title: $t('dashboard.analytics.bet_amount'),
|
|
|
|
|
+ totalTitle: $t('dashboard.analytics.yesterday'),
|
|
|
|
|
+ totalValue: 0,
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ key: 'bet_amount'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ icon: IconGameProfit,
|
|
|
|
|
+ title: $t('dashboard.analytics.game_profit'),
|
|
|
|
|
+ totalTitle: $t('dashboard.analytics.yesterday'),
|
|
|
|
|
+ totalValue: 0,
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ key: 'game_profit'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ icon: IconOnlineUsers,
|
|
|
|
|
+ title: $t('dashboard.analytics.online_users'),
|
|
|
|
|
+ totalTitle: $t('dashboard.analytics.yesterday'),
|
|
|
|
|
+ totalValue: 0,
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ key: 'online_users'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ icon: IconLoginUsers,
|
|
|
|
|
+ title: $t('dashboard.analytics.login_users'),
|
|
|
|
|
+ totalTitle: $t('dashboard.analytics.yesterday'),
|
|
|
|
|
+ totalValue: 0,
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ key: 'login_users'
|
|
|
|
|
+ },
|
|
|
|
|
+ {
|
|
|
|
|
+ icon: IconRegisterUsers,
|
|
|
|
|
+ title: $t('dashboard.analytics.register_users'),
|
|
|
|
|
+ totalTitle: $t('dashboard.analytics.yesterday'),
|
|
|
|
|
+ totalValue: 0,
|
|
|
|
|
+ value: 0,
|
|
|
|
|
+ key: 'register_users'
|
|
|
|
|
+ },
|
|
|
|
|
+]);
|
|
|
|
|
+const getData = async function () {
|
|
|
|
|
+ let res = await getOverviewDashboard();
|
|
|
|
|
+ overviewItems.forEach(item => {
|
|
|
|
|
+ let key = item.key;
|
|
|
|
|
+ item['value'] = res?.today[key] || 0;
|
|
|
|
|
+ item['totalValue'] = res?.yesterday[key] || 0;
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+getData();
|
|
|
|
|
+const userStore = useUserStore();
|
|
|
|
|
+const avatar = computed(() => {
|
|
|
|
|
+ return userStore.userInfo?.avatar ?? preferences.app.defaultAvatar;
|
|
|
|
|
+});
|
|
|
|
|
|
|
|
-const overviewItems: AnalysisOverviewItem[] = [
|
|
|
|
|
- {
|
|
|
|
|
- icon: SvgCardIcon,
|
|
|
|
|
- title: '用户量',
|
|
|
|
|
- totalTitle: '总用户量',
|
|
|
|
|
- totalValue: 120_000,
|
|
|
|
|
- value: 2000,
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- icon: SvgCakeIcon,
|
|
|
|
|
- title: '访问量',
|
|
|
|
|
- totalTitle: '总访问量',
|
|
|
|
|
- totalValue: 500_000,
|
|
|
|
|
- value: 20_000,
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- icon: SvgDownloadIcon,
|
|
|
|
|
- title: '下载量',
|
|
|
|
|
- totalTitle: '总下载量',
|
|
|
|
|
- totalValue: 120_000,
|
|
|
|
|
- value: 8000,
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- icon: SvgBellIcon,
|
|
|
|
|
- title: '使用量',
|
|
|
|
|
- totalTitle: '总使用量',
|
|
|
|
|
- totalValue: 50_000,
|
|
|
|
|
- value: 5000,
|
|
|
|
|
- },
|
|
|
|
|
-];
|
|
|
|
|
|
|
+function getGreeting() {
|
|
|
|
|
+ // 获取当前时间的小时数
|
|
|
|
|
+ const now = new Date();
|
|
|
|
|
+ const hours = now.getHours();
|
|
|
|
|
+
|
|
|
|
|
+ // 判断时间段并输出问候语
|
|
|
|
|
+ if (hours < 12) {
|
|
|
|
|
+ return $t('dashboard.analytics.good_morning');
|
|
|
|
|
+ } else if (hours >= 12 && hours < 18) {
|
|
|
|
|
+ return $t('dashboard.analytics.good_afternoon');
|
|
|
|
|
+ } else {
|
|
|
|
|
+ return $t('dashboard.analytics.good_evening');
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+// 调用函数
|
|
|
|
|
+let timeDesc = getGreeting();
|
|
|
|
|
|
|
|
-const chartTabs: TabOption[] = [
|
|
|
|
|
- {
|
|
|
|
|
- label: '流量趋势',
|
|
|
|
|
- value: 'trends',
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- label: '月访问量',
|
|
|
|
|
- value: 'visits',
|
|
|
|
|
- },
|
|
|
|
|
-];
|
|
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
<template>
|
|
|
- <div class="p-5">
|
|
|
|
|
- <AnalysisOverview :items="overviewItems" />
|
|
|
|
|
- <AnalysisChartsTabs :tabs="chartTabs" class="mt-5">
|
|
|
|
|
- <template #trends>
|
|
|
|
|
- <AnalyticsTrends />
|
|
|
|
|
- </template>
|
|
|
|
|
- <template #visits>
|
|
|
|
|
- <AnalyticsVisits />
|
|
|
|
|
- </template>
|
|
|
|
|
- </AnalysisChartsTabs>
|
|
|
|
|
-
|
|
|
|
|
- <div class="mt-5 w-full md:flex">
|
|
|
|
|
- <AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问数量">
|
|
|
|
|
- <AnalyticsVisitsData />
|
|
|
|
|
- </AnalysisChartCard>
|
|
|
|
|
- <AnalysisChartCard class="mt-5 md:mr-4 md:mt-0 md:w-1/3" title="访问来源">
|
|
|
|
|
- <AnalyticsVisitsSource />
|
|
|
|
|
- </AnalysisChartCard>
|
|
|
|
|
- <AnalysisChartCard class="mt-5 md:mt-0 md:w-1/3" title="访问来源">
|
|
|
|
|
- <AnalyticsVisitsSales />
|
|
|
|
|
- </AnalysisChartCard>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
|
|
+<Page>
|
|
|
|
|
+ <div class="p-5">
|
|
|
|
|
+ <Card class="bottom-4">
|
|
|
|
|
+ <div class="flex content-center items-center">
|
|
|
|
|
+ <Avatar :size="84" :src="avatar"></Avatar>
|
|
|
|
|
+ <TypographyTitle :level="3" style="margin-left: 1rem;">{{timeDesc}} , {{userStore.userInfo?.realName}}, 开始您一天的工作吧!</TypographyTitle>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </Card>
|
|
|
|
|
+ <AnalysisOverview :items="overviewItems" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+</Page>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+::v-deep(.size-8) {width:2.6rem;height:2.6rem;}
|
|
|
|
|
+::v-deep(.icon-up > div:last-child) {justify-content: normal}
|
|
|
|
|
+::v-deep(.icon-down > div:last-child) {justify-content: normal}
|
|
|
|
|
+
|
|
|
|
|
+::v-deep(.icon-up > div:last-child span:last-child) {position: relative;padding-left:1rem;}
|
|
|
|
|
+::v-deep(.icon-down > div:last-child span:last-child) {position: relative;padding-left:1rem;}
|
|
|
|
|
+
|
|
|
|
|
+::v-deep(.icon-up > div:last-child span:last-child::after) {
|
|
|
|
|
+ width: 1rem;
|
|
|
|
|
+ height: 1rem;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ content: " ";
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ left: .1rem;
|
|
|
|
|
+ top: .15rem;
|
|
|
|
|
+ background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%230eaf03' d='M7.03 9.97h4v8.92l2.01.03V9.97h3.99l-5-5Z' stroke-width='0.5' stroke='%230eaf03'/%3E%3C/svg%3E") no-repeat;
|
|
|
|
|
+ background-size: 100% 100%;
|
|
|
|
|
+ background-position: -.5rem 0;
|
|
|
|
|
+ padding-left: 2rem;
|
|
|
|
|
+}
|
|
|
|
|
+::v-deep(.icon-down > div:last-child span:last-child::after) {
|
|
|
|
|
+ width: 1rem;
|
|
|
|
|
+ height: 1rem;
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ content: " ";
|
|
|
|
|
+ display: inline-block;
|
|
|
|
|
+ left: .1rem;
|
|
|
|
|
+ top: .15rem;
|
|
|
|
|
+ background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='%23af1203' d='M7.03 13.92h4V5l2.01-.03v8.95h3.99l-5 5Z' stroke-width='0.5' stroke='%23af1203'/%3E%3C/svg%3E") no-repeat;
|
|
|
|
|
+ background-size: 100% 100%;
|
|
|
|
|
+ background-position: -.5rem 0;
|
|
|
|
|
+ padding-left: 2rem;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|