个人页面
This commit is contained in:
+99
-7
@@ -1,43 +1,135 @@
|
||||
export const peopleIntro = {
|
||||
title: "一年后的我们",
|
||||
text: "这里可以做成同学卡片:姓名、所在城市、学校或方向,以及一句想对大家说的话。"
|
||||
text: "这里可以做成同学卡片:姓名、所在城市、学校或方向,以及一句想对大家说的话。点进个人页,可以看到更完整的一年后近况。"
|
||||
};
|
||||
|
||||
export const people = [
|
||||
{
|
||||
slug: "student-a",
|
||||
initial: "A",
|
||||
name: "同学 A",
|
||||
location: "北京",
|
||||
text: "这一年的关键词:开始、独立、想念。想和大家说:下次见面一定要拍一张新的合照。"
|
||||
school: "示例大学",
|
||||
direction: "计算机科学",
|
||||
keywords: ["开始", "独立", "想念"],
|
||||
text: "这一年的关键词:开始、独立、想念。想和大家说:下次见面一定要拍一张新的合照。",
|
||||
currentStatus: "在新的城市慢慢适应大学节奏,学会了自己安排时间,也开始认真做一些以前只停留在想法里的事情。",
|
||||
highlight: "第一次独自完成一个小项目,虽然过程有点乱,但最后跑起来的时候很开心。",
|
||||
toPastSelf: "别太紧张,后来你会发现,那些看起来很难的日子真的会过去。",
|
||||
messageToClass: "希望下次见面时,我们还能像以前一样很快聊起来。",
|
||||
favoriteMemory: "晚自习后一起走出教学楼,风吹过来的那几分钟。",
|
||||
contact: "可填写微信、邮箱或留空"
|
||||
},
|
||||
{
|
||||
slug: "student-b",
|
||||
initial: "B",
|
||||
name: "同学 B",
|
||||
location: "上海",
|
||||
text: "偶尔还是会梦到上课铃。高中最珍贵的是:有人陪你一起把普通日子过得很亮。"
|
||||
school: "示例学院",
|
||||
direction: "新闻传播",
|
||||
keywords: ["观察", "表达", "勇气"],
|
||||
text: "偶尔还是会梦到上课铃。高中最珍贵的是:有人陪你一起把普通日子过得很亮。",
|
||||
currentStatus: "这一年开始更频繁地记录生活,拍照、写稿、做采访,也更习惯主动表达自己的想法。",
|
||||
highlight: "加入了校园媒体,第一次以采访者的身份认识陌生人。",
|
||||
toPastSelf: "不要总觉得自己不够好,你其实一直在认真长大。",
|
||||
messageToClass: "愿大家都有很多新的故事,也别忘了把故事讲给老同学听。",
|
||||
favoriteMemory: "运动会看台上大家一起喊加油,声音乱七八糟但特别真。",
|
||||
contact: "可填写微信、邮箱或留空"
|
||||
},
|
||||
{
|
||||
slug: "student-c",
|
||||
initial: "C",
|
||||
name: "同学 C",
|
||||
location: "广州",
|
||||
text: "现在比以前更忙,也更懂得珍惜。希望大家都在自己的路上慢慢发光。"
|
||||
school: "示例大学",
|
||||
direction: "临床医学",
|
||||
keywords: ["忙碌", "坚持", "珍惜"],
|
||||
text: "现在比以前更忙,也更懂得珍惜。希望大家都在自己的路上慢慢发光。",
|
||||
currentStatus: "课很多,节奏也快,但渐渐知道自己为什么选择这条路。",
|
||||
highlight: "第一次在实验课上把课本里的知识和真实操作连起来。",
|
||||
toPastSelf: "可以慢一点,但不要轻易否定自己。",
|
||||
messageToClass: "大家都要好好吃饭、好好睡觉、好好生活。",
|
||||
favoriteMemory: "高三春天的倒计时牌,每天都少一点,也每天更靠近终点。",
|
||||
contact: "可填写微信、邮箱或留空"
|
||||
},
|
||||
{
|
||||
slug: "student-d",
|
||||
initial: "D",
|
||||
name: "同学 D",
|
||||
location: "成都",
|
||||
text: "想念晚自习后的小卖部,也想念那些不用解释就能笑出来的人。"
|
||||
school: "示例大学",
|
||||
direction: "建筑学",
|
||||
keywords: ["画图", "熬夜", "发现"],
|
||||
text: "想念晚自习后的小卖部,也想念那些不用解释就能笑出来的人。",
|
||||
currentStatus: "经常画图画到很晚,也开始用新的方式观察城市和空间。",
|
||||
highlight: "第一次做完整模型,手上都是胶水,但看着它成型很有成就感。",
|
||||
toPastSelf: "不用急着证明什么,你会慢慢找到自己的节奏。",
|
||||
messageToClass: "下次聚会一定别只说说,真的要约起来。",
|
||||
favoriteMemory: "课间围在一起聊天,最后因为上课铃匆匆散开。",
|
||||
contact: "可填写微信、邮箱或留空"
|
||||
},
|
||||
{
|
||||
slug: "student-e",
|
||||
initial: "E",
|
||||
name: "同学 E",
|
||||
location: "武汉",
|
||||
text: "一年过去,很多事情都变了,但听到班级群消息还是会立刻点开。"
|
||||
school: "示例大学",
|
||||
direction: "经济学",
|
||||
keywords: ["变化", "尝试", "班群"],
|
||||
text: "一年过去,很多事情都变了,但听到班级群消息还是会立刻点开。",
|
||||
currentStatus: "试着参加社团、认识新人,也学会接受生活里那些计划外的变化。",
|
||||
highlight: "第一次做公开展示,紧张到手心出汗,但还是讲完了。",
|
||||
toPastSelf: "别害怕出错,很多机会都是试出来的。",
|
||||
messageToClass: "班群别沉太久,偶尔冒泡也很好。",
|
||||
favoriteMemory: "毕业照那天大家到处找笔签名,像在认真保存彼此。",
|
||||
contact: "可填写微信、邮箱或留空"
|
||||
},
|
||||
{
|
||||
slug: "student-f",
|
||||
initial: "F",
|
||||
name: "同学 F",
|
||||
location: "南京",
|
||||
text: "希望我们都成为更好的自己,也永远记得曾经一起努力过的样子。"
|
||||
school: "示例大学",
|
||||
direction: "软件工程",
|
||||
keywords: ["代码", "成长", "再见面"],
|
||||
text: "希望我们都成为更好的自己,也永远记得曾经一起努力过的样子。",
|
||||
currentStatus: "写了很多以前看不懂的代码,也慢慢习惯从错误信息里找答案。",
|
||||
highlight: "第一次把自己的网页部署上线,发给朋友看的时候很有仪式感。",
|
||||
toPastSelf: "高三辛苦是真的,但你比自己想象得更能坚持。",
|
||||
messageToClass: "愿我们下次见面,既能聊过去,也能聊现在。",
|
||||
favoriteMemory: "最后一节课结束后,没有人马上离开教室。",
|
||||
contact: "可填写微信、邮箱或留空"
|
||||
},
|
||||
{
|
||||
slug: "student-g",
|
||||
initial: "G",
|
||||
name: "同学 G",
|
||||
location: "杭州",
|
||||
school: "示例大学",
|
||||
direction: "视觉传达",
|
||||
keywords: ["审美", "作品", "灵感"],
|
||||
text: "这一年开始认真做作品集,也更相信普通生活里有很多值得记录的东西。",
|
||||
currentStatus: "在学习排版、摄影和品牌设计,手机相册里多了很多路牌、海报和天空。",
|
||||
highlight: "第一次参加小型展览,看到自己的作品被别人停下来观看。",
|
||||
toPastSelf: "你喜欢的东西不是没用,它会慢慢变成你的方向。",
|
||||
messageToClass: "以后大家有照片和故事都发我,我来整理成页面。",
|
||||
favoriteMemory: "教室窗帘被风吹起来,阳光落在桌面上的下午。",
|
||||
contact: "可填写微信、邮箱或留空"
|
||||
},
|
||||
{
|
||||
slug: "student-h",
|
||||
initial: "H",
|
||||
name: "同学 H",
|
||||
location: "西安",
|
||||
school: "示例大学",
|
||||
direction: "自动化",
|
||||
keywords: ["实验", "社团", "稳定"],
|
||||
text: "新的生活没有想象中轻松,但也有很多意料之外的有趣。",
|
||||
currentStatus: "在实验室和社团之间来回切换,逐渐学会把复杂的事拆成一步一步。",
|
||||
highlight: "和同学一起做了一个能动起来的小装置。",
|
||||
toPastSelf: "保持好奇,别把自己困在成绩单里。",
|
||||
messageToClass: "希望每个人都能在新环境里遇见好朋友。",
|
||||
favoriteMemory: "晚读时有人忍不住笑,整排人都跟着憋笑。",
|
||||
contact: "可填写微信、邮箱或留空"
|
||||
}
|
||||
];
|
||||
|
||||
@@ -113,13 +113,17 @@ const previewPeople = people.slice(0, 6);
|
||||
<div class="people-grid">
|
||||
{
|
||||
previewPeople.map((person) => (
|
||||
<article class="person">
|
||||
<a class="person person-link" href={`/people/${person.slug}/`}>
|
||||
<div class="avatar">{person.initial}</div>
|
||||
<h3>
|
||||
{person.name} · {person.location}
|
||||
</h3>
|
||||
<div class="person-meta">
|
||||
<span>{person.school}</span>
|
||||
<span>{person.direction}</span>
|
||||
</div>
|
||||
<p>{person.text}</p>
|
||||
</article>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -20,13 +20,20 @@ import { site } from "../data/site";
|
||||
<div class="people-grid page-grid">
|
||||
{
|
||||
people.map((person) => (
|
||||
<article class="person">
|
||||
<a class="person person-link" href={`/people/${person.slug}/`}>
|
||||
<div class="avatar">{person.initial}</div>
|
||||
<h3>
|
||||
{person.name} · {person.location}
|
||||
</h3>
|
||||
<div class="person-meta">
|
||||
<span>{person.school}</span>
|
||||
<span>{person.direction}</span>
|
||||
</div>
|
||||
<div class="keyword-row">
|
||||
{person.keywords.map((keyword) => <span>{keyword}</span>)}
|
||||
</div>
|
||||
<p>{person.text}</p>
|
||||
</article>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
import BaseLayout from "../../layouts/BaseLayout.astro";
|
||||
import { people, peopleIntro } from "../../data/people";
|
||||
import { site } from "../../data/site";
|
||||
|
||||
export function getStaticPaths() {
|
||||
return people.map((person) => ({
|
||||
params: { slug: person.slug },
|
||||
props: { person }
|
||||
}));
|
||||
}
|
||||
|
||||
const { person } = Astro.props;
|
||||
---
|
||||
|
||||
<BaseLayout title={`${person.name} · ${peopleIntro.title} · ${site.className}`}>
|
||||
<main class="page-main">
|
||||
<section class="page-hero person-hero">
|
||||
<div class="section-inner person-hero-inner">
|
||||
<div>
|
||||
<a class="back-link" href="/people/">返回同学列表</a>
|
||||
<p class="eyebrow">Classmate Profile</p>
|
||||
<h1>{person.name}</h1>
|
||||
<p>{person.text}</p>
|
||||
</div>
|
||||
<aside class="profile-card">
|
||||
<div class="avatar profile-avatar">{person.initial}</div>
|
||||
<dl>
|
||||
<div>
|
||||
<dt>所在城市</dt>
|
||||
<dd>{person.location}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>学校</dt>
|
||||
<dd>{person.school}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>方向</dt>
|
||||
<dd>{person.direction}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</aside>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="section-inner detail-grid">
|
||||
<article class="detail-panel wide">
|
||||
<p class="eyebrow">Now</p>
|
||||
<h2>这一年的近况</h2>
|
||||
<p>{person.currentStatus}</p>
|
||||
</article>
|
||||
|
||||
<article class="detail-panel">
|
||||
<p class="eyebrow">Keywords</p>
|
||||
<h2>三个关键词</h2>
|
||||
<div class="keyword-row large">
|
||||
{person.keywords.map((keyword) => <span>{keyword}</span>)}
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="detail-panel">
|
||||
<p class="eyebrow">Highlight</p>
|
||||
<h2>这一年的小事</h2>
|
||||
<p>{person.highlight}</p>
|
||||
</article>
|
||||
|
||||
<article class="detail-panel">
|
||||
<p class="eyebrow">Past Self</p>
|
||||
<h2>想对高中时的自己说</h2>
|
||||
<p>{person.toPastSelf}</p>
|
||||
</article>
|
||||
|
||||
<article class="detail-panel">
|
||||
<p class="eyebrow">Memory</p>
|
||||
<h2>最想带走的高中瞬间</h2>
|
||||
<p>{person.favoriteMemory}</p>
|
||||
</article>
|
||||
|
||||
<article class="detail-panel wide">
|
||||
<p class="eyebrow">To Class</p>
|
||||
<h2>想对大家说</h2>
|
||||
<p>{person.messageToClass}</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</BaseLayout>
|
||||
+152
-5
@@ -222,8 +222,13 @@ h2 {
|
||||
box-shadow: 0 8px 28px rgba(39, 55, 52, 0.06);
|
||||
}
|
||||
|
||||
.moment > div {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.moment-link {
|
||||
position: relative;
|
||||
padding-right: 70px;
|
||||
transition:
|
||||
border-color 180ms ease,
|
||||
box-shadow 180ms ease,
|
||||
@@ -232,10 +237,9 @@ h2 {
|
||||
|
||||
.moment-link::after {
|
||||
content: "查看";
|
||||
align-self: start;
|
||||
justify-self: end;
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
right: 24px;
|
||||
color: var(--green);
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
@@ -504,6 +508,41 @@ h2 {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.person-link {
|
||||
display: block;
|
||||
transition:
|
||||
border-color 180ms ease,
|
||||
box-shadow 180ms ease,
|
||||
transform 180ms ease;
|
||||
}
|
||||
|
||||
.person-link:hover {
|
||||
transform: translateY(-3px);
|
||||
border-color: rgba(55, 109, 90, 0.34);
|
||||
box-shadow: 0 16px 38px rgba(39, 55, 52, 0.12);
|
||||
}
|
||||
|
||||
.person-meta,
|
||||
.keyword-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin: 0 0 14px;
|
||||
}
|
||||
|
||||
.person-meta span,
|
||||
.keyword-row span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 28px;
|
||||
padding: 4px 9px;
|
||||
border-radius: 999px;
|
||||
color: var(--green);
|
||||
background: color-mix(in srgb, var(--green), white 88%);
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
@@ -522,6 +561,97 @@ h2 {
|
||||
.person:nth-child(4) { --accent: #7b6b3a; }
|
||||
.person:nth-child(5) { --accent: #4d796d; }
|
||||
.person:nth-child(6) { --accent: #755c86; }
|
||||
.person:nth-child(7) { --accent: #8b5f4d; }
|
||||
.person:nth-child(8) { --accent: #2f6f79; }
|
||||
|
||||
.person-hero-inner {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(280px, 360px);
|
||||
gap: clamp(28px, 5vw, 70px);
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
.profile-card {
|
||||
padding: 24px;
|
||||
border: 1px solid rgba(255, 253, 247, 0.22);
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 253, 247, 0.1);
|
||||
backdrop-filter: blur(12px);
|
||||
}
|
||||
|
||||
.profile-avatar {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
margin-bottom: 22px;
|
||||
background: #f1c979;
|
||||
color: #21312d;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.profile-card dl {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.profile-card div {
|
||||
display: grid;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.profile-card dt {
|
||||
color: rgba(255, 253, 247, 0.58);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.profile-card dd {
|
||||
margin: 0;
|
||||
color: #fffdf7;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.detail-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.detail-panel {
|
||||
min-height: 220px;
|
||||
padding: 26px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
box-shadow: 0 8px 28px rgba(39, 55, 52, 0.06);
|
||||
}
|
||||
|
||||
.detail-panel.wide {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.detail-panel .eyebrow {
|
||||
color: var(--blue);
|
||||
}
|
||||
|
||||
.detail-panel h2 {
|
||||
margin-bottom: 16px;
|
||||
font-size: clamp(24px, 3vw, 34px);
|
||||
}
|
||||
|
||||
.detail-panel p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
}
|
||||
|
||||
.keyword-row.large {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.keyword-row.large span {
|
||||
min-height: 40px;
|
||||
padding: 7px 14px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.message-wall {
|
||||
display: grid;
|
||||
@@ -605,7 +735,9 @@ footer {
|
||||
|
||||
.stats,
|
||||
.section-title,
|
||||
.message-wall {
|
||||
.message-wall,
|
||||
.person-hero-inner,
|
||||
.detail-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
@@ -627,6 +759,21 @@ footer {
|
||||
.moment {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.moment > div {
|
||||
grid-column: auto;
|
||||
}
|
||||
|
||||
.moment-link {
|
||||
padding-right: 22px;
|
||||
}
|
||||
|
||||
.moment-link::after {
|
||||
position: static;
|
||||
margin-top: 10px;
|
||||
grid-column: auto;
|
||||
justify-self: start;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
|
||||
Reference in New Issue
Block a user