refactor: 移除获胜记录的百分比计算和显示。

This commit is contained in:
邹方成 2025-12-26 13:28:05 +08:00
parent 4249ad3954
commit b9b60b15a1
5 changed files with 120 additions and 16 deletions

View File

@ -102,8 +102,8 @@ export function cancelShipping(user_id, batch_no) {
return authRequest({ url: `/api/app/users/${user_id}/inventory/cancel-shipping`, method: 'POST', data: { batch_no } }) return authRequest({ url: `/api/app/users/${user_id}/inventory/cancel-shipping`, method: 'POST', data: { batch_no } })
} }
export function getItemCards(user_id, status) { export function getItemCards(user_id, status, page = 1, page_size = 20) {
const data = {} const data = { page, page_size }
if (status !== undefined) data.status = status if (status !== undefined) data.status = status
return authRequest({ url: `/api/app/users/${user_id}/item_cards`, method: 'GET', data }) return authRequest({ url: `/api/app/users/${user_id}/item_cards`, method: 'GET', data })
} }

View File

@ -7,7 +7,7 @@
<view class="record-title">{{ item.title }}</view> <view class="record-title">{{ item.title }}</view>
<view class="record-meta"> <view class="record-meta">
<text class="record-count">x{{ item.count }}</text> <text class="record-count">x{{ item.count }}</text>
<text v-if="item.percent" class="record-percent">{{ item.percent }}%</text> <!-- <text v-if="item.percent" class="record-percent">{{ item.percent }}%</text> -->
</view> </view>
</view> </view>
</view> </view>

View File

@ -39,10 +39,10 @@ export function useRecords() {
aggregate[key].count += 1 aggregate[key].count += 1
}) })
const total = list.length || 1 // const total = list.length || 1
winRecords.value = Object.values(aggregate).map(it => ({ winRecords.value = Object.values(aggregate).map(it => ({
...it, ...it,
percent: ((it.count / total) * 100).toFixed(1) // percent: ((it.count / total) * 100).toFixed(1)
})) }))
} catch (e) { } catch (e) {
console.error('fetchWinRecords error', e) console.error('fetchWinRecords error', e)

View File

@ -31,6 +31,7 @@
refresher-enabled refresher-enabled
:refresher-triggered="isRefreshing" :refresher-triggered="isRefreshing"
@refresherrefresh="onRefresh" @refresherrefresh="onRefresh"
@scrolltolower="loadMore"
> >
<!-- 加载状态 --> <!-- 加载状态 -->
<view v-if="loading && list.length === 0" class="loading-state"> <view v-if="loading && list.length === 0" class="loading-state">
@ -109,6 +110,13 @@
</view> </view>
</view> </view>
</view> </view>
<!-- 加载更多 -->
<view v-if="loading && list.length > 0" class="loading-more">
<view class="spinner"></view>
<text>加载更多...</text>
</view>
<view v-else-if="!hasMore && list.length > 0" class="no-more">- 到底啦 -</view>
</scroll-view> </scroll-view>
</view> </view>
</template> </template>
@ -122,6 +130,9 @@ const list = ref([])
const loading = ref(false) const loading = ref(false)
const isRefreshing = ref(false) const isRefreshing = ref(false)
const currentTab = ref(0) const currentTab = ref(0)
const page = ref(1)
const pageSize = 20
const hasMore = ref(true)
// ID // ID
function getUserId() { function getUserId() {
@ -185,18 +196,28 @@ function switchTab(tab) {
uni.vibrateShort({ type: 'light' }) uni.vibrateShort({ type: 'light' })
currentTab.value = tab currentTab.value = tab
list.value = [] list.value = []
page.value = 1
hasMore.value = true
fetchData() fetchData()
} }
// //
async function onRefresh() { async function onRefresh() {
isRefreshing.value = true isRefreshing.value = true
await fetchData() page.value = 1
hasMore.value = true
await fetchData(false)
isRefreshing.value = false isRefreshing.value = false
} }
//
async function loadMore() {
if (loading.value || !hasMore.value) return
await fetchData(true)
}
// //
async function fetchData() { async function fetchData(append = false) {
if (!checkAuth()) return if (!checkAuth()) return
if (loading.value) return if (loading.value) return
@ -205,15 +226,24 @@ async function fetchData() {
const userId = getUserId() const userId = getUserId()
// status: 1=unused, 2=used, 3=expired // status: 1=unused, 2=used, 3=expired
const status = currentTab.value === 0 ? 1 : (currentTab.value === 1 ? 2 : 3) const status = currentTab.value === 0 ? 1 : (currentTab.value === 1 ? 2 : 3)
const res = await getItemCards(userId, status) const res = await getItemCards(userId, status, page.value, pageSize)
let items = Array.isArray(res) ? res : (res.list || res.data || []) let items = Array.isArray(res) ? res : (res.list || res.data || [])
// items is now a direct list of individual cards (backend aggregation removed) if (append) {
list.value = [...list.value, ...items]
} else {
list.value = items list.value = items
}
if (items.length < pageSize) {
hasMore.value = false
} else {
page.value++
}
} catch (e) { } catch (e) {
console.error('获取道具卡失败:', e) console.error('获取道具卡失败:', e)
list.value = [] hasMore.value = false
} finally { } finally {
loading.value = false loading.value = false
} }
@ -657,4 +687,23 @@ onLoad(() => {
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
/* 加载更多 */
.loading-more {
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 0;
color: $text-tertiary;
font-size: 24rpx;
gap: 12rpx;
}
.no-more {
text-align: center;
padding: 40rpx 0;
color: $text-tertiary;
font-size: 24rpx;
opacity: 0.6;
}
</style> </style>

View File

@ -97,12 +97,19 @@
<image class="empty-img" src="/static/empty.png" mode="widthFix" /> <image class="empty-img" src="/static/empty.png" mode="widthFix" />
<text class="empty-text">暂无相关兑换项</text> <text class="empty-text">暂无相关兑换项</text>
</view> </view>
<!-- 加载更多 -->
<view v-if="loading && items.length > 0" class="loading-more">
<view class="spinner"></view>
<text>加载更多...</text>
</view>
<view v-else-if="!hasMore && items.length > 0" class="no-more">- 到底啦 -</view>
</view> </view>
</view> </view>
</template> </template>
<script setup> <script setup>
import { onShow } from '@dcloudio/uni-app' import { onShow, onReachBottom } from '@dcloudio/uni-app'
import { ref, watch } from 'vue' import { ref, watch } from 'vue'
import { getStoreItems, redeemProductByPoints, redeemCouponByPoints, redeemItemCardByPoints } from '../../api/appUser' import { getStoreItems, redeemProductByPoints, redeemCouponByPoints, redeemItemCardByPoints } from '../../api/appUser'
@ -111,6 +118,9 @@ const keyword = ref('')
const currentTab = ref('product') const currentTab = ref('product')
const items = ref([]) const items = ref([])
const allItems = ref([]) const allItems = ref([])
const page = ref(1)
const pageSize = 20
const hasMore = ref(true)
const tabs = [ const tabs = [
{ id: 'product', name: '商品' }, { id: 'product', name: '商品' },
@ -146,19 +156,36 @@ function switchTab(id) {
currentTab.value = id currentTab.value = id
loading.value = true loading.value = true
items.value = [] items.value = []
allItems.value = []
page.value = 1
hasMore.value = true
loadItems() loadItems()
} }
async function loadItems() { async function loadItems(append = false) {
if (loading.value && append) return
loading.value = true loading.value = true
try { try {
const res = await getStoreItems(currentTab.value, 1, 100) const res = await getStoreItems(currentTab.value, page.value, pageSize)
const list = res.list || res || [] const list = res.list || res || []
allItems.value = normalizeItems(list, currentTab.value) const newItems = normalizeItems(list, currentTab.value)
if (append) {
allItems.value = [...allItems.value, ...newItems]
} else {
allItems.value = newItems
}
if (newItems.length < pageSize) {
hasMore.value = false
} else {
page.value++
}
applyFilters() applyFilters()
} catch (e) { } catch (e) {
console.error(e) console.error(e)
items.value = [] hasMore.value = false
} finally { } finally {
loading.value = false loading.value = false
} }
@ -232,12 +259,21 @@ onShow(() => {
const token = uni.getStorageSync('token') const token = uni.getStorageSync('token')
const phoneBound = !!uni.getStorageSync('phone_bound') const phoneBound = !!uni.getStorageSync('phone_bound')
if (token && phoneBound) { if (token && phoneBound) {
page.value = 1
hasMore.value = true
allItems.value = []
loadItems() loadItems()
} else { } else {
// Redirect logic if needed // Redirect logic if needed
} }
}) })
onReachBottom(() => {
if (!loading.value && hasMore.value) {
loadItems(true)
}
})
watch(keyword, () => applyFilters()) watch(keyword, () => applyFilters())
</script> </script>
@ -426,4 +462,23 @@ watch(keyword, () => applyFilters())
} }
@keyframes spin { to { transform: rotate(360deg); } } @keyframes spin { to { transform: rotate(360deg); } }
/* 加载更多 */
.loading-more {
display: flex;
align-items: center;
justify-content: center;
padding: 30rpx 0;
color: $text-tertiary;
font-size: 24rpx;
gap: 12rpx;
}
.no-more {
text-align: center;
padding: 40rpx 0;
color: $text-tertiary;
font-size: 24rpx;
opacity: 0.6;
}
</style> </style>