tiefen_space_h5/app/search/page.js

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>
);
};