|
|
@@ -4,28 +4,35 @@
|
|
|
<!-- 数据概览 -->
|
|
|
<div class="mb-16px">
|
|
|
<div class="flex items-center mb-12px">
|
|
|
- <div class="w-4px h-18px rounded-sm mr-8px" style="background-color: #1890ff"></div>
|
|
|
<span class="text-16px font-bold">数据概览</span>
|
|
|
</div>
|
|
|
<div class="grid xl:grid-cols-5 lg:grid-cols-4 md:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-12px">
|
|
|
<!-- 注册用户 -->
|
|
|
- <div class="overview-card">
|
|
|
- <div class="card-header" style="color: #fa8c16">注册用户</div>
|
|
|
- <div class="card-body flex items-center justify-center" style="min-height: 70px">
|
|
|
- <span class="text-32px font-bold">{{ overviewData.registeredUsers ?? 0 }}</span>
|
|
|
+ <div class="register-card">
|
|
|
+ <div class="register-card-left">
|
|
|
+ <div class="text-32px font-bold text-white">{{ overviewData.registeredUsers ?? 0 }}</div>
|
|
|
+ <div class="text-14px text-white mt-8px" style="opacity: 0.85">注册用户</div>
|
|
|
+ </div>
|
|
|
+ <div class="register-card-right">
|
|
|
+ <img :src="zcImg" alt="注册用户" class="register-icon" />
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- 累计/今年/本月/今日 -->
|
|
|
- <div v-for="item in statsCards" :key="item.key" class="overview-card" :class="{ 'active-card': item.key === 'today' }">
|
|
|
- <div class="card-header" :style="{ color: item.color }">{{ item.title }}</div>
|
|
|
- <div class="card-body grid grid-cols-2 text-center" style="min-height: 70px">
|
|
|
- <div class="flex flex-col justify-center">
|
|
|
- <div class="text-22px font-bold">{{ item.data?.reservationCount ?? 0 }}</div>
|
|
|
- <div class="text-12px text-gray-400 mt-4px">预约人数</div>
|
|
|
+ <div v-for="item in statsCards" :key="item.key" class="overview-card">
|
|
|
+ <div class="card-title">{{ item.title }}</div>
|
|
|
+ <div class="card-content">
|
|
|
+ <div class="card-nums">
|
|
|
+ <div class="num-item">
|
|
|
+ <div class="text-24px font-bold">{{ item.data?.reservationCount ?? 0 }}</div>
|
|
|
+ <div class="text-12px text-gray-400 mt-4px">预约人数</div>
|
|
|
+ </div>
|
|
|
+ <div class="num-item">
|
|
|
+ <div class="text-24px font-bold">{{ item.data?.entryCount ?? 0 }}</div>
|
|
|
+ <div class="text-12px text-gray-400 mt-4px">入场人数</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div class="flex flex-col justify-center">
|
|
|
- <div class="text-22px font-bold">{{ item.data?.entryCount ?? 0 }}</div>
|
|
|
- <div class="text-12px text-gray-400 mt-4px">入场人数</div>
|
|
|
+ <div class="card-icon">
|
|
|
+ <img :src="item.icon" :alt="item.title" class="stats-icon" />
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -33,7 +40,7 @@
|
|
|
</div>
|
|
|
|
|
|
<!-- 图表区域 -->
|
|
|
- <div class="grid lg:grid-cols-2 grid-cols-1 gap-16px mb-16px">
|
|
|
+ <div class="grid lg:grid-cols-2 grid-cols-1 gap-16px mb-16px">
|
|
|
<!-- 学校预约概览 - 柱状图 -->
|
|
|
<a-card :bordered="false" title="学校预约概览">
|
|
|
<BarChart :chartData="schoolOverviewData" height="350px" />
|
|
|
@@ -105,14 +112,19 @@
|
|
|
import BarChart from './components/BarChart.vue';
|
|
|
import MonthlyLineChart from './components/MonthlyLineChart.vue';
|
|
|
import { getOverview, getSchoolOverview, getSchoolMonthly, getSchoolReservationPage, getSchools } from './api';
|
|
|
+ import zcImg from '/@/assets/images/indx/zc.png';
|
|
|
+ import leijiImg from '/@/assets/images/indx/leiji.png';
|
|
|
+ import jnImg from '/@/assets/images/indx/jn.png';
|
|
|
+ import yueImg from '/@/assets/images/indx/yue.png';
|
|
|
+ import dayImg from '/@/assets/images/indx/day.png';
|
|
|
|
|
|
// ========== 数据概览 ==========
|
|
|
const overviewData = ref<any>({});
|
|
|
const statsCards = computed(() => [
|
|
|
- { key: 'cumulative', title: '累计', color: '#597EF7', data: overviewData.value.cumulative },
|
|
|
- { key: 'thisYear', title: '今年', color: '#52C41A', data: overviewData.value.thisYear },
|
|
|
- { key: 'thisMonth', title: '本月', color: '#FA8C16', data: overviewData.value.thisMonth },
|
|
|
- { key: 'today', title: '今日', color: '#1890FF', data: overviewData.value.today },
|
|
|
+ { key: 'cumulative', title: '累计', icon: leijiImg, data: overviewData.value.cumulative },
|
|
|
+ { key: 'thisYear', title: '今年', icon: jnImg, data: overviewData.value.thisYear },
|
|
|
+ { key: 'thisMonth', title: '本月', icon: yueImg, data: overviewData.value.thisMonth },
|
|
|
+ { key: 'today', title: '今日', icon: dayImg, data: overviewData.value.today },
|
|
|
]);
|
|
|
|
|
|
async function fetchOverview() {
|
|
|
@@ -238,27 +250,81 @@
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
+ /* 注册用户卡片 - 蓝色渐变 */
|
|
|
+ .register-card {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 20px 24px;
|
|
|
+ border-radius: 8px;
|
|
|
+ background: linear-gradient(135deg, #6da0f7 0%, #4a7cf7 100%);
|
|
|
+ min-height: 120px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .register-card-left {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .register-card-right {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .register-icon {
|
|
|
+ width: 72px;
|
|
|
+ height: 72px;
|
|
|
+ object-fit: contain;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 统计卡片 */
|
|
|
.overview-card {
|
|
|
border: 1px solid #e8e8e8;
|
|
|
- border-radius: 4px;
|
|
|
+ border-radius: 8px;
|
|
|
overflow: hidden;
|
|
|
background: #fff;
|
|
|
+ padding: 16px 20px;
|
|
|
+ min-height: 120px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-title {
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ margin-bottom: 12px;
|
|
|
}
|
|
|
|
|
|
- .overview-card.active-card {
|
|
|
- border: 2px solid #1890ff;
|
|
|
+ .card-content {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ flex: 1;
|
|
|
}
|
|
|
|
|
|
- .card-header {
|
|
|
- text-align: center;
|
|
|
- padding: 6px 0;
|
|
|
- font-weight: bold;
|
|
|
- font-size: 15px;
|
|
|
- border-bottom: 1px solid #f0f0f0;
|
|
|
+ .card-nums {
|
|
|
+ display: flex;
|
|
|
+ gap: 24px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .num-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .card-icon {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
}
|
|
|
|
|
|
- .card-body {
|
|
|
- padding: 12px;
|
|
|
+ .stats-icon {
|
|
|
+ width: 52px;
|
|
|
+ height: 52px;
|
|
|
+ object-fit: contain;
|
|
|
}
|
|
|
|
|
|
.table-section :deep(.ant-table-thead > tr > th) {
|