diff --git a/app/[nsfront]/[nsbehind]/[name]/[version]/page.tsx b/app/[nsfront]/[nsbehind]/[name]/[version]/page.tsx index ea7b194..b20db55 100644 --- a/app/[nsfront]/[nsbehind]/[name]/[version]/page.tsx +++ b/app/[nsfront]/[nsbehind]/[name]/[version]/page.tsx @@ -4,7 +4,8 @@ import React, { useEffect, useState } from 'react'; import Link from 'next/link'; import { cratesInfo } from '@/app/lib/all_interface'; import { useParams } from 'next/navigation'; -import { Pagination } from 'antd'; +// import { Pagination } from 'antd'; +import Image from 'next/image'; // import NewHeader from '@/components/NewHeader'; interface CVE { @@ -24,116 +25,110 @@ interface CVE { } const CveCard = ({ cve }: { cve: CVE }) => ( -
- {/* 标题和ID */} -
-

- {cve.subtitle || 'No subtitle available'} -

-

+

+ {/* Package Name (红色标题) */} + {cve.subtitle && ( +
+

+ {cve.subtitle} +

+
+ )} + + {/* ID */} +
+

{cve.id || 'No ID available'}

- {/* 时间信息 */} -
+ {/* Reported */} +
- Reported - {cve.reported || 'Not specified'} + Reported + {cve.reported || 'Not specified'}
-
- {/* 时间信息 */} -
- Issued - {cve.issued || 'Not specified'} + {/* Issued */} +
+ Issued + {cve.issued || 'Not specified'}
- - - {/* 包信息 */} -
- Package - {cve.package || 'No package info'} + {/* Package */} +
+ Package + {cve.package || 'No package info'}
- - - - {/* 类型信息 */} + {/* Type */} {cve.ttype && ( -
- Type - {cve.ttype} +
+ Type + {cve.ttype}
)} - - {/* 别名信息 */} + {/* Aliases */} {cve.aliases && ( -
- Aliases - {Array.isArray(cve.aliases) ? cve.aliases.join(', ') : cve.aliases} +
+ Aliases + {Array.isArray(cve.aliases) ? cve.aliases.join(', ') : cve.aliases}
- )} - {/* 关键词 */} + {/* Keywords */} {cve.keywords && ( -
- Keywords - {cve.keywords} +
+ Keywords + {cve.keywords}
)} - - {/* 修复状态 */} + {/* Patched */} {cve.patched && ( -
- Patched - {cve.patched} +
+ Patched + {cve.patched}
- )} - {/* 未受影响版本 */} + {/* Unaffected */} {cve.unaffected && ( -
- Unaffected - {cve.unaffected} +
+ Unaffected + {cve.unaffected}
- )} {/* URL */} {cve.url && ( -
- Url + )} - {/* 引用链接 */} + {/* Reference */} {cve.reference && ( -
-

Reference

-
+
+ Reference +
{cve.reference.split(' ').map((url: string, i: number) => ( {url} @@ -142,11 +137,11 @@ const CveCard = ({ cve }: { cve: CVE }) => (
)} - {/* 描述信息 */} + {/* Description */} {cve.description && ( -
-

Description

-

{cve.description}

+
+ Description +

{cve.description}

)}
@@ -170,9 +165,8 @@ const CratePage = () => { } const data = await response.json(); setResults(data); - console.log('data in overviewwwwwwwww:', data); } catch (error) { - console.error('Error fetching data:', error); + console.error('Error fetching crate data:', error); setError('An error occurred'); } finally { setLoading(false); @@ -181,11 +175,10 @@ const CratePage = () => { fetchCrateData(); }, [params.name, params.version, params.nsfront, params.nsbehind]); - console.log('results in overviewwwwwwwww:', results); + if (loading) return

Loading...

; if (error) return

Error: {error}

; - // 计算当前页的 CVE 数据 const getCurrentPageItems = (items: CVE[], currentPage: number) => { const start = (currentPage - 1) * itemsPerPage; const end = start + itemsPerPage; @@ -193,293 +186,535 @@ const CratePage = () => { }; return ( -
-
-
- - {/* Security Advisories 主框 */} -
- {/* Security Advisories 标题 */} -
-
-

Security Advisories

- 0 - ? 'rgb(179, 20, 18)' - : 'rgb(34, 197, 94)' - }} - > - {results ? (results.cves?.length || 0) + (results.dep_cves?.length || 0) : 0} - +
+
+
+
+ {/* 左侧内容区域 - 占据2列 */} +
+ {/* Security Advisories 标题 */} +
+
+

+ Security Advisories +

-
- {/* 两个子框的容器 */} -
- {/* In this package 框 */} -
-
-

In this package

- 0) ? 'rgb(179, 20, 18)' : 'rgb(34, 197, 94)' }}> - {results?.cves?.length || 0} - + {/* Security Advisories 内容 */} +
+ {/* In this package */} +
0 ? 'h-[502px]' : 'h-[300px]'}`}> +
+

In this package

+ 0 ? 'bg-[#FD5656]' : 'bg-[#4B68FF]'}`}> + {results?.cves?.length || 0} + +
+
+ {results?.cves && results.cves.length > 0 ? ( +
0 ? "overflow-auto h-full w-full" : ""}> + {getCurrentPageItems(results.cves, packageCurrentPage).map((cve, index) => ( + + ))} + {results.cves.length > itemsPerPage && ( +
+ + + {Array.from({ length: Math.min(5, Math.ceil(results.cves.length / itemsPerPage)) }).map((_, i) => { + const pageNum = packageCurrentPage - Math.floor(Math.min(5, Math.ceil(results.cves.length / itemsPerPage)) / 2) + i; + if (pageNum > 0 && pageNum <= Math.ceil(results.cves.length / itemsPerPage)) { + return ( + + ); + } + return null; + })} + + +
+ )} +
+ ) : ( +
+ No vulnerabilities +

No vulnerabilities found

+
+ )} +
-
- {results?.cves && results.cves.length > 0 ? ( - <> - {getCurrentPageItems(results.cves, packageCurrentPage).map((cve, index) => ( - - ))} - {results.cves.length > itemsPerPage && ( -
- -
- )} - - ) : ( -

No vulnerabilities found

- )} + + {/* In the dependencies */} +
0 ? 'h-[502px]' : 'h-[300px]'}`}> +
+

In the dependencies

+ 0 ? 'bg-[#FD5656]' : 'bg-[#4B68FF]'}`}> + {results?.dep_cves?.length || 0} + +
+
+ {results?.dep_cves && results.dep_cves.length > 0 ? ( +
0 ? "overflow-auto h-full w-full" : ""}> + {getCurrentPageItems(results.dep_cves, depCurrentPage).map((cve, index) => ( + + ))} + {results.dep_cves.length > itemsPerPage && ( +
+ + + {Array.from({ length: Math.min(5, results.dep_cves.length) }).map((_, i) => { + const pageNum = depCurrentPage - 2 + i; + if (pageNum > 0 && pageNum <= results.dep_cves.length) { + return ( + + ); + } + return null; + })} + + +
+ )} +
+ ) : ( +
+ No vulnerabilities +

No vulnerabilities found

+
+ )} +
- {/* In the dependencies 框 */} -
-
-

In the dependencies

- 0 ? 'rgb(179, 20, 18)' : 'rgb(34, 197, 94)' }}> - {results?.dep_cves?.length || 0} - + {/* Licenses */} +
+ {/* Licenses 标题 */} + -
- {results?.dep_cves && results.dep_cves.length > 0 ? ( - <> - {getCurrentPageItems(results.dep_cves, depCurrentPage).map((cve, index) => ( - - ))} - {results.dep_cves.length > itemsPerPage && ( -
- -
- )} - - ) : ( -

No vulnerabilities found

- )} + {/* Licenses 内容 */} +
+
+ {results ? results.license : 'No results available'} +
-
-
- {/* Licenses */} -
-

Licenses

- - Learn more about license information. - -
- LICENSES -
-
- {results ? results.license : 'No results available'} -
-
+ {/* Dependencies */} +
+ {/* Dependencies 标题 */} +
+
+

+ Dependencies +

+
+ {/* Dependencies 内容 */} + {results && (results.dependencies.direct + results.dependencies.indirect) > 0 ? ( +
+
+ {/* Direct */} +
+
Direct
+
{results.dependencies.direct}
+
+
+
+
+ + {/* Indirect */} +
+
Indirect
+
{results.dependencies.indirect}
+
+
+
+
+
+ +
+ + + View all dependencies ({results.dependencies.direct + results.dependencies.indirect}) + + +
+
+ ) : ( +
+ This Package Has No Known Dependencies. +
+ )} +
- {/* Dependencies */} -
-
-

Dependencies

- - {results ? results.dependencies.direct + results.dependencies.indirect : 0} - -
- {/* Direct */} -
-
Direct
- - {results ? JSON.stringify(results.dependencies.direct) : 'No cves detected.'} - -
-
0 - ? (results.dependencies.direct / (results.dependencies.direct + results.dependencies.indirect)) * 100 - : 0 // 当分母为0时,条状图宽度直接设为0% - }%`, - backgroundColor: 'rgb(50,165,224)', - }} - className="h-full rounded" - >
+ {/* Dependents */} +
+ {/* Dependents 标题 */} +
+
+

+ Dependents +

+
+ {/* Dependents 内容 */} + {results && (results.dependents.direct + results.dependents.indirect) > 0 ? ( +
+
+ {/* Direct */} +
+
Direct
+
{results.dependents.direct}
+
+
+
+
+ + {/* Indirect */} +
+
Indirect
+
{results.dependents.indirect}
+
+
+
+
+
+ +
+ + + View all dependents ({results.dependents.direct + results.dependents.indirect}) + + +
+
+ ) : ( +
+ This Package Has No Known Dependents. +
+ )}
- {/* Indirect */} -
-
Indirect
- - {results ? JSON.stringify(results.dependencies.indirect) : 'No results available'} - -
-
0 - ? (results.dependencies.indirect / (results.dependencies.direct + results.dependencies.indirect)) * 100 - : 0 - }%`, - backgroundColor: 'rgb(50,165,224)', - }} - className="h-full rounded" - >
+ + {/* 右侧内容区域 - 占据1列 */} +
+ {/* 第一个摘要 */} +
+
+ icon +

+ 摘要 +

+
+
-
-
- -
- View all dependencies + {/* 第二个摘要 */} +
+
+ icon +

+ 摘要 +

- -
-
+ +
- {/* Dependents */} -
-
-

Dependents

- - {results ? results.dependents.direct + results.dependents.indirect : 0} - -
- {/* Direct */} -
-
Direct
- - {results ? JSON.stringify(results.dependents.direct) : 'No results available'} - - -
-
0 - ? (results.dependents.direct / (results.dependents.direct + results.dependents.indirect)) * 100 - : 0 // 当分母为0时,条状图宽度直接设为0% - }%`, - backgroundColor: 'rgb(50,165,224)', - }} - className="h-full rounded" - >
+ {/* Documentation */} +
+
+ icon +

+ Documentation +

+
+
-
- {/* Indirect */} -
-
Indirect
- - {results ? JSON.stringify(results.dependents.indirect) : 'No results available'} - -
-
0 - ? (results.dependents.indirect / (results.dependents.direct + results.dependents.indirect)) * 100 - : 0 // 当分母为0时,将宽度设为0% - }%`, - backgroundColor: 'rgb(50,165,224)', - }} - className="h-full rounded" - >
+ + {/* GitHub Links */} +
+
+ icon +

+ GitHub Links +

+
+
-
-
- -
- View all dependents + {/* OpenSSF Scorecard */} +
+
+ icon +

+ OpenSSF Scorecard +

+
+

+ The Open Source Security Foundation is a cross-industry collaboration to improve the security of + open source software (OSS). The Scorecard provides security health metrics for open source projects. +

+ + View information about checks and how to fix failures. + + +
+
8.3/10
+
Scorecard as of November 11, 2024
+
+ +
+ {[ + { name: 'Code-Review', score: '10/10' }, + { name: 'Maintained', score: '10/10' }, + { name: 'CI/Best-Practices', score: '10/10' }, + { name: 'License', score: '10/10' }, + { name: 'Dangerous-Workflow', score: '10/10' }, + { name: 'Security-Policy', score: '10/10' }, + { name: 'Token-Permissions', score: '10/10' }, + { name: 'Binary-Artifacts', score: '10/10' }, + { name: 'Pinned-Dependencies', score: '10/10' } + ].map((item, index) => ( +
+ {item.name} + {item.score} +
+ ))}
- +
-
- - {/* 新增的块: doc_url 和 github_url */} -
-
-

Documentation & GitHub Links

- +
+
+
+
+ CratesPro Logo
-
- GitHub URL: - - {results ? results.github_url : 'No results available'} - + +
+

Resources

+
    +
  • Documentation
  • +
  • About
  • +
  • Blog
  • +
  • FAQ
  • +
-
- {/* OpenSSF scorecard */} -
-

OpenSSF scorecard

-

The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.

- View information about checks and how to fix failures. -
-
8.3/10
-
Scorecard as of November 11, 2024.
+
+

API

+
    +
  • API
  • +
  • BigQuery Dataset
  • +
  • GitHub
  • +
-
-
Code-Review10/10
-
Maintained10/10
-
CI/Best-Practices0/10
-
License10/10
-
Dangerous-Workflow10/10
-
Security-Policy10/10
-
Token-Permissions10/10
-
Binary-Artifacts10/10
-
Pinned-Dependencies0/10
+ +
+

Legal

+
    +
  • Legal
  • +
  • Privacy
  • +
  • Terms
  • +
+ +
+

Copyright © 2023 jp21.com.cn All Rights Reserved(@ICPBH180237号)

+
-
+
); }; diff --git a/components/CrateNav.tsx b/components/CrateNav.tsx index 8d5b39b..eae2d72 100644 --- a/components/CrateNav.tsx +++ b/components/CrateNav.tsx @@ -1,7 +1,9 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import NewHeader from '@/components/NewHeader'; +import { useHeaderContext } from '../app/context/CrateContext'; +import Image from 'next/image'; interface CrateNavProps { nsfront: string; @@ -13,6 +15,10 @@ interface CrateNavProps { const CrateNav: React.FC = ({ nsfront, nsbehind, name, version }) => { const pathname = usePathname(); const basePath = `/${nsfront}/${nsbehind}/${name}/${version}`; + const [isOpen, setIsOpen] = useState(false); + const [currentVersion, setCurrentVersion] = useState(version); + const [searchTerm, setSearchTerm] = useState(''); + const { crateData, setCrateData } = useHeaderContext(); const navItems = [ { name: 'Overview', path: '' }, @@ -21,6 +27,22 @@ const CrateNav: React.FC = ({ nsfront, nsbehind, name, version }) { name: 'Versions', path: '/versions' }, ]; + useEffect(() => { + const fetchData = async () => { + if (!crateData.results) { + const response = await fetch(`/api/crates/${nsfront}/${nsbehind}/${name}/${version}`); + const data = await response.json(); + setCrateData({ + crateName: data.crate_name, + crateVersion: version, + results: data, + }); + } + }; + + fetchData(); + }, [nsfront, nsbehind, name, version, setCrateData, crateData.results]); + const isActive = (path: string) => { if (path === '') { return pathname === basePath; @@ -28,25 +50,91 @@ const CrateNav: React.FC = ({ nsfront, nsbehind, name, version }) return pathname === `${basePath}${path}`; }; + const toggleDropdown = () => { + setIsOpen((prev) => !prev); + }; + + const closeDropdown = () => { + setIsOpen(false); + }; + return (
- +
); }; diff --git a/components/HeaderWithSearch.tsx b/components/HeaderWithSearch.tsx index 75c08d3..9e24d94 100644 --- a/components/HeaderWithSearch.tsx +++ b/components/HeaderWithSearch.tsx @@ -1,83 +1,34 @@ // components/Header.js 'use client'; -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import Link from 'next/link'; -import { useHeaderContext } from '../app/context/CrateContext'; -import { useParams } from 'next/navigation'; import { message } from 'antd'; -import { useRouter } from 'next/navigation'; -// import { cratesInfo } from '@/app/lib/all_interface'; const Header = () => { - const router = useRouter(); - console.log('paramsssssssssssss:', router.refresh); - const params = useParams(); - const [messageApi, contextHolder] = message.useMessage();//antd-message的hooks调用 + const [messageApi, contextHolder] = message.useMessage(); const [searchQuery, setSearchQuery] = useState(''); - const { crateData, setCrateData } = useHeaderContext(); - const [isOpen, setIsOpen] = useState(false); - - - const [currentVersion, setCurrentVersion] = useState(params.version); // 存储当前选中的版本 const handleKeyPress = (e: { key: string; }) => { - // 检查是否按下了回车键 if (e.key === 'Enter') { - // 如果是回车键,执行搜索 performSearch(); } }; const performSearch = () => { if (!searchQuery || searchQuery.trim() === '') { - messageApi.warning('请输入搜索内容'); - //alert("请输入搜索内容"); // 可选:提示用户输入内容 } if (searchQuery.trim()) { - // 使用 Link 跳转到搜索页面 window.location.href = `/search?crate_name=${searchQuery}`; } }; - useEffect(() => { - const path = params.path || ''; // 确保有值 - console.log('path:', path); - }, [params.path]); // 依赖于 params.path - // 使用 useEffect 从 API 获取数据 - useEffect(() => { - const fetchData = async () => { - // 如果 crateData.results 为空,说明数据还未加载 - if (!crateData.results) { - const response = await fetch(`/api/crates/${params.nsfront}/${params.nsbehind}/${params.name}/${params.version}`); - const data = await response.json(); - console.log('dataaaaaaaaaaaaaa:', data); - setCrateData({ - crateName: data.crate_name, - crateVersion: params.version, - results: data, - }); - - } - }; - - fetchData(); - }, [params.nsfront, params.nsbehind, params.name, params.version, setCrateData, crateData.crateVersion, crateData.results]); // 添加 crateData 作为依赖项 - - const toggleDropdown = () => { - setIsOpen((prev) => !prev); - }; - - const closeDropdown = () => { - setIsOpen(false); - - }; return ( <> {contextHolder}
-
+
open @@ -87,55 +38,8 @@ const Header = () => { insights
-
- {params.name} -
- - {isOpen && ( -
-
-
-
    - {crateData.results?.versions.map((version, index) => ( - { - setCurrentVersion(version); - }} - href={`/${params.nsfront}/${params.nsbehind}/${crateData.results?.crate_name}/${version}`} - > -
  • - - {version} - -
  • - - ))} -
-
-
- )} -
-
-
+
{
- ); }; diff --git a/package.json b/package.json index 6d69e83..b9ef0c6 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,10 @@ "@types/node": "22.13.10", "@types/react": "18.3.12", "@types/react-dom": "18.3.1", - "eslint": "9.22.0", + "eslint": "9.21.0", "eslint-config-next": "^15.1.0" }, "engines": { "node": ">=20.12.0" } -} +} \ No newline at end of file diff --git a/public/images/homepage/1.png b/public/images/homepage/1.png new file mode 100644 index 0000000..dbdf38c Binary files /dev/null and b/public/images/homepage/1.png differ diff --git a/public/images/homepage/2.png b/public/images/homepage/2.png new file mode 100644 index 0000000..dc95d5a Binary files /dev/null and b/public/images/homepage/2.png differ diff --git a/public/images/homepage/3.png b/public/images/homepage/3.png new file mode 100644 index 0000000..80cb138 Binary files /dev/null and b/public/images/homepage/3.png differ diff --git a/public/images/homepage/4.png b/public/images/homepage/4.png new file mode 100644 index 0000000..df42690 Binary files /dev/null and b/public/images/homepage/4.png differ diff --git a/public/images/homepage/5.png b/public/images/homepage/5.png new file mode 100644 index 0000000..29342f1 Binary files /dev/null and b/public/images/homepage/5.png differ diff --git a/public/images/homepage/Vector.png b/public/images/homepage/Vector.png new file mode 100644 index 0000000..674181e Binary files /dev/null and b/public/images/homepage/Vector.png differ diff --git a/public/images/homepage/miss.png b/public/images/homepage/miss.png new file mode 100644 index 0000000..8e28a1e Binary files /dev/null and b/public/images/homepage/miss.png differ diff --git a/public/images/homepage/verison-up.png b/public/images/homepage/verison-up.png new file mode 100644 index 0000000..04701a6 Binary files /dev/null and b/public/images/homepage/verison-up.png differ diff --git a/public/images/homepage/version-down.png b/public/images/homepage/version-down.png new file mode 100644 index 0000000..e648b56 Binary files /dev/null and b/public/images/homepage/version-down.png differ