From 021fa171b559a2fce28c5b5dc97648d4a311dd31 Mon Sep 17 00:00:00 2001 From: master1lan <278457198@qq.com> Date: Sun, 8 Jan 2023 22:25:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=A7=86=E9=A2=91=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 18 ------ src/components/image/index.tsx | 11 ++-- src/components/masonry/index.tsx | 1 - src/main.tsx | 14 ++-- src/routers/layout/layout.module.less | 13 ++-- src/routers/layout/nav.tsx | 93 ++++++++++++++++++++------- src/routers/layout/tools.ts | 9 +++ src/routers/video/index.tsx | 2 + src/routers/video/masonry.tsx | 50 ++++++++++---- src/utils/faker/index.ts | 44 ------------- src/utils/fetch/index.ts | 31 +++++---- src/utils/time/index.ts | 2 +- vite.config.ts | 18 +++--- 13 files changed, 170 insertions(+), 136 deletions(-) delete mode 100644 src/App.tsx create mode 100644 src/routers/layout/tools.ts delete mode 100644 src/utils/faker/index.ts diff --git a/src/App.tsx b/src/App.tsx deleted file mode 100644 index a2e3776..0000000 --- a/src/App.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import Masonry from "@components/masonry"; -import { Link, Outlet } from "react-router-dom"; -import Image from "@components/image"; -export default function App() { - // return ; - const url = `https://images.pexels.com/photos/5702958/pexels-photo-5702958.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1`; - - return ( -
- {/* */} - {/* */} - 测试第一个跳转 - test to video - test to read - -
- ); -} diff --git a/src/components/image/index.tsx b/src/components/image/index.tsx index eb00eaa..180b1b0 100644 --- a/src/components/image/index.tsx +++ b/src/components/image/index.tsx @@ -82,8 +82,8 @@ export function ImageBasic({ }: Omit & { children?: ReactElement; }) { - const res = useLoading(url), - { isLoaded, success } = res, + const // res = useLoading(url), + // { isLoaded, success } = res, real_fallback_url = fallbackUrl || DefaultFallbackUrl; const once_callback = useCallback(Once(callback!!), []); return ( @@ -91,9 +91,12 @@ export function ImageBasic({ {({ inView, ref, entry }) => (
diff --git a/src/components/masonry/index.tsx b/src/components/masonry/index.tsx index 9395ec7..391b16a 100644 --- a/src/components/masonry/index.tsx +++ b/src/components/masonry/index.tsx @@ -1,7 +1,6 @@ import { FC, useState, useEffect, useCallback } from "react"; import { Masonry as Masonic_masonry } from "masonic"; import Image from "@components/image"; -import { FetchNewImages } from "@utils/faker/index"; import { SingleRun, concurrencyRequest } from "@utils/index"; import { fetchVideos } from "@utils/fetch"; import { nanoid } from "nanoid"; diff --git a/src/main.tsx b/src/main.tsx index 2c5c399..72d3cbf 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,14 +1,14 @@ -import React from "react"; +import React, { lazy, Suspense } from "react"; import ReactDOM from "react-dom/client"; import { createBrowserRouter, RouterProvider } from "react-router-dom"; import VideoPage from "./routers/video"; import "./index.less"; -import ReadPage from "./routers/read"; -import Layout from "./routers/layout"; -import PhotoPage from "./routers/photo"; -import ErrorPage from "./routers/error"; import "intersection-observer"; import "./normalize.css"; +const ReadPage = lazy(() => import("./routers/read")), + Layout = lazy(() => import("./routers/layout")), + PhotoPage = lazy(() => import("./routers/photo")), + ErrorPage = lazy(() => import("./routers/error")); const router = createBrowserRouter([ { path: "/", @@ -50,7 +50,9 @@ const router = createBrowserRouter([ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( // - + + + // ); diff --git a/src/routers/layout/layout.module.less b/src/routers/layout/layout.module.less index 2cdf1ce..9b18792 100644 --- a/src/routers/layout/layout.module.less +++ b/src/routers/layout/layout.module.less @@ -76,9 +76,7 @@ } } -::-webkit-scrollbar { - display: none; -} + .nav { position: relative; @@ -89,6 +87,11 @@ overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none; + + &::-webkit-scrollbar { + display: none; + } + @itemWidth: 80px; @itemMarginHalfWidth: 8px; @itemMarginHalfHeight: 4px; @@ -140,6 +143,4 @@ z-index: 1; cursor: pointer; } -} - -//todo 写好header \ No newline at end of file +} \ No newline at end of file diff --git a/src/routers/layout/nav.tsx b/src/routers/layout/nav.tsx index 7964b08..36b1961 100644 --- a/src/routers/layout/nav.tsx +++ b/src/routers/layout/nav.tsx @@ -22,12 +22,11 @@ import { nanoid } from "nanoid"; import styles from "./layout.module.less"; import { FC, useState, useEffect, useMemo, memo } from "react"; import { Pick } from "@utils/index"; - +//todo 拆分组件 +//todo 修改文件夹 export default function Header_Nav() { //todo 这里在loacalstorage中查找 const [navLists, setLists] = useState(nav_tag_list); - //最后一个span是否可见 - const { ref, inView } = useInView({ initialInView: true }); //tag区是否展开 const [showed, setShow] = useState(false); //拖拽事件绑定 @@ -86,29 +85,41 @@ export default function Header_Nav() { data-showed={showed} > {ComRes} - -
setShow((showed) => !showed)} - style={{ - display: inView ? "none" : "flex", - }} - > - -
+ setShow((show) => !show)} />
); } -const NavItem: FC = (props) => { +const NavInViewItem: FC<{ + handlerClick: React.MouseEventHandler; +}> = ({ handlerClick }) => { + //最后一个span是否可见 + const { ref, inView } = useInView({ initialInView: true }); + return ( + <> + +
+ +
+ + ); +}; + +const NavItem: FC = memo((props) => { const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id: props.id }); const style = { @@ -126,7 +137,7 @@ const NavItem: FC = (props) => { )} ); -}; +}); const NavRouterChipItem: FC> = memo((props) => ( @@ -162,8 +173,16 @@ type NavRouterItemType = { type: "router"; pathname: string; name: string; + cancelable: boolean; +}; +type NavQueryItemType = { + id: string; + type: "query"; + query: string; + queryType: "q" | "tname" | "copyright"; + queryString: string; + cancelable: boolean; }; -type NavQueryItemType = { id: string; type: "query"; query: string }; type NavListItemType = NavQueryItemType | NavRouterItemType; const nav_tag_list = [ @@ -180,49 +199,77 @@ const nav_tag_list = [ { type: "query", query: "所有二创", + queryType: "q", + queryString: "", }, { type: "query", query: "露早", + queryType: "q", + queryString: "露早", }, { type: "query", query: "柚恩", + queryType: "q", + queryString: "柚恩", }, { type: "query", query: "莞儿", + queryType: "q", + queryString: "莞儿", }, { type: "query", query: "米诺", + queryType: "q", + queryString: "米诺", }, { type: "query", query: "虞莫", + queryType: "q", + queryString: "虞莫", }, { type: "query", query: "动画分区", + queryType: "tname", + queryString: "animation", }, { type: "query", query: "音乐分区", + queryType: "tname", + queryString: "music", }, { type: "query", query: "舞蹈分区", + queryType: "tname", + queryString: "dance", }, { type: "query", query: "游戏分区", + queryType: "tname", + queryString: "delicacy", }, { type: "query", query: "鬼畜分区", + queryType: "tname", + queryString: "guichu", }, { type: "query", query: "其他分区", + queryType: "tname", + queryString: "other", }, -].map((item) => ({ ...item, id: nanoid(3) })) as NavListItemType[]; +].map((item) => ({ + ...item, + id: nanoid(3), + cancelable: false, +})) as NavListItemType[]; diff --git a/src/routers/layout/tools.ts b/src/routers/layout/tools.ts new file mode 100644 index 0000000..2d4691c --- /dev/null +++ b/src/routers/layout/tools.ts @@ -0,0 +1,9 @@ +export function getLocalStorage(searchName: string, defaultRes: T) { + if (!localStorage.getItem(searchName)) { + localStorage.setItem(searchName, JSON.stringify(defaultRes)); + } + return JSON.parse(localStorage.getItem(searchName) as string); +} +export function setLocalstorage(itemName: string, targetRes: unknown): void { + localStorage.setItem(itemName, JSON.stringify(targetRes)); +} diff --git a/src/routers/video/index.tsx b/src/routers/video/index.tsx index eb06d97..b2a6542 100644 --- a/src/routers/video/index.tsx +++ b/src/routers/video/index.tsx @@ -6,3 +6,5 @@ export default function VideoPage() { ); } + +//todo 添加上拉刷新 diff --git a/src/routers/video/masonry.tsx b/src/routers/video/masonry.tsx index c7368fe..91841f8 100644 --- a/src/routers/video/masonry.tsx +++ b/src/routers/video/masonry.tsx @@ -1,28 +1,39 @@ import { fetchVideos } from "@utils/fetch"; import { concurrencyRequest, Pick } from "@utils/index"; -import { useState, useEffect, FC } from "react"; +import { useState, useEffect, FC, memo } from "react"; import { VideoRouterImageCardType, VideoRouterMasonryType } from "./videotype"; import { getImageSize } from "@components/image/tool"; import Grid from "@mui/material/Unstable_Grid2"; import ImageShouldResizeProview from "@components/proview/imageSize"; import { VideoRouterImageCard } from "./masonryItem"; import { Skeleton } from "@mui/material"; +import { nanoid } from "nanoid"; /** * @description 该组件负责渲染视频图片的瀑布流 */ export default function VideoMasonry(props: any) { - const [lists, setLists] = useState([]); + const [lists, setLists] = useState< + (VideoRouterImageCardType & { id: string })[] + >([]); const [isLoading, setLoading] = useState(true); useEffect(() => { // 在内部定义fetchHandler,保证拿到的是同步的 - const fetchHandler = async () => { + const fetchHandler = async (page: number = 1, ...resProps: any[]) => { const res = await fetchVideos({ order: "view", - page: 1, + page, + ...resProps, }), data = res.data.result, - urls = data.map((item) => item.pic); - const imageSizelists = await concurrencyRequest(urls, getImageSize, 6); + url_pic = data.map( + (item) => `${item.pic}@672w_378h_1c_!web-search-common-cover` + ), + url_face = data.map((item) => item.face); + const imageSizelists = await concurrencyRequest( + [...url_pic, ...url_face], + getImageSize, + 10 + ); setLists((lists) => [ ...lists, ...data.map((item, index) => { @@ -45,7 +56,17 @@ export default function VideoMasonry(props: any) { "favorite", "face" ); - return itemRes; + if (index === data.length - 3) { + return { + ...itemRes, + id: nanoid(4), + observer: true, + callback: (inView: boolean) => { + fetchHandler(page + 1, ...resProps); + }, + }; + } + return { ...itemRes, id: nanoid(4) }; }), ]); }; @@ -64,10 +85,8 @@ export default function VideoMasonry(props: any) { xs: 4, }} > - {lists.map((item, index) => ( - - - + {lists.map((item) => ( + ))} {isLoading && } @@ -75,6 +94,13 @@ export default function VideoMasonry(props: any) { ); } +const MemoItems: FC = memo((props) => { + return ( + + + + ); +}); const LoadingSkeleton: FC<{ num: number }> = ({ num = 0 }) => { return ( @@ -115,4 +141,4 @@ const LoadingSkeleton: FC<{ num: number }> = ({ num = 0 }) => { ); }; -//todo:改成feed流 +//todo:修改获取数据的方式 diff --git a/src/utils/faker/index.ts b/src/utils/faker/index.ts deleted file mode 100644 index fdfd0e7..0000000 --- a/src/utils/faker/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { faker } from "@faker-js/faker"; -import { nanoid } from "nanoid"; -import { useMemo, useState } from "react"; - -const randomListImageUrls = [ - `https://images.pexels.com/photos/14840714/pexels-photo-14840714.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1`, - `https://images.pexels.com/photos/9493793/pexels-photo-9493793.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1`, - `https://images.pexels.com/photos/5702958/pexels-photo-5702958.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1`, - `https://images.pexels.com/photos/6605345/pexels-photo-6605345.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1`, - `https://images.pexels.com/photos/1314509/pexels-photo-1314509.jpeg?auto=compress&cs=tinysrgb&w=600`, - `https://images.pexels.com/photos/3254555/pexels-photo-3254555.jpeg?auto=compress&cs=tinysrgb&w=600`, -]; - -export function createRandomBlob() { - return { - // image: faker.image.imageUrl(640, 480, "cat", true), - image: - randomListImageUrls.find(() => Math.random() > 0.7) || - randomListImageUrls[0], - name: faker.name.fullName(), - id: nanoid(4), - }; -} - -export function useFakerImages(size: number = 10) { - const _list = useMemo(() => { - return Array.from({ length: size }, () => createRandomBlob()); - }, [size]); - return _list; -} -export function FetchNewImages(size: number = 10): Promise< - { - image: string; - name: string; - id: string; - }[] -> { - return new Promise((resolve, reject) => { - setTimeout(() => { - const arr = Array.from({ length: size }, () => createRandomBlob()); - resolve(arr); - }, 100 + Math.random() * 100); - }); -} diff --git a/src/utils/fetch/index.ts b/src/utils/fetch/index.ts index a18238c..5a62104 100644 --- a/src/utils/fetch/index.ts +++ b/src/utils/fetch/index.ts @@ -11,16 +11,23 @@ import { IFetchVideoParams, RFetchVideoRes } from "./fetchtype"; export function fetchVideos( params: IFetchVideoParams ): Promise { - return new Promise((resolve) => { - setTimeout(() => { - resolve(videoJson); - }, 1000); - }); - return fetch("/v1/video-interface/advanced-search?order=pubdate&page=1", { - method: "GET", - headers: { - "ocp-Apim-Subscription-Key": "3cc4284fbb864965a7a9ad0f28af8496", - origin: "https://portal.api.eoe.best", - }, - }).then((response) => response.json() as Promise); + // return new Promise((resolve) => { + // setTimeout(() => { + // resolve(videoJson); + // }, 1000); + // }); + return fetch( + `/v1/video-interface/advanced-search?order=${params.order}&page=${ + params.page + }©right=${params.copyright || 1}&q=${params.q || ""}${ + params.tname && `&tname=${params.tname}` + }`, + { + method: "GET", + headers: { + "ocp-Apim-Subscription-Key": "3cc4284fbb864965a7a9ad0f28af8496", + origin: "https://portal.api.eoe.best", + }, + } + ).then((response) => response.json() as Promise); } diff --git a/src/utils/time/index.ts b/src/utils/time/index.ts index 7b97e96..920c511 100644 --- a/src/utils/time/index.ts +++ b/src/utils/time/index.ts @@ -5,7 +5,7 @@ import "dayjs/locale/zh-cn"; dayJs.locale("zh-cn"); dayJs.extend(realtiveTime); dayJs.extend(duration); - +//todo 修改时间显示,1天前这种要改成具体的时间 export default function getrealtiveTime(time: number): string { return dayJs(time).fromNow(); } diff --git a/vite.config.ts b/vite.config.ts index 392e271..a804d36 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -18,15 +18,15 @@ export default defineConfig({ build: { target: "es2015", minify: "esbuild", - rollupOptions: { - output: { - manualChunks(id) { - if (id.includes("node_modules")) { - return "vendor"; - } - }, - }, - }, + // rollupOptions: { + // output: { + // manualChunks(id) { + // if (id.includes("node_modules")) { + // return "vendor"; + // } + // }, + // }, + // }, }, server: { proxy: {