Skip to content

Commit

Permalink
🏗️ refactor(custom): 手机端高级搜索完成,至此全部搜索初版完成
Browse files Browse the repository at this point in the history
ISSUES CLOSED: #20 #28
  • Loading branch information
master1lan committed Feb 28, 2023
1 parent aac18c5 commit deeebb4
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 92 deletions.
3 changes: 3 additions & 0 deletions src/routers/layout/search/pc/pc.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
transition: all 300ms ease;
font-size: 12px;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
max-width: 75px;
}

span+input {
Expand Down
8 changes: 6 additions & 2 deletions src/routers/layout/search/pc/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,18 @@ type AdvanceItemProps = {
const AdvanceSearchItem = forwardRef<HTMLInputElement, AdvanceItemProps>(
(props, ref) => {
const { inputRef, handerfocus } = useBackRef(ref);
const { focused } = useSearchFocus();
return (
<>
<div
className={`${pcStyles["SearchItem"]} ${pcStyles["itemPadding"]} ${pcStyles["item"]}`}
onClick={handerfocus}
>
<span>{props.title}</span>
<span>{focused ? props.title : inputRef.current?.value}</span>
<input
ref={inputRef}
autoComplete='off'
maxLength={20}
defaultValue={props.inputDefaultValue}
onKeyDown={(event) => {
if (event.key === "Enter") {
Expand All @@ -146,6 +148,7 @@ const AdvanceSearchLastItem = forwardRef<
AdvanceItemProps & { onSubmit: () => void }
>((props, ref) => {
const { inputRef, handerfocus } = useBackRef(ref);
const { focused } = useSearchFocus();
return (
<>
<div
Expand All @@ -155,10 +158,11 @@ const AdvanceSearchLastItem = forwardRef<
<div
className={`flex-grow ${pcStyles["itemPadding"]} ${pcStyles["item"]}`}
>
<span>{props.title}</span>
<span>{focused ? props.title : inputRef.current?.value}</span>
<input
ref={inputRef}
autoComplete='off'
maxLength={20}
defaultValue={props.inputDefaultValue}
onKeyDown={(event) => {
if (event.key === "Enter") {
Expand Down
161 changes: 91 additions & 70 deletions src/routers/layout/search/phone/item.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import SearchIcon from "@mui/icons-material/Search";
import { FC, forwardRef, useState } from "react";
import { useBackRef } from "../pc/hooks";
import { NameAndFaceUrlsType } from "./url";
type PhoneSearchItemProps = {
defaultOpen: boolean;
open: boolean;
onOpen?: () => void;
openTitle: string;
inputDefaultValue: string;
onCompleteSearch: (() => void) | false;
nextCallback: () => void;
closeTitle: string;
closeValue: string;
UrlLists: { label: string; url: string }[];
UrlLists: NameAndFaceUrlsType;
};

export const PhoneSearchItem = forwardRef<
Expand All @@ -17,91 +18,111 @@ export const PhoneSearchItem = forwardRef<
>((props, ref) => {
const {
closeTitle,
closeValue,
inputDefaultValue,
onCompleteSearch,
nextCallback,
UrlLists,
open,
onOpen,
openTitle,
} = props;
// todo 增加获取input值
const [open, setOpen] = useState(props.defaultOpen);
const isActive = (label: string) => label === inputDefaultValue;
const { inputRef } = useBackRef(ref);
const handlerImgClick = (label: string) => {
if (onCompleteSearch) {
inputRef.current!.value = label;
onCompleteSearch();
} else {
nextCallback();
}
const [inputvalue, setValue] = useState(inputDefaultValue);
const handerEnter = (callback?: Function) => {
callback && callback();
setTimeout(() => {
Promise.resolve().then(() => {
if (onCompleteSearch) {
onCompleteSearch();
} else {
nextCallback();
}
});
}, 0);
};
const handlerImgClick = (label: string) =>
handerEnter(() => setValue(() => label));
return (
<div>
{!open && (
<CloseItem
title={closeTitle}
value={closeValue}
onClick={setOpen.bind(null, true)}
/>
)}
{open && (
<div className='bg-white shadow-lg p-6 rounded-3xl font-semibold overflow-hidden'>
<div className='text-xl'>哪个标签?</div>
<div className='my-4 border rounded-2xl h-14 px-5 flex items-center'>
<SearchIcon />
<input
ref={inputRef}
className='self-stretch focus-within:outline-none pl-2 font-normal '
maxLength={20}
defaultValue={inputDefaultValue}
onKeyDown={(event) => {
if (event.key === "Enter") {
onCompleteSearch && onCompleteSearch();
}
}}
/>
</div>
<div className='flex gap-3 -mx-6 overflow-x-scroll snap-proximity snap-x no-scrollbar'>
{UrlLists.map((item, index) => (
<div
className={`${!index ? "ml-6" : ""} flex-shrink-0 h-40 w-32`}
onClick={handlerImgClick.bind(null, item.label)}
key={index}
>
<img
src={item.url}
width={128}
height={128}
className={`${
isActive(item.label) ? "border-black" : "border-gray-200"
} block border rounded-xl border-solid aspect-square`}
/>
<span
className={`${
isActive(item.label)
? "font-semibold text-gray-800"
: "font-normal text-gray-600"
} text-sm`}
>
{item.label}
</span>
</div>
))}
</div>
<div className={`${!open ? "block" : "hidden"}`}>
<CloseItem title={closeTitle} value={inputvalue} onClick={onOpen} />
</div>
<div
className={`${
open ? "block" : "hidden"
} bg-white shadow-lg p-6 rounded-3xl font-semibold overflow-hidden mb-3`}
>
<div className='text-xl'>{openTitle}</div>
<div className='my-4 border rounded-2xl h-14 px-5 flex items-center'>
<SearchIcon />
<input
ref={ref}
className='self-stretch focus-within:outline-none pl-2 font-normal '
maxLength={20}
value={inputvalue}
onChange={(event) => setValue(() => event.target.value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
handerEnter();
}
}}
/>
</div>
)}
<ImgGally
UrlLists={UrlLists}
onClick={handlerImgClick}
activeValue={inputvalue}
/>
</div>
</div>
);
});

const CloseItem: FC<{ title: string; value: string; onClick: () => void }> = ({
const ImgGally: FC<
Pick<PhoneSearchItemProps, "UrlLists"> & {
onClick: (value: string) => void;
activeValue: string;
}
> = ({ UrlLists, onClick, activeValue }) => {
const isActive = (label: string) => label === activeValue;
return (
<div className='flex gap-3 -mx-6 overflow-x-scroll snap-proximity snap-x no-scrollbar'>
{UrlLists.map((item, index) => (
<div
className={`${!index ? "ml-6" : ""} flex-shrink-0 h-40 w-32`}
onClick={onClick.bind(null, item.value)}
key={index}
>
<img
src={item.url}
width={128}
height={128}
className={`${
isActive(item.value) ? "border-black" : "border-gray-200"
} block border rounded-xl border-solid aspect-square`}
/>
<span
className={`${
isActive(item.value)
? "font-semibold text-gray-800"
: "font-normal text-gray-600"
} text-sm`}
>
{item.label}
</span>
</div>
))}
</div>
);
};

const CloseItem: FC<{ title: string; value: string; onClick?: () => void }> = ({
title,
value,
onClick,
}) => {
return (
<div
className='flex flex-row justify-between bg-white shadow-lg p-6 rounded-3xl text-sm font-semibold'
className='flex flex-row justify-between bg-white shadow-md p-6 rounded-3xl text-sm font-semibold mb-3'
onClick={onClick}
>
<p className='text-gray-600'>{title}</p>
Expand Down
66 changes: 52 additions & 14 deletions src/routers/layout/search/phone/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Modal, Tab, Tabs } from "@mui/material";
import { FC, useRef } from "react";
import SearchIcon from "@mui/icons-material/Search";
import { FC, useRef, useState } from "react";
import { useSearchMode } from "../pc/hooks";
import { PhoneSearchItem } from "./item";
import { idolNameAndFaceUrls } from "./url";
import { idolNameAndFaceUrls, phoneMoreNameAndFaceUrls } from "./url";
import { useURLParams } from "@utils/hooks/url";
import { useNavigate } from "react-router-dom";
type PhotoModalSearchProps = {
Expand All @@ -12,6 +11,7 @@ type PhotoModalSearchProps = {
};
export default function PhotoModalSearch(props: PhotoModalSearchProps) {
const { open, onClose } = props;
const { searchMode } = useSearchMode();
return (
<>
<Modal {...props}>
Expand All @@ -24,7 +24,8 @@ export default function PhotoModalSearch(props: PhotoModalSearchProps) {
</div>
{/* content */}
<div className='flex-grow mt-4 mx-3'>
<TagContentCom onClose={onClose} />
{searchMode === "搜索tag" && <TagContentCom onClose={onClose} />}
{searchMode === "搜索更多" && <MoreContentCom onClose={onClose} />}
</div>
</div>
</Modal>
Expand All @@ -39,32 +40,69 @@ const TagContentCom: FC<ModeComProps> = ({ onClose }) => {
const [tag] = useURLParams(["tag"]);
const navigate = useNavigate();
const handlerSubmit = () => {
//@ts-ignore
const value = inputRef.current!.getValue();
const value = inputRef.current!.value;
navigate(`/search?tag=${value}`);
onClose();
};
const { searchMode } = useSearchMode();
return (
<div
className={`transition-all duration-150 ease-in-out ${
searchMode == "搜索tag" ? "block" : "hidden"
}`}
>
<div className={`transition-all duration-150 ease-in-out `}>
<PhoneSearchItem
ref={inputRef}
defaultOpen={true}
openTitle={`哪个标签?`}
open={true}
inputDefaultValue={tag}
onCompleteSearch={handlerSubmit}
nextCallback={() => {}}
closeTitle='标签'
closeValue={tag}
UrlLists={idolNameAndFaceUrls}
/>
</div>
);
};

const MoreContentCom: FC<ModeComProps> = ({ onClose }) => {
const [tag, name] = useURLParams(["tag", "name"]);
const { searchMode } = useSearchMode();
const [activeLine, changeActiveLine] = useState<typeof searchMode>("搜索tag"),
handerChangeActiveLine = (name: typeof searchMode) =>
changeActiveLine(name);
const tagInputRef = useRef<HTMLInputElement>(null),
nameInputRef = useRef<HTMLInputElement>(null);
const navigate = useNavigate();
const handlerSubmit = () => {
const tag = tagInputRef.current!.value,
name = nameInputRef.current!.value;
console.log({ tag, name });
navigate(`/search?tag=${tag}&name=${name}`);
onClose();
};
return (
<div className={`transition-all duration-150 ease-in-out`}>
<PhoneSearchItem
openTitle={`哪个标签?`}
ref={tagInputRef}
open={activeLine === "搜索tag"}
onOpen={handerChangeActiveLine.bind(null, "搜索tag")}
inputDefaultValue={tag}
onCompleteSearch={false}
nextCallback={handerChangeActiveLine.bind(null, "搜索更多")}
closeTitle='标签'
UrlLists={idolNameAndFaceUrls}
/>
<PhoneSearchItem
openTitle={`谁的投稿?`}
ref={nameInputRef}
open={activeLine === "搜索更多"}
onOpen={handerChangeActiveLine.bind(null, "搜索更多")}
inputDefaultValue={name}
onCompleteSearch={handlerSubmit}
nextCallback={() => {}}
closeTitle='用户'
UrlLists={phoneMoreNameAndFaceUrls}
/>
</div>
);
};
// 选择栏
const SearchHeader = () => {
const { searchMode, handlerChangeSearchMode } = useSearchMode();
Expand Down
25 changes: 19 additions & 6 deletions src/routers/layout/search/phone/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,23 @@ export const luzaoFaceURL = `https://i0.hdslb.com/bfs/face/5d699ce6f66ce4770092b
export const wanerFaceURL = `https://i1.hdslb.com/bfs/face/4d36b041654ef91a0b2f7f34ca9ade33cdbf837e.jpg@240w_240h_1c_1s.webp`;
export const minuoFaceURl = `https://i2.hdslb.com/bfs/face/3da6145e81745cabd1f79b9c61772f884e783b7e.jpg@240w_240h_1c_1s.webp`;

export const idolNameAndFaceUrls: { label: string; url: string }[] = [
{ label: "露早", url: luzaoFaceURL },
{ label: "虞莫", url: yumoFaceURL },
{ label: "莞儿", url: wanerFaceURL },
{ label: "柚恩", url: youenFaceURL },
{ label: "米诺", url: minuoFaceURl },
export type NameAndFaceUrlsType = {
label: string;
url: string;
value: string;
}[];

export const idolNameAndFaceUrls: NameAndFaceUrlsType = [
{ label: "露早", url: luzaoFaceURL, value: "露早GOGO" },
{ label: "虞莫", url: yumoFaceURL, value: "虞莫MOMO" },
{ label: "莞儿", url: wanerFaceURL, value: "莞儿睡不醒" },
{ label: "柚恩", url: youenFaceURL, value: "柚恩不加糖" },
{ label: "米诺", url: minuoFaceURl, value: "米诺高分少女" },
];

export const lubozuFaceUrl = `https://i0.hdslb.com/bfs/face/4fb5beac7b6eff7981897176430df514b7201556.jpg@240w_240h_1c_1s.webp`;

export const phoneMoreNameAndFaceUrls: NameAndFaceUrlsType = [
{ label: "录播组", url: lubozuFaceUrl, value: "哎呀米诺录播组" },
...idolNameAndFaceUrls,
];

0 comments on commit deeebb4

Please sign in to comment.