bindbox-mini/composables/useRewards.js

108 lines
3.4 KiB
JavaScript

/**
* 奖励数据管理 Composable
*/
import { ref, computed, watch } from 'vue'
import { getActivityIssueRewards } from '@/api/appUser'
import { normalizeRewards, groupRewardsByLevel } from '@/utils/activity'
import { cleanUrl } from '@/utils/format'
import { getRewardCacheItem, setRewardCache, isFresh } from '@/utils/cache'
/**
* 奖励数据管理
* @param {Ref<string>} activityIdRef - 活动ID的响应式引用
* @param {Ref<string>} currentIssueIdRef - 当前期ID的响应式引用
*/
export function useRewards(activityIdRef, currentIssueIdRef) {
const rewardsMap = ref({})
const loading = ref(false)
const currentIssueRewards = computed(() => {
const issueId = currentIssueIdRef?.value || currentIssueIdRef
const m = rewardsMap.value || {}
return (issueId && Array.isArray(m[issueId])) ? m[issueId] : []
})
const rewardGroups = computed(() => {
return groupRewardsByLevel(currentIssueRewards.value)
})
/**
* 获取多期的奖励数据(带缓存)
* @param {Array} issueList - 期列表
*/
async function fetchRewardsForIssues(issueList) {
const activityId = activityIdRef?.value || activityIdRef
if (!activityId) return
const list = issueList || []
const toFetch = []
// 先从缓存加载
list.forEach(issue => {
const cached = getRewardCacheItem(activityId, issue.id)
if (cached) {
rewardsMap.value = { ...rewardsMap.value, [issue.id]: cached }
} else {
toFetch.push(issue)
}
})
if (!toFetch.length) return
loading.value = true
try {
const promises = toFetch.map(it => getActivityIssueRewards(activityId, it.id))
const results = await Promise.allSettled(promises)
results.forEach((res, i) => {
const issueId = toFetch[i]?.id
if (!issueId) return
const value = res.status === 'fulfilled' ? normalizeRewards(res.value, cleanUrl) : []
rewardsMap.value = { ...rewardsMap.value, [issueId]: value }
setRewardCache(activityId, issueId, value)
})
} catch (e) {
console.error('fetchRewardsForIssues error', e)
} finally {
loading.value = false
}
}
/**
* 获取单期的奖励数据
* @param {string} issueId - 期ID
*/
async function fetchRewardsForIssue(issueId) {
const activityId = activityIdRef?.value || activityIdRef
if (!activityId || !issueId) return
// 先检查缓存
const cached = getRewardCacheItem(activityId, issueId)
if (cached) {
rewardsMap.value = { ...rewardsMap.value, [issueId]: cached }
return
}
loading.value = true
try {
const res = await getActivityIssueRewards(activityId, issueId)
const value = normalizeRewards(res, cleanUrl)
rewardsMap.value = { ...rewardsMap.value, [issueId]: value }
setRewardCache(activityId, issueId, value)
} catch (e) {
console.error('fetchRewardsForIssue error', e)
} finally {
loading.value = false
}
}
return {
rewardsMap,
loading,
currentIssueRewards,
rewardGroups,
fetchRewardsForIssues,
fetchRewardsForIssue
}
}