Files
mini-programs/src/container/listContainer/index.tsx
2025-11-08 20:14:54 +08:00

159 lines
4.1 KiB
TypeScript

import { View, Text, Image } from "@tarojs/components";
import ListCard from "@/components/ListCard";
import ListLoadError from "@/components/ListLoadError";
import ListCardSkeleton from "@/components/ListCardSkeleton";
import { useReachBottom } from "@tarojs/taro";
import { useUserInfo } from "@/store/userStore";
import { setStorage, getStorage } from "@/store/storage";
import { NTRPTestEntryCard } from "@/components";
import { EvaluateScene } from "@/store/evaluateStore";
import "./index.scss";
import { useRef, useEffect, useState } from "react";
const ListContainer = (props) => {
const {
loading,
isShowNoData,
data = [],
error,
reload,
// recommendList,
loadMoreMatches,
errorImg,
emptyText,
btnText,
btnImg,
style,
collapse = false,
defaultShowNum,
} = props;
const timerRef = useRef<NodeJS.Timeout | null>(null);
const [showNumber, setShowNumber] = useState(0)
const userInfo = useUserInfo();
useReachBottom(() => {
// 加载更多方法
if (loading) {
return;
}
// timerRef.current = setTimeout(() => {
loadMoreMatches();
// }, 500);
});
useEffect(() => {
setShowNumber(
() => {
return defaultShowNum === undefined ? data?.length : defaultShowNum
})
}, [data])
useEffect(() => {
return () => {
if (timerRef.current) {
clearTimeout(timerRef.current);
}
};
}, []);
if (error) {
return <ListLoadError reload={reload} />;
}
const renderSkeleton = () => {
return (
<>
{new Array(10).fill(0).map(() => {
return <ListCardSkeleton />;
})}
</>
);
};
// 对于没有ntrp等级的用户每个月展示一次, 插在第三个位置
function insertEvaluateCard(list) {
if (!list || list.length === 0) {
return list;
}
if (userInfo.ntrp_level) {
return list;
}
const lastShowTime = getStorage("list_evaluate_card");
if (!lastShowTime) {
setStorage("list_evaluate_card", Date.now());
}
if (Date.now() - Number(lastShowTime) < 30 * 24 * 60 * 60 * 1000) {
return list;
}
if (list.length <= 3) {
return [...list, { type: "evaluateCard" }];
}
const [item1, item2, item3, ...rest] = list;
return [item1, item2, item3, { type: "evaluateCard" }, ...rest];
}
// 渲染列表
const renderList = (list) => {
// 请求数据为空
if (isShowNoData) {
return (
<ListLoadError
reload={reload}
errorImg={errorImg}
btnText={btnText}
btnImg={btnImg}
text={emptyText || "暂无数据"}
/>
);
}
showNumber !== undefined && (list = list.slice(0, showNumber))
// 渲染数据
return (
<>
{insertEvaluateCard(list).map((match, index) => {
if (match.type === "evaluateCard") {
return (
<NTRPTestEntryCard key="evaluate" type={EvaluateScene.list} />
);
}
return <ListCard key={match?.id || index} {...match} />;
})}
</>
);
};
return (
<View className="listContentWrapper" style={style}>
{renderList(data)}
{/* 显示骨架屏 */}
{loading && renderSkeleton()}
{/* <View className="recommendTextWrapper">
<Text className="recommendText">搜索结果较少,已为你推荐其他内容</Text>
</View>
{renderList(recommendList)} */}
{/* 到底了 */}
{collapse ?
data?.length > defaultShowNum ?
data?.length > showNumber ?
<View className="collapse-btn fold" onClick={() => { setShowNumber(data?.length) }}>
<Text></Text>
<Image src={require("@/static/userInfo/fold.svg")}></Image>
</View> :
<View className="collapse-btn" onClick={() => { setShowNumber(defaultShowNum) }}>
<Text></Text>
<Image src={require("@/static/userInfo/fold.svg")}></Image>
</View>
:
null
: data?.length > 0 && <View className="bottomTextWrapper"></View>}
</View>
);
};
export default ListContainer;