一、需求背景

2026-08-08,站长提出:为每个主题和回帖增加「顶 / 踩 / 举报」功能。本插件作为独立插件开发,未修改论坛程序核心代码。

二、方案设计

  • 顶踩:一人一票,支持改票与取消;计数用冗余字段实时维护,避免列表逐条查询
  • 举报:填写理由提交,管理员在后台处理(标记已处理 / 忽略 / 禁言作者)
  • 数据plugin_topic_votes(投票记录,唯一键 用户+目标 防重复)、plugin_topic_reports(举报记录)
  • 前台:主题详情页与每条回复下方显示顶踩计数与操作按钮;未登录仅显示计数
  • 后台:新增「顶踩与举报」管理页,可开关功能、设置举报最短字数、处理举报

三、实现要点

  • 全部逻辑在 app/plugins/topic_vote/plugin.php 单文件内,遵循 bbs1.org 插件开发规范
  • 详情页数据一次性批量读取,写操作在事务内完成
  • 计数缓存列带插件前缀(plugin_topic_vote_up/downplugin_topic_report_count),卸载时自动回收

四、版本记录

版本内容
v1.0.0顶 / 踩 / 举报与后台管理上线
v1.0.1修复取消投票时计数未回退的问题
v1.1.0样式调整;举报理由预置;踩隐藏 / 顶置顶 / 举报回收站 自动治理
v1.1.1举报弹层改为居中弹窗,不再被页面遮挡
v1.1.2举报理由改为按钮右侧内联展开,样式紧凑,不依赖脚本
v1.1.3回收站显示策略:主题列表隐藏,回帖保留作者、正文替换提示
v1.1.4后台举报/回收站列表标题可点击,回帖直达所属主帖并定位
v1.1.5修复回收站提示文字被压缩成竖排的问题(grid 容器横跨整行)
v1.1.6后台三个列表默认折叠,点击展开,避免长列表拉长页面
v1.1.7后台回帖链接改为新标签页打开,便于连续处理
v1.1.8后台三个列表全部链接均新标签页打开,临时隐藏列表补链接
v1.1.9「忽略」改为「不违规」:一键恢复原内容并清零举报数
v1.2.0禁言管理:默认禁言时长可配、到期自动解除、后台手动解除
v1.3.0允许游客(未登录)顶踩/举报开关,游客身份用 cookie 匿名指纹
v1.3.1「标记已处理」改为「确认违规」,点击后内容自动移入回收站
v1.4.0表名规范化:plugin_topic_vote_votes/reports,旧表数据自动迁移,MySQL/SQLite 通用
v1.4.1修复 N+1:后台举报列表批量映射目标/举报人,列表页阈值全关跳过查询

五、验证结果

  • 顶、踩、改票、取消全流程计数正确
  • 不能对自己的内容操作;重复举报幂等
  • 后台处理举报、设置保存/恢复正常
  • v1.1.0:列表页与详情页隐藏/回收站占位正确;置顶自动生效;计划任务到期自动恢复隐藏
  • v1.1.1/1.1.2:举报交互三种形态均已实测(居中弹窗 / 按钮右侧内联展开),最终采用内联展开(文档流内天然不被遮挡)

更新记录

  • v1.4.1(2026-08-11):响应开发者反馈,修复循环内查询(N+1)——① 后台「待处理举报」列表原先每条举报循环内查 2 次(目标内容 + 举报人),改为循环外批量收集 ID → rows_by_ids 一次查回 → 内存映射,列表 100 条时查询从 ~200 次降到 3 次;② 前台板块列表页因核心 topic.list_columns 白名单带不出插件列、且无列表级 hook(逐行 after_render),只能每行主键单查 trashed/hidden 状态,本次增加「隐藏/回收站阈值全关时直接跳过」优化;详情页本就走 after_view 批量收集,无 N+1。
  • v1.4.0(2026-08-08):为方便插件分发,表名规范化为 plugin_topic_vote_votes / plugin_topic_vote_reports(与插件名前缀对齐);新增 topic_vote_migrate_legacy_tables():检测旧表存在则逐行迁移数据(含 guest_key,INSERT IGNORE 幂等)后删除旧表;移除 MySQL 专用 ALTER TABLE 迁移逻辑(改用建新表+迁移数据,MySQL/SQLite 通用,UNIQUE(user_id,guest_key,target_type,target_id) 内联约束双库兼容)。线上 MySQL 实测:旧表 votes 6 / reports 12 全部迁入新表,旧表删除,功能回归通过。
  • v1.3.1(2026-08-08):待处理举报中的「标记已处理」按钮改为「确认违规」——点击后即视为管理员手动确认该内容违规,系统自动将该主题/回帖移入回收站(主题列表隐藏、回帖保留作者信息仅正文替换提示),举报记录标记为已处理。实测:回复移入回收站、前台提示显示、后台回收站列表可见,全部正常。
  • v1.3.0(2026-08-08):后台设置新增「允许游客顶踩 / 举报」开关(默认关闭)。开启后未登录用户可直接顶踩/举报,身份用 cookie 匿名指纹(tv_guest,32 位随机 hex)标识;投票与举报表新增 guest_key 列,唯一键升级为 (user_id,guest_key,target_type,target_id),游客与注册用户互不干扰(注册用户 guest_key 恒为空)。关闭开关时游客仍只看到计数与登录提示。
  • v1.2.0(2026-08-08):新增禁言管理——后台设置可配置「默认禁言时长(分钟,0=永久)」;点击「禁言作者」时按该时长禁言(到期时间写入 plugin_topic_vote_muted_until,0=永久);新增 unmute_expired 计划任务(60 秒)到期自动解除;后台新增「禁言管理」折叠区块(列出所有被禁言用户,显示剩余时间/永久,可一键解除禁言)。此前核心禁言是永久且无解除入口,本次全部补上。
  • v1.1.9(2026-08-08):待处理举报中的「忽略」按钮改为「不违规」——点击后:若该内容因举报在回收站则自动恢复,同时举报数清零,举报记录标记为不违规;实测内容恢复、计数归零、状态更新全部正常。
  • v1.1.8(2026-08-08):后台「待处理举报」「回收站」「临时隐藏中」三个列表中的全部链接(主题与回帖)均改为新标签页打开(target=_blank + rel=noopener);「临时隐藏中」列表原先没有链接,本次同步补上(主题直达、回帖直达主帖并定位)。
  • v1.1.7(2026-08-08):后台「待处理举报」「回收站」列表中的回帖链接改为新标签页打开(target=_blank + rel=noopener),查看上下文后原列表页保留在后台,便于连续处理;实测点击后新标签直达主帖并定位到该回复。
  • v1.1.6(2026-08-08):后台「顶踩与举报」页的「待处理举报」「回收站」「临时隐藏中」三个列表改为默认折叠(原生 details,无脚本依赖),点击标题展开/收起,避免列表内容多时拉长整个页面;标题右侧显示数量与状态,带展开箭头。
  • v1.1.5(2026-08-08):修复回帖回收站提示文字被压缩成竖排(每字一行)的问题——提示块所在父容器为 grid 布局(li.post-item),已加 grid-column:1/-1 + min-width:0 使其横跨整行横向显示;实测 772px 宽、单行文字。
  • v1.1.4(2026-08-08):后台「待处理举报」与「回收站」列表中,主题与回帖标题均可点击——回帖链接直达所属主帖并自动定位到该回复(replyid),方便管理员快速判断是否违规。
  • v1.1.3(2026-08-08):优化回收站浏览体验——主题被移入回收站后板块列表完全不再显示(详情页仅简短提示);回帖被移入回收站后保留作者与时间等发布信息,仅正文区域替换为提示文案。
  • v1.1.2(2026-08-08):举报理由表单改为点击「举报」后在按钮右侧内联展开(原生 details 展开,处于文档流内,天然不被遮挡、样式紧凑,且不依赖任何脚本);移除上一版的 JS 弹窗逻辑与 JS 资源。
  • v1.1.1(2026-08-08):修复举报弹层被页面容器遮挡的问题——点击举报改为屏幕居中弹窗(fixed 遮罩 + 居中面板,不受父容器 overflow 影响),支持 ESC / 点击遮罩 / 右上角关闭;浏览器禁用脚本时自动降级为原下拉展开方式。
  • v1.1.0(2026-08-08):去掉顶踩举报按钮条的上边框线,按钮条与下一条内容间距加大,便于区分归属;举报理由改为后台可编辑的预置选项(默认 6 类常见违规理由),用户举报时直接选择;新增自动治理——踩数达到阈值自动临时隐藏(默认 5 踩隐藏 5 分钟,到期由计划任务自动恢复)、顶数达到阈值自动置顶(默认 10 顶)、举报数达到阈值自动移入回收站(默认 3 次,管理员可在插件后台恢复或彻底删除);后台新增「回收站」与「临时隐藏中」管理区块,阈值均可配置。
  • v1.0.1(2026-08-08):修复取消投票时顶踩计数未回退的问题。