134 lines
3.5 KiB
Vue
134 lines
3.5 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 CoinEmptyState from "./components/CoinEmptyState.vue";
|
|
import { getStoreGoldRuleListAPI } from "@/apis";
|
|
|
|
const PAGE_SIZE = 20;
|
|
const storeId = ref("");
|
|
const coinRules = ref([]);
|
|
const page = ref(0);
|
|
const loading = ref(false);
|
|
const noMore = ref(false);
|
|
const loaded = ref(false);
|
|
const showEmpty = computed(() => loaded.value && !coinRules.value.length);
|
|
|
|
const updatePaginationState = (result, list, nextPage) => {
|
|
const currentPage = Number(result?.page) || nextPage;
|
|
const pageCount = Number(result?.pageCount ?? result?.page_count);
|
|
const totalCount = Number(result?.totalCount ?? result?.total);
|
|
const responsePageSize =
|
|
Number(result?.pageSize ?? result?.page_size) || PAGE_SIZE;
|
|
|
|
page.value = currentPage;
|
|
if (Number.isFinite(pageCount) && pageCount >= 0) {
|
|
noMore.value = currentPage >= pageCount;
|
|
return;
|
|
}
|
|
if (Number.isFinite(totalCount) && totalCount >= 0) {
|
|
noMore.value = coinRules.value.length >= totalCount;
|
|
return;
|
|
}
|
|
noMore.value = list.length < responsePageSize;
|
|
};
|
|
|
|
const loadRules = 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 getStoreGoldRuleListAPI({
|
|
storeId: storeId.value,
|
|
page: nextPage,
|
|
pageSize: PAGE_SIZE,
|
|
});
|
|
const list = Array.isArray(result?.list) ? result.list : [];
|
|
const mappedList = list.map((item) => ({
|
|
id: item.id,
|
|
content: item.content || "",
|
|
}));
|
|
|
|
coinRules.value = reset ? mappedList : coinRules.value.concat(mappedList);
|
|
updatePaginationState(result, list, nextPage);
|
|
} catch (error) {
|
|
if (reset) {
|
|
coinRules.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;
|
|
loadRules({ reset: true });
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<Container :bgType="6" :isHome="true" @scrolltolower="loadRules">
|
|
<template #header>
|
|
<CoinHeader title="金币规则" />
|
|
</template>
|
|
<view class="rules-page">
|
|
<CoinEmptyState v-if="showEmpty" text="暂无金币规则。" />
|
|
<template v-else>
|
|
<view
|
|
v-for="rule in coinRules"
|
|
:key="rule.id"
|
|
class="rules-page__item"
|
|
>
|
|
<rich-text class="rules-page__content" :nodes="rule.content" />
|
|
</view>
|
|
</template>
|
|
<view v-if="loading" class="rules-page__status">
|
|
<text>加载中...</text>
|
|
</view>
|
|
</view>
|
|
</Container>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.rules-page {
|
|
width: 100%;
|
|
padding: 28rpx 38rpx 60rpx;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.rules-page__item {
|
|
margin-bottom: 26rpx;
|
|
color: rgba(255, 255, 255, 0.88);
|
|
font-size: 28rpx;
|
|
line-height: 52rpx;
|
|
text-align: justify;
|
|
}
|
|
|
|
.rules-page__content {
|
|
display: block;
|
|
}
|
|
|
|
.rules-page__status {
|
|
padding: 12rpx 0 20rpx;
|
|
color: rgba(255, 255, 255, 0.6);
|
|
font-size: 24rpx;
|
|
line-height: 34rpx;
|
|
text-align: center;
|
|
}
|
|
</style>
|