在本站,并不是所有页面都需要全局组件。而有些仅适用于单页的CSS也并不会加入整个网站的全局CSS中。
当然……这些组件对于文章编写与网站运行同样具有重要意义。

所以说……在下面找到自己想使用的组件吧……
别忘了使用以下的代码来将你选择的组件框选上以让其可在页面中以完整的HTML格式正常工作。

!!!
这里是组件代码
!!!

目录

页面内目录

注意:因为该站版式与博客系统的特性,在使用该组件时,请将页面的讨论区关闭。讨论区的标题使用的不是H2。

组件特点

该组件可绕过博客站的pjax设置,避免在删除原页面内容后无法加载目录的情况出现。

有意思的是,本组件的css可以影响博客站版式自带的目录。

组件源代码

<!-- 目录容器 -->
<div class="toc-container">
  <div class="toc-heading">目录</div>
  <div class="toc-list"></div>
</div>

<style>
/* 保持原有容器样式 */
.toc-container {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 1.2rem;
  margin: 1.5rem 0;
  background: #f8f9fa;
}

.toc-heading {
  font-size: 1.25rem;
  font-weight: 600;
  color: #2c3e50;
  margin-bottom: 0.8rem;
  padding-bottom: 0.4rem;
  border-bottom: 2px solid #3498db;
}

/* 调整列表容器 */
.toc-list {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

/* 目录项样式 */
.toc-item {
  line-height: 1.5;
  transition: transform 0.2s ease;
  position: relative;
}

.toc-item:hover {
  transform: translateX(5px);
}

/* 层级缩进 */
.toc-item.h3 { margin-left: 1rem; }
.toc-item.h4 { margin-left: 2rem; }
.toc-item.h5 { margin-left: 3rem; }

/* 链接样式 */
.toc-item a {
  text-decoration: none;
  color: #34495e;
  display: block;
  padding: 0.3rem 0.8rem;
  border-radius: 4px;
  position: relative;
}

.toc-item a:hover {
  color: #2980b9;
  background: #ecf5ff;
}

/* 可选的连接线样式 */
.toc-item::before {
  content: "";
  position: absolute;
  left: -8px;
  top: 50%;
  height: 1px;
  width: 6px;
  background: #3498db;
  transform: translateY(-50%);
  opacity: 0;
  transition: opacity 0.2s;
}

.toc-item:hover::before {
  opacity: 1;
}
</style>

<script>
// 将目录生成逻辑封装成函数
function generateTOC() {
  const tocList = document.querySelector('.toc-list');
  // 清空旧内容
  tocList.innerHTML = '';
  
  // 使用更精确的选择器避免获取到其他区域标题
  const headings = document.querySelectorAll('.post-content h2, .post-content h3, .post-content h4, .post-content h5');

  headings.forEach(heading => {
    // 添加防重复ID生成逻辑
    if (!heading.id) {
      const baseID = heading.textContent
        .toLowerCase()
        .replace(/[^\w\u4e00-\u9fa5]+/g, '-')
        .replace(/^-|-$/g, '');
      
      // 添加唯一性校验
      let uniqueID = baseID;
      let counter = 1;
      while (document.getElementById(uniqueID)) {
        uniqueID = `${baseID}-${counter++}`;
      }
      heading.id = uniqueID;
    }

    // 创建目录项(保持之前的div结构)
    const item = document.createElement('div');
    item.className = `toc-item ${heading.tagName.toLowerCase()}`;
    
    const link = document.createElement('a');
    link.href = `#${heading.id}`;
    link.textContent = heading.textContent;
    
    // 增强的滚动定位逻辑
    link.addEventListener('click', (e) => {
      e.preventDefault();
      const target = document.getElementById(heading.id);
      if (target) {
        const offset = 96; // 根据实际header高度调整
        const topPos = target.getBoundingClientRect().top + window.pageYOffset - offset;
        
        window.scrollTo({
          top: topPos,
          behavior: 'smooth'
        });
        
        // PJAX兼容的hash更新
        history.replaceState({}, '', `#${heading.id}`);
      }
    });

    item.appendChild(link);
    tocList.appendChild(item);
  });
}

// 初始加载
document.addEventListener('DOMContentLoaded', generateTOC);

// PJAX兼容处理
document.addEventListener('pjax:complete', generateTOC); // 通用PJAX事件
document.addEventListener('pjax:success', generateTOC);  // 部分库使用这个事件

// 如果使用WordPress等CMS,可能需要以下适配
document.addEventListener('DOMSubtreeModified', function(e) {
  if (document.querySelector('.pjax-container')) {
    generateTOC();
  }
});
</script>

组件预览

看到页面上的目录了嘛?那个目录用的就是这个组件哦~


计时器组件

<style>
    /* 基础样式 - 同时适用于移动端和桌面端 */
    .countdown-container {
        border: 2px solid #ddd;
        border-radius: 12px;
        padding: 16px;
        margin: 16px auto;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        max-width: 280px;
        width: 90%;
        box-sizing: border-box;
        transition: transform 0.3s ease;
        background-color: white;
    }
    
    .countdown-container:hover {
        transform: translateY(-3px);
        box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
    }
    
    .countdown-title {
        font-size: 16px;
        font-weight: bold;
        margin-bottom: 8px;
        text-align: center;
        color: #333;
    }
    
    .time-display {
        font-size: 20px;
        text-align: center;
        margin: 8px 0;
        font-weight: bold;
        color: #222;
        min-height: 1.2em;
    }
    
    .time {
        font-size: 13px;
        color: #666;
        font-weight: normal;
        padding-top: 6px;
        text-align: center;
    }
    
    /* 正计时特殊样式 */
    .counting-up {
        color: #4CAF50;
    }

    /* 桌面端适配 (宽度大于768px) */
    @media (min-width: 768px) {
        .countdown-container {
            max-width: 320px;
            padding: 20px;
            border-radius: 14px;
            margin: 20px auto;
        }
        
        .countdown-title {
            font-size: 18px;
            margin-bottom: 12px;
        }
        
        .time-display {
            font-size: 24px;
            margin: 12px 0;
        }
        
        .time {
            font-size: 14px;
            padding-top: 8px;
        }
    }

    /* 小尺寸手机适配 (宽度小于400px) */
    @media (max-width: 400px) {
        .countdown-container {
            border-width: 1px;
            padding: 12px;
            border-radius: 10px;
        }
        
        .countdown-title {
            font-size: 15px;
        }
        
        .time-display {
            font-size: 18px;
        }
        
        .time {
            font-size: 12px;
        }
    }
</style>

<script>
// 配置项(支持倒计时和正计时)
const timeConfig = [
    { // 倒计时示例
        id: "time-display1",
        targetTime: new Date("2025-12-15T23:59:59"),
        mode: "countdown" // 倒计时模式
    },
    { // 正计时示例
        id: "time-display2",
        targetTime: new Date("2025-01-01T00:00:00"),
        mode: "countup" // 正计时模式
    }
];

// 时间计算函数
function updateAllTimers() {
    const now = new Date();
    
    timeConfig.forEach(config => {
        const diff = config.targetTime - now;
        const element = document.getElementById(config.id);

        if (config.mode === "countdown") {
            // 倒计时逻辑
            if (diff > 0) {
                const days = Math.floor(diff / (1000 * 60 * 60 * 24));
                const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
                const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
                element.innerHTML = `${days}天${hours}小时${minutes}分`;
            } else {
                element.innerHTML = "已截止";
            }
        } else {
            // 正计时逻辑
            const elapsed = now - config.targetTime;
            if (elapsed > 0) {
                const days = Math.floor(elapsed / (1000 * 60 * 60 * 24));
                const hours = Math.floor((elapsed % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
                const minutes = Math.floor((elapsed % (1000 * 60 * 60)) / (1000 * 60));
                element.innerHTML = `${days}天${hours}小时${minutes}分`;
            } else {
                element.innerHTML = "未开始";
            }
        }
    });
}

// 初始化并每秒更新
function initCountdown() {
    updateAllTimers();
    setInterval(updateAllTimers, 1000);
}

// 普通页面加载初始化
document.addEventListener('DOMContentLoaded', initCountdown);

// PJAX兼容处理
if (typeof jQuery !== 'undefined' && jQuery.pjax) {
    $(document).on('pjax:end', initCountdown);
} else if (typeof pjax !== 'undefined') {
    document.addEventListener('pjax:complete', initCountdown);
}
</script>
<!-- 示例1:项目截止(倒计时) -->
<div class="countdown-container">
    <div class="countdown-title">项目提交截止</div>
    <div id="time-display1" class="time-display"></div>
    <div class="time">截止时间:2025-12-15 23:59</div>
</div>

<!-- 示例2:活动已开始(正计时) -->
<div class="countdown-container">
    <div class="countdown-title">系统运行时间</div>
    <div id="time-display2" class="time-display counting-up"></div>
    <div class="time">开始时间:2025-01-01 00:00</div>
</div>

核心功能

  1. 双模式支持

    • countdown 模式:事件开始前的倒计时(红色/默认色)。
    • countup 模式:事件开始后的正计时(绿色)。
  2. 视觉优化

    • 正计时数字显示为绿色(不过需要你手动添加)。
    • 添加 min-height 防止布局抖动。
    • 移动端适配。
  3. 精度提升

    • 更新时间间隔改为1秒(原为1分钟)。
    • 实时计算天/小时/分钟。
  4. 配置更灵活

    • 每个事件可独立设置模式。
    • 自动识别状态无需手动配置。
  5. 可在使用PJAX的网站上运行。

使用方法

  1. 添加新事件

    {
     id: "显示元素的ID",
     targetTime: new Date("YYYY-MM-DDTHH:mm:ss"), // 目标时间
     mode: "countdown" 或 "countup", // 必填
    }
  2. 样式调整

    • 修改 .counting-up 的 color 属性可改变正计时颜色。
    • 修改 .countdown-container 的 background-color 属性可改变全局倒计时背景颜色。
    • 如果不需要状态标签,可以在HTML容器中删除带有