tiefen_space_h5/app/space/page.js

362 lines
12 KiB
JavaScript

"use client";
import React, { useEffect, useRef, useState } from "react";
import {
Tabs,
Swiper,
Toast,
Image,
List,
InfiniteScroll,
SpinLoading,
} from "antd-mobile";
import PostItem from "@/components/PostItem";
import "./index.css";
import Link from "next/link";
import Empty from "@/components/Empty";
import { useRouter } from "next/navigation";
import PostItemSkeleton from "@/components/skeletons/PostItemSkeleton";
import requireAPI from "@/utils/requireAPI";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faRefresh } from "@fortawesome/free-solid-svg-icons";
import InfiniteScrollContent from "@/components/InfiniteScrollContent";
const tabItems = [
{ key: "space", title: "空间" },
{ key: "post", title: "动态" },
];
// const scrollHeight = 700;
// const scrollHeight = window.innerHeight-126
export default function Space() {
const swiperRef = useRef(null);
const [activeIndex, setActiveIndex] = useState(0);
const [dataList, setDataList] = useState([]);
// const [spacePost, setSpacePost] = useState([]);
const [hasMore, setHasMore] = useState(1);
const [scrollHeight, setScrollHeight] = useState(0);
const [offset, setOffset] = useState(0);
const [loading, setLoading] = useState(false);
const scrollRef = useRef(null);
const router = useRouter();
// 获取屏幕高度
// const scrollHeight = 600;
useEffect(() => {
setScrollHeight(window.innerHeight - 57 - 44);
// const handleResize = () => {
// setScrollHeight(window.innerHeight - 126);
// };
// window.addEventListener("resize", handleResize);
// return () => {
// // window.removeEventListener("resize", handleResize);
// };
}, []);
useEffect(() => {
firstRequest();
}, [activeIndex]);
const firstRequest = () => {
resetOffset();
if (activeIndex === 0) {
getSpaceList();
}
if (activeIndex === 1) {
getSpacePosts(0).then((res) => {
res && setDataList(res);
});
}
};
const resetOffset = () => {
setOffset(0);
// setDataList([]);
};
const getSpaceList = async () => {
// setLoading(true);
try {
const data = await requireAPI("POST", "/api/zone/list_by_visitor_mid");
// setLoading(false);
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
return;
}
//在末尾添加元素以展示查看更多卡片
if (data.data.list.length !== 0) {
const finalData = [...data.data.list];
setDataList(finalData);
return;
}
} catch (error) {
console.error(error);
}
};
const getSpacePosts = async (offset) => {
// setLoading(true);
try {
const data = await requireAPI(
"POST",
"/api/zone_moment/list_by_visitor_mid",
{
body: { offset, limit: 4 },
}
);
// setLoading(false);
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
return;
}
//在末尾添加元素以展示查看更多卡片
setHasMore(data.data.more);
setOffset(data.data.offset);
if (data.data.list.length !== 0) {
const finalData = [...data.data.list];
return finalData;
}
} catch (error) {
console.error(error);
}
};
async function loadMore() {
if (!offset) return;
const append = await getSpacePosts(offset);
if (append) {
setDataList((val) => [...val, ...append]);
// setHasMore(append.length > 0);
}
}
return (
<div
className="h-screen overflow-x-hidden"
// style={{ maxHeight: `${scrollHeight}px` }}
>
<div className="flex justify-between items-center px-2 custom-tabs text-gray-400 sticky top-0 z-10 bg-deepBg">
<Tabs
activeKey={tabItems[activeIndex].key}
onChange={(key) => {
const index = tabItems.findIndex((item) => item.key === key);
setActiveIndex(index);
swiperRef.current?.swipeTo(index);
}}
>
{tabItems.map((item) => (
<Tabs.Tab
forceRender={false}
title={item.title}
key={item.key}
className="text-left"
/>
))}
</Tabs>
<Link
href="search"
className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full"
>
<Image
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/search.png"}
/>
</Link>
</div>
<Swiper
direction="horizontal"
indicator={() => null}
ref={swiperRef}
defaultIndex={activeIndex}
onIndexChange={(index) => {
setActiveIndex(index);
}}
>
<Swiper.Item>
{!activeIndex && (
<div>
{!loading ? (
// <div className="px-4 pb-8">
// </div>
<>
{dataList?.length > 0 ? (
<div className="px-4 pb-20">
<ul className="grid grid-cols-2 gap-2 overflow-y-auto">
{dataList?.map((item) => (
<li key={item.id}>
<VisitingCard data={item} />
</li>
))}
<li onClick={() => router.replace("/search")}>
<div
// onPress={() => navigation.navigate("Stream")}
// onClick={}
className="w-full h-52"
>
<div
className="h-full flex flex-col rounded-lg overflow-hidden bg-[#FFFFFF1A] bg-no-repeat bg-right-bottom bg-40%"
style={{
backgroundImage: `url(${
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/magnifier.png"
})`,
}}
>
{/* <div className="w-full z-0"></div>
<div
className="w-full z-0 h-[42px]"
></div> */}
<div className="flex flex-col w-full h-full px-[22px] py-[30px]">
<p className="text-white font-medium text-lg">
发现更多
</p>
<p className="text-[#FFFFFF40] font-sm">
缘分就在不经意间
</p>
<Image
width={32}
height={32}
className="mt-4"
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/rightarrow_border.png"
}
/>
</div>
</div>
</div>
</li>
</ul>
</div>
) : (
<div
className={`flex flex-col items-center justify-center`}
style={{ height: `${scrollHeight}px` }}
>
<Empty type="nospace" />
<div className="flex flex-col mt-6">
<Link
href="search"
className="bg-[#FFFFFF40] px-12 py-2 rounded-full text-base text-white"
>
搜索空间
</Link>
{/* <Link
href="search"
className="bg-[#FFFFFF40] px-12 py-2 rounded-full text-base text-white mt-2"
>
查看推荐
</Link> */}
</div>
</div>
)}
</>
) : (
<div
className="w-full text-center flex items-center justify-center"
style={{ height: scrollHeight - 60 + "px" }}
>
<SpinLoading />
</div>
)}
</div>
)}
</Swiper.Item>
<Swiper.Item>
{!!activeIndex && (
<div className="px-4 pb-20" ref={scrollRef}>
<List className="scrollbarBox_hidden">
{loading && (
<>
<PostItemSkeleton />
<PostItemSkeleton />
<PostItemSkeleton />
<PostItemSkeleton />
</>
)}
{dataList?.map((item, index) => (
<List.Item className="!p-0" key={item.id + "_" + index}>
<PostItem
type="space"
data={item}
date={new Date(item.ct * 1000)}
/>
</List.Item>
))}
<InfiniteScroll loadMore={loadMore} hasMore={hasMore} >
<InfiniteScrollContent hasMore={hasMore} isEmpty={dataList.length===0} showNoMore={!dataList.length}/>
</InfiniteScroll>
</List>
{/* {!dataList?.length && (
<div
className={`flex flex-col items-center justify-center`}
style={{ height: `${scrollHeight}px` }}
>
<Empty type="nodata" />
</div>
)} */}
</div>
)}
</Swiper.Item>
</Swiper>
<div
className={`fixed bottom-[96px] right-4 z-[999] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
loading && !offset ? "animate-spin" : ""
}`}
>
<FontAwesomeIcon
icon={faRefresh}
size="xl"
// onClick={firstRequest}
onClick={() => {
scrollRef.current?.scrollTo(0, 0);
firstRequest();
}}
/>
</div>
</div>
);
}
const VisitingCard = ({ data }) => {
const router = useRouter();
return (
<div
className="relative h-52"
onClick={() => router.push("/space/" + data?.streamer_ext?.mid)}
>
{data?.is_unread_zone_moment_exist === 1 && (
<Image
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/images/space_new.png"}
width={78}
fit="contain"
className="absolute top-2 right-2"
/>
)}
<Image
width={"100%"}
height={"100%"}
src={data?.streamer_ext?.cover.images[0].urls[0]}
fit="cover"
className="rounded-lg"
/>
<div className="absolute bottom-0 left-0 w-full px-2 py-3 bg-[#1b1b1b] flex items-center rounded-b-lg">
<span className="font-bold overflow-hidden whitespace-nowrap text-ellipsis">
{data?.streamer_ext?.name}
</span>
<ul className="flex ml-2">
{data?.admission_price !== 0 && (
<li className="text-[10px] bg-primary rounded px-1 mr-1 whitespace-nowrap">
付费
</li>
)}
{data.visitor_role === 3 && (
<li className="text-[10px] bg-primary rounded px-1 mr-1 whitespace-nowrap">
创建者
</li>
)}
</ul>
</div>
</div>
);
};