162 lines
4.4 KiB
Vue
162 lines
4.4 KiB
Vue
<script setup>
|
|
definePage({ layout: 'default', auth: true })
|
|
import { onReachBottom } from '@dcloudio/uni-app'
|
|
// 类型映射配置
|
|
const typeConfig = {
|
|
descendant_promotion: {
|
|
chinese: '下级推广奖励',
|
|
color: { bg: 'bg-blue-100', text: 'text-blue-800', dot: 'bg-blue-500' },
|
|
},
|
|
descendant_upgrade_vip: {
|
|
chinese: '下级升级VIP奖励',
|
|
color: { bg: 'bg-green-100', text: 'text-green-800', dot: 'bg-green-500' },
|
|
},
|
|
descendant_upgrade_svip: {
|
|
chinese: '下级升级SVIP奖励',
|
|
color: { bg: 'bg-purple-100', text: 'text-purple-800', dot: 'bg-purple-500' },
|
|
},
|
|
descendant_withdraw: {
|
|
chinese: '下级提现奖励',
|
|
color: { bg: 'bg-indigo-100', text: 'text-indigo-800', dot: 'bg-indigo-500' },
|
|
},
|
|
default: {
|
|
chinese: '其他奖励',
|
|
color: { bg: 'bg-gray-100', text: 'text-gray-800', dot: 'bg-gray-500' },
|
|
},
|
|
}
|
|
|
|
const page = ref(1)
|
|
const pageSize = ref(10)
|
|
const data = ref({
|
|
total: 0,
|
|
list: [],
|
|
})
|
|
const loading = ref(false)
|
|
const hasMore = ref(true)
|
|
const loadMoreState = ref('loading')
|
|
|
|
// 类型转中文
|
|
function typeToChinese(type) {
|
|
return typeConfig[type]?.chinese || typeConfig.default.chinese
|
|
}
|
|
|
|
// 获取颜色样式
|
|
function getReportTypeStyle(type) {
|
|
const config = typeConfig[type] || typeConfig.default
|
|
return `${config.color.bg} ${config.color.text}`
|
|
}
|
|
|
|
// 获取小圆点颜色
|
|
function getDotColor(type) {
|
|
return typeConfig[type]?.color.dot || typeConfig.default.color.dot
|
|
}
|
|
|
|
// 获取数据
|
|
function mergeUniqueById(oldList, newList) {
|
|
const map = new Map()
|
|
const resolveKey = (item, index) => String(item?.id ?? item?.order_id ?? `${item?.create_time || ''}_${item?.type || ''}_${index}`)
|
|
oldList.forEach((item, index) => {
|
|
map.set(resolveKey(item, index), item)
|
|
})
|
|
newList.forEach((item, index) => {
|
|
map.set(resolveKey(item, oldList.length + index), item)
|
|
})
|
|
return Array.from(map.values())
|
|
}
|
|
|
|
async function getData(reset = false) {
|
|
try {
|
|
if (loading.value)
|
|
return
|
|
if (!reset && !hasMore.value)
|
|
return
|
|
loading.value = true
|
|
if (reset) {
|
|
page.value = 1
|
|
hasMore.value = true
|
|
loadMoreState.value = 'loading'
|
|
data.value = { total: 0, list: [] }
|
|
}
|
|
const { data: res, error } = await useApiFetch(
|
|
`/agent/rewards?page=${page.value}&page_size=${pageSize.value}`,
|
|
{ silent: true },
|
|
).get().json()
|
|
|
|
if (res.value?.code === 200 && !error.value) {
|
|
const incoming = res.value.data.list || []
|
|
data.value.total = res.value.data.total || 0
|
|
data.value.list = reset
|
|
? incoming
|
|
: mergeUniqueById(data.value.list, incoming)
|
|
const isLastPage = incoming.length < pageSize.value || data.value.list.length >= data.value.total
|
|
hasMore.value = !isLastPage
|
|
loadMoreState.value = isLastPage ? 'finished' : 'loading'
|
|
if (!isLastPage)
|
|
page.value += 1
|
|
}
|
|
else {
|
|
loadMoreState.value = 'error'
|
|
}
|
|
}
|
|
finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
// 初始化加载
|
|
onMounted(() => {
|
|
getData(true)
|
|
})
|
|
|
|
onReachBottom(() => {
|
|
getData()
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<view class="min-h-screen bg-gray-50">
|
|
<view class="reward-scroll">
|
|
<view v-for="(item, index) in data.list" :key="index" class="mx-4 my-2 rounded-lg bg-white p-4 shadow-sm">
|
|
<view class="mb-2 flex items-center justify-between">
|
|
<text class="text-sm text-gray-500">
|
|
{{ item.create_time || '-' }}
|
|
</text>
|
|
<text class="text-green-500 font-bold">
|
|
+{{ item.amount.toFixed(2) }}
|
|
</text>
|
|
</view>
|
|
<view class="flex items-center">
|
|
<text
|
|
class="inline-flex items-center rounded-full px-2 py-1 text-xs font-medium"
|
|
:class="getReportTypeStyle(item.type)"
|
|
>
|
|
<text class="mr-1 h-2 w-2 rounded-full" :class="getDotColor(item.type)" />
|
|
{{ typeToChinese(item.type) }}
|
|
</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="loading" class="py-4 text-center text-sm text-gray-400">
|
|
加载中...
|
|
</view>
|
|
<EmptyState v-else-if="!data.list.length" text="暂无奖励明细" />
|
|
</view>
|
|
<wd-loadmore v-if="data.list.length > 0" :state="loadMoreState" @reload="getData" />
|
|
</view>
|
|
</template>
|
|
|
|
<style scoped>
|
|
/* 保持原有样式不变 */
|
|
.list-enter-active {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.list-enter-from {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
}
|
|
|
|
.reward-scroll {
|
|
min-height: calc(100vh - 110px);
|
|
}
|
|
</style>
|