"use client"; import Link from "next/link"; import { LinkType } from "../_lib/data/linkType"; import { Link as _Link } from "../_lib/data/link"; import { useEffect, useMemo, useState } from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faArrowRight, faClock, faFire} from "@fortawesome/free-solid-svg-icons"; import { useAtom } from "jotai"; import { linkTypeAtom } from "../_lib/atom"; import Image from "next/image"; import clsx from "clsx"; const PICTURE_PREFIX = 'https://newuitab.oss-cn-hangzhou.aliyuncs.com/ai_upload/downloads/' export const LinkBlock = ({ val }: { val: _Link }) => { return <Link className="flex gap-x-2 bg-white rounded-lg py-4 px-2 cursor-pointer duration-150 hover:-translate-y-1 shadow-sm" href={val.articleId ? `/article/${val.articleId}` : val.link || ''} target="_blank"> <img src={val.logoLink.startsWith('http') ? val.logoLink : (PICTURE_PREFIX + val.logoLink)} className="w-[40px] h-[40px]"></img> <div className="flex-1 w-0 flex flex-col justify-between"> <span className=" font-bold text-ellipsis overflow-hidden whitespace-nowrap">{val.name}</span> <span className=" text-ellipsis overflow-hidden whitespace-nowrap text-[#665] text-xs" title={val.description}>{val.description}</span> </div> </Link> } export default function LinkListBox({ linkTypeList, linkList, showHot, showRecent }: { linkTypeList: LinkType[]; linkList: _Link[]; showHot: boolean; showRecent: boolean }) { const hotList = useMemo(() => linkList.filter((val, index) => val.isHot && index < 12), [linkList]) const recentList = useMemo(() => linkList.map(val => val).sort((a, b) => b.addTime - a.addTime).filter((_, idx) => idx < 12), [linkList]) const [currentId] = useAtom(linkTypeAtom) const [selectSubType, setSelectSubType] = useState<Map<string, string>>(new Map()) useEffect(() => { if (linkTypeList.length === 0) return for (let i = 0; i < linkTypeList.length; i++) { const item = linkTypeList[i]; console.log(item); if (item.subCategory?.length) { setSelectSubType(pre => { return new Map(pre.set(item._id, item.subCategory?.length ? item.subCategory[0] : '')); }) } } }, [linkTypeList, setSelectSubType]) useEffect(() => { if (currentId) { // 根据 targetId 查找对应的元素 const element = document.getElementById(currentId); if (element) { // 滚动到找到的元素位置 element.scrollIntoView({ behavior: 'smooth' }); } } }, [currentId]) return <div className="flex w-full flex-col gap-y-4"> { showHot && <div className="flex flex-col gap-y-2" > <div className="flex items-center text-[#555555] gap-x-2 text-xl"> <FontAwesomeIcon icon={faFire} className="text-red-500 "></FontAwesomeIcon> <span className="text-white bg-red-500/90 rounded-2xl px-3 py-1 text-[14px] font-bold">热门网站</span> </div> <div className=" grid grid-cols-3 lg:grid-cols-6 gap-4 "> { hotList.map(val => ( <LinkBlock val={val} key={val._id} /> )) } </div> </div> } { showRecent && <div className="flex flex-col gap-y-2" > <div className="flex items-center text-[#555555] gap-x-2 text-xl"> <FontAwesomeIcon icon={faClock} className="text-blue-500"></FontAwesomeIcon> <span className="text-white bg-blue-500/90 rounded-2xl px-3 py-1 text-[14px] font-bold">最新收录</span> </div> <div className=" grid grid-cols-3 lg:grid-cols-6 gap-4 "> { recentList.map(val => ( <LinkBlock val={val} key={val._id} /> )) } </div> </div> } { linkTypeList.map(item => ( <div className="flex flex-col gap-y-2" key={item._id} id={item._id}> <div className="flex items-center text-[#555555] gap-x-2 w-full text-xl relative"> <img src={item.icon as string} className="w-[30px] h-[30px] object-cover"></img> <span>{item.label}</span> { linkList.filter(val => val.type === item._id).length >= 42 && <Link href={"/detail/" + item._id} className="absolute cursor-pointer hover:text-[#333] right-1 text-[#666] flex gap-x-1 items-center text-[14px] "> 查看该分类下所有 <FontAwesomeIcon icon={faArrowRight}></FontAwesomeIcon> </Link> } </div> { item.subCategory && item.subCategory.length > 0 && <div className=" flex gap-x-3 text-[#666] py-2 text-[16px]"> { item.subCategory.map(subItem => ( <div key={subItem} onClick={() => { setSelectSubType(pre => { return new Map(pre.set(item._id, subItem)) }) }} className={clsx(" px-3 py-1 rounded-lg ", selectSubType.get(item._id) === subItem ? "text-white bg-orange-300" : "bg-[#f5f5f5] shadow hover:bg-orange-300/30 cursor-pointer" )}> {subItem} </div> )) } </div> } <div className=" grid grid-cols-3 lg:grid-cols-6 gap-4 "> { item.subCategory ? linkList.filter(val => val.type === item._id && val.subLinkType?.includes(selectSubType.get(item._id) || '-1')).filter((_, idx) => idx < 42).map(val => ( <LinkBlock val={val} key={val._id} /> )) : linkList.filter(val => val.type === item._id).filter((_, idx) => idx < 42).map(val => ( <LinkBlock val={val} key={val._id} /> )) } </div> </div> )) } </div> }