import { Text, View, ScrollView } from "@tarojs/components"; import { Heart, HeartFill, Plus } from "@nutui/icons-react-taro"; import { Message } from "@nutui/icons-react-taro"; import avatar from "../../asset/img/avatar.png"; import { Grid, GridItem, Image, ImagePreview, Toast, } from "@nutui/nutui-react-taro"; import { createPortal } from "react-dom"; import MoreButton from "../fllower-button"; import { circlePostListApi } from "../../api/post"; import { useEffect, useState, useCallback, useImperativeHandle, forwardRef, } from "react"; import { strSlice } from "../../utils/index"; import { followApi, interactionApi, unfollowApi } from "../../api/interaction"; import { Dialog } from "@nutui/nutui-react-taro"; import { getStorageSync, navigateTo } from "@tarojs/taro"; interface PostListProps { style?: any; } export interface PostListRef { loadMore: () => void; refresh: () => void; hasMore: boolean; loading: boolean; } const PostList = forwardRef(({ style }, ref) => { const [postList, setPostList] = useState([]); const [showPreview, setShowPreview] = useState(false); const [init, setInit] = useState(0); const [mediaUrl, setMediaUrl] = useState([]); // 分页相关状态 const [currentPage, setCurrentPage] = useState(1); const [hasMore, setHasMore] = useState(true); const [loading, setLoading] = useState(false); const [refreshing, setRefreshing] = useState(false); const pageSize = 10; const getPostList = useCallback( async (page = 1, isRefresh = false) => { if (isRefresh) { setRefreshing(true); } else { setLoading(true); } try { let circleInfo = getStorageSync("circleInfo"); const res: any = await circlePostListApi({ circleId: circleInfo.id, page, pageSize: pageSize, }); if (res.code === 200) { const newList = res.data.list || []; if (isRefresh || page === 1) { setPostList(newList); } else { setPostList((prev) => [...prev, ...newList]); } // 判断是否还有更多数据 setHasMore(res.data.has_more); setCurrentPage(page); } } catch (error) { Toast.show("load_error", { content: "加载失败,请重试", duration: 2, }); } finally { setLoading(false); setRefreshing(false); } }, [pageSize] ); // 下拉刷新 const handleRefresh = useCallback(async () => { await getPostList(1, true); }, [getPostList]); // 上拉加载更多 const handleLoadMore = useCallback(async () => { if (hasMore && !loading && !refreshing) { await getPostList(currentPage + 1, false); } }, [hasMore, currentPage, getPostList, loading, refreshing]); // ScrollView 滚动到底部事件 const handleScrollToLower = useCallback(() => { handleLoadMore(); }, [handleLoadMore]); // ScrollView 下拉刷新事件 const handleRefresherRefresh = useCallback(async () => { await handleRefresh(); }, [handleRefresh]); const handleMoreClick = (postIndex: number) => { const data = [...postList]; data.splice(postIndex, 1); setPostList(data); }; // 点赞 const handleInteraction = async (postId: number, type) => { const res: any = await interactionApi({ target_type: "post", target_id: postId, interaction_type: type, }); if (res.code === 200) { const data = [...postList]; data.forEach((item: any) => { if (item.id === postId) { item.is_praised = type === "praise" ? true : false; item.like_count = type === "praise" ? item.like_count + 1 : item.like_count - 1; } }); console.log(data); setPostList(data); } }; // 关注/不关注 const handleFollowClick = (followeeId: number, is_followed) => { if (is_followed) { unfollowApi({ followee_id: followeeId }).then(() => { Toast.show("follow_success", { content: "取消关注成功", duration: 2, lockScroll: true, }); const data = [...postList]; data.forEach((item: any) => { item.is_followed = false; }); setPostList(data); Dialog.close("followed_dialog"); }); } else { followApi({ followee_id: followeeId }).then(() => { Toast.show("follow_success", { content: "关注成功", duration: 2, lockScroll: true, }); const data = [...postList]; data.forEach((item: any) => { item.is_followed = true; }); setPostList(data); }); } }; // 暴露方法给父组件 useImperativeHandle(ref, () => ({ loadMore: handleLoadMore, refresh: handleRefresh, hasMore, loading, })); useEffect(() => { getPostList(1, true); }, [getPostList]); return ( <> {postList.map((item: any, index: number) => { return ( { navigateTo({ url: `/pages/self/index?id=${item.user_id}`, }); }} > {item.user.nickname || item.user.username || "微信用户"} {item.user.is_official ? ( 官方账号 ) : ( <> )} { e.stopPropagation(); handleFollowClick(item.user_id, item.is_followed); }} > {!item.is_followed && } {item.is_followed ? "已关注" : "关注"} {!item.user.is_official && ( )} navigateTo({ url: `/pages/detail/index?id=${item.id}` }) } > {item.type === "1" ? ( <> {strSlice(item.content, 100)} {item.content.length > 100 && ( 全文 )} ) : ( <> {item.content.length > 100 && ( 全文 )} )} {item.media_url.map((ite: any, index: number) => { return ( { e.preventDefault(); e.stopPropagation(); setMediaUrl(item.media_url); setInit(index + 1); setShowPreview(true); }} /> ); })} {item.comment_count} { e.stopPropagation(); handleInteraction( item.id, item.is_praised ? "dispraise" : "praise" ); }} > {item.is_praised ? ( ) : ( )} {item.like_count} ); })} {/* 空状态提示 */} {postList.length === 0 && !loading && ( 暂无帖子 )} {/* 加载更多提示 */} {hasMore && ( {loading ? "加载中..." : "上拉加载更多"} )} {!hasMore && postList.length > 0 && ( 没有更多了 )} {showPreview && createPortal( setShowPreview(false)} indicator />, document.body )} ); }); PostList.displayName = "PostList"; export default PostList;