[hot_rank]跨版块热度榜与精选热
- 跨版块热度榜与精选ID hot_rank版本 2.2.0插件制作者 cxk123售价 30 积分3221 行 / 200.1 KBHook / 路由 / 后台页把「按发帖时间排」升级成「按真实热度排」:回复、浏览、窗口内去重回帖人、新近度各按权重加权,收费插件安装说明购买后点击“授权码”获取一次性授权码;在后台 > 插件广场点击在线安装或更新,并填写该授权码。已购买用户更新免费:每次在线安装或更新前,重新点击“授权码”获取新的一次性授权码即可,无需再次购买;也可直接下载新版后用后台“插件上传”更新。尊重并感谢他人劳动,请勿传播代码。app/plugins/hot_rank/plugin.php插件预览6 张开发日志已有 6 条
此项目接受所有登录用户协助维护和提交更新。
主楼 版本 1.0.0 更新:
首次上架:跨版块热度榜与精选 1.0.0【为什么做这一款(实测结论)】
市场 certified 312 + beta 94 = 406 条里,「权重 / 加权 / 衰减 / 归一」0 命中;
直接竞品 hot_topics 2.1.2 自述「零存储、不建表、不依赖自然周月」且候选只按 created_at 过滤 ——
于是没有历史榜(昨天的日榜今天无法重建)、没有自然期、老帖翻红永不入榜。
本款把这三处补齐。【四项能力】
- 可配置权重热度算法:热度 = 回复×w_reply + round(浏览/K)×w_view + 窗口内去重回帖人×w_viewer + 新近度×w_fresh + 人工加权。
权重一律钳制成整数后内联进 SQL(只有时间与 LIMIT 用绑定参数、列在比较左侧),
一条聚合 SQL、无窗口函数;候选窗口按「窗口内有活动」(created_at 或 last_reply_at 落入窗口)→ 老帖被回复即可翻红。- 日 / 周 / 月 + 历史榜:自然日 / ISO 周 / 自然月三种期号,每期冻结算法版本 + 分项得分 + 计数;
历史榜可按任意一期回看(?a=hot_rank&view=archive&kind=day&key=YYYY-MM-DD),
主题后来被删掉也照样显示并标注「已删除」;升降箭头由上一期同榜一次读回。- 榜单页 + 侧栏卡片 + DIY 组件:侧栏卡片只在白名单页渲染、读预写缓存 → 零查询、其它页字节不变;
向 layout_diy 注册 hot_rank:top / hot_rank:picks 两个只读组件;主题行整批走匿名遮蔽契约。
- 精选位 + 人工加权(含审计):加减分可排期、可到期自动失效、可为负;精选位手工排序与上限;
后台列出生效项与全量审计;写操作 POST + CSRF;用户侧标注「编辑精选 / 运营加权 ±N」。
【数据与预算】
4 张自有表(期快照 / 榜条目 / 加权与精选 / 审计)+ 7 枚具名索引,不碰核心 app_* 结构与任何其它插件的数据表;
页面固定 1 条 SQL 出榜、不随主题数增长;计划任务每轮 ≤9 条语句(每多配一个版块榜 +3),
跨期用冻结的 window_end 落上一期终版、幂等,每日清理超期快照。【兼容与降级】
PHP 8.1+ / SQLite / MySQL / PostgreSQL;未装 layout_diy 或未装匿名区时全部功能照常、且零额外查询。插件质量报告
插件:
hot_rankHook 功能范围 循环 使用频率 文件读写 修改系统表 读写系统表 读写自己的表 sidebar.feature_links 首页/侧栏快捷功能 否 5 - - - - sidebar.stack 全站侧栏组件栈 否 5 - - - - topic.title_suffix 首页/版块主题列表逐条标题 是 5 - - - - diy_layout.components 非系统hook 否 1 - - - - topic.template 非系统hook 否 1 - - - 读 plugin_hot_rank_boosts 颜色说明:黄色表示有数据读写,红色表示 Hook 在系统循环中执行,浅蓝色表示有文件写入。“列表跳过”表示回调在列表路径会提前返回,“回调内”表示操作位于回调自身或其帮助函数的循环体内。“文件批处理”表示逐个处理用户一次提交的文件,属于必要操作,不标记修正。只有操作实际处于需要优化的循环路径时,才会标记“修正❗️”。
数据字典
plugin_hot_rank_snapshots字段 类型 可空 默认值 约束 - 动态定义 - - 无法静态解析 plugin_hot_rank_entries字段 类型 可空 默认值 约束 - 动态定义 - - 无法静态解析 plugin_hot_rank_boosts字段 类型 可空 默认值 约束 - 动态定义 - - 无法静态解析 plugin_hot_rank_audit字段 类型 可空 默认值 约束 - 动态定义 - - 无法静态解析 - 83天前
大佬做插件挺频繁呀,这么多时间捣鼓插件🤔
版本 1.0.1 更新:
1.0.1:修「侧栏卡片把首页整页查询预算顶上去」+ 与其它插件的预算断言对齐【修的是什么】
侧栏卡片渲染时调了匿名遮蔽契约 anon_board.mask_rows。契约在「站点上确实有匿名内容」时
实测要发 2 条查询(先探一次有没有匿名内容,再取一次主题旗标)—— 卡片挂在首页 / 版块页的白名单上,
于是这两个页面的整页查询数被 +2。插件自己的账(SQL 文本含 plugin_hot_rank 的语句数)仍然是 0,
所以本插件套件测不到;是别的套件对首页有「≤9 条」的绝对断言才暴露出来。【改法】
侧栏卡片不再调遮蔽契约:它一行都不渲染身份字段(只有名次 / 标题 / 热度分,标题本来就是公开信息)。
榜单页 / 历史榜 / 精选页 / 主题页标注照常整批遮蔽(那些地方真的要显示作者)。
改完白名单页的热度榜自有查询数仍是 0,且跨插件契约查询也回到 0。【验证】
本插件套件新增「卡片开关 开 / 关 两态下首页整页 SQL 条数完全相等」的断言;
回归里受影响的那套页面对首页查询数有绝对断言的套件复跑通过。版本 1.0.2 更新:
hot_rank 1.0.2- 新增第三个原生只读组件「热榜 TOP N」(hot_rank:board):当期榜前 N 名 + 升降箭头(与榜单页同一个渲染器)+ 热度分,声明成本 7 条。
- 主题行整批过匿名区遮蔽契约后再读身份字段;被遮蔽的行带 data-hot-rank-diy-masked="1"、不出现真实昵称;契约异常时整块降级,绝不输出未遮蔽的行。
- 当期还没有快照 / 站点没落过榜时零查询返回空块;站点标记为 0 时先花一条聚合语句按真实数据自愈。
- 计划任务的上一轮账目(实际语句数 / 预算 / 落榜 / 冻结 / 延后 / 清理)落到后台概览,不用再翻计划任务日志。
- 未装 / 未启用 layout_diy 时行为、查询数、页面字节逐字节不变(套件有 A/B 对照)。
版本 1.0.2 更新:
hot_rank 1.0.2- 新增第三个原生只读组件「热榜 TOP N」(hot_rank:board):当期榜前 N 名 + 升降箭头(与榜单页同一个渲染器)+ 热度分,声明成本 7 条。
- 主题行整批过匿名区遮蔽契约后再读身份字段;被遮蔽的行带 data-hot-rank-diy-masked="1"、不出现真实昵称;契约异常时整块降级,绝不输出未遮蔽的行。
- 当期还没有快照 / 站点没落过榜时零查询返回空块;站点标记为 0 时先花一条聚合语句按真实数据自愈。
- 计划任务的上一轮账目(实际语句数 / 预算 / 落榜 / 冻结 / 延后 / 清理)落到后台概览,不用再翻计划任务日志。
- 未装 / 未启用 layout_diy 时行为、查询数、页面字节逐字节不变(套件有 A/B 对照)。
版本 1.0.2 更新:
hot_rank 1.0.2- 新增第三个原生只读组件「热榜 TOP N」(hot_rank:board):当期榜前 N 名 + 升降箭头(与榜单页同一个渲染器)+ 热度分,声明成本 7 条。
- 主题行整批过匿名区遮蔽契约后再读身份字段;被遮蔽的行带 data-hot-rank-diy-masked="1"、不出现真实昵称;契约异常时整块降级,绝不输出未遮蔽的行。
- 当期还没有快照 / 站点没落过榜时零查询返回空块;站点标记为 0 时先花一条聚合语句按真实数据自愈。
- 计划任务的上一轮账目(实际语句数 / 预算 / 落榜 / 冻结 / 延后 / 清理)落到后台概览,不用再翻计划任务日志。
- 未装 / 未启用 layout_diy 时行为、查询数、页面字节逐字节不变(套件有 A/B 对照)。
版本 2.0.0 更新:
2.0.0 · 三项新能力 + 两处真缺陷修复(同一版本号原子抬升)【新能力】
- 飙升榜(?a=hot_rank&view=movers):本期 vs 上一期的名次与分数变化 —— 上升(上期 #N → 本期 #M)/ 新上榜 / 掉出榜。全部来自两期已冻结的快照,零新增表、零新增写路径;掉出榜的标题取自上一期的冻结行,主题被删也照常显示。
- 单主题热度走势(?a=hot_rank&view=trend&topic=<id>):一个主题在保留期内每一期的名次与分数(分数柱 + 分项 + 最好名次 / 上榜期数),名次用相关子查询数出来、依然不依赖窗口函数;主题被删后历史照样可查。榜单行右侧新增「走势」入口,三个视图互相可达。
- 后台「权重试算(只读沙盒)」:用试算权重跑一遍出榜,列出会进入 / 会掉出 / 名次变化最大 / 分数变化最大,并给出「榜首对照」;跑的是与计划任务同一条出榜 SQL,所以试算看到的名次就是保存后会落进去的名次。试算不写榜 / 不写快照 / 不写审计。
- 人工加权支持版块作用域:可以只作用于某个版块榜(默认全站)。出榜算法、榜单行标注、后台「作用域」列三处同口径;审计里也记下作用域。
【修复】
· 卡片缓存与「立即重算」的写入分工:原先收尾只有两条路拿快照 id,都落空时会静默跳过卡片缓存刷新(榜已重算、卡片还是旧的),提示语也一个字不提。现在补上第三条路(补一条查库语句,受每轮 9 条预算约束),并把去向写进提示语:「卡片缓存 已刷新(… · 本轮落榜/快照缓存/补查)」或「卡片缓存 待下一轮」。
· 站点标记 plugin_hot_rank_live 原先有两个写者(「站上有任何快照」与「卡片那一期有没有快照」)互相覆盖:卡片周期当期还没落榜时,一次普通写操作就会把标记冲成「无榜」,快捷入口与页面组件跟着降级。现在标记只有一个写者,卡片刷新只写卡片自己的键。
· 计划任务每轮写的「各期条目数」原先只写不读,现在显示在后台概览;后台概览同时显示卡片缓存的写入时刻与条数。
· 修掉一处空操作死分支(精选的作用域判定条件与赋值同式,任何输入下都不改变状态)。【口径不变】热度算法、期号与窗口、每期冻结、遮蔽契约、查询预算(非白名单页 0 条 / 计划任务每轮 ≤9 条)与依赖方向全部不变;升级后历史快照与审计原样可读。
版本 2.1.0 更新:
2.1.0 · 并发加固 + 榜单导出/存档 + 到期提醒(无表结构变更,覆盖升级即可)【并发加固】站点是多进程的,后台「立即重算」与计划任务会同时写同一份缓存。三处加固,一条查询都不多花:
- 条目重建进事务:删旧条目 + 写新条目包在核心事务里,并发读者要么看到旧的一整份、要么看到新的一整份,不会撞进「旧的已删、新的还没写」的空窗(那个空窗会把卡片缓存刷成空数组,侧栏卡片整块消失到下一轮)。
- 空窗保护:万一还是读到空集,只要快照行说这一期本来有条目,就判定为并发窗口 → 保留上一份缓存,绝不写空。
- 来源时间单调门 + settings 单调写入门:卡片缓存带「内容来源时刻」写,来源更旧就不覆盖;期号键 / 快照 id 键 / 写入时刻这些语义单调的键只前进不回退。
三组计数(空窗保护 / 来源更旧 / 单调门拦下)与最近一次拦截时间都显示在后台概览上。
套件里既有 6 轮「立即重算 ∥ 计划任务」的真并发 burst(断言缓存内容逐项等于当期快照 top-N、期号键没有回退、没有半成品快照、插件仍启用),也有两道门的确定性验证(哨兵缓存夹具)。【榜单导出 / 存档】?a=hot_rank&view=export&kind=day&key=<期号>&format=csv|json
导的就是那一期冻结快照:名次与页面逐字同口径,主题后来被删也照样导出并标「已删除」。列含分项与冻结计数(回复/浏览/去重回帖人/新近小时/人工加权/四项得分/总分/窗口/算法版本)。CSV 带 UTF-8 BOM(Excel 直开不乱码)并做公式注入中和(= + - @ 开头加单引号前缀);JSON 带 meta 信封(期号 / 窗口 / 是否冻结 / 算法版本 / 列定义)。不含任何身份字段(无作者、无 user_id)。查询 ≤3,与行数无关;非法期号自动降级到最新一期,非法 format 回落 csv。当期榜与历史榜的 meta 栏都有「导出 CSV / 导出 JSON」入口。【到期提醒】后台「人工加权 / 编辑精选」区新增提醒面板:7 天内到期的条目(含「还剩 N 小时」)与「已排期未生效」的条数。运营加权到期只是 SQL 按时间过滤、不会发通知,所以把要续期的直接摆到眼前。全部从已读入的生效项推,零额外查询。
【升级】本版没有任何表结构变更(只加代码路径与 settings 键)→ 老库直接覆盖 plugin.php,一发请求(插件注册表同步)即自愈:版本认到 2.1.0、插件仍启用、老快照/条目/审计原样保留、四张表与索引的 SQL 指纹逐字节不变。套件用 1.0.2 的产物走完了整条升级路径。
【口径不变】热度算法、期号与窗口、每期冻结、遮蔽契约、查询预算(非白名单页 0 条 / 计划任务每轮 ≤9 条)与依赖方向全部不变;历史快照与审计原样可读。
版本 2.2.0 更新:
2.2.0 · 榜单可见性 + 覆盖升级不砖 + 卡片空窗- 修复(越权):出榜 SQL、渲染层、导出(公开链接)与侧栏卡片此前都没有版块可见性判定 ⇒ 受限版块的主题会进榜单、被导出、被卡片展示。现已四处按核心同一口径过滤:快照保留、渲染层过滤(冻结账不重算),站内没有受限版块时 SQL 文本逐字节不变。
- 修复(覆盖升级会砖):本插件此前只会在安装时建表/补列,而核心在覆盖文件时不会重跑安装 ⇒ 老站点覆盖升级后会因缺表缺列抛异常并被自动停用。现在补上「结构版本戳 + 请求级零查询快路 + 幂等 DDL」自愈链路。
- 修复:侧栏卡片缓存在刚跨期、本期榜单还未算出时会写入空数组(而渲染路径零查询直出)⇒ 卡片空白到下一轮计划任务。现在补一处零查询短路:本期数据尚未就绪时保留上一期内容。
- 另修复
?days=形式的「表达式与绑定参数比较」在 SQLite 上恒假的时间窗(同类问题,已内联为整数比较)。
升级:覆盖文件即自愈;无数据结构破坏性变更。