博客模板更改记录

引言

生命不息,折腾不止。为了提供更好的阅读体验和交互功能,近期对博客模板进行了多项底层与UI层面的升级。本文详细记录了核心代码的修改过程。


1. 添加字体切换组件(已弃用)

在侧边栏新增了 <FontToggle /> 组件,支持用户在 Serif(衬线体)、Sans-serif(无衬线体)等字体间无缝切换,满足不同用户的阅读偏好。

2. 增加代码块 Diff 高亮支持

信息

此功能允许在 Markdown 代码块中使用 insdel 参数来高亮显示新增或删除的行,极大地提升了技术文章中代码变更的可读性。

Shiki Store 改造

app/stores/shiki.ts 中添加了解析 insdelstartlinenumber 参数的逻辑,并实现了自定义的 transformer 来处理 diff 高亮和行号偏移。

3. 新增文章最后编辑时间卡片

在文章页面底部添加了一个显示文章最后编辑时间的卡片,提示读者信息的时效性。

重构了文章底部版权卡片,增加了文章作者、发布时间及协议跳转,视觉上更加整洁美观。

5. 评论系统改为 Artalk

将博客的评论系统从原有的组件替换为 Artalk,以提供更丰富的评论功能(表情、图片灯箱、LaTeX 公式)和更好的隐私掌控。

6. 增加标签云页面

使用线性插值算法根据标签文章数量动态计算字体大小,实现标签云效果。

7. 升级 LinkCard 图标支持

现在 ::link-card 组件支持直接使用 Iconify 图标集合(例如 ph:check),同时兼容填入图片 URL。

LinkCard.vuevue
   <slot name="icon" class="link-card-icon-slot">
      <Icon v-if="icon && icon.includes(':') && !icon.includes('/')" :name="icon" class="link-card-icon" size="2.5rem" />
      <UtilImg v-else-if="icon" class="link-card-icon" :src="icon" :mirror />
   </slot>

8. 增加文章加密功能

实现了一个纯前端的文章加密方案。在构建阶段使用 AES 算法加密文章正文,浏览器端通过用户输入的答案进行解密渲染。既保护了隐私,又无需后端服务支持。

核心实现

编写了一个 Nuxt 模块,在 content:file:afterParse 钩子中拦截 Markdown 解析结果,将 body 对象序列化并加密,替换为 <DecryptVerifier> 组件节点。

9. 新增动态(Echo)功能

新增了类似朋友圈的“动态”板块,用于发布短篇想法或生活点滴。支持 Markdown 渲染、图片九宫格、外部扩展(视频、链接)以及点赞评论互动。

核心特性

  • API 集成:对接外部 API 获取动态数据,支持分页加载。
  • Markdown 渲染:在动态卡片中支持部分 Markdown 语法及 MDC 组件渲染。
  • 智能时间显示:实现了仿微信的“刚刚”、“几分钟前”等相对时间显示。
  • 交互体验:支持点赞(本地存储状态)、评论(Artalk 集成)、长文折叠、图片灯箱。
app/pages/echo/index.vuevue
<script setup lang="ts">
// ... 数据获取逻辑
const fetchEchoes = async () => {
  // ...
  const data = await $fetch<EchoResponse>(url)
  // ...
}
</script>

<template>
  <div class="echo-page">
    <div class="echo-header">
      <h2 class="echo-title">动态</h2>
      <p class="echo-desc">记录生活中的点滴与思考</p>
    </div>
    
    <div class="echo-container">
      <TransitionGroup name="list" tag="div" class="echo-list">
        <EchoCard 
          v-for="echo in echoes" 
          :key="echo.id" 
          :echo="echo"
          @like="handleLike"
          @tag-click="handleTagClick"
        />
      </TransitionGroup>
    </div>
  </div>
</template>

10. 增加 Mermaid 图表支持

为了在技术文章中更直观地展示流程图和架构图,现在在 Markdown 代码块中标记为 mermaid 语言时,将自动渲染为 Mermaid 图表。

核心实现

拦截了默认的代码块组件渲染,新增了 <Mermaid /> 组件,利用其在客户端异步加载 mermaid 运行时解析渲染,并可根据站点明暗主题自动切换配置。

app/components/content/ProsePre.vuevue
<script setup lang="ts">
// ...
onMounted(async () => {
	if (props.language === 'mermaid')
		return // 交给 Mermaid 组件自行接管渲染

	// 处理其他语言的高亮...
})
</script>

<template>
  <Mermaid v-if="language === 'mermaid'" :code="code" />
  <figure v-else>
    <!-- 原有高亮代码块 -->
  </figure>
</template>

11. 新增 Album 相册组件

为满足摄影集的展示需求,新增了一套强大的 <Album /><AlbumItem /> 相册组合套件。支持折叠展开、双缓冲动态首图轮播、并深度集成了手势友好的全屏灯箱。

主要功能与实现

  • 多图相册网格:利用 Vue 的 provide/inject 收集子 <AlbumItem /> 组件。
  • 自定义灯箱 (Lightbox):支持原生 JavaScript Pointer Event 进行拖拽平移和双指缩放,通过计算图片的相对屏幕显示比例实现安全边界阻挡。
  • 双缓冲轮播图:若未单独提供封面,将抽取相片集数组,使用独立的 layerAlayerB 双图片层交替淡入淡出轮播,避免直接修改 src 造成的加载白屏。
app/components/content/Album.vuevue
<script setup lang="ts">
// ...
const activeLayer = ref<'a' | 'b'>('a') // 双缓冲避免白屏
const layerA = ref('')
const layerB = ref('')

function startCarousel() {
	carouselTimer = setInterval(() => {
		const nextIdx = (carouselIndex.value + 1) % items.value.length
		const nextSrc = items.value[nextIdx]?.src || ''

		// 将下一张图片预加载到后景层
		if (activeLayer.value === 'a') {
			layerB.value = nextSrc
			activeLayer.value = 'b'
		} else {
			layerA.value = nextSrc
			activeLayer.value = 'a'
		}
		carouselIndex.value = nextIdx
	}, 4000)
}

provide('album-register', (item) => {
	const index = items.value.length
	items.value.push(item)
	return index
})
provide('album-open', (index: number) => { /* 调起全局灯箱 */ })
</script>
距离上次编辑:

部分信息可能已经过时。

GitHub + Azure 学生免费权益申请指北
已抵达博客尽头

评论

评论加载中...