blob: d906e33255992a2fe60a0fa2ab5193caf46f2faa [file] [log] [blame]
wua80b90d2025-06-15 10:36:02 +08001// src/components/HomeFeed.jsx
wueb6e6ca2025-06-15 10:35:32 +08002
wua80b90d2025-06-15 10:36:02 +08003import React, { useState, useEffect } from 'react'
4import { ThumbsUp } from 'lucide-react'
5import { fetchPosts, fetchPost } from '../api/posts'
6import '../style/HomeFeed.css'
wueb6e6ca2025-06-15 10:35:32 +08007
8const categories = [
9 '推荐','穿搭','美食','彩妆','影视',
10 '职场','情感','家居','游戏','旅行','健身'
11]
12
13export default function HomeFeed() {
14 const [activeCat, setActiveCat] = useState('推荐')
wua80b90d2025-06-15 10:36:02 +080015 const [items, setItems] = useState([])
16 const [loading, setLoading] = useState(true)
17 const [error, setError] = useState(null)
18
19 useEffect(() => {
20 async function loadPosts() {
21 try {
22 const list = await fetchPosts() // [{id, title, heat, created_at}, …]
23 // 为了拿到 media_urls 和 user_id,这里再拉详情
24 const detailed = await Promise.all(
25 list.map(async p => {
26 const d = await fetchPost(p.id)
27 return {
28 id: d.id,
29 title: d.title,
30 author: `作者 ${d.user_id}`,
31 avatar: `https://i.pravatar.cc/40?img=${d.user_id}`,
32 img: d.media_urls?.[0] || '', // 用第一张媒体作为封面
33 likes: d.heat
34 }
35 })
36 )
37 setItems(detailed)
38 } catch (e) {
39 setError(e.message)
40 } finally {
41 setLoading(false)
42 }
43 }
44 loadPosts()
45 }, [])
wueb6e6ca2025-06-15 10:35:32 +080046
47 return (
48 <div className="home-feed">
49 {/* 顶部分类 */}
50 <nav className="feed-tabs">
51 {categories.map(cat => (
52 <button
53 key={cat}
54 className={cat === activeCat ? 'tab active' : 'tab'}
55 onClick={() => setActiveCat(cat)}
56 >
57 {cat}
58 </button>
59 ))}
60 </nav>
61
wua80b90d2025-06-15 10:36:02 +080062 {/* 状态提示 */}
63 {loading ? (
64 <div className="loading">加载中…</div>
65 ) : error ? (
66 <div className="error">加载失败:{error}</div>
67 ) : (
68 /* 瀑布流卡片区 */
69 <div className="feed-grid">
70 {items.map(item => (
71 <div key={item.id} className="feed-card">
72 <img className="card-img" src={item.img} alt={item.title} />
73 <h3 className="card-title">{item.title}</h3>
74 <div className="card-footer">
75 <div className="card-author">
76 <img className="avatar" src={item.avatar} alt={item.author} />
77 <span className="username">{item.author}</span>
78 </div>
79 <div className="card-likes">
80 <ThumbsUp size={16} />
81 <span className="likes-count">{item.likes}</span>
82 </div>
wueb6e6ca2025-06-15 10:35:32 +080083 </div>
84 </div>
wua80b90d2025-06-15 10:36:02 +080085 ))}
86 </div>
87 )}
wueb6e6ca2025-06-15 10:35:32 +080088 </div>
89 )
wua80b90d2025-06-15 10:36:02 +080090}