个人简历网站搭建:2 解析原有结构并构建首页

2.0 架构解析思路

我的原有的项目在我的github里面。接下来我会从细节上一步步修改成我想要的结构,前提是能够读懂原有的结构。

我有如下几个需求:

  • 首页页面的结构改成附加一些动态效果,并且左边的目录页面太宽了,想要优化一下。
  • 在某个地方添加中英文版本的切换按键,并编写中英文页面。中文优先,如果有时间构建英文页面。
  • 为首页中的出现的每个项目构建页面能够实现跳转。

2.0.1 解析思路

按这 3 个需求,建议按"先外壳,再内容,再路由"的顺序读。

2.0.1.1 先看全站外壳

  • astro.config.mjs
  • src/layouts/BaseLayout.astro
  • src/components/SideBar.astro
  • src/components/SideBarMenu.astro
  • src/components/Header.astro
  • src/styles/global.css

看什么:

  • 侧边栏宽度在哪定的
  • 主内容区最大宽度在哪定的
  • 移动端/桌面端怎么切换
  • 语言按钮放哪最合适

2.0.1.2 再看首页内容

  • src/pages/index.astro
  • src/components/HorizontalCard.astro
  • src/components/Card.astro

看什么:

  • 首页当前是静态写死,还是可以抽成数据
  • 动效适合加在 hero、卡片、分区标题、滚动出现
  • 每个项目卡片现在怎么跳转

2.0.1.3 再看数据和路由

  • src/content/config.ts
  • src/content/blog
  • src/content/store
  • src/pages/blog/[...page].astro
  • src/pages/store/[...page].astro

看什么:

  • 这项目已经有"内容集合 + 列表页 + 详情页"的模式
  • 你的"项目页"可以直接照这个模式新增一套

2.0.1.4 语言切换

  • 中文优先,建议先把中文做成默认
  • 英文不要一开始硬翻整站,先做"核心入口页"英文化
  • 最稳的方式是:
    • 统一把文案抽到配置文件
    • 再做 zh/en 两份数据
    • 切换按钮放在 Header 或 SideBarFooter

2.0.2 VSCode下载插件

作为第一次编码Astro,建议先装这几个(VS Code):

  1. Astro(官方,必须)
  • 提供 .astro 语法高亮、诊断、跳转
  1. Tailwind CSS IntelliSense
  • 你这个项目大量用 Tailwind / DaisyUI,装了更好读 class
  1. ESLint(可选)
  • 读 JS/TS 逻辑更清晰,减少低级错误
  1. Prettier(可选)
  • 保持格式统一,改动更容易审查

另外命令行建议装:

powershell 复制代码
npm install
npx astro check

这样能提前发现 .astro 文件里的类型/语法问题。

有关前端页面展示,你可以使用代码:

bash 复制代码
npm run dev

很可惜不像html在vscode里面有插件live sever,可以点击就可以查看前端,这里你需要手动输入代码。

2.1 设置模板

由于我需要整体修改的页面功能过多,我只借助原有git下来的代码的框架,并不借鉴里面的内容。关于页面设计,主要参考daisyUI进行设计。

现在这个主页面(抽屉布局)主要看这 4 个文件:

  1. 布局骨架
  1. 左侧边栏
  1. 样式与动画
  1. 首页内容本体

2.1.1 src/layouts/BaseLayout.astro详细解释

src/layouts/BaseLayout.astro 的意义就是:

  • 规定每一页的整体外壳
  • 统一头部、侧边栏、主内容区、动画、主题等
  • 让不同页面只需要往里面填自己的内容

简单说:

  • BaseLayout = 全站模板
  • index.astro / projects.astro 这类页面 = 具体内容

你现在这套结构就是:

先用 BaseLayout 定骨架,再用各个页面往 slot 里填内容。

下面按行解释 src/layouts/BaseLayout.astro

  • 1-16

    Astro 前置脚本区,负责导入组件、读取全站配置、接收页面参数。

  • 2

    导入 BaseHead,用于输出 <head> 里的 meta/title。

  • 3

    导入 SideBar,用于左侧抽屉。

  • 4

    导入 Astro 的视图切换动画组件。

  • 6

    从配置文件读取站点默认标题、描述和动画开关。

  • 8-15

    从页面传入参数:

    • image:分享图
    • title:标题,默认 SITE_TITLE
    • description:描述,默认 SITE_DESCRIPTION
    • includeSidebar:是否显示侧栏
    • sideBarActiveItemID:侧栏高亮项
    • ogType:Open Graph 类型
  • 18

    HTML5 文档声明。

  • 19

    <html>

    • lang="zh-CN":页面语言中文
    • data-theme="silk":DaisyUI 主题
  • 20-23
    <head> 区域:

    • 21 输出头部 meta
    • 22 启用页面切换动画
  • 24
    <body> 开始。

  • 25
    app-shell 是整个页面外壳,drawer lg:drawer-open 表示这是 DaisyUI 抽屉布局,大屏默认可开。

  • 26

    隐藏的 checkbox,用来控制抽屉开合,checked 表示默认打开。

  • 27
    drawer-content:主内容区。

  • 28-34

    小屏左上角的抽屉按钮:

    • 28 固定定位,只在小屏显示
    • 29 label 绑定 my-drawer
    • 30-32 汉堡图标。为了手机端能够流畅体验。
  • 35-38

    顶部导航条:

    • navbar 是 DaisyUI 的导航容器
    • flex-1 占位把文字推到右边
    • Guoxuan 是右对齐的品牌文字
  • 39

    灰层遮罩,点击可关闭抽屉。

  • 40-42

    主内容区:

    • shell-content 控制整体灰感/透明度
    • slot 是页面内容插入点
  • 43-82

    页脚:

    • 43 footer 容器
    • 44-61 左侧 logo 和说明
    • 62-81 三列链接区,目前 href="" 为空占位
  • 83
    drawer-content 结束。

  • 84

    条件渲染侧栏:如果 includeSidebar=true 才显示。

  • 85
    app-shell 结束。

  • 86-87

    HTML 文档结束。

一句话总结:

这个文件就是全站骨架 ,负责把"头部、抽屉、主内容、页脚"拼起来,具体每一页只把内容塞进 slot

2.1.2 src/components/SideBar.astro详细解释

下面按当前最新版逐行解释 src/components/SideBar.astro

  • 1-3

    Astro 前置脚本区。这里导入了 Astro 图片组件能力。

  • 2
    import { Image } from "astro:assets";

    使用 Astro 的图片组件来渲染头像,支持构建期图片优化。

  • 5
    <div class="drawer-side z-40">

    侧栏根容器,drawer-side 接入 DaisyUI Drawer 结构,z-40 提升层级避免被主内容盖住。

  • 6
    <label for="my-drawer" class="drawer-overlay"></label>

    这是抽屉遮罩层,绑定 my-drawer。点击遮罩会触发关闭抽屉。

  • 7-8
    aside.sidebar-shell + div.sidebar-panel

    侧栏的外壳和内部面板。宽度、收缩动画、布局细节主要由全局 CSS 的这些类控制。

  • 9-17

    顶部头像区:

    • sidebar-top:顶部区域容器
    • a href="/":点击头像回首页
    • avatarw-11 h-11 rounded-lg ...:头像框尺寸/圆角/裁切
    • Image src="/profile.webp":头像图片来源,alt 是无障碍文本,width/height/format 提供优化信息
  • 19
    <div class="sidebar-body">

    侧栏主体菜单区域开始。

  • 20-27

    第一个菜单项(收起/展开开关):

    • label for="my-drawer" 而不是 button,直接控制抽屉开关
    • sidebar-item sidebar-toggle:沿用统一菜单样式并加 toggle 样式
    • aria-label="Toggle sidebar":无障碍描述
    • svg:收缩展开图标
    • span.sidebar-text:文字 Toggle,通常在收起状态会被 CSS 隐藏或淡出
  • 28-34

    第二个菜单项(Homepage):

    • a href="/":跳转首页
    • sidebar-icon 图标 + sidebar-text 文案
    • 当前文案是 Homepage
  • 35-43

    第三个菜单项(Settings):

    • a href="#":当前是占位链接
    • 图标为设置样式
    • 文案是 Settings
    • 后续可以改成真实路由(如 /settings
  • 44-47

    组件结构闭合:结束 sidebar-bodysidebar-panelasidedrawer-side

一句话总结:

这个文件只负责"左侧抽屉本体结构(头像 + 菜单)",抽屉开关状态来自 my-drawer,而宽度滑动、文字显隐、动画细节主要在 src/styles/global.css 中控制。

2.1.3 src/styles/global.css详细解释

下面按当前最新版逐行解释 src/styles/global.css

  • 1-8
    .sidebar-shell 定义侧栏外壳的默认状态(收起态):

    • width: 3.5rem:收起时窄栏宽度
    • min-height: 100vh:侧栏撑满整屏高度
    • background: hsl(var(--b2)):使用 DaisyUI 主题底色
    • border-right:右侧细分割线
    • transition: width 340ms ease:宽度变化动画
    • overflow: hidden:收起时把超出的文字/内容裁掉
  • 10-12

    #my-drawer 被勾选(展开)时,把侧栏宽度改为 10rem

    这是"抽屉滑开"核心规则之一。

  • 14-19
    .sidebar-panel 是侧栏内部主容器:

    • 纵向 flex 布局
    • 最小高度全屏
    • 内边距 0.5rem
  • 21-26
    .sidebar-top 是头像顶部行:

    • 水平 flex
    • 垂直居中
    • 默认 justify-content: space-between(收起/展开时会被后续规则覆盖)
    • 行高最小 3.25rem
  • 28-32
    .sidebar-toggle(Toggle 那一项):

    • 宽度占满
    • flex-shrink: 0 防止被压扁
  • 34-38
    .sidebar-icon 统一图标大小:

    • 宽高都 1rem
    • 禁止收缩,避免图标在不同状态尺寸不一致
  • 40-44
    .sidebar-body 菜单区域:

    • display: grid
    • gap: 0.5rem 菜单项间距
    • 顶部外边距 1rem
  • 46-54
    .sidebar-item 统一每个菜单项样式:

    • 行内 flex(图标 + 文字)
    • 垂直居中
    • 图标文字间距 0.75rem
    • 最小高度 2.75rem
    • 内边距 0.75rem 0.8rem
    • 圆角 0.75rem
    • white-space: nowrap 防止文字换行
  • 56-58
    .sidebar-item:hover 鼠标悬停背景高亮,使用主题前景色做很淡的混合。

  • 60-69
    .brand-wordmark 控制顶部 Guoxuan 文本样式:

    • margin-left: auto 把文字推到右侧
    • 右内边距 1rem
    • 字体族 Georgia/Times(衬线风格)
    • 字号 1.5rem、字重 400、字距微压缩
    • 文本颜色跟随主题前景色
  • 71-73
    .shell-content 主内容透明度变化动画。

    目前只定义了过渡属性,实际透明变化由其他状态/层实现。

  • 75-86
    .shell-dim 是非侧栏区域灰层:

    • 默认 display: none 隐藏
    • position: fixed 铺满屏幕
    • left: 3.5rem:从收起侧栏右边开始,不盖住侧栏本体
    • 灰色背景 rgba(80, 80, 80, 0.34)
    • 初始 opacity: 0
    • 过渡:透明度 + left(跟随侧栏宽度变化)
    • z-index: 20 保证在主内容上层
  • 88-92

    抽屉展开时显示灰层:

    • display: block
    • left: 10rem(对应展开宽度)
    • opacity: 1(真正变灰)
  • 94-96

    展开时把 .sidebar-top 设为 justify-content: center

    这条后面又被更具体选择器覆盖(见 126-128),最终实际是 flex-start

  • 98-100

    展开时 .sidebar-item 左对齐。

    后面同样有更具体/重复规则。

  • 102-109
    .sidebar-text(菜单文字)默认收起态:

    • max-width: 0 + opacity: 0 + translateX(-6px)
    • overflow: hidden 裁切文字
    • 定义宽度/透明/位移过渡
      实现"收起只看图标,展开文字滑入"。
  • 111-115

    展开时 .sidebar-text

    • max-width: 10rem
    • opacity: 1
    • translateX(0)
      形成文字显现动画。
  • 117-119

    展开时 .sidebar-item 左对齐(与 98-100 含义重复)。

  • 121-124

    展开时 .sidebar-item

    • 再次左对齐(重复)
    • 额外补 padding-inline: 0.8rem
  • 126-128

    展开时 .sidebar-top 左对齐。

    由于选择器更具体,覆盖了 94-96center

一句话总结:

这个 CSS 主要做了 4 件事:侧栏宽度滑动(3.5rem -> 10rem)、文字显隐动画、非侧栏灰层覆盖、图标/菜单统一尺寸 ;其中 94-100117-128 存在重复和相互覆盖,后续可以精简。

2.1.4 src/pages/index.astro详细解释

下面按当前最新版逐行解释 src/pages/index.astro

  • 1-3

    Astro 前置脚本区。这里只做一件事:导入页面要用的布局组件。

  • 2
    import BaseLayout from "../layouts/BaseLayout.astro";

    把全站骨架布局引入首页。后面的首页内容都会被塞进这个布局的 <slot />

  • 5
    <BaseLayout sideBarActiveItemID="home">

    首页使用全站布局,并传入参数 sideBarActiveItemID="home"

    语义上这是告诉侧栏"当前页是 home"(是否真正高亮取决于 SideBar.astro 是否使用了这个参数)。

  • 6
    <div class="p-4 sm:p-6">

    首页内容外层容器,负责留白:

    • 默认内边距 p-4
    • 小屏以上 sm:p-6(更大留白)
  • 7
    <div class="text-2xl font-bold">Page Content</div>

    当前首页正文只是占位文案:

    • text-2xl:较大字号
    • font-bold:粗体
      这行就是你后续要替换成真实首页模块的位置。
  • 8-9

    关闭内容容器和 BaseLayout

    到这里,首页内容定义结束,最终渲染时会被包在全站抽屉/导航/footer 外壳中。

一句话总结:

这个文件现在非常"轻":只负责把首页内容挂到 BaseLayout 上,并放了一个 Page Content 占位块。后续你做个人主页,主要在这里替换成各个 section。

2.2 设置主页

2.2.1 需求分析

整体分为几个部分:

  • 首先展示一些基本的个人信息和网页介绍,下面附加一些链接和联系方式。
  • 以时间轴的形式展示学历和实习经历
  • 最后着重构建项目的展示。由于这里只是一个入口,我分为四类:quant web3 AI other四类,每类仅分出三个项目供点击。每个项目的展示以卡片为基础,每个卡片有标题、描述以及图片。
  • 我也需要上边栏滚动进行每个部分的显示,知道这篇文章你滑动到了哪个部分。


2.2.2 实现方法

下面逐行解释 src/pages/index.astro

文件定位

  • 这个文件负责"首页本身"的全部内容。
  • 它不再依赖骨架里的上边栏,而是自己定义:
    • 顶部目录栏
    • 个人信息首屏
    • 教育经历
    • 职业经历
    • 技术实践
    • 顶部目录的滚动高亮逻辑
    • 技术实践卡片切换逻辑
    • 页面私有样式

1. 前置脚本区

  • 1 ---:Astro frontmatter 开始。这里面写的是服务端/构建时执行的脚本,不是直接输出到页面的 HTML。
  • 2 import BaseLayout ...:导入全站骨架布局。这个首页会被包进 BaseLayout.astro
  • 3 空行:只是为了分块更清楚。

2. 职业经历数据

  • 4 const workExperiences = [:定义职业经历数组,后面时间线会循环这个数组生成。
  • 5 第一条职业经历对象开始。
  • 6 company:公司名 Arrakis Green FinTech
  • 7 location:地点 中国 香港
  • 8 role:岗位 AI 独立研究员
  • 9 time:时间范围。
  • 10 logoSrc:这段经历对应的 logo 图片路径。
  • 11 logoAlt:图片替代文本。
  • 12 第一条经历对象结束。
  • 13 第二条职业经历对象开始。
  • 14 第二条公司名 国泰君安证券
  • 15 第二条地点 中国 深圳
  • 16 第二条岗位 量化研究实习生
  • 17 第二条时间范围。
  • 18 第二条 logo 路径。
  • 19 第二条 logo 替代文本。
  • 20 第二条对象结束。
  • 21 第三条职业经历对象开始。
  • 22 第三条公司名 Goldman Sachs
  • 23 第三条地点 中国 香港
  • 24 第三条岗位 量化研究实习生
  • 25 第三条时间范围。
  • 26 第三条 logo 路径。
  • 27 第三条 logo 替代文本。
  • 28 第三条对象结束。
  • 29 ];:职业经历数组结束。

3. 技术实践数据

  • 31 const techPracticeGroups = [:定义技术实践四大分类的数据源。
  • 32 第一组开始。
  • 33 id: "quant":分组内部唯一标识,供切换逻辑使用。
  • 34 title: "Quant":标签页显示标题。
  • 35 description:当前分组的说明文字。
  • 36 items: [:该分组下的项目卡片列表开始。
  • 37-42 第一张 Quant 卡片:标题、描述、图片、图片替代文本。
  • 43-48 第二张 Quant 卡片。
  • 49-54 第三张 Quant 卡片。
  • 55 Quant 的 items 结束。
  • 56 Quant 分组结束。
  • 57 第二组 AI 开始。
  • 58 id: "ai":AI 分组标识。
  • 59 title: "AI":标签页标题。
  • 60 AI 分组说明。
  • 61 AI 的卡片数组开始。
  • 62-67 第一张 AI 卡片。
  • 68-73 第二张 AI 卡片。
  • 74-79 第三张 AI 卡片。
  • 80 AI 的 items 结束。
  • 81 AI 分组结束。
  • 82 第三组 Web3 开始。
  • 83 id: "web3"
  • 84 title: "Web3"
  • 85 Web3 分组说明。
  • 86 Web3 卡片数组开始。
  • 87-92 第一张 Web3 卡片。
  • 93-98 第二张 Web3 卡片。
  • 99-104 第三张 Web3 卡片。
  • 105 Web3 的 items 结束。
  • 106 Web3 分组结束。
  • 107 第四组 Others 开始。
  • 108 id: "others"
  • 109 title: "Others"
  • 110 Others 分组说明。
  • 111 Others 卡片数组开始。
  • 112-117 第一张 Others 卡片。
  • 118-123 第二张 Others 卡片。
  • 124-129 第三张 Others 卡片。
  • 130 Others 的 items 结束。
  • 131 Others 分组结束。
  • 132 技术实践总数组结束。
  • 133 ---:Astro frontmatter 结束,下面开始输出 HTML。

4. 首页外壳与顶部目录栏

  • 135 <BaseLayout ...>:把当前页包进全站骨架里,同时把侧边栏高亮项设为 home
  • 136 <header id="page-header" ...>:首页自己的顶部栏开始。sticky top-0 表示吸顶;z-30 保证层级较高。
  • 137 顶栏内部容器:
    • mx-auto max-w-6xl:限制最大宽度并居中。
    • h-12:顶栏固定高度。
    • justify-between:左边目录、右边名字分开。
    • px-6 sm:px-10 lg:px-14:不同屏幕下左右内边距。
  • 138 <nav ...>:顶部目录导航开始。
    • page-nav 是你自己定义的样式钩子。
    • overflow-x-auto 表示窄屏时可以横向滚动。
  • 139 "个人信息"目录项:
    • href="#personal-info":点击跳到 id="personal-info" 的区块。
    • page-nav-link-active:默认进页面时它先高亮。
    • data-page-link="personal-info":给脚本用来匹配区块。
    • aria-current="true":无障碍语义上说明它是当前项。
  • 140 "教育经历"目录项,目标是 #education-section
  • 141 "职业经历"目录项,目标是 #work-section
  • 142 "技术实践"目录项,目标是 #tech-practice-section
  • 143 </nav>:目录导航结束。
  • 144 Guoxuan:顶栏右侧名字。
  • 145 顶栏内部容器结束。
  • 146 顶栏结束。

5. 正文总容器

  • 148 首页正文总容器开始:
    • max-w-6xl 保持和顶栏同宽。
    • pt-12 sm:pt-16 lg:pt-24:顶部大留白,制造"导航下方留一块空间再开始正文"的效果。
    • pb-10:底部留白。
  • 149 首屏信息区开始,同时把它作为 #personal-info 锚点目标。
    • grid:大屏下左右两列。
    • lg:grid-cols-[1fr_320px]:左边自适应,右边头像固定 320px
  • 150 左侧文字列开始。
  • 151 个人大标题 <h1>
    • text-right:右对齐。
    • text-5xl sm:text-6xl:响应式字号。
    • style="font-family: Georgia...":手动指定衬线字体。
  • 152 标题文字 Guoxuan Sun
  • 153 </h1>:标题结束。

6. 首屏自我介绍文本

  • 155 段落容器开始:
    • mt-8:与标题拉开距离。
    • space-y-7:每段之间统一垂直间距。
    • text-lg leading-10:较大的阅读字号和行高。
  • 156-159 第一段介绍:
    • 说明这是个人主页。
    • 说明主题是职业发展、技术实践、研究兴趣。
  • 161-163 第二段介绍:
    • 解释左侧抽屉栏是网站架构栏。
    • 解释上侧栏是当前页面的目录。
  • 165-168 第三段介绍:
    • 引导用户通过下方联系方式联系你。
    • 引导用户查看代码仓库。
  • 169 段落容器结束。

7. 联系方式按钮区

  • 171 联系方式容器开始:
    • flex flex-wrap gap-3:横向排列,空间不够时自动换行。
  • 172 邮箱按钮开始,href="mailto:..." 点击会打开邮件客户端。
  • 173-175 邮箱图标 SVG。
  • 176 邮箱文字。
  • 177 邮箱按钮结束。
  • 178 LinkedIn 按钮开始。
    • target="_blank":新标签页打开。
    • rel="noreferrer":安全相关属性。
  • 179-181 LinkedIn 图标 SVG。
  • 182 LinkedIn 文本。
  • 183 LinkedIn 按钮结束。
  • 184 GitHub 按钮开始。
  • 185-190 GitHub 图标 SVG 路径定义。
  • 191 SVG 结束。
  • 192 GitHub 文本。
  • 193 GitHub 按钮结束。
  • 194 CSDN 按钮开始。
  • 195-200 CSDN/博客图标 SVG。
  • 201 CSDN 文本。
  • 202 按钮结束。
  • 203 联系方式容器结束。
  • 204 左侧文字列结束。

8. 首屏头像列

  • 206 右侧头像列开始。
    • order-first lg:order-none:小屏时头像排前面,大屏恢复到右侧。
  • 207 图片外框:
    • rounded-xl 圆角。
    • border 边框。
    • shadow-sm 小阴影。
  • 208-213 <img> 标签:
    • src="/profile.webp":头像来源。
    • alt:无障碍替代文本。
    • object-cover:裁剪铺满容器。
    • loading="eager":首屏图片优先加载。
  • 214 图片外框结束。
  • 215 头像列结束。
  • 216 首屏两列区结束。

9. 第一条分割线

  • 218 divider:首屏和教育经历之间的分隔线。

10. 教育经历区

  • 220 教育区 <section> 开始:
    • id="education-section":顶部目录点击目标。
    • aria-labelledby="education-title":关联到标题,方便无障碍。
    • page-anchor-section:滚动锚点修正的样式钩子。
  • 221 教育区标题。
  • 222 使用 DaisyUI 的 timeline timeline-vertical 生成竖直时间线。
  • 223 第一条教育经历 <li> 开始。
  • 224 左侧时间文本。
  • 225-227 中间时间线节点,小圆点表示时间点。
  • 228 右侧内容卡片开始。
  • 229 卡片内部横向布局开始。
  • 230 logo 容器。
  • 231 香港中文大学 logo 图片。
  • 232 logo 容器结束。
  • 233 文本内容容器开始。
  • 234-236 学校链接,点击跳学校官网。
  • 237 专业名称。
  • 238 文本容器结束。
  • 239 行布局结束。
  • 240 卡片结束。
  • 241 时间线连接线 <hr />
  • 242 第一条教育经历结束。
  • 243 第二条教育经历开始。
  • 244 上方连接线。
  • 245 河海大学时间文本。
  • 246-248 第二个时间点节点。
  • 249 第二张教育卡片开始。
  • 250 卡片内部布局开始。
  • 251 logo 容器。
  • 252 河海大学 logo。
  • 253 logo 容器结束。
  • 254 文字容器开始。
  • 255-257 河海大学官网链接。
  • 258 本科专业名称。
  • 259 文字容器结束。
  • 260 行布局结束。
  • 261 卡片结束。
  • 262 第二条教育经历结束。
  • 263 时间线列表结束。
  • 264 教育区结束。

11. 第二条分割线

  • 266 教育和职业经历之间的分割线。

12. 职业经历区

  • 268 职业经历区开始,id="work-section" 是顶部目录锚点。
  • 269 职业经历区标题。
  • 270 外层 overflow-x-auto:如果横向时间线太宽,可以横向滚动。
  • 271 timeline timeline-horizontal min-w-[960px]:横向时间线,最小宽度 960。
  • 272workExperiences.map(...) 循环渲染每条工作经历。
  • 273 每一项 <li> 开始。
  • 274 如果不是第一项,就先画左侧连接线。
  • 276 timeline-start:时间线起点位置内容容器。
  • 277-292 条件渲染:
    • 偶数项时在上方显示时间。
    • 奇数项时在上方显示公司卡片。
  • 278 偶数项时间文本。
  • 280 奇数项卡片开始。
  • 281 卡片内部横向布局。
  • 282 logo 容器。
  • 283 工作 logo 图片。
  • 284 logo 容器结束。
  • 285 公司文字容器开始。
  • 286 公司名称。
  • 287 公司地点。
  • 288 文字容器结束。
  • 289 行布局结束。
  • 290 岗位名称。
  • 291 奇数项卡片结束。
  • 292 条件块结束。
  • 295-297 中间时间点节点。
  • 299 timeline-end:时间线另一侧内容容器。
  • 300-315 第二个条件渲染:
    • 偶数项时这里放公司卡片。
    • 奇数项时这里放时间。
  • 301-312 偶数项公司卡片结构,与上方那张相同。
  • 314 奇数项时间文本。
  • 315 条件块结束。
  • 318 如果不是最后一项,右侧再接一条连接线。
  • 319 当前工作 <li> 结束。
  • 320 map 循环结束。
  • 321 时间线 <ul> 结束。
  • 322 横向滚动容器结束。
  • 323 职业经历区结束。

13. 第三条分割线

  • 325 职业经历和技术实践之间的分割线。

14. 技术实践区

  • 327 技术实践区开始,id="tech-practice-section" 是顶部目录跳转目标。
  • 328 内层总容器开始。
  • 329 顶部头部布局:
    • 小屏竖排。
    • 大屏横向分布。
  • 330 左侧标题说明容器开始。
  • 331 技术实践标题。
  • 332 辅助说明文字。
  • 333 左侧说明容器结束。
  • 334 右侧标签页容器开始:
    • tabs tabs-boxed 是 DaisyUI 标签样式。
  • 335 开始循环 techPracticeGroups 渲染标签按钮。
  • 336-340 每个标签按钮:
    • type="button":防止当成表单提交按钮。
    • class 中如果 index === 0,默认第一个标签激活。
    • data-tech-tab={group.id}:把分组 id 存到按钮上,供脚本读取。
  • 341 按钮显示文本,如 Quant
  • 342 按钮结束。
  • 343 map 结束。
  • 344 标签容器结束。
  • 345 顶部布局结束。
  • 347 下半部分内容容器开始。
  • 348-350 分组描述段落:
    • 默认显示第一组 Quant 的描述。
    • 后续会被脚本动态改写。
  • 352 卡片网格开始:
    • 小屏单列。
    • md 两列。
    • xl 三列。
  • 353 循环当前默认分组的 3 张卡片。
  • 354-358 每张卡片外层 article
    • tech-stack-card 是你自定义的卡片样式钩子。
    • is-active 让第一张初始突出。
    • data-tech-carddata-card-index 给脚本识别。
  • 359-363 整张卡片用 <button> 包住,点击时可以切换激活态。
  • 364 图片区域外层,固定 16:10 比例。
  • 365-371 卡片图片:
    • data-tech-image 让脚本后续替换图片时能找到它。
  • 372 图片区域结束。
  • 373 文字内容区域开始。
  • 374 项目标题,data-tech-title 供脚本替换。
  • 375 项目描述,data-tech-copy 供脚本替换。
  • 376 文字区域结束。
  • 377 按钮结束。
  • 378 卡片结束。
  • 379 卡片循环结束。
  • 380 网格结束。
  • 381 内容容器结束。
  • 382 技术实践内层容器结束。
  • 383 技术实践区结束。
  • 384 首页正文总容器结束。
  • 385 BaseLayout 结束。

15. 页面交互脚本

  • 387 <script define:vars={``{ techPracticeGroups }} is:inline>
    • 在页面里写内联脚本。
    • define:vars 把前面 Astro 里的 techPracticeGroups 注入到浏览器端脚本。
  • 388 获取顶部栏元素。
  • 389 找到所有顶部目录链接。
  • 390-392 根据目录链接上的 data-page-link,去找对应的正文区块 DOM。
  • 393 找到所有技术实践标签按钮。
  • 394 找到所有技术实践卡片。
  • 395 找到描述段落 DOM。
  • 396 activeGroup 初始设为第一组 Quant

16. 顶部目录与锚点修正逻辑

  • 398 定义 syncHeaderOffset 函数。
  • 399 如果没找到头栏,直接退出。
  • 400 把头栏高度写进 CSS 变量 --page-header-offset
    • + 18 是额外补偿,避免锚点跳转时区块太贴顶。
  • 401 函数结束。
  • 403 定义 setActivePageLink(targetId)
  • 404 遍历每一个目录项。
  • 405 判断当前链接是不是目标链接。
  • 406 用类名切换当前项高亮。
  • 407 同时更新 aria-current 状态。
  • 411 目录状态切换函数结束。

17. 顶部目录滚动高亮

  • 414 如果确实找到了可观察的页面区块,就初始化滚动逻辑。
  • 415 先同步一次头栏高度偏移。
  • 416 窗口尺寸变化时重新同步偏移。
  • 418 创建 IntersectionObserver
  • 419-423 观察回调:
    • 过滤掉当前不可见区块。
    • 按可见比例从大到小排序。
  • 424-426 如果有可见区块,就把最"显眼"的那个区块对应导航设为当前项。
  • 428-431 观察器参数:
    • rootMargin 改变判断区域。
    • threshold 规定触发比例。
  • 432 观察器创建结束。
  • 434 对每个页面区块开始观察。
  • 436 遍历每个顶部目录链接。
  • 437-440 点击目录时,先立即设置当前项状态,避免视觉延迟。
  • 441 监听绑定结束。
  • 442 这一整段顶部目录逻辑结束。

18. 技术实践卡片高亮逻辑

  • 444 定义 activateCard(activeIndex)
  • 445-448 遍历所有卡片:
    • 当前卡片加 is-active
    • 非当前卡片去掉 is-active
    • 同时更新 aria-pressed
  • 449 函数结束。

19. 技术实践分类切换逻辑

  • 451 定义 renderGroup(groupId)
  • 452techPracticeGroups 里找到对应分组。
  • 453 找不到就退出。
  • 455 更新当前激活的分组。
  • 456 把顶部说明文字换成新分组说明。
  • 458 遍历当前 3 张卡片 DOM。
  • 459 拿到这个位置对应的新数据项。
  • 460 找到卡片里的图片节点。
  • 461 找到标题节点。
  • 462 找到描述节点。
  • 464 如果某个节点缺失,就跳过。
  • 465 替换图片地址。
  • 466 替换图片替代文本。
  • 467 替换标题文字。
  • 468 替换描述文字。
  • 469 当前卡片更新结束。
  • 471 切换分组后默认激活第一张卡片。
  • 472 函数结束。

20. 技术实践交互初始化

  • 474 页面初次加载时,先激活第一张卡片。
  • 475-478 给每张卡片绑定事件:
    • 鼠标移入时高亮
    • 点击时高亮
  • 480 遍历顶部的分类标签。
  • 481-486 点击标签时:
    • 取出目标分组 id
    • 切换 tab-active
    • 调用 renderGroup(target) 刷新 3 张卡片
  • 487 标签循环结束。
  • 488 脚本结束。

21. 页面私有样式

  • 490 <style is:inline>:当前页面的局部内联样式开始。
  • 491-493 page-nav:Firefox 下隐藏横向滚动条。
  • 495-497 page-nav::-webkit-scrollbar:Chrome/Safari 下隐藏滚动条。
  • 499-502#personal-info 和各个大区块设置 scroll-margin-top
    • 锚点跳转时会预留出顶部栏的高度。
  • 504 .page-nav-link 样式开始。
  • 505inline-flex 保证文字和下划线控制稳定。
  • 506 垂直居中。
  • 507 给目录项底部一点空间,用来放下划线。
  • 508 默认下划线透明。
  • 509 目录字号。
  • 510 行高为 1,收紧文字高度。
  • 511 字母/汉字间距略拉开。
  • 512 默认文字颜色较浅。
  • 513 去掉默认链接下划线。
  • 514 过渡动画:颜色和边框颜色平滑变化。
  • 515 当前规则结束。
  • 517-519 hover 时把目录文字变深。
  • 522-524 当前项样式:
    • page-nav-link-active
    • aria-current="true"
    • 显示深色文字和底部实线
  • 526 .tech-stack-card 开始。
  • 527 卡片的过渡动画定义。
  • 528 默认降低饱和度,让非激活卡片看起来更"退后"。
  • 529 鼠标形状变成手型。
  • 530 当前规则结束。
  • 532-537 激活卡片样式:
    • 饱和度恢复
    • 边框变成主题色
    • 阴影增强
  • 544 样式结束。

一句话总结

  • 这个文件本质上做了三件事:
    • 用数据数组描述首页内容
    • 用 Astro 模板把这些数据渲染成首页结构
    • 用一小段前端脚本实现"顶部目录滚动高亮"和"技术实践分类切换"

如果你要,我下一步可以继续做两件事之一:

  1. 单独把 387-488 这段脚本逐行拆得更细
  2. 单独把 135-385 这段 HTML 结构画成"页面结构图"给你看
相关推荐
Moment17 小时前
面试官:上下文过长导致语义偏移,工程上怎么优化
前端·后端·面试
kkoral17 小时前
Vue3 图片标框功能实现方案
前端·vue.js·vscode·typescript
IT_陈寒17 小时前
React hooks依赖数组坑得我差点重写整个组件
前端·人工智能·后端
刀法如飞17 小时前
【Claude Code AI编程实战指南】
前端·后端·ai编程
怕浪猫17 小时前
# Electron 开发实战(三):基础UI开发与布局全解
前端·javascript·electron
你觉得脆皮鸡好吃吗17 小时前
XSS渗透 Session
前端·网络·xss·网络安全学习
大可-17 小时前
CSDN博客-星火知识库教程
前端·javascript·vue.js·elementui·html
fhqlongteng18 小时前
RK3576上electron调用GPU的功能设置方法
前端·javascript·electron·gpu·rk3576
weixin_3975740918 小时前
ReAct推理链的工程化实现与最佳实践
前端·react.js·前端框架