Files
shoot-miniprograms/src/pages/coin/rules.vue
T
2026-08-20 16:10:17 +08:00

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>