新增「最近评论」挂件:主题自建(替代 Comments Widget Plus 插件) #22

Closed
opened 2026-10-26 23:35:22 +00:00 by laoyang · 2 comments
Owner

来源

用户 2026-10-27 提出:

现在我们来增加一个小挂件,就是显示最近评论的小挂件。主题里面原来 WordPress 自己原来就有一个的,但是那个实在是太丑了,所以我安装了一个插件。评论小工具加。但我感觉这应该是我们主题做的事。所以你就参考这个插件,然后做出一个漂亮的最近评论的小插件。

现状盘点(已核对线上 yangyq.net,WP 7.1.3)

一、主题已经注销了 WP 原生的最近评论挂件

inc/theme-widgets.php 第 21–34 行的 widgets_init() 里:

$wp_widget = array(
    'WP_Widget_Pages',
    'WP_Widget_Meta',
    'WP_Widget_Recent_Posts',
    'WP_Widget_Recent_Comments',   // ← 就是它
    'WP_Widget_RSS',
    'WP_Widget_Search',
    'WP_Widget_Tag_Cloud',
    'WP_Nav_Menu_Widget',
);
foreach ($wp_widget as $wp_widget) {
    unregister_widget($wp_widget);
}

所以后台根本看不到原生那个。这是 3.2.x 之前就有的决定(原生样式是裸 <ul><li>,跟主题完全不搭)。

二、当前用的是插件 comments-widget-plus 1.3

  • 路径 wp-content/plugins/comments-widget-plus/,实际代码 560 行(PHP 535 + CSS 25)
  • 侧栏顺序实测:["about-3","search-3","posts-2","cwp-widget-3","categories-3","media_image-2"]
  • 实例 cwp-widget-3 的配置:avatar: false、excerpt: true、excerpt_limit: 35、limit: 10、order: DESC、exclude_pings: true
  • 渲染尺寸实测:397 × 992(占满整个侧栏高度,10 条评论)

三、它「丑」的三个具体原因(都有实测依据)

① 中文语序是断裂的。 插件用一条 _x() 拼句子:

_x( '%1$s %2$son%3$s %4$s', 'widgets', 'comments-widget-plus' )
//  作者      "on"      文章标题

英文读起来是「作者 on 文章标题」,翻成中文就成了:

「同步日历-我的第一款鸿蒙应用(鸿蒙CalDav客户端)上的 老杨」

—— 而插件根本没带 zh_CN 语言包(languages/ 目录下只有一个 .pot),这句是主题的翻译域在兜底,语序错位。

② 一条评论占 96px 高、混了 4 个信息层级全平铺。 实测每条 <li>:

元素 字号 颜色
文章标题链接 16px #00a2ff
作者 16px #333
评论摘要 16px #787878

三层同为 16px,只能靠颜色区分。而「文章标题」是最长的(实测首条宽 332px、折成 2 行 50px),把真正的评论内容挤到最下面。

③ 没有头像。 实例里 avatar: false(插件默认也是 false),纯文字流,视觉上没有任何抓手。

四、插件的功能清单(本次要对齐的能力)

来自 readme.txt 与 form():

  • 标题 + 标题链接 URL
  • 每页条数 limit、跳过 offset
  • 排序 DESC / ASC
  • 限定文章类型 post_type
  • 排除 pingback / trackback
  • 显示头像 + 头像尺寸 + 头像形状(圆角/方形)
  • 显示评论摘要 + 摘要长度
  • 自定义 CSS class

需求

一、在主题里新建 widget_recent_comments 挂件(w-comments)

名字要避开 WP 保留的 widget_recent_comments id_base —— 那个已被 unregister_widget 注销,但 id_base 冲突会让老数据复活。用 yang_recent_comments 作 id_base,CSS 类 w-comments,与现有 w-about / w-tags / w-search / w-ad / w-posts / w-recommended 保持一致。

二、视觉设计(这次的重点)

不是"把插件照抄一遍再加点 CSS",要按侧栏的视觉层级重做:

  1. 头像必须有:圆形、固定尺寸(默认 40px),object-fit:cover 防变形,配 flex 布局而不是 float(插件的 float:left 在长文本下会出现文字环绕错位)。
  2. 信息层级要分明:评论内容为主体(15px / #5a5a5a),作者(14px / 主色 #00a2ff)、文章标题(13px / 灰 #999,单行省略)作为元信息放在下方一行。
  3. 中文语序:「作者 在《文章标题》中评论」→ 实际输出拆成两行,元信息行是「作者 · 文章标题」,不在句子里塞 on。
  4. 相对时间:human_time_diff(),比绝对日期更适合侧栏。
  5. 条与条之间用细分隔线,last-child 去掉,跟 .w-recommended .bookmark-item 的做法一致。
  6. 整体高度要可控:默认 5 条,不再默认 10 条占满 992px。

三、可配置项(照插件的功能对齐,但收敛到够用的范围)

  • 标题(走 yang_widget_title(),与其它挂件一致)
  • 显示条数(默认 5,1–20)
  • 是否显示头像 + 头像尺寸(默认 40)
  • 是否显示评论摘要 + 摘要字数(默认 40)
  • 排序(最新优先 / 最早优先)
  • 排除 pingback / trackback(默认开)
  • 限定文章类型(默认 post)

四、CSS 规则不依赖祖先(写入本版硬约束)

3.2.51 刚踩过的坑:.k-main .sidebar .w-about .wrapper img 这种三段祖先选择器,在后台「外观→小工具」预览里一条都不生效。新挂件的规则只依赖 .w-comments 自身。

五、性能

  • 用 WP_Comment_Query 一次取回,不逐条 get_comment()。
  • 头像走 get_avatar()(WP 自带缓存与 pre_get_avatar 过滤)。
  • 不做额外缓存层 —— 侧栏每次请求查一次评论表,wp_comments 上有 comment_approved_date_gmt 索引,10 条的开销可忽略。插件的 wp_cache_get/set('cwp_widget','widget') + 三个 add_action 清缓存是过度设计,且它的缓存键是全局的(多个实例会互相污染)。

验收标准

  1. 后台「外观 → 小工具」出现「最近评论」挂件,表单 7 项可配。
  2. 前台侧栏渲染:头像圆形 40px、内容/作者/文章标题三层清晰、条间有分隔线、末条无分隔线。
  3. 中文语序正确,不出现英文 on 的直译痕迹。
  4. 后台预览环境与前台渲染尺寸一致(选择器不依赖祖先)。
  5. 长评论不会撑破布局:摘要按字数截断 + overflow-wrap:break-word。
  6. 无评论时不输出空壳挂件(不显示标题 + 空 <ul>)。
  7. 用户手动把侧栏挂件从插件换成主题版后,撤销插件安装不影响其他功能。

不在本次范围

  • 不改现有 widget_about / widget_ad / widget_tags / widget_search / widget_posts。
  • 不自动迁移插件的实例数据(两者 id_base 不同,需要用户手动在侧栏里换挂件;我会在 readme 里写清楚换法)。
  • 不接管插件的后台设置页(插件没有设置页,全在挂件表单里)。

为什么单独建单

是新增一个此前主题里不存在的小工具(最近评论 w-comments),不是 #20 挂件一致性、#21 个人简介、#19 热点条数里任何一张的补充;可以单独验收、单独发版。

## 来源 用户 2026-10-27 提出: > 现在我们来增加一个小挂件,就是显示最近评论的小挂件。主题里面原来 WordPress 自己原来就有一个的,但是那个实在是太丑了,所以我安装了一个插件。评论小工具加。但我感觉这应该是我们主题做的事。所以你就参考这个插件,然后做出一个漂亮的最近评论的小插件。 ## 现状盘点(已核对线上 `yangyq.net`,WP 7.1.3) ### 一、主题**已经注销**了 WP 原生的最近评论挂件 `inc/theme-widgets.php` 第 21–34 行的 `widgets_init()` 里: ```php $wp_widget = array( 'WP_Widget_Pages', 'WP_Widget_Meta', 'WP_Widget_Recent_Posts', 'WP_Widget_Recent_Comments', // ← 就是它 'WP_Widget_RSS', 'WP_Widget_Search', 'WP_Widget_Tag_Cloud', 'WP_Nav_Menu_Widget', ); foreach ($wp_widget as $wp_widget) { unregister_widget($wp_widget); } ``` 所以后台根本看不到原生那个。这是 3.2.x 之前就有的决定(原生样式是裸 `<ul><li>`,跟主题完全不搭)。 ### 二、当前用的是插件 `comments-widget-plus` 1.3 - 路径 `wp-content/plugins/comments-widget-plus/`,实际代码 560 行(PHP 535 + CSS 25) - 侧栏顺序实测:`["about-3","search-3","posts-2","cwp-widget-3","categories-3","media_image-2"]` - 实例 `cwp-widget-3` 的配置:`avatar: false`、`excerpt: true`、`excerpt_limit: 35`、`limit: 10`、`order: DESC`、`exclude_pings: true` - 渲染尺寸实测:**397 × 992**(占满整个侧栏高度,10 条评论) ### 三、它「丑」的三个具体原因(都有实测依据) **① 中文语序是断裂的。** 插件用一条 `_x()` 拼句子: ```php _x( '%1$s %2$son%3$s %4$s', 'widgets', 'comments-widget-plus' ) // 作者 "on" 文章标题 ``` 英文读起来是「作者 on 文章标题」,翻成中文就成了: > 「同步日历-我的第一款鸿蒙应用(鸿蒙CalDav客户端)**上的** 老杨」 —— 而插件**根本没带 zh_CN 语言包**(`languages/` 目录下只有一个 `.pot`),这句是主题的翻译域在兜底,语序错位。 **② 一条评论占 96px 高、混了 4 个信息层级全平铺。** 实测每条 `<li>`: | 元素 | 字号 | 颜色 | |---|---|---| | 文章标题链接 | 16px | `#00a2ff` | | 作者 | 16px | `#333` | | 评论摘要 | 16px | `#787878` | 三层**同为 16px**,只能靠颜色区分。而「文章标题」是最长的(实测首条宽 332px、折成 2 行 50px),把真正的评论内容挤到最下面。 **③ 没有头像。** 实例里 `avatar: false`(插件默认也是 false),纯文字流,视觉上没有任何抓手。 ### 四、插件的功能清单(本次要对齐的能力) 来自 `readme.txt` 与 `form()`: - 标题 + 标题链接 URL - 每页条数 `limit`、跳过 `offset` - 排序 `DESC` / `ASC` - 限定文章类型 `post_type` - 排除 pingback / trackback - 显示头像 + 头像尺寸 + 头像形状(圆角/方形) - 显示评论摘要 + 摘要长度 - 自定义 CSS class ## 需求 ### 一、在主题里新建 `widget_recent_comments` 挂件(`w-comments`) 名字要避开 WP 保留的 `widget_recent_comments` id_base —— 那个已被 `unregister_widget` 注销,但 id_base 冲突会让老数据复活。用 `yang_recent_comments` 作 id_base,CSS 类 `w-comments`,与现有 `w-about / w-tags / w-search / w-ad / w-posts / w-recommended` 保持一致。 ### 二、视觉设计(这次的重点) 不是"把插件照抄一遍再加点 CSS",要按侧栏的视觉层级重做: 1. **头像必须有**:圆形、固定尺寸(默认 40px),`object-fit:cover` 防变形,配 `flex` 布局而不是 `float`(插件的 `float:left` 在长文本下会出现文字环绕错位)。 2. **信息层级要分明**:评论内容为主体(15px / `#5a5a5a`),作者(14px / 主色 `#00a2ff`)、文章标题(13px / 灰 `#999`,单行省略)作为元信息**放在下方一行**。 3. **中文语序**:「作者 在《文章标题》中评论」→ 实际输出拆成两行,元信息行是「作者 · 文章标题」,不在句子里塞 `on`。 4. **相对时间**:`human_time_diff()`,比绝对日期更适合侧栏。 5. **条与条之间用细分隔线**,`last-child` 去掉,跟 `.w-recommended .bookmark-item` 的做法一致。 6. **整体高度要可控**:默认 5 条,不再默认 10 条占满 992px。 ### 三、可配置项(照插件的功能对齐,但收敛到够用的范围) - 标题(走 `yang_widget_title()`,与其它挂件一致) - 显示条数(默认 5,1–20) - 是否显示头像 + 头像尺寸(默认 40) - 是否显示评论摘要 + 摘要字数(默认 40) - 排序(最新优先 / 最早优先) - 排除 pingback / trackback(默认开) - 限定文章类型(默认 `post`) ### 四、CSS 规则**不依赖祖先**(写入本版硬约束) 3.2.51 刚踩过的坑:`.k-main .sidebar .w-about .wrapper img` 这种三段祖先选择器,在后台「外观→小工具」预览里一条都不生效。新挂件的规则**只依赖 `.w-comments` 自身**。 ### 五、性能 - 用 `WP_Comment_Query` 一次取回,不逐条 `get_comment()`。 - 头像走 `get_avatar()`(WP 自带缓存与 `pre_get_avatar` 过滤)。 - 不做额外缓存层 —— 侧栏每次请求查一次评论表,`wp_comments` 上有 `comment_approved_date_gmt` 索引,10 条的开销可忽略。插件的 `wp_cache_get/set('cwp_widget','widget')` + 三个 `add_action` 清缓存是过度设计,且它的缓存键是全局的(多个实例会互相污染)。 ## 验收标准 1. 后台「外观 → 小工具」出现「最近评论」挂件,表单 7 项可配。 2. 前台侧栏渲染:头像圆形 40px、内容/作者/文章标题三层清晰、条间有分隔线、末条无分隔线。 3. **中文语序正确**,不出现英文 `on` 的直译痕迹。 4. 后台预览环境与前台**渲染尺寸一致**(选择器不依赖祖先)。 5. 长评论不会撑破布局:摘要按字数截断 + `overflow-wrap:break-word`。 6. 无评论时**不输出空壳挂件**(不显示标题 + 空 `<ul>`)。 7. 用户手动把侧栏挂件从插件换成主题版后,**撤销插件安装**不影响其他功能。 ## 不在本次范围 - 不改现有 `widget_about / widget_ad / widget_tags / widget_search / widget_posts`。 - 不自动迁移插件的实例数据(两者 id_base 不同,需要用户手动在侧栏里换挂件;我会在 readme 里写清楚换法)。 - 不接管插件的后台设置页(插件没有设置页,全在挂件表单里)。 --- ### 为什么单独建单 是新增一个此前主题里不存在的小工具(最近评论 w-comments),不是 #20 挂件一致性、#21 个人简介、#19 热点条数里任何一张的补充;可以单独验收、单独发版。
Author
Owner

3.2.52 已发布到更新通道

update.json 版本号已改为 3.2.52,readme.html 首行是 V3.2.52。
服务器主题目录仍是 3.2.51,未被覆盖 —— 需要你在 WP 后台「外观 → 主题」点升级。

提交:baa1d16


做了什么

主题新增 widget_recent_comments(id_base = yang_recent_comments),外观参照 ThemeZee 的 Comments Widget Plus,但只依到 .w-comments 自身写样式。

前端长什么样

  • 头像 40px 圆形(object-fit:cover,配 max-width/max-height 双保险,大图不会撑爆)
  • 摘要按字符截断(mb_substr),不用 wp_html_excerpt(那个按字节切,中文会切出半个字)
  • 元信息三段各自成 span:作者 · 相对时间 · 文章标题,不拼成 "作者在《文章》中评论" 这种句式(i18n 时语序会错位)
  • 三层字号:摘要 15px / 作者 14px / 文章 13px
  • 条间虚线,最后一条去掉分隔线

后台九项设置:标题、条数、显示头像、头像尺寸、显示摘要、摘要字数、排除 pingback、评论类型、文章类型

从插件版换过来要手动做一步:外观 → 小工具,把旧的插件版「最近评论」删掉,再拖入新版「最近评论」。两者 id_base 不同,不会互相覆盖,同时挂着会重复显示。


顺手修掉的一个真 bug

form() 里 post_type 原来走 pick(),而 pick() 把空串当"没填"、回落 'post'。

后果:老实例(存的是空串,表示「全部类型」)在后台下拉框显示「文章」,前台却按「全部类型」渲染。用户看到的是"我设置了只看文章,怎么页面评论还出别的",无从解释。

改成 widget() 和 form() 都直接读原值,两处都把空串 / any 认作「全部类型」。这个 bug 是本地预演抓出来的 —— 只测 widget() 一侧,前后台一致性永远成立。


验证

套件 结果
行为测试 _comments_test.php 112 / 0
行为反证 _comments_falsify.php PHP 25/25 + CSS 10/10 全真红
几何回归 _comments_geom.js 50 / 0
线上真实页面 _comments_live_geom.js 30 / 0
静态反证 _comments_live_falsify.js 23 / 0
发布脚本在服务器 22 组反证全真红,PHP/CSS 判据 0 失败

反证这一版特意重写过架构:正本和"被改坏的副本"走同一套判据函数,比对失败条数增量。老写法另写一遍 grep 只证明了"注入改了字节",没证明判据有牙齿 —— 判据根本没被执行。

顺带在这轮抓掉 4 类判据缺陷(都会导致假绿或恒红):

  1. .yang-comment-text 是 CSS 选择器写法,PHP 源码里是 class="...",在正确代码上恒红
  2. 按行 grep 漏掉跨行的 echo(esc_html 在下一行)
  3. CSS 选择器从 .w-comments 起匹,祖先那截天然落在匹配范围外
  4. 用「总条数 ≥ N」当前置 —— 删掉 1 条还剩 14 条

等你确认

升级后请在侧栏实际看一下这三件事:

  1. 头像圆不圆、有没有被大图撑变形
  2. 长评论 / 长文章标题会不会撑破侧栏
  3. 中文摘要有没有被切出半个字

确认没问题我再关这张单。

## 3.2.52 已发布到更新通道 `update.json` 版本号已改为 **3.2.52**,`readme.html` 首行是 V3.2.52。 **服务器主题目录仍是 3.2.51,未被覆盖** —— 需要你在 WP 后台「外观 → 主题」点升级。 提交:`baa1d16` --- ### 做了什么 主题新增 `widget_recent_comments`(`id_base = yang_recent_comments`),外观参照 ThemeZee 的 Comments Widget Plus,但只依到 `.w-comments` 自身写样式。 **前端长什么样** - 头像 40px 圆形(`object-fit:cover`,配 `max-width`/`max-height` 双保险,大图不会撑爆) - 摘要按**字符**截断(`mb_substr`),不用 `wp_html_excerpt`(那个按字节切,中文会切出半个字) - 元信息三段各自成 `span`:作者 · 相对时间 · 文章标题,不拼成 "作者在《文章》中评论" 这种句式(i18n 时语序会错位) - 三层字号:摘要 15px / 作者 14px / 文章 13px - 条间虚线,最后一条去掉分隔线 **后台九项设置**:标题、条数、显示头像、头像尺寸、显示摘要、摘要字数、排除 pingback、评论类型、文章类型 **从插件版换过来要手动做一步**:外观 → 小工具,把旧的插件版「最近评论」删掉,再拖入新版「最近评论」。两者 `id_base` 不同,不会互相覆盖,同时挂着会重复显示。 --- ### 顺手修掉的一个真 bug `form()` 里 `post_type` 原来走 `pick()`,而 `pick()` 把空串当"没填"、回落 `'post'`。 后果:老实例(存的是空串,表示「全部类型」)在**后台下拉框显示「文章」,前台却按「全部类型」渲染**。用户看到的是"我设置了只看文章,怎么页面评论还出别的",无从解释。 改成 `widget()` 和 `form()` 都直接读原值,两处都把空串 / `any` 认作「全部类型」。这个 bug 是本地预演抓出来的 —— 只测 `widget()` 一侧,前后台一致性永远成立。 --- ### 验证 | 套件 | 结果 | |---|---| | 行为测试 `_comments_test.php` | 112 / 0 | | 行为反证 `_comments_falsify.php` | PHP 25/25 + CSS 10/10 全真红 | | 几何回归 `_comments_geom.js` | 50 / 0 | | 线上真实页面 `_comments_live_geom.js` | 30 / 0 | | 静态反证 `_comments_live_falsify.js` | 23 / 0 | | 发布脚本在服务器 | 22 组反证全真红,PHP/CSS 判据 0 失败 | 反证这一版特意重写过架构:**正本和"被改坏的副本"走同一套判据函数,比对失败条数增量**。老写法另写一遍 grep 只证明了"注入改了字节",没证明判据有牙齿 —— 判据根本没被执行。 顺带在这轮抓掉 4 类判据缺陷(都会导致假绿或恒红): 1. `.yang-comment-text` 是 CSS 选择器写法,PHP 源码里是 `class="..."`,**在正确代码上恒红** 2. 按行 grep 漏掉跨行的 `echo`(`esc_html` 在下一行) 3. CSS 选择器从 `.w-comments` 起匹,祖先那截天然落在匹配范围外 4. 用「总条数 ≥ N」当前置 —— 删掉 1 条还剩 14 条 --- ### 等你确认 升级后请在侧栏实际看一下这三件事: 1. 头像圆不圆、有没有被大图撑变形 2. 长评论 / 长文章标题会不会撑破侧栏 3. 中文摘要有没有被切出半个字 确认没问题我再关这张单。
Author
Owner

按用户确认收尾,交付见上条发布评论。

交付版本:3.2.52(主题自建「最近评论」挂件,替代 Comments Widget Plus)

用户已验收,关闭本单。

按用户确认收尾,交付见上条发布评论。 交付版本:3.2.52(主题自建「最近评论」挂件,替代 Comments Widget Plus) 用户已验收,关闭本单。
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/wordpress-kratos-yang#22