[开发]楼中楼(floor_reply)插件说明

👑Lv.11 元老 🌞 骨干会员
2026-10-25 01:10:57

本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:WWW/update/27/plugins/floor_reply/说明.md。

楼中楼(floor_reply)插件说明

版本:1.1.0 | 作者:FlintHub | 状态:✅ 已启用

功能:在帖子楼层(posts)下方支持对楼层的再回复(楼中楼),支持 @ 提及用户(高亮 + 跳转个人主页);

并在有人回复楼层 / @ 到某人时发送通知,通知可深链直达那一条楼中楼。


一、功能简介

  • 楼中楼:对某条回复(楼层)进行再回复,数据存独立库,不占用核心楼层数
  • @ 提及:回复时 @ 指定用户,前端高亮显示,点击跳转其个人主页
  • mention_user_id 只记录第一个被 @ 的用户,仅用于列表高亮渲染
  • 通知则覆盖全部被 @ 的用户(见第四节)
  • 回复计数联动:回复成功后同步更新帖子的回复数与最后回复时间(Thread::incrementReplyCount)
  • 积分奖励:回复成功触发核心积分奖励(Points::markReplied / Points::award),并计入站点统计
  • 通知 + 深链(V1.1.0):楼中楼回复会通知楼层作者与被 @ 的人(楼主可选),

点通知直达该条楼中楼所在页并高亮

二、目录结构

plugins/floor_reply/
├── plugin.json              # 插件清单(6 个钩子 + admin_url + permissions)
├── Plugin.php               # 独立库连接 + 建表 + 楼中楼统计/计数 + 配置读写 + pageOfReply()
├── FrontController.php      # 楼中楼回复 / 列表接口(?focus= 深链)
├── AdminController.php      # 后台通知设置页(V1.1.0 新增)
├── hook/
│   ├── init_after.php               # 幂等建表兜底
│   ├── route_register.php           # 前台路由(回复/列表/删除)
│   ├── admin_route_register.php     # 后台路由(V1.1.0 新增,需 route:admin 权限)
│   ├── layout_head_end.php          # 注入楼中楼 CSS/JS(仅 thread/show)
│   ├── post_operation_after.php     # 楼层下注入"楼中楼"入口 + 锚点
│   └── controller_view_before.php   # 一次性批量注入各楼层楼中楼数 + 自动展开开关
├── views/
│   ├── list.php             # 楼中楼列表局部模板(htmx 片段)
│   └── admin.php            # 后台设置页(V1.1.0 新增)
├── assets/                  # style.css / script.js
└── lang/                    # zh.php / en.php / zh_tw.php

三、数据表(插件独立库 plugins/floor_reply/data/floor_reply.sqlite)

表用途
fr_replies楼中楼回复(post_id / thread_id / user_id / mention_user_id / content / created_at,索引 idx_fr_post、idx_fr_thread)

  • 建表:activate() + init_after 双保险(幂等 DDL)
  • 卸载:uninstall() 删表 并清理核心 settings 表里本插件的配置键(会清空全部楼中楼数据,请谨慎)

四、路由

前台

方法路径说明
GET/floor-reply/list/{id}某楼层({id} = 楼层 post_id)的楼中楼列表片段(htmx 局部渲染,每页 5 条)<br>可选 ?page=N 翻页;可选 ?focus=<楼中楼ID> 强制渲染该条所在页并标记高亮(通知深链用)
POST/floor-reply/reply提交楼中楼回复(CSRF + 频控)
POST/floor-reply/delete删除楼中楼回复(作者本人 / 管理员 / 楼主)

后台

方法路径说明
GET/admin/floor-reply通知设置页
POST/admin/floor-reply/save保存设置(CSRF)

⚠️ 后台路由需在 plugin.json 声明 route:admin;写全局设置需 system:settings。二者均已声明。

五、通知机制(V1.1.0)

收件人规则

一条楼中楼回复可能同时命中三类收件人,按优先级去重,保证「每个收件人最多收到 1 条」:

优先级收件人通知类型默认
1被 @ 到的人mention✅ 开
2楼层作者floor_reply✅ 开
3楼主(帖子作者)floor_reply❌ 关

  • 回复人自己永不收到通知(与核心 notifyReply / notifyQuote / notifyVote 一致)
  • 楼主默认不通知:楼中楼是「楼层内部的对话」,核心 notifyReplyAggregated() 已负责「帖子有新回复」的聚合通知
  • 通知写入核心 business.sqlite 的 notifications 表:related_id = 楼层 post_id、related_type = 'floor'

深链格式

/thread/{主题ID}?pid={楼层ID}&fr={楼中楼ID}#fr-{楼中楼ID}

三段分工:

  • ?pid= → 核心 ThreadController::show() 经 Post::pageOf() 算出楼层所在页码并跳转
  • ?fr= → 本插件 ?focus= 参数算出该条楼中楼所在页并标记高亮
  • #fr-{id} → 原生锚点兜底,script.js 负责滚动到视野中央

通知文案键(核心语言包 lang/{zh,en,zh_tw}.php)

键用途
plugin.notifications.floor_reply「{user} 回复了你在「{title}」中的回复」
plugin.notifications.floor_reply_owner「{user} 在「{title}」的楼中楼中回复了 {target}」(楼主专用,避免误称「你的回复」)
plugin.notifications.mentioned「{user} 在回复中提到了你,主题「{title}」」

六、后台设置项

配置存核心 settings 表,键前缀 floor_reply_。

键默认说明
floor_reply_notify_floor_author1通知楼层作者
floor_reply_notify_mention1通知被 @ 的人
floor_reply_notify_thread_owner0通知楼主(默认关)
floor_reply_auto_expand1打开帖子时自动展开已有楼中楼(通知深链不受此开关影响)

七、安全与规范

  • 提交受 RateLimiter 频控(3 次 / 30 秒)保护,防刷分漏洞
  • 回复内容入库前 strip_tags(),输出经 $this->e() / renderMentions() 转义,防 XSS
  • 全部 PDO 预处理绑定;ID 一律 (int) 强转
  • 后台设置页表单带 csrf 隐藏域,服务端 Csrf::verifyOrDie() 校验
  • 楼中楼仅占独立库,不写核心帖子表结构,卸载/禁用对核心数据零污染
  • 样式全部走 --mn-* 主题变量(含 fallback),双主题(浅色 / 暗夜星辰)可读

八、注意事项

  • 依赖 controller_view_before 一次性注入全帖楼中楼数据,避免每楼层一次查询
  • 删除楼层(post)时不自动清理其楼中楼(历史遗留记录保留)
  • 删除楼中楼不撤回已发出的通知(通知按「历史事件」处理)
  • 积分奖励 / 回复计数联动为核心约定,流程调整时需同步 Plugin.php 内相关方法
  • 改动 plugin.json 的 hooks 后必须重建 plugins/plugins_cache.json(删文件或调 Plugin::refresh()),否则新钩子不生效
  • 通知深链的页码换算口径与核心 Post::getByThread() 严格同桶同表同排序;若核心改了楼层排序规则,Post::pageOf() 需同步调整
轻量级、高性能、零 MySQL 依赖的PHP社区系统。
| 瀏覽 5 次 | 回覆 0 次

全部回覆 (0)

暫無回覆

請 登入