Files
quyun/frontend/wechat/src/views/ArticleList.vue
2025-05-07 09:15:18 +08:00

100 lines
2.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { postApi } from '@/api/postApi'
import ArticleListItem from '@/components/ArticleListItem.vue'
import { useIntersectionObserver } from '@vueuse/core'
import { onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const searchInput = ref('')
const loadingTrigger = ref(null)
const articles = ref([])
const loading = ref(false)
const hasMore = ref(true)
const currentPage = ref(1)
const limit = 10
const fetchArticles = async () => {
if (loading.value) return
loading.value = true
try {
const { data } = await postApi.list({
page: currentPage.value,
limit,
keyword: searchInput.value
})
if (data.items?.length === 0) {
hasMore.value = false
} else {
articles.value.push(...data.items)
currentPage.value += 1
}
} catch (error) {
console.error('Failed to fetch articles:', error)
} finally {
loading.value = false
}
}
useIntersectionObserver(
loadingTrigger,
([{ isIntersecting }]) => {
if (isIntersecting && !loading.value && hasMore.value) {
fetchArticles()
}
},
{
threshold: 0,
rootMargin: '100px'
}
)
const handleSearch = () => {
articles.value = []
currentPage.value = 1
hasMore.value = true
fetchArticles()
}
const handleKeyup = (e) => {
if (e.key === 'Enter') {
handleSearch()
}
}
onMounted(() => {
fetchArticles()
})
</script>
<template>
<div class="h-full flex flex-col">
<div class="flex-none bg-white border-b border-gray-200 z-50 shadow">
<div class="p-4">
<input type="search" v-model="searchInput" @keyup="handleKeyup" placeholder="搜索文章"
class="w-full px-4 py-2 border border-gray-300 rounded-full focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent">
</div>
</div>
<div class="flex-1 overflow-y-auto">
<div class="p-4">
<ArticleListItem v-for="article in articles" :key="article.id" :article="article" class="mb-4" />
<div ref="loadingTrigger" class="py-4 text-center" v-show="hasMore || loading">
<div v-if="loading"
class="animate-spin rounded-full h-8 w-8 border-4 border-gray-200 border-t-blue-600 mx-auto">
</div>
<div v-else class="h-8">
<!-- 空白占位保持触发器可见 -->
</div>
</div>
<div v-if="!hasMore && articles.length > 0" class="text-center text-gray-500 py-4">
没有更多文章了
</div>
</div>
</div>
</div>
</template>