22import { useEffect , useState , Suspense } from 'react' ;
33import { useSearchParams } from 'next/navigation' ;
44import Link from 'next/link' ;
5- // import NewHeader from '@/components/NewHeader';
5+ import Image from 'next/image' ;
6+ import NewHeader from '@/components/NewHeader' ;
67import { searchResult } from '@/app/lib/all_interface' ;
78
89const 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+ <<
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+ <
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+ >
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+ >>
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