-
-
-
+
+ {/* Banner 骨架 */}
+
+ {/* 两栏骨架 */}
+
);
@@ -66,24 +81,31 @@ export default function AboutPage() {
if (!data) {
return (
-
暂无关于信息
+
+ 暂无关于信息
+
);
}
return (
-
-
+ {/* Hero Banner */}
+
-
+
+ {/* 两栏:-mt-16 让身份卡里的头像(-mt-12)正好叠到 banner 下沿 */}
+
);
}
\ No newline at end of file
diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css
index aa4e0e7..9d9f02d 100644
--- a/frontend/src/app/globals.css
+++ b/frontend/src/app/globals.css
@@ -842,6 +842,157 @@
border-color: rgba(239, 68, 68, 0.3);
}
+/* ===== 关于页:Mesh Banner / 粒子 / 侧栏小标题 / Tech 图标 ===== */
+.banner-mesh {
+ background-color: #1e3a8a;
+ background-image:
+ radial-gradient(at 18% 24%, rgba(59, 130, 246, 0.85) 0px, transparent 55%),
+ radial-gradient(at 82% 18%, rgba(99, 102, 241, 0.7) 0px, transparent 55%),
+ radial-gradient(at 72% 78%, rgba(96, 165, 250, 0.6) 0px, transparent 55%),
+ linear-gradient(135deg, #1e3a8a 0%, #2563eb 50%, #1e40af 100%);
+}
+.banner-grid {
+ position: absolute;
+ inset: 0;
+ background-image:
+ linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
+ background-size: 60px 60px;
+ -webkit-mask-image: radial-gradient(ellipse at center, black 25%, transparent 75%);
+ mask-image: radial-gradient(ellipse at center, black 25%, transparent 75%);
+ pointer-events: none;
+}
+.banner-grid::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 1px;
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
+}
+
+@keyframes drift {
+ 0%,
+ 100% {
+ transform: translateY(0);
+ opacity: 0.5;
+ }
+ 50% {
+ transform: translateY(-10px);
+ opacity: 1;
+ }
+}
+.particle {
+ animation: drift 6s ease-in-out infinite;
+}
+
+@keyframes rise {
+ from {
+ opacity: 0;
+ transform: translateY(6px);
+ }
+ to {
+ opacity: 1;
+ transform: none;
+ }
+}
+.reveal-up {
+ animation: rise 0.5s cubic-bezier(0.16, 1, 0.3, 1) both;
+}
+
+/* 侧栏小标题:左竖条 + 文字 */
+.side-title {
+ font-size: 0.875rem;
+ font-weight: 600;
+ color: var(--foreground);
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+.side-title::before {
+ content: "";
+ width: 0.25rem;
+ height: 1rem;
+ border-radius: 9999px;
+ background: var(--primary);
+ flex-shrink: 0;
+}
+
+.link-brand {
+ color: var(--muted-foreground);
+ transition: color 150ms ease;
+}
+.link-brand:hover {
+ color: var(--primary);
+}
+
+/* Tech Stack 32×32 小图标 */
+.tech-icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 32px;
+ height: 32px;
+ border-radius: 8px;
+ color: #fff;
+ font-weight: 700;
+ font-size: 11px;
+ font-family: var(--font-mono, ui-monospace, monospace);
+ box-shadow: 0 4px 10px -3px rgba(0, 0, 0, 0.18);
+ transition: transform 0.15s ease;
+ cursor: default;
+}
+.tech-icon:hover {
+ transform: translateY(-2px);
+}
+
+/* 头像环:内白 + 外品牌蓝 */
+.avatar-ring {
+ box-shadow:
+ 0 0 0 4px var(--card),
+ 0 0 0 6px var(--primary),
+ 0 8px 24px -6px rgba(0, 0, 0, 0.18);
+}
+/* 头像占位:品牌渐变 + 首字母 */
+.avatar-placeholder {
+ background: linear-gradient(135deg, #60a5fa 0%, #2563eb 50%, #1e3a8a 100%);
+ color: #fff;
+ font-weight: 700;
+ letter-spacing: -0.02em;
+ text-transform: lowercase;
+}
+
+/* 身份卡:上方贴出大头像的「口袋」容器 */
+/* Card 默认 overflow-hidden + hover 上移;
+ 身份卡既要可见(让 -mt-12 的头像不被裁),又不能 hover 上移(避免头像视觉抖动)。 */
+.card-static {
+ overflow: visible !important;
+}
+.card-static:hover {
+ --tw-translate-y: 0 !important;
+ translate: none !important;
+}
+
+/* Banner 标签条(pill 样式) */
+.banner-pill {
+ display: inline-flex;
+ align-items: center;
+ padding: 0.125rem 0.5rem;
+ border-radius: 0.25rem;
+ font-size: 11px;
+ line-height: 1.4;
+ backdrop-filter: blur(8px);
+ -webkit-backdrop-filter: blur(8px);
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .particle,
+ .reveal-up {
+ animation: none;
+ }
+}
+
/* ===== DataTable 状态徽章(spec §5.13) ===== */
.status-badge {
display: inline-flex;
diff --git a/frontend/src/components/about/AboutMain.tsx b/frontend/src/components/about/AboutMain.tsx
index fcf9405..5d8d6bc 100644
--- a/frontend/src/components/about/AboutMain.tsx
+++ b/frontend/src/components/about/AboutMain.tsx
@@ -1,140 +1,100 @@
"use client";
import type { AboutInfo } from "@/lib/about";
-import { BannerUploader } from "./BannerUploader";
+import { Card, CardContent } from "@/components/ui/card";
interface AboutMainProps {
data: AboutInfo;
- editable: boolean;
- bannerValue: string;
- onBannerChange?: (url: string) => void;
}
/**
- * 关于页右侧主体:
- * - 顶部 banner(可由管理员更换)
- * - 主标题 "Hi, I'm [昵称]" + 副标题
- * - "About Me" 项目列表(emoji + 文本)
- * - "Tech Stack" 技术栈图标网格
- * - 后端 / 前端 / 其他技能(若有)
+ * 关于页右侧主体内容:
+ * - About Me 项目列表
+ * - Skills(Backend / Frontend / Other)
+ * - Bio 长文
+ *
+ * 注:banner 由 page.tsx 单独管理(要让它在 grid 上方,跟身份卡重叠)。
*/
-export function AboutMain({
- data,
- editable,
- bannerValue,
- onBannerChange,
-}: AboutMainProps) {
- const hasBanner = Boolean(bannerValue);
-
+export function AboutMain({ data }: AboutMainProps) {
return (
-
- {hasBanner && (
-
onBannerChange?.(url)}
- editable={editable}
- />
- )}
-
- {/* Greeting 区块 */}
-
-
- 🎉 Hi, I'm {data.nickname || "未命名"}
-
- {data.subtitle && (
-
- {data.subtitle}
-
- )}
-
-
+
{data.aboutPoints.length > 0 && (
-
-
- 🌱
- About Me
-
-
- {data.aboutPoints.map((p, idx) => (
- -
- {p.emoji || "•"}
- {p.text}
-
- ))}
-
-
- )}
-
- {data.techStack.length > 0 && (
-
-
- 🛠
- Tech Stack
-
-
- {data.techStack.map((t, idx) => (
-
- {t.icon || t.name?.[0]?.toUpperCase() || "?"}
-
- ))}
-
-
+
+
+
+ 🌱
+ About Me
+
+
+ {data.aboutPoints.map((p, idx) => (
+ -
+ {p.emoji || "•"}
+ {p.text}
+
+ ))}
+
+
+
)}
{(data.backendSkills || data.frontendSkills || data.otherSkills) && (
-
-
- 💻
- Skills
-
-
- {data.backendSkills && (
-
-
- Backend
-
-
- {data.backendSkills}
-
-
- )}
- {data.frontendSkills && (
-
-
- Frontend
+
+
+
+ 💻
+ Skills
+
+
+ {data.backendSkills && (
+
+
+ Backend
+
+
+ {data.backendSkills}
+
-
- {data.frontendSkills}
+ )}
+ {data.frontendSkills && (
+
+
+ Frontend
+
+
+ {data.frontendSkills}
+
-
- )}
- {data.otherSkills && (
-
-
- Other
+ )}
+ {data.otherSkills && (
+
+
+ Other
+
+
+ {data.otherSkills}
+
-
{data.otherSkills}
-
- )}
-
-
+ )}
+
+
+
)}
{data.bio && (
-
-
- 📝
- Bio
-
-
- {data.bio}
-
-
+
+
+
+ 📝
+ Bio
+
+
+ {data.bio}
+
+
+
)}
);
diff --git a/frontend/src/components/about/AboutSidebar.tsx b/frontend/src/components/about/AboutSidebar.tsx
index 03e67f5..329df48 100644
--- a/frontend/src/components/about/AboutSidebar.tsx
+++ b/frontend/src/components/about/AboutSidebar.tsx
@@ -1,9 +1,10 @@
"use client";
import Link from "next/link";
-import { Pencil, Link2, Mail } from "lucide-react";
+import { Globe, Pencil, Mail } from "lucide-react";
import type { AboutInfo } from "@/lib/about";
import { AvatarUploader } from "./AvatarUploader";
+import { Card, CardContent } from "@/components/ui/card";
import { cn } from "@/lib/utils";
interface AboutSidebarProps {
@@ -11,19 +12,16 @@ interface AboutSidebarProps {
editable: boolean;
/** 头像上传后回调(仅在 editable 时有效) */
onAvatarChange?: (url: string) => void;
- /** 头像 URL 受控值(编辑场景下使用,传入 AvatarUploader) */
+ /** 头像 URL 受控值 */
avatarValue: string;
className?: string;
}
/**
* 关于页左侧栏:
- * [大头像] 昵称 · pronouns
- * 一句话 intro
- * [编辑资料] 按钮(管理员)
- * followers · following
- * 邮箱 + 网站链接
- * Achievements 徽章
+ * ① 身份卡:头像 + 昵称 + pronouns + 一句话 intro + 编辑资料(重叠在 banner 下沿)
+ * ② 联系方式:邮箱 / 网站
+ * ③ Tech Stack:5×n 技术图标网格
*/
export function AboutSidebar({
data,
@@ -32,104 +30,132 @@ export function AboutSidebar({
avatarValue,
className,
}: AboutSidebarProps) {
- return (
-
+
+
+
+
+
+
+ 🌱 About Me
+
+
+ - 🤖Interested in AI Agent & Full-stack development, currently diving deep into both fields.
+ - 🌿Love open source, keep learning and building practical projects.
+ - ⚙️Exploring systems programming & big data ecosystem.
+ - 🌙Enjoy anime in spare time.
+ - 📮Contact: ideast2025@gmail.com
+
+
+
+
+
+ 💻 Skills
+
+
+
+
Backend
+
Go / Python / FastAPI
+PostgreSQL / Redis
+Docker
+分布式 / 大数据生态
+
+
+
Frontend
+
TypeScript / JavaScript
+React / Next.js
+Node.js
+Tailwind / Radix
+
+
+
Other
+
Rust (学习中)
+Git / GitHub
+AI Agent / LLM
+二次元
+
+
+
+
+
+
+ 📝 Bio
+
+
+一个对 AI Agent 和系统编程充满好奇的全栈开发者。
+喜欢用代码把模糊的想法变成能用的东西,
+也愿意把踩过的坑写成笔记分享给同样在路上的人。
+
+持续学习,持续输出,欢迎一起交流。🌙
+
+
+
+
+
+
+
+