
简介这是一款面向Discuz论坛站长的商业插件正式版专门解决隐藏内容回复审核失效的问题。Discuz默认情况下即使会员回复未通过审核、回复被删除或帖子进入回收站仍能查看隐藏内容导致大量无意义灌水回复。该插件通过权限校验确保只有审核通过的回复才能解锁隐藏内容从而提升回帖质量与社区秩序。插件支持手机版与PC版可按用户组和版块灵活开启并兼容主流浏览器。资源包共8个文件包含4个XML配置文件与4个PHP程序文件XML用于多编码语言包与插件配置PHP负责核心逻辑与钩子处理压缩包仅12KB轻量易部署。目前已有167人浏览学习适合需要优化论坛内容管理、抑制垃圾回复的站长直接安装使用安装后即可获得更清洁有序的社区互动环境。1. 隐藏内容回复增强插件到底改了什么从「回复可见」到「回复后精准可见」做 Discuz 论坛运营的人多半遇到过这个场景帖子里埋了下载地址、提取码、附件用[hide]标签一包用户必须回复才能看到。原生的逻辑很粗暴——只要回复了整段隐藏内容就全部放出来。于是灌水回复满天飞「1111」「看看」「感谢分享」刷屏真正有价值的讨论被淹没。更麻烦的是你没法控制「回复后看到多少」——要么全给要么全不给。这个「隐藏内容回复增强」插件要解决的就是这个断层。它把原生[hide]的单一开关拆成了可配置的可见策略回复后显示部分内容、达到一定积分才显示、指定用户组直接可见、甚至按回复字数决定解锁程度。对运营者来说这是把「回复可见」从一刀切变成可调档位的工具对开发者来说这是一次典型的 Discuz 插件钩子hook改造实战。下面按「它改了什么 → 怎么装怎么配 → 代码层怎么接 → 坑在哪」的顺序讲透新手能照着复现熟手能看清边界。2. 先搞懂 Discuz 的 hide 标签解析链路插件到底挂在哪一环2.1 原生[hide]从发帖到渲染走了哪几步要改隐藏内容逻辑得先知道 Discuz 在哪个环节处理[hide]。以常见的 Discuz X3.4/X3.5 为例帖子内容从数据库取出到最终 HTML 输出大致经过这几步发帖时[hide]作为普通 BBCode 原样存入pre_forum_post表的message字段不做特殊处理。读帖时forum_viewthread.php调用discuzcode()函数定义在source/function/function_discuzcode.php解析 BBCode。discuzcode()内部对[hide]的处理会检查当前用户是否已回复该帖、是否有管理权限然后决定输出真实内容还是提示文字。判断「是否已回复」依赖pre_forum_post里该用户在本帖的回复记录通常是一次查询或缓存命中。关键点在于原生逻辑把「是否回复」当成唯一的布尔开关。插件要做的增强本质是在第 3 步插入自己的判断分支——在「已回复」和「未回复」之间插入更多中间状态。2.2 插件用 hook 还是改源码两种接入方式的取舍Discuz 插件体系提供两类接入点一是plugin/目录下的独立插件通过hook脚本挂载二是直接改function_discuzcode.php等核心文件。这个增强插件属于前者走的是标准插件路线。为什么优先选 hook 而不是改源码三个现实理由升级不丢改动Discuz 核心文件在版本升级时会被覆盖直接改源码意味着每次升级都要重新打补丁血泪经验是改了三处忘了第四处线上直接白屏。可开关插件在后台可以一键启用/禁用出问题能快速回退改源码没有后悔药。多插件共存hook 机制按优先级排队多个插件改同一处时冲突可控改源码是硬覆盖谁后改谁生效。代价是 hook 能拿到的上下文有限某些深层变量需要靠全局变量或重新查询补齐。这个插件在实现「按积分解锁」时就需要额外查一次用户积分属于可接受的成本。2.3 增强逻辑的三个判断维度把原生的一维判断扩展成多维这个插件实际用了三个维度维度原生行为增强后行为数据来源回复状态回复全可见回复按配置显示比例pre_forum_post回复记录用户积分不判断积分达标才解锁pre_common_member积分字段用户组仅管理组可见指定用户组直接可见pre_common_usergroup这三个维度可以组合。比如配置成「普通用户回复后显示 50% 内容积分满 100 显示全部版主直接可见」就覆盖了绝大多数运营场景。理解这张表后面配置和排错时就知道每个开关对应查哪张表。3. 安装与后台配置把插件跑起来的最小步骤3.1 上传与启用的标准流程Discuz 插件安装有固定套路这里按标准流程走一遍。假设你已经拿到插件包通常是一个以插件标识命名的目录内含plugin_xxx.class.php和安装脚本。# 1. 备份数据库和论坛目录这一步不能省 mysqldump -u root -p discuz_db /backup/discuz_$(date %Y%m%d).sql tar -czf /backup/discuz_site_$(date %Y%m%d).tar.gz /www/discuz # 2. 把插件目录上传到 source/plugin/ 下 # 假设插件标识为 hide_enhance cp -r ./hide_enhance /www/discuz/source/plugin/ # 3. 确认目录权限Discuz 需要对插件目录可读 chown -R www:www /www/discuz/source/plugin/hide_enhance chmod -R 755 /www/discuz/source/plugin/hide_enhance上传后进入后台「应用 → 插件 → 插件列表」找到「隐藏内容回复增强」点安装。安装脚本会往pre_common_plugin等表写入插件记录并可能创建自己的配置表常见命名如pre_plugin_hide_enhance。提示安装前务必确认插件包里的discuz_plugin_xxx.xml或安装脚本与你的 Discuz 编码GBK/UTF-8一致编码不匹配会导致后台中文乱码这是最常见的翻车点之一。3.2 后台参数逐项说明安装完成后进入插件设置页核心参数通常有这几项逐项说清含义和推荐值启用状态总开关。调试阶段建议先关配置好再开。默认显示比例回复后显示内容的百分比取值 0-100。设 0 等于原生行为回复全可见设 50 表示只显示一半。推荐从 30 开始试太高失去引导回复的意义太低用户觉得被耍。积分门槛达到该积分才解锁全部内容。填 0 表示不启用积分维度。建议结合论坛实际积分分布设比如新用户注册送 10 分门槛设 50 比较合理。豁免用户组哪些用户组不受限制直接可见。通常填管理员、超级版主、版主。用用户组 ID 逗号分隔。提示文案未解锁时显示的提示支持 HTML。默认是「回复后可见」可以改成「回复后可见 50%积分满 100 解锁全部」。是否记录解锁日志开启后会往日志表写记录方便排查「为什么这个用户看不到」。调试期建议开稳定后可关以省数据库写入。3.3 验证配置是否生效配置完别急着全站放开先建一个测试帖验证测试帖内容 这是公开部分。 [hide]这是隐藏部分回复后按比例显示。[/hide] 这是结尾公开部分。用三个账号分别测试未回复的普通用户、已回复的普通用户、版主。预期结果未回复普通用户看到提示文案隐藏部分不显示。已回复普通用户看到隐藏部分的前 50%按你设的比例。版主直接看到全部隐藏内容。如果三者行为都符合预期说明插件主链路通了。任何一项不对回到第 5 章的排查清单对照。4. 代码层怎么接hook 挂载点与核心判断逻辑4.1 找到 discuzcode 的 hook 挂载位置Discuz 的discuzcode()函数里预留了插件钩子常见形式是hookscript()调用。你需要在插件类里实现对应方法。典型挂载点是在[hide]解析分支前后。?php // source/plugin/hide_enhance/plugin_hide_enhance.class.php class plugin_hide_enhance { // 挂载到 discuzcode 的 hide 解析前 function discuzcode_hide_before($param) { global $_G; // $param 里通常带 message、authorid 等上下文 $message $param[message]; // 判断当前用户是否已回复本帖 $tid $_G[tid]; $uid $_G[uid]; $has_replied $this-check_user_replied($tid, $uid); // 把判断结果塞回全局供后续解析使用 $_G[hide_enhance][has_replied] $has_replied; return $param; } // 检查用户是否回复过该帖 private function check_user_replied($tid, $uid) { global $_G; if (empty($uid)) return false; // 查回复记录注意用 C::t 走 Discuz 的缓存层 $count C::t(forum_post)-count_by_tid_authorid($tid, $uid); return $count 0; } }这段代码的逻辑在[hide]解析前先算出「当前用户是否已回复」把结果存到全局变量。后续解析时直接读这个标记避免重复查询。C::t(forum_post)是 Discuz 的数据层封装比裸写 SQL 更安全也更容易命中缓存。参数说明$tid是当前主题 ID$uid是当前用户 ID都从$_G全局取。count_by_tid_authorid是 Discuz 内置方法统计某用户在某主题下的回复数。如果你的 Discuz 版本没有这个方法需要自己写查询注意用DB::query并做好防注入。4.2 按比例截断隐藏内容的实现「显示 50%」这个需求实现上有两种思路按字符数截断或按段落截断。字符数截断简单但可能截断到 HTML 标签中间导致页面错乱段落截断更安全。// 按段落截断隐藏内容 private function truncate_content($content, $percent) { if ($percent 100) return $content; if ($percent 0) return ; // 按换行或段落标签切分 $paragraphs preg_split(/\n/, $content); $total count($paragraphs); $show_count max(1, floor($total * $percent / 100)); $shown array_slice($paragraphs, 0, $show_count); $result implode(\n, $shown); // 补上提示告诉用户还有多少没显示 $result . \n\n[还有 . ($total - $show_count) . 段内容回复或提升积分后可见]; return $result; }逻辑说明先按换行把内容切成段落数组算出应显示的段数至少显示 1 段避免用户回复后什么都看不到用array_slice取前 N 段最后拼上剩余段数提示。参数$percent就是后台配的显示比例$content是[hide]标签内的原始内容。注意如果隐藏内容里有 BBCode 标签如[attach]、[img]按段落切分可能把标签和内容切开。稳妥做法是先解析 BBCode 再截断或者限制隐藏内容里只放纯文本和简单标签。4.3 积分判断与用户组豁免的合并逻辑三个维度最终要合并成一个「显示多少」的结论。合并顺序很重要建议按「豁免 → 积分 → 回复」的优先级private function calc_show_percent($tid, $uid, $authorid) { global $_G; // 1. 作者本人直接全可见 if ($uid $authorid) return 100; // 2. 豁免用户组直接全可见 $exempt_groups explode(,, $this-config[exempt_groups]); if (in_array($_G[groupid], $exempt_groups)) return 100; // 3. 积分达标全可见 $credits $_G[member][credits]; if ($credits $this-config[credit_threshold]) return 100; // 4. 已回复按比例显示 if ($this-check_user_replied($tid, $uid)) { return $this-config[default_percent]; } // 5. 都没满足显示 0 return 0; }这个顺序的理由作者和豁免组是「特权」优先级最高积分是「硬门槛」达标就该给全回复是「软引导」给部分。如果顺序反了比如先判断回复那积分达标的用户可能只看到 50%体验就错了。参数$authorid是主题作者 ID从帖子数据里取。4.4 缓存与性能别让每次读帖都查库上面代码每次读帖都会查回复记录和积分高并发下数据库压力明显。Discuz 自带缓存机制应该利用起来// 用 Discuz 缓存存回复状态减少查询 private function check_user_replied_cached($tid, $uid) { $cache_key hide_enhance_reply_ . $tid . _ . $uid; $cached C::t(common_cache)-fetch($cache_key); if ($cached ! false) { return $cached[value]; } $replied $this-check_user_replied($tid, $uid); // 缓存 300 秒回复后最多 5 分钟生效 C::t(common_cache)-insert(array( cachekey $cache_key, value $replied ? 1 : 0, expire TIMESTAMP 300, ), false, true); return $replied; }逻辑先查缓存命中直接返回未命中查库后写缓存有效期 300 秒。参数$cache_key用主题 ID 和用户 ID 拼保证唯一。insert的第三个参数true表示存在则更新。代价是用户回复后最多 5 分钟才看到解锁对大多数论坛可接受如果要求实时把缓存时间调短或回复时主动清缓存。5. 避坑与排查五个真实踩过的坑5.1 回复后仍显示「回复可见」现象用户明明回复了刷新页面还是提示要回复。原因缓存没更新或者check_user_replied查错了表。Discuz 的回复可能存pre_forum_post但某些版本用pre_forum_postcomment存点评两者不是一回事。解决先确认回复落在哪张表用 SQL 直接查SELECT * FROM pre_forum_post WHERE tidxxx AND authoridyyy AND first0。first0排除楼主首帖。如果查得到但插件判断为未回复检查缓存 key 是否拼错或缓存时间设太长。5.2 隐藏内容截断后 BBCode 标签裸露现象页面出现[attach]123[/attach]这样的原始标签或者图片显示不出来。原因按字符数截断时切到了 BBCode 标签中间或者截断发生在 BBCode 解析之前。解决改成按段落截断见 4.2并确保截断在discuzcode()解析之后执行。如果必须按字符截断先用正则把 BBCode 标签整体保护起来截断后再还原。5.3 积分判断取到的是缓存旧值现象用户积分已经够了但插件还是按旧积分判断不给解锁。原因$_G[member][credits]来自会话缓存用户积分变动后缓存未及时刷新。解决积分判断前强制刷新或改用实时查询C::t(common_member)-fetch($uid)重新取。代价是多一次查询但积分门槛场景下准确性比性能重要。5.4 插件启用后全站帖子隐藏内容消失现象启用插件后所有带[hide]的帖子隐藏内容都不显示了连已回复用户也看不到。原因hook 挂载点选错或者calc_show_percent返回值逻辑有误默认返回了 0。解决先禁用插件确认是插件问题再检查 hook 是否挂在了discuzcode的正确分支。临时把默认返回改成 100 测试如果恢复正常说明是判断逻辑问题逐维度排查。5.5 与其它 BBCode 插件冲突现象装了隐藏增强后另一个处理[hide]的插件失效或两者行为叠加导致内容重复显示。原因两个插件挂了同一个 hook执行顺序不确定或者都修改了$message变量。解决在插件后台调整 hook 优先级让增强插件在原生解析之后执行。如果冲突无法调和考虑合并逻辑或禁用其中一个。Discuz 插件冲突没有银弹只能靠日志和二分法定位。6. 进阶把解锁策略做成可配置规则引擎上面讲的是固定三维度判断。实际运营中需求会变——今天想按回复字数解锁明天想按注册天数后天想按是否上传头像。每次都改代码不现实更好的做法是把判断逻辑抽成规则表后台可配。思路是建一张规则表pre_plugin_hide_enhance_rule字段包括规则 ID、条件类型回复/积分/用户组/注册天数/回复字数、比较符//、阈值、显示比例、优先级。判断时按优先级遍历规则命中第一条就返回对应比例。private function calc_by_rules($tid, $uid) { $rules C::t(#hide_enhance#rule)-fetch_all_by_priority(); foreach ($rules as $rule) { $value $this-get_condition_value($rule[condition_type], $tid, $uid); if ($this-compare($value, $rule[operator], $rule[threshold])) { return $rule[show_percent]; } } return 0; // 无规则命中 } private function get_condition_value($type, $tid, $uid) { global $_G; switch ($type) { case reply: return $this-check_user_replied($tid, $uid) ? 1 : 0; case credits: return $_G[member][credits]; case regdays: return floor((TIMESTAMP - $_G[member][regdate]) / 86400); case replylen: return $this-get_user_reply_length($tid, $uid); default: return 0; } }这样后台加一条「注册天数 30 显示 100%」的规则不用改代码就生效。规则引擎的代价是每次判断要遍历规则表规则多了性能下降建议规则数控制在 20 条以内并给规则表加缓存。验证规则是否按预期工作时我习惯在插件里加一个调试开关开启后把命中的规则 ID 和计算结果输出到页面注释里排查时一眼就能看到是哪条规则生效、哪个条件没满足。这个习惯帮我省了无数次翻日志的时间。最后说个我自己的教训这类增强插件最容易被忽略的是「解锁后的体验」。用户费劲回复了结果只看到 30% 还带一句冷冰冰的提示反而更挫败。提示文案要写得像人话比如「已解锁 30%再攒 50 积分看全部」比「积分不足」友好得多。技术实现只是骨架运营细节才是让插件真正有用的地方。希望帮到你。本文还有配套的精品资源点击获取