返回项目列表

阿逗的个人空间

一个个人网站,集成了 AI 智能聊天助手、后台管理系统、国际化支持和暗色模式。

2026年4月1日精选AI 驱动
AINext.js
在线演示

技术栈

类别技术
框架Next.js 16 (App Router, Webpack)
语言TypeScript 5
前端React 19
样式Tailwind CSS 4
动画Framer Motion 12
国际化next-intl 4
数据存储Upstash Redis
文件存储Vercel Blob
AI 集成Vercel AI SDK 6 (智谱/OpenAI/Anthropic)
认证JWT (jose) + bcryptjs
邮件Nodemailer 8
表单React Hook Form 7 + Zod 4
富文本Tiptap 3(关于页)
Markdownreact-markdown + rehype-highlight + remark-gfm(博客/项目)
图片处理Sharp
PDF 解析unpdf(简历文本提取)
PWASerwist 9(Service Worker)
部署Vercel

功能特性

前台展示

  • Hero 区域 - 动态打字机效果、渐变背景动画、技术标签展示
  • 关于我 - 个人简介、快速信息卡片、兴趣爱好展示
  • 技能展示 - 动态分类的技能卡片,支持自定义分类、颜色主题和排序,含熟练度标识、高亮标记和自定义图标;技能名称支持可开启的国际化(默认单一语言,软技能等描述性内容可启用中英双语切换)
  • 数据统计 - 动画计数器展示项目数、经验年限等
  • 项目展示 - 3D 倾斜卡片效果、缩略图展示、技术栈标签、外链跳转
  • 工作经历 - 时间线布局、成就列表
  • 博客文章 - 文章列表、详情页、目录导航、Markdown 渲染、中英双语内容、JetBrains Mono 等宽字体按需加载
  • 联系表单 - 表单验证、邮件/推送通知
  • AI 聊天 - 悬浮聊天窗口、全屏聊天页面、简历模式/通用模式切换、首次使用引导提示、无障碍支持(aria-live 实时播报)、移动端自定义指针拖拽关闭、空闲时延迟加载、虚拟滚动消息列表、停止生成按钮、紧凑型响应式头部布局
  • 暗色模式 - 跟随系统/手动切换、无闪烁主题加载、安全 localStorage 访问、iOS PWA 状态栏主题自动同步、沉浸式状态栏(black-translucent)
  • 国际化 - 中文/英文双语支持,URL 路径前缀区分
  • SEO 优化 - 动态 Metadata、Open Graph、Twitter Card、Sitemap、Robots.txt、JSON-LD
  • 动态 Favicon - 根据暗色/亮色模式自动切换
  • 回到顶部 - 滚动显示的回到顶部按钮,支持果冻滚动模式自适应
  • 果冻滚动 - 桌面端平滑惯性滚动效果,自动检测设备,移动端使用原生滚动,支持跨页面锚点导航
  • 响应式设计 - 完整的移动端适配
  • 加载骨架屏 - 博客/项目列表与详情页的骨架屏加载状态、首页区域骨架屏
  • PWA 支持 - 可安装到桌面,含安装提示组件、快捷方式(项目/博客),支持 iOS 状态栏主题跟随切换、刘海屏安全区域适配(沉浸式状态栏)
  • 性能优化 - Framer Motion LazyMotion 按需加载、聊天页面动态导入(next/dynamic 延迟加载大型组件)、ISR 增量静态生成(300秒 revalidate)、内存缓存优化(300秒 TTL,减少 80% Redis 查询)、JWT Token 缓存(LRU 淘汰策略,30秒 TTL,最大 100 条)、i18n 消息缓存、Link 预加载(hover 时提前加载目标页面)、滚动会话恢复(跨页面锚点导航)、自定义平滑滚动效果(jellyScrollToElement)、服务端组件 + Suspense 流式渲染(首页 Promise.all 并行获取数据,各区域独立加载,提升首屏性能)、开发模式性能日志(数据获取耗时监控)、DNS 预连接优化(提前解析外部资源域名)、Service Worker 外部图片缓存(CacheFirst 策略,30天过期)、CSS 性能优化(will-change、contain 属性)、Bundle Analyzer 支持(ANALYZE=true 分析打包体积)

后台管理

  • 仪表盘 - 数据概览统计
  • Hero 管理 - 编辑问候语、姓名、标签语、CTA 等
  • 关于管理 - 编辑个人简介、快速信息、兴趣爱好
  • 技能管理 - 增删改技能项、自定义分类管理(增删改分类、颜色主题、排序)、熟练度
  • 项目管理 - 完整 CRUD、Slug 格式验证、Slug 修改警告、缩略图上传、排序、图片上传
  • 经历管理 - 工作经历的增删改
  • 博客管理 - Markdown 编辑器、中英双语内容编辑、新建/编辑
  • 联系管理 - 社交链接、简历上传、可用状态
  • 敏感词管理 - 配置简历脱敏的敏感词映射(原始词→替换词),AI 助手自动替换
  • 留言管理 - 查看/删除留言、已读标记
  • 数据统计 - 编辑展示的统计数字
  • 密码修改 - 安全的密码修改流程(8位以上,含大小写字母和数字),速率限制防护,修改后自动清除 Token 缓存
  • 文件上传 - 支持图片和 PDF 上传到 Vercel Blob(文件类型魔数校验、文件名清洗、分类白名单、PDF 文本自动提取)

AI 聊天系统

  • 多 AI 提供商 - 支持智谱 AI (GLM-4)、OpenAI (GPT-4o-mini)、Anthropic (Claude)
  • 双模式切换 - 简历模式(回答个人相关问题)、通用模式(回答各类问题)
  • 简历内容集成 - 简历模式自动加载 PDF 提取的简历文本作为重要参考上下文
  • 隐私保护 - 用户可配置敏感词映射(公司名自动替换为通用名称),系统提示词包含强制保密规则,禁止泄露公司名称
  • 上下文管理 - Token 感知的上下文窗口管理,压缩版作品集上下文(约 60% token 削减),长对话自动摘要,用户偏好/需求提取
  • 虚拟滚动 - 大量消息时仅渲染视口内消息,保证流畅滚动体验
  • 停止生成 - 支持手动停止 AI 生成,保留已接收内容
  • 自动重试 - AI 请求失败时自动重试,可手动取消
  • 系统提示词缓存 - 30 秒 TTL 内存缓存,减少重复构建开销
  • 管理后台安全 - 系统提示词包含禁止回答管理后台相关问题的指令
  • 流式响应 - 实时流式输出 AI 回复,支持错误处理与中断
  • 超时处理 - AI API 60 秒超时保护,超时返回 504 状态码
  • 打字机动画 - 欢迎消息的逐字显示效果
  • 速率限制 - 按小时/按天的请求频率限制(Redis Lua 原子脚本),速率信息通过响应头返回
  • 登录意图检测 - 输入"login"/"admin"触发登录弹窗
  • Markdown 渲染 - AI 回复支持代码块、加粗、列表等

通知系统

  • 邮件通知 (SMTP) - 收到新留言时发送邮件
  • Bark 推送 (iOS) - 通过 Bark 推送到 iPhone
  • Server酱推送 - 通过 Server酱推送到微信

项目结构

personal-portfolio/
├── app/                          # Next.js App Router
│   ├── [locale]/                 # 国际化路由
│   │   ├── page.tsx              # 首页(各 Section 组合)
│   │   ├── blog/                 # 博客列表 & 详情(含加载骨架屏、JetBrains Mono 字体按需加载)
│   │   ├── chat/                 # 全屏 AI 聊天页
│   │   ├── projects/             # 项目列表 & 详情(含加载骨架屏)
│   │   ├── layout.tsx            # 国际化布局
│   │   ├── error.tsx             # 错误页面
│   │   ├── loading.tsx           # 加载状态
│   │   └── not-found.tsx         # 404 页面
│   ├── admin/                    # 后台管理系统
│   │   ├── layout.tsx            # 管理后台布局
│   │   ├── about/                # 关于管理
│   │   ├── blog/                 # 博客管理
│   │   ├── contact/              # 联系管理
│   │   ├── experience/           # 经历管理
│   │   ├── hero/                 # Hero 管理
│   │   ├── messages/             # 留言管理
│   │   ├── projects/             # 项目管理
│   │   ├── sensitive-words/      # 敏感词管理
│   │   ├── skills/               # 技能管理
│   │   ├── stats/                # 统计管理
│   │   └── change-password/      # 密码修改
│   ├── api/                      # API 路由
│   │   ├── admin/                # 管理后台 API
│   │   ├── auth/                 # 认证 API (登录/登出/验证/改密)
│   │   ├── chat/                 # AI 聊天 API
│   │   ├── contact/              # 联系表单 API
│   │   └── warmup/               # 预热 API(Vercel Cron 定时调用)
│   ├── sw.ts                     # Serwist Service Worker 入口
│   ├── layout.tsx                # 根布局
│   ├── page.tsx                  # 根页面(重定向到默认语言)
│   ├── globals.css               # 全局样式入口
│   ├── manifest.ts               # PWA Manifest(快捷方式、自适应图标)
│   ├── robots.ts                 # Robots.txt 生成
│   ├── sitemap.ts                # Sitemap 生成
│   ├── error.tsx                 # 全局错误页面
│   └── global-error.tsx          # 全局未捕获错误页面
├── components/
│   ├── admin/                    # 管理后台组件
│   │   ├── AdminErrorBoundary.tsx # 管理后台错误边界
│   │   ├── AdminHeader.tsx       # 管理后台头部
│   │   ├── AdminSidebar.tsx      # 侧边栏导航
│   │   ├── ConfirmDialog.tsx     # 确认弹窗
│   │   ├── DataTable.tsx         # 数据表格
│   │   ├── ImageUpload.tsx       # 文件上传(支持图片和PDF)
│   │   ├── MarkdownEditor.tsx    # Markdown 编辑器
│   │   ├── MessageToast.tsx      # 消息提示
│   │   ├── RichTextEditor.tsx    # Tiptap 富文本编辑器(关于页)
│   │   ├── SensitiveWordsEditor.tsx # 敏感词编辑器
│   │   ├── SaveStatus.tsx        # 保存状态指示
│   │   └── SortableList.tsx      # 可排序列表
│   ├── ai/                       # AI 聊天组件
│   │   ├── ChatInput.tsx         # 聊天输入框(支持停止生成)
│   │   ├── ChatMessage.tsx       # 消息气泡
│   │   ├── ChatWidget.tsx        # 悬浮聊天窗口(移动端拖拽关闭)
│   │   ├── ClientChatWidget.tsx  # 客户端聊天入口(空闲时延迟加载)
│   │   ├── LoginModal.tsx        # 登录弹窗
│   │   ├── MarkdownRenderer.tsx  # Markdown 渲染
│   │   ├── ModeToggle.tsx        # 模式切换
│   │   ├── QuickPrompts.tsx      # 快捷提示
│   │   ├── TypingIndicator.tsx   # 输入中动画
│   │   └── VirtualMessageList.tsx # 虚拟滚动消息列表
│   ├── blog/                     # 博客组件
│   │   ├── BlogDetailClient.tsx  # 博客详情客户端
│   │   ├── BlogListClient.tsx    # 博客列表客户端
│   │   ├── MDXComponents.tsx     # Markdown 渲染 & 目录
│   │   └── PostCard.tsx          # 文章卡片
│   ├── layout/                   # 布局组件
│   │   ├── ClientPortfolioWrapper.tsx # 客户端页面包装器(含果冻滚动)
│   │   ├── ClientProviders.tsx   # 客户端 Provider 组合
│   │   ├── DynamicFavicon.tsx    # 动态 Favicon
│   │   ├── Footer.tsx            # 页脚
│   │   ├── Header.tsx            # 导航头部
│   │   ├── LanguageSwitcher.tsx  # 语言切换
│   │   ├── Navigation.tsx        # 导航菜单
│   │   ├── PWAInstallPrompt.tsx # PWA 安装提示组件
│   │   ├── PortfolioPageWrapper.tsx # 页面包装器
│   │   ├── ThemeProvider.tsx     # 主题 Provider
│   │   └── ThemeToggle.tsx       # 主题切换
│   ├── sections/                 # 首页各区域组件
│   │   ├── HeroSection.tsx       # Hero 区域
│   │   ├── HeroSectionWithData.tsx # Hero 区域(服务端组件,支持 Suspense)
│   │   ├── AboutSection.tsx      # 关于区域
│   │   ├── AboutSectionWithData.tsx # 关于区域(服务端组件,支持 Suspense)
│   │   ├── SkillsSection.tsx     # 技能区域
│   │   ├── SkillsSectionWithData.tsx # 技能区域(服务端组件,支持 Suspense)
│   │   ├── StatsSection.tsx      # 统计区域
│   │   ├── StatsSectionWithData.tsx # 统计区域(服务端组件,支持 Suspense)
│   │   ├── ProjectsSection.tsx   # 项目区域
│   │   ├── ProjectsSectionWithData.tsx # 项目区域(服务端组件,支持 Suspense)
│   │   ├── ExperienceSection.tsx # 经历区域
│   │   ├── ExperienceSectionWithData.tsx # 经历区域(服务端组件,支持 Suspense)
│   │   ├── BlogSection.tsx       # 博客区域
│   │   ├── BlogSectionWithData.tsx # 博客区域(服务端组件,支持 Suspense)
│   │   ├── ContactSection.tsx    # 联系区域
│   │   ├── ContactSectionWithData.tsx # 联系区域(服务端组件,支持 Suspense)
│   │   ├── ProjectCard.tsx       # 项目卡片
│   │   ├── ProjectDetailContent.tsx # 项目详情内容
│   │   ├── SectionSkeleton.tsx   # 骨架屏(Hero、About、Skills、Stats、Projects、Experience、Blog、Contact)
│   │   └── TimelineItem.tsx      # 时间线项
│   ├── seo/                      # SEO 组件
│   │   └── JsonLd.tsx            # JSON-LD 结构化数据(Person、WebSite、Article、Breadcrumb)
│   └── ui/                       # 通用 UI 组件
│       ├── AnimatedCounter.tsx   # 动画计数器
│       ├── AnimatedLine.tsx      # 动画线条
│       ├── Badge.tsx             # 徽章
│       ├── Button.tsx            # 按钮
│       ├── ContactForm.tsx       # 联系表单
│       ├── DatePicker.tsx        # 日期选择器
│       ├── Dialog.tsx            # 对话框
│       ├── FloatingParticles.tsx # 浮动粒子
│       ├── Input.tsx             # 输入框
│       ├── MagneticButton.tsx    # 磁性按钮
│       ├── MarkdownRenderer.tsx  # Markdown 渲染器
│       ├── MouseGlow.tsx         # 鼠标光晕
│       ├── OptimizedJellyScroll.tsx # 果冻滚动组件
│       ├── ScrollToTopButton.tsx # 回到顶部
│       ├── Select.tsx            # 选择器
│       ├── Skeleton.tsx          # 骨架屏
│       ├── Textarea.tsx          # 文本域
│       └── TiltCard.tsx          # 3D 倾斜卡片
├── hooks/                        # 自定义 Hooks
│   ├── useChat.ts                # AI 聊天逻辑
│   └── usePWAInstall.ts          # PWA 安装 Hook
├── i18n/                         # 国际化
│   ├── zh-CN.json                # 中文翻译
│   ├── en-US.json                # 英文翻译
│   ├── routing.ts                # 路由配置
│   ├── navigation.ts             # 导航工具
│   ├── request.ts                # 请求配置(含消息缓存)
│   └── server.ts                 # 服务端国际化工具
├── lib/                          # 工具库
│   ├── ai/                       # AI 相关
│   │   ├── providers/            # AI 提供商实现
│   │   │   ├── zhipu.ts          # 智谱 AI(SSE 流式解析、超时保护、缓冲区溢出处理)
│   │   │   ├── openai.ts         # OpenAI
│   │   │   ├── anthropic.ts      # Anthropic
│   │   │   ├── types.ts          # 类型定义
│   │   │   └── index.ts          # 提供商注册
│   │   ├── context.ts            # 上下文构建(含简历内容集成)
│   │   ├── context-compressor.ts # 上下文压缩(精简格式,约 60% token 削减)
│   │   ├── redact.ts            # 简历内容脱敏(用户配置的敏感词映射替换)
│   │   ├── extractor.ts          # 用户偏好/需求提取
│   │   ├── summarizer.ts         # 对话摘要(长对话自动压缩)
│   │   ├── tokenizer.ts          # Token 估算与上下文窗口管理
│   │   ├── utils.ts              # AI 工具函数(流收集等)
│   │   ├── rate-limit.ts         # 速率限制
│   │   ├── resume-parser.ts      # 简历文本获取
│   │   └── system-prompts.ts     # 系统提示词(含 30 秒缓存、管理后台安全警告)
│   ├── auth/                     # 认证
│   │   ├── index.ts              # 认证工具(含 withAuth 包装器)
│   │   ├── jwt.ts                # JWT 工具(含 Token 缓存、LRU 淘汰策略)
│   │   └── middleware.ts         # 认证中间件
│   ├── i18n/                     # 国际化工具
│   │   └── server.ts             # 服务端翻译与语言解析
│   ├── api.ts                    # 服务端数据获取层
│   ├── api-client.ts             # 客户端 API 请求工具
│   ├── constants.ts              # 共享常量(默认技能分类等)
│   ├── data.ts                   # Upstash Redis 数据读写(含 LRU 缓存、原子追加、开发模式性能日志)
│   ├── framer-optimizations.tsx  # Framer Motion 性能优化(LazyMotion、OptimizedMotionDiv)
│   ├── notification.ts           # 通知推送
│   ├── rate-limit.ts             # 通用速率限制(Redis Lua 原子脚本)
│   ├── redis.ts                  # Redis 单例(统一连接管理)
│   ├── revalidate.ts             # 缓存重新验证工具
│   ├── scroll-session.ts         # 滚动会话恢复(跨页面锚点导航,TTL 过期)
│   └── utils.ts                  # 通用工具(getLocaleKey、getClientIp、errorResponse、formatDateTime)
├── types/                        # TypeScript 类型
│   └── index.ts                  # 全局类型定义
├── styles/                       # 样式
│   └── globals.css               # 全局样式(CSS 变量、动画、滚动条等)
├── public/                       # 静态资源
│   ├── icons/                    # 图标目录(UniApp 等自定义图标)
│   └── images/                   # 图片目录
├── scripts/                      # 脚本
│   └── generate-password-hash.js # 密码哈希生成工具
├── next.config.ts                # Next.js 配置
├── proxy.ts                      # Next.js 中间件(i18n 路由 + 管理后台认证保护)
├── vercel.json                   # Vercel 部署配置
├── .env.example                  # 环境变量模板
└── package.json                  # 项目依赖

快速开始

环境要求

  • Node.js 18+
  • pnpm 8+

安装

# 克隆项目
git clone https://github.com/Adou377/personal-portfolio.git
cd personal-portfolio

# 安装依赖
pnpm install

# 复制环境变量
cp .env.example .env.local

# 编辑 .env.local 填入实际配置

配置环境变量

复制 .env.example 到 .env.local,然后根据以下说明填写:

基础配置

变量说明示例
NEXT_PUBLIC_SITE_URL网站域名https://trend-flow.top
NEXT_PUBLIC_DEFAULT_LOCALE默认语言zh-CN

数据存储配置(必需)

变量说明获取方式
UPSTASH_REDIS_REST_URLUpstash Redis REST URLUpstash Console
UPSTASH_REDIS_REST_TOKENUpstash Redis TokenUpstash Console
BLOB_READ_WRITE_TOKENVercel Blob 读写令牌Vercel Storage

AI 聊天配置(至少配置一个提供商)

变量说明
AI_PROVIDERAI 提供商:zhipu / openai / anthropic
ZHIPU_API_KEY智谱 AI API Key
ZHIPU_MODEL智谱模型名(如 glm-4.7-flash)
ZHIPU_BASE_URL智谱 API 地址
OPENAI_API_KEYOpenAI API Key
OPENAI_MODELOpenAI 模型名
ANTHROPIC_API_KEYAnthropic API Key
ANTHROPIC_MODELAnthropic 模型名

AI 速率限制

变量说明默认值
AI_RATE_LIMIT_HOURLY每小时请求限制20
AI_RATE_LIMIT_DAILY每天请求限制100
AI_DAILY_BUDGET_TOKENS每日 Token 预算100000

通知配置(按需配置,不配置则跳过)

变量说明
SMTP_HOSTSMTP 服务器地址
SMTP_PORTSMTP 端口
SMTP_USERSMTP 用户名
SMTP_PASSSMTP 授权码
CONTACT_EMAIL接收通知的邮箱
BARK_SERVER_URLBark 推送地址
BARK_ICON_URLBark 图标 URL
BARK_SOUNDBark 提示音
SERVERCHAN_SENDKEYServer酱 SendKey
SERVERCHAN_CHANNELServer酱推送渠道

管理员认证

变量说明
ADMIN_PASSWORD_HASH管理员密码的 bcrypt 哈希
JWT_SECRETJWT 签名密钥(至少 32 字符)
JWT_EXPIRES_INToken 有效期(如 24h、7d)
ADMIN_LOGIN_MAX_ATTEMPTS最大登录尝试次数
ADMIN_LOGIN_LOCKOUT_MINUTES登录锁定时长(分钟)

文件上传

变量说明默认值
UPLOAD_MAX_SIZE上传文件最大尺寸 (MB)5

生成管理员密码

node scripts/generate-password-hash.js

运行后会生成密码哈希和 JWT 密钥,将其填入 .env.local。

开发

pnpm dev

访问 http://localhost:3000 查看网站。

构建

pnpm build

代码检查

pnpm lint

部署

Vercel 部署(推荐)

  1. 将项目推送到 GitHub
  2. 在 Vercel 导入项目
  3. 创建 Upstash Redis 数据库
    • 访问 Upstash Console
    • 创建新数据库,选择与 Vercel 项目同区域
    • 复制 UPSTASH_REDIS_REST_URL 和 UPSTASH_REDIS_REST_TOKEN
  4. 创建 Vercel Blob Store
    • 访问 Vercel Storage
    • 创建 Blob Store 并关联项目
    • 复制 BLOB_READ_WRITE_TOKEN
  5. 配置环境变量(参考上方配置说明)
  6. 部署

项目已包含 vercel.json 配置,设置了安全响应头(含 CSP)、日本区域部署和 Cron 定时任务(每 5 分钟预热服务器)。

安全头配置

项目通过 vercel.json 配置了以下安全头:

  • Cache-Control: public, max-age=0, must-revalidate - HTML 页面禁止缓存
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection: 1; mode=block
  • Referrer-Policy: strict-origin-when-cross-origin
  • Content-Security-Policy - 限制脚本、样式、图片、连接等来源(支持 Vercel Blob、SimpleIcons CDN)
  • API 路由 Cache-Control: no-store
  • 静态资源 Cache-Control: public, max-age=31536000, immutable

管理后台

访问 /admin 进入管理后台,使用配置的密码登录。

数据存储

项目使用 Upstash Redis 存储结构化数据(JSON),使用 Vercel Blob 存储上传的文件(图片、PDF 等)。这种架构适合 Serverless 部署环境,数据持久化且可扩展。

简历上传

上传 PDF 简历时,系统会自动提取文本内容并存储到 contact.json,AI 聊天简历模式会优先使用提取的简历文本作为上下文。

自定义

修改主题色

编辑 styles/globals.css 中的 CSS 变量:

:root {
  --primary: #8FB2C9;
  --accent: #E94560;
  --ai-glow: #7C3AED;
  /* ... */
}

.dark {
  --primary: #8FB2C9;
  --accent: #E94560;
  --ai-glow: #A78BFA;
  /* ... */
}

修改个人信息

通过管理后台修改所有个人数据。

添加语言

  1. 在 i18n/routing.ts 中添加新语言到 locales
  2. 创建对应的翻译文件(如 i18n/ja-JP.json)
  3. 更新 types/index.ts 中的 Locale 类型

技术栈

Next.jsTypeScriptTailwind CSSVercel AI SDKnext-intl
AINext.js