mirror of
https://github.com/afoim/fuwari.git
synced 2026-01-31 09:03:18 +08:00
100 lines
4.5 KiB
Plaintext
100 lines
4.5 KiB
Plaintext
---
|
||
import { Icon } from "astro-icon/components";
|
||
import { profileConfig, umamiConfig } from "../../config";
|
||
import { url } from "../../utils/url-utils";
|
||
import ImageWrapper from "../misc/ImageWrapper.astro";
|
||
|
||
const config = profileConfig;
|
||
---
|
||
<div class="card-base p-3">
|
||
<a aria-label="Go to About Page" href={url('/about/')}
|
||
class="group block relative mx-auto mt-1 lg:mx-0 lg:mt-0 mb-3
|
||
max-w-[12rem] lg:max-w-none overflow-hidden rounded-xl active:scale-95">
|
||
<div class="absolute transition pointer-events-none group-hover:bg-black/30 group-active:bg-black/50
|
||
w-full h-full z-50 flex items-center justify-center">
|
||
<Icon name="fa6-regular:address-card"
|
||
class="transition opacity-0 scale-90 group-hover:scale-100 group-hover:opacity-100 text-white text-5xl">
|
||
</Icon>
|
||
</div>
|
||
<ImageWrapper src={config.avatar || ""} alt="Profile Image of the Author" class="mx-auto lg:w-full h-full lg:mt-0 "></ImageWrapper>
|
||
</a>
|
||
<div class="px-2">
|
||
<div class="font-bold text-xl text-center mb-1 dark:text-neutral-50 transition">{config.name}</div>
|
||
<div class="h-1 w-5 bg-[var(--primary)] mx-auto rounded-full mb-2 transition"></div>
|
||
<div class="text-center text-neutral-400 mb-2.5 transition">{config.bio}</div>
|
||
<div class="flex flex-wrap gap-2 justify-center mb-1">
|
||
{config.links.length > 1 && config.links.map(item =>
|
||
<a rel="me" aria-label={item.name} href={item.url} target="_blank" class="btn-regular rounded-lg h-10 w-10 active:scale-90">
|
||
<Icon name={item.icon} class="text-[1.5rem]"></Icon>
|
||
</a>
|
||
)}
|
||
{config.links.length == 1 && <a rel="me" aria-label={config.links[0].name} href={config.links[0].url} target="_blank"
|
||
class="btn-regular rounded-lg h-10 gap-2 px-3 font-bold active:scale-95">
|
||
<Icon name={config.links[0].icon} class="text-[1.5rem]"></Icon>
|
||
{config.links[0].name}
|
||
</a>}
|
||
</div>
|
||
|
||
<!-- 全站访问量统计 -->
|
||
<div class="text-center text-sm text-neutral-500 dark:text-neutral-400 mt-3 pt-3 border-t border-neutral-200 dark:border-neutral-700">
|
||
<div class="flex items-center justify-center gap-1">
|
||
<Icon name="material-symbols:visibility-outline" class="text-base"></Icon>
|
||
<span id="site-stats">加载中...</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script define:vars={{ umamiConfig }}>
|
||
// 获取全站访问量统计
|
||
async function loadSiteStats() {
|
||
if (!umamiConfig.enable) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
// 调用全局工具获取 Umami 分享数据
|
||
const { websiteId, token } = await getUmamiShareData(umamiConfig.baseUrl, umamiConfig.shareId);
|
||
|
||
// 第二步:获取全站统计数据(不指定url参数获取全站数据)
|
||
const currentTimestamp = Date.now();
|
||
const statsUrl = `${umamiConfig.baseUrl}/api/websites/${websiteId}/stats?startAt=0&endAt=${currentTimestamp}&unit=hour&timezone=${encodeURIComponent(umamiConfig.timezone)}&compare=false`;
|
||
|
||
const statsResponse = await fetch(statsUrl, {
|
||
headers: {
|
||
'x-umami-share-token': token
|
||
}
|
||
});
|
||
|
||
if (statsResponse.status === 401) {
|
||
// token 失效,清理缓存后重新获取一次
|
||
clearUmamiShareCache();
|
||
return await loadSiteStats();
|
||
}
|
||
|
||
if (!statsResponse.ok) {
|
||
throw new Error('获取统计数据失败');
|
||
}
|
||
|
||
const statsData = await statsResponse.json();
|
||
const pageviews = statsData.pageviews?.value || 0;
|
||
const visitors = statsData.visits?.value || 0;
|
||
|
||
const statsElement = document.getElementById('site-stats');
|
||
if (statsElement) {
|
||
statsElement.textContent = `浏览量 ${pageviews} · 访问数 ${visitors}`;
|
||
}
|
||
} catch (error) {
|
||
console.error('获取全站统计失败:', error);
|
||
const statsElement = document.getElementById('site-stats');
|
||
if (statsElement) {
|
||
statsElement.textContent = '统计不可用';
|
||
}
|
||
}
|
||
}
|
||
|
||
// 页面加载完成后获取统计数据
|
||
document.addEventListener('DOMContentLoaded', loadSiteStats);
|
||
</script>
|
||
|