This commit is contained in:
expdsn 2025-02-17 18:17:12 +08:00
parent 2603adc802
commit f273be61d4
33 changed files with 79 additions and 165 deletions

View File

@ -2,7 +2,7 @@ import { getArticle } from "@/app/_lib/data/article"
import MarkdownView from "@/app/_ui/MarkdownView"
import { faArrowRight } from "@fortawesome/free-solid-svg-icons"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
import { MdEditor } from "md-editor-rt"
import Image from "next/image"
import Link from "next/link"
export default async function Page({ params }: { params: Promise<{ id: string }> }) {
@ -14,8 +14,8 @@ export default async function Page({ params }: { params: Promise<{ id: string }>
<div className="w-full h-full ">
<div className="flex gap-x-5">
<div className="p-4 rounded-lg">
<img src={article?.cover} className=" rounded-lg shadow object-cover w-[200px] h-[200px]">
</img>
<Image src={article?.cover} width={200} height={200} className=" rounded-lg shadow object-cover w-[200px] h-[200px]" alt="">
</Image>
</div>
<div className="flex flex-col gap-y-3 py-5">
<h1 className="text-2xl">{article.title}</h1>

View File

@ -1,7 +1,6 @@
"use server";
import { getCollection } from "../mongodb";
import { ReactNode } from "react";
export type Link = {
name: string;

View File

@ -1,7 +1,6 @@
"use server";
import { ObjectId } from "mongodb";
import { verifySession } from "../dal";
import { getCollection } from "../mongodb";
export type SearchTypeItem = {

View File

@ -1,5 +1,5 @@
// lib/mongodb.ts
import { MongoClient, Db } from 'mongodb';
import { MongoClient } from 'mongodb';
const uri = process.env.MONGODB_URI;

View File

@ -1,4 +1,3 @@
import { message } from "antd"
/**
*
@ -13,7 +12,7 @@ export async function mRequest<T>(
data?: any,
responseType: 'json' | 'text' | 'blob' = 'json'
): Promise<T> {
let options: RequestInit = {
const options: RequestInit = {
method: method,
headers: {
'Content-Type': 'application/json'

View File

@ -23,7 +23,7 @@ export async function decrypt(session: string | undefined = '') {
algorithms: ['HS256'],
})
return payload
} catch (error) {
} catch {
console.log('Failed to verify session')
}
}

View File

@ -1,20 +0,0 @@
const OSS = require('ali-oss');
// 创建OSS实例
const client = new OSS({
accessKeyId: 'LTAI5tNzopZHJFa2Q9vqr1u5',
accessKeySecret: 'qPu7fyft0KJ1l6SGqbS71IW0vDbRlr'
// 先不指定region和bucket以便后续查询
});
// 列出所有Bucket
client.listBuckets().then((result) => {
console.log('所有的Bucket:', result.buckets);
// 打印每个Bucket的信息
result.buckets.forEach((bucket) => {
console.log('Bucket名称:', bucket.name);
console.log('Bucket所在区域:', bucket.location);
});
}).catch((error) => {
console.error('列出Bucket失败:', error);
});

View File

@ -1,52 +0,0 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { LinkTypeItem } from "../_lib/types";
import { faPenClip, faThumbsUp } from "@fortawesome/free-solid-svg-icons";
const defaultLinkList = [
{
label: 'AI应用集',
icon: <FontAwesomeIcon icon={faThumbsUp} className="fa-fw text-blue-500" />,
href: '/ai-apps',
id: 1,
},
{
label: 'AI写作工具',
icon: <FontAwesomeIcon icon={faPenClip} className="fa-fw text-blue-500" />,
id: 2,
},
{
label: 'AI写作工具',
icon: <FontAwesomeIcon icon={faPenClip} className="fa-fw text-blue-500" />,
id: 3,
},
{
label: 'AI写作工具',
icon: <FontAwesomeIcon icon={faPenClip} className="fa-fw text-blue-500" />,
id: 4,
},
{
label: 'AI写作工具',
icon: <FontAwesomeIcon icon={faPenClip} className="fa-fw text-blue-500" />,
id: 5,
},
{
label: 'AI写作工具',
icon: <FontAwesomeIcon icon={faPenClip} className="fa-fw text-blue-500" />,
id: 6,
},
{
label: 'AI写作工具',
icon: <FontAwesomeIcon icon={faPenClip} className="fa-fw text-blue-500" />,
id: 7,
},
{
label: 'AI写作工具',
icon: <FontAwesomeIcon icon={faPenClip} className="fa-fw text-blue-500" />,
id: 8,
},
{
label: 'AI写作工具',
icon: <FontAwesomeIcon icon={faPenClip} className="fa-fw text-blue-500" />,
id: 9,
}
] as LinkTypeItem[];

View File

@ -24,7 +24,7 @@ export default function ImageUpload(props: {
if (url) {
props.onChange?.(url)
}
} catch (e) {
} catch {
setLoading(false)
}

View File

@ -4,7 +4,7 @@ import { LinkType } from "../_lib/data/linkType";
import { Link as _Link } from "../_lib/data/link";
import { useEffect, useMemo } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faClock, faFire, faTimeline, faTimesCircle, faTimesRectangle, faVolumeTimes } from "@fortawesome/free-solid-svg-icons";
import { faClock, faFire } from "@fortawesome/free-solid-svg-icons";
import { useAtom } from "jotai";
import { linkTypeAtom } from "../_lib/atom";
import Image from "next/image";
@ -12,7 +12,7 @@ import Image from "next/image";
const LinkBlock = ({ val }: { val: _Link }) => {
return <Link className="flex gap-x-2 bg-white rounded-lg py-4 pl-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} className="w-[40px] h-[40px]"></img>
<Image alt="image" src={val.logoLink} className="w-[40px] h-[40px]" width={40} height={40}></Image>
<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-[#666] text-xs" title={val.description}>{val.description}</span>
@ -20,8 +20,8 @@ const LinkBlock = ({ val }: { val: _Link }) => {
</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), [])
const recentList = useMemo(() => linkList.map(val => val).sort((a, b) => b.addTime - a.addTime).filter((_, idx) => idx < 12), [])
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)
useEffect(() => {
console.log(currentId);
@ -72,7 +72,7 @@ export default function LinkListBox({ linkTypeList, linkList, showHot, showRecen
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 text-xl">
<img src={item.icon as string} className="w-[30px] h-[30px] object-cover"></img>
<Image src={item.icon as string} className="w-[30px] h-[30px] object-cover" width={30} height={30} alt=""></Image>
<span>{item.label}</span>
</div>

View File

@ -1,5 +1,5 @@
"use client";
import { MdPreview, MdCatalog } from 'md-editor-rt';
import { MdPreview} from 'md-editor-rt';
export default function MarkdownView({ value = '' }: { value?: string }) {
return (

View File

@ -1,4 +1,6 @@
export default function PosterBox({ posterList }: { posterList: string[] }) {
console.log('posterList', posterList);
return (
<div className="w-full min-h-[140px] bg-white shadow-md rounded-lg p-2">
<div className="w-full grid grid-cols-5 gap-x-2">

View File

@ -6,10 +6,8 @@ import clsx from "clsx";
import { useEffect, useMemo, useState } from "react";
import Logo from "./Logo";
import { useRequest } from "ahooks";
import { mRequest } from "../_lib/request";
import { getSearchTypeList, getSearchWayList, SearchTypeItem, SearchWayItemType } from "../_lib/data/search";
import { getSearchTypeList, getSearchWayList, SearchWayItemType } from "../_lib/data/search";
import { doSearch } from "../_lib/utils";
import { log } from "node:console";
const defaultSearchEngine: SearchWayItemType = {
@ -61,7 +59,7 @@ export default function Search() {
if (filterSeachList.length > 0) {
setActiveSearchKey(filterSeachList[0]._id)
}
}, [selectKey])
}, [filterSeachList, selectKey])
return (
<div className="w-full flex justify-center flex-col items-center py-10 h-[300px]">

View File

@ -1,17 +1,17 @@
"use client";
import Link from "next/link";
import { LinkTypeItem } from "../_lib/types";
import Logo from "./Logo";
import clsx from "clsx";
import { usePathname, useRouter } from "next/navigation";
import { useAtom } from "jotai";
import { linkTypeAtom } from "../_lib/atom";
import { LinkType } from "../_lib/data/linkType";
import Image from "next/image";
export default function SiderNav({ linkList }: { linkList: LinkType[] }) {
const pathname = usePathname()
const router = useRouter()
const [, setSelectType] = useAtom(linkTypeAtom)
return (
<div className="w-[220px] flex flex-col gap-y-2 fixed left-0 top-0 h-[100vh] bg-[#F9F9F9]">
<div className="bg-white shadow-sm">
@ -32,14 +32,14 @@ export default function SiderNav({ linkList }: { linkList: LinkType[] }) {
</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}
onClick={() => {
if (pathname !== '/') {
router.replace('/')
}
setSelectType(item._id)
}}
>
<img src={item.icon as string} className="w-[20px] h-[20px] object-cover"></img>
<Image src={item.icon as string} className="w-[20px] h-[20px] object-cover" alt="" width={20} height={20} ></Image>
<span>{item.label}</span>
</div>

View File

@ -25,7 +25,7 @@ import { useState } from "react"
export default function LinkTable(props: { id: string }) {
const [loading, setLoading] = useState(false)
const [loading] = useState(false)
const { data: LinkTypeList } = useRequest(async () => mRequest<{
list: LinkType[]
}>('GET', '/api/linkType'))
@ -83,7 +83,7 @@ export default function LinkTable(props: { id: string }) {
title: "图标",
dataIndex: "logoLink",
render: (_, row) => (
<Image width={80} src={row.logoLink}></Image>
<Image width={80} src={row.logoLink} alt=""></Image>
)
},
{

View File

@ -20,7 +20,7 @@ export default function Page() {
},
{
title: '操作',
render: (_, row) => (
render: () => (
<Space>
<Button type="primary"></Button>
<Button type="primary"></Button>

View File

@ -2,14 +2,10 @@
import { ArticleType } from '@/app/_lib/data/article';
import ImageUpload from '@/app/_ui/ImageUpload';
import { faArrowLeft, faRibbon } from '@fortawesome/free-solid-svg-icons';
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { BackTop, Button, Card, Col, DatePicker, Form, Grid, Input, InputNumber, message, Row, Select, Space, Upload } from 'antd';
import dynamic from 'next/dynamic';
import { useParams, useRouter } from 'next/navigation'
import { useState } from 'react';
// const MDEditor = dynamic(() => import('@uiw/react-md-editor'), { ssr: false });
import { Button, Card, Col, DatePicker, Form, Input, InputNumber, message, Row, Select, Space } from 'antd';
import { useRouter } from 'next/navigation'
import { MdEditor } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';
import '@ant-design/v5-patch-for-react-19';

View File

@ -41,7 +41,7 @@ export default function Page() {
dataIndex: "content",
render: (_, item) => (
<>
<Image src={item.content} width={70} ></Image>
<Image src={item.content} width={70} alt="" ></Image>
</>
)
},

View File

@ -1,31 +1,16 @@
"use client";
import { Button, Card, Drawer, Form, Image, Input, InputNumber, message, Modal, Popconfirm, Space, Table } from "antd";
import { useRef, useState } from "react";
import { Button, Card, Drawer, Form, Image, Input, InputNumber, message, Popconfirm, Space, Table } from "antd";
import { useState } from "react";
import { useAntdTable } from "ahooks";
import { mRequest } from "@/app/_lib/request";
import { LinkTypeItem } from "@/app/_lib/types";
import LinkTable from "./LinkTable";
import ImageUpload from "@/app/_ui/ImageUpload";
import { useForm } from "antd/es/form/Form";
import { LinkType } from "@/app/_lib/data/linkType";
import { getLinkTypeList, LinkType } from "@/app/_lib/data/linkType";
import '@ant-design/v5-patch-for-react-19';
export default function Page() {
const { tableProps, refresh } = useAntdTable(
async ({ current, pageSize }) => {
return mRequest<{
total: number;
data: LinkTypeItem[]
}>(
"GET",
`/api/linkType?page=${current}&pageSize=${pageSize}`
).then((res: any) => {
return {
total: res?.total || 0,
list: res?.list || [],
}
})
},
async ({ current, pageSize }) => getLinkTypeList({ page: current, pageSize }),
)
const [selectedType, setSelectedType] = useState<undefined | null | LinkType>(
@ -69,7 +54,7 @@ export default function Page() {
dataIndex: "icon",
render: (_, item) => (
<>
<Image src={item.icon} width={70} ></Image>
<Image src={item.icon} width={70} alt=""></Image>
</>
)
},
@ -187,7 +172,7 @@ export default function Page() {
</Form.Item>
</Form>
</Drawer>
{/* <Drawer
forceRender
title={'添加图标'}

View File

@ -1,7 +1,7 @@
import { SearchWayItemType } from "@/app/_lib/data/search";
import { mRequest } from "@/app/_lib/request";
import { useRequest } from "ahooks";
import { Checkbox, Space } from "antd";
import { Checkbox } from "antd";
import { useMemo } from "react";
export default function SearchSelect({ value, onChange }: { value?: string[]; onChange?: (e: any) => void }) {

View File

@ -66,7 +66,7 @@ export default function Page() {
// mRequest('DELETE', `/api/search/${row._id}`).then(res => {
// refresh()
// })
deleteSearchWay(row._id).then(res => {
deleteSearchWay(row._id).then(() => {
refresh()
message.success('删除成功')
})
@ -132,7 +132,7 @@ export default function Page() {
okText="确定"
cancelText="取消"
onConfirm={() => {
mRequest('DELETE', `/api/searchType/${row._id}`).then(res => {
mRequest('DELETE', `/api/searchType/${row._id}`).then(() => {
refreshTypeList()
message.success('删除成功')
})

View File

@ -19,7 +19,7 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ i
_id: new ObjectId(slug)
})
return Response.json({ message: '删除成功' })
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -15,7 +15,7 @@ export async function POST(request: NextRequest) {
const collection = await getCollection('article');
const data = await collection.insertOne(body);
return Response.json(data)
} catch (e) {
} catch {
return Response.error()
}
}
@ -25,7 +25,7 @@ export async function PUT(request: NextRequest) {
const collection = await getCollection('article');
const data = await collection.updateOne({ _id: body._id }, { $set: body });
return Response.json(data)
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -1,4 +1,4 @@
import { getCollection, getDb } from "@/app/_lib/mongodb";
import { getCollection } from "@/app/_lib/mongodb";
import { ObjectId } from "mongodb";
import { NextRequest } from "next/server";
import { verifySession } from "@/app/_lib/dal";
@ -26,7 +26,7 @@ export async function GET(req: NextRequest) {
total,
list: data,
})
} catch (e) {
} catch {
return Response.error()
}
}
@ -46,7 +46,7 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ i
_id: new ObjectId(slug)
})
return Response.json({ message: '删除成功' })
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -1,9 +1,6 @@
import { verifySession } from "@/app/_lib/dal";
import { Link } from "@/app/_lib/data/link";
import { User } from "@/app/_lib/data/user";
import { getCollection, getDb } from "@/app/_lib/mongodb";
import { message } from "antd";
import bcrypt from 'bcrypt';
import { getCollection } from "@/app/_lib/mongodb";
import { ObjectId } from "mongodb";
import { NextRequest } from "next/server";
@ -29,7 +26,7 @@ export async function GET(req: NextRequest) {
total,
list: data,
})
} catch (e) {
} catch {
return Response.error()
}
}
@ -48,7 +45,7 @@ export async function POST(req: NextRequest) {
const collection = await getCollection('link')
await collection.insertOne(link)
return Response.json({ message: '成功' })
} catch (e) {
} catch {
return Response.error()
}
}
@ -67,7 +64,7 @@ export async function PUT(req: NextRequest) {
const collection = await getCollection('link')
await collection.replaceOne({ _id: new ObjectId(link._id) }, { ...link, _id: new ObjectId(link._id) })
return Response.json({ message: '成功' })
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -1,5 +1,5 @@
import { verifySession } from "@/app/_lib/dal";
import { getCollection, getDb } from "@/app/_lib/mongodb";
import { getCollection} from "@/app/_lib/mongodb";
import { ObjectId } from "mongodb";
import { NextRequest } from "next/server";
import { getLinkList } from "@/app/_lib/data/link";
@ -19,7 +19,7 @@ export async function GET(req: NextRequest) {
const res = await getLinkList({ page, pageSize })
return Response.json(res)
} catch (e) {
} catch {
return Response.error()
}
}
@ -40,7 +40,7 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ i
_id: new ObjectId(slug)
})
return Response.json({ message: '删除成功' })
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -1,6 +1,6 @@
import { verifySession } from "@/app/_lib/dal";
import { getLinkTypeList, LinkType } from "@/app/_lib/data/linkType";
import { getCollection, getDb } from "@/app/_lib/mongodb";
import { getCollection } from "@/app/_lib/mongodb";
import { ObjectId } from "mongodb";
import { NextRequest } from "next/server";
@ -11,7 +11,7 @@ export async function GET(req: NextRequest) {
const pageSize = parseInt(req.nextUrl.searchParams.get('pageSize') || '10') || 10;
const res = await getLinkTypeList({ page, pageSize })
return Response.json(res)
} catch (e) {
} catch {
return Response.error()
}
}
@ -29,7 +29,7 @@ export async function POST(req: NextRequest) {
const collection = await getCollection('link-type')
await collection.insertOne(link)
return Response.json({ message: '成功' })
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -1,9 +1,9 @@
import { getCollection, getDb } from "@/app/_lib/mongodb";
import { getCollection } from "@/app/_lib/mongodb";
import { ObjectId } from "mongodb";
import { NextRequest } from "next/server";
import { verifySession } from "@/app/_lib/dal";
import { getLinkList, Link } from "@/app/_lib/data/link";
import { getLinkList } from "@/app/_lib/data/link";
export async function GET(req: NextRequest) {
try {
@ -13,7 +13,7 @@ export async function GET(req: NextRequest) {
const res = await getLinkList({ page, pageSize, typeId })
return Response.json(res)
} catch (e) {
} catch {
return Response.error()
}
}
@ -34,7 +34,7 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ i
_id: new ObjectId(slug)
})
return Response.json({ message: '删除成功' })
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -1,7 +1,7 @@
import { verifySession } from "@/app/_lib/dal";
import { Link } from "@/app/_lib/data/link";
import { getSearchWayList } from "@/app/_lib/data/search";
import { getCollection, getDb } from "@/app/_lib/mongodb";
import { getCollection } from "@/app/_lib/mongodb";
import { ObjectId } from "mongodb";
import { NextRequest } from "next/server";
@ -14,7 +14,7 @@ export async function GET(req: NextRequest) {
const res = await getSearchWayList({ page, pageSize })
return Response.json(res)
} catch (e) {
} catch {
return Response.error()
}
}
@ -33,7 +33,7 @@ export async function POST(req: NextRequest) {
const collection = await getCollection('search')
await collection.insertOne(link)
return Response.json({ message: '成功' })
} catch (e) {
} catch {
return Response.error()
}
}
@ -56,7 +56,7 @@ export async function PUT(req: NextRequest) {
return Response.json({ message: '成功' })
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -1,4 +1,4 @@
import { getCollection, getDb } from "@/app/_lib/mongodb";
import { getCollection } from "@/app/_lib/mongodb";
import { ObjectId } from "mongodb";
import { NextRequest } from "next/server";
import { verifySession } from "@/app/_lib/dal";
@ -6,7 +6,7 @@ import { verifySession } from "@/app/_lib/dal";
export async function DELETE(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
try {
const session = await verifySession()
// Check if the user is authenticated
if (!session) {
// User is not authenticated
@ -19,7 +19,7 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ i
_id: new ObjectId(slug)
})
return Response.json({ message: '删除成功' })
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -13,7 +13,7 @@ export async function GET(req: NextRequest) {
const res = await getSearchTypeList({ page, pageSize })
return Response.json(res)
} catch (e) {
} catch {
return Response.error()
}
}
@ -31,7 +31,7 @@ export async function POST(req: NextRequest) {
const res = collection.insertOne(item)
return Response.json(res)
} catch (e) {
} catch {
return Response.error()
}
}
@ -50,7 +50,7 @@ export async function PUT(req: NextRequest) {
const item = await req.json() as SearchTypeItem
const res = await collection.replaceOne({ _id: new ObjectId(item._id) }, { ...item, _id: new ObjectId(item._id) })
return Response.json(res)
} catch (e) {
} catch {
return Response.error()
}
}

View File

@ -13,7 +13,7 @@ const eslintConfig = [
...compat.extends("next/core-web-vitals", "next/typescript"),
{
rules: {
"@typescript-eslint/no-explicit-any": "",
"@typescript-eslint/no-explicit-any": "off", // 禁用对显式 any 类型的检查
},
},
];

View File

@ -14,6 +14,17 @@ const nextConfig: NextConfig = {
]
},
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'aihlp.com.cn',
port: '',
pathname: '/**',
search: '',
},
],
},
};
export default nextConfig;