tiefen_space_h5/app/search/page.js

292 lines
9.5 KiB
JavaScript
Raw Normal View History

2024-06-25 20:18:37 +08:00
"use client";
import React, { useEffect, useRef, useState } from "react";
import { Input, List, DotLoading, Toast, Image } from "antd-mobile";
2024-06-25 20:18:37 +08:00
import { useRouter } from "next/navigation";
2024-07-06 11:05:19 +08:00
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleLeft } from "@fortawesome/free-solid-svg-icons";
2024-07-22 16:07:41 +08:00
import requireAPI from "@/utils/requireAPI";
2024-07-06 11:05:19 +08:00
import { debounce } from "@/utils/tools";
import Empty from "@/components/Empty";
const newDebounce = debounce(function (fn) {
fn && fn();
}, 500);
2024-06-25 20:18:37 +08:00
export default function Search() {
const router = useRouter();
2024-08-05 13:10:33 +08:00
const inputRef = useRef();
2024-06-25 20:18:37 +08:00
// 获取屏幕高度
// const scrollHeight = 600;
const [searchValue, setSearchValue] = useState("");
2024-07-06 11:05:19 +08:00
const [loading, setLoading] = useState(false);
const [streamers, setStreamers] = useState([]);
2024-07-08 20:07:36 +08:00
// const [zones, setZones] = useState([]);
2024-08-05 13:10:33 +08:00
useEffect(() => {
inputRef.current?.focus();
}, []);
2024-07-06 11:05:19 +08:00
const isNumeric = (str) => {
return /^\d+$/.test(str);
};
const getResult = async (value) => {
2024-08-05 18:59:30 +08:00
// console.log("searchValue", value);
2024-07-06 11:05:19 +08:00
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);
2024-07-22 16:07:41 +08:00
const data = await requireAPI("POST", api, {
2024-07-06 11:05:19 +08:00
body: {
...querryParams,
offset: 0,
limit: 20,
},
});
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
return;
}
// if (!ignore) {
2024-07-08 20:07:36 +08:00
// const zonesData = data.data.list.filter((item) => item.zones.length > 0);
2024-07-06 11:05:19 +08:00
setStreamers(data.data.list);
2024-07-08 20:07:36 +08:00
// setZones(zonesData);
2024-07-06 11:05:19 +08:00
// }
setLoading(false);
} catch (error) {
console.error(error);
}
};
2024-06-25 20:18:37 +08:00
return (
<div className="">
2024-07-08 20:07:36 +08:00
<div className="flex items-center p-4 sticky top-0 bg-black z-10">
2024-07-06 11:05:19 +08:00
<FontAwesomeIcon
icon={faAngleLeft}
size="xl"
className="mr-3"
onClick={() => {
2024-06-25 20:18:37 +08:00
router.back();
2024-07-06 11:05:19 +08:00
}}
/>
2024-06-25 20:18:37 +08:00
<div className="flex items-center w-full">
2024-07-06 11:05:19 +08:00
<div className="relative bg-[#FFFFFF1A] rounded-lg px-4 py-1 w-full">
2024-06-25 20:18:37 +08:00
<Input
placeholder="搜索Ta的昵称或id"
2024-08-05 13:10:33 +08:00
autoFocus={true}
2024-06-25 20:18:37 +08:00
value={searchValue}
2024-08-05 13:10:33 +08:00
ref={inputRef}
2024-08-05 17:24:27 +08:00
style={{
"--font-size": "16px",
}}
2024-06-25 20:18:37 +08:00
onChange={(val) => {
2024-07-06 11:05:19 +08:00
setSearchValue((old) => {
let test = (e) => {
if (val == "") {
setStreamers([]);
2024-07-08 20:07:36 +08:00
// setZones([]);
2024-07-06 11:05:19 +08:00
return;
}
getResult(val);
};
newDebounce(test);
return val;
});
2024-06-25 20:18:37 +08:00
}}
/>
2024-07-06 11:05:19 +08:00
<div className="absolute top-1/2 -translate-y-1/2 right-2">
{loading && <DotLoading />}
</div>
2024-06-25 20:18:37 +08:00
</div>
{searchValue && (
<p
className="text-base whitespace-no-wrap ml-2 text-primary font-bold"
2024-06-25 20:18:37 +08:00
onClick={() => {
setSearchValue("");
}}
>
清空
</p>
)}
</div>
</div>
<List className="px-4 overflow-y-auto scrollbarBox_hidden">
2024-07-06 11:05:19 +08:00
{!streamers.length && (
<div
className={`h-screen -mt-[57px] flex flex-col items-center justify-center`}
>
<Empty type="nodata" />
2024-06-25 20:18:37 +08:00
</div>
2024-07-06 11:05:19 +08:00
)}
2024-07-08 20:07:36 +08:00
<div>
{streamers?.filter((streamer) => streamer.zones.length > 0).length >
0 && (
2024-07-08 20:07:36 +08:00
<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}
2024-07-19 16:22:43 +08:00
link={`space/person_space_introduce/${item.mid}`}
2024-07-24 14:26:46 +08:00
search={searchValue}
/>
));
})()}
2024-07-08 20:07:36 +08:00
</div>
)}
{streamers.length > 0 && (
<div>
2024-07-19 16:22:43 +08:00
<p className="mt-2 mb-1 text-white text-xl font-medium">用户</p>
2024-07-08 20:07:36 +08:00
{streamers.map((item) => (
2024-07-24 14:26:46 +08:00
<ZoneItem data={item} key={item.id} link={`/profile/${item.mid}`} search={searchValue}/>
2024-07-08 20:07:36 +08:00
))}
2024-06-25 20:18:37 +08:00
</div>
2024-07-08 20:07:36 +08:00
)}
</div>
2024-06-25 20:18:37 +08:00
</List>
</div>
);
}
2024-07-08 20:07:36 +08:00
2024-07-24 14:26:46 +08:00
const ZoneItem = ({ data, showMore, link,search }) => {
2024-07-08 20:07:36 +08:00
const router = useRouter();
return (
<List.Item
className="!p-0"
2024-07-24 15:32:23 +08:00
onClick={() => {router.push(link)}}
2024-07-08 20:07:36 +08:00
key={data.id}
arrow={false}
>
{
<div>
<div
className="grid grid-cols-[2.5rem_100%] gap-2 items-center"
style={{ maxWidth: "calc(100vw - 2rem)" }}
>
2024-07-24 20:20:09 +08:00
<Image
className="flex-none w-10 h-10 rounded-full mr-2"
src={data?.avatar?.images[0]?.urls[0]}
width="2.5rem"
height="2.5rem"
alt=""
2024-07-24 20:20:09 +08:00
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>
2024-07-08 20:07:36 +08:00
</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}
2024-07-24 19:08:22 +08:00
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>
)}
2024-07-08 20:07:36 +08:00
</div>
}
2024-07-08 20:07:36 +08:00
</List.Item>
);
};