init
Some checks failed
Clean ESA Versions on Main / clean-esa-versions (push) Has been cancelled

This commit is contained in:
2026-01-02 00:03:49 +08:00
commit 7b7e32ddd4
348 changed files with 148701 additions and 0 deletions

91
public/js/umami-share.js Normal file
View File

@@ -0,0 +1,91 @@
(function (global) {
const cacheKey = 'umami-share-cache';
const cacheTTL = 3600_000; // 1h
async function fetchShareData(baseUrl, shareId) {
const cached = localStorage.getItem(cacheKey);
if (cached) {
try {
const parsed = JSON.parse(cached);
if (Date.now() - parsed.timestamp < cacheTTL) {
return parsed.value;
}
} catch {
localStorage.removeItem(cacheKey);
}
}
const res = await fetch(`${baseUrl}/api/share/${shareId}`);
if (!res.ok) {
throw new Error('获取 Umami 分享信息失败');
}
const data = await res.json();
localStorage.setItem(cacheKey, JSON.stringify({ timestamp: Date.now(), value: data }));
return data;
}
/**
* 获取 Umami 分享数据websiteId、token
* 在缓存 TTL 内复用;并用全局 Promise 避免并发请求
* @param {string} baseUrl
* @param {string} shareId
* @returns {Promise<{websiteId: string, token: string}>}
*/
global.getUmamiShareData = function (baseUrl, shareId) {
if (!global.__umamiSharePromise) {
global.__umamiSharePromise = fetchShareData(baseUrl, shareId).catch((err) => {
delete global.__umamiSharePromise;
throw err;
});
}
return global.__umamiSharePromise;
};
global.clearUmamiShareCache = function () {
localStorage.removeItem(cacheKey);
delete global.__umamiSharePromise;
};
/**
* 获取 Umami 统计数据
* 自动处理 token 获取和过期重试
* @param {string} baseUrl
* @param {string} shareId
* @param {object} queryParams
* @returns {Promise<any>}
*/
global.fetchUmamiStats = async function (baseUrl, shareId, queryParams) {
async function doFetch(isRetry = false) {
const { websiteId, token } = await global.getUmamiShareData(baseUrl, shareId);
const currentTimestamp = Date.now();
const params = new URLSearchParams({
startAt: 0,
endAt: currentTimestamp,
unit: 'hour',
timezone: queryParams.timezone || 'Asia/Shanghai',
compare: false,
...queryParams
});
const statsUrl = `${baseUrl}/api/websites/${websiteId}/stats?${params.toString()}`;
const res = await fetch(statsUrl, {
headers: {
'x-umami-share-token': token
}
});
if (!res.ok) {
if (res.status === 401 && !isRetry) {
global.clearUmamiShareCache();
return doFetch(true);
}
throw new Error('获取统计数据失败');
}
return await res.json();
}
return doFetch();
};
})(window);