halo + 得到改造

v1

<div id="audio-player"></div>
<div id="prev"></div>
<div id="next"></div>
<script>
(function() {
  // 获取当前页面 ?p 参数
  const urlParams = new URLSearchParams(window.location.search);
  const p = urlParams.get('p'); // 文章名,如 "category-qowzw0ne-1"
  if (!p) return;
  const splits = p.split("-");
  const seq = parseInt(splits[splits.length - 1], 10); // 序号
  const category = splits.slice(0, splits.length - 1).join("-"); // 分类id
  const baseUrl = window.location.origin;

  // 拉取当前文章详情
  fetch('/apis/api.content.halo.run/v1alpha1/posts/' + p)
    .then(res => res.ok ? res.json() : null)
    .then(data => {
      if (!data) {
        document.getElementById('audio-player').innerHTML = "无法获取文章信息";
        document.getElementById('prev').innerHTML = "";
        document.getElementById('next').innerHTML = "";
        return;
      }
      // 遍历所有系列中文名
      var hasDedao = false;
      if (Array.isArray(data.categories)) {
        for (var i = 0; i < data.categories.length; i++) {
          var displayName = data.categories[i]?.spec?.displayName || "";
          if (displayName.includes("得到")) {
            hasDedao = true;
            break;
          }
        }
      }
      // 如果系列名里没有“得到”,清空所有div
      if (!hasDedao) {
        document.getElementById('audio-player').innerHTML = "";
        document.getElementById('prev').innerHTML = "";
        document.getElementById('next').innerHTML = "";
        return;
      }
      // 音频地址依然用第一个系列名和文章标题
      var seriesCnName = data.categories[0]?.spec?.displayName || "未知系列";
      var articleTitle = data.spec.title || p;

      // 播放器
      var audioUrl = 'https://minio.haoshenqi.top/dedao-mp3/' + encodeURIComponent(seriesCnName) + '/' + encodeURIComponent(articleTitle) + '.mp3';
      document.getElementById('audio-player').innerHTML =
        `<audio controls style="width:100%;">
          <source src="${audioUrl}" type="audio/mpeg">
          您的浏览器不支持 audio 标签。
        </audio>`;

      // 上一篇(获取中文标题)
      if (seq > 0) {
        const prevName = category + '-' + (seq-1);
        fetch('/apis/api.content.halo.run/v1alpha1/posts/' + prevName)
          .then(res => res.ok ? res.json() : null)
          .then(prevData => {
            if (prevData && prevData.spec && prevData.spec.title) {
              document.getElementById('prev').innerHTML =
                `<a href="${baseUrl}/?p=${prevName}">上一篇:${prevData.spec.title}</a>`;
            } else {
              document.getElementById('prev').innerHTML = "没有上一篇了";
            }
          });
      } else {
        document.getElementById('prev').innerHTML = "没有上一篇了";
      }

      // 下一篇(获取中文标题并判断是否存在)
      const nextName = category + '-' + (seq+1);
      fetch('/apis/api.content.halo.run/v1alpha1/posts/' + nextName)
        .then(res => res.ok ? res.json() : null)
        .then(nextData => {
          if (nextData && nextData.spec && nextData.spec.title) {
            document.getElementById("next").innerHTML =
              `<a href="${baseUrl}/?p=${nextName}">下一篇:${nextData.spec.title}</a>`;
          } else {
            document.getElementById("next").innerHTML = "没有下一篇了";
          }
        });
    });

})();
</script>

v2

<div id="audio-player"></div>
<div id="prev"></div>
<div id="next"></div>
<script>
(function() {
  console.log("脚本启动");
  // 获取当前页面 ?p 参数
  const urlParams = new URLSearchParams(window.location.search);
  const p = urlParams.get('p'); // 文章名,如 "category-qowzw0ne-1"
  if (!p) return;
  const splits = p.split("-");
  const seq = parseInt(splits[splits.length - 1], 10); // 序号
  const category = splits.slice(0, splits.length - 1).join("-"); // 分类id
  const baseUrl = window.location.origin;

  // 工具函数: 自动播放标志
  function getAutoPlayFlag(series) {
    let info = localStorage.getItem('haloAutoPlayInfo');
    if (!info) return false;
    try {
      info = JSON.parse(info);
      // 系列必须一致,且未过期
      return info.series === series && Date.now() < info.expire;
    } catch(e) { return false; }
  }
  function setAutoPlayFlag(series) {
    localStorage.setItem('haloAutoPlayInfo', JSON.stringify({
      series: series,
      expire: Date.now() + 30 * 60 * 1000 // 半小时
    }));
  }

  // 拉取当前文章详情
  fetch('/apis/api.content.halo.run/v1alpha1/posts/' + p)
    .then(res => {
      console.log("当前文章详情响应状态:", res.status);
      return res.ok ? res.json() : null;
    })
    .then(data => {
      console.log("当前文章详情数据:", data);
      if (!data) {
        document.getElementById('audio-player').innerHTML = "无法获取文章信息";
        document.getElementById('prev').innerHTML = "";
        document.getElementById('next').innerHTML = "";
        return;
      }

      // 遍历所有系列中文名
      var hasDedao = false;
      if (Array.isArray(data.categories)) {
        for (var i = 0; i < data.categories.length; i++) {
          var displayName = data.categories[i]?.spec?.displayName || "";
          console.log("第",i,"个系列中文名:",displayName);
          if (displayName.includes("得到")) {
            hasDedao = true;
            break;
          }
        }
      }
      console.log("是否有'得到'系列:", hasDedao);
      if (!hasDedao) {
        document.getElementById('audio-player').innerHTML = "";
        document.getElementById('prev').innerHTML = "";
        document.getElementById('next').innerHTML = "";
        return;
      }
      var seriesCnName = data.categories[0]?.spec?.displayName || "未知系列";
      var articleTitle = data.spec.title || p;

      // 先渲染音频播放器和提示区域
      document.getElementById('audio-player').innerHTML =
        `<audio id="myAudio" controls style="width:100%;">
          <source src="https://minio.haoshenqi.top/dedao-mp3/${encodeURIComponent(seriesCnName)}/${encodeURIComponent(articleTitle)}.mp3" type="audio/mpeg">
          您的浏览器不支持 audio 标签。
        </audio>
        <div id="jump-tip" style="display:none; color:#d33; margin:8px 0;"></div>
        <div id="hover-tip" style="display:none; color:#007; margin:8px 0; font-size:0.9em;"></div>`;

      // 上一篇(获取中文标题)
      if (seq > 0) {
        const prevName = category + '-' + (seq-1);
        fetch('/apis/api.content.halo.run/v1alpha1/posts/' + prevName)
          .then(res => res.ok ? res.json() : null)
          .then(prevData => {
            if (prevData && prevData.spec && prevData.spec.title) {
              document.getElementById('prev').innerHTML =
                `<a href="${baseUrl}/?p=${prevName}">上一篇:${prevData.spec.title}</a>`;
            } else {
              document.getElementById('prev').innerHTML = "没有上一篇了";
            }
          });
      } else {
        document.getElementById('prev').innerHTML = "没有上一篇了";
      }

      // 下一篇(获取中文标题并判断是否存在)
      const nextName = category + '-' + (seq+1);
      fetch('/apis/api.content.halo.run/v1alpha1/posts/' + nextName)
        .then(res => res.ok ? res.json() : null)
        .then(nextData => {
          if (nextData && nextData.spec && nextData.spec.title) {
            const nextTitle = nextData.spec.title;
            const nextLink = `${baseUrl}/?p=${nextName}`;
            document.getElementById("next").innerHTML =
              `<a href="${nextLink}">下一篇:${nextTitle}</a>`;
            // 自动跳转功能
            setTimeout(function() {
              const audio = document.getElementById('myAudio');
              if (audio) {
                audio.onended = function() {
                  const tip = document.getElementById('jump-tip');
                  tip.innerText = `即将自动跳转下一篇《${nextTitle}》`;
                  tip.style.display = "block";
                  setAutoPlayFlag(seriesCnName); // 跳转时自动续期
                  setTimeout(function() {
                    window.location.href = nextLink;
                  }, 2000);
                };
                // 监听用户点击播放
                audio.addEventListener("play", function() {
                  setAutoPlayFlag(seriesCnName);
                  console.log("记录用户点击播放,系列:", seriesCnName);
                });
                // 悬停提示
                audio.addEventListener("mouseover", function() {
                  const hoverTip = document.getElementById('hover-tip');
                  hoverTip.innerText = "会自动播放整个系列";
                  hoverTip.style.display = "block";
                });
                audio.addEventListener("mouseout", function() {
                  const hoverTip = document.getElementById('hover-tip');
                  hoverTip.style.display = "none";
                });
                // 跳转后自动播放(如果有flag且未失效)
                if (getAutoPlayFlag(seriesCnName)) {
                  console.log("检测到自动播放标志,自动播放音频");
                  audio.play();
                } else {
                  console.log("没有自动播放标志,不自动播放");
                }
              }
            }, 100); // 100ms确保audio已渲染
          } else {
            document.getElementById("next").innerHTML = "没有下一篇了";
            setTimeout(function() {
              const audio = document.getElementById('myAudio');
              if (audio) {
                audio.onended = null;
                audio.addEventListener("mouseover", function() {
                  document.getElementById('hover-tip').innerText = "会自动播放整个系列";
                  document.getElementById('hover-tip').style.display = "block";
                });
                audio.addEventListener("mouseout", function() {
                  document.getElementById('hover-tip').style.display = "none";
                });
                audio.addEventListener("play", function() {
                  setAutoPlayFlag(seriesCnName);
                  console.log("记录用户点击播放,系列:", seriesCnName);
                });
                if (getAutoPlayFlag(seriesCnName)) {
                  console.log("检测到自动播放标志,自动播放音频");
                  audio.play();
                } else {
                  console.log("没有自动播放标志,不自动播放");
                }
              }
            }, 100);
          }
        });
    });

})();
</script>