Skip to content

Commit 167749d

Browse files
committed
feat: Build site structure with pages and components
1 parent 9b3efe1 commit 167749d

7 files changed

Lines changed: 746 additions & 59 deletions

File tree

‎app/about/page.tsx‎

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
'use client';
2+
3+
import { Navigation } from '../components/Navigation';
4+
5+
export default function About() {
6+
return (
7+
<div className="flex flex-col min-h-screen bg-white dark:bg-black text-zinc-900 dark:text-zinc-50">
8+
<Navigation />
9+
10+
<main className="flex-1 max-w-4xl mx-auto w-full px-6 sm:px-8">
11+
{/* 关于页面标题 */}
12+
<section className="py-24 sm:py-32">
13+
<div className="space-y-6">
14+
<h1 className="text-5xl sm:text-6xl font-light tracking-tight leading-tight">
15+
关于我
16+
</h1>
17+
<p className="text-lg sm:text-xl text-zinc-600 dark:text-zinc-400 font-light leading-relaxed max-w-2xl">
18+
我是一名热情的全栈开发工程师,致力于创建美观、高效且用户友好的数字产品。
19+
</p>
20+
</div>
21+
</section>
22+
23+
{/* 个人简介 */}
24+
<section className="py-20 sm:py-24 border-t border-zinc-200 dark:border-zinc-800">
25+
<div className="space-y-8">
26+
<h2 className="text-3xl font-light tracking-tight">我的故事</h2>
27+
<div className="space-y-6 text-lg leading-relaxed">
28+
<p className="text-zinc-700 dark:text-zinc-300">
29+
我从事 Web 开发已有 5 年以上的经验。在这个过程中,我对前端技术的热情不断增长,特别是对 React 和现代 JavaScript 框架的深入理解。
30+
</p>
31+
<p className="text-zinc-700 dark:text-zinc-300">
32+
除了前端开发,我也擅长后端技术,使用 Node.js 和各种数据库技术构建了多个完整的应用系统。我相信全栈能力能帮助我更好地理解整个产品的架构。
33+
</p>
34+
<p className="text-zinc-700 dark:text-zinc-300">
35+
我不仅关注代码质量,更重视用户体验。在每个项目中,我都花时间思考如何让界面更直观、交互更流畅,让用户的每一次操作都感到舒适。
36+
</p>
37+
</div>
38+
</div>
39+
</section>
40+
41+
{/* 技能 */}
42+
<section className="py-20 sm:py-24 border-t border-zinc-200 dark:border-zinc-800">
43+
<div className="space-y-8">
44+
<h2 className="text-3xl font-light tracking-tight">技能与专长</h2>
45+
<div className="grid sm:grid-cols-2 gap-12">
46+
<div className="space-y-4">
47+
<h3 className="text-xl font-light">前端技术</h3>
48+
<ul className="space-y-2 text-zinc-700 dark:text-zinc-300 font-light">
49+
<li>• JavaScript / TypeScript</li>
50+
<li>• React / Next.js</li>
51+
<li>• TailwindCSS / 样式设计</li>
52+
<li>• 响应式设计 / 性能优化</li>
53+
</ul>
54+
</div>
55+
<div className="space-y-4">
56+
<h3 className="text-xl font-light">后端与其他</h3>
57+
<ul className="space-y-2 text-zinc-700 dark:text-zinc-300 font-light">
58+
<li>• Node.js / Express</li>
59+
<li>• 数据库设计 / SQL</li>
60+
<li>• API 设计 / REST</li>
61+
<li>• Git / DevOps 基础</li>
62+
</ul>
63+
</div>
64+
</div>
65+
</div>
66+
</section>
67+
68+
{/* 工作经历 */}
69+
<section className="py-20 sm:py-24 border-t border-zinc-200 dark:border-zinc-800">
70+
<div className="space-y-8">
71+
<h2 className="text-3xl font-light tracking-tight">工作经历</h2>
72+
<div className="space-y-8">
73+
<div className="border-l-2 border-zinc-300 dark:border-zinc-700 pl-6">
74+
<h3 className="text-xl font-light">高级前端工程师</h3>
75+
<p className="text-sm text-zinc-600 dark:text-zinc-400 mt-1">2022 - 至今</p>
76+
<p className="text-zinc-700 dark:text-zinc-300 mt-3 leading-relaxed">
77+
负责公司主要产品的前端架构设计和开发,优化了页面加载速度 40%,提升了用户体验。
78+
</p>
79+
</div>
80+
<div className="border-l-2 border-zinc-300 dark:border-zinc-700 pl-6">
81+
<h3 className="text-xl font-light">全栈开发工程师</h3>
82+
<p className="text-sm text-zinc-600 dark:text-zinc-400 mt-1">2020 - 2022</p>
83+
<p className="text-zinc-700 dark:text-zinc-300 mt-3 leading-relaxed">
84+
参与多个项目的全栈开发,从需求分析到部署上线,积累了丰富的端到端开发经验。
85+
</p>
86+
</div>
87+
</div>
88+
</div>
89+
</section>
90+
</main>
91+
92+
{/* 页脚 */}
93+
<footer className="border-t border-zinc-200 dark:border-zinc-800 mt-12">
94+
<div className="max-w-4xl mx-auto px-6 sm:px-8 py-12 text-center text-sm font-light text-zinc-600 dark:text-zinc-400">
95+
<p>© 2024 Wu. 精心设计 · 用心编写</p>
96+
</div>
97+
</footer>
98+
</div>
99+
);
100+
}

‎app/components/Navigation.tsx‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Link from 'next/link';
2+
3+
export function Navigation() {
4+
return (
5+
<nav className="sticky top-0 z-50 border-b border-zinc-200 dark:border-zinc-800 bg-white/80 dark:bg-black/80 backdrop-blur-sm">
6+
<div className="max-w-4xl mx-auto px-6 sm:px-8 py-4 flex justify-between items-center">
7+
<Link href="/" className="flex items-center gap-2 text-xl font-light tracking-tight hover:opacity-80 transition text-blue-500 dark:hover:text-blue-400">
8+
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#0000F5"><path d="M281.5-201.5Q200-283 200-400q0-94 55.5-168.5T401-669q-33-8-57.5-28.5T304-747q-15-29-21-63t-2-69q41-5 78 5t67 32q30 22 49.5 53t23.5 70q13-31 34.5-61.5T600-856l56 56q-43 43-63.5 73T564-667q88 28 142 101.5T760-400q0 117-81.5 198.5T480-120q-117 0-198.5-81.5Zm340-57Q680-317 680-400t-58.5-141.5Q563-600 480-600t-141.5 58.5Q280-483 280-400t58.5 141.5Q397-200 480-200t141.5-58.5ZM480-400Z"/></svg>
9+
</Link>
10+
<ul className="flex gap-8 text-sm font-poppins font-light">
11+
<li><Link href="/about" className="hover:text-zinc-600 dark:hover:text-zinc-400 transition">关于</Link></li>
12+
<li><Link href="/projects" className="hover:text-zinc-600 dark:hover:text-zinc-400 transition">项目</Link></li>
13+
<li><Link href="/contact" className="hover:text-zinc-600 dark:hover:text-zinc-400 transition">联系</Link></li>
14+
</ul>
15+
</div>
16+
</nav>
17+
);
18+
}

‎app/components/TypingEffect.tsx‎

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
'use client';
2+
3+
import { useEffect, useReducer } from 'react';
4+
5+
interface TypingEffectProps {
6+
text: string;
7+
speed?: number;
8+
delayBetweenCycles?: number;
9+
className?: string;
10+
}
11+
12+
interface State {
13+
displayedText: string;
14+
isDeleting: boolean;
15+
isWaiting: boolean;
16+
}
17+
18+
type Action =
19+
| { type: 'TYPE_CHAR' }
20+
| { type: 'DELETE_CHAR' }
21+
| { type: 'START_WAITING' }
22+
| { type: 'START_DELETING' }
23+
| { type: 'RESTART' };
24+
25+
export function TypingEffect({
26+
text,
27+
speed = 50,
28+
delayBetweenCycles = 2000,
29+
className = ''
30+
}: TypingEffectProps) {
31+
const initialState: State = {
32+
displayedText: '',
33+
isDeleting: false,
34+
isWaiting: false,
35+
};
36+
37+
const reducer = (state: State, action: Action): State => {
38+
switch (action.type) {
39+
case 'TYPE_CHAR':
40+
return {
41+
...state,
42+
displayedText: text.slice(0, state.displayedText.length + 1),
43+
};
44+
case 'DELETE_CHAR':
45+
return {
46+
...state,
47+
displayedText: state.displayedText.slice(0, -1),
48+
};
49+
case 'START_WAITING':
50+
return {
51+
...state,
52+
isWaiting: true,
53+
};
54+
case 'START_DELETING':
55+
return {
56+
...state,
57+
isWaiting: false,
58+
isDeleting: true,
59+
};
60+
case 'RESTART':
61+
return {
62+
...state,
63+
isDeleting: false,
64+
};
65+
default:
66+
return state;
67+
}
68+
};
69+
70+
const [state, dispatch] = useReducer(reducer, initialState);
71+
const { displayedText, isDeleting, isWaiting } = state;
72+
73+
useEffect(() => {
74+
let timer: NodeJS.Timeout;
75+
76+
if (isWaiting) {
77+
// 等待阶段
78+
timer = setTimeout(() => {
79+
dispatch({ type: 'START_DELETING' });
80+
}, delayBetweenCycles);
81+
} else if (!isDeleting) {
82+
// 打字阶段
83+
if (displayedText.length < text.length) {
84+
timer = setTimeout(() => {
85+
dispatch({ type: 'TYPE_CHAR' });
86+
}, speed);
87+
} else if (displayedText.length === text.length) {
88+
timer = setTimeout(() => {
89+
dispatch({ type: 'START_WAITING' });
90+
}, 50);
91+
}
92+
} else {
93+
// 删除阶段
94+
if (displayedText.length > 0) {
95+
timer = setTimeout(() => {
96+
dispatch({ type: 'DELETE_CHAR' });
97+
}, speed / 2);
98+
} else {
99+
timer = setTimeout(() => {
100+
dispatch({ type: 'RESTART' });
101+
}, 50);
102+
}
103+
}
104+
105+
return () => clearTimeout(timer);
106+
}, [displayedText, text, speed, isDeleting, isWaiting, delayBetweenCycles]);
107+
108+
return (
109+
<span className={className}>
110+
{displayedText}
111+
<span className="animate-pulse">|</span>
112+
</span>
113+
);
114+
}
115+

0 commit comments

Comments
 (0)