# 为 Hexo Shoka 新增 “动态” 和 “画作” 页面

最近给博客增加了两个独立页面:用于展示部分 X(Twitter)帖子的 “动态” 页,以及用于展示最近 Pixiv 作品的 “画作” 页。

最初希望两个页面都能在访问时自动获取最新内容,但实际实现时遇到了平台接口、请求频率和跨站加载方面的限制。为了让 GitHub Pages 上的静态博客保持稳定,最终采用了 “固定内容展示 + 外部详情链接” 的方案。

# 页面目标

  • 在 Shoka 菜单中加入 “动态” 和 “画作” 入口;
  • 动态页直接显示部分推文内容,而不是只有外部链接;
  • 画作页以卡片网格展示最近 12 项 Pixiv 作品;
  • 不在公开仓库中保存 X 或 Pixiv 的私密 API 凭据;
  • 保持 GitHub Pages 子目录 “/Bananaki/” 下的资源路径正确。

# 动态页的实现

# 最初遇到的问题

最初尝试在访问页面时获取最新推文,但这种方式并不适合当前的纯静态站点:

  • X API 存在权限和频率限制,容易出现 “Rate limit exceeded”;
  • 第三方组件可能只显示外部链接,也可能受到登录、年龄限制和隐私设置影响;
  • GitHub Pages 不能安全保存 Write API Key 等服务端密钥;
  • 浏览器端请求成功与否会受访客网络环境影响。

因此没有继续实现 “每次访问都实时同步全部推文”,而是改为保存指定推文的公开展示内容。

# 固定展示部分推文

动态页使用普通 HTML 保存推文内容和原始状态链接,每一条放在独立卡片中:

1
2
3
4
5
6
7
8
9
<div class="tweet-window">
<section class="tweet-card">
<blockquote class="twitter-tweet" data-dnt="true" data-theme="dark">
<p lang="ja" dir="ltr">推文内容……</p>
&mdash; バナナキ (@GohanNanaki)
<a href="https://x.com/GohanNanaki/status/推文ID">发布日期</a>
</blockquote>
</section>
</div>

页面顶部只标注 “仅展示部分推文”,避免让访客误认为这里是完整时间线或会自动按点赞数排序。

对于需要登录 X 并通过年龄验证的内容,不尝试绕过平台限制,只显示说明和原始链接:

1
2
3
4
5
<section class="tweet-card tweet-restricted">
<p><strong>年龄限制内容</strong></p>
<p>该推文需要登录 X 并通过年龄验证后查看。</p>
<p><a href="https://x.com/GohanNanaki/status/推文ID">在 X 上打开这条推文</a></p>
</section>

固定内容增加后,页面会变得很长。因此给外层容器设置最大高度和纵向滚动:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.tweet-window {
max-width: 720px;
max-height: 1000px;
margin: 0 auto;
padding: 0 14px;
overflow-y: auto;
border-radius: 12px;
}

.tweet-card {
margin: 16px 0;
padding: 18px 20px;
border-radius: 12px;
}

这种实现不依赖私密 API,构建后就是普通静态 HTML。缺点是更换推文时需要手动更新,但稳定性比实时请求更高。

# 画作页的实现

# 为什么使用本地缩略图

Pixiv 原图不适合直接作为第三方网站的长期热链资源,访问也可能受到登录状态和来源限制。因此画作页将缩略图保存到博客本地,点击卡片后再前往 Pixiv 查看原图和详情。

目前页面固定展示最近 12 项作品,每张卡片包含本地缩略图、作品标题、Pixiv 详情链接,以及多图作品的页数标记:

1
2
3
4
5
6
7
8
9
10
<a class="artwork-card"
href="https://www.pixiv.net/artworks/作品ID"
target="_blank"
rel="noopener noreferrer">
<div class="artwork-cover">
<img src="/Bananaki/images/pixiv/作品ID.jpg" alt="作品标题">
<span class="artwork-pages">2P</span>
</div>
<div class="artwork-title">作品标题</div>
</a>

“target=_blank” 用于在新标签页打开 Pixiv,“rel=noopener noreferrer” 用于避免新页面访问当前页面的窗口对象。

# 响应式网格

桌面端使用三列布局,较窄的屏幕切换为两列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.artwork-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
}

.artwork-cover {
aspect-ratio: 1 / 1;
overflow: hidden;
}

.artwork-cover img {
width: 100%;
height: 100%;
object-fit: cover;
}

@media (max-width: 767px) {
.artwork-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
}

“aspect-ratio” 和 “object-fit: cover” 可以让不同尺寸的缩略图保持统一比例,标题过长时则使用省略号。

# 添加 Shoka 菜单入口

两个页面建立后,在 Shoka 配置中增加入口,并把友站菜单放在最后:

1
2
3
4
menu:
动态: /twitter/ || twitter
画作: /artworks/ || star
friends: /friends/ || heart

页面文件分别放在:

1
2
source/twitter/index.md
source/artworks/index.md

# GitHub Pages 子目录路径

博客目前发布在 “https://nanakidesu.github.io/Bananaki/”,因此本地图片路径需要包含 “/Bananaki/” 前缀:

1
<img src="/Bananaki/images/pixiv/148977449.jpg" alt="作品标题">

如果直接写成 “/images/pixiv/…”,浏览器会从域名根目录寻找图片,部署后就会出现缩略图无法显示的问题。

后续如果博客切换到自定义域名并从域名根目录提供内容,应统一把 Hexo 的 “root” 改为 “/”,同时调整这些写死的 “/Bananaki/” 路径。

# 最终方案的取舍

  • 动态页展示固定的部分推文,不调用 X 私密 API;
  • 受限制的推文只提供合规的外部入口;
  • 画作页展示最近 12 项作品的本地缩略图;
  • 原图、完整信息和互动仍然交给 Pixiv;
  • 使用响应式 CSS 适配桌面端和移动端;
  • 保留 “/Bananaki/” 子目录兼容,并为切换自定义域名留下调整空间。

# 总结

对于部署在 GitHub Pages 上的 Hexo 静态博客,实时调用社交平台接口并不一定是最稳定的方案。平台限流、跨域、登录验证和密钥安全都会增加维护成本。

将少量公开内容保存为静态页面,再把完整内容链接回原平台,虽然需要手动更新,却能获得更可控的加载效果,也不会把敏感凭据暴露到公开仓库。对于个人博客来说,这是当前更加简单、稳定且安全的实现方式。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

米饭バナナキ 微信支付

微信支付

米饭バナナキ 支付宝

支付宝

米饭バナナキ line

line