tiefen_space_h5/app/profile/[mid]/page.js

540 lines
19 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useEffect, useRef, useState, useMemo } from "react";
import { Swiper, Divider, Popover, Toast } from "antd-mobile";
import { useRouter, useParams } from "next/navigation";
import Link from "next/link";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faAngleLeft,
faAngleRight,
faEllipsisVertical,
faWarning,
faCircleMinus,
} from "@fortawesome/free-solid-svg-icons";
import requireAPI from "@/utils/requireAPI";
import AddWeChat from "@/components/AddWeChat";
import { handleFollow, checkRelation, handleBlock } from "@/api/public";
import { getStreamerDetailInfo } from "@/api/space";
import { get } from "@/utils/storeInfo";
import { handleShowVideo } from "@/utils/tools/handleFuns";
import clipboard from "copy-to-clipboard";
import ImagesMask from "@/components/ImagesMask";
import OwnImage from "@/components/OwnImage";
import OwnIcon from "@/components/OwnIcon";
// import * as Clipboard from "expo-clipboard";
export default function PersonSpace() {
const { mid } = useParams();
const router = useRouter();
const [streamerInfo, setStreamerInfo] = useState(null);
const [spaceData, setSpaceData] = useState(null);
const [loading, setLoading] = useState(false);
const [visible, setVisible] = useState(false);
const [isFollow, setIsFollow] = useState(false);
const [topPhotos, setTopPhotos] = useState([]);
const [account, setAccount] = useState([]);
const currentIndex = useRef();
const imagesMaskRef = useRef(null);
// 获取屏幕高度
// const scrollHeight = 600;
useEffect(() => {
handleGetStreamerInfo();
getSpaceData();
getRelationData();
const account = get("account");
setAccount(account);
}, []);
const showPhotos = (photos, index) => {
currentIndex.current = index;
imagesMaskRef.current.show(photos, index, streamerInfo);
};
const handleGetStreamerInfo = async () => {
try {
setLoading(true);
const data = await getStreamerDetailInfo(Number(mid));
setStreamerInfo({
...data,
});
const photosArr = [
...data?.streamer_ext?.cover?.images?.map((item) => ({
url: item.urls[0],
id: item.id,
type: "video",
})),
...data?.streamer_ext?.album?.images.map((item) => ({
url: item.urls[0],
id: item.id,
type: "img",
})),
];
// console.log("photosArr", photosArr);
setTopPhotos(photosArr);
setLoading(false);
} catch (error) {
// console.error(error);
}
};
const getSpaceData = async () => {
try {
const data = await requireAPI("POST", "/api/zone/list_by_mid", {
body: {
mid: Number(mid),
},
});
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
return;
}
setSpaceData(data.data.list[0]);
} catch (error) {
// console.error(error);
}
};
const getRelationData = async () => {
const account = get("account");
const subMid = account.mid;
const objMid = Number(mid);
const temIsFollowed = await checkRelation(subMid, objMid, 0);
setIsFollow(temIsFollowed);
};
//保存内容到剪贴板
const copy = (_data) => {
// console.log("_data", _data);
clipboard(_data);
Toast.show({
icon: "success",
content: "已复制到剪贴板",
position: "top",
});
};
const toolPopover = useMemo(() => {
return (
<Popover
stopPropagation={["click", "touchstart"]}
destroyOnHide={true}
style={{ "--background": "#1E1C29" }}
content={
<ul>
<li
onClick={async () => {
const account = await get("account");
const subMid = account.mid;
const objMid = mid;
handleBlock(subMid, Number(mid));
}}
>
<FontAwesomeIcon
icon={faCircleMinus}
// size="xl"
color="#f87171"
className="mr-4"
/>
<span>拉黑</span>
</li>
<hr className="border-[#ffffff2b] my-1" />
<li
onClick={() => {
router.push("/messageDetail");
}}
>
<FontAwesomeIcon
icon={faWarning}
// size="xl"
color="#3B69B8"
className="mr-4"
/>
<span>举报</span>
</li>
</ul>
}
trigger="click"
placement="left"
>
<div className="w-[36px] flex justify-center">
<FontAwesomeIcon
icon={faEllipsisVertical}
size="xl"
style={{ maxWidth: "5px" }}
/>
</div>
</Popover>
);
}, [account]);
return (
<div className="h-screen overflow-x-hidden overflow-y-auto">
<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>
{toolPopover}
</div>
{/* 内容 */}
<div className="overflow-y-auto">
<div className="min-h-[60px]">
{!!topPhotos.length && (
<Swiper
autoplay
loop
indicatorProps={{
style: {
"--dot-color": "#FF669E30",
"--active-dot-color": "#FF669E",
},
}}
>
{topPhotos.map((photo, index) => (
<Swiper.Item key={index}>
<div
className="relative min-w-full max-w-[100vw]"
key={index}
onClick={() => {
if (photo.type == "video") {
handleShowVideo({
url: streamerInfo?.streamer_ext?.shorts?.videos[0]
?.cover_urls[0],
mp4: streamerInfo?.streamer_ext?.shorts?.videos[0]
?.urls[0],
w: streamerInfo?.streamer_ext?.shorts?.videos[0]
?.cover_w,
h: streamerInfo?.streamer_ext?.shorts?.videos[0]
?.cover_h,
});
} else {
showPhotos(
topPhotos.filter((it) => it.type == "img"),
topPhotos
.filter((it) => it.type == "img")
.indexOf(photo)
);
}
}}
>
<OwnImage
className="h-[320px] w-full"
fit="cover"
src={photo?.url}
// onClick={() => {
// Toast.show(`你点击了卡片 ${index + 1}`);
// }}
/>
{photo.type == "video" && (
<div className="absolute top-0 w-full h-full flex justify-center items-center bg-[#33333348]">
<OwnIcon
src="/icons/play.png"
className="w-[98px] h-[98px]"
/>
</div>
)}
</div>
</Swiper.Item>
))}
</Swiper>
)}
</div>
<div className="p-4 pb-24">
<div>
<div className="mb-2">
<div className="flex items-center mb-2">
<p className="text-2xl mr-2">
{streamerInfo?.streamer_ext?.name}
</p>
<OwnIcon src="/icons/verification.png" className="w-5 h-5" />
</div>
<ul className="flex">
{streamerInfo?.streamer_ext?.tag?.map((item, index) => (
<li
key={index}
className="rounded-md bg-primary mr-2 px-2 py-1 text-xs mb-1"
>
{item}
</li>
))}
</ul>
</div>
<div>
<ul className="flex mb-1 flex-wrap">
<li className="h-4 flex items-center text-xs bg-[#FFFFFF1A] rounded-full px-2 py-2.5 mb-1 mr-1">
<OwnIcon
src="/icons/info/ID.png"
className="w-[14px] h-[14px]"
outClassName="mr-1"
/>
<span>{streamerInfo?.streamer_ext?.user_id}</span>
</li>
<li className="h-4 flex items-center text-xs bg-[#FFFFFF1A] rounded-full px-2 py-2.5 mb-1 mr-1">
<OwnIcon
src="/icons/info/fan.png"
className="w-[14px] h-[14px]"
outClassName="mr-1"
/>
<span className="text-white text-xs font-medium ml-0.5">
{`全网粉丝 : ${streamerInfo?.streamer_ext?.fans || 0}`}
</span>
</li>
{streamerInfo?.streamer_ext?.age && (
<li className="h-4 flex items-center text-xs bg-[#FFFFFF1A] rounded-full px-2 py-2.5 mb-1 mr-1">
{streamerInfo?.streamer_ext?.gender === 1 ? (
<OwnIcon
src="/icons/info/female.png"
className="w-[14px] h-[14px]"
outClassName="mr-1"
/>
) : (
<OwnIcon
src="/icons/info/male.png"
className="w-[14px] h-[14px]"
outClassName="mr-1"
/>
)}
<span className="text-white text-xs font-medium ml-0.5">
{streamerInfo?.streamer_ext?.age}
</span>
</li>
)}
{streamerInfo?.streamer_ext?.height && (
<li className="h-4 flex items-center text-xs bg-[#FFFFFF1A] rounded-full px-2 py-2.5 mb-1 mr-1">
<OwnIcon
src="/icons/info/height.png"
className="w-[14px] h-[14px]"
outClassName="mr-1"
/>
<span className="text-white text-xs font-medium ml-0.5">
{`${streamerInfo?.streamer_ext?.height}cm`}
</span>
</li>
)}
{streamerInfo?.streamer_ext?.weight && (
<li className="h-4 flex items-center text-xs bg-[#FFFFFF1A] rounded-full px-2 py-2.5 mb-1 mr-1">
<OwnIcon
src="/icons/info/weight.png"
className="w-[14px] h-[14px]"
outClassName="mr-1"
/>
<span className="text-white text-xs font-medium ml-0.5">
{`${streamerInfo?.streamer_ext?.weight}kg`}
</span>
</li>
)}
{streamerInfo?.streamer_ext?.constellation && (
<li className="h-4 flex items-center text-xs bg-[#FFFFFF1A] rounded-full px-2 py-2.5 mb-1 mr-1">
<OwnIcon
src="/icons/info/constellation.png"
className="w-[14px] h-[14px]"
outClassName="mr-1"
/>
<span className="text-white text-xs font-medium ml-0.5">
{streamerInfo?.streamer_ext?.constellation}
</span>
</li>
)}
{streamerInfo?.streamer_ext?.city && (
<li className="h-4 flex items-center text-xs bg-[#FFFFFF1A] rounded-full px-2 py-2.5 mb-1 mr-1">
<OwnIcon
src="/icons/info/location.png"
className="w-[14px] h-[14px]"
outClassName="mr-1"
/>
<span className="text-white text-xs font-medium ml-0.5">
{streamerInfo?.streamer_ext?.city}
</span>
</li>
)}
</ul>
{streamerInfo?.streamer_ext?.bio && (
<div
className="whitespace-pre-wrap"
style={{ overflowWrap: "anywhere" }}
>
<span className="text-[#ffffff88]">个性签名</span>
{streamerInfo?.streamer_ext?.bio}
</div>
)}
</div>
</div>
{spaceData && !!spaceData?.previews?.images?.length && (
<>
<Divider />
<div>
<div
onClick={() =>
router.push(
spaceData?.visitor_role === 4
? `/space/person_space_introduce/${mid}`
: `/space/${mid}`
)
}
>
<div className="flex justify-between items-center mb-2">
<span className="font-bold text-base">空间动态</span>
<div className="h-4 text-xs text-[#ffffff88]">
<span className="mr-2">
查看{spaceData?.zone_moment_count}
</span>
<FontAwesomeIcon
icon={faAngleRight}
size="xl"
style={{ maxWidth: "12px" }}
className="h-4"
/>
</div>
</div>
<div className="flex ">
{spaceData?.previews?.images
?.slice(0, 4)
.map((item, index) => (
<div
key={item.id}
className="w-20 h-20 overflow-hidden rounded mr-1"
>
<OwnImage
className={`w-[20vw] h-[20vw] ${
spaceData?.visitor_role === 4 && "imageBlur"
}`}
rounded="rounded"
outClassName="mr-2"
fit="cover"
src={item.urls[0]}
/>
</div>
))}
</div>
</div>
</div>
</>
)}
<>
<Divider />
<div>
<p className="font-bold mb-2 text-base">来这找我玩</p>
<ul>
<li className="flex justify-between border-[1.5px] border-[#ffffff43] rounded-xl p-2 mb-2">
<div className="flex justify-between items-center">
<OwnIcon
className="w-[32px] h-[32px]"
outClassName="mr-2"
src="/images/platform_wechat.png"
/>
<div className="text-base">
<span>微信</span>
<span
className="text-[#3B69B8]"
onClick={() => setVisible(true)}
>
点击查看
</span>
</div>
</div>
</li>
{streamerInfo?.streamer_ext?.platforms?.map((item) => (
<li
key={item.id}
className="grid gap-1 justify-between border-[1.5px] border-[#ffffff43] rounded-xl p-2"
style={{ gridTemplateColumns: "calc(100% - 130px) 130px" }}
>
<div className="flex items-center">
<OwnImage
className="w-[32px] h-[32px]"
outClassName="mr-2"
src={item?.icon.images[0].urls[0]}
/>
<div className="text-base max-w-28 truncate">
{item?.link_name}{item?.nickname}
</div>
</div>
<div className="flex justify-between text-sm">
<div
className="flex items-center"
onClick={() => {
copy(item.url);
}}
>
{/* <FontAwesomeIcon
icon={faCopy}
size="xl"
className="h-3 mr-1"
/> */}
<OwnIcon
className="w-[24px] h-[24px]"
outClassName="mr-1"
src="/icons/copy.png"
/>
<span className="whitespace-nowrap">复制</span>
</div>
<div className="flex items-center">
{/* <FontAwesomeIcon
icon={faAngleRight}
size="xl"
className="h-3 mr-1"
/> */}
<OwnIcon
className="w-[24px] h-[24px]"
outClassName="mr-1"
src="/icons/goto.png"
/>
<Link href={item?.url} className="whitespace-nowrap">
前往
</Link>
</div>
</div>
</li>
))}
</ul>
</div>
</>
</div>
<div className="flex justify-between items-center px-4 py-4 fixed bottom-0 bg-deepBg w-full border-t-2 border-[#FFFFFF1A]">
<div
className="text-base bg-[#FFFFFF1A] py-2 px-6 rounded-full whitespace-nowrap"
onClick={() => handleFollow(isFollow, Number(mid), setIsFollow)}
>
{isFollow ? "已关注" : "关注"}
</div>
<div
className="text-base bg-[#FFFFFF1A] py-2 px-6 rounded-full whitespace-nowrap"
onClick={() =>
router.push(
"/messageDetail?mid=" + streamerInfo?.streamer_ext?.mid
)
}
>
私聊
</div>
<div
className="bg-primary px-10 py-2 text-base rounded-full whitespace-nowrap"
onClick={() => setVisible(true)}
>
添加微信
</div>
</div>
</div>
<AddWeChat
visible={visible}
closeMask={setVisible}
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}
/>
<ImagesMask ref={imagesMaskRef} />
</div>
);
}