From b0c3834d317f440b4b647a9cefa580d33fc50b14 Mon Sep 17 00:00:00 2001 From: mackt <1033530438@qq.com> Date: Thu, 9 May 2024 17:06:33 +0800 Subject: [PATCH] =?UTF-8?q?update(Search):=201.=20=E6=90=9C=E7=B4=A2?= =?UTF-8?q?=E9=AB=98=E4=BA=AE=202.=20=E6=96=87=E6=9C=AC=E6=BA=A2=E5=87=BA?= =?UTF-8?q?=E7=9C=81=E7=95=A5=203.=20styles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Journal/MiniJournalCard.tsx | 16 +++++- .../Journal/MiniJournalCardList.tsx | 4 +- src/components/Search/Dropdown.tsx | 7 +-- src/components/Search/Search.tsx | 23 ++++---- src/components/Search/widget/Journal.tsx | 7 +-- src/components/Search/widget/Single.tsx | 8 +-- src/components/SongCard/SongCard.tsx | 53 ++++++++++++------- src/components/SongCard/SongCardList.tsx | 11 ++-- src/components/common/HighlightText.tsx | 29 ++++++++++ src/components/index.ts | 1 + 10 files changed, 117 insertions(+), 42 deletions(-) create mode 100644 src/components/common/HighlightText.tsx diff --git a/src/components/Journal/MiniJournalCard.tsx b/src/components/Journal/MiniJournalCard.tsx index ae24ab9..0a5a404 100644 --- a/src/components/Journal/MiniJournalCard.tsx +++ b/src/components/Journal/MiniJournalCard.tsx @@ -1,15 +1,19 @@ import Image from 'next/image'; import Link from 'next/link'; +import { HighlightText } from '@/components'; + export default function MiniJournalCard({ image, journalNo, title, + keyword, onClick, }: { image: string; journalNo: string; title: string; + keyword: string; onClick?: () => void; }) { return ( @@ -23,8 +27,16 @@ export default function MiniJournalCard({ className="w-162px h-100px rounded-3px group-hover:transform-scale-105 transition-transform-300" unoptimized /> -
{`vol${journalNo.toString().padStart(4, '0')}`}
-
{title}
+ + ); diff --git a/src/components/Journal/MiniJournalCardList.tsx b/src/components/Journal/MiniJournalCardList.tsx index d17ec17..ce999e2 100644 --- a/src/components/Journal/MiniJournalCardList.tsx +++ b/src/components/Journal/MiniJournalCardList.tsx @@ -2,11 +2,12 @@ import MiniJournalCard from './MiniJournalCard'; interface IProps { list: JournalInfo[]; + keyword: string; className?: string; onClick: () => void; } -export default function MiniJournalCardList({ list, className, onClick }: IProps) { +export default function MiniJournalCardList({ list, keyword, className, onClick }: IProps) { return (
{list.map((item) => ( @@ -15,6 +16,7 @@ export default function MiniJournalCardList({ list, className, onClick }: IProps image={item.image} journalNo={item.journalNo} title={item.title} + keyword={keyword} onClick={onClick} /> ))} diff --git a/src/components/Search/Dropdown.tsx b/src/components/Search/Dropdown.tsx index 17e47f0..4013ab1 100644 --- a/src/components/Search/Dropdown.tsx +++ b/src/components/Search/Dropdown.tsx @@ -5,12 +5,13 @@ import Single from './widget/Single'; interface IProps { journalData: JournalInfo[]; + keyword: string; songData: SongInfo[]; className?: string; onClose: () => void; } -export default function SearchDropdown({ journalData, songData, className, onClose }: IProps) { +export default function SearchDropdown({ journalData, keyword, songData, className, onClose }: IProps) { const haveData = journalData.length || songData.length; return ( @@ -20,8 +21,8 @@ export default function SearchDropdown({ journalData, songData, className, onClo > {haveData ? (
- {!!songData.length && } - {!!journalData.length && } + {!!songData.length && } + {!!journalData.length && }
) : ( diff --git a/src/components/Search/Search.tsx b/src/components/Search/Search.tsx index de752a9..f9553d6 100644 --- a/src/components/Search/Search.tsx +++ b/src/components/Search/Search.tsx @@ -14,18 +14,18 @@ interface IProps { } export default function Search({ className }: IProps) { - const [value, setValue] = useState(''); + const [keyword, setKeyword] = useState(''); const [journalData, setJournalData] = useState([]); const [songData, setSongData] = useState([]); const [showDropDown, setShowDropDown] = useState(false); const searchRef = useRef(null); - const handleInput: (value: string) => void = (value) => { - setShowDropDown(!!value.trim()); + const handleInput: (keyword: string) => void = (keyword) => { + setShowDropDown(!!keyword.trim()); - if (value.trim()) { - setValue(value); - handleSearch(value); + if (keyword.trim()) { + setKeyword(keyword); + handleSearch(keyword); } }; @@ -50,7 +50,7 @@ export default function Search({ className }: IProps) { // input 聚焦时,展示下拉框 const handleInputFocus = () => { - if (value.trim()) setShowDropDown(true); + if (keyword.trim()) setShowDropDown(true); }; const handleClickOutside = (e: Event) => { @@ -68,10 +68,15 @@ export default function Search({ className }: IProps) { return (
- handleInput(value), 200)} onFocus={handleInputFocus} /> + handleInput(keyword), 200)} onFocus={handleInputFocus} /> {showDropDown && ( - setShowDropDown(false)} /> + setShowDropDown(false)} + /> )}
); diff --git a/src/components/Search/widget/Journal.tsx b/src/components/Search/widget/Journal.tsx index 477cc40..d2aef19 100644 --- a/src/components/Search/widget/Journal.tsx +++ b/src/components/Search/widget/Journal.tsx @@ -2,15 +2,16 @@ import { MiniJournalCardList } from '@/components'; interface IProps { data: JournalInfo[]; + keyword: string; className?: string; onClose: () => void; } -export default function Journal({ data, className, onClose }: IProps) { +export default function Journal({ data, keyword, className, onClose }: IProps) { return (
-

期刊

- +

期刊

+
); } diff --git a/src/components/Search/widget/Single.tsx b/src/components/Search/widget/Single.tsx index b5a5c1c..def0f51 100644 --- a/src/components/Search/widget/Single.tsx +++ b/src/components/Search/widget/Single.tsx @@ -2,19 +2,21 @@ import { SongCardList } from '@/components'; interface IProps { data: SongInfo[]; + keyword: string; className?: string; } -export default function Single({ data, className }: IProps) { +export default function Single({ data, keyword, className }: IProps) { return (
-

单曲

+

单曲

); diff --git a/src/components/SongCard/SongCard.tsx b/src/components/SongCard/SongCard.tsx index 142b764..a292c9b 100644 --- a/src/components/SongCard/SongCard.tsx +++ b/src/components/SongCard/SongCard.tsx @@ -1,6 +1,6 @@ import Image from 'next/image'; -import { CollectButton, IconEqualizer } from '@/components'; +import { CollectButton, IconEqualizer, HighlightText } from '@/components'; interface Props extends SongInfo { /** 播放状态 */ @@ -9,36 +9,53 @@ interface Props extends SongInfo { showCollect: boolean; /** 显示均衡器效果 */ showEq: boolean; + keyword: string; onPlay: (id: string) => void; } -export default function SongCard({ playState, id, title, pic, artist, haveCollect, duration, showEq, onPlay }: Props) { +export default function SongCard({ + playState, + id, + title, + pic, + artist, + album, + showCollect, + haveCollect, + duration, + showEq, + keyword, + onPlay, +}: Props) { return (
onPlay(id)} > {/* left */} -
+
{/* 专辑封面 */} {title} + {/* 歌曲名称/歌手 */} -
-
- {title} -
-
- {artist} -
+
+ +
@@ -48,17 +65,17 @@ export default function SongCard({ playState, id, title, pic, artist, haveCollec {showEq && } {/* 音频时长 */} -

{duration || '00:00'}

+

{duration || '00:00'}

{/* 收藏按钮单曲 */} - { + {showCollect && ( - } + )}
); diff --git a/src/components/SongCard/SongCardList.tsx b/src/components/SongCard/SongCardList.tsx index 08781e2..b258371 100644 --- a/src/components/SongCard/SongCardList.tsx +++ b/src/components/SongCard/SongCardList.tsx @@ -16,6 +16,8 @@ interface Props { * playerCard: 播放器内 */ listInfo: { type: 'vol' | 'collectSingle' | 'playerCard'; id: string | null }; + // 高亮关键词 + keyword: string; /** * @description 点击单曲事件 * playList: 播放当前列表 @@ -23,8 +25,8 @@ interface Props { */ clickType?: 'playList' | 'playPush'; songList: SongInfo[]; - /** 收藏按钮的显示逻辑 always: 总是显示 playing: 播放时显示 */ - collectType?: 'always' | 'playing'; + /** 收藏按钮的展示逻辑 always: 总是展示 playing: 播放时展示; none: 不展示*/ + collectType?: 'always' | 'playing' | 'none'; className?: string; } @@ -32,6 +34,7 @@ export default function SongCardList({ listInfo, songList, className, + keyword, collectType = 'always', clickType = 'playList', }: Props) { @@ -113,7 +116,9 @@ export default function SongCardList({ playState={playState} showEq={item.id === audioId} onPlay={(audioId: string) => handlePlay(audioId)} - showCollect={collectType === 'always' || (collectType === 'playing' && item.id === audioId)} + keyword={keyword} + // showCollect={collectType === 'always' || (collectType === 'playing' && item.id === audioId)} + showCollect={collectType === 'always' || collectType === 'playing'} /> ))}
diff --git a/src/components/common/HighlightText.tsx b/src/components/common/HighlightText.tsx new file mode 100644 index 0000000..e6f2ce0 --- /dev/null +++ b/src/components/common/HighlightText.tsx @@ -0,0 +1,29 @@ +'use client'; + +import { useEffect, useState } from 'react'; + +interface Iprops { + text: string; + keyword: string; + className?: string; +} + +const HighlightText = ({ text, keyword, className }: Iprops) => { + // 使用useState钩子来存储处理后的文本 + const [highlightedText, setHighlightedText] = useState(text); + + useEffect(() => { + if (!keyword) return; + // 创建一个正则表达式,全局匹配并忽略大小写 + const regex = new RegExp(keyword, 'gi'); + // 使用replace方法替换所有匹配的关键字,并用span标签包裹起来 + const newText = text.replace(regex, `$&`); + // 更新状态以触发组件重新渲染 + setHighlightedText(newText); + }, []); // 仅在text或keyword变化时重新执行effect + + // 渲染带有高亮的文本 + return

; +}; + +export default HighlightText; diff --git a/src/components/index.ts b/src/components/index.ts index a3cfa6d..66fab27 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -64,3 +64,4 @@ export { default as QRCodeDialog } from './common/QRCodeDialog'; export { default as InfiniteScroller } from './common/InfiniteScroller'; export { default as Pagination } from './Pagination/Pagination'; export { default as Search } from './Search/Search'; +export { default as HighlightText } from './common/HighlightText';