This commit is contained in:
expdsn 2025-02-17 10:30:40 +08:00
parent f532a992e1
commit 2603adc802
10 changed files with 68 additions and 26 deletions

View File

@ -1,5 +1,6 @@
import SiderNav from "../_ui/SiderNav"; import SiderNav from "../_ui/SiderNav";
import { getLinkTypeList } from "../_lib/data/linkType"; import { getLinkTypeList } from "../_lib/data/linkType";
import HeaderNav from "../_ui/HeaderNav";
export default async function Layout({ children }: Readonly<{ children: React.ReactNode }>) { export default async function Layout({ children }: Readonly<{ children: React.ReactNode }>) {
@ -16,6 +17,8 @@ export default async function Layout({ children }: Readonly<{ children: React.Re
</div> </div>
</div> </div>
<HeaderNav></HeaderNav>
{children} {children}
</div> </div>

View File

@ -15,12 +15,8 @@ export default async function Page() {
<div className="flex min-h-full w-full font-[family-name:var(--font-geist-sans)] relative"> <div className="flex min-h-full w-full font-[family-name:var(--font-geist-sans)] relative">
<SiderNav linkList={linkTypeList} /> <SiderNav linkList={linkTypeList} />
<div className="w-full"> <div className="w-full">
<main className="flex-1 relative flex flex-col p-5 gap-y-4"> <main className="flex-1 relative flex flex-col p-5 gap-y-4">
{/* <HeaderNav></HeaderNav> */}
<Search></Search> <Search></Search>
{/* <PosterBox posterList={[]} /> */}
<LinkListBox linkList={linkList} linkTypeList={linkTypeList} showHot showRecent></LinkListBox> <LinkListBox linkList={linkList} linkTypeList={linkTypeList} showHot showRecent></LinkListBox>
</main> </main>
<Footer></Footer> <Footer></Footer>

View File

@ -0,0 +1,5 @@
export default function Page() {
return <div>
home
</div>
}

View File

@ -2,4 +2,3 @@ import { atom } from 'jotai';
// 定义一个简单的原子 // 定义一个简单的原子
export const linkTypeAtom = atom(''); export const linkTypeAtom = atom('');

View File

@ -1,5 +1,7 @@
"use server"; "use server";
import { ObjectId } from "mongodb";
import { verifySession } from "../dal";
import { getCollection } from "../mongodb"; import { getCollection } from "../mongodb";
export type SearchTypeItem = { export type SearchTypeItem = {
@ -37,7 +39,7 @@ export async function getSearchTypeList({ page = 1, pageSize = 9999 }: {
const list = await cursor.toArray(); const list = await cursor.toArray();
// 计算总数量 // 计算总数量
const total = (await collection.find<SearchTypeItem>({}).toArray()).length const total = await collection.countDocuments()
return { return {
total, total,
list list
@ -69,3 +71,11 @@ export async function getSearchWayList({ page = 1, pageSize = 9999 }: {
list list
} }
} }
export async function deleteSearchWay(id: string) {
const collection = await getCollection('search-type')
collection.deleteOne({
_id: new ObjectId(id)
})
}

View File

@ -1,11 +1,12 @@
import Link from "next/link";
export default function HeaderNav() { export default function HeaderNav() {
return ( return (
<header className="w-full gap-x-2 flex py-4 px-5 text-[14px]"> <header className="w-full gap-x-2 flex py-4 px-5 text-[14px]">
<div>AI应用集</div> <Link href={"/"}>AI合集</Link>
<div>AI应用集</div> <Link href={"/news"}>AI新闻</Link>
<div>AI应用集</div> <Link href={"/article"}>AI文章</Link>
<div>AI应用集</div>
<div>AI应用集</div>
</header> </header>
); );
} }

View File

@ -39,8 +39,8 @@ export default function LinkListBox({ linkTypeList, linkList, showHot, showRecen
{ {
showHot && <div className="flex flex-col gap-y-2" > showHot && <div className="flex flex-col gap-y-2" >
<div className="flex items-center text-[#555555] gap-x-2 text-xl"> <div className="flex items-center text-[#555555] gap-x-2 text-xl">
<FontAwesomeIcon icon={faFire} className="text-red-500"></FontAwesomeIcon> <FontAwesomeIcon icon={faFire} className="text-red-500 "></FontAwesomeIcon>
<span className="text-white bg-red-500/90 rounded-2xl px-3 text-[14px] font-bold"></span> <span className="text-white bg-red-500/90 rounded-2xl px-3 py-1 text-[14px] font-bold"></span>
</div> </div>
<div className=" grid grid-cols-3 lg:grid-cols-6 gap-4 "> <div className=" grid grid-cols-3 lg:grid-cols-6 gap-4 ">
{ {
@ -55,7 +55,7 @@ export default function LinkListBox({ linkTypeList, linkList, showHot, showRecen
showRecent && <div className="flex flex-col gap-y-2" > showRecent && <div className="flex flex-col gap-y-2" >
<div className="flex items-center text-[#555555] gap-x-2 text-xl"> <div className="flex items-center text-[#555555] gap-x-2 text-xl">
<FontAwesomeIcon icon={faClock} className="text-blue-500"></FontAwesomeIcon> <FontAwesomeIcon icon={faClock} className="text-blue-500"></FontAwesomeIcon>
<span className="text-white bg-blue-500/90 rounded-2xl px-3 text-[14px] font-bold"></span> <span className="text-white bg-blue-500/90 rounded-2xl px-3 py-1 text-[14px] font-bold"></span>
</div> </div>
<div className=" grid grid-cols-3 lg:grid-cols-6 gap-4 "> <div className=" grid grid-cols-3 lg:grid-cols-6 gap-4 ">

View File

@ -7,16 +7,30 @@ import { useEffect, useMemo, useState } from "react";
import Logo from "./Logo"; import Logo from "./Logo";
import { useRequest } from "ahooks"; import { useRequest } from "ahooks";
import { mRequest } from "../_lib/request"; import { mRequest } from "../_lib/request";
import { SearchTypeItem, SearchWayItemType } from "../_lib/data/search"; import { getSearchTypeList, getSearchWayList, SearchTypeItem, SearchWayItemType } from "../_lib/data/search";
import { doSearch } from "../_lib/utils"; import { doSearch } from "../_lib/utils";
import { log } from "node:console"; import { log } from "node:console";
const defaultSearchEngine: SearchWayItemType = {
_id: 'default',
label: '站内',
value: '/search?wd=%s',
fullName: '站内',
}
export default function Search() { export default function Search() {
const { data: searchWayList = [] } = useRequest(() => mRequest<{ list: SearchWayItemType[] }>('GET', '/api/search?page=1&pageSize=999').then(res => res.list)) const { data: searchWayList = [] } = useRequest(() => getSearchWayList({ page: 1, pageSize: 9999 }).then(res => [defaultSearchEngine, ...res.list]))
const { data: searchTypeList = [] } = useRequest(() => mRequest<{ list: SearchTypeItem[] }>('GET', '/api/searchType?page=1&pageSize=999').then(res => res.list)) const { data: searchTypeList = [] } = useRequest(() => getSearchTypeList({ page: 1, pageSize: 9999 }).then(res => res.list.map((val, idx) => {
if (idx === 0) {
return {
...val,
includes: ['default', ...val.includes]
}
}
return val
})))
const [selectKey, setSelectKey] = useState<string | null>(null) const [selectKey, setSelectKey] = useState<string | null>(null)
const [activeSearchKey, setActiveSearchKey] = useState<string | null>(null) const [activeSearchKey, setActiveSearchKey] = useState<string | null>(null)
const [inputStr, setInputStr] = useState('') const [inputStr, setInputStr] = useState('')
@ -49,25 +63,28 @@ export default function Search() {
} }
}, [selectKey]) }, [selectKey])
return ( return (
<div className="w-full flex justify-center flex-col items-center py-10 h-[500px]"> <div className="w-full flex justify-center flex-col items-center py-10 h-[300px]">
<div className="w-[200px]"> <div className="w-[200px]">
<Logo></Logo> <Logo></Logo>
</div> </div>
<div className="w-full lg:w-[800px] flex flex-col gap-y-2"> <div className="w-full lg:w-[800px] flex flex-col gap-y-2">
<div className="flex w-full justify-center gap-x-5 text-[#666666]"> <div className="flex w-full justify-center gap-x-5 text-[#666666]">
{ {
searchTypeList.map(item => ( searchTypeList.map((item, idx) => (
<div key={item._id} <div key={item._id}
onClick={() => { onClick={() => {
setSelectKey(item._id) setSelectKey(item._id)
}} }}
className={clsx(item._id === selectKey ? className={clsx(item._id === selectKey || (idx === 0 && selectKey === 'default') ?
"text-[#333]" : "text-[#999] cursor-pointer")}> "text-[#333]" : "text-[#999] cursor-pointer")}>
{item.name} {item.name}
</div> </div>
)) ))
} }
</div> </div>
<div className="w-full relative"> <div className="w-full relative">
<input <input
@ -83,10 +100,11 @@ export default function Search() {
setInputStr(e.target.value) setInputStr(e.target.value)
}} }}
placeholder={`${activeSearch?.label}搜索`} className="w-full bg-[#C4C2C6] px-4 h-[50px] rounded-3xl outline-none" /> placeholder={`${activeSearch?.label || ' '}搜索`} className="w-full bg-[#C4C2C6] px-4 h-[50px] rounded-3xl outline-none" />
<FontAwesomeIcon className="text-white absolute top-1/2 -translate-y-1/2 right-6 text-xl" icon={faSearch}></FontAwesomeIcon> <FontAwesomeIcon className="text-white absolute top-1/2 -translate-y-1/2 right-6 text-xl" icon={faSearch}></FontAwesomeIcon>
</div> </div>
<div className="w-full flex justify-center gap-x-4 "> <div className="w-full flex justify-center gap-x-4 ">
{ {
filterSeachList.map(item => ( filterSeachList.map(item => (
<div key={item._id} onClick={() => { <div key={item._id} onClick={() => {

View File

@ -3,13 +3,14 @@ import Link from "next/link";
import { LinkTypeItem } from "../_lib/types"; import { LinkTypeItem } from "../_lib/types";
import Logo from "./Logo"; import Logo from "./Logo";
import clsx from "clsx"; import clsx from "clsx";
import { usePathname } from "next/navigation"; import { usePathname, useRouter } from "next/navigation";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { linkTypeAtom } from "../_lib/atom"; import { linkTypeAtom } from "../_lib/atom";
import { LinkType } from "../_lib/data/linkType"; import { LinkType } from "../_lib/data/linkType";
export default function SiderNav({ linkList }: { linkList: LinkType[] }) { export default function SiderNav({ linkList }: { linkList: LinkType[] }) {
const pathname = usePathname() const pathname = usePathname()
const router = useRouter()
const [, setSelectType] = useAtom(linkTypeAtom) const [, setSelectType] = useAtom(linkTypeAtom)
return ( return (
<div className="w-[220px] flex flex-col gap-y-2 fixed left-0 top-0 h-[100vh] bg-[#F9F9F9]"> <div className="w-[220px] flex flex-col gap-y-2 fixed left-0 top-0 h-[100vh] bg-[#F9F9F9]">
@ -31,6 +32,10 @@ export default function SiderNav({ linkList }: { linkList: LinkType[] }) {
</Link> : </Link> :
<div className="cursor-pointer py-3 flex gap-x-2 items-center hover:bg-[#E0E0E0] rounded pl-3 text-[#515C6B] hover:text-[#5961F9] text-[14px]" key={item._id} <div className="cursor-pointer py-3 flex gap-x-2 items-center hover:bg-[#E0E0E0] rounded pl-3 text-[#515C6B] hover:text-[#5961F9] text-[14px]" key={item._id}
onClick={() => { onClick={() => {
if (pathname !== '/') {
router.replace('/')
}
setSelectType(item._id) setSelectType(item._id)
}} }}
> >

View File

@ -1,5 +1,5 @@
"use client"; "use client";
import { SearchTypeItem, SearchWayItemType } from "@/app/_lib/data/search"; import { deleteSearchWay, SearchTypeItem, SearchWayItemType } from "@/app/_lib/data/search";
import { mRequest } from "@/app/_lib/request"; import { mRequest } from "@/app/_lib/request";
import { useAntdTable } from "ahooks"; import { useAntdTable } from "ahooks";
import { Button, Card, Drawer, Form, Input, InputNumber, message, Popconfirm, Space, Table } from "antd"; import { Button, Card, Drawer, Form, Input, InputNumber, message, Popconfirm, Space, Table } from "antd";
@ -63,8 +63,12 @@ export default function Page() {
okText="确定" okText="确定"
cancelText="取消" cancelText="取消"
onConfirm={() => { onConfirm={() => {
mRequest('DELETE', `/api/search/${row._id}`).then(res => { // mRequest('DELETE', `/api/search/${row._id}`).then(res => {
// refresh()
// })
deleteSearchWay(row._id).then(res => {
refresh() refresh()
message.success('删除成功')
}) })
}} }}
> >
@ -243,6 +247,7 @@ export default function Page() {
await mRequest("POST", "/api/searchType", { await mRequest("POST", "/api/searchType", {
...res, ...res,
}) })
} }
refreshTypeList() refreshTypeList()
setSelectedType(undefined) setSelectedType(undefined)