57 lines
1.6 KiB
TypeScript
57 lines
1.6 KiB
TypeScript
"use client";
|
||
|
||
import { useEffect } from "react";
|
||
|
||
export function FaviconUpdater() {
|
||
useEffect(() => {
|
||
let isDisposed = false;
|
||
|
||
// 从 API 获取最新的 favicon 设置
|
||
fetch("/api/site-settings")
|
||
.then((res) => res.json())
|
||
.then((settings) => {
|
||
if (!settings.favicon || isDisposed) {
|
||
return;
|
||
}
|
||
|
||
const faviconUrl = settings.favicon;
|
||
const timestamp = Date.now();
|
||
const urlWithCache = `${faviconUrl}${faviconUrl.includes("?") ? "&" : "?"}v=${timestamp}`;
|
||
|
||
// 仅处理本组件创建的 link,避免删除 Next/React 管理的 head 节点
|
||
const oldLinks = document.querySelectorAll(
|
||
'link[data-managed-favicon="true"]'
|
||
);
|
||
oldLinks.forEach((link) => {
|
||
if (link.parentNode) {
|
||
link.parentNode.removeChild(link);
|
||
}
|
||
});
|
||
|
||
const createManagedLink = (rel: string, href: string, type?: string) => {
|
||
const link = document.createElement("link");
|
||
link.rel = rel;
|
||
link.href = href;
|
||
link.setAttribute("data-managed-favicon", "true");
|
||
if (type) {
|
||
link.type = type;
|
||
}
|
||
document.head.appendChild(link);
|
||
};
|
||
|
||
createManagedLink("icon", urlWithCache, "image/x-icon");
|
||
createManagedLink("apple-touch-icon", urlWithCache);
|
||
createManagedLink("shortcut icon", urlWithCache);
|
||
})
|
||
.catch((error) => {
|
||
console.error("[Favicon] Error updating favicon:", error);
|
||
});
|
||
|
||
return () => {
|
||
isDisposed = true;
|
||
};
|
||
}, []);
|
||
|
||
return null;
|
||
}
|