From e3f98298ea34cc24c37217a9eb8d744ccfb7e574 Mon Sep 17 00:00:00 2001 From: master1lan <278457198@qq.com> Date: Wed, 11 Jan 2023 14:04:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0tag=E6=A0=8F=E4=B8=AA?= =?UTF-8?q?=E6=80=A7=E5=8C=96=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routers/layout/nav/index.tsx | 125 ++-------------- src/routers/layout/nav/tools.ts | 184 ++++++++++++++++++++++++ src/routers/layout/tools.ts | 7 +- src/routers/video/item/icon.tsx | 15 ++ src/routers/video/item/item.module.less | 26 ++-- src/routers/video/item/videoinfo.tsx | 30 ++-- vite.config.ts | 23 +-- 7 files changed, 258 insertions(+), 152 deletions(-) create mode 100644 src/routers/layout/nav/tools.ts diff --git a/src/routers/layout/nav/index.tsx b/src/routers/layout/nav/index.tsx index 66726ee..342b523 100644 --- a/src/routers/layout/nav/index.tsx +++ b/src/routers/layout/nav/index.tsx @@ -18,16 +18,21 @@ import { restrictToHorizontalAxis, restrictToParentElement, } from "@dnd-kit/modifiers"; -import { nanoid } from "nanoid"; import styles from "./nav.module.less"; import { FC, useState, useEffect, useMemo, memo } from "react"; import { Pick } from "@utils/index"; import { Flipped, Flipper } from "react-flip-toolkit"; +import { + NavListItemType, + NavRouterItemType, + NavQueryItemType, + useNavList, +} from "./tools"; +import { setLocalstorage } from "../tools"; //todo 拆分组件 -//todo 修改文件夹 export default function Header_Nav() { //todo 这里在loacalstorage中查找 - const [navLists, setLists] = useState(nav_tag_list); + const [navLists, setLists] = useNavList(); //tag区是否展开 const [showed, setShow] = useState(false); //拖拽事件绑定 @@ -52,9 +57,11 @@ export default function Header_Nav() { const { active, over } = event; if (over && active.id !== over.id) { setLists((items) => { - const oldIndex = items.findIndex((item) => item.id === active.id); - const newIndex = items.findIndex((item) => item.id === over.id); - return arrayMove(items, oldIndex, newIndex); + const oldIndex = items.findIndex((item) => item.id === active.id), + newIndex = items.findIndex((item) => item.id === over.id), + newLists = arrayMove(items, oldIndex, newIndex); + setLocalstorage("navTagLists", newLists); + return newLists; }); } } @@ -179,109 +186,3 @@ const NavTagChipItem: FC> = memo((props) => { ); }); //todo:修复展示更多栏的bug - -type NavRouterItemType = { - id: string; - 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 NavListItemType = NavQueryItemType | NavRouterItemType; - -const nav_tag_list = [ - { - type: "router", - pathname: "photo", - name: "图片", - }, - { - type: "router", - pathname: "video", - name: "视频", - }, - { - 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), - cancelable: false, -})) as NavListItemType[]; diff --git a/src/routers/layout/nav/tools.ts b/src/routers/layout/nav/tools.ts new file mode 100644 index 0000000..956d2ba --- /dev/null +++ b/src/routers/layout/nav/tools.ts @@ -0,0 +1,184 @@ +import { nanoid } from "nanoid"; +import { useMemo, useState } from "react"; +import { getLocalStorage } from "../tools"; +//todo 将数据加密 +export function useNavList(): [ + NavListItemType[], + React.Dispatch> +] { + const nav_ok_lists = useMemo(() => { + const local_lists = getLocalStorage("navTagLists", [] as NavListItemType[]); + if (PassNavList(local_lists)) { + return local_lists; + } + return nav_tag_list; + }, []); + const [navLists, setLists] = useState(nav_ok_lists); + return [navLists, setLists]; +} +// 判断类型 +const isNavRouterItemType = ( + input: NavListItemType +): input is NavRouterItemType => { + return input.type === "router"; +}; +//检查对象是否有相应属性且类型相同 +function checkPropertyType( + input: T, + property: string, + type: string +) { + return input.hasOwnProperty(property) && typeof input[property] === type; +} +//检测从localstorage提取的list是否满足条件 +function PassNavList(lists: NavListItemType[]) { + if ( + lists.length > 0 && + lists.every((item) => { + if ( + !allHasTypes.every(({ name, type }) => + checkPropertyType(item, name, type) + ) + ) { + return false; + } + if (isNavRouterItemType(item)) { + return routerHasTypes.every(({ name, type }) => + checkPropertyType(item, name, type) + ); + } else { + return queryHasTypes.every(({ name, type }) => + checkPropertyType(item, name, type) + ); + } + }) + ) { + return true; + } + return false; +} +//构造器 +const createHasType = (...rest: string[]) => { + return { name: rest[0], type: rest[1] || "string" }; +}; +//构造器 +const createHasTypeList = (inputList: string[][]) => + inputList.map((items) => createHasType(...items)); + +const allHasTypes = createHasTypeList([ + ["id"], + ["type"], + ["cancelable", "boolean"], + ]), + routerHasTypes = createHasTypeList([["pathname"], ["name"]]), + queryHasTypes = createHasTypeList([ + ["query"], + ["queryType"], + ["queryString"], + ]); + +export type NavRouterItemType = { + id: string; + type: "router"; + pathname: string; + name: string; + cancelable: boolean; +}; +export type NavQueryItemType = { + id: string; + type: "query"; + query: string; + queryType: "q" | "tname" | "copyright"; + queryString: string; + cancelable: boolean; +}; +export type NavListItemType = NavQueryItemType | NavRouterItemType; + +const nav_tag_list = [ + { + type: "router", + pathname: "photo", + name: "图片", + }, + { + type: "router", + pathname: "video", + name: "视频", + }, + { + 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), + cancelable: false, +})) as NavListItemType[]; diff --git a/src/routers/layout/tools.ts b/src/routers/layout/tools.ts index 2d4691c..ecbd197 100644 --- a/src/routers/layout/tools.ts +++ b/src/routers/layout/tools.ts @@ -1,9 +1,12 @@ -export function getLocalStorage(searchName: string, defaultRes: T) { +export function getLocalStorage(searchName: string, defaultRes: T): T { + if (!localStorage) { + return defaultRes; + } 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)); + if (localStorage) localStorage.setItem(itemName, JSON.stringify(targetRes)); } diff --git a/src/routers/video/item/icon.tsx b/src/routers/video/item/icon.tsx index 03350ab..b96d774 100644 --- a/src/routers/video/item/icon.tsx +++ b/src/routers/video/item/icon.tsx @@ -12,3 +12,18 @@ export const CoinIcon: FC<{ /> ); + +export const BiliIcon: FC<{ + height: number | string; + width?: number | string; + color?: string; +}> = ({ height, width = height, color = "#fff" }) => ( + + + +); diff --git a/src/routers/video/item/item.module.less b/src/routers/video/item/item.module.less index cca42b8..abe1594 100644 --- a/src/routers/video/item/item.module.less +++ b/src/routers/video/item/item.module.less @@ -3,9 +3,9 @@ display: flex; flex-flow: column nowrap; - &>:first-child { - flex: 1; - } + // &>:first-child { + // flex: 1; + // } .video-data { transition: opacity .3s linear; @@ -56,15 +56,14 @@ margin-top: 5px; } - &>p { + p { color: #18191c; - // font-size: 15px; cursor: pointer; transition: color .2s linear; - height: 40px; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; + vertical-align: baseline; text-overflow: ellipsis; line-break: anywhere; -webkit-line-clamp: 2; @@ -74,21 +73,18 @@ &:active { color: #00aeec; } - - &>a { - line-height: 1.25; - } } .video-up { display: flex; - align-items: stretch; + align-items: center; &>*:not(:first-child) { margin-left: 5px; } &-desc { + flex: 1; font-size: 13px; display: flex; flex-flow: column nowrap; @@ -96,19 +92,17 @@ cursor: default; &-data { + flex: 1; display: flex; flex-flow: row nowrap; - overflow: hidden; - text-overflow: ellipsis; + justify-content: space-evenly; &>span { white-space: nowrap; display: flex; align-items: center; - &:not(:first-of-type) { - margin-left: 10px; - } + } } diff --git a/src/routers/video/item/videoinfo.tsx b/src/routers/video/item/videoinfo.tsx index 824ceb0..49535ef 100644 --- a/src/routers/video/item/videoinfo.tsx +++ b/src/routers/video/item/videoinfo.tsx @@ -6,7 +6,7 @@ import getFixedNumber from "@utils/number"; import getrealtiveTime from "@utils/time"; import { FC } from "react"; import { VideoRouterImageCardType } from "../videotype"; -import { CoinIcon } from "./icon"; +import { BiliIcon, CoinIcon } from "./icon"; import styles from "./item.module.less"; export const VideoInfo: FC< Pick< @@ -25,18 +25,20 @@ export const VideoInfo: FC< const matchsmSize = useScreenMatchSize("sm"); return (
- - - {title} - - + + {title} +
- {matchsmSize && } + {matchsmSize ? ( + + ) : ( + + )}
{name} @@ -65,7 +67,11 @@ export const VideoInfo: FC< const DataP = styled("p")(({ theme }) => ({ fontSize: "15px", + height: "40px", + lineHeight: "20px", [theme.breakpoints.down("sm")]: { fontSize: "13px", + height: "30px", + lineHeight: "15px", }, })); diff --git a/vite.config.ts b/vite.config.ts index d68ac50..8d6a86c 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -19,16 +19,19 @@ export default defineConfig({ }, plugins: [ react(), - visualizer(), - viteCompression(), - legacy({ - // 设置目标浏览器,browserslist 配置语法 - targets: [ - "defaults", - "iOS >= 9, Android >= 4.4, last 2 versions, > 0.2%, not dead", - ], - }), - splitVendorChunkPlugin(), + { ...visualizer(), apply: "build" }, + { ...viteCompression(), apply: "build" }, + { + ...legacy({ + // 设置目标浏览器,browserslist 配置语法 + targets: [ + "defaults", + "iOS >= 9, Android >= 4.4, last 2 versions, > 0.2%, not dead", + ], + }), + apply: "build", + }, + { ...splitVendorChunkPlugin(), apply: "build" }, ], build: { // target: "es2015",