Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/[nsfront]/[nsbehind]/[name]/[version]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Link from 'next/link';
import { cratesInfo } from '@/app/lib/all_interface';
import { useParams } from 'next/navigation';
import { Pagination } from 'antd';
// import NewHeader from '@/components/NewHeader';

interface CVE {
subtitle?: string;
Expand Down
4 changes: 2 additions & 2 deletions app/[nsfront]/[nsbehind]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@/app/ui/global.css';
import { HeaderProvider } from '../../context/CrateContext';
import Header from '@/components/HeaderWithSearch';
// import Header from '@/components/HeaderWithSearch';


export const metadata = {
Expand All @@ -17,7 +17,7 @@ export default function layout({
<html lang="cn">
<body>
<HeaderProvider>
<Header />
{/* <Header /> */}
{children}
</HeaderProvider>
</body>
Expand Down
4 changes: 2 additions & 2 deletions app/search/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";
import '@/app/ui/global.css';
import NewHeader from '@/components/NewHeader';
// import NewHeader from '@/components/NewHeader';



Expand All @@ -13,7 +13,7 @@ export default function RootLayout({
return (
<html lang="cn">
<body>
<NewHeader />
{/* <NewHeader /> */}
{children}

</body>
Expand Down
285 changes: 223 additions & 62 deletions app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,30 @@
import { useEffect, useState, Suspense } from 'react';
import { useSearchParams } from 'next/navigation';
import Link from 'next/link';
// import NewHeader from '@/components/NewHeader';
import Image from 'next/image';
import NewHeader from '@/components/NewHeader';
import { searchResult } from '@/app/lib/all_interface';

const Search = () => {
const [results, setResults] = useState<searchResult | null>(null);
const [currentPage, setCurrentPage] = useState(1); // 添加当前页码状态
const [loading, setLoading] = useState(false); // 添加加载状态
// const [currentPage, setCurrentPage] = useState(1);
const [loading, setLoading] = useState(false);
const searchParams = useSearchParams();
const name = searchParams.get('crate_name');
const [activeTab, setActiveTab] = useState('All');
const [localCurrentPage, setLocalCurrentPage] = useState(1); // 本地分页状态
// const itemsPerPage = 10; // 每页显示10条

useEffect(() => {
if (name) {
fetchResults(name, currentPage); // 使用 name 和当前页发起请求
// 计算需要向后端请求的页码
const backendPage = Math.ceil(localCurrentPage / 2);
fetchResults(name, backendPage);
}
}, [name, currentPage]); // 当 name 或 currentPage 改变时重新运行
}, [name, localCurrentPage]);

const fetchResults = async (query: string, page: number) => {
setLoading(true); // 开始加载数据
setLoading(true);
try {
const response = await fetch('/api/search', {
method: 'POST',
Expand All @@ -29,8 +35,8 @@ const Search = () => {
body: JSON.stringify({
query,
pagination: {
page, // 使用传入的页码
per_page: 20 // 每页条数
page,
per_page: 20 // 保持后端每页20个
}
}),
});
Expand All @@ -39,86 +45,241 @@ const Search = () => {
}
const data1 = await response.json();
const data = data1.data;
setResults(data); // 假设返回的数据data字段
setResults(data);
} catch (error) {
console.error('Error fetching data:', error);
} finally {
setLoading(false); // 数据加载完成
setLoading(false);
}
};

// 计算当前页面应该显示的数据
const getCurrentPageItems = () => {
if (!results || !results.data || !results.data.items || !results.data.items.length) {
return [];
}

const isFirstHalf = localCurrentPage % 2 === 1; // 奇数页显示前半部分,偶数页显示后半部分
const startIndex = isFirstHalf ? 0 : 10;
const endIndex = isFirstHalf ? Math.min(10, results.data.items.length) : Math.min(20, results.data.items.length);

return results.data.items.slice(startIndex, endIndex);
};

// 计算总页数
const getTotalLocalPages = () => {
if (!results) return 0;
return results.data.total_page * 2; // 后端每页20条,前端每页10条,所以总页数翻倍
};

const handleNextPage = () => {
if (results && currentPage < results.data.total_page) {
setCurrentPage(prevPage => prevPage + 1); // 增加页码
const totalPages = getTotalLocalPages();
if (localCurrentPage < totalPages) {
setLocalCurrentPage(prevPage => prevPage + 1);
}
};

const handlePreviousPage = () => {
if (currentPage > 1) {
setCurrentPage(prevPage => prevPage - 1); // 减少页码
if (localCurrentPage > 1) {
setLocalCurrentPage(prevPage => prevPage - 1);
}
};

console.log("results:", results?.data.items);
// 直接跳转到指定页码
const goToPage = (page: number) => {
const totalPages = getTotalLocalPages();
if (page >= 1 && page <= totalPages) {
setLocalCurrentPage(page);
}
};

// 获取当前页应显示的数据
const currentItems = getCurrentPageItems();

return (
<div className="min-h-screen bg-gray-100 flex flex-col">
{/* <NewHeader /> */}
<div className="max-w-2xl ml-10 p-4 flex-grow">
<div id="results" className="space-y-4">
{loading ? (
<p>Loading...</p>
) : results ? (
results.data.total_page > 0 && results.data.items.length > 0 ? (
results.data.items.map((item, index) => (
<Link
<div className="min-h-screen bg-white flex flex-col">
{/* 添加 Header */}
<NewHeader />

{/* 创建一个居中的容器 */}
<div className="flex mt-0 justify-center w-full">
<div className="w-[1500px] flex flex-col">
{/* 标签导航 */}
<div className="h-[64px] flex-shrink-0 rounded-[12px] bg-white shadow-[0_0_12px_0_rgba(43,88,221,0.09)] flex items-center px-6 my-6">
<button
className={`mr-8 py-2 ${activeTab === 'All' ? 'text-blue-500 border-b-2 border-blue-500' : 'text-gray-600'}`}
onClick={() => setActiveTab('All')}
>
All
</button>
<button
className={`mr-8 py-2 ${activeTab === 'Packages' ? 'text-blue-500 border-b-2 border-blue-500' : 'text-gray-600'}`}
onClick={() => setActiveTab('Packages')}
>
Packages
</button>
<button
className={`mr-8 py-2 ${activeTab === 'Advisories' ? 'text-blue-500 border-b-2 border-blue-500' : 'text-gray-600'}`}
onClick={() => setActiveTab('Advisories')}
>
Advisories
</button>
<button
className={`mr-8 py-2 ${activeTab === 'Projects' ? 'text-blue-500 border-b-2 border-blue-500' : 'text-gray-600'}`}
onClick={() => setActiveTab('Projects')}
>
Projects
</button>

<div className="ml-auto">
<span className="text-[#4b68ff] font-['HarmonyOS_Sans_SC'] text-base font-normal tracking-[0.64px]"
style={{ textShadow: '0 0 20px rgba(43, 88, 221, 0.16)' }}>
Total {results?.data.total_page ? results.data.items.length * results.data.total_page : 0} results
</span>
</div>
</div>

{/* 搜索结果 */}
<div className="w-full">
{loading ? (
<p>Loading...</p>
) : currentItems.length > 0 ? (
currentItems.map((item, index) => (
<div
key={index}
href={`/${item.nsfront}/${item.nsbehind}/${item.name}/${item.version}`}
className={`
flex
mb-4

h-[90px]
flex-shrink-0
rounded-[12px]
bg-white
transition-all
duration-200
hover:bg-[#4b68ff14]
hover:shadow-[0_0_12px_0_rgba(43,88,221,0.2)]
`}
>
<div className="p-4 rounded-md hover:bg-blue-100 transition">
<strong style={{ color: 'rgb(0, 121, 192)' }}>{item.name}</strong>
<div>
Crate • {item.version} • {item.nsfront}/{item.nsbehind}
<Link href={`/${item.nsfront}/${item.nsbehind}/${item.name}/${item.version}`} className="block h-full">
<div className="p-6 h-full flex flex-col justify-center">
<div className="text-sm text-gray-600 mb-1">NuGet</div>
<div className="text-blue-500 font-medium text-lg">{item.name}</div>
<div className="text-gray-600 text-sm">
Package {item.version} • Published October 22,2021
</div>
</div>
</div>
</Link>
</Link>
</div>
))
) : (
<p>No items found.</p>
)
) : (
<p>Loading...</p>
)}
</div>

{/* 分页控制 */}
{results && getTotalLocalPages() > 0 && (
<div className="flex ml-6 mt-8 mb-8">
<button
onClick={() => goToPage(1)}
className="mx-1 w-8 h-8 rounded-full flex items-center justify-center border"
disabled={localCurrentPage === 1}
>
&lt;&lt;
</button>
<button
onClick={handlePreviousPage}
className="mx-1 w-8 h-8 rounded-full flex items-center justify-center border"
disabled={localCurrentPage === 1}
>
&lt;
</button>

{/* 页码指示器 */}
{Array.from({ length: Math.min(5, getTotalLocalPages()) }).map((_, i) => {
const pageNum = localCurrentPage - 2 + i;
if (pageNum > 0 && pageNum <= getTotalLocalPages()) {
return (
<button
key={i}
onClick={() => goToPage(pageNum)}
className={`mx-1 w-8 h-8 rounded-full flex items-center justify-center ${localCurrentPage === pageNum
? 'bg-blue-500 text-white'
: 'border'
}`}
>
{pageNum}
</button>
);
}
return null;
})}

<button
onClick={handleNextPage}
className="mx-1 w-8 h-8 rounded-full flex items-center justify-center border"
disabled={localCurrentPage >= getTotalLocalPages()}
>
&gt;
</button>
<button
onClick={() => goToPage(getTotalLocalPages())}
className="mx-1 w-8 h-8 rounded-full flex items-center justify-center border"
disabled={localCurrentPage >= getTotalLocalPages()}
>
&gt;&gt;
</button>
</div>
)}
</div>
</div>
{/* Package•1.0.4•Published July 19, 2019 */}
{/* 当前页数在按钮上方 */}
<div className="flex flex-col items-start mt-2 mb-4 custom-margin-left">
{results && (
<div className="mb-2">
<p>
Current page: {currentPage} / Total page: {results.data.total_page}
</p>
<footer className="bg-[#002851] text-white py-12">
<div className="max-w-6xl mx-auto px-4">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div>
<Image
src="/images/homepage/logo-footer.png"
alt="CratesPro Logo"
width={180}
height={60}
className="mb-4"
/>
</div>

<div>
<h4 className="text-lg font-semibold mb-4">Resources</h4>
<ul className="space-y-2">
<li><Link href="#" className="hover:text-blue-300">Documentation</Link></li>
<li><Link href="#" className="hover:text-blue-300">About</Link></li>
<li><Link href="#" className="hover:text-blue-300">Blog</Link></li>
<li><Link href="#" className="hover:text-blue-300">FAQ</Link></li>
</ul>
</div>

<div>
<h4 className="text-lg font-semibold mb-4">API</h4>
<ul className="space-y-2">
<li><Link href="#" className="hover:text-blue-300">API</Link></li>
<li><Link href="#" className="hover:text-blue-300">BigQuery Dataset</Link></li>
<li><Link href="#" className="hover:text-blue-300">GitHub</Link></li>
</ul>
</div>

<div>
<h4 className="text-lg font-semibold mb-4">Legal</h4>
<ul className="space-y-2">
<li><Link href="#" className="hover:text-blue-300">Legal</Link></li>
<li><Link href="#" className="hover:text-blue-300">Privacy</Link></li>
<li><Link href="#" className="hover:text-blue-300">Terms</Link></li>
</ul>
</div>
</div>
)}
{results && results.data.total_page > 0 && (
<div className="flex">
<button
onClick={handlePreviousPage}
disabled={currentPage === 1}
className="mx-0 px-4 py-2 bg-blue-500 text-white rounded-md disabled:bg-gray-300"
>
Previous
</button>
<button
onClick={handleNextPage}
disabled={results === null || currentPage >= results.data.total_page}
className="mx-20 px-4 py-2 bg-blue-500 text-white rounded-md disabled:bg-gray-300"
>
Next
</button>

<div className="border-t border-gray-700 mt-8 pt-8 text-center text-sm">
<p>Copyright © 2023 jp21.com.cn All Rights Reserved(@ICPBH180237号)</p>
</div>
)}
</div>
</div>
</footer>
</div>
);
}
Expand Down
Loading