typecho留言墙开发


摘要由 AI 智能生成

为 Typecho 开发便利贴留言墙

前言

在浏览过一些师傅们的博客,看到一些让人眼前一亮的留言墙。

每一条留言都是一个独立的小故事,我认为都很有意义。于是,NoteWall 插件诞生了。

开发时遇到很多坑,记录适配PJAX和优化交互体验的一些细节。

云烟
现在应该正常了 前两天评论区被广告轰炸 防御策略拉满了
@蒙需: 为什么总是提示评论失败,再试一次。
2026-01-18
云烟
回复
@测试评论者: 测试评论
2026-01-17
测试评论者
测试评论
2026-01-17
蒙需
为什么总是提示评论失败,再试一次。
2026-01-16
云烟
收到啦,感谢博客集团队的用心跟进!问题顺利解决太好了,辛苦各位~ 也祝平台运营越来越顺
@博客集: 今天复盘项目,才发现这么久都没处理...
2025-12-31
博客集
今天复盘项目,才发现这么久都没处理好您的问题,已经把运维祭天了,实在抱歉哈,目前已解决,日常来...
2025-12-31
蒙需
订阅成功
@云烟: 您好 我调整了一下 请尝试使用:h...
2025-12-29
云烟
您好 我调整了一下 请尝试使用:https://www.yunyanck.cn/rss.xml
@蒙需: 如何订阅您的文章,试了 rss 和...
2025-12-29
蒙需
如何订阅您的文章,试了 rss 和 feed 好像都不行
2025-12-29
云烟
原本计划一个人出发的 但是从银川市区到阿拉善盟需要拼车,车上都是志同道合的人便组成了队友
@蒙需: 这类活动队友怎么组成起来的呀 个...
2025-12-26
蒙需
这类活动队友怎么组成起来的呀 个人貌似也不方便行动。
2025-12-26
云烟
全程跟着两步路轨迹走,基本上一路上会有信号,当然一定要组队前往
@小彦: 来看看,沙漠探险有一定风险,要是失...
2025-12-09
小彦
来看看,沙漠探险有一定风险,要是失联了怎么办
2025-12-09
云烟
@格子老师: 干得漂亮,真厉害
2025-12-06
云烟
看着照片 回味曾经去过的地方
@ymz316: 这个的确很有情绪
2025-12-06
ymz316
这个的确很有情绪
2025-12-06
格子老师
干得漂亮,真厉害
2025-12-06
云烟
记录足迹 回忆起来超带感
@Loekman: 不错!对于喜欢旅行的人来说是必备
2025-11-30
云烟
哈哈同为折腾党
@寻鹤: 真好,我刚玩的时候就喜欢折腾这样的...
2025-11-30
寻鹤
真好,我刚玩的时候就喜欢折腾这样的,如今地图插件又多了一个版本
2025-11-30
Loekman
不错!对于喜欢旅行的人来说是必备
2025-11-29
雁心
很好!谢谢作者~~强迫症患者的良药
2025-11-22
云烟
只要分配的id不冲突就不会出现错误
@天天下载ttzip: 删除没用的ID,后面文章递进,会不...
2025-09-11
天天下载ttzip
删除没用的ID,后面文章递进,会不会造成错误
2025-09-10
Daniel
感谢分享
2025-09-07
sanfox
看看
2025-09-06
Echo
1
2025-08-07
XYS
1
2025-04-23
云烟
测试
2025-04-10
个人占星
信仰是一个不可思议的东西
2025-04-06
print
1
2025-04-05
维生素
好啊
2025-03-17
成安
看看
2025-03-06
Deep Router
感谢博主分享,我也自己弄了个docker加速镜像
2025-03-03
1
测试
2025-03-03
云烟
原文https://github.com/guchangan1/All-Defense-Tool
2025-02-20
1
111
2025-02-20
云烟
测试
2025-02-18
云烟
博客整体迁移完成
2025-02-06
您好
感谢分享,谢谢站长
2025-01-02
啊啊
好啊
2024-12-26
云烟
1111
@megaweb9 at: Great goods from ...
2024-11-11
megaweb9 at
Great goods from you, man. I've consider your s...
2024-11-07
试试
看看
2024-11-04
展示酷
学习了!
2024-10-19

查看效果


一、 核心视觉:如何画出一张“便利贴”?

首先是视觉设计。便利贴的灵魂在于“非秩序感”和“纸张质感”。

  1. 随机旋转:现实中的便利贴不可能贴得横平竖直。
  2. 卷角阴影:利用 CSS 的 border-radiusbox-shadow 模拟纸张微微翘起的效果。
  3. 图钉效果:用 CSS 画一个小圆点,配合径向渐变(Radial Gradient)做出金属光泽。

但开发过程中遇到了一个问题:头像变形
很多 Typecho 主题为了响应式,会强制设定 img { width: 100% }。这导致头像被拉伸成了巨大的方块。即使加了 !important 甚至都被主题样式覆盖。

解决方案
我放弃了 <img /> 标签,改用 div 容器配合 background-image。主题的 CSS 只会匹配图片标签,不会影响普通的 div。

/* 核心代码:防拉伸头像容器 */
.note-avatar-bg {
    display: block !important;
    width: 40px !important;    /* 锁死宽度 */
    height: 40px !important;   /* 锁死高度 */
    border-radius: 50% !important;
    /* 关键:使用背景图填充,配合 cover 属性,无论图片比例如何都完美适应 */
    background-size: cover;    
    background-position: center center;
    background-repeat: no-repeat;
    background-color: #e0e0e0;
}

二、 交互体验:赋予便利贴“物理属性”

参考师傅们的留言墙设计了拖拽的效果。

这里没有引入庞大的 jQuery UI 或第三方库,而是用原生 JS 手写了拖拽逻辑。

关键逻辑:

  1. 随机分布:页面加载时,通过 Math.random() 计算每个卡片的 lefttoprotate 角度。
  2. 零延迟拖拽:监听 mousedowntouchstart。为了防止鼠标甩得太快导致“脱手”,移动事件必须绑定在 document 上,而不是元素本身。
// 初始化随机布局片段
for(var i=0; i<notes.length; i++) {
    var n = notes[i];
    // 计算容器内的随机坐标
    var x = Math.random() * (cw - 220);
    var y = Math.random() * (ch - 220);
    // 给它一个 -3度 到 3度 的随机倾斜,看起来更自然
    var r = Math.random() * 6 - 3; 
    
    n.style.left = x + "px";
    n.style.top = y + "px";
    n.style.transform = "rotate(" + r + "deg)";
}

三、 攻克痛点:PJAX 与 QQ 头像

在测试阶段,我遇到了两个 Typecho 插件开发中经典的大坑。

1. PJAX 刷新导致的“堆叠事故”

博客启用了 PJAX 无刷新加载。每次点击页面时,JS 不会重新运行,导致便利贴墙没有进行初始化排版,所有卡片都堆在了左上角 (0,0) 的位置。

解决方法:
引入 MutationObserver 监听器。它就像一个“哨兵”,时刻盯着页面 DOM 的变化。只要发现便利贴墙的容器插入到了页面中,就强制执行排版函数。

// 针对 PJAX 的 MutationObserver 监听
var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        if (mutation.addedNodes.length) {
            var container = document.getElementById("note-wall-container");
            // 只要墙出现了,且还没排版过,立即执行!
            if (container && !container.classList.contains("init-done")) {
                initNoteWall();
            }
        }
    });
});
observer.observe(document.body, { childList: true, subtree: true });

2. QQ 邮箱头像不显示

国内访问 Gravatar 并不稳定,且很多用户只有 QQ 头像。
我在 PHP 中增加了一个正则判断:如果是 QQ 邮箱,直接调用腾讯官方的头像接口;否则使用极客族(Geekzu)的高速 CDN 源。

// PHP 后端判断逻辑
if (strpos($mail, '@qq.com') !== false && preg_match('/^\d+@qq\.com$/', $mail)) {
    $qq = str_replace('@qq.com', '', $mail);
    // 腾讯官方接口,稳!
    $avatarUrl = 'https://q1.qlogo.cn/g?b=qq&nk=' . $qq . '&s=100';
} else {
    // 极客族高速源
    $avatarUrl = 'https://sdn.geekzu.org/avatar/' . md5($mail) . '?s=100&d=mm';
}

四、 逻辑升华:关联评论的“画中画”

最初的版本所有留言都是平级的,看不出谁回复了谁。
为了体现“对话感”,我重写了数据库查询逻辑,使用了 SQL 自连接(Self-Left Join)

在查询每一条评论时,顺便去查询它 parent ID 对应的父级评论内容。如果存在父级评论,就在便利贴下方渲染一个半透明的“引用条”。

// Typecho 数据库查询构造
$select = $db->select('c.*', 'p.author as parentAuthor', 'p.text as parentText')
    ->from('table.comments as c')
    // 左连接:把 table.comments 表连一遍,取名为 p (parent)
    ->join('table.comments as p', 'c.parent = p.coid', Typecho_Db::LEFT_JOIN)
    ->where('c.status = ?', 'approved')
    ->limit($limit);

效果如下图所示,回复的评论会带有一个精致的小尾巴,既不破坏整体美感,又保留了上下文逻辑。
mjwmxzb0.png


从最初简单的 div 堆叠,到解决 CSS 样式冲突,再到适配 PJAX 和 QQ 头像,NoteWall 最终打磨成了一个勉强还能看的 Typecho 插件,后续上传到github开源。

评论区
头像
文章目录