我是基于Kimi moonshot-v1-8k实现的AI助手,在此博客上负责整理和概括文章

本文详细记录了作者在搭建Hexo博客Butterfly主题时遇到的问题及解决方案。主要内容包括:1. 设置随机主题背景,包括文章封面、小站背景和磁贴封面背景,通过静态和动态JS脚本实现;2. 遇到的问题及解决方法,如自动部署缓存问题、插件bug等;3. 自定义樱花飘落脚本和相册界面魔改,通过注入JS和CSS样式实现。文章还记录了编辑和更新历程,为搭建Hexo博客提供了实用参考。同时,介绍了移动端背景图片显示不全的CSS代码改进、Aplayer播放器的魔改、解决anzhiyu版本的bug、配置music的md文件、调整CSS样式、添加音乐界面标题处理等技术细节。文章还探讨了随机磁贴封面的bug修复、阅读进度按钮问题、夜间模式切换和gulp全局资源压缩等优化措施。最后,文章提到了完善音乐界面和修改bug的过程,包括增加卡片选择主题歌单、解决公式渲染和pdf显示问题,以及修复音乐播放界面的bug。此外,文章还介绍了如何优化看板娘样式的步骤,包括Fork原项目、创建新分支、本地修改代码、更新CDN内容、自定义看板娘样式等,实现了看板娘的个性化设置和功能优化。整体上,本文详细记录了网站优化和bug修复的过程,为搭建Hexo博客提供了宝贵的经验和参考。


编辑记录

2024-10-22 第一次编辑

  • 设置随机背景和一些小坑

2024-10-25 第二次编辑

  • 其他碎碎念

2024-11-16 第三次编辑

  • 完善音乐界面

2024-11-23 第四次编辑

  • 解决一些 bug

2024-12-09 第五次编辑

  • 优化看板娘

  本文章是作为此次开发个人 Hexo 博客过程遇到的坑及其解决方法的总结。

# 怎么设置随机主题背景

# 随机文章封面背景

  随机文章封面的实现使用的是 hexo 后端静态的 js 脚本实现,在 \themes\butterfly\scripts 中新建 random_img.js ,每当重新 hexo 三连时,都会执行这里的 js,不过是静态的,不能动态变化,即不能刷新网页执行。
  该脚本的思路是:通过 hexo.theme.config.xxx 来读取主题配置文件 ( _config.butterfly.yml ) 的对应参数,这里是 mytheme ,读取之后根据是否有值来决定根据日期随机还是选择某个确定主题。
  该脚本不需要 inject 注入,这里设置文章封面本质还是获取了主题配置文件的 cover 参数进行封面设置。

# 随机小站背景

  设置随机背景,使用的是前端能动态刷新的 js 脚本实现,并与后端 js 进行通信传递参数,在 \themes\butterfly\source\js 中新建 randombg.js ,此为前端脚本,负责刷新封面;在 \themes\butterfly\scripts 中新建 setbgtheme.js ,此为后端脚本,负责获取主题配置文件参数,并传递到前端 js。
   setbgtheme.js 的代码如下:
tabs setbgtheme, 2

hexo.extend.filter.register('after_render:html', (str) => {
    const bgtheme = hexo.theme.config.bgtheme;
    return str.replace('</head>', `
        <script>
            window.bgtheme = "${bgtheme}";
        </script>
    </head>`);
});
hexo.extend.filter.register('after_render:html', (str) => {
    const bgtheme = hexo.theme.config.Mytheme;
    return str.replace('</head>', `
        <script>
            window.bgtheme = "${bgtheme}";
        </script>
    </head>`);
});

endtabs
作用是在渲染 html 后,获取主题配置文件的参数 bgtheme ,并通过 window.bgtheme 传递到前端脚本。
   randombg.js 的类似前面随机文章封面,但设置封面是通过 F12 获取网站对应封面元素,再进行设置,但注意,由于设置封面是使用了 url() 的形式,其中的图片链接参数的空格会被忽略,因此要加上空格转换为 %20 的代码 const backgroundUrl = backimg.replace(/ /g, "%20") ,此外,要想获取到封面元素,主题配置文件中的参数 background 必须要设置一个默认封面,网页才能渲染出元素用于脚本获取。(该脚本需要在主题配置文件进行 inject 注入,每次刷新网页都会进行更新)

# 随机磁贴封面背景

  设置随机背景,使用的是前端能动态刷新的 js 脚本实现,并与后端 js 进行通信传递参数,在 \themes\butterfly\source\js 中新建 random_mag_bg.js ,此为前端脚本,负责刷新封面;在 \themes\butterfly\scripts 中新建 setmagtheme.js ,此为后端脚本,负责获取配置文件 ( _config.yml ) 参数,并传递到前端 js。
   setmagtheme.js 的代码如下:
tabs setmagtheme, 2

hexo.extend.filter.register('after_render:html', (str) => {
    const { config } = hexo;
    // 读取选定主题
    const selectedTheme = config.selected_theme; 
   
    return str.replace('</head>', `
        <script>
            window.selectedTheme = "${selectedTheme}";
            console.log("当前mag主题:", window.selectedTheme);
        </script>
    </head>`);
});
hexo.extend.filter.register('after_render:html', (str) => {
    const selectedTheme = hexo.theme.config.Mytheme
    return str.replace('</head>', `
        <script>
            window.selectedTheme = "${selectedTheme}";
            console.log("当前mag主题:", window.selectedTheme);
        </script>
    </head>`);
});

endtabs

由此将配置文件的参数 config.selected_theme 通过 window.selectedTheme 传递到前端 js。
   random_mag_bg.jsrandobg.js 类似,也是获取网页对应部分元素设置背景图片,不过不需要在配置文件先配置 message.cover ,但同样需要在主题配置文件注入。

tip warning faa-horizontal animated-hover 有空时可以将配置文件的三个 theme 合为一个 endtip
note success simple 已成功统一参数为 Mytheme 2024.10.25 endnote

# 一些小坑

# 自动部署遇到问题

  • Github Actions 启动自动部署时,发现当按时间触发时, random_img.js 并没有按日期更换主题,而当 push 触发时,却能切换,查找资料,发现原来是因为时间触发时没有清理图片缓存导致没法更新 ,解决方法就是在图片链接后加 '?v=' + new Date().getTime() ,例如 https://cloudflare-imgbed-9os.pages.dev/file/1729429003335_kon_24.webp?v=1729578064697 这样每次加载图片都会变化,但加上这个字符串并不会影响原来图片的有效性。
  • 在首次进行自动部署时,需要获取追番信息的话,需要在 autodeploy.yml 中加入相应代码:
l
- name: 生成静态文件
      run: |
        hexo bangumi -u #或者hexo bangumi -u 'SESSDATA'
        hexo clean
        hexo generate
  • Github Pages 全自动部署教程

  • 10.25 更新:重新写一个自动部署程序,前面通过在图片后加日期字符串并不起作用,于是采用 hexo deploy 的方式进行部署。步骤如下:

    • 在生成 SSH 密钥时,确保生成 PEM 格式的密钥
    h
    ssh-keygen -t rsa -b 4096 -m PEM -C "your_email@example.com"
    • 将 SSH 公钥添加到 GitHub
      • 打开 GitHub 网站,在你的用户设置中找到 Settings > SSH and GPG keys
      • 点击 New SSH key ,将生成的 id_ed25519.pub(假如是id_ed25519) 文件中的内容复制并粘贴到 GitHub 的 SSH 公钥输入框中。
    • 在 GitHub Actions 中添加 SSH 私钥
      • 进入你的 GitHub 项目页面,点击 Settings > Secrets and variables > Actions
      • 添加一个新的 Secret ,命名为 ACTIONS_DEPLOY_KEY ,并将 id_ed25519 文件的内容复制进去。注意,这里是 SSH 的私钥。
    • 修改 _config.yml 使用 SSH URL
      • 使用 SSH URL 代替 HTTPS,修改 _config.yml 文件的 deploy 配置,如下所示:
        l
        deploy:
          type: git
          repo: git@github.com:ei4869/ei4869.github.io.git
          branch: main
    • 更新 GitHub Actions 工作流以支持 SSH
    l
    name: 自动部署
    on:
      push:
        branches:
          - master
      release:
        types:
          - published
      schedule:
        # 每天的 0 点和 3 点(北京时间)自动部署
        - cron: '0 16 * * *'  # UTC 时间 16 点对应北京时间 0 点.
        - cron: '0 19 * * *'  # UTC 时间 19 点对应北京时间 3 点.
    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
        - name: 检查分支
          uses: actions/checkout@v2
          with:
            ref: master
        - name: 安装 Node
          uses: actions/setup-node@v1
          with:
            node-version: "20.x"
        - name: 设置时区
          run: echo "TZ='Asia/Shanghai'" >> $GITHUB_ENV.
        - name: 安装 Hexo
          run: |
            export TZ='Asia/Shanghai'
            npm install hexo-cli -g
        - name: 缓存 Hexo
          uses: actions/cache@v1
          id: cache
          with:
            path: node_modules
            key: $<!--swig0-->-$<!--swig1-->
        - name: 安装依赖
          if: steps.cache.outputs.cache-hit != 'true'
          run: |
            npm install --save
        - name: 生成静态文件
          run: |
            export TZ='Asia/Shanghai'  # 设置时区
            hexo clean
            hexo generate
            gulp
        - name: 配置 Git 用户信息和分支
          run: |
            git config --global user.name "$"
            git config --global user.email "$"
        - name: 设置 SSH 密钥
          uses: webfactory/ssh-agent@v0.5.3
          with:
            ssh-private-key: $<!--swig4-->
        - name: 部署
          run: |
            hexo deploy

    通过以上,能实现定时自动重启项目,并且随机文章封面能定时更新。

# hexo-butterfly-categories-card 插件 bug

  该插件 bug 显示的分类的名字和描述对应不上,于是暂时没有其他方法,只能不设置 message.descr 参数,即不显示描述。

# 自定义一个樱花飘落脚本

  原脚本樱花是全屏飘落,我在 gallery\index.md 中通过

l
<script async src="https://npm.elemecdn.com/tzy-blog/lib/js/other/sakura.js"></script>

进行注入,但要想部分区域注入樱花特效的话,我新建了 js\sakuraa.js ,通过修改获取的网页的元素可进行指定区域内飘落。

# 相册界面魔改

  本质通过外挂标签设置图库集合,在其 index.md 中添加:

<div class="gallery-group-main">
 galleryGroup name description link img-url 
 galleryGroup name description link img-url 
 galleryGroup name description link img-url 
</div>

但我为了指定单独修改 gallery 的界面,为其添加了指定的类 gallery-page ,如下:(10.25,更好的指定 class 的方法)
tabs gallery-page, 2

<body class="gallery-page">
<div class="gallery-group-main">
 galleryGroup name description link img-url 
 galleryGroup name description link img-url 
 galleryGroup name description link img-url 
</div>
</body>
<body>
    <div class="gallery-group-main">
     galleryGroup name description link img-url 
     galleryGroup name description link img-url 
     galleryGroup name description link img-url 
    </div>
    <script>
    document.addEventListener("DOMContentLoaded", function() {
        document.body.classList.add('gallery-page'); 
    });
    </script>
</body>

endtabs
这样该页面就有了一个独立的指明身份的 class。 span red, (使用 script 脚本注入,动态更改 body 的 class 为指定 class,不会被其他样式改变,保证 class 为想要的 class) 而后续要改动该页面样式,比如去除页面里的文本白框,让放置的图片融于背景,只需调节 css 样式:

/* 特定页面(如 gallery 页面)样式设置 */
.gallery-page{
  background: transparent !important;
}
/* 设置单独相册背景 */
.gallery-page #web_bg {
  background: url(https://cloudflare-imgbed-9os.pages.dev/file/1729429000558_kon_23.webp) !important; 
  background-size: cover !important; 
  background-position: center center !important; 
  background-repeat: no-repeat !important; 
}
.gallery-page .page #page-header {
  background: transparent !important;
}
.gallery-page .page #content-inner #page {
  background: transparent !important;
  border: none !important;      /* 去除边框 */
  backdrop-filter: none !important; 
  box-shadow: none !important;   /* 去除阴影 */
}
.gallery-page .page #footer::before,
.gallery-page .page #page-header::before {
  background: initial !important;
}

之后,要去除子图库的背景白框时,只需要在其 md 文件中,指定 class 为 gallery-page 即可,例如:
tabs gallery-page, 2

<body class="gallery-page">
 gallery 
![](https://cloudflare-imgbed-9os.pages.dev/file/1729306187581_kon_12.webp)
 endgallery 
</body>
<body>
 gallery 
![](https://cloudflare-imgbed-9os.pages.dev/file/1729306187581_kon_12.webp)
 endgallery 
<script>
    document.addEventListener("DOMContentLoaded", function() {
        document.body.classList.add('gallery-page'); // 将类名添加为 music-page
    });
</script>
</body>

endtabs

  还有个小坑,子图库界面一开始加载时,里面的图片会一直抖动,也就是高一直在微微变化,查找资料发现是因为图片样式没有固定,导致为了适应布局图片会自己一直在变,解决方法是在 css 中加入固定样式的代码:

/* 调节相册样式,防止抖动 */
.gallery-items {
  position: relative;
  overflow: hidden; /* 防止内容溢出 */
}
.item {
  position: absolute;
  width: 348px; /* 你可以根据需要调整 */
  height: 205px; /* 确保所有图片区域的大小一致 */
  margin: 0; /* 去掉默认外边距 */
  padding: 0; /* 去掉默认内边距 */
}
.item a {
  display: block;
  width: 100%;
  height: 100%;
}
.item img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* 确保图片保持比例并覆盖整个容器 */
  display: block; /* 去除图片底部的空白空间 */
}
body.gallery-page {
  margin: 0;
  padding: 0;
  overflow-x: hidden; /* 避免水平滚动 */
}

# 移动端背景图片样式改进

  在手机端背景图片会只显示一部分,为了解决这个问题,在 css 中加入代码,使能容纳完整图片,虽然图片不会充满区域,但观感更好吧 (额额,其实 cover 的话也还行吧)。

/* 调节背景图片 */
#web_bg {
  background-size: cover; /* 确保背景图片覆盖整个容器 */
  background-position: center center; /* 将背景图片居中显示 */
  background-repeat: no-repeat; /* 防止背景图片重复 */
  height: 100vh; /* 将背景高度设置为视口高度 */
  width: 100vw; /* 将背景宽度设置为视口宽度 */
  overflow: hidden; /* 确保背景图片不会超出边界 */
}
/* 针对移动端调整 */
@media only screen and (max-width: 768px) {
  #web_bg {
      background-size: contain; /* 确保移动端背景图片按比例缩放 */
  }
}

# Aplayer 播放器

  音乐播放器魔改参考链接:魔改音乐播放器

# Aplayer 播放器魔改 (自改版本)

  为了解决 anzhiyu 版本的 bug,只能自己重写一个界面,不过更简单,但解决了 bug。我的播放器用了官方的播放器样式。

  • 主题配置文件引入 js:
l
bottom:
   - <script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>
  • 配置 music 的 md 文件
n
---
title: 音乐馆
date: 2021-04-24 21:41:30
# type: music
aplayer: true
top_img: false
comments: false
aside: false
---
<body class="music-page">
 meting "9224307215" "tencent" "playlist" "autoplay" "mutex:false" "listmaxheight:440px" "preload:none" "theme:#ad7a86"
<script>
    document.addEventListener("DOMContentLoaded", function() {
        document.body.classList.add('music-page'); // 将类名添加为 music-page
    });
</script>
 <script>
    // 获取 class 为 page 的第一个元素
    const pageElement = document.querySelector('.page');
    if (pageElement) {
        // 查找其子元素中是否有 ID 为 page 的元素
        const childElement = pageElement.querySelector('#page');
        if (childElement) {
                // 修改元素的 ID
            childElement.id = 'music-page';
        }
    }
</script>
<script>
  document.addEventListener("DOMContentLoaded", function() {
    // 获取需要调整的元素
    const contentInner = document.getElementById("content-inner");
    const musicPage = document.getElementById("music-page");
    const pageTitle = musicPage.querySelector(".page-title");
    if (pageTitle) {
      // 在 content-inner 之后插入标题
      contentInner.insertAdjacentElement('beforebegin', pageTitle);
      pageTitle.style.textAlign = 'center';
      pageTitle.style.marginTop = '0px'; // 可以根据需要调整
        }
    });
</script>
<canvas id="universe"></canvas>
<script defer src="/js/universe.js"></script>
</body>

先不管后面的脚本注入,主要是 meting "9224307215" "tencent" "playlist" "autoplay" "mutex:false" "listmaxheight:440px" "preload:none" "theme:#ad7a86" 这里使用 meting 引入播放器, listmaxheight 是歌单列表长度, theme 是歌曲封面背景色 (不是歌单页面背景色)。

  • 配置 music 页面特征 ID:
    首先为了和其他页面区分开来,给界面一个独立的 class 也就是 music-page ,通过脚本注入:
t
<script>
    document.addEventListener("DOMContentLoaded", function() {
        document.body.classList.add('music-page'); // 将类名添加为 music-page
    });
</script>

再给后面的 class:pageid:page 的子元素重命名为 id:music-page

t
<script>
    // 获取 class 为 page 的第一个元素
    const pageElement = document.querySelector('.page');
    if (pageElement) {
        // 查找其子元素中是否有 ID 为 page 的元素
        const childElement = pageElement.querySelector('#page');
        if (childElement) {
                // 修改元素的 ID
            childElement.id = 'music-page';
        }
    }
</script>

这样能方便指定 id 调整 css 样式。

  • 调整 css
    由于 css 代码比较多,所以直接新建一个 mymusic.css ,后续再在主题配置文件注入即可。配置内容为:
s
/* 消除文本框,使用透明背景 */
.page #music-page {
    background: transparent !important; /* 设置背景透明 */
    border: none !important;            /* 去除边框 */
    box-shadow: none !important;       /* 去除阴影 */
  }
  #article-container {
    background-color: rgba(255, 255, 255, 0) !important; /* 透明背景 */
    border: 1px solid rgba(0, 0, 0, 0.1) !important; /* 可选:半透明边框 */
    margin-top: 80px;   /* 调节整个歌单和顶部的距离 */
  }
  /* 调节整个歌单的背景色,这里是淡灰色 */
  .aplayer {
    /* opacity: 0.6; */
    background-color: rgba(235, 224, 224, 0.395) !important;
  }
  
  /* 固定整个页面,禁止垂直滚动,这里 z-index 设为 auto,防止因为 z-index 设置不合适导致进度条和音量按钮 bug*/
  #music-page {
    position: fixed;   /* 使其固定在屏幕上 */
    top: 0;            /* 距离顶部 0 */
    left: 0;           /* 距离左侧 0 */
    width: 100vw;      /* 占满视口的宽度 */
    height: 100vh;     /* 占满视口的高度 */
    overflow: hidden;  /* 禁用内部滚动条 */
    z-index: auto;     /* 确保在其他内容之上 */
    background-color: #ffffff; /* 可选:设置背景颜色 */
  }
  
  /* 隐藏整个页面的水平滚动条 */
  body {
    overflow-x: hidden;
  }
  
  /* 自设 music 页面单独背景,指定为 music-page 里的 web_bg*/
  .music-page #web_bg {
    background: url(https://cloudflare-imgbed-9os.pages.dev/file/1729677618289_8b35b49fcc4e3a1c37c128f8c1eff16b558fb1bb.jpg@1256w_708h_!web-article-pic.webp) !important; 
    background-size: cover !important; 
    background-position: center center !important; 
    background-repeat: no-repeat !important; 
  }
  
  /* 调整歌曲列表,每行的高度和字体大小,行变宽字体变大 */
  .aplayer .aplayer-list ol li{
    line-height: 45px !important;
    font-size: 15px !important;
  }
  
  .aplayer.aplayer-withlrc .aplayer-info {
    padding: 0 7px 0 !important;
    margin-top: 0px;
  }
  
  .page #music-page {
    margin-top: -10px;
  }
  
  /* 加粗歌曲标题作者歌词的文字 */
  .aplayer .aplayer-info .aplayer-music .aplayer-title,
  .aplayer .aplayer-info .aplayer-music .aplayer-author,
  .aplayer .aplayer-lrc p.aplayer-lrc-current {
    font-weight: bold !important; /* 加粗文字 */
    color: #333 !important; 
  }
  /* 加粗歌曲列表的标题作者索引的文字 */
  .aplayer .aplayer-list ol li .aplayer-list-title,
  .aplayer .aplayer-list ol li .aplayer-list-author {
    font-weight: bold !important; /* 加粗文字 */
    color: #333 !important; 
  } 
  .aplayer .aplayer-list ol li .aplayer-list-index {
    font-weight: bold !important; /* 加粗索引 */
    color: #333 !important; 
  }
  
  /* 加深显示播放时间颜色 */
  .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-time-inner{
    font-weight: bold !important; 
    color: #333 !important; 
  }
  
  /* 加深显示图标颜色 */
  .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon svg{
    filter: brightness(0.2) !important; /* 降低填充亮度 */
  }
  .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon svg path{
    stroke: #333 !important;  /* 加深轮廓线条颜色 */
  }
  
  /* 调整歌单列表,每一行的上下边框颜色使其变浅 */
  #article-container .aplayer ol li {
    border: 1px solid rgba(232, 208, 208, 0.5) !important; /* 使用 RGBA 来设置边框颜色,使其变浅 */
    /* 你可以根据需要调整边框宽度和样式 */
  }
  
  /* 调整歌单最左侧指示条的颜色 */
  .aplayer .aplayer-list ol li.aplayer-list-light .aplayer-list-cur {
    background-color: #0a1de9 !important; /* 设置新的背景颜色 */
  }
  
   /* 调整歌单列表当前播放曲目的背景高亮颜色 */
  .aplayer .aplayer-list ol li.aplayer-list-light  {
    background-color: #f2f5ea !important; 
  }
  
  /* 隐藏版权说明 */
  #footer-wrap .copyright{
    display: none !important;
  }
  
  /* 隐藏模型 */
  .music-page #live2d-widget {
    display: none !important;
  }
  
  /* 适用于移动端的媒体查询 */
  @media (max-width: 768px) {
    /* 适配 #music-page */
    #music-page {
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;      /* 占满视口宽度 */
      height: 100vh;     /* 占满视口高度 */
      overflow-y: auto;  /* 启用垂直滚动 */
      background-color: #ffffff; /* 可选:背景颜色 */
      padding: 10px;     /* 为移动端增加内边距 */
    }
  
    /* 适配标题,直接隐藏 */
    .music-page h1 {
      display: none !important;
    }
  
    /* 适配 #article-container */
    #article-container {
      background-color: rgba(255, 255, 255, 0) !important;
      border: 1px solid rgba(0, 0, 0, 0.1) !important;
      margin-top: 60px;
      padding: 10px;         /* 增加内边距,使内容更贴合移动端 */
    }
  
    /* 适配 APlayer 音乐播放器 */
    .aplayer {
      background-color: rgba(235, 224, 224, 0.5) !important; /* 半透明背景 */
      margin-bottom: 20px;
    }
  
    /* 调整播放列表的字体和间距 */
    .aplayer .aplayer-list ol li {
      line-height: 40px !important;  /* 调整行高 */
      font-size: 14px !important;     /* 调整字体大小 */
    }
  
    /* 调整歌词部分 */
    .aplayer .aplayer-info .aplayer-music .aplayer-title,
    .aplayer .aplayer-info .aplayer-music .aplayer-author,
    .aplayer .aplayer-lrc p.aplayer-lrc-current {
      font-size: 14px !important;    /* 调整歌词字体大小 */
      color: #333 !important;        /* 设置字体颜色 */
    }
  
    /* 调整播放时间的显示,更易读 */
    .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-time-inner {
      font-weight: bold !important; 
      color: #333 !important; 
      font-size: 14px !important;  /* 调整字体大小,适合移动设备 */
    }
  
    /* 针对移动端:调节图标填充亮度 */
    .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon svg {
      filter: brightness(0.3) !important; /* 略微减小亮度调节 */
      width: 18px !important;  /* 调整图标大小,适合移动端 */
      height: 18px !important; /* 确保图标在移动端的可点击性 */
    }
  
      /* 针对移动端:加深图标线条颜色 */
      .aplayer .aplayer-info .aplayer-controller .aplayer-time .aplayer-icon svg path {
        stroke: #333 !important;
      }
  
    /* 播放器控制按钮适配 */
    .aplayer .aplayer-info {
      padding: 0 10px !important;     /* 调整内边距 */
      margin-top: 0px;
    }
  
    /* 播放列表项目的边框 */
    #article-container .aplayer ol li {
      border: 1px solid rgba(232, 208, 208, 0.5) !important;
    }
  
    /* 设置播放列表项目的背景颜色 */
    .aplayer .aplayer-list ol li.aplayer-list-light {
      background-color: #f2f5ea !important;
    }
  
    /* 隐藏版权信息 */
    #footer-wrap .copyright {
      display: none !important;
    }
  
    /* 设置控制栏和播放列表之间的空隙 */
    .aplayer .aplayer-info {
      margin-bottom: 10px;
    }
  }

对于音乐界面标题的处理,直接在 md 文件注入 js,动态调整其位置,使其上升到 content-inner 级,居中加粗显示:

t
<script>
  document.addEventListener("DOMContentLoaded", function() {
    // 获取需要调整的元素
    const contentInner = document.getElementById("content-inner");
    const musicPage = document.getElementById("music-page");
    const pageTitle = musicPage.querySelector(".page-title");
    if (pageTitle) {
      // 在 content-inner 之后插入标题
      contentInner.insertAdjacentElement('beforebegin', pageTitle);
      pageTitle.style.textAlign = 'center';
      pageTitle.style.marginTop = '0px'; // 可以根据需要调整
        }
    });
</script>

通过以上,PC 端和移动端的音乐界面都能正常显示,没有 bug 啦!你的名字夜晚飞星的蓝黑天空加上几乎透明浅灰的歌单列表,还是挺适配的。至此,自改的 Aplayer 播放器还算可以。

# 其它碎碎念 (10.25)

# 随机磁贴封面的 bug

  昨天还是会出现偶尔磁贴封面图片为 null 的情况,明明图片链接都有效,明明使用了 IntersectionObserver 懒加载,而且再次刷新页面大概率就又正常了,今天重新改下代码,加入了获取随机图片时如果获取为 null 再次获取的代码,看起来稳定了很多,刷了 n 遍界面都没问题,但不知道还会不会出现,看后续表现吧,贴上改后代码: span red, 10.25 16:34: 呜呜,好像彻底解决了啊,原来是 addEventListener('DOMContentLoaded',); 的问题啊,改用 window.onload 而不是 DOMContentLoaded ,能确保所有资源和元素都已加载。贴上再次改进后的完整代码:

t
'use strict'; 
// 在所有资源加载完成后执行脚本
window.onload = function () {
    // 定义主题图片对象
    const themes = {
        kon: [
            "https://cloudflare-imgbed-9os.pages.dev/file/1729306198549_kon_5.webp",
            "https://cloudflare-imgbed-9os.pages.dev/file/1729306191301_kon_7.webp",
            "https://cloudflare-imgbed-9os.pages.dev/file/1729306191486_kon_6.webp",
            "https://cloudflare-imgbed-9os.pages.dev/file/1729428993734_kon_18.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729428993850_kon_19.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729428996317_kon_20.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429001817_kon_21.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429002735_kon_22.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429000558_kon_23.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429003335_kon_24.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429007799_kon_25.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729428998336_kon_26.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429009566_kon_27.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429003993_kon_28.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429003878_kon_29.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429010529_kon_30.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429007853_kon_31.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429008008_kon_32.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429010316_kon_33.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429013647_kon_15.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429006011_kon_16.webp", 
            "https://cloudflare-imgbed-9os.pages.dev/file/1729429018278_kon_17.webp"
        ],
        sp: [
            "https://cloudflare-imgbed-9os.pages.dev/file/1729306222386_summer pockets_1.webp",
            "https://cloudflare-imgbed-9os.pages.dev/file/1729306218357_summer pockets_12.webp",
            "https://cloudflare-imgbed-9os.pages.dev/file/1729306217685_summer pockets_3.webp"
        ]
        // 可以在此添加更多主题
    };
    // 获取随机图片的函数
    function getRandomCoverImage(theme) {
        const themeImages = themes[theme];
        if (themeImages && themeImages.length > 0) {
            let coverImage = null;
            let attempt = 0;
            const maxAttempts = 10; // 最大尝试次数
            while (!coverImage && attempt < maxAttempts) {
                const randomIndex = Math.floor(Math.random() * themeImages.length);
                coverImage = themeImages[randomIndex];
                attempt++;
                if (!coverImage) {
                    console.warn("获取图片失败,重新尝试...");
                }
            }
            // 如果仍然没有有效图片,返回一个默认图片
            return coverImage || "https://cloudflare-imgbed-9os.pages.dev/file/1729429018278_kon_17.webp";
        } else {
            console.warn("Theme not defined or no images available.");
            return "https://cloudflare-imgbed-9os.pages.dev/file/1729429018278_kon_17.webp"; // 默认图片链接
        }
    }
    // 获取当天的主题
    function getDailyTheme() {
        const today = new Date();
        const dayOfYear = Math.floor((today - new Date(today.getFullYear(), 0, 0)) / 86400000);
        const themeNames = Object.keys(themes);
        const themeIndex = dayOfYear % themeNames.length;
        return themeNames[themeIndex];
    }
    function updateCategoryBarCover() {
        const theme = window.selectedTheme === '' ? getDailyTheme() : window.selectedTheme;
        const categoryItems = document.querySelectorAll('.categoryBar-list-item');
        if (!categoryItems || categoryItems.length === 0) {
            console.warn("未找到任何分类项元素,确保页面结构正确。");
            return;
        }
        console.log("当前磁贴主题:", theme);
        console.log("选中的分类项数量:", categoryItems.length);
    
        // 使用 IntersectionObserver 进行懒加载
        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    const item = entry.target;
                    const coverImage = getRandomCoverImage(theme).replace(/ /g, "%20");
                    if (coverImage) {
                        item.style.backgroundImage = `url(${coverImage})`;
                        item.style.backgroundSize = "cover";
                        item.style.backgroundRepeat = "no-repeat";
                        item.style.backgroundPosition = "center center";
                        console.log("已设置封面图片:", coverImage);
                    } else {
                        console.error("未能获取有效的封面图片");
                    }
                    // 停止观察已加载的元素
                    observer.unobserve(item);
                }
            });
        });
    
        categoryItems.forEach(item => {
            observer.observe(item);
        });
    }
    // 执行更新操作
    updateCategoryBarCover();
};

# 阅读进度按钮问题

参考链接,但实际使用有 bug,目前涉及的需要修改的文件的代码都已更新,解决了 bug。

# 夜间模式切换

参考链接。先按 1.0 操作再到 2.0 替换部分 1.0 内容才能实现。

# gulp 全局资源压缩

参考链接。但注意,要生成 \public 文件夹,需要使用 hexo generate 命令,而不能使用 hexo g ,真是离谱啊。

# 源码连接仓库

  • 创建存放源码的私有仓库
    创建仓库存放源码,设为私密。创建完成后,需要把博客的源码 push 到这里。首先获取远程仓库地址,此处虽然 SSH 和 HTTPS 均可。SSH 在绑定过 ssh key 的设备上无需再输入密码,HTTPS 则需要输入密码。
  • 在 [Blogroot] 路径下 右键->Git Bash Here
    h
    git init # 初始化 git
    这一步会在你的博客目录下新建一个 .git 文件夹。因为是隐藏文件夹,所以需要你先确保当前目录下隐藏文件夹可见才能看到它。
  • 添加屏蔽项
    在远端提交前,我们需要先调整一下屏蔽项,能够使用指令进行安装的内容不包括在需要提交的源码内,这样可以显著减少需要提交的文件量和加快提交速度。打开 [Blogroot]/.gitignore(也是隐藏文件), 输入以下内容:
    t
    .DS_Store
    Thumbs.db
    db.json
    *.log
    node_modules/
    public/
    .deploy*/
    .deploy_git*/
    .idea
    themes/butterfly/.git
    如果不是 butterfly 主题,记得替换最后一行内容为你自己当前使用的主题。
  • 第一次 push 到远程仓库
    右键->Git Bash Here :
    h
    git add . # 添加文件到本地仓库
    git commit -m "自定义内容即可" # 添加文件描述信息
    git remote add origin git@github.com:username/YourRepositoryName.git #链接远程仓库地址,创建主分支
  • 偶尔会遇到一些与远端内容不一致的问题,一般是因为在创建远程仓库时点选了生成 README.md 或者 license 的选项,输入指令:
    h
    # 要是提示 origin 已经存在,那么执行
    git remote rm origin
    # 然后再重新尝试
    git remote add origin git@github.com:username/YourRepositoryName.git
    git pull origin YourBranchName # 把远程仓库的新增的内容覆盖到本地仓库
    git push -u origin YourBranchName -f
    # 把本地仓库的文件推送到远程仓库的主分支,
    #YourBranchName 记得替换成分支名,一般是 master。
    #2020 年 10 月后 github 新建仓库默认分支改为 main
    # -f 是强制提交,主要是因为前后版本不一致造成的。
    # 然后执行以下指令生成网站并部署到 GitHub 上。
    #(Hexo 部署网站是根据_config.yml 内的配置,所以不受影响)
    hexo generate
    hexo deploy
  • 后续更新仓库
    只需要在本地 bash 执行 git 三连即可推送代码改动到仓库,若添加了自动部署,则可自动在推送的同时更新网站。
    h
    git add .
    git commit -m "..."
    git push
    # 将改动推送到 GitHub

# 小知识

  • \public 文件夹是网站展示的内容的文件夹, \source 则是存放数据的文件夹,包括发布的文章,页面的 md 文件等等。而配置网站主题样式之类的一般在 \theme\butterfly 里面操作,可以添加 js、css、img 以及其他比如 pug 等文件吧。
  • 要改变页面的样式,若需要脚本注入,可在 md 文件里用 script 标签进行动态修改,其他简单的不需要用到函数什么的只需要修改样式,可以 F12 查找要修改的网页元素,然后使用 css 进行修改,一般可以用一个通用的 custom.css 在主题配置文件注入即可。
  • \theme\butterfly\script 里的 js 文件是后端文件,是静态的,需要重启项目才能执行,刷新网页并不会执行,不需要注入,会直接调用,也能直接读取配置文件的参数; \theme\butterfly\source\js 里的 js 文件是前端文件,是动态的,会随着网页刷新再次执行,需要在主题配置文件 inject,要获取到配置文件的参数,可以在 \theme\butterfly\script 创建后端文件,通过 window.参数 传递配置文件的参数,前端文件再通过 window.参数 获取到参数。可以利用这一点读取参数进行一些动态刷新操作。
  • 一般本地资源的调用路径都是以 \theme\butterfly\source 为根路径吧,比如注入 js 时路径用 \js\xxx.js 即可,引用图片时用 \img\xxx.jpg 即可。
  • 网页元素,在 css 中,一般是 .class , #id 的方式。要想直接改变目标元素的样式,可以 F12 检查,找到对应元素所在位置,一般双击它在下面栏的样式表会有它和其他元素的依赖关系,直接复制在 css 中使用即可。如图:

示例图片

note info modern 注意:这里使用html语法设置图片时,用的本地图片的话,本地图片需要存到themes/butterfly/source/img里,但是src路径引用的路径需要为/img/xxx.jpg endnote + 为了防止在PC端顶部菜单栏有时会收起而不是展开状态,在主题配置文件使用了脚本注入,保证在PC端保持展开状态。 ``` yml bottom: - ```

# 完善音乐界面 (11.16)

  在音乐界面增加卡片,用于选择对应主题的歌单。具体实现为:

  • 修改 music 文件夹里的 index.md 文件内容,使用外挂标签设置链接卡片,修改后的文件内容为:
n
---
title: 音乐馆
# type: music
aplayer: true
top_img: false
comments: false
aside: false
---
<body>
 sitegroup 
 site KON, url=/music/kon, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1729429000558_kon_23.webp, description=轻音永不毕业! 
 site Summer Pockets, url=/music/sp, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1729919005838_summer pockets_3.webp, description=唯有那份眩目,未曾忘记... 
 site Eva, url=/music/eva, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1729915127264_EVA_5.webp, description=梦是现实的延续,现实是梦的终结。 
 site Ghibli, url=/music/ghibli, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1730449515623_ghibli_22.webp, description=只要有想见的人,自己就不再是孤单一人。 
 site love, url=/music/love, screenshot=https://cloudflare-imgbed-9os.pages.dev/file/1729765205778_1729764735768.webp, description=心灵补给站。 
 endsitegroup 
<script>
    document.addEventListener("DOMContentLoaded", function() {
        document.body.classList.add('musiccard-page'); 
    });
</script>
</body>

其中,为该页面设置了 class 为 "musiccard-page",用于调整该页面的 css 样式。

  • 设置该页面的 css 样式如下:
s
.site-card .img {
  height: 200px !important; /* 设置高度 */
  overflow: hidden !important;
}
.site-card .img img {
  object-fit: cover !important; /* 图片适应容器 */
  width: 100% !important;
  height: 100% !important;
}
.info .title {
  font-size: 1.2rem !important; /* 设置标题字体大小 */
  font-weight: bold !important; /* 加粗标题字体 */
  color: rgb(18, 188, 240) !important; /* 使标题字体颜色更加醒目,采用鲜艳颜色 */
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5) !important; /* 为标题添加阴影效果,增强对比 */
}
.info .desc {
  font-size: 1.2rem !important; /* 设置描述字体大小 */
  font-weight: 500 !important; /* 为描述设置较轻的粗细 */
  color: #fff !important; /* 白色字体 */
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3) !important; /* 轻微阴影增强可读性 */
}
.musiccard-page .page #content-inner #page #article-container {
  border: none !important;  /* 移除边框 */
  box-shadow: none !important;  /* 移除阴影效果 */
}
/* 特定页面(如 gallery 页面)样式设置 */
.musiccard-page{
  background: transparent !important;
}
.musiccard-page #web_bg {
  filter: blur(5px) !important; /* 添加模糊效果,8px 是模糊的强度 */
}
.musiccard-page #web_bg::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.3); /* 调整背景透明度,0.5 为 50% 透明度 */
  z-index: 1; /* 使透明覆盖层位于背景图上方 */
}
.musiccard-page .page #page-header {
  background: transparent !important;
}
.musiccard-page .page #content-inner #page {
  background: transparent !important;
  border: none !important;    /* 去除边框 */
  backdrop-filter: none !important;
  box-shadow: none !important;  /* 去除阴影 */
}
.musiccard-page .page #footer::before,
.musiccard-page .page #page-header::before {
  background: initial !important;
}

主要就是去除背景,使边框透明等,还有就是对背景进行适当模糊和透明度处理,去除页脚等。并对每个卡片图片的大小,以及标题描述的文字进行适当处理,使更加醒目。

  • music 文件夹新建存储主题歌单的 page 界面,这里包括 konsp 等,这些页面里的 index.md 沿用原本音乐界面格式,歌单 id 不同,这样就形成了不同卡片主题有着不同歌单。

# 修改 bug (11.23)

  1. 发现在博客里的公式渲染后出现问题,例如SrCoOxSrCoO_x 的 '_' 会被识别为强调文本的作用,实际应表示下标。查找资料后解决如下:最终还是使用已经安装的 hexo-renderer-kramed ,但需要先执行:
    h
    npm uninstall hexo-renderer-marked
    然后主题配置文件里开启 mathjax 支持,enable 置为 true。之后在 博客目录\node_modules\kramed\lib\rules\inline.js 中做如下变动:
    n
    // em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
    em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
    原先的正则表达式会识别_和 $ 并用于强调文本,修改后_不会被识别,此后 $ $ 的行内表达式正常渲染。
    但要进行自动部署,由于是自动重新安装依赖项,所以需要在自动部署代码加入自动修改 inline.js 内容的脚本。于是在博客根目录创建 fix_kramed.js ,内容为:
    t
    const fs = require('fs');
    const path = require('path');
    const inlineRulesPath = path.join(
        __dirname,
        'node_modules',
        'kramed',
        'lib',
        'rules',
        'inline.js'
    );
    fs.readFile(inlineRulesPath, 'utf8', (err, data) => {
        if (err) {
            console.error('Failed to read inline.js:', err);
            process.exit(1);
        }
        // 原有的 em 规则字符串
        const originalEmRuleStr = "em: /^\\b_((?:__|[\\s\\S])+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/";
        // 新的 em 规则字符串
        const newEmRuleStr = "em: /^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/";
        // 查找原有的 em 规则并替换
        const index = data.indexOf(originalEmRuleStr);
        if (index !== -1) {
            // 替换原有的 em 规则
            const updatedData = data.substring(0, index) + newEmRuleStr + data.substring(index + originalEmRuleStr.length);
            fs.writeFile(inlineRulesPath, updatedData, 'utf8', (err) => {
                if (err) {
                    console.error('Failed to update inline.js:', err);
                    process.exit(1);
                }
                console.log('Successfully updated Kramed rules.');
                console.log('Updated Rule:', newEmRuleStr);
            });
        } else {
            console.log('Original em rule not found.');
        }
    });
    原本采用正则表达式匹配原规则再用新规则替换,但一直匹配不到,最后采用字符串替换的方法成功替换了 em 规则。`autodeploy.yml 增加内容:
    l
    - name: 安装依赖
      if: steps.cache.outputs.cache-hit != 'true'
      run: |
        npm install --save
    - name: 修改 Kramed 规则
      run: node fix_kramed.js
    - name: 生成静态文件
    注意,调试时,可在自动部署代码中加入:
    l
    - name: Debug File Path
      run: ls node_modules/kramed/lib/rules
    - name: Output Kramed Rules for Debugging
      run: cat node_modules/kramed/lib/rules/inline.js
    用于检查 inline.js 路径和文件内容,检查是否成功替换。这些操作后,规则修改,自动部署后也能正常渲染行内公式了。
  2. 文章里 pdf 显示问题解决方法:安装 hexo-pdf :
    h
    npm install --save hexo-pdf
    可以在存放静态资源的 source 文件夹里新建 pdf 文件夹用于存放 pdf 资源,在文章里,要显示 pdf 时,使用命令:
    n
    pdf /pdf/xxx.pdf
    注意文件名不要含特殊字符。
  3. 音乐播放界面的歌单发现 bug,歌单底部歌曲鼠标点击不触发,减小歌单列表长度能解决一点,但后面发现是底部 footer 元素阻挡,原先只是隐藏但仍存在会影响点击,于是使用脚本自动删除 footer 后解决,在每个音乐界面的 md 文件后加入:
    n
    <script>
    document.addEventListener('DOMContentLoaded', () => {
      const footer = document.getElementById('footer');
      if (footer) {
        footer.remove(); // 删除 footer 元素
      }
    });
    </script>
    之后歌单所有歌曲点击正常。

# 优化看板娘 (12.09)

  原来的看板娘不能随时关闭,而且比较单调,于是在这里进行参考,重新设置了看板娘样式。具体步骤为:

  1. Fork 原项目,并在本地 git clone fork 的项目,为了保持代码清晰和便于回退,保留原分支,创建新分支:
    h
    git clone https://github.com/yourusername/repository-name.git
    cd repository-name
    git checkout -b new-branch-name
    new-branch-name 替换为要新建的分支名。
  2. 在本地进行代码修改,然后推送到新分支:
    h
    git add .;git commit -m "update on 24.12.08";git push origin customize
    customize 为示例分支。
  3. 由于仓库的资源使用 jsdelivr CDN 加载,而 jsdelivr 的缓存机制会导致修改的内容无法及时更新,折腾半天,采用不断打新标签的方式更新代码内容。当有新的代码改动提交时,创建新标签并推送,然后只需要更改链接即可。
    h
    git add .;git commit -m "update on 24.12.08";git push origin customize;git tag -a v1.0.6 -m "更新代码";git push origin v1.0.6
    每次修改代码后,使用上述命令推送内容到仓库,并创建新标签和推送内容。
    相应地,修改 autoload.js 的路径链接:
    t
    //live2d_path 参数建议使用绝对路径
    const live2d_path = "https://fastly.jsdelivr.net/gh/ei4869/live2d-widget-fork@v1.0.6/";
    ei4869live2d-widget-fork 分别为用户名和仓库,新的标签 @v1.0.6 能刷新缓存,同步更新 CDN 内容。
    要想删除某个 tag 时,采用以下命令:
    h
    git tag -d v1.0.0;git push origin --delete v1.0.0
    要想删除除了某个 tag (如 v1.0.6) 外的其他 tag 时,采用以下命令:
    h
    git tag | grep -v 'v1.0.6' | xargs git tag -d;
    git ls-remote --tags origin | awk '{print $2}' | grep -v 'v1.0.6' | sed 's|refs/tags/||' | xargs -I {} git push origin --delete {}
  4. 自定义看板娘样式,可以修改 live2d-widget-fork 里的以下内容: waifu.css 用于修改具体网页里呈现的样式,我这里修改了原来的大小 (#live2d),位置 (#waifu),文字框高度 (#waifu-tips) 等,最主要的 autoload.js 用来设置主函数,可以修改里面的代码:
    t
    initWidget({
    		waifuPath: live2d_path + "waifu-tips.json",
    		//apiPath: "https://live2d.fghrsh.net/api/",
    		cdnPath: "https://fastly.jsdelivr.net/gh/fghrsh/live2d_api/",
    		tools: ["hitokoto", "switch-model", "switch-texture", "photo", "quit"]
    	});
    我这里把功能按钮 ( tools ) 减少了两个 (纸飞机游戏和模型信息)。通过修改 apiPathcdnPath 里的资源可以增添喜欢的模型,这里还没深入了解 (这两个只需配置一个即可)。另外 waifu-tips.json 中定义了触发条件(selector,CSS 选择器)和触发时显示的文字(text)可以根据需要修改 (主要就是改变一些动作触发的对话),而 src/waifu-tips.js 包含了按钮和对话框的逻辑,可以根据代码一步步分析进行个性化配置 (还没深入并修改)。目前就只改了 tools 和 css 里的配置。