131 lines
3.7 KiB
Vue
131 lines
3.7 KiB
Vue
<script setup>
|
|
import { computed, ref } from "vue";
|
|
import { onLoad } from "@dcloudio/uni-app";
|
|
import Container from "@/components/Container.vue";
|
|
import CoinHeader from "./components/CoinHeader.vue";
|
|
import CoinRecordList from "./components/CoinRecordList.vue";
|
|
import CoinEmptyState from "./components/CoinEmptyState.vue";
|
|
import { getGoldLogAPI } from "@/apis";
|
|
|
|
const PAGE_SIZE = 20;
|
|
const storeId = ref("");
|
|
const exchangeRecords = ref([]);
|
|
const page = ref(0);
|
|
const total = ref(0);
|
|
const loading = ref(false);
|
|
const noMore = ref(false);
|
|
const loaded = ref(false);
|
|
const showEmpty = computed(() => loaded.value && !exchangeRecords.value.length);
|
|
|
|
const formatRecord = (item = {}) => {
|
|
const [date = "", time = ""] = String(item.createdAt || "").split(" ");
|
|
return {
|
|
id: item.id,
|
|
content: item.remark || "-",
|
|
type: item.typeDesc || "-",
|
|
date,
|
|
time,
|
|
amount: String(Number(item.amount) || 0),
|
|
};
|
|
};
|
|
|
|
// 实际接口返回 totalCount/pageCount/pageSize,同时兼容接口文档中的旧字段。
|
|
const updatePaginationState = (result, list, nextPage) => {
|
|
const currentPage = Number(result?.page) || nextPage;
|
|
const pageCount = Number(result?.pageCount);
|
|
const totalCount = Number(result?.totalCount ?? result?.total);
|
|
const responsePageSize = Number(result?.pageSize ?? result?.perPage) || PAGE_SIZE;
|
|
|
|
page.value = currentPage;
|
|
total.value = Number.isFinite(totalCount) ? totalCount : 0;
|
|
|
|
if (Number.isFinite(pageCount) && pageCount >= 0) {
|
|
noMore.value = currentPage >= pageCount;
|
|
return;
|
|
}
|
|
if (Number.isFinite(totalCount) && totalCount >= 0) {
|
|
noMore.value = exchangeRecords.value.length >= totalCount;
|
|
return;
|
|
}
|
|
noMore.value = list.length < responsePageSize;
|
|
};
|
|
|
|
const loadRecords = async ({ reset = false } = {}) => {
|
|
if (loading.value || (!reset && noMore.value)) return;
|
|
|
|
const nextPage = reset ? 1 : page.value + 1;
|
|
loading.value = true;
|
|
if (reset) noMore.value = false;
|
|
|
|
try {
|
|
const result = await getGoldLogAPI({
|
|
page: nextPage,
|
|
pageSize: PAGE_SIZE,
|
|
type: 2,
|
|
storeId: storeId.value,
|
|
});
|
|
const list = Array.isArray(result?.list) ? result.list : [];
|
|
const mappedList = list.map(formatRecord);
|
|
exchangeRecords.value = reset
|
|
? mappedList
|
|
: exchangeRecords.value.concat(mappedList);
|
|
updatePaginationState(result, list, nextPage);
|
|
} catch (error) {
|
|
if (reset) {
|
|
exchangeRecords.value = [];
|
|
page.value = 0;
|
|
}
|
|
console.error("加载金币兑换记录失败", error);
|
|
} finally {
|
|
loading.value = false;
|
|
loaded.value = true;
|
|
}
|
|
};
|
|
|
|
onLoad((options = {}) => {
|
|
const currentStoreId = String(options.storeId || "");
|
|
if (!/^\d+$/.test(currentStoreId) || Number(currentStoreId) <= 0) {
|
|
uni.redirectTo({
|
|
url: "/pages/coin/nearby-stores",
|
|
});
|
|
return;
|
|
}
|
|
|
|
storeId.value = currentStoreId;
|
|
loadRecords({ reset: true });
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<Container :bgType="6" :isHome="true" @scrolltolower="loadRecords">
|
|
<template #header>
|
|
<CoinHeader title="金币兑换记录" />
|
|
</template>
|
|
<view class="records-page">
|
|
<CoinEmptyState v-if="showEmpty" text="暂无金币兑换记录。" />
|
|
<CoinRecordList v-else mode="exchange" :records="exchangeRecords" />
|
|
<view
|
|
v-if="loading || (noMore && exchangeRecords.length)"
|
|
class="records-page__status"
|
|
>
|
|
<text>{{ loading ? "加载中..." : "没有更多了" }}</text>
|
|
</view>
|
|
</view>
|
|
</Container>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.records-page {
|
|
width: 100%;
|
|
min-height: 100%;
|
|
}
|
|
|
|
.records-page__status {
|
|
padding: 24rpx 0 32rpx;
|
|
color: rgba(255, 255, 255, 0.6);
|
|
font-size: 24rpx;
|
|
line-height: 34rpx;
|
|
text-align: center;
|
|
}
|
|
</style>
|