diff --git a/src/components/analysis/ranking/OverallRankingTab.vue b/src/components/analysis/ranking/OverallRankingTab.vue index 015c4495..254e9770 100644 --- a/src/components/analysis/ranking/OverallRankingTab.vue +++ b/src/components/analysis/ranking/OverallRankingTab.vue @@ -15,17 +15,23 @@ const props = defineProps<{ const memberActivity = ref([]) const availableYears = ref([]) +const isBaseLoading = ref(false) async function loadBaseData() { if (!props.sessionId) return - const dataService = useDataService() - const [members, years] = await Promise.all([ - dataService.getMemberActivity(props.sessionId, props.timeFilter), - dataService.getAvailableYears(props.sessionId), - ]) - memberActivity.value = members - availableYears.value = years + isBaseLoading.value = true + try { + const dataService = useDataService() + const [members, years] = await Promise.all([ + dataService.getMemberActivity(props.sessionId, props.timeFilter), + dataService.getAvailableYears(props.sessionId), + ]) + memberActivity.value = members + availableYears.value = years + } finally { + isBaseLoading.value = false + } } watch( @@ -48,7 +54,7 @@ const seasonTitle = computed(() => { return minYear === maxYear ? `${minYear} 赛季` : `${minYear}-${maxYear} 赛季` } - return '全部赛季' + return isBaseLoading.value ? '赛季' : '全部赛季' }) const rankingTimeFilter = computed(() => ({ @@ -103,6 +109,7 @@ const mainContentClass = computed(() => RANKING_LAYOUTS[widthMode.value].content diff --git a/src/components/analysis/ranking/sections/ActivityRank.vue b/src/components/analysis/ranking/sections/ActivityRank.vue index b2dfc300..3159cc50 100644 --- a/src/components/analysis/ranking/sections/ActivityRank.vue +++ b/src/components/analysis/ranking/sections/ActivityRank.vue @@ -4,14 +4,16 @@ import type { DragonKingAnalysis, CheckInAnalysis } from '@openchatlab/core' import type { MemberActivity } from '@/types/analysis' import { EChartRank } from '@/components/charts' import type { RankItem } from '@/components/charts' -import { SectionCard, LoadingState, Tabs, TopNSelect } from '@/components/UI' +import { SectionCard, Tabs, TopNSelect } from '@/components/UI' import { useDataService } from '@/services/data/service' import type { TimeFilter } from '@openchatlab/shared-types' +import RankingLoadingBody from './RankingLoadingBody.vue' const props = withDefaults( defineProps<{ sessionId: string memberActivity: MemberActivity[] + baseLoading?: boolean timeFilter?: TimeFilter /** 是否显示 TopN 选择器 */ showTopNSelect?: boolean @@ -89,6 +91,11 @@ const loyaltyRankData = computed(() => { })) }) +const showLoading = computed(() => { + if (activeTab.value === 'activity') return Boolean(props.baseLoading) && props.memberActivity.length === 0 + return isLoading.value +}) + const currentRankData = computed(() => { switch (activeTab.value) { case 'activity': @@ -132,12 +139,12 @@ const cardDescription = computed(() => { case 'activity': return '按消息发送数量排名' case 'dragon': { - const totalDays = dragonKingAnalysis.value?.totalDays ?? 0 - return `每天发言最多的人+1(共 ${totalDays} 天)` + const totalDays = dragonKingAnalysis.value?.totalDays + return totalDays == null ? '每天发言最多的人+1' : `每天发言最多的人+1(共 ${totalDays} 天)` } case 'loyalty': { - const totalDays = checkInAnalysis.value?.totalDays ?? 0 - return `累计发言天数排名(共 ${totalDays} 天)` + const totalDays = checkInAnalysis.value?.totalDays + return totalDays == null ? '累计发言天数排名' : `累计发言天数排名(共 ${totalDays} 天)` } default: return '' @@ -168,7 +175,7 @@ watch( - + diff --git a/src/components/analysis/ranking/sections/DivingRank.vue b/src/components/analysis/ranking/sections/DivingRank.vue index c08a0b38..c5030241 100644 --- a/src/components/analysis/ranking/sections/DivingRank.vue +++ b/src/components/analysis/ranking/sections/DivingRank.vue @@ -2,9 +2,10 @@ import { ref, watch } from 'vue' import type { DivingAnalysis } from '@openchatlab/core' import { EChartDivingRank } from '../charts' -import { LoadingState } from '@/components/UI' +import { EmptyState, SectionCard } from '@/components/UI' import { useDataService } from '@/services/data/service' import type { TimeFilter } from '@openchatlab/shared-types' +import RankingLoadingBody from './RankingLoadingBody.vue' const props = defineProps<{ sessionId: string @@ -36,10 +37,15 @@ watch( diff --git a/src/components/analysis/ranking/sections/MemeBattleRank.vue b/src/components/analysis/ranking/sections/MemeBattleRank.vue index 267f99a9..2966fda7 100644 --- a/src/components/analysis/ranking/sections/MemeBattleRank.vue +++ b/src/components/analysis/ranking/sections/MemeBattleRank.vue @@ -3,10 +3,11 @@ import { computed, ref, watch } from 'vue' import type { MemeBattleAnalysis } from '@openchatlab/core' import { EChartRank } from '@/components/charts' import type { RankItem } from '@/components/charts' -import { LoadingState, Tabs, SectionCard, TopNSelect } from '@/components/UI' +import { Tabs, SectionCard, TopNSelect } from '@/components/UI' import { EChartBattleRank } from '../charts' import { useDataService } from '@/services/data/service' import type { TimeFilter } from '@openchatlab/shared-types' +import RankingLoadingBody from './RankingLoadingBody.vue' const props = withDefaults( defineProps<{ @@ -111,9 +112,7 @@ watch(