feat(dashboard): onShow 强制刷新 + Tab 缓存 + 下拉刷新(scroll-view refresher)

This commit is contained in:
zheng020 2026-06-02 22:55:04 +08:00
parent b40ca02bd1
commit 20f86ceec0

View File

@ -1,5 +1,12 @@
<template> <template>
<view class="dashboard-container" :style="{ background: pageBg }"> <scroll-view
scroll-y
class="dashboard-page-bg dashboard-scroll"
:refresher-enabled="true"
:refresher-triggered="loading.overall"
@refresherrefresh="handlePullDownRefresh"
>
<view class="dashboard-container">
<DashboardHeader <DashboardHeader
:active-tab="activeTab" :active-tab="activeTab"
@update:active-tab="handleTabChange" @update:active-tab="handleTabChange"
@ -48,10 +55,12 @@
</view> </view>
</view> </view>
</view> </view>
</scroll-view>
</template> </template>
<script setup> <script setup>
import { ref, onUnmounted } from 'vue' import { ref, onUnmounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import DashboardHeader from './components/DashboardHeader.vue' import DashboardHeader from './components/DashboardHeader.vue'
import CrystalOverview from './components/CrystalOverview.vue' import CrystalOverview from './components/CrystalOverview.vue'
import IncomeCurve from './components/IncomeCurve.vue' import IncomeCurve from './components/IncomeCurve.vue'
@ -60,48 +69,52 @@ import LikeIncomeBoard from './components/LikeIncomeBoard.vue'
import CollectionMatrix from './components/CollectionMatrix.vue' import CollectionMatrix from './components/CollectionMatrix.vue'
import { useDashboardData } from '@/composables/useDashboardData' import { useDashboardData } from '@/composables/useDashboardData'
const pageBg = 'linear-gradient(153deg, #FF9597 0%, #80DFFF 33%, #B8B8B8 74%, #D9D9D9 100%)'
const activeTab = ref('crystal') const activeTab = ref('crystal')
const starId = ref(uni.getStorageSync('star_id') || null) 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, starId: starId.value,
}) })
// Tab 30 Tab cache-aware
function handleTabChange(tab) { function handleTabChange(tab) {
activeTab.value = 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(() => { onUnmounted(() => {
dispose() dispose()
}) })
// 30 spec §4.1
onShow(() => {
refresh(null, true)
})
</script> </script>
<style lang="scss" scoped> <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 { .dashboard-container {
min-height: 100vh; min-height: 100vh;
padding: 0;
} }
.dashboard-content { .dashboard-content {
padding: 24rpx 32rpx 80rpx; 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 { .season-placeholder {
background: rgba(255, 255, 255, 0.15); background: rgba(255, 255, 255, 0.15);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
@ -111,21 +124,7 @@ onUnmounted(() => {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.placeholder-icon { font-size: 96rpx; margin-bottom: 24rpx; }
.placeholder-icon { .placeholder-title { color: #ffffff; font-size: 36rpx; font-weight: 700; margin-bottom: 16rpx; }
font-size: 96rpx; .placeholder-sub { color: rgba(255, 255, 255, 0.7); font-size: 26rpx; }
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> </style>