topfans/frontend/pages/dashboard/dashboard.vue
zheng020 0bf2d152be feat(dashboard): ExhibitionCenter 3联+5行表格
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-03 01:20:50 +08:00

118 lines
2.7 KiB
Vue

<template>
<view class="dashboard-container" :style="{ background: pageBg }">
<DashboardHeader
:active-tab="activeTab"
@update:active-tab="handleTabChange"
/>
<!-- Tab 1: 水晶相关 -->
<view v-if="activeTab === 'crystal'" class="dashboard-content">
<CrystalOverview
:data="data.today"
:loading="loading.today"
:error="error.today"
@retry="refresh('today')"
/>
<IncomeCurve
:points="data.curve?.points || []"
:loading="loading.curve"
:error="error.curve"
@retry="refresh('curve')"
/>
<ExhibitionCenter
:data="data.exhibition"
:loading="loading.exhibition"
:error="error.exhibition"
@retry="refresh('exhibition')"
/>
</view>
<!-- Tab 2: 赛季总览(占位) -->
<view v-else class="dashboard-content">
<view class="season-placeholder">
<text class="placeholder-icon">🏆</text>
<text class="placeholder-title">赛季总览 · 即将上线</text>
<text class="placeholder-sub">历史赛季数据正在筹备中</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref, onUnmounted } from 'vue'
import DashboardHeader from './components/DashboardHeader.vue'
import CrystalOverview from './components/CrystalOverview.vue'
import IncomeCurve from './components/IncomeCurve.vue'
import ExhibitionCenter from './components/ExhibitionCenter.vue'
import { useDashboardData } from '@/composables/useDashboardData'
const pageBg = 'linear-gradient(153deg, #FF9597 0%, #80DFFF 33%, #B8B8B8 74%, #D9D9D9 100%)'
const activeTab = ref('crystal')
const starId = ref(uni.getStorageSync('star_id') || null)
const { loading, error, data, refresh, isReady, dispose } = useDashboardData({
starId: starId.value,
})
function handleTabChange(tab) {
activeTab.value = tab
}
onUnmounted(() => {
dispose()
})
</script>
<style lang="scss" scoped>
.dashboard-container {
min-height: 100vh;
padding: 0;
}
.dashboard-content {
padding: 24rpx 32rpx 80rpx;
}
.placeholder-section {
background: rgba(255, 255, 255, 0.1);
border-radius: 22rpx;
padding: 80rpx 32rpx;
display: flex;
align-items: center;
justify-content: center;
}
.placeholder-text {
color: rgba(255, 255, 255, 0.6);
font-size: 28rpx;
}
.season-placeholder {
background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px);
border-radius: 22rpx;
padding: 120rpx 32rpx;
display: flex;
flex-direction: column;
align-items: center;
}
.placeholder-icon {
font-size: 96rpx;
margin-bottom: 24rpx;
}
.placeholder-title {
color: #ffffff;
font-size: 36rpx;
font-weight: 700;
margin-bottom: 16rpx;
}
.placeholder-sub {
color: rgba(255, 255, 255, 0.7);
font-size: 26rpx;
}
</style>