diff --git a/.env.example b/.env.example
index facb12f..049df13 100644
--- a/.env.example
+++ b/.env.example
@@ -1,5 +1,9 @@
+# Github Token
VITE_GITHUB_TOKEN=your-github-token
+# UMAMI API KEY
+VITE_UMAMI_API_KEY=your-umami-api-key
+
# SMTP 服务器地址
SMTP_HOST=smtp.example.com
diff --git a/README.md b/README.md
index b3d1e14..86a9e60 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,10 @@ const siteConfig: SiteConfig = {
title: "I'm a software developer.", // 你的简介,可为空
avatar: "avatar.webp", // 你的头像,可为public目录下的文件或外部链接
bio: "Hello World", // 你的喜欢的一句话,可为空
+ birthday: "xxxx-xx-xx", // 你的生日,可为空
+ gender: "", // 你的性别,可为空
+ pronouns: "", // 你希望别人如何称呼你,可为空
+ location: "", // 你的居住地,可为空
},
// 社交链接,预定义的社交链接可在 `src/components/SocialLink.vue` 中查阅
@@ -52,8 +56,16 @@ const siteConfig: SiteConfig = {
],
siteMeta: {
- title: "RhenCloud", // 网站标题
+ title: "Example Title", // 网站标题
icon: "favicon.ico", // 网站图标,可为public目录下的文件或外部链接
+ startDate:"xxxx-xx-xx", // 网站创建日期
+ },
+
+ umami: {
+ enable: true, // 是否启用 Umami 分析
+ url: "https://cloud.umami.is/script.js", // Umami 分析脚本 URL,一般无需修改
+ websiteId: "YOUR_WEBSITE_ID", // Umami 网站 ID
+ apiBase: "https://api.umami.is", // Umami API 地址,一般无需修改
},
// 技能图标展示,详见https://github.com/tandpfun/skill-icons#icons-list
@@ -100,9 +112,11 @@ const siteConfig: SiteConfig = {
footer: {
beian: "备案号", // 备案号,留空则不显示
beianLink: "https://beian.miit.gov.cn/", // 备案号链接,一般无需修改
- showHitokoto: true, // 是否显示一言
- hitokotoType: "a&b&c&d&j", // 一言类型,详见 https://developer.hitokoto.cn/sentence/#%E5%8F%A5%E5%AD%90%E7%B1%BB%E5%9E%8B-%E5%8F%82%E6%95%B0
customHtml: '', // 自定义 HTML 代码,如统计代码等
+ hitokoto: {
+ enable: true, // 是否启用一言
+ type: "a&b&c&d&j", // 一言类型,详见 https://developer.hitokoto.cn/sentence/#%E5%8F%A5%E5%AD%90%E7%B1%BB%E5%9E%8B-%E5%8F%82%E6%95%B0
+ },
},
};
```
@@ -112,11 +126,12 @@ const siteConfig: SiteConfig = {
- **404 页面**:修改 `public/404.html` 来自定义 404 错误页面的样式与内容。
- **友链展示逻辑**:`FriendsSection.vue` 默认使用随机顺序渲染 `siteConfig.friends`,如需固定顺序请修改该组件。
-## 环境变量(邮件发送)
+## 环境变量
在 Vercel 控制台或本地 `.env` 配置:
-- `VITE_GITHUB_TOKEN`: 具有仓库读取权限的 GitHub Token,用于绕过 GitHub API 速率限制。
+- `VITE_GITHUB_TOKEN`: 具有仓库读取权限的 GitHub Token,用于绕过 GitHub API 速率限制。(可选)
+- `UMAMI_API_KEY`: Umami 分析的 API Key。
- `SMTP_HOST`: 邮件服务器主机名
- `SMTP_PORT`: 端口(如 465 或 587)
- `SMTP_USER`: 发件人邮箱账号
@@ -140,7 +155,7 @@ pnpm dev
pnpm build
```
-产物输出到 `dist/`。
+产物输出到
## 部署到 Vercel
diff --git a/package.json b/package.json
index b6f91af..f54fba9 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "@jaseeey/vue-umami-plugin": "^1.4.0",
"@vercel/node": "^5.5.15",
"express": "^5.2.1",
"he": "^1.2.0",
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..efc037a
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,2 @@
+onlyBuiltDependencies:
+ - esbuild
diff --git a/src/App.vue b/src/App.vue
index 0358a03..40be79b 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -9,6 +9,7 @@
@@ -54,14 +107,17 @@ onMounted(() => {
text-align: center;
margin-top: 8px;
}
+
.from {
margin-left: 6px;
}
+
.beian {
font-size: 12px;
margin: 6px 0;
letter-spacing: 0.2px;
}
+
.beian a {
color: inherit;
opacity: 0.85;
@@ -69,12 +125,20 @@ onMounted(() => {
border-radius: 8px;
transition: color 0.2s ease, background 0.2s ease, opacity 0.2s ease;
}
+
.beian a:hover {
color: var(--accent, #7cc1ff);
background: rgba(124, 193, 255, 0.1);
opacity: 1;
}
+
.custom-html {
margin-top: 6px;
}
+
+.stats {
+ font-size: 12px;
+ margin: 6px 0;
+ letter-spacing: 0.2px;
+}
diff --git a/src/config/siteConfig.ts b/src/config/siteConfig.ts
index cc6d1be..47ae771 100644
--- a/src/config/siteConfig.ts
+++ b/src/config/siteConfig.ts
@@ -1,60 +1,4 @@
-interface SiteConfig {
- profile: {
- name: string;
- title: string;
- avatar: string;
- bio: string;
- birthday?: string;
- gender?: string;
- pronouns?: string;
- location?: string;
- };
- socialLinks: Array<{
- name: string;
- url: string;
- }>;
- github: {
- username: string;
- };
- about: Array<{
- title: string;
- desc: string;
- icon: string;
- }>;
- siteMeta: {
- title: string;
- icon: string;
- };
- skills: Array<{
- title: string;
- items: string[];
- }>;
- sites: Array<{
- name: string;
- desc: string;
- url: string;
- }>;
- projects: Array<{
- name: string;
- url: string;
- desc: string;
- }>;
- friends: Array<{
- name: string;
- desc: string;
- url: string;
- avatar: string;
- }>;
- footer: {
- beian: string;
- beianLink: string;
- showHitokoto: boolean;
- hitokotoType: string;
- customHtml: string;
- };
-}
-
-const siteConfig: SiteConfig = {
+const siteConfig = {
profile: {
name: "RhenCloud",
title: "I'm RhenCloud.",
@@ -88,6 +32,14 @@ const siteConfig: SiteConfig = {
siteMeta: {
title: "RhenCloud",
icon: "favicon.ico", // public/favicon.ico
+ startDate: "2025-12-06",
+ },
+
+ umami: {
+ enable: true,
+ url: "https://cloud.umami.is/script.js",
+ websiteId: "ddcd51c3-ccc7-45e4-81e6-11567027f69b",
+ apiBase: "https://api.umami.is",
},
skills: [
@@ -143,9 +95,11 @@ const siteConfig: SiteConfig = {
footer: {
beian: "津ICP备2025039003号-1",
beianLink: "https://beian.miit.gov.cn/",
- showHitokoto: true,
- hitokotoType: "a&b&c&d&j",
customHtml: '© 2025 RhenCloud',
+ hitokoto: {
+ enable: true,
+ type: "a&b&c&d&j",
+ },
},
};
diff --git a/src/main.ts b/src/main.ts
index c8c4d1e..0811677 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,6 +1,15 @@
import { createApp } from "vue";
+import { VueUmamiPlugin } from "@jaseeey/vue-umami-plugin";
import App from "./App.vue";
import router from "./router";
import "./styles.css";
+import siteConfig from "./config/siteConfig";
-createApp(App).use(router).mount("#app");
+const app = createApp(App);
+
+if (process.env.NODE_ENV !== "development") {
+ if (siteConfig.umami?.enable) {
+ app.use(VueUmamiPlugin({ websiteID: siteConfig.umami.websiteId, scriptSrc: siteConfig.umami.url, router }));
+ }
+}
+app.use(router).mount("#app");
diff --git a/src/views/About.vue b/src/views/About.vue
index 99df128..589a0ab 100644
--- a/src/views/About.vue
+++ b/src/views/About.vue
@@ -25,8 +25,6 @@ const github = reactive({
// 修改此处:使用 VITE_ 前缀
const githubToken = import.meta.env.VITE_GITHUB_TOKEN ?? "";
-console.log(githubToken);
-
onMounted(() => {
document.title = siteMeta.title;
const link = document.querySelector("link[rel~='icon']") || document.createElement("link");