tiefen_space_h5/app/space/[id]/page.js

666 lines
23 KiB
JavaScript

"use client";
import React, { useEffect, useState, useRef, useMemo } from "react";
import {
Image,
FloatingPanel,
JumboTabs,
List,
InfiniteScroll,
Toast,
Popup,
} from "antd-mobile";
import { useRouter, useParams } from "next/navigation";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleLeft, faRefresh } from "@fortawesome/free-solid-svg-icons";
import PostItem from "@/components/PostItem";
import PostItemSkeleton from "@/components/skeletons/PostItemSkeleton";
import requireAPI from "@/utils/requireAPI";
import AddWeChat from "@/components/AddWeChat";
import SeeTiefen from "@/components/SeeTiefen";
import DefaultMask from "@/components/DefaultMask";
import { getSpaceData, getStreamerInfo } from "@/api/space";
import baseRequest from "@/utils/baseRequest";
import createPost from "../../../public/icons/createpost.png";
const anchors = [
typeof window !== "undefined" ? window.innerHeight - 280 : "100vh",
typeof window !== "undefined" ? window.innerHeight - 180 : "100vh",
typeof window !== "undefined" ? window.innerHeight - 60 : "100vh",
// 200, 300, 400,
];
export default function PersonSpace() {
const base = baseRequest();
const router = useRouter();
const { id } = useParams();
const contentBox = useRef();
const [hasMore, setHasMore] = useState(true);
const [scrollHeight, setScrollHeight] = useState(0);
const [postList, setPostList] = useState([]);
const [tabItems, setTabItems] = useState([]);
const [offset, setOffset] = useState(0);
const [maskVisible, setMaskVisible] = useState({ visible: false, type: "" });
const [currentKey, setCurrentKey] = useState("all");
const [loading, setLoading] = useState(false);
const [streamerInfo, setStreamerInfo] = useState(null);
const [currentTime, setCurrentTime] = useState();
const scrollRef = useRef(null);
const [createPostMask, setCreatePostMask] = useState(false);
//退款中Modal是否展示
const [isRefundingModalVisible, setIsRefundingModalVisible] = useState(false);
const ironFanProgress = useMemo(
() =>
Math.floor(
(streamerInfo?.expenditure / streamerInfo?.ironfanship_price) * 100
),
[streamerInfo]
);
useEffect(() => {
setScrollHeight(window.innerHeight - 126);
if (contentBox.current) {
contentBox.current.style.transform = "translateY(-12px)";
// debugger
}
getStreamerInfo(Number(id)).then((res) => {
let tabitems = res?.is_superfanship_enabled
? [
{ label: "全部", key: "all" },
{ label: "铁粉专享", key: "ironFan" },
{ label: "超粉专享", key: "chaofen" },
]
: [
{ label: "全部", key: "all" },
{ label: "铁粉专享", key: "ironFan" },
];
setTabItems(tabitems);
setStreamerInfo(res);
});
getCurrentTime();
getSpaceData(Number(id)).then((res) => {
if (res) {
const { isRefunding, noRole } = res;
isRefunding && router.push("/");
noRole && router.replace("person_space_introduce/" + id);
}
});
}, []);
useEffect(() => {
if (currentKey) {
firstRequest(currentKey);
}
}, [currentKey, streamerInfo]);
const getCurrentTime = async () => {
setCurrentTime(Math.floor(new Date().getTime() / 1000));
};
async function loadMore() {
// if (!offset) return;
const append = await getPostList(streamerInfo.id, currentKey, offset);
if (append) {
setPostList((val) => [...val, ...append]);
// setHasMore(append.length > 0);
}
}
const getPostList = async (zid, activeKey, offset) => {
try {
setLoading(true);
let body = {
zid: zid,
ct_upper_bound: Math.floor(new Date().getTime() / 1000),
offset,
limit: 4,
};
switch (activeKey) {
case "all":
body = body;
break;
case "ironFan":
body = {
...body,
c_type: 1,
is_ironfan_visible: 1,
};
break;
case "chaofen":
body = {
...body,
c_type: 1,
};
break;
default:
break;
}
// console.log("body",body)
const data = await requireAPI("POST", "/api/zone_moment/list_by_zid", {
body,
});
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
return;
}
setLoading(false);
setOffset(data.data.offset);
setHasMore(data.data.more);
return data.data.list;
} catch (error) {
setLoading(false);
}
};
const firstRequest = (currentKey) => {
if (typeof window == "undefined") return;
let floatingPanel = document.getElementsByClassName(
"adm-floating-panel-content"
)[0];
floatingPanel?.scrollTo(0, 0);
setOffset(0);
setHasMore(true);
if (!postList.length) return;
if (streamerInfo) {
getPostList(streamerInfo.id, currentKey, 0).then((res) => {
setPostList(res || []);
});
}
};
return (
<div
className={`${
!!streamerInfo?.is_superfanship_enabled
? "spaceBoxThree"
: "spaceBoxTwo"
}`}
>
<div className="flex justify-between items-center p-4 fixed top-0 z-10 w-full">
<div className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full">
<FontAwesomeIcon
icon={faAngleLeft}
size="xl"
style={{ maxWidth: "12px" }}
onClick={() => {
router.back();
}}
/>
</div>
<div onClick={() => router.push("setting/" + streamerInfo?.mid)}>
<Image
width={42}
height={42}
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/setting.png"}
placeholder=""
/>
</div>
</div>
{/* 内容 */}
<div>
<div
className="bg-no-repeat bg-cover bg-center"
style={{
backgroundImage: `url(${
streamerInfo?.streamer_ext?.cover?.images[0]?.urls[0] || ""
})`,
}}
>
<div className="px-4 pt-24 pb-8 bg-[#181818a9]">
<div className="flex justify-between items-center">
<div className="flex items-center">
<Image
width="64px"
height="64px"
className="rounded-full mr-2 border-2 border-white"
fit="cover"
src={streamerInfo?.streamer_ext?.avatar?.images[0]?.urls[0]}
/>
<div>
<p className="text-2xl mb-1">
{streamerInfo?.streamer_ext?.name}
</p>
<div className="flex">
<div className="h-4 flex items-center text-xs bg-[#ffffff18] rounded-full px-2 py-2.5 mb-1 w-max mr-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/info/ID.png"
}
width={14}
height={14}
className="w-4 h-full mr-1"
placeholder=""
/>
<span>{streamerInfo?.streamer_ext?.user_id}</span>
</div>
<div className="h-4 flex items-center text-xs bg-[#ffffff18] rounded-full px-2 py-2.5 mb-1 w-max">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/edit.png"
}
width={14}
height={14}
className="w-4 h-full mr-1"
placeholder=""
/>
<span>{streamerInfo?.zone_moment_count}</span>
</div>
</div>
</div>
</div>
<div
className="flex flex-col items-center"
onClick={() =>
router.push("/share/" + streamerInfo?.streamer_ext?.mid)
}
>
<p className="text-base px-3 py-1 rounded-full bg-primary">
分享
</p>
</div>
</div>
<ul className="flex mt-8">
<li
className="flex flex-col items-center mr-4"
onClick={() =>
setMaskVisible({ visible: true, type: "weChat" })
}
>
<div className="w-9 h-9 flex items-center justify-center bg-[#1d1d1d71] rounded-full mb-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/images/wechat_bg.png"
}
width={32}
height={32}
className="w-4 h-full"
placeholder=""
/>
</div>
<p className="text-xs whitespace-nowrap">查看微信</p>
</li>
<li
className="flex flex-col items-center mr-6"
onClick={() =>
setMaskVisible({ visible: true, type: "ironFan" })
}
>
<div className="w-9 h-9 flex items-center justify-center bg-[#1d1d1d71] rounded-full mb-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/tiefen_bg.png"
}
width={32}
height={32}
className="w-4 h-full"
placeholder=""
/>
</div>
<p className="text-xs whitespace-nowrap">
{streamerInfo?.is_ironfanship_unlocked === 1
? "已是铁粉"
: "成为铁粉"}
</p>
<p className="text-[#ffffff54] text-[10px]">{`${parseInt(
streamerInfo?.expenditure / 100,
10
)}/${parseInt(streamerInfo?.ironfanship_price / 100, 10)}`}</p>
</li>
{!!streamerInfo?.is_superfanship_enabled && (
<li
className="flex flex-col items-center mr-6"
onClick={() => {
// console.log(
// "streamerInfo?.is_superfanship_unlocked === 1",
// streamerInfo?.is_superfanship_unlocked === 1
// );
streamerInfo?.is_superfanship_unlocked === 1
? setCurrentKey("chaofen")
: router.push(
"/webView/" +
encodeURIComponent(
"/zone/pay/" +
streamerInfo?.id +
"/h5_zone_superfanship/0" +
"?base=" +
encodeURIComponent(JSON.stringify(base))
)
);
}}
>
<div className="w-9 h-9 flex items-center justify-center bg-[#1d1d1d71] rounded-full mb-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/chaofen_bg.png"
}
width={32}
height={32}
className="w-4 h-full"
placeholder=""
/>
</div>
<p className="text-xs whitespace-nowrap">
{streamerInfo?.is_superfanship_unlocked === 1
? "尊贵超粉"
: "成为超粉"}
</p>
</li>
)}
<li
className="flex flex-col items-center mr-6"
onClick={() => {
router.push("/messageDetail");
}}
>
<div className="w-9 h-9 flex items-center justify-center bg-[#1d1d1d71] rounded-full mb-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/report_bg.png"
}
width={32}
height={32}
className="w-4 h-full"
placeholder=""
/>
</div>
<p className="text-xs whitespace-nowrap">举报</p>
</li>
{streamerInfo?.visitor_role === 3 && (
<li
onClick={() => router.push("visibleToOneselfSpacePosts")}
className="flex flex-col items-center"
>
<div className="w-9 h-9 flex items-center justify-center bg-[#1d1d1d71] rounded-full mb-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/review_fail_bg.png"
}
width={32}
height={32}
className="w-4 h-full"
placeholder=""
/>
</div>
<p className="text-xs whitespace-nowrap">审核未通过</p>
</li>
)}
</ul>
</div>
</div>
<FloatingPanel
anchors={anchors}
ref={scrollRef}
className="bg-deepBg"
style={{ height: "calc(100vh - 60px)" }}
>
<JumboTabs
onChange={(key) => setCurrentKey(key)}
activeKey={currentKey}
className="bg-deepBg pb-12"
>
{tabItems.map((it) => (
<JumboTabs.Tab
title={it.label}
key={it.key}
description={
currentKey == it.key && (
<div className="titlePinkLine relative w-full"></div>
)
}
destroyOnClose={true}
>
<div className="overflow-y-auto scrollbarBox_hidden px-1">
<List>
{loading && !postList.length && (
<>
<PostItemSkeleton />
<PostItemSkeleton />
<PostItemSkeleton />
<PostItemSkeleton />
</>
)}
{/* {!postList.length && !loading && (
<div
className={`flex flex-col items-center mt-20`}
style={{ height: `${scrollHeight}px` }}
>
<Empty type="nodata" />
</div>
)} */}
{postList.map((item, index) => (
<List.Item key={item.id + "_" + index} className="!p-0">
<PostItem
type="space"
data={item}
date={new Date(item.ct * 1000)}
/>
</List.Item>
))}
<InfiniteScroll loadMore={loadMore} hasMore={hasMore} />
</List>
</div>
</JumboTabs.Tab>
))}
</JumboTabs>
</FloatingPanel>
<div
className={`fixed bottom-[136px] right-4 z-[50] w-10 h-10 flex items-center justify-center bg-[#1d1d1d71] rounded-full text-white ${
loading && !offset ? "animate-spin" : ""
}`}
style={{ zIndex: 999 }}
>
<FontAwesomeIcon
icon={faRefresh}
style={{ maxWidth: "32px" }}
size="2xl"
// onClick={() => {
// router.refresh();
// }}
onClick={() => {
firstRequest();
}}
/>
</div>
{streamerInfo?.visitor_role != 3 && (
<ul className="flex justify-around mt-8 px-4 py-2 fixed bottom-0 z-[999] bg-deepBg w-full border-t-2 border-[#FFFFFF1A]">
<li
className="flex flex-col items-center"
onClick={() => setMaskVisible({ visible: true, type: "weChat" })}
>
<div className="w-9 h-9 flex items-center justify-center bg-[#1d1d1d71] rounded-full mb-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/images/wechat.png"
}
width={22}
height={22}
className="w-4 h-full"
placeholder=""
/>
</div>
<p className="text-xs">查看微信</p>
</li>
<li
className="flex flex-col items-center"
onClick={() => setMaskVisible({ visible: true, type: "ironFan" })}
>
<div className="w-9 h-9 flex items-center justify-center bg-[#1d1d1d71] rounded-full mb-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/tiefen.png"
}
width={22}
height={22}
className="w-4 h-full"
placeholder=""
/>
</div>
<p className="text-xs">
{streamerInfo?.is_ironfanship_unlocked === 1
? "已是铁粉"
: "成为铁粉"}
</p>
{/* <p className="text-[#ffffff54] text-[10px]">0/299</p> */}
</li>
{!!streamerInfo?.is_superfanship_enabled && (
<li
className="flex flex-col items-center"
onClick={() => {
streamerInfo?.is_superfanship_unlocked === 1
? setCurrentKey("chaofen")
: router.push(
"/webView/" +
encodeURIComponent(
"/zone/pay/" +
streamerInfo?.id +
"/h5_zone_superfanship/0" +
"?base=" +
encodeURIComponent(JSON.stringify(base))
)
);
}}
>
<div className="w-9 h-9 flex items-center justify-center bg-[#1d1d1d71] rounded-full mb-1">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
"/icons/chaofen.png"
}
width={22}
height={22}
className="w-4 h-full"
placeholder=""
/>
</div>
<p className="text-xs">
{streamerInfo?.is_superfanship_unlocked === 1
? "尊贵超粉"
: "成为超粉"}
</p>
</li>
)}
</ul>
)}
{maskVisible.type == "weChat" && (
<AddWeChat
visible={maskVisible.visible}
closeMask={(close) => setMaskVisible({ visible: false, type: "" })}
price={streamerInfo?.streamer_ext?.wechat_coin_price}
name={streamerInfo?.streamer_ext?.name}
streamerMid={streamerInfo?.streamer_ext?.mid}
avatar={streamerInfo?.streamer_ext?.avatar?.images[0]?.urls[0]}
streamerData={streamerInfo}
/>
)}
{maskVisible.type == "ironFan" && (
<SeeTiefen
visible={maskVisible.visible}
ironFanProgress={ironFanProgress}
expenditure={streamerInfo.expenditure}
ironfanship_price={streamerInfo.ironfanship_price}
closeMask={() => {
setMaskVisible({ visible: false, type: "" });
}}
handleClick={() => {
setCurrentKey("ironFan");
setMaskVisible({ visible: false, type: "" });
}}
/>
)}
<DefaultMask
title="当前空间正在退款中"
content="退款中空间不支持查看,请关注原支付渠道退款进度,退款后无法再次进入当前空间。"
visible={isRefundingModalVisible}
closeMask={() => {
setIsRefundingModalVisible(false);
}}
/>
</div>
{streamerInfo?.visitor_role === 3 && (
<div
// onClick={() => setIsCreatePostModalVisible(!isCreatePostModalVisible)}
className="fixed right-6 bottom-12"
style={{ zIndex: 999 }}
onClick={() => {
setCreatePostMask(true);
}}
>
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/createpost.png"
}
width={88}
height={88}
placeholder=""
/>
</div>
)}
<Popup
visible={createPostMask}
onMaskClick={() => {
setCreatePostMask(false);
}}
className="p-4"
bodyStyle={{
borderRadius: "16px",
width: "calc(100% - 48px)",
margin: "24px",
padding: "14px",
}}
>
<div className="flex justify-around items-center pt-4 pb-6">
<div
className="flex flex-col justify-center items-center"
onClick={() => {
setCreatePostMask(false);
router.push("createImagePost");
}}
>
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/image_post.png"
}
width={48}
height={48}
className="w-4 h-full"
placeholder=""
/>
<p className="mt-2">发图片</p>
</div>
<div
className="flex flex-col justify-center items-center"
onClick={() => {
setCreatePostMask(false);
router.push("createVideoPost");
}}
>
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/video_post.png"
}
width={48}
height={48}
className="w-4 h-full"
placeholder=""
/>
<p className="mt-2">发视频</p>
</div>
</div>
<p
className="pt-4 text-center border-t border-[#ffffff40]"
onClick={() => setCreatePostMask(false)}
>
取消
</p>
</Popup>
</div>
);
}