@@ -45,12 +45,13 @@ const currentReading = bookshelfData.find((item: any) => item.status === 'readin
4545 { /* 最近在读 - 详细信息 */ }
4646 { currentReading && (
4747 <div class = ' dashboard-card reading-card group relative overflow-hidden rounded-lg border bg-background p-6 hover:border-primary/50 transition-all' >
48- <div class = ' absolute inset-0 bg-gradient-to-br from-purple-500/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500' ></div >
48+ { /* 背景图片层 */ }
49+ <div class = ' absolute inset-0 bg-gradient-to-br from-purple-500/20 via-purple-400/10 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-700 scale-110 group-hover:scale-100' ></div >
4950 <div class = ' absolute top-0 right-0 w-32 h-32 bg-purple-500/5 rounded-full blur-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500' ></div >
5051 <div class = ' relative' >
5152 <div class = ' flex items-start gap-4 mb-4' >
52- <div class = ' size-8 rounded-lg bg-purple-100 dark:bg-purple-900 flex items-center justify-center group-hover:scale-110 transition-all duration-300 flex-shrink-0' >
53- <Icon name = ' shelf ' class = ' size-5 text-purple-600 dark:text-purple-400' />
53+ <div class = ' icon-mask size-8 rounded-lg bg-purple-100 dark:bg-purple-900 flex items-center justify-center transition-all duration-500 flex-shrink-0' >
54+ <Icon name = ' book ' class = ' size-5 text-purple-600 dark:text-purple-400 transition-all duration-500 ' />
5455 </div >
5556 <div class = ' flex-1 min-w-0' >
5657 <div class = ' flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 mb-1' >
@@ -96,13 +97,14 @@ const currentReading = bookshelfData.find((item: any) => item.status === 'readin
9697
9798 { /* 最新文章 */ }
9899 <div class =' dashboard-card posts-card group relative overflow-hidden rounded-lg border bg-background p-6 hover:border-primary/50 transition-all' >
99- <div class =' absolute inset-0 bg-gradient-to-br from-blue-500/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500' ></div >
100+ { /* 背景图片层 */ }
101+ <div class =' absolute inset-0 bg-gradient-to-br from-blue-500/20 via-blue-400/10 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-700 scale-110 group-hover:scale-100' ></div >
100102 <div class =' absolute top-0 right-0 w-32 h-32 bg-blue-500/5 rounded-full blur-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500' ></div >
101103 <div class =' relative' >
102104 <div class =' flex items-center justify-between mb-4' >
103105 <div class =' flex items-center gap-2' >
104- <div class =' size-8 rounded-lg bg-blue-100 dark:bg-blue-900 flex items-center justify-center group-hover:scale-110 transition-all duration-300 ' >
105- <Icon name =' document' class =' size-5 text-blue-600 dark:text-blue-400' />
106+ <div class =' icon-mask size-8 rounded-lg bg-blue-100 dark:bg-blue-900 flex items-center justify-center transition-all duration-500 ' >
107+ <Icon name =' document' class =' size-5 text-blue-600 dark:text-blue-400 transition-all duration-500 ' />
106108 </div >
107109 <h2 class =' text-lg font-semibold text-foreground' >最新文章</h2 >
108110 </div >
@@ -173,38 +175,69 @@ const currentReading = bookshelfData.find((item: any) => item.status === 'readin
173175
174176 { /* 统计卡片 */ }
175177 <div class =' dashboard-card stats-card group relative overflow-hidden rounded-lg border bg-background p-6 hover:border-primary/50 transition-all' >
176- <div class =' absolute inset-0 bg-gradient-to-br from-blue-500/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500' ></div >
178+ { /* 背景图片层 */ }
179+ <div class =' absolute inset-0 bg-gradient-to-br from-blue-500/20 via-blue-400/10 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-700 scale-110 group-hover:scale-100' ></div >
177180 <div class =' absolute top-0 right-0 w-32 h-32 bg-blue-500/5 rounded-full blur-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500' ></div >
178181 <div class =' relative' >
179182 <div class =' flex items-center gap-2 mb-4' >
180- <div class =' size-8 rounded-lg bg-blue-100 dark:bg-blue-900 flex items-center justify-center group-hover:scale-110 transition-all duration-300 ' >
181- <Icon name =' content-statistic' class =' size-5 text-blue-600 dark:text-blue-400' />
183+ <div class =' icon-mask size-8 rounded-lg bg-blue-100 dark:bg-blue-900 flex items-center justify-center transition-all duration-500 ' >
184+ <Icon name =' content-statistic' class =' size-5 text-blue-600 dark:text-blue-400 transition-all duration-500 ' />
182185 </div >
183186 <h2 class =' text-lg font-semibold text-foreground' >统计</h2 >
184187 </div >
185- <div class =' grid grid-cols-2 gap-4' >
186- <div class =' text-center p-3 rounded-lg bg-muted/50' >
187- <div class =' text-2xl font-bold text-foreground mb-1' >{ totalPosts } </div >
188- <div class =' text-xs text-muted-foreground' >文章总数</div >
188+
189+ <div class =' space-y-2' >
190+ { /* 文章总数 */ }
191+ <div class =' flex items-center gap-0 overflow-hidden rounded-md border border-purple-200 dark:border-purple-800' >
192+ <div class =' px-3 py-1 text-sm font-medium text-purple-700 dark:text-purple-300 bg-purple-50 dark:bg-purple-950/30 text-left' >∑ 文章</div >
193+ <div class =' flex items-center gap-2 px-3 py-1 bg-purple-100 dark:bg-purple-900 flex-1' >
194+ <span class =' text-sm font-semibold text-purple-900 dark:text-purple-100' >{ totalPosts } / 100</span >
195+ <div class =' h-1 flex-1 max-w-32 bg-purple-200 dark:bg-purple-800 rounded-full overflow-hidden relative' >
196+ <div class =' h-full bg-gradient-to-r from-purple-500 to-purple-600 transition-all duration-1000 charging-animation' style ={ ` width: ${Math .min ((totalPosts / 100 ) * 100 , 100 )}% ` } ></div >
197+ </div >
198+ </div >
199+ </div >
200+
201+ { /* 总字数 */ }
202+ <div class =' flex items-center gap-0 overflow-hidden rounded-md border border-blue-200 dark:border-blue-800' >
203+ <div class =' px-3 py-1 text-sm font-medium text-blue-700 dark:text-blue-300 bg-blue-50 dark:bg-blue-950/30 text-left' >∑ 字数</div >
204+ <div class =' flex items-center gap-2 px-3 py-1 bg-blue-100 dark:bg-blue-900 flex-1' >
205+ <span class =' text-sm font-semibold text-blue-900 dark:text-blue-100' >
206+ <span id =' total-words-display' >{ totalWords .toLocaleString ()} </span > / 10万
207+ </span >
208+ <div class =' h-1 flex-1 max-w-32 bg-blue-200 dark:bg-blue-800 rounded-full overflow-hidden relative' >
209+ <div class =' h-full bg-gradient-to-r from-blue-500 to-blue-600 transition-all duration-1000 charging-animation' style ={ ` width: ${Math .min ((totalWords / 100000 ) * 100 , 100 )}% ` } ></div >
210+ </div >
211+ </div >
189212 </div >
190- <div class =' text-center p-3 rounded-lg bg-muted/50' >
191- <div class =' text-2xl font-bold text-foreground mb-1' >
192- <span id =' total-words-counter' class =' inline-block' >{ totalWords .toLocaleString ()} </span >
213+
214+ { /* 总浏览量 */ }
215+ <div class =' flex items-center gap-0 overflow-hidden rounded-md border border-green-200 dark:border-green-800' >
216+ <div class =' px-3 py-1 text-sm font-medium text-green-700 dark:text-green-300 bg-green-50 dark:bg-green-950/30 text-left' >∑ 浏览</div >
217+ <div class =' flex items-center gap-2 px-3 py-1 bg-green-100 dark:bg-green-900 flex-1' >
218+ <span class =' text-sm font-semibold text-green-900 dark:text-green-100' >
219+ <span id =' total-views-display' >-</span > / 100万
220+ </span >
221+ <div class =' h-1 flex-1 max-w-32 bg-green-200 dark:bg-green-800 rounded-full overflow-hidden relative' >
222+ <div id =' total-views-progress' class =' h-full bg-gradient-to-r from-green-500 to-green-600 transition-all duration-1000 charging-animation' style =' width: 0%' ></div >
223+ </div >
193224 </div >
194- <div class =' text-xs text-muted-foreground' >总字数</div >
195225 </div >
226+
227+ <span id =' vercount_value_site_pv' class =' hidden' ></span >
196228 </div >
197229 </div >
198230 </div >
199231
200232 { /* GitHub 活动图 */ }
201233 <div class =' dashboard-card github-card group relative overflow-hidden rounded-lg border bg-background p-6 hover:border-primary/50 transition-all' >
202- <div class =' absolute inset-0 bg-gradient-to-br from-orange-500/5 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500' ></div >
234+ { /* 背景图片层 */ }
235+ <div class =' absolute inset-0 bg-gradient-to-br from-orange-500/20 via-orange-400/10 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-700 scale-110 group-hover:scale-100' ></div >
203236 <div class =' absolute top-0 right-0 w-32 h-32 bg-orange-500/5 rounded-full blur-3xl opacity-0 group-hover:opacity-100 transition-opacity duration-500' ></div >
204237 <div class =' relative' >
205238 <div class =' flex items-center gap-2 mb-4' >
206- <div class =' size-8 rounded-lg bg-orange-100 dark:bg-orange-900 flex items-center justify-center group-hover:scale-110 transition-all duration-300 ' >
207- <Icon name =' github' class =' size-5 text-orange-600 dark:text-orange-400' />
239+ <div class =' icon-mask size-8 rounded-lg bg-orange-100 dark:bg-orange-900 flex items-center justify-center transition-all duration-500 ' >
240+ <Icon name =' github' class =' size-5 text-orange-600 dark:text-orange-400 transition-all duration-500 ' />
208241 </div >
209242 <h2 class =' text-lg font-semibold text-foreground' >GitHub</h2 >
210243 </div >
@@ -274,17 +307,57 @@ const currentReading = bookshelfData.find((item: any) => item.status === 'readin
274307 }
275308 }
276309
310+ // 更新总浏览量显示和进度条
311+ function updateViewsDisplay(viewsElement, progressElement, newValue) {
312+ if (viewsElement && progressElement && newValue && newValue !== '-') {
313+ const views = parseInt(newValue.replace(/,/g, ''));
314+ viewsElement.textContent = views.toLocaleString();
315+
316+ // 更新进度条
317+ const percentage = Math.min((views / 1000000) * 100, 100);
318+ progressElement.style.width = percentage + '%';
319+ }
320+ }
321+
277322 // 页面加载后启动动画
278323 document.addEventListener('DOMContentLoaded', () => {
279- const counterElement = document.getElementById('total-words-counter');
280- if (counterElement) {
281- const targetValue = counterElement.textContent;
282- counterElement.textContent = '0';
324+ // 总字数滚动动画
325+ const wordsDisplayElement = document.getElementById('total-words-display');
326+ if (wordsDisplayElement) {
327+ const targetValue = wordsDisplayElement.textContent;
328+ wordsDisplayElement.textContent = '0';
283329 setTimeout(() => {
284- animateCounter(counterElement , targetValue, 2000);
330+ animateCounter(wordsDisplayElement , targetValue, 2000);
285331 }, 500);
286332 }
287333
334+ // 监听总浏览量更新
335+ const viewsDisplayElement = document.getElementById('total-views-display');
336+ const viewsProgressElement = document.getElementById('total-views-progress');
337+ const vercountElement = document.getElementById('vercount_value_site_pv');
338+
339+ if (viewsDisplayElement && viewsProgressElement && vercountElement) {
340+ // 使用 MutationObserver 监听 vercount 元素的变化
341+ const observer = new MutationObserver((mutations) => {
342+ mutations.forEach((mutation) => {
343+ if (mutation.type === 'childList' || mutation.type === 'characterData') {
344+ const newValue = vercountElement.textContent;
345+ updateViewsDisplay(viewsDisplayElement, viewsProgressElement, newValue);
346+ }
347+ });
348+ });
349+
350+ observer.observe(vercountElement, {
351+ childList: true,
352+ characterData: true,
353+ subtree: true
354+ });
355+
356+ // 立即检查一次(如果值已经加载)
357+ const currentValue = vercountElement.textContent;
358+ updateViewsDisplay(viewsDisplayElement, viewsProgressElement, currentValue);
359+ }
360+
288361 // 初始化邮箱链接
289362 obfuscateEmail();
290363 });
@@ -338,6 +411,50 @@ const currentReading = bookshelfData.find((item: any) => item.status === 'readin
338411 }
339412 }
340413
414+ /* 充电动画效果 */
415+ .charging-animation {
416+ position: relative;
417+ overflow: hidden;
418+ animation: pulse 2s ease-in-out infinite;
419+ }
420+
421+ .charging-animation::after {
422+ content: '';
423+ position: absolute;
424+ top: 0;
425+ left: -100%;
426+ width: 100%;
427+ height: 100%;
428+ background: linear-gradient(
429+ 90deg,
430+ transparent,
431+ rgba(255, 255, 255, 0.3),
432+ transparent
433+ );
434+ animation: charging 2s ease-in-out infinite;
435+ }
436+
437+ @keyframes charging {
438+ 0% {
439+ left: -100%;
440+ }
441+ 50% {
442+ left: 100%;
443+ }
444+ 100% {
445+ left: 100%;
446+ }
447+ }
448+
449+ @keyframes pulse {
450+ 0%, 100% {
451+ opacity: 1;
452+ }
453+ 50% {
454+ opacity: 0.9;
455+ }
456+ }
457+
341458
342459 /* 卡片悬停效果 */
343460 .reading-card:hover {
@@ -393,13 +510,44 @@ const currentReading = bookshelfData.find((item: any) => item.status === 'readin
393510 }
394511 }
395512
396- /* 数字滚动动画 */
397- #total-words-counter {
398- transition: transform 0.1s ease-out;
513+ /* 图标遮罩动画效果 */
514+ .icon-mask {
515+ position: relative;
516+ overflow: hidden;
517+ }
518+
519+ .icon-mask::before {
520+ content: '';
521+ position: absolute;
522+ inset: 0;
523+ background: inherit;
524+ opacity: 1;
525+ transition: all 0.5s ease;
399526 }
400527
401- #total-words-counter:hover {
402- transform: scale(1.1);
528+ .icon-mask svg {
529+ position: relative;
530+ z-index: 1;
531+ }
532+
533+ /* 悬停时图标遮罩淡出 */
534+ .group:hover .icon-mask::before {
535+ opacity: 0;
536+ transform: scale(1.5);
537+ }
538+
539+ /* 图标微动画 - 持续浮动 */
540+ .icon-mask svg {
541+ animation: iconFloat 3s ease-in-out infinite;
542+ }
543+
544+ @keyframes iconFloat {
545+ 0%, 100% {
546+ transform: translateY(0);
547+ }
548+ 50% {
549+ transform: translateY(-3px);
550+ }
403551 }
404552
405553</style >
0 commit comments