chore:一些修复

This commit is contained in:
2026-01-15 19:53:17 +08:00
parent 53685b1531
commit 6edb6af6ee
6 changed files with 851 additions and 85 deletions

View File

@@ -79,15 +79,9 @@
<script setup>
import { ref, onMounted, computed } from "vue";
import siteConfig from "~/config/siteConfig";
const props = defineProps({
wakatime: {
type: Object,
required: false,
default: () => ({ languages: [] }),
},
});
const wakatime = props.wakatime;
const wakapi = siteConfig.wakapi;
const weeklyData = ref(null);
const allTimeData = ref(null);
@@ -123,65 +117,45 @@ const formatTime = (seconds) => {
};
const fetchWakatimeData = async () => {
if (!wakatime.enable) return;
if (!wakapi.enable) {
console.warn("Wakatime is disabled in siteConfig.");
return;
}
const apiUrl = wakapi.apiUrl || "https://wakatime.com/api/v1";
const username = wakapi.username;
if (!username) {
console.error("Wakatime username is not configured.");
return;
}
try {
const params = new URLSearchParams();
if (wakatime.apiUrl && wakatime.apiUrl !== "https://wakatime.com/api/v1") {
params.append("apiUrl", wakatime.apiUrl);
}
const url = `/api/wakatime${params.toString() ? `?${params.toString()}` : ""}`;
console.log("Fetching Wakatime data from:", url);
const response = await fetch(url);
console.log("Response status:", response.status);
console.log("Response headers:", Object.fromEntries(response.headers.entries()));
const [weeklyStatsResponse, allTimeStatsResponse, statusResponse] = await Promise.all([
fetch(`${apiUrl}/users/${username}/stats/last_7_days`),
fetch(`${apiUrl}/users/${username}/stats`),
fetch(`${apiUrl}/users/${username}/status`),
]);
if (response.ok) {
const data = await response.json();
console.log("Wakatime data:", data);
weeklyData.value = data.weekly;
allTimeData.value = data.allTime;
statusData.value = data.status;
if (weeklyStatsResponse.ok) {
weeklyData.value = await weeklyStatsResponse.json();
} else {
const errorText = await response.text();
console.error("API Error:", response.status, errorText);
if (response.status === 500 && errorText.includes("Wakatime API Key not configured")) {
console.warn("Wakatime API Key not configured - hiding component");
showComponent.value = false;
return;
}
throw new Error(`API returned ${response.status}: ${errorText}`);
console.error("Failed to fetch weekly stats:", weeklyStatsResponse.status);
}
if (allTimeStatsResponse.ok) {
allTimeData.value = await allTimeStatsResponse.json();
} else {
console.warn("All-time stats not available:", allTimeStatsResponse.status);
}
if (statusResponse.ok) {
statusData.value = await statusResponse.json();
} else {
console.warn("Status data not available:", statusResponse.status);
}
} catch (error) {
console.error("Failed to fetch Wakatime data:", error);
// 在开发环境中,如果 API 不可用,设置一些示例数据
if (import.meta.env.DEV) {
console.log("Using mock data for development");
weeklyData.value = {
total_seconds: 36000,
daily_average: 5142,
days_including_holidays: 7,
languages: [
{ name: "TypeScript", percent: 45.2, total_seconds: 16272 },
{ name: "Vue", percent: 30.1, total_seconds: 10836 },
{ name: "JavaScript", percent: 15.3, total_seconds: 5508 },
{ name: "Python", percent: 9.4, total_seconds: 3384 },
],
};
allTimeData.value = {
total_seconds: 864000,
daily_average: 2800,
days_including_holidays: 308,
languages: [
{ name: "JavaScript", percent: 35.2, total_seconds: 304128 },
{ name: "TypeScript", percent: 28.1, total_seconds: 242688 },
{ name: "Python", percent: 20.3, total_seconds: 175392 },
{ name: "Vue", percent: 10.1, total_seconds: 87296 },
{ name: "CSS", percent: 6.3, total_seconds: 54432 },
],
};
statusData.value = { is_coding: false };
}
console.error("Error fetching Wakatime data:", error);
}
};

View File

@@ -2,7 +2,7 @@ const siteConfig = {
profile: {
name: "RhenCloud",
title: "I'm RhenCloud.",
avatar: "/avatar.webp", // public/avatar.webp
avatar: "/avatar-1.webp", // public/avatar.webp
bio: "趁世界还未重启之前 约一次爱恋",
email: "i@rhen.cloud",
birthday: "2010-03-28",
@@ -32,9 +32,13 @@ const siteConfig = {
siteMeta: {
title: "RhenCloud",
description: "RhenCloud的个人主页分享技术、生活、兴趣。",
keywords: ["Technology", "Blog", "Development", "Programming"],
author: "RhenCloud",
url: "https://rhen.cloud",
icon: "/favicon.svg", // public/favicon.svg
favicon: "/favicon.svg", // public/favicon.svg
startDate: "2025-12-06",
lang: "zh-CN",
},
appearance: {
@@ -80,9 +84,10 @@ const siteConfig = {
apiBase: "https://api.umami.is",
},
wakatime: {
enable: true,
wakapi: {
enable: false,
apiUrl: "https://wakapi.rhen.cloud/api/v1",
username: "RhenCloud",
},
skills: [

View File

@@ -5,18 +5,7 @@ import tailwindcss from "@tailwindcss/vite";
export default defineNuxtConfig({
compatibilityDate: "2025-12-12",
srcDir: "app/",
modules: ["@nuxt/image", "@nuxt/eslint", "@nuxtjs/sitemap"],
// eslint: {
// config: {
// extends: ["plugin:nuxt/recommended", "prettier"],
// plugins: ["prettier"],
// rules: {
// "prettier/prettier": "error",
// },
// stylistic: true
// },
// },
modules: ["@nuxt/image", "@nuxt/eslint", "@nuxtjs/sitemap", "@nuxtjs/seo"],
// 禁用 Vue Router 的非关键警告
vue: {
@@ -32,11 +21,6 @@ export default defineNuxtConfig({
plugins: [tailwindcss()],
},
site: {
url: siteConfig.siteMeta.url,
title: siteConfig.siteMeta.title,
},
routeRules: {
"/": { prerender: true },
"/about": { isr: 3600 },
@@ -47,9 +31,22 @@ export default defineNuxtConfig({
app: {
head: {
charset: "utf-8",
viewport: "width=device-width,initial-scale=1,maximum-scale=5",
title: siteConfig.siteMeta.title,
titleTemplate: `%s - ${siteConfig.siteMeta.title}`,
meta: [
{ name: "author", content: siteConfig.siteMeta.author },
{ name: "language", content: "zh-CN" },
{ name: "description", content: siteConfig.siteMeta.description },
],
link: [
{ rel: "icon", href: siteConfig.siteMeta.icon },
{ rel: "icon", href: siteConfig.siteMeta.favicon, type: "image/svg+xml" },
{ rel: "canonical", href: siteConfig.siteMeta.url },
{ rel: "alternate", hreflang: siteConfig.siteMeta.lang, href: siteConfig.siteMeta.url },
{ rel: "dns-prefetch", href: siteConfig.siteMeta.url },
{ rel: "preconnect", href: siteConfig.siteMeta.url },
{ rel: "icon", href: siteConfig.siteMeta.favicon },
// Font Awesome CDN 预加载和优化
{
rel: "preload",
@@ -73,6 +70,8 @@ export default defineNuxtConfig({
},
],
},
pageTransition: { name: "page", mode: "out-in" },
layoutTransition: { name: "layout", mode: "out-in" },
},
nitro: {
@@ -91,9 +90,11 @@ export default defineNuxtConfig({
senderEmail: process.env.SENDER_EMAIL ?? "",
adminEmail: process.env.ADMIN_EMAIL ?? "",
smtpSecure: process.env.SMTP_SECURE ? process.env.SMTP_SECURE === "true" : undefined,
wakatimeApiKey: process.env.WAKATIME_API_KEY ?? "",
wakatimeApiUrl: process.env.WAKATIME_API_URL ?? "https://wakatime.com/api/v1",
githubToken: process.env.NUXT_PUBLIC_GITHUB_TOKEN ?? "",
umamiApiKey: process.env.UMAMI_API_KEY ?? "",
public: {
wakatimeApiKey: process.env.WAKATIME_API_KEY ?? "",
wakatimeApiUrl: process.env.WAKATIME_API_URL ?? "https://wakatime.com/api/v1",
},
},
});

View File

@@ -16,6 +16,7 @@
"@giscus/vue": "^3.1.1",
"@jaseeey/vue-umami-plugin": "^1.4.0",
"@nuxt/image": "2.0.0",
"@nuxtjs/seo": "3.3.0",
"@nuxtjs/sitemap": "^7.5.0",
"nodemailer": "^7.0.11",
"nuxt": "^4.2.2",

785
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
public/avatar-1.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 KiB