import React, { useState, useEffect, useRef } from 'react' import Taro, { usePullDownRefresh, useReachBottom, useDidShow } from '@tarojs/taro' import { View, Text, Image, Swiper, SwiperItem, ScrollView } from '@tarojs/components' import { AtSearchBar, AtTabs, AtIcon, AtActivityIndicator } from 'taro-ui' import { getTopics, getAnnouncements, getStarUsers } from '../../api' import './index.scss' const ForumList = () => { const [topics, setTopics] = useState([]) const [announcements, setAnnouncements] = useState([]) const [starUsers, setStarUsers] = useState([]) const [loading, setLoading] = useState(false) const [hasMore, setHasMore] = useState(true) const [page, setPage] = useState(1) const [searchText, setSearchText] = useState('') const [currentTab, setCurrentTab] = useState(0) const isMounted = useRef(false) const categories = [ { title: '全部话题', key: 'all' }, { title: '技术讨论', key: 'discussion' }, { title: '求助问答', key: 'help' }, { title: '经验分享', key: 'share' }, { title: '官方公告', key: 'notice' }, ] const fetchExtraData = async () => { try { const [announceRes, starRes] = await Promise.all([ getAnnouncements(), getStarUsers() ]) setAnnouncements(Array.isArray(announceRes) ? announceRes : (announceRes.results || announceRes.data || [])) setStarUsers(Array.isArray(starRes) ? starRes : (starRes.data || [])) } catch (err) { console.error('Fetch extra data failed', err) } } const fetchList = async (reset = false) => { if (loading) return if (!reset && !hasMore) return setLoading(true) try { const currentPage = reset ? 1 : page const params: any = { page: currentPage, search: searchText } if (categories[currentTab].key !== 'all') { params.category = categories[currentTab].key } const res = await getTopics(params) let newTopics: any[] = [] let hasNextPage = false if (Array.isArray(res)) { newTopics = res hasNextPage = false } else { newTopics = res.results || res.data || [] hasNextPage = !!res.next } if (reset) { setTopics(newTopics) } else { setTopics(prev => [...prev, ...newTopics]) } setHasMore(hasNextPage) if (hasNextPage) { setPage(currentPage + 1) } } catch (error) { console.error(error) Taro.showToast({ title: '加载失败', icon: 'none' }) } finally { setLoading(false) Taro.stopPullDownRefresh() } } useDidShow(() => { fetchList(true) fetchExtraData() }) useEffect(() => { if (!isMounted.current) { isMounted.current = true return } fetchList(true) // fetchExtraData is covered by useDidShow usually, but if tab change needs it? likely not. }, [currentTab]) usePullDownRefresh(() => { fetchList(true) fetchExtraData() }) useReachBottom(() => { fetchList(false) }) const handleSearch = (value) => { setSearchText(value) } const onSearchConfirm = () => { fetchList(true) } const handleTabClick = (value) => { setCurrentTab(value) // useEffect will trigger fetch } const navigateToDetail = (id) => { Taro.navigateTo({ url: `/subpackages/forum/detail/index?id=${id}` }) } const navigateToCreate = () => { const token = Taro.getStorageSync('token') if (!token) { Taro.showToast({ title: '请先登录', icon: 'none' }) // Optional: Trigger login flow return } Taro.navigateTo({ url: '/subpackages/forum/create/index' }) } const navigateToActivity = () => { Taro.navigateTo({ url: '/subpackages/forum/activity/index' }) } const getCategoryLabel = (cat) => { const map = { 'help': '求助', 'share': '分享', 'notice': '公告', 'discussion': '讨论' } return map[cat] || '讨论' } // Helper to extract first image from markdown const getCoverImage = (content) => { const match = content.match(/!\[.*?\]\((.*?)\)/) return match ? match[1] : null } const stripMarkdown = (content) => { return content.replace(/!\[.*?\]\(.*?\)/g, '[图片]').replace(/[#*`]/g, '') } return ( Quant Speed Developer Community 技术交流 · 硬件开发 · 官方支持 发布新帖 社区活动 {/* Announcements Section */} {announcements.length > 0 && ( 社区公告 {announcements.map(item => ( {item.title} ))} )} {/* Star Users Section */} {starUsers.length > 0 && ( 技术专家榜 {starUsers.map(user => ( {user.nickname} {user.title || '专家'} ))} )} {topics.map(item => ( navigateToDetail(item.id)} > {item.is_pinned && 置顶} {getCategoryLabel(item.category)} {item.is_verified_owner && 认证} {item.title} {stripMarkdown(item.content)} {getCoverImage(item.content) && ( )} {item.author_info?.nickname || '匿名'} 👁 {item.view_count || 0} 💬 {item.replies?.length || 0} ))} {loading && } {!loading && topics.length === 0 && 暂无内容} ) } export default ForumList