Skip to content

Commit e6ea6f4

Browse files
authored
search result and the header of overview page (#156)
* search result and the header of overview page * debug
1 parent ba0d29f commit e6ea6f4

File tree

7 files changed

+290
-126
lines changed

7 files changed

+290
-126
lines changed

app/[nsfront]/[nsbehind]/[name]/[version]/page.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Link from 'next/link';
55
import { cratesInfo } from '@/app/lib/all_interface';
66
import { useParams } from 'next/navigation';
77
import { Pagination } from 'antd';
8+
// import NewHeader from '@/components/NewHeader';
89

910
interface CVE {
1011
subtitle?: string;

app/[nsfront]/[nsbehind]/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import '@/app/ui/global.css';
22
import { HeaderProvider } from '../../context/CrateContext';
3-
import Header from '@/components/HeaderWithSearch';
3+
// import Header from '@/components/HeaderWithSearch';
44

55

66
export const metadata = {
@@ -17,7 +17,7 @@ export default function layout({
1717
<html lang="cn">
1818
<body>
1919
<HeaderProvider>
20-
<Header />
20+
{/* <Header /> */}
2121
{children}
2222
</HeaderProvider>
2323
</body>

app/search/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22
import '@/app/ui/global.css';
3-
import NewHeader from '@/components/NewHeader';
3+
// import NewHeader from '@/components/NewHeader';
44

55

66

@@ -13,7 +13,7 @@ export default function RootLayout({
1313
return (
1414
<html lang="cn">
1515
<body>
16-
<NewHeader />
16+
{/* <NewHeader /> */}
1717
{children}
1818

1919
</body>

app/search/page.tsx

Lines changed: 223 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,30 @@
22
import { useEffect, useState, Suspense } from 'react';
33
import { useSearchParams } from 'next/navigation';
44
import Link from 'next/link';
5-
// import NewHeader from '@/components/NewHeader';
5+
import Image from 'next/image';
6+
import NewHeader from '@/components/NewHeader';
67
import { searchResult } from '@/app/lib/all_interface';
78

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

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

2127
const fetchResults = async (query: string, page: number) => {
22-
setLoading(true); // 开始加载数据
28+
setLoading(true);
2329
try {
2430
const response = await fetch('/api/search', {
2531
method: 'POST',
@@ -29,8 +35,8 @@ const Search = () => {
2935
body: JSON.stringify({
3036
query,
3137
pagination: {
32-
page, // 使用传入的页码
33-
per_page: 20 // 每页条数
38+
page,
39+
per_page: 20 // 保持后端每页20个
3440
}
3541
}),
3642
});
@@ -39,86 +45,241 @@ const Search = () => {
3945
}
4046
const data1 = await response.json();
4147
const data = data1.data;
42-
setResults(data); // 假设返回的数据data字段
48+
setResults(data);
4349
} catch (error) {
4450
console.error('Error fetching data:', error);
4551
} finally {
46-
setLoading(false); // 数据加载完成
52+
setLoading(false);
4753
}
4854
};
4955

56+
// 计算当前页面应该显示的数据
57+
const getCurrentPageItems = () => {
58+
if (!results || !results.data || !results.data.items || !results.data.items.length) {
59+
return [];
60+
}
61+
62+
const isFirstHalf = localCurrentPage % 2 === 1; // 奇数页显示前半部分,偶数页显示后半部分
63+
const startIndex = isFirstHalf ? 0 : 10;
64+
const endIndex = isFirstHalf ? Math.min(10, results.data.items.length) : Math.min(20, results.data.items.length);
65+
66+
return results.data.items.slice(startIndex, endIndex);
67+
};
68+
69+
// 计算总页数
70+
const getTotalLocalPages = () => {
71+
if (!results) return 0;
72+
return results.data.total_page * 2; // 后端每页20条,前端每页10条,所以总页数翻倍
73+
};
74+
5075
const handleNextPage = () => {
51-
if (results && currentPage < results.data.total_page) {
52-
setCurrentPage(prevPage => prevPage + 1); // 增加页码
76+
const totalPages = getTotalLocalPages();
77+
if (localCurrentPage < totalPages) {
78+
setLocalCurrentPage(prevPage => prevPage + 1);
5379
}
5480
};
5581

5682
const handlePreviousPage = () => {
57-
if (currentPage > 1) {
58-
setCurrentPage(prevPage => prevPage - 1); // 减少页码
83+
if (localCurrentPage > 1) {
84+
setLocalCurrentPage(prevPage => prevPage - 1);
5985
}
6086
};
6187

62-
console.log("results:", results?.data.items);
88+
// 直接跳转到指定页码
89+
const goToPage = (page: number) => {
90+
const totalPages = getTotalLocalPages();
91+
if (page >= 1 && page <= totalPages) {
92+
setLocalCurrentPage(page);
93+
}
94+
};
95+
96+
// 获取当前页应显示的数据
97+
const currentItems = getCurrentPageItems();
98+
6399
return (
64-
<div className="min-h-screen bg-gray-100 flex flex-col">
65-
{/* <NewHeader /> */}
66-
<div className="max-w-2xl ml-10 p-4 flex-grow">
67-
<div id="results" className="space-y-4">
68-
{loading ? (
69-
<p>Loading...</p>
70-
) : results ? (
71-
results.data.total_page > 0 && results.data.items.length > 0 ? (
72-
results.data.items.map((item, index) => (
73-
<Link
100+
<div className="min-h-screen bg-white flex flex-col">
101+
{/* 添加 Header */}
102+
<NewHeader />
103+
104+
{/* 创建一个居中的容器 */}
105+
<div className="flex mt-0 justify-center w-full">
106+
<div className="w-[1500px] flex flex-col">
107+
{/* 标签导航 */}
108+
<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">
109+
<button
110+
className={`mr-8 py-2 ${activeTab === 'All' ? 'text-blue-500 border-b-2 border-blue-500' : 'text-gray-600'}`}
111+
onClick={() => setActiveTab('All')}
112+
>
113+
All
114+
</button>
115+
<button
116+
className={`mr-8 py-2 ${activeTab === 'Packages' ? 'text-blue-500 border-b-2 border-blue-500' : 'text-gray-600'}`}
117+
onClick={() => setActiveTab('Packages')}
118+
>
119+
Packages
120+
</button>
121+
<button
122+
className={`mr-8 py-2 ${activeTab === 'Advisories' ? 'text-blue-500 border-b-2 border-blue-500' : 'text-gray-600'}`}
123+
onClick={() => setActiveTab('Advisories')}
124+
>
125+
Advisories
126+
</button>
127+
<button
128+
className={`mr-8 py-2 ${activeTab === 'Projects' ? 'text-blue-500 border-b-2 border-blue-500' : 'text-gray-600'}`}
129+
onClick={() => setActiveTab('Projects')}
130+
>
131+
Projects
132+
</button>
133+
134+
<div className="ml-auto">
135+
<span className="text-[#4b68ff] font-['HarmonyOS_Sans_SC'] text-base font-normal tracking-[0.64px]"
136+
style={{ textShadow: '0 0 20px rgba(43, 88, 221, 0.16)' }}>
137+
Total {results?.data.total_page ? results.data.items.length * results.data.total_page : 0} results
138+
</span>
139+
</div>
140+
</div>
141+
142+
{/* 搜索结果 */}
143+
<div className="w-full">
144+
{loading ? (
145+
<p>Loading...</p>
146+
) : currentItems.length > 0 ? (
147+
currentItems.map((item, index) => (
148+
<div
74149
key={index}
75-
href={`/${item.nsfront}/${item.nsbehind}/${item.name}/${item.version}`}
150+
className={`
151+
flex
152+
mb-4
153+
154+
h-[90px]
155+
flex-shrink-0
156+
rounded-[12px]
157+
bg-white
158+
transition-all
159+
duration-200
160+
hover:bg-[#4b68ff14]
161+
hover:shadow-[0_0_12px_0_rgba(43,88,221,0.2)]
162+
`}
76163
>
77-
<div className="p-4 rounded-md hover:bg-blue-100 transition">
78-
<strong style={{ color: 'rgb(0, 121, 192)' }}>{item.name}</strong>
79-
<div>
80-
Crate • {item.version}{item.nsfront}/{item.nsbehind}
164+
<Link href={`/${item.nsfront}/${item.nsbehind}/${item.name}/${item.version}`} className="block h-full">
165+
<div className="p-6 h-full flex flex-col justify-center">
166+
<div className="text-sm text-gray-600 mb-1">NuGet</div>
167+
<div className="text-blue-500 font-medium text-lg">{item.name}</div>
168+
<div className="text-gray-600 text-sm">
169+
Package {item.version} • Published October 22,2021
170+
</div>
81171
</div>
82-
</div>
83-
</Link>
172+
</Link>
173+
</div>
84174
))
85175
) : (
86176
<p>No items found.</p>
87-
)
88-
) : (
89-
<p>Loading...</p>
177+
)}
178+
</div>
179+
180+
{/* 分页控制 */}
181+
{results && getTotalLocalPages() > 0 && (
182+
<div className="flex ml-6 mt-8 mb-8">
183+
<button
184+
onClick={() => goToPage(1)}
185+
className="mx-1 w-8 h-8 rounded-full flex items-center justify-center border"
186+
disabled={localCurrentPage === 1}
187+
>
188+
&lt;&lt;
189+
</button>
190+
<button
191+
onClick={handlePreviousPage}
192+
className="mx-1 w-8 h-8 rounded-full flex items-center justify-center border"
193+
disabled={localCurrentPage === 1}
194+
>
195+
&lt;
196+
</button>
197+
198+
{/* 页码指示器 */}
199+
{Array.from({ length: Math.min(5, getTotalLocalPages()) }).map((_, i) => {
200+
const pageNum = localCurrentPage - 2 + i;
201+
if (pageNum > 0 && pageNum <= getTotalLocalPages()) {
202+
return (
203+
<button
204+
key={i}
205+
onClick={() => goToPage(pageNum)}
206+
className={`mx-1 w-8 h-8 rounded-full flex items-center justify-center ${localCurrentPage === pageNum
207+
? 'bg-blue-500 text-white'
208+
: 'border'
209+
}`}
210+
>
211+
{pageNum}
212+
</button>
213+
);
214+
}
215+
return null;
216+
})}
217+
218+
<button
219+
onClick={handleNextPage}
220+
className="mx-1 w-8 h-8 rounded-full flex items-center justify-center border"
221+
disabled={localCurrentPage >= getTotalLocalPages()}
222+
>
223+
&gt;
224+
</button>
225+
<button
226+
onClick={() => goToPage(getTotalLocalPages())}
227+
className="mx-1 w-8 h-8 rounded-full flex items-center justify-center border"
228+
disabled={localCurrentPage >= getTotalLocalPages()}
229+
>
230+
&gt;&gt;
231+
</button>
232+
</div>
90233
)}
91234
</div>
92235
</div>
93-
{/* Package•1.0.4•Published July 19, 2019 */}
94-
{/* 当前页数在按钮上方 */}
95-
<div className="flex flex-col items-start mt-2 mb-4 custom-margin-left">
96-
{results && (
97-
<div className="mb-2">
98-
<p>
99-
Current page: {currentPage} / Total page: {results.data.total_page}
100-
</p>
236+
<footer className="bg-[#002851] text-white py-12">
237+
<div className="max-w-6xl mx-auto px-4">
238+
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
239+
<div>
240+
<Image
241+
src="/images/homepage/logo-footer.png"
242+
alt="CratesPro Logo"
243+
width={180}
244+
height={60}
245+
className="mb-4"
246+
/>
247+
</div>
248+
249+
<div>
250+
<h4 className="text-lg font-semibold mb-4">Resources</h4>
251+
<ul className="space-y-2">
252+
<li><Link href="#" className="hover:text-blue-300">Documentation</Link></li>
253+
<li><Link href="#" className="hover:text-blue-300">About</Link></li>
254+
<li><Link href="#" className="hover:text-blue-300">Blog</Link></li>
255+
<li><Link href="#" className="hover:text-blue-300">FAQ</Link></li>
256+
</ul>
257+
</div>
258+
259+
<div>
260+
<h4 className="text-lg font-semibold mb-4">API</h4>
261+
<ul className="space-y-2">
262+
<li><Link href="#" className="hover:text-blue-300">API</Link></li>
263+
<li><Link href="#" className="hover:text-blue-300">BigQuery Dataset</Link></li>
264+
<li><Link href="#" className="hover:text-blue-300">GitHub</Link></li>
265+
</ul>
266+
</div>
267+
268+
<div>
269+
<h4 className="text-lg font-semibold mb-4">Legal</h4>
270+
<ul className="space-y-2">
271+
<li><Link href="#" className="hover:text-blue-300">Legal</Link></li>
272+
<li><Link href="#" className="hover:text-blue-300">Privacy</Link></li>
273+
<li><Link href="#" className="hover:text-blue-300">Terms</Link></li>
274+
</ul>
275+
</div>
101276
</div>
102-
)}
103-
{results && results.data.total_page > 0 && (
104-
<div className="flex">
105-
<button
106-
onClick={handlePreviousPage}
107-
disabled={currentPage === 1}
108-
className="mx-0 px-4 py-2 bg-blue-500 text-white rounded-md disabled:bg-gray-300"
109-
>
110-
Previous
111-
</button>
112-
<button
113-
onClick={handleNextPage}
114-
disabled={results === null || currentPage >= results.data.total_page}
115-
className="mx-20 px-4 py-2 bg-blue-500 text-white rounded-md disabled:bg-gray-300"
116-
>
117-
Next
118-
</button>
277+
278+
<div className="border-t border-gray-700 mt-8 pt-8 text-center text-sm">
279+
<p>Copyright © 2023 jp21.com.cn All Rights Reserved(@ICPBH180237号)</p>
119280
</div>
120-
)}
121-
</div>
281+
</div>
282+
</footer>
122283
</div>
123284
);
124285
}

0 commit comments

Comments
 (0)