From c4f8e4ed91029d47a552e14a77c33d9f02319478 Mon Sep 17 00:00:00 2001 From: master1lan <278457198@qq.com> Date: Sat, 25 Feb 2023 14:47:48 +0800 Subject: [PATCH] =?UTF-8?q?:wheelchair:=20perf(custom):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=99=AE=E9=80=9A=E6=90=9C=E7=B4=A2=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 目前距离1.0版本还需要对sider页面的tag选择修改、大屏下tag栏展示布局修改、添加次高级搜索等 --- src/routers/layout/routernav/index.tsx | 19 +++++-- src/routers/layout/search/index.tsx | 37 ++----------- src/routers/search/index.tsx | 66 +++++++++++++++++++---- src/routers/search/select.tsx | 72 ++++++++++++++++++++++++++ src/routers/search/tool.ts | 31 +++++++++++ src/utils/fetch/fetchtype.ts | 3 +- src/utils/hooks/url.ts | 5 ++ 7 files changed, 183 insertions(+), 50 deletions(-) create mode 100644 src/routers/search/select.tsx create mode 100644 src/routers/search/tool.ts create mode 100644 src/utils/hooks/url.ts diff --git a/src/routers/layout/routernav/index.tsx b/src/routers/layout/routernav/index.tsx index e5d1d5b..4308fed 100644 --- a/src/routers/layout/routernav/index.tsx +++ b/src/routers/layout/routernav/index.tsx @@ -54,11 +54,20 @@ type DrawerHrefItemType = { }[]; } & Pick; -const DrawerNavItem: FC> = ({ title }) => ( - - - -); +const DrawerNavItem: FC> = ({ title }) => { + const shouldShow = ["/", "/video", "/photo"].includes( + window.location.pathname + ); + return ( + <> + {shouldShow && ( + + + + )} + + ); +}; const DrawerHrefLink: FC> = ( props diff --git a/src/routers/layout/search/index.tsx b/src/routers/layout/search/index.tsx index fc390fd..e0f24d5 100644 --- a/src/routers/layout/search/index.tsx +++ b/src/routers/layout/search/index.tsx @@ -1,9 +1,10 @@ import SearchSharpIcon from "@mui/icons-material/SearchSharp"; -import { Form, useNavigate } from "react-router-dom"; +import { Form, useLocation, useNavigate } from "react-router-dom"; import styles from "./search.module.less"; import { useSearchFocus } from "@components/proview/searchFocus"; import { Flipped } from "react-flip-toolkit"; import SearchIcon from "@mui/icons-material/Search"; +import { useURLParams } from "@utils/hooks/url"; // todo 增加高级搜索以及手机端的搜索 export default function Search() { const navigate = useNavigate(); @@ -11,6 +12,7 @@ export default function Search() { const value = (document.getElementById("q") as HTMLInputElement).value; navigate(`/search?tag=${value}`); }; + const [tag] = useURLParams(["tag"]); return ( <>
{ if (event.key === "Enter") { handlerSubmit(); @@ -39,35 +42,3 @@ export default function Search() { ); } - -function Search_1() { - const { focused, bind } = useSearchFocus(); - return ( - <> - -
-
-
- -
-
- -
-
-
-
- - ); -} diff --git a/src/routers/search/index.tsx b/src/routers/search/index.tsx index d8ef118..3791d89 100644 --- a/src/routers/search/index.tsx +++ b/src/routers/search/index.tsx @@ -3,10 +3,15 @@ import { fetchVideohandler, PickVideoRouterImageCardType, } from "@routers/video/tools"; +import { useChangeLoading } from "@store/loading"; import { nanoid } from "nanoid"; +import { useEffect, useState } from "react"; import { useLoaderData } from "react-router-dom"; import { useSearchShowState } from "./hooks"; - +import { VideoListType } from "../video/masonry"; +import SelectNav from "./select"; +import { videoOrderType } from "@utils/fetch/fetchtype"; +import { OrderArr } from "./tool"; type LoaderType = { request: { url: string; @@ -18,17 +23,56 @@ type LoaderReturnType = UnPromisify>; export async function loader({ request }: LoaderType) { const url = new URL(request.url), tag = url.searchParams.get("tag"); - const data = await fetchVideohandler(1, { order: "score", q: `tag.${tag}` }); - return { data }; + let order = url.searchParams.get("order") as videoOrderType; + if (!OrderArr.includes(order)) { + order = "score"; + } + return [tag, order] as const; } export default function SearchPage() { - const { data } = useLoaderData() as LoaderReturnType, - filterData = data.map((item) => ({ - ...PickVideoRouterImageCardType(item), - id: nanoid(4), - })); - const { loading, isEmpty } = useSearchShowState(filterData), - propsObj = { loading, isEmpty, data: filterData }; - return ; + const loaderData = useLoaderData() as LoaderReturnType, + [tag, order] = loaderData; + const [lists, setLists] = useState([]); + const { handerChangeLoading } = useChangeLoading("searchIsloading"); + useEffect(() => { + setLists([]); + handerChangeLoading(true); + function handlerSetList( + datas: UnPromisify>, + nextPage: number + ) { + setLists((lists) => [ + ...lists, + ...datas.map((item, index) => { + const itemRes = PickVideoRouterImageCardType(item); + if (index === datas.length - 5) { + return { + ...itemRes, + id: nanoid(4), + observer: true, + callback: (inView: boolean) => fetchHandler(nextPage), + }; + } + return { ...itemRes, id: nanoid(4) }; + }), + ]); + } + const fetchHandler = async (page: number = 1) => { + const data = await fetchVideohandler(page, { + order, + q: `tag.${tag}`, + }); + handlerSetList(data, page + 1); + }; + fetchHandler(1).then(() => handerChangeLoading(false)); + }, loaderData); + const { loading, isEmpty } = useSearchShowState(lists), + propsObj = { loading, isEmpty, data: lists }; + return ( +
+ + +
+ ); } diff --git a/src/routers/search/select.tsx b/src/routers/search/select.tsx new file mode 100644 index 0000000..e4383a0 --- /dev/null +++ b/src/routers/search/select.tsx @@ -0,0 +1,72 @@ +import { videoOrderType } from "@utils/fetch/fetchtype"; +import { nanoid } from "nanoid"; +import { FC } from "react"; +import { useNavigate } from "react-router-dom"; +import { OrderArr, returnReplacedParmasURl } from "./tool"; +import { useURLParams } from "@utils/hooks/url"; + +export default function SelectNav() { + const navigate = useNavigate(), + handlerCilck = (queryString: videoOrderType) => { + const replacedUrl = returnReplacedParmasURl([ + { parmas: "order", replace: queryString }, + ]), + newQuerySrting = new URL(replacedUrl).search; + navigate(`/search${newQuerySrting}`); + }; + return ( +
+ {Search_Nav.map((item) => ( + + ))} +
+ ); +} + +const SearchNavItem: FC<{ + onClick: () => void; + label: string; + queryString: videoOrderType; +}> = ({ label, onClick, queryString }) => { + const [order] = useURLParams(["order"]), + isCurOrder = OrderArr.includes(order as videoOrderType) + ? order === queryString + : queryString === "score"; + return ( +
+ {label} +
+ ); +}; + +type searchNavType = { + id: string; + label: "综合排序" | "最多播放" | "最新发表"; + queryString: videoOrderType; +}; +const Search_Nav: searchNavType[] = [ + { + id: nanoid(4), + label: "综合排序", + queryString: "score", + }, + { + id: nanoid(4), + label: "最多播放", + queryString: "view", + }, + { + id: nanoid(4), + label: "最新发表", + queryString: "pubdate", + }, +]; diff --git a/src/routers/search/tool.ts b/src/routers/search/tool.ts new file mode 100644 index 0000000..e54ef24 --- /dev/null +++ b/src/routers/search/tool.ts @@ -0,0 +1,31 @@ +import { videoOrderType } from "@utils/fetch/fetchtype"; + +function ParseQueryString(queryString: string) { + const regExp = /([^&=]+)=([\w\W]*?)(&|$)/g; + let result = null, + ret: { [key: string]: string } = {}; + while ((result = regExp.exec(queryString)) != null) { + ret[result[1]] = result[2]; + } + return ret; +} +export const parseURL = (url = window.location.href) => { + const objUrl = new URL(url), + params = objUrl.search.slice(1); + return ParseQueryString(params); +}; + +export const returnReplacedParmasURl = ( + input: { parmas: string; replace: string }[] +) => { + const originUrl = window.location.href, + paramsObj = parseURL(originUrl); + input.forEach(({ parmas, replace }) => (paramsObj[parmas] = replace)); + return originUrl.replace( + window.location.search, + `?${Object.entries(paramsObj) + .map(([key, value]) => `${key}=${value}`) + .join("&")}` + ); +}; +export const OrderArr: videoOrderType[] = ["pubdate", "score", "view"]; diff --git a/src/utils/fetch/fetchtype.ts b/src/utils/fetch/fetchtype.ts index 6d05df3..d5ab7fe 100644 --- a/src/utils/fetch/fetchtype.ts +++ b/src/utils/fetch/fetchtype.ts @@ -1,3 +1,4 @@ +export type videoOrderType = "pubdate" | "view" | "score"; /** *@description video接口的请求参数类型 */ @@ -7,7 +8,7 @@ export interface IFetchVideoParams { * pubdate为最新发布排序,view为最多播放排序,score为最高得分排序 * @example pubdate | view | score */ - order: "pubdate" | "view" | "score"; + order: videoOrderType; /** * @description 分页,每页返回20个;从1开始,自然数递增 * @example 1 diff --git a/src/utils/hooks/url.ts b/src/utils/hooks/url.ts new file mode 100644 index 0000000..96c9c61 --- /dev/null +++ b/src/utils/hooks/url.ts @@ -0,0 +1,5 @@ +export const useURLParams = (searchList: string[]) => { + const originURl = window.location.href; + const url = new URL(originURl); + return searchList.map((item) => url.searchParams.get(item) || ""); +};