中 / EN · 个人作品集单页应用 · AI 全栈开发 × 视觉设计 A personal portfolio SPA built with React + Vite + Tailwind CSS, featuring an AI chat assistant and a hidden game library easter egg.
Laser(伊泽)的个人作品集 —— 一个从视觉出发、用代码落地的全栈创作者主页。站内收录平面设计、UI/UX、视频剪辑、三维建模、交互开发与 AI 项目,并内置一个可对话的 AI 助手「Etta」与彩蛋隐藏游戏库。
| 层 | 技术 |
|---|---|
| 框架 | React 18 · React Router 6 (HashRouter) |
| 构建 | Vite 5 · @vitejs/plugin-react |
| 样式 | Tailwind CSS 3 · PostCSS · Autoprefixer |
| 图标 | lucide-react |
| 搜索 | pinyin-pro(拼音搜索) |
| 视频 | hls.js(入场 HLS 视频流) |
| Markdown 渲染 | react-markdown(聊天气泡富文本) |
| 图表 | Apache ECharts 6(echarts-lite/v1 协议)· Mermaid 11(动态加载) |
| 媒体处理 | sharp · pdf2png(构建脚本) |
| AI 对话 | DeepSeek Chat API(本地规则先行 + 双层识别 + 本地兜底) |
- 入场动画场景 — 融合 HLS 背景视频、中央光晕、浮动标签与网格线的介绍场景
- 首页分区 — 关于我、代表作品预览、核心技能、联系方式(含微信二维码弹窗)
- 作品总览页 — 分类导航、拼音/关键词搜索、作品卡片流,第一个分类为「人工智能开发」
- 作品详情页 — 每个作品独立详情,含描述、标签、图集与相关作品推荐
- AI 聊天助手「Etta」 — 悬浮对话面板,支持多轮对话、Markdown 富文本、ECharts/Mermaid 图表渲染、界面识别与一键跳转(详见下方「AI 模块」)
- 彩蛋隐藏游戏库 — 点击导航栏 Logo 10 次解锁 6 款小游戏(贪吃蛇、五子棋、扫雷、蜘蛛纸牌、跳一跳、魂斗罗)
- 自定义光标 — CustomCursor 全局自定义鼠标效果
| 路径 | 页面 | 说明 |
|---|---|---|
#/ |
HomePage | 首页(入场 + 各分区) |
#/works |
WorksPage | 作品总览(支持 ?cat= 分类) |
#/works/:id |
DetailPage | 作品详情 |
#/easter-egg |
EasterEggPage | 彩蛋隐藏游戏库 |
使用 HashRouter,兼容 GitHub Pages 等静态托管,无需服务端回退配置。
AI 助手采用「本地规则先行 + 双层识别 + 本地兜底」策略,任何情况下都能响应,并保证「内容解答类提问绝不误跳转」:
- 本地规则先行 — 内容解答类提问(是什么 / 介绍 / 讲解 / 输出 等)先在本地确定性命中:匹配到已知作品则直接输出其介绍,不进 LLM、不跳转(见
localAnswer.js) - Function Calling — 其余情况请求带
tools,模型原生返回结构化tool_calls,解析后跳转 - JSON 模式 — Function Calling 失败时,用
response_format强制合法 JSON - 本地兜底 — 未配置 API Key 或 API 不可用时,走关键词 / 本地界面匹配
- 输出防御 — LLM 在内容类提问时误判为导航,
applyParsed自动降级为正文回答
回复渲染支持 Markdown(react-markdown)与 数据图表(ECharts echarts-lite/v1 精简协议)流程图 / 时序图(Mermaid 动态加载);会话历史按 token 预算裁剪(tokenPrune.js),利用 DeepSeek 前缀缓存降低长会话成本。
核心文件:
| 文件 | 职责 |
|---|---|
src/utils/aiEngine.js |
AI 引擎:对话 + 界面调用(本地先行 + 三层识别 + 输出防御) |
src/utils/localAnswer.js |
本地规则先行:内容解答确定性兜底,杜绝误跳转 |
src/utils/actionParser.js |
解析 AI 输出为可执行动作 |
src/utils/tokenPrune.js |
会话历史按 token 预算裁剪(前缀缓存友好) |
src/utils/chartParser.js |
echarts-lite/v1 图表规格解析(纯函数,含单测) |
src/data/interfaceCatalog.js |
界面清单:AI 可跳转目的地的权威注册表 |
src/data/aiPrompt.js |
系统提示词(人设、多轮追问、意图边界、跳转规则、图表输出规则) |
src/components/ai/AIChatPanel.jsx |
聊天面板 UI(消息气泡、Markdown、图表、动作卡片) |
src/components/ai/MarkdownChart.jsx |
ECharts 模块化渲染组件 |
src/components/ai/MermaidRenderer.jsx |
Mermaid 动态渲染组件 |
图表规格使用「LLM 输出精简 chartSpec JSON」的业界主流做法(参考 OpenVizAI / WrenAI / ECharts-Lite 议题),坏规格自动优雅降级为显示原始代码,绝不崩溃。
AI 配置:src/config/aiConfig.js 被 .gitignore 忽略,本地开发手动创建;CI 部署时由 GitHub Actions 通过 secrets.DEEPSEEK_API_KEY 自动注入。未配置时 AI 自动切换本地兜底模式。
作品数据由 两份来源合并生成(见 src/data/worksData.js):
src/data/manifest.json— 构建脚本自动扫描public/生成的文件清单src/data/workMetadata.js— 人工维护的标题、描述、分类等元数据
因此每次启动 / 构建前都必须先运行 manifest 生成脚本,确保数据与磁盘文件同步。
npm run manifest # 扫描 public/ 并重写 src/data/manifest.json- 新增静态作品:把文件放入
public/对应目录,并在workMetadata.js登记元数据 - 外部项目(GitHub 等):标记
isExternal: true,仅登记元数据即可
# 1. 安装依赖
npm install
# 2. 本地开发(自动先跑 manifest)
npm run dev # http://localhost:5173
# 3. 生产构建(自动先跑 manifest)
npm run build # 输出到 dist/
# 4. 本地预览构建产物
npm run preview也可用根目录
server.js(Node 静态服务器)预览旧版静态页。
├── src/
│ ├── components/
│ │ ├── ai/ # AI 聊天面板(MarkdownChart、MermaidRenderer)
│ │ ├── intro/ # 入场场景(IntroScene、Navbar 等)
│ │ ├── layout/ # 自定义光标、滚动回顶
│ │ ├── sections/ # 首页分区(About、Skills、Contact、WorksPreview)
│ │ └── works/ # 作品卡片、分类导航、搜索
│ ├── config/
│ │ ├── siteConfig.js # 站点全局配置(品牌、联系方式、技能、奖项)
│ │ └── aiConfig.js # AI 配置(.gitignore 忽略)
│ ├── data/ # 作品元数据、清单、界面注册表、AI 提示词
│ ├── hooks/ # useInView / useCountUp / useLocalStorage / useMediaQuery
│ ├── pages/ # HomePage / WorksPage / DetailPage / EasterEggPage
│ ├── utils/ # aiEngine / actionParser / localAnswer / chartParser / tokenPrune / pinyinSearch
│ ├── App.jsx # 路由与全局布局
│ └── main.jsx # 应用入口
├── public/
│ ├── program/ # 交互作品(QQ音乐、小游戏 HTML)
│ ├── img/ # 作品缩略图
│ ├── video/ # AIGC 视频作品
│ ├── detail/ # 历史静态详情页(已不再被引用)
│ ├── art/ modeling/ AIGC/ # 设计稿、建模源文件、工作流
├── scripts/
│ ├── generate-manifest.mjs # 自动扫描生成 manifest.json
│ └── pdf2png.mjs # PDF 转 PNG 工具
└── .github/workflows/deploy.yml # GitHub Pages 自动部署
推送到 main 分支即触发 deploy.yml 自动构建并部署到 GitHub Pages:
- Node 20 +
npm ci安装依赖 - 通过
secrets.DEEPSEEK_API_KEY注入src/config/aiConfig.js npm run build产出dist/- 上传并发布到 GitHub Pages
仓库需在 GitHub 设置中启用 Pages(Source: GitHub Actions)。
验证方式:npm run build 构建 + npm run dev 本地运行 + 浏览器逐路由实测。
| 模块 | 状态 | 说明 |
|---|---|---|
| 构建(build) | PASS | 1602 modules,产物正常生成 |
首页 #/ |
PASS | 入场、About、WorksPreview、Skills、Contact 均渲染 |
作品总览 #/works |
PASS | 分类导航(AI 开发置顶)、搜索、卡片跳转正常 |
作品详情 #/works/:id |
PASS | 描述、标签、相关作品正常 |
彩蛋游戏库 #/easter-egg |
PASS | 6 款隐藏小游戏正常展示 |
| AI 聊天面板 | PASS | 本地规则先行 + 双层识别 + 本地兜底;Markdown 富文本渲染 |
| AI 图表渲染 | PASS | ECharts 输出 <canvas>、Mermaid 输出 <svg>(运行时验证) |
| 彩蛋解锁(Logo ×10) | PASS | 逻辑正确,连点 10 次跳转 /easter-egg |
单测:
test/下用 Node 内置测试运行器(node --test)覆盖图表规格解析、token 裁剪与本地规则先行,共 17 个用例。
非阻塞提示:入场 HLS 视频流为远程资源(Mux CDN),偶发
ERR_ABORTED,不影响功能。React Router v6 future flags 已显式启用(v7_startTransition/v7_relativeSplatPath),弃用警告已消除。
本项目仅用于个人学习与展示,作品与代码版权归原作者 Laser(伊泽)所有。