mirror of
https://github.com/RhenCloud/Cloud-Home.git
synced 2026-01-22 17:39:07 +08:00
feat: 添加个人信息展示功能,更新配置文件以支持年龄、性别、代词和地区
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Rhen Cloud
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# Cloud Home
|
# Cloud Home
|
||||||
|
|
||||||
一个基于 Vue 的个人主页模板,内置友链申请、项目展示、友链随机展示、自定义配置,支持 Vercel 部署与邮件通知。
|
一个基于 Vue 的个人主页模板,内置友链申请、网站展示、项目展示、友链随机展示、自定义配置,支持 Vercel 部署与邮件通知。
|
||||||
|
|
||||||
## 特性
|
## 特性
|
||||||
|
|
||||||
@@ -145,9 +145,7 @@ pnpm build
|
|||||||
## 部署到 Vercel
|
## 部署到 Vercel
|
||||||
|
|
||||||
1. 导入仓库到 Vercel。
|
1. 导入仓库到 Vercel。
|
||||||
2. 设置上文的 SMTP 环境变量。
|
2. 设置上文的环境变量。
|
||||||
3. 保持 `vercel.json` 中 `distDir: "dist"`。
|
|
||||||
4. 部署后,静态文件从 `dist/` 提供,API 走 `/api/send-mail`。
|
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,41 @@
|
|||||||
<section class="card panel">
|
<section class="card panel">
|
||||||
<h2>个人简介</h2>
|
<h2>个人简介</h2>
|
||||||
<p class="muted">关于我 · About Me</p>
|
<p class="muted">关于我 · About Me</p>
|
||||||
|
|
||||||
|
<div class="about-grid info-grid">
|
||||||
|
<article v-if="age" class="about-card info-card">
|
||||||
|
<div class="about-head">
|
||||||
|
<span class="icon">🎂</span>
|
||||||
|
<h3>年龄</h3>
|
||||||
|
</div>
|
||||||
|
<p class="muted">{{ age }} 岁</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article v-if="profile?.gender" class="about-card info-card">
|
||||||
|
<div class="about-head">
|
||||||
|
<span class="icon">⚧️</span>
|
||||||
|
<h3>性别</h3>
|
||||||
|
</div>
|
||||||
|
<p class="muted">{{ profile.gender }}</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article v-if="profile?.pronouns" class="about-card info-card">
|
||||||
|
<div class="about-head">
|
||||||
|
<span class="icon">🗣️</span>
|
||||||
|
<h3>代词</h3>
|
||||||
|
</div>
|
||||||
|
<p class="muted">{{ profile.pronouns }}</p>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article v-if="profile?.location" class="about-card info-card">
|
||||||
|
<div class="about-head">
|
||||||
|
<span class="icon">📍</span>
|
||||||
|
<h3>地区</h3>
|
||||||
|
</div>
|
||||||
|
<p class="muted">{{ profile.location }}</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="about-grid">
|
<div class="about-grid">
|
||||||
<article v-for="item in items" :key="item.title" class="about-card">
|
<article v-for="item in items" :key="item.title" class="about-card">
|
||||||
<div class="about-head">
|
<div class="about-head">
|
||||||
@@ -15,7 +50,24 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
defineProps({ items: Array });
|
import { computed } from "vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
items: Array,
|
||||||
|
profile: Object,
|
||||||
|
});
|
||||||
|
|
||||||
|
const age = computed(() => {
|
||||||
|
if (!props.profile?.birthday) return null;
|
||||||
|
const birthDate = new Date(props.profile.birthday);
|
||||||
|
const today = new Date();
|
||||||
|
let age = today.getFullYear() - birthDate.getFullYear();
|
||||||
|
const m = today.getMonth() - birthDate.getMonth();
|
||||||
|
if (m < 0 || (m === 0 && today.getDate() < birthDate.getDate())) {
|
||||||
|
age--;
|
||||||
|
}
|
||||||
|
return age;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -36,10 +88,23 @@ h2 {
|
|||||||
grid-template-columns: repeat(2, minmax(240px, 1fr));
|
grid-template-columns: repeat(2, minmax(240px, 1fr));
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
}
|
}
|
||||||
|
.info-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 14px;
|
||||||
|
}
|
||||||
|
.about-grid + .about-grid {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 720px) {
|
||||||
.about-grid {
|
.about-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
.info-grid {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.about-card {
|
.about-card {
|
||||||
background: linear-gradient(135deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.02));
|
background: linear-gradient(135deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.02));
|
||||||
@@ -49,6 +114,34 @@ h2 {
|
|||||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
|
||||||
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
.info-card {
|
||||||
|
flex: 1 1 140px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
}
|
||||||
|
.info-card .about-head {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.info-card .about-head h3 {
|
||||||
|
font-size: 15px;
|
||||||
|
color: rgba(255, 255, 255, 0.9);
|
||||||
|
font-weight: 600;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.info-card .icon {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
.info-card .muted {
|
||||||
|
margin: 0;
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: 500;
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
.about-card:hover {
|
.about-card:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
border-color: rgba(124, 193, 255, 0.4);
|
border-color: rgba(124, 193, 255, 0.4);
|
||||||
|
|||||||
@@ -4,6 +4,10 @@ interface SiteConfig {
|
|||||||
title: string;
|
title: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
bio: string;
|
bio: string;
|
||||||
|
birthday?: string;
|
||||||
|
gender?: string;
|
||||||
|
pronouns?: string;
|
||||||
|
location?: string;
|
||||||
};
|
};
|
||||||
socialLinks: Array<{
|
socialLinks: Array<{
|
||||||
name: string;
|
name: string;
|
||||||
@@ -56,6 +60,10 @@ const siteConfig: SiteConfig = {
|
|||||||
title: "I'm RhenCloud.",
|
title: "I'm RhenCloud.",
|
||||||
avatar: "avatar.webp", // public/avatar.webp
|
avatar: "avatar.webp", // public/avatar.webp
|
||||||
bio: "趁世界还未重启之前 约一次爱恋",
|
bio: "趁世界还未重启之前 约一次爱恋",
|
||||||
|
birthday: "2010-03-28",
|
||||||
|
// gender: "女",
|
||||||
|
pronouns: "她",
|
||||||
|
location: "中国 · 天津",
|
||||||
},
|
},
|
||||||
|
|
||||||
socialLinks: [
|
socialLinks: [
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<main class="page">
|
<main class="page">
|
||||||
<HeroSection :profile="profile" />
|
<HeroSection :profile="profile" />
|
||||||
<SocialLinks :links="socialLinks" />
|
<SocialLinks :links="socialLinks" />
|
||||||
<AboutSection :items="about" />
|
<AboutSection :items="about" :profile="profile" />
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user