fix: 修复 Umami v3 API 浏览量统计

This commit is contained in:
mckero committed 2025-11-21 12:27:49 +08:00
1 parent 294fe4c092
commit af0a425c72
4 files changed
+43 -50

No files matched your search

+6 -4
View File
@@ -122,14 +122,15 @@ const { remarkPluginFrontmatter } = await entry.render();
// 第一步:获取网站ID和token
const shareResponse = await fetch(`${umamiConfig.baseUrl}/api/share/${umamiConfig.shareId}`);
if (!shareResponse.ok) {
throw new Error('获取分享信息失败');
throw new Error(`获取分享信息失败: ${shareResponse.status}`);
}
const shareData = await shareResponse.json();
const { websiteId, token } = shareData;
// 第二步:获取统计数据
const currentTimestamp = Date.now();
const statsUrl = `${umamiConfig.baseUrl}/api/websites/${websiteId}/stats?startAt=0&endAt=${currentTimestamp}&unit=hour&timezone=${encodeURIComponent(umamiConfig.timezone)}&url=%2Fposts%2F${slug}%2F&compare=false`;
// 使用 path=eq. 前缀进行精确匹配
const statsUrl = `${umamiConfig.baseUrl}/api/websites/${websiteId}/stats?startAt=0&endAt=${currentTimestamp}&unit=hour&timezone=${encodeURIComponent(umamiConfig.timezone)}&path=eq./posts/${slug}/&compare=false`;
const statsResponse = await fetch(statsUrl, {
headers: {
@@ -138,11 +139,12 @@ const { remarkPluginFrontmatter } = await entry.render();
});
if (!statsResponse.ok) {
throw new Error('获取统计数据失败');
throw new Error(`获取统计数据失败: ${statsResponse.status}`);
}
const statsData = await statsResponse.json();
const pageViews = statsData.pageviews?.value || 0;
// Umami v2/v3 兼容:直接读取 pageviews
const pageViews = statsData.pageviews || 0;
const displayElement = document.getElementById(`page-views-${slug}`);
if (displayElement) {
+7 -5
View File
@@ -102,14 +102,15 @@ const className = Astro.props.class;
// 第一步:获取网站ID和token
const shareResponse = await fetch(`${umamiConfig.baseUrl}/api/share/${umamiConfig.shareId}`);
if (!shareResponse.ok) {
throw new Error('获取分享信息失败');
throw new Error(`获取分享信息失败: ${shareResponse.status}`);
}
const shareData = await shareResponse.json();
const { websiteId, token } = shareData;
// 第二步:获取统计数据
const currentTimestamp = Date.now();
const statsUrl = `${umamiConfig.baseUrl}/api/websites/${websiteId}/stats?startAt=0&endAt=${currentTimestamp}&unit=hour&timezone=${encodeURIComponent(umamiConfig.timezone)}&url=%2Fposts%2F${slug}%2F&compare=false`;
// 使用 path=eq. 前缀进行精确匹配
const statsUrl = `${umamiConfig.baseUrl}/api/websites/${websiteId}/stats?startAt=0&endAt=${currentTimestamp}&unit=hour&timezone=${encodeURIComponent(umamiConfig.timezone)}&path=eq./posts/${slug}/&compare=false`;
const statsResponse = await fetch(statsUrl, {
headers: {
@@ -118,12 +119,13 @@ const className = Astro.props.class;
});
if (!statsResponse.ok) {
throw new Error('获取统计数据失败');
throw new Error(`获取统计数据失败: ${statsResponse.status}`);
}
const statsData = await statsResponse.json();
const pageViews = statsData.pageviews?.value || 0;
const visits = statsData.visits?.value || 0;
// Umami v2/v3 兼容
const pageViews = statsData.pageviews || 0;
const visits = statsData.visitors || 0;
const displayElement = document.getElementById('page-views-display');
if (displayElement) {
+5 -4
View File
@@ -56,12 +56,12 @@ const config = profileConfig;
// 第一步:获取网站ID和token
const shareResponse = await fetch(`${umamiConfig.baseUrl}/api/share/${umamiConfig.shareId}`);
if (!shareResponse.ok) {
throw new Error('获取分享信息失败');
throw new Error(`获取分享信息失败: ${shareResponse.status}`);
}
const shareData = await shareResponse.json();
const { websiteId, token } = shareData;
// 第二步:获取全站统计数据(不指定url参数获取全站数据)
// 第二步:获取全站统计数据(不指定path参数获取全站数据)
const currentTimestamp = Date.now();
const statsUrl = `${umamiConfig.baseUrl}/api/websites/${websiteId}/stats?startAt=0&endAt=${currentTimestamp}&unit=hour&timezone=${encodeURIComponent(umamiConfig.timezone)}&compare=false`;
@@ -72,11 +72,12 @@ const config = profileConfig;
});
if (!statsResponse.ok) {
throw new Error('获取统计数据失败');
throw new Error(`获取统计数据失败: ${statsResponse.status}`);
}
const statsData = await statsResponse.json();
const pageviews = statsData.pageviews?.value || 0;
// Umami v2/v3 兼容
const pageviews = statsData.pageviews || 0;
const statsElement = document.getElementById('site-stats');
if (statsElement) {
+25 -37
View File
@@ -12,65 +12,56 @@ import { LinkPreset } from "./types/config";
export const siteConfig: SiteConfig = {
title: "MC_Kero blog",
subtitle: "MC_Kero的博客,有时候会写点文章",
lang: "zh_CN", // Language code, e.g. 'en', 'zh_CN', 'ja', etc.
lang: "zh_CN",
themeColor: {
hue: 355, // Default hue for the theme color, from 0 to 360. e.g. red: 0, teal: 200, cyan: 250, pink: 345
fixed: false, // Hide the theme color picker for visitors
hue: 355,
fixed: false,
},
banner: {
enable: false,
src: "assets/images/demo-banner.png", // Relative to the /src directory. Relative to the /public directory if it starts with '/'
position: "center", // Equivalent to object-position, only supports 'top', 'center', 'bottom'. 'center' by default
src: "assets/images/demo-banner.png",
position: "center",
credit: {
enable: false, // Display the credit text of the banner image
text: "", // Credit text to be displayed
url: "", // (Optional) URL link to the original artwork or artist's page
enable: false,
text: "",
url: "",
},
},
toc: {
enable: true, // Display the table of contents on the right side of the post
depth: 2, // Maximum heading depth to show in the table, from 1 to 3
enable: true,
depth: 2,
},
favicon: [
// Leave this array empty to use the default favicon
// {
// src: '/favicon/icon.png', // Path of the favicon, relative to the /public directory
// theme: 'light', // (Optional) Either 'light' or 'dark', set only if you have different favicons for light and dark mode
// sizes: '32x32', // (Optional) Size of the favicon, set only if you have favicons of different sizes
// }
],
favicon: [],
};
export const navBarConfig: NavBarConfig = {
links: [
LinkPreset.Home,
LinkPreset.Archive,
LinkPreset.Series,
LinkPreset.Series,
LinkPreset.Friends,
LinkPreset.About,
{
name: "状态",
url: "https://status.mckero.com", // Internal links should not include the base path, as it is automatically added
external: true, // Show an external link icon and will open in a new tab
url: "https://status.mckero.com",
external: true,
},
{
name: "统计",
url: "https://umami.mckero.com/share/v4wXkxwCYns2ypLN/blog.mckero.com", // Internal links should not include the base path, as it is automatically added
external: true, // Show an external link icon and will open in a new tab
},
name: "统计",
url: "https://umami.mckero.com/share/v4wXkxwCYns2ypLN/blog.mckero.com",
external: true,
},
],
};
export const profileConfig: ProfileConfig = {
avatar: "assets/images/demo-avatar.png", // Relative to the /src directory. Relative to the /public directory if it starts with '/'
avatar: "assets/images/demo-avatar.png",
name: "MC_Kero",
bio: "依稀当年泪目干!",
links: [
{
name: "Github",
icon: "fa6-brands:github", // Visit https://icones.js.org/ for icon codes
// You will need to install the corresponding icon set if it's not already included
// `pnpm add @iconify-json/<icon-set-name>`
icon: "fa6-brands:github",
url: "https://github.com/MCKero6423",
},
{
@@ -78,7 +69,6 @@ export const profileConfig: ProfileConfig = {
icon: "fa6-brands:bilibili",
url: "https://space.bilibili.com/3493260722964658",
},
],
};
@@ -90,19 +80,17 @@ export const licenseConfig: LicenseConfig = {
export const umamiConfig: UmamiConfig = {
enable: true,
baseUrl: "https://umami.mckero.com",
baseUrl: "https://umami.mckero.com", // 自部署版本,不需要加 /analytics/us
shareId: "v4wXkxwCYns2ypLN",
timezone: "Asia/Shanghai",
};
export const expressiveCodeConfig: ExpressiveCodeConfig = {
// Note: Some styles (such as background color) are being overridden, see the astro.config.mjs file.
// Please select a dark theme, as this blog theme currently only supports dark background color
theme: "github-dark",
};
export const commentConfig: CommentConfig = {
twikoo: {
envId: 'https://twikoo.mckero.com/.netlify/functions/twikoo',
},
}
twikoo: {
envId: 'https://twikoo.mckero.com/.netlify/functions/twikoo',
},
}