588 lines
21 KiB
JavaScript
588 lines
21 KiB
JavaScript
"use client";
|
||
|
||
import React, { useEffect, useRef, useState } from "react";
|
||
import { Image, 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 * 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],
|
||
type: "video",
|
||
})),
|
||
...data?.streamer_ext?.album?.images.map((item) => ({
|
||
url: item.urls[0],
|
||
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",
|
||
});
|
||
};
|
||
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>
|
||
{get("account")?.mid != mid && (
|
||
<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>
|
||
)}
|
||
</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],
|
||
});
|
||
} else {
|
||
showPhotos(
|
||
topPhotos.filter((it) => it.type == "img"),
|
||
topPhotos
|
||
.filter((it) => it.type == "img")
|
||
.indexOf(photo)
|
||
);
|
||
}
|
||
}}
|
||
>
|
||
<Image
|
||
className="h-12 w-full"
|
||
fit="cover"
|
||
height={320}
|
||
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]">
|
||
<Image
|
||
className=""
|
||
width={98}
|
||
height={98}
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/play.png"
|
||
}
|
||
/>
|
||
</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>
|
||
<div className="w-5 h-5">
|
||
<Image
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/verification.png"
|
||
}
|
||
/>
|
||
</div>
|
||
</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">
|
||
<Image
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/info/ID.png"
|
||
}
|
||
width={14}
|
||
height={14}
|
||
className="w-4 h-full 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">
|
||
<Image
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/info/fan.png"
|
||
}
|
||
width={14}
|
||
height={14}
|
||
className="w-4 h-full 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 ? (
|
||
<Image
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/info/female.png"
|
||
}
|
||
width={14}
|
||
height={14}
|
||
className="w-4 h-full mr-1"
|
||
/>
|
||
) : (
|
||
<Image
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/info/male.png"
|
||
}
|
||
width={14}
|
||
height={14}
|
||
className="w-4 h-full 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">
|
||
<Image
|
||
width={14}
|
||
height={14}
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/info/height.png"
|
||
}
|
||
className="w-4 h-full 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">
|
||
<Image
|
||
width={14}
|
||
height={14}
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/info/weight.png"
|
||
}
|
||
className="w-4 h-full 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">
|
||
<Image
|
||
width={14}
|
||
height={14}
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/info/constellation.png"
|
||
}
|
||
className="w-4 h-full 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">
|
||
<Image
|
||
width={14}
|
||
height={14}
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/info/location.png"
|
||
}
|
||
className="w-4 h-full 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"
|
||
onClick={() => {
|
||
router.back();
|
||
}}
|
||
/>
|
||
</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"
|
||
>
|
||
<Image
|
||
width="20vw"
|
||
height="20vw"
|
||
className={`rounded mr-2 ${
|
||
spaceData?.visitor_role === 4 && "imageBlur"
|
||
}`}
|
||
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">
|
||
<Image
|
||
height={32}
|
||
width={32}
|
||
className="mr-2"
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/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">
|
||
<Image
|
||
height={32}
|
||
width={32}
|
||
className="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"
|
||
/> */}
|
||
<Image
|
||
height={24}
|
||
width={24}
|
||
className="mr-1"
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/icons/copy.png"
|
||
}
|
||
/>
|
||
<span className="whitespace-nowrap">复制</span>
|
||
</div>
|
||
<div className="flex items-center">
|
||
{/* <FontAwesomeIcon
|
||
icon={faAngleRight}
|
||
size="xl"
|
||
className="h-3 mr-1"
|
||
/> */}
|
||
<Image
|
||
height={24}
|
||
width={24}
|
||
className="mr-1"
|
||
src={
|
||
process.env.NEXT_PUBLIC_WEB_ASSETS_URL +
|
||
"/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>
|
||
);
|
||
}
|