Files
CosScene/clients/pages/mine/favorites.vue
T
2026-05-09 16:40:29 +08:00

134 lines
2.7 KiB
Vue

<script setup>
import { ref } from "vue";
import { onPullDownRefresh, onReachBottom, onShow } from "@dcloudio/uni-app";
import { getFavorites } from "@/api/favorite";
import { extractList } from "@/utils/request";
import { checkLogin } from "@/utils/auth";
import SpotCard from "@/components/spot-card/spot-card.vue";
onShow(() => { checkLogin(); });
const favorites = ref([]);
const page = ref(1);
const pageSize = 10;
const hasMore = ref(true);
const loading = ref(false);
const fetchFavorites = async (reset = false) => {
if (loading.value) return;
if (!reset && !hasMore.value) return;
loading.value = true;
if (reset) {
page.value = 1;
hasMore.value = true;
}
try {
const res = await getFavorites({ page: page.value, page_size: pageSize });
const list = extractList(res);
if (reset) {
favorites.value = list;
} else {
favorites.value.push(...list);
}
if (list.length < pageSize) {
hasMore.value = false;
} else {
page.value++;
}
} catch (e) {
console.error(e);
} finally {
loading.value = false;
}
};
const goDetail = (item) => {
const id = item.spot_id || item.spot?.id || item.id;
if (id) {
uni.navigateTo({ url: `/pages/spot/detail?id=${id}` });
}
};
onPullDownRefresh(async () => {
await fetchFavorites(true);
uni.stopPullDownRefresh();
});
onReachBottom(() => {
fetchFavorites();
});
fetchFavorites(true);
</script>
<template>
<view class="favorites-page">
<view class="list">
<SpotCard
v-for="item in favorites"
:key="item.id"
:spot="item.spot || item"
@click="goDetail(item)"
/>
<view v-if="loading" class="status-tip">
<text>加载中...</text>
</view>
<view v-else-if="!hasMore && favorites.length > 0" class="status-tip">
<text>没有更多了</text>
</view>
<view v-else-if="!loading && favorites.length === 0" class="empty-state">
<uni-icons type="heart-filled" size="48" color="#6366f1" class="empty-icon" />
<text class="empty-title">暂无收藏</text>
<text class="empty-desc">去发现页浏览并收藏喜欢的取景地吧</text>
</view>
</view>
</view>
</template>
<style scoped>
.favorites-page {
min-height: 100vh;
background: #f5f6fa;
}
.list {
padding: 24rpx 32rpx;
}
.status-tip {
text-align: center;
padding: 40rpx 0;
color: #94a3b8;
font-size: 26rpx;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
padding: 160rpx 0;
}
.empty-icon {
font-size: 96rpx;
margin-bottom: 24rpx;
}
.empty-title {
font-size: 32rpx;
font-weight: 600;
color: #1e293b;
margin-bottom: 12rpx;
}
.empty-desc {
font-size: 26rpx;
color: #94a3b8;
}
</style>