feat(dashboard): onShow 强制刷新 + Tab 缓存 + 下拉刷新(scroll-view refresher)
This commit is contained in:
parent
b40ca02bd1
commit
20f86ceec0
@ -1,57 +1,66 @@
|
||||
<template>
|
||||
<view class="dashboard-container" :style="{ background: pageBg }">
|
||||
<DashboardHeader
|
||||
:active-tab="activeTab"
|
||||
@update:active-tab="handleTabChange"
|
||||
/>
|
||||
<scroll-view
|
||||
scroll-y
|
||||
class="dashboard-page-bg dashboard-scroll"
|
||||
:refresher-enabled="true"
|
||||
:refresher-triggered="loading.overall"
|
||||
@refresherrefresh="handlePullDownRefresh"
|
||||
>
|
||||
<view class="dashboard-container">
|
||||
<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')"
|
||||
/>
|
||||
<LikeIncomeBoard
|
||||
:stats="data.likeIncome ? { total_like_count: data.likeIncome.total_like_count, total_income: data.likeIncome.total_income } : null"
|
||||
:levels="data.likeIncome?.levels || []"
|
||||
:loading="loading.likeIncome"
|
||||
:error="error.likeIncome"
|
||||
@retry="refresh('likeIncome')"
|
||||
/>
|
||||
<CollectionMatrix
|
||||
:top-five="data.topAssets?.items || []"
|
||||
:levels="data.levels?.items || []"
|
||||
:upgrades="data.upgrades || { upcoming: [], recent: [] }"
|
||||
/>
|
||||
</view>
|
||||
<!-- 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')"
|
||||
/>
|
||||
<LikeIncomeBoard
|
||||
:stats="data.likeIncome ? { total_like_count: data.likeIncome.total_like_count, total_income: data.likeIncome.total_income } : null"
|
||||
:levels="data.likeIncome?.levels || []"
|
||||
:loading="loading.likeIncome"
|
||||
:error="error.likeIncome"
|
||||
@retry="refresh('likeIncome')"
|
||||
/>
|
||||
<CollectionMatrix
|
||||
:top-five="data.topAssets?.items || []"
|
||||
:levels="data.levels?.items || []"
|
||||
:upgrades="data.upgrades || { upcoming: [], recent: [] }"
|
||||
/>
|
||||
</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>
|
||||
<!-- 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>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onUnmounted } from 'vue'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import DashboardHeader from './components/DashboardHeader.vue'
|
||||
import CrystalOverview from './components/CrystalOverview.vue'
|
||||
import IncomeCurve from './components/IncomeCurve.vue'
|
||||
@ -60,48 +69,52 @@ import LikeIncomeBoard from './components/LikeIncomeBoard.vue'
|
||||
import CollectionMatrix from './components/CollectionMatrix.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({
|
||||
const { loading, error, data, refresh, isReady, lastFetched, dispose } = useDashboardData({
|
||||
starId: starId.value,
|
||||
})
|
||||
|
||||
// Tab 切换:30 分钟内复用缓存;切回水晶 Tab 时 cache-aware 刷新
|
||||
function handleTabChange(tab) {
|
||||
activeTab.value = tab
|
||||
if (tab === 'crystal') {
|
||||
// refresh() 默认走 30 分钟缓存(不闪骨架屏);需要强刷用 refresh(null, true)
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
|
||||
// 下拉刷新
|
||||
async function handlePullDownRefresh() {
|
||||
await refresh(null, true) // force=true 绕缓存
|
||||
uni.stopPullDownRefresh()
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
dispose()
|
||||
})
|
||||
|
||||
// 从其他页面返回时强制刷新(绕 30 分钟缓存,spec §4.1)
|
||||
onShow(() => {
|
||||
refresh(null, true)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dashboard-page-bg {
|
||||
background: linear-gradient(153deg, #FF9597 0%, #80DFFF 33%, #B8B8B8 74%, #D9D9D9 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
.dashboard-scroll {
|
||||
height: 100vh;
|
||||
}
|
||||
.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);
|
||||
@ -111,21 +124,7 @@ onUnmounted(() => {
|
||||
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;
|
||||
}
|
||||
.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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user