Skip to content

Commit 879b799

Browse files
committed
feat: add GitHub star counter with caching
1 parent ec8b86e commit 879b799

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

src/components/GitHubStarCounter.tsx

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
import { useState, useEffect } from 'react';
2+
import { GithubOutlined } from '@ant-design/icons';
3+
import { Tooltip } from 'antd';
4+
5+
interface GitHubStarCounterProps {
6+
owner: string;
7+
repo: string;
8+
cacheTime?: number; // 缓存时间,单位:毫秒,默认30分钟
9+
}
10+
11+
const CACHE_KEY = 'github-stars-cache';
12+
13+
interface StarCache {
14+
count: number;
15+
timestamp: number;
16+
owner: string;
17+
repo: string;
18+
}
19+
20+
/**
21+
* GitHub Star计数器组件
22+
* 显示项目的star数,并支持缓存
23+
*/
24+
const GitHubStarCounter: React.FC<GitHubStarCounterProps> = ({
25+
owner,
26+
repo,
27+
cacheTime = 30 * 60 * 1000 // 默认30分钟
28+
}) => {
29+
const [starCount, setStarCount] = useState<number | null>(null);
30+
const [loading, setLoading] = useState(true);
31+
32+
useEffect(() => {
33+
const fetchStarCount = async () => {
34+
try {
35+
// 尝试从缓存中获取
36+
const cachedData = localStorage.getItem(CACHE_KEY);
37+
if (cachedData) {
38+
const cache: StarCache = JSON.parse(cachedData);
39+
40+
// 检查是否是同一仓库的缓存
41+
if (cache.owner === owner && cache.repo === repo) {
42+
// 检查缓存是否过期
43+
const now = Date.now();
44+
if (now - cache.timestamp < cacheTime) {
45+
setStarCount(cache.count);
46+
setLoading(false);
47+
return;
48+
}
49+
}
50+
}
51+
52+
// 缓存不存在或已过期,发起请求
53+
const response = await fetch(`https://api.github.com/repos/${owner}/${repo}`);
54+
55+
if (!response.ok) {
56+
throw new Error('Failed to fetch repo data');
57+
}
58+
59+
const data = await response.json();
60+
const count = data.stargazers_count;
61+
62+
// 更新缓存
63+
const cacheData: StarCache = {
64+
count,
65+
timestamp: Date.now(),
66+
owner,
67+
repo
68+
};
69+
70+
localStorage.setItem(CACHE_KEY, JSON.stringify(cacheData));
71+
setStarCount(count);
72+
} catch (error) {
73+
console.error('Error fetching GitHub stars:', error);
74+
// 如果请求失败但有缓存,使用缓存数据,不管是否过期
75+
const cachedData = localStorage.getItem(CACHE_KEY);
76+
if (cachedData) {
77+
const cache: StarCache = JSON.parse(cachedData);
78+
if (cache.owner === owner && cache.repo === repo) {
79+
setStarCount(cache.count);
80+
}
81+
}
82+
} finally {
83+
setLoading(false);
84+
}
85+
};
86+
87+
fetchStarCount();
88+
}, [owner, repo, cacheTime]);
89+
90+
// 样式
91+
const containerStyle = {
92+
display: 'inline-flex',
93+
alignItems: 'center',
94+
justifyContent: 'center',
95+
fontWeight: 500,
96+
fontSize: '14px',
97+
padding: '4px 8px',
98+
border: '1px solid #e1e4e8',
99+
borderRadius: '6px',
100+
color: '#24292e',
101+
backgroundColor: '#f6f8fa',
102+
cursor: 'pointer',
103+
transition: 'all 0.2s ease',
104+
height: '28px',
105+
lineHeight: '20px'
106+
};
107+
108+
// 当鼠标悬停时的样式
109+
const hoverStyle = {
110+
backgroundColor: '#e1e4e8'
111+
};
112+
113+
return (
114+
<Tooltip title="Star us on GitHub">
115+
<a
116+
href={`https://github.com/${owner}/${repo}`}
117+
target="_blank"
118+
rel="noopener noreferrer"
119+
style={containerStyle}
120+
onMouseOver={(e) => {
121+
Object.assign(e.currentTarget.style, hoverStyle);
122+
}}
123+
onMouseOut={(e) => {
124+
Object.assign(e.currentTarget.style, containerStyle);
125+
}}
126+
>
127+
<GithubOutlined style={{ marginRight: '6px' }} />
128+
{loading ? '...' : `${starCount || 0}`}
129+
</a>
130+
</Tooltip>
131+
);
132+
};
133+
134+
export default GitHubStarCounter;

src/components/NavBar.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { PlusOutlined, MenuOutlined } from '@ant-design/icons';
66
import { useTranslation } from 'react-i18next';
77
import { changeLanguage } from '../i18n';
88
import { useMediaQuery } from 'react-responsive';
9+
import GitHubStarCounter from './GitHubStarCounter';
910
// @ts-ignore
1011
import faviconLogo from '../assets/favicon.png';
1112
// @ts-ignore
@@ -169,6 +170,9 @@ const NavBar = () => {
169170
alignItems: 'center',
170171
gap: '8px'
171172
}}>
173+
{/* GitHub Star计数 */}
174+
<GitHubStarCounter owner="JSREP" repo="crawler-leetcode" />
175+
172176
{/* 贡献题目按钮 */}
173177
<Button
174178
type="primary"
@@ -216,6 +220,11 @@ const NavBar = () => {
216220
style={{ border: 'none' }}
217221
/>
218222
<div style={{ marginTop: 24, padding: '0 16px' }}>
223+
{/* 移动端GitHub Star计数 */}
224+
<div style={{ marginBottom: 16, display: 'flex', justifyContent: 'center' }}>
225+
<GitHubStarCounter owner="JSREP" repo="crawler-leetcode" />
226+
</div>
227+
219228
<Button
220229
type="primary"
221230
icon={<PlusOutlined />}

0 commit comments

Comments
 (0)