import { useState, useCallback } from 'react'; import { View, Text, ScrollView } from '@tarojs/components'; import Taro from '@tarojs/taro'; import { safeNavigateTo } from '@/utils/navigate'; import { usePageData } from '@/hooks/usePageData'; import { listArticles, listCategories } from '../../services/article'; import PageShell from '@/components/ui/PageShell'; import ContentCard from '@/components/ui/ContentCard'; import LoadingCard from '@/components/ui/LoadingCard'; import EmptyState from '@/components/EmptyState'; import ErrorState from '@/components/ErrorState'; import Loading from '@/components/Loading'; import { useElderClass } from '../../hooks/useElderClass'; import './index.scss'; interface ArticleItem { id: string; title: string; summary?: string; cover_image?: string; category?: string; category_id?: string; category_name?: string; published_at?: string; status?: string; } interface ArticleCategory { id: string; name: string; parent_id?: string | null; } export default function ArticleList() { const modeClass = useElderClass(); const [articles, setArticles] = useState([]); const [page, setPage] = useState(1); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(false); const [error, setError] = useState(false); const [categories, setCategories] = useState([]); const [activeCategory, setActiveCategory] = useState(null); const fetchData = useCallback(async (p: number, append = false, categoryId?: string | null) => { setLoading(true); setError(false); try { const cid = categoryId !== undefined ? categoryId : activeCategory; const res = await listArticles({ page: p, category_id: cid || undefined, }); const list = res.data || []; setArticles(append ? (prev) => [...prev, ...list] : list); setTotal(res.total); setPage(p); } catch { setError(true); Taro.showToast({ title: '加载失败', icon: 'none' }); } finally { setLoading(false); } }, [activeCategory]); usePageData( useCallback(async () => { try { const cats = await listCategories(); setCategories(cats || []); } catch { setCategories([]); } await fetchData(1); }, [fetchData]), { throttleMs: 10000, enablePullDown: true }, ); const handleCategoryChange = (categoryId: string | null) => { setActiveCategory(categoryId); fetchData(1, false, categoryId); }; const goToDetail = (id: string) => { safeNavigateTo(`/pages/article/detail/index?id=${id}`); }; if (loading && articles.length === 0 && !error) { return ; } return ( {categories.length > 0 && ( handleCategoryChange(null)} > 全部 {categories.map((cat) => ( handleCategoryChange(cat.id)} > {cat.name} ))} )} {error ? ( fetchData(1, false, null)} /> ) : articles.length === 0 && !loading ? ( ) : ( {articles.map((a) => ( goToDetail(a.id)} > {a.title} {a.summary && ( {a.summary} )} {(a.category_name || a.category) && ( {a.category_name || a.category} )} {a.published_at && ( {a.published_at.slice(0, 10)} )} ))} )} {loading && } ); }