Files
AboutMe/src/components/sidebar/profile.astro
2026-02-04 18:00:06 +04:00

120 lines
5.6 KiB
Plaintext

---
import { Icon } from "astro-icon/components";
import { profileConfig, umamiConfig } from "@/config";
import { url } from "@utils/url";
import { i18n } from "@i18n/translation";
import I18nKey from "@i18n/i18nKey";
import ImageWrapper from "@/components/common/imageWrapper.astro";
// 解析 umami
const umamiEnabled = umamiConfig.enabled || false;
const umamiWebsiteId = umamiConfig.scripts.match(/data-website-id="([^"]+)"/)?.[1] || "";
const umamiApiKey = umamiConfig.apiKey || "";
const umamiBaseUrl = umamiConfig.baseUrl || "";
interface Props {
class?: string;
style?: string;
side?: string;
}
const { class: className, style, side = "default" } = Astro.props;
const id = `profile-${side}`;
---
<div id={id} data-swup-persist={id} 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-48 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={profileConfig.avatar || ""} alt="Profile Image of the Author" class="mx-auto lg:w-full h-full lg:mt-0" loading="eager"></ImageWrapper>
</a>
<div class="px-2">
<div class="font-bold text-xl text-center mb-1 dark:text-neutral-50 transition">{profileConfig.name}</div>
<div class="h-1 w-5 bg-(--primary) mx-auto rounded-full mb-2 transition"></div>
<div class="text-center text-neutral-400 mb-2.5 transition">{profileConfig.bio}</div>
<div class="flex gap-2 justify-center mb-1">
{profileConfig.links.length > 1 && profileConfig.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 flex items-center justify-center">
{item.rawIcon ? (
<span class="text-[1.5rem] [&>svg]:w-full [&>svg]:h-full [&>svg]:block" set:html={item.rawIcon}></span>
) : (
<Icon name={item.icon} class="text-[1.5rem]"></Icon>
)}
</a>
)}
{profileConfig.links.length == 1 && <a rel="me" aria-label={profileConfig.links[0].name} href={profileConfig.links[0].url} target="_blank"
class="btn-regular rounded-lg h-10 gap-2 px-3 font-bold active:scale-95 flex items-center">
{profileConfig.links[0].rawIcon ? (
<span class="text-[1.5rem] [&>svg]:w-full [&>svg]:h-full [&>svg]:block" set:html={profileConfig.links[0].rawIcon}></span>
) : (
<Icon name={profileConfig.links[0].icon} class="text-[1.5rem]"></Icon>
)}
{profileConfig.links[0].name}
</a>}
</div>
{umamiEnabled && (
<hr class="my-2 border-t border-dashed border-gray-300 dark:border-gray-700" />
<div class="text-sm text-gray-500 mt-2 text-center"
id="site-stats-container"
data-umami-base-url={umamiBaseUrl}
data-umami-api-key={umamiApiKey}
data-umami-website-id={umamiWebsiteId}
data-i18n-error={i18n(I18nKey.statsError)}
>
<Icon name="fa6-solid:eye" class="inline-block mr-1 text-gray-400 text-sm align-middle" />
<span id="site-stats-display">统计加载中...</span>
</div>
)}
</div>
</div>
{umamiEnabled && (
<script>
import "@/plugins/umami-share";
// 客户端统计文案生成函数
function generateStatsText(pageViews, visits) {
return `浏览量 ${pageViews} · 访问次数 ${visits}`;
}
// 获取访问量统计
async function fetchSiteStats() {
const container = document.getElementById('site-stats-container');
if (!container) return;
const umamiBaseUrl = container.dataset.umamiBaseUrl;
const umamiApiKey = container.dataset.umamiApiKey;
const umamiWebsiteId = container.dataset.umamiWebsiteId;
const i18nError = container.dataset.i18nError;
try {
// 调用全局工具获取 Umami 统计数据
// @ts-ignore
const stats = await window.getUmamiWebsiteStats(umamiBaseUrl, umamiApiKey, umamiWebsiteId);
// 从返回的数据中提取页面浏览量和访客数
const pageViews = stats.pageviews || 0;
const visits = stats.visits || 0;
// 更新页面上的显示内容
const displayElement = document.getElementById('site-stats-display');
if (displayElement) {
displayElement.textContent = generateStatsText(pageViews, visits);
}
} catch (error) {
console.error('Error fetching site stats:', error);
const displayElement = document.getElementById('site-stats-display');
if (displayElement) {
displayElement.textContent = i18nError || null;
}
}
}
// 页面加载完成后获取统计数据
fetchSiteStats();
document.addEventListener('astro:page-load', fetchSiteStats);
</script>
)}