• xuexilea
    顶踩与举报
    ID topic_vote版本 1.4.1插件制作者 xuexilea免费625 行 / 44.6 KBHook / 路由 / 后台页
    支持给主题和回帖点顶踩,举报内容由管理员处理;踩到阈值自动隐藏、顶到阈值自动置顶。
    app/plugins/topic_vote/plugin.php
    开发日志已有 1 条

    个人独立维护项目。

    • xuexilea
      xuexilea
      版本 1.4.1 c0309529d6b7 更新:旧格式迁移:已将插件代码转存到开发日志,主题正文改为基础介绍。release
    主楼
  • 质量报告

    插件质量报告

    插件:topic_vote

    Hook功能范围循环使用频率文件读写修改系统表读写系统表读写自己的表
    reply.after_render主题查看页/回帖列表逐条渲染是5----
    topic.after_render首页/版块列表/主题查看逐条渲染是5----
    topic.after_view主题查看页完成加载否4---读 plugin_topic_vote_votes

    颜色说明:黄色表示有数据读写,红色表示 Hook 在系统循环中执行,浅蓝色表示有文件写入。“列表跳过”表示回调在列表路径会提前返回,“回调内”表示操作位于回调自身或其帮助函数的循环体内。“文件批处理”表示逐个处理用户一次提交的文件,属于必要操作,不标记修正。只有操作实际处于需要优化的循环路径时,才会标记“修正❗️”。

    数据字典

    plugin_topic_vote_votes

    字段类型可空默认值约束
    idid否-主键、自增
    user_iduint否-唯一
    guest_keyVARCHAR(32)否''唯一
    target_typestring否-唯一
    target_iduint否-唯一
    voteINTEGER否--
    created_atuint否--

    plugin_topic_vote_reports

    字段类型可空默认值约束
    idid否-主键、自增
    user_iduint否-唯一
    guest_keyVARCHAR(32)否''唯一
    target_typestring否-唯一
    target_iduint否-唯一
    reasontext否--
    statusINTEGER否0-
    created_atuint否--
    handled_atuint否0-
    handler_iduint否0-
    #1
  • 233

    @xuexilea 已按 topic/245 完成 1.4.0 整改:使用规范化新表迁移旧投票和举报数据,移除 MySQL 专用 ALTER TABLE,已验证 SQLite 旧数据迁移。平台不允许非原作者更新同 ID,修正版源码:

    topic_vote_1.4.0.php1

    #2
  • bbs1org

    @xuexilea 这个插件有严重性能问题啊。不要在循环里面查询

    #3
  • xuexilea

    看看是不是修复了

    #4
  • idc

    这个现在一楼显示全部的顶踩了

    #5
  • 等风来

    这个显示是不是有问题
    1.jpeg

    #6
  • 350

    🔍 插件审查报告(对照《AI 开发规则》与开发者文档)

    🔒 安全问题

    未发现明显问题。SQL 全走参数化,表名来自白名单函数(plugin.php:119-121),IN 占位用 sql_marks()(plugin.php:170);用户数据输出均经 h()(plugin.php:256-278、509-519、534-571);状态路由 require_post()+form_token(),游客/登录分支校验(plugin.php:290-292、342-344),后台 need_admin()(plugin.php:395),全局 check() 校验 _csrf;投票/举报靠 UNIQUE 唯一键去重(plugin.php:81-82),无客户端可篡改的积分结算。

    ⚡ 性能问题

    红区钩子内 DB 读取 + N+1:topic.after_render 的列表分支对每行执行 one("SELECT ... WHERE id=?")(plugin.php:241);核心 topic_list_row 在循环内逐行触发该钩子(index.php:2059/2080),构成渲染循环 N+1,违反红区规则「topic.after_render 调用链内禁止任何 DB 读取」。虽有阈值开关守卫,但默认 hide_down_threshold=5(plugin.php:25)即处于启用态,列表页默认触发。详情页设计良好:topic.after_view 先批量收集计数与我的投票(plugin.php:171、191),渲染时零查询。

    🐛 功能/规范缺陷

    1. Cookie 名 tv_guest 未以插件 ID 前缀(plugin.php:129、132),违反规则 16/116,应改 topic_vote_guest。
    2. CSS 硬编码 font-size:12px/13px 与 border-radius:999px/8px(plugin.php:285),应使用 --font-size-xs/--font-size-sm 与 var(--radius)。
    3. manifest author 为 rdzn(plugin.php:610),与主题作者 xuexilea 不一致。

    ✅ 修复优先级

    1. topic.after_render 列表分支的 one() 改为列表页一次性收集(高,红区 N+1)。
    2. Cookie 名前缀化 tv_guest → topic_vote_guest(低)。
    3. CSS 字号/圆角改用系统变量(低)。
    #7
  • 399

    🔍 插件审查报告(AI 自动审查,对照《AI 开发规则》与开发者文档;本插件未被 8/18 楼上 350 的报告覆盖,属独立首次审查)

    插件:topic_vote v1.4.1

    🔒 安全问题
    未发现明显问题。写操作(顶/踩/举报/禁言解除)均经 need_login()/need_admin() 与 require_post()+CSRF 校验;SQL 均参数化。

    ⚡ 性能问题
    红区 Hook 存在非零 DB 读的分支:topic_vote_after_render()(同时挂在 topic.after_render 与 reply.after_render)在列表页渲染路径下,若本条内容没有被 topic.after_view 预加载阶段收集到计数缓存($GLOBALS['__topic_vote_data'] 未命中),且后台"踩到阈值自动隐藏"或"举报到阈值自动进回收站"任一功能开启时,会对当前行执行一次 one() 单行查询以读取隐藏/回收站状态(plugin.php 约 240-243 行)。规则要求红区调用链内禁止任何数据库读取;虽然此处仅在特定路径(列表页 + 未预加载 + 阈值功能开启)触发,且限定为按主键单行查询,不构成 N+1 式全表扫描,但仍属于对红区规则的字面违反,建议评估能否把该状态一并纳入既有的预加载缓存(如通过 topic.index_data.loaded 补充查询隐藏/回收站字段),彻底消除列表路径下的按行查询。

    🐛 功能/规范缺陷
    命名前缀、Hook 使用(topic.after_view/after_render、cron 双任务)均符合规范,未见其它问题。

    ✅ 修复优先级
    建议优先处理性能项:把隐藏/回收站状态纳入统一预加载,避免列表页在特定配置下产生按行查询。

    #8
  • xuexilea

    旧格式迁移:已将插件代码转存到开发日志,主题正文改为基础介绍。

    #9

发表回复

登录后回复