290 lines
9.4 KiB
JavaScript
290 lines
9.4 KiB
JavaScript
"use client";
|
|
|
|
import React, { useEffect, useRef, useState } from "react";
|
|
import { Input, List, DotLoading, Toast, Image } from "antd-mobile";
|
|
import { useRouter } from "next/navigation";
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
import { faAngleLeft } from "@fortawesome/free-solid-svg-icons";
|
|
import requireAPI from "@/utils/requireAPI";
|
|
import { debounce } from "@/utils/tools";
|
|
import Empty from "@/components/Empty";
|
|
const newDebounce = debounce(function (fn) {
|
|
fn && fn();
|
|
}, 500);
|
|
export default function Search() {
|
|
const router = useRouter();
|
|
const inputRef = useRef();
|
|
// 获取屏幕高度
|
|
// const scrollHeight = 600;
|
|
const [searchValue, setSearchValue] = useState("");
|
|
const [loading, setLoading] = useState(false);
|
|
const [streamers, setStreamers] = useState([]);
|
|
// const [zones, setZones] = useState([]);
|
|
useEffect(() => {
|
|
inputRef.current?.focus();
|
|
}, []);
|
|
|
|
const isNumeric = (str) => {
|
|
return /^\d+$/.test(str);
|
|
};
|
|
const getResult = async (value) => {
|
|
// console.log("searchValue", value);
|
|
const isSearchInt = isNumeric(value);
|
|
let api = "";
|
|
let querryParams = "";
|
|
if (isSearchInt) {
|
|
api = "/api/streamer/list_ext_fuzzily_by_user_id";
|
|
querryParams = { user_id: parseInt(value, 10) };
|
|
} else {
|
|
api = "/api/streamer/list_ext_fuzzily_by_name";
|
|
querryParams = { name: value };
|
|
}
|
|
try {
|
|
setLoading(true);
|
|
const data = await requireAPI("POST", api, {
|
|
body: {
|
|
...querryParams,
|
|
offset: 0,
|
|
limit: 20,
|
|
},
|
|
});
|
|
if (data.ret === -1) {
|
|
Toast.show({
|
|
icon: "fail",
|
|
content: data.msg,
|
|
position: "top",
|
|
});
|
|
return;
|
|
}
|
|
// if (!ignore) {
|
|
// const zonesData = data.data.list.filter((item) => item.zones.length > 0);
|
|
setStreamers(data.data.list);
|
|
// setZones(zonesData);
|
|
// }
|
|
setLoading(false);
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
};
|
|
return (
|
|
<div className="">
|
|
<div className="flex items-center p-4 sticky top-0 bg-black z-10">
|
|
<FontAwesomeIcon
|
|
icon={faAngleLeft}
|
|
size="xl"
|
|
className="mr-3"
|
|
onClick={() => {
|
|
router.back();
|
|
}}
|
|
/>
|
|
<div className="flex items-center w-full">
|
|
<div className="relative bg-[#FFFFFF1A] rounded-lg px-4 py-1 w-full">
|
|
<Input
|
|
placeholder="搜索Ta的昵称或id"
|
|
autoFocus={true}
|
|
value={searchValue}
|
|
ref={inputRef}
|
|
style={{
|
|
"--font-size": "16px",
|
|
}}
|
|
onChange={(val) => {
|
|
setSearchValue((old) => {
|
|
let test = (e) => {
|
|
if (val == "") {
|
|
setStreamers([]);
|
|
// setZones([]);
|
|
return;
|
|
}
|
|
getResult(val);
|
|
};
|
|
newDebounce(test);
|
|
return val;
|
|
});
|
|
}}
|
|
/>
|
|
<div className="absolute top-1/2 -translate-y-1/2 right-2">
|
|
{loading && <DotLoading />}
|
|
</div>
|
|
</div>
|
|
{searchValue && (
|
|
<p
|
|
className="text-base whitespace-no-wrap ml-2 text-primary font-bold"
|
|
onClick={() => {
|
|
setSearchValue("");
|
|
}}
|
|
>
|
|
清空
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<List className="px-4 overflow-y-auto scrollbarBox_hidden">
|
|
{!streamers.length && (
|
|
<div
|
|
className={`h-screen -mt-[57px] flex flex-col items-center justify-center`}
|
|
>
|
|
<Empty type="nodata" />
|
|
</div>
|
|
)}
|
|
<div>
|
|
{streamers?.filter((streamer) => streamer.zones.length > 0).length >
|
|
0 && (
|
|
<div>
|
|
<p className="mt-2 mb-1 text-white text-xl font-medium">空间</p>
|
|
{(() => {
|
|
let arr = streamers?.filter(
|
|
(streamer) => streamer.zones.length > 0
|
|
);
|
|
return arr?.map((item) => (
|
|
<ZoneItem
|
|
data={item}
|
|
key={item.id}
|
|
showMore={arr.length === 1}
|
|
link={`space/person_space_introduce/${item.mid}`}
|
|
search={searchValue}
|
|
/>
|
|
));
|
|
})()}
|
|
</div>
|
|
)}
|
|
{streamers.length > 0 && (
|
|
<div>
|
|
<p className="mt-2 mb-1 text-white text-xl font-medium">用户</p>
|
|
{streamers.map((item) => (
|
|
<ZoneItem data={item} key={item.id} link={`/profile/${item.mid}`} search={searchValue}/>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</List>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const ZoneItem = ({ data, showMore, link,search }) => {
|
|
const router = useRouter();
|
|
return (
|
|
<List.Item
|
|
className="!p-0"
|
|
onClick={() => {router.push(link)}}
|
|
key={data.id}
|
|
arrow={false}
|
|
>
|
|
{
|
|
<div>
|
|
<div
|
|
className="grid grid-cols-[2.5rem_100%] gap-2 items-center"
|
|
style={{ maxWidth: "calc(100vw - 2rem)" }}
|
|
>
|
|
<Image
|
|
className="flex-none w-10 h-10 rounded-full mr-2"
|
|
src={data?.avatar?.images[0]?.urls[0]}
|
|
alt=""
|
|
fit="cover"
|
|
/>
|
|
<div className="flex-1">
|
|
<div className="flex items-center">
|
|
<span className="text-md mr-2 text-base text-white font-medium">
|
|
{data?.name}
|
|
</span>
|
|
<span className="py-0.5 px-2 ml-1 bg-[#FFFFFF1A] rounded-full text-white text-xs font-medium">
|
|
ID {data.user_id}
|
|
</span>
|
|
</div>
|
|
<p className="text-sm text-[#FFFFFF80] pr-16 overflow-hidden whitespace-nowrap text-ellipsis">
|
|
{data?.bio}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
{showMore && (
|
|
<div className="bg-[#FFFFFF1A] rounded-xl mt-2 p-2">
|
|
<p className="text-[#FFFFFF80] text-sm py-4">
|
|
Ta的动态·
|
|
{data?.zones[0].zone_moment_count > 99
|
|
? "99+"
|
|
: data?.zones[0].zone_moment_count}
|
|
{data?.zones[0].image_count > 0 &&
|
|
` | 图片·${
|
|
data?.zones[0].image_count > 99
|
|
? "99+"
|
|
: data?.zones[0].image_count
|
|
}`}
|
|
{data?.zones[0].video_count > 0 &&
|
|
` | 视频·${
|
|
data?.zones[0].video_count > 99
|
|
? "99+"
|
|
: data?.zones[0].video_count
|
|
}`}
|
|
</p>
|
|
<div className="grid grid-cols-[auto_120px] gap-2 grid-rows-1 w-full">
|
|
<div
|
|
className="relative w-mfull h-full"
|
|
// onClick={() => {
|
|
// if (item.type == "video") {
|
|
// handleShowVideo(item);
|
|
// } else {
|
|
// showPhotos(photos, index);
|
|
// }
|
|
// }}
|
|
>
|
|
<Image
|
|
// lazy={true}
|
|
placeholder={
|
|
<div className="w-full h-full bg-[#1d1d1d] rounded"></div>
|
|
}
|
|
width="100%"
|
|
height="100%"
|
|
className={`rounded-xl max-w-full`}
|
|
fit="cover"
|
|
src={data?.shorts?.videos[0]?.cover_urls[0]}
|
|
/>
|
|
{
|
|
<div className="absolute top-0 w-full h-full rounded-xl flex justify-center items-center bg-[#33333348]">
|
|
<Image
|
|
className=""
|
|
width={98}
|
|
height={98}
|
|
src={process.env.NEXT_PUBLIC_WEB_ASSETS_URL+"/icons/play.png"}
|
|
placeholder=""
|
|
/>
|
|
</div>
|
|
}
|
|
</div>
|
|
<div className="h-full grid grid-rows-3 gap-2">
|
|
<Image
|
|
// lazy={true}
|
|
placeholder={
|
|
<div className="w-full h-full bg-[#1d1d1d] rounded"></div>
|
|
}
|
|
width={120}
|
|
height={120}
|
|
className={`rounded-xl max-w-full`}
|
|
fit="cover"
|
|
src={data?.cover?.images[0]?.urls[0]}
|
|
/>
|
|
{data.album.images.map((_item, index) => {
|
|
if (index > 1) return;
|
|
return (
|
|
<Image
|
|
// lazy={true}
|
|
placeholder={
|
|
<div className="w-full h-full bg-[#1d1d1d] rounded"></div>
|
|
}
|
|
width={120}
|
|
height={120}
|
|
className={`rounded-xl max-w-full`}
|
|
fit="cover"
|
|
src={_item?.urls[0]}
|
|
/>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
}
|
|
</List.Item>
|
|
);
|
|
};
|