feat(stats): 重构统计区域样式并优化数据展示

- 使用grid布局重构统计区域,替换原有的flex布局
- 添加响应式设计,适配PC、平板和移动端显示
- 为统计项添加悬停效果和过渡动画
- 集成verCount统计服务,替换不蒜子统计
- 添加数据格式化功能,支持K/W/M单位显示
- 增加访客数和访问量的国际化支持
- 优化统计数字的显示格式和可读性
This commit is contained in:
hehh
2025-11-25 16:47:21 +08:00
parent 3b81941a48
commit 7776df1268
3 changed files with 170 additions and 40 deletions

View File

@@ -151,10 +151,12 @@
<span class="stat-key" data-i18n="stats.followers">Followers</span>
</div>
<div class="stat-item">
<span class="stat-val neon-font" id="visit-count">
<span id="busuanzi_value_site_pv">--</span>
</span>
<span class="stat-key">Visitors</span>
<span id="busuanzi_value_site_pv" style='display:none'>0</span>
<span class="stat-key" data-i18n="stats.visitNum">Visit num</span>
</div>
<div class="stat-item">
<span id="busuanzi_value_site_uv" style='display:none'>0</span>
<span class="stat-key" data-i18n="stats.visitors">Visitors</span>
</div>
</div>
@@ -324,11 +326,16 @@
<script src="https://cdn.jsdelivr.net/npm/artalk@latest/dist/i18n/en.js"></script>
<script src="js/about.js?version=20251125"></script>
<!-- 不蒜子统计 -->
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<!-- verCount统计 -->
<script defer src="https://events.vercount.one/js"></script>
<script>
!function(p){"use strict";!function(t){var s=window,e=document,i=p,c="".concat("https:"===e.location.protocol?"https://":"http://","sdk.51.la/js-sdk-pro.min.js"),n=e.createElement("script"),r=e.getElementsByTagName("script")[0];n.type="text/javascript",n.setAttribute("charset","UTF-8"),n.async=!0,n.src=c,n.id="LA_COLLECT",i.d=n;var o=function(){s.LA.ids.push(i)};s.LA?s.LA.ids&&o():(s.LA=p,s.LA.ids=[],o()),r.parentNode.insertBefore(n,r)}()}({id:"3OBGjwDdEIRS7XZ1",ck:"3OBGjwDdEIRS7XZ1"});
try {
!function(p){"use strict";!function(t){var s=window,e=document,i=p,c="".concat("https:"===e.location.protocol?"https://":"http://","sdk.51.la/js-sdk-pro.min.js"),n=e.createElement("script"),r=e.getElementsByTagName("script")[0];n.type="text/javascript",n.setAttribute("charset","UTF-8"),n.async=!0,n.src=c,n.id="LA_COLLECT",i.d=n;var o=function(){s.LA.ids.push(i)};s.LA?s.LA.ids&&o():(s.LA=p,s.LA.ids=[],o()),r.parentNode.insertBefore(n,r)}()}({id:"3OBGjwDdEIRS7XZ1",ck:"3OBGjwDdEIRS7XZ1"});
} catch (e) {
console.log("51.la统计错误", e);
}
</script>
<script>
// 百度站点统计
@@ -346,29 +353,68 @@
})();
</script>
<!-- 先定义 gtag 函数作为安全兜底 -->
<script type="text/javascript">
try {
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
<!-- 自动格式化脚本 -->
<script>
// 核心格式化函数:支持 K / W / M保留最多两位小数去除尾随零
function formatWithUnit(num) {
num = Number(num);
if (isNaN(num) || num < 0) return '0';
// 小于 1000直接显示
if (num < 1_000) {
return Math.floor(num).toString();
}
gtag('js', new Date());
} catch (e) {
console.log("Google Analytics Init 错误", e);
// 1K ~ 9.99K
if (num < 10_000) {
let val = (num / 1_000).toFixed(2);
return parseFloat(val) + 'K';
}
// 1W ~ 99.99W 1W = 10,000
if (num < 1_000_000) {
let val = (num / 10_000).toFixed(2);
return parseFloat(val) + 'W';
}
// ≥ 1M
let val = (num / 1_000_000).toFixed(2);
return parseFloat(val) + 'M';
}
</script>
// 监听不蒜子数据更新并格式化
function initFormatter() {
const pvEl = document.getElementById('busuanzi_value_site_pv');
const uvEl = document.getElementById('busuanzi_value_site_uv');
<!-- 再异步加载 Google 的 gtag.js -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-DYWDEVKDP0"></script>
if (!pvEl && !uvEl) return;
<!-- 可选:继续调用 config -->
<script type="text/javascript">
try {
gtag('config', 'G-DYWDEVKDP0');
} catch (e) {
console.error("Google Analytics config 失败", e);
const observer = new MutationObserver(() => {
if (pvEl?.textContent) {
const raw = pvEl.textContent.trim().replace(/[,]/g, '');
const num = parseFloat(raw);
if (!isNaN(num)) {
pvEl.textContent = formatWithUnit(num);
}
}
if (uvEl?.textContent) {
const raw = uvEl.textContent.trim().replace(/[,]/g, '');
const num = parseFloat(raw);
if (!isNaN(num)) {
uvEl.textContent = formatWithUnit(num);
}
}
});
if (pvEl) observer.observe(pvEl, { childList: true, subtree: true });
if (uvEl) observer.observe(uvEl, { childList: true, subtree: true });
}
// 启动
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initFormatter);
} else {
initFormatter();
}
</script>
</body>