import { ArrowRightOutlined, LeftOutlined, RightOutlined, SearchOutlined } from '@ant-design/icons'; import { Button, Card, Empty, Input, Select, Space, Spin, Tag } from 'antd'; import { useEffect, useRef, useState } from 'react'; import type { PointsMallProduct } from '../../../api'; import type { PointsMallPageLogicOutput } from '../PointsMallPageLogic'; import '../styles/points-mall-h5-products.css'; interface Props { logic: PointsMallPageLogicOutput; } export default function PointsMallH5Products({ logic }: Props) { const { q, sort, productsLoading, products, total, userPoints, exchangeLoading, setQ, setSort, page, setPage, handleExchangeClick } = logic; const [displayProducts, setDisplayProducts] = useState([]); const loadingMoreRef = useRef(false); const scrollRef = useRef(null); // 监听搜索/排序变化,重置列表 useEffect(() => { setDisplayProducts(products); // eslint-disable-next-line react-hooks/exhaustive-deps }, [q, sort]); // 监听数据变化,追加到显示列表 useEffect(() => { if (page === 1) { setDisplayProducts(products); } else { setDisplayProducts(prev => { const existingIds = new Set(prev.map(p => p.id)); const newItems = products.filter(p => !existingIds.has(p.id)); return [...prev, ...newItems]; }); } loadingMoreRef.current = false; }, [products, page]); const hasMore = displayProducts.length < total; // 瀑布流滚动加载 useEffect(() => { const handleScroll = () => { // 获取滚动容器,H5 端通常是 App.tsx 里的 .main-content const container = document.querySelector('.main-content'); if (!container || !hasMore || productsLoading || loadingMoreRef.current) return; const { scrollTop, scrollHeight, clientHeight } = container; // 距离底部 100px 时触发加载 if (scrollTop + clientHeight >= scrollHeight - 100) { loadingMoreRef.current = true; setPage(prev => prev + 1); } }; const container = document.querySelector('.main-content'); container?.addEventListener('scroll', handleScroll); return () => container?.removeEventListener('scroll', handleScroll); }, [hasMore, productsLoading]); return (
{ setQ(e.target.value); }} prefix={} placeholder="搜索商品" allowClear variant="borderless" className="points-mall-search-input-h5" />