官方不提供现金交易,线下交易风险自担,请仔细鉴别!
xnx_need_avatar 默认头像发帖拦截
Xiuno BBS X 插件,对仍使用系统默认头像的用户拦截发帖与回帖操作,引导其先到个人中心设置自定义头像,从而提升社区内容质量与视觉一致性。通过多个 hook 在请求入口与提交前双重拦截,核心代码零硬编码插件名。
功能特性
- 默认头像判定:基于
user_read_cache($uid)读出的avatar_url字符串与default_avatar_url()严格比较,覆盖三种「实际仍是默认头像」的场景:
avatar==0(从未设置过头像)
2. avatar<0 且对应预设头像文件已被删除(user_format 回落默认) 3. avatar>0 但上传的物理文件丢失(user_format 回落默认)
- 双重拦截:GET 请求入口拦截(输出完整提示页)+ POST 提交前兜底拦截(输出 htmx 友好的 HTML 片段),绕过页面直连接口提交同样被拦
- 全场景覆盖:发新帖、回帖、帖子详情页快速回复表单三处入口均有拦截点
- 快速回复表单替换:命中拦截时用 CSS 隐藏原表单元素,改为显示「请先设置头像」提示卡 + 「去设置」链接,而非整体跳转
- 用户组豁免:管理员组(gid=1,2)默认豁免,可后台自定义豁免用户组列表(逗号分隔)
- 一键开关:后台可整体启用 / 禁用,禁用后所有 hook 调用
shouldBlock()立即返回 false - 多语言:内置简体中文、繁体中文、英文三套语言包
安装说明
- 将插件目录放入
plugin/xnx_need_avatar/ - 进入后台「插件管理」找到「默认头像发帖拦截」点击安装
- 安装时自动写入默认配置:
enabled=1、exempt_gids='1,2'(即默认启用,管理员组豁免) - 卸载时自动删除
xnx_need_avatar配置项,不残留数据
插件仅使用 setting 表存储配置,不建任何附加数据表,安装 / 卸载零副作用。
使用指南
后台配置
访问 /admin/plugin-setting-xnx_need_avatar,仅管理员组(gid=1,2)可进入,POST 操作经 CsrfService::check() CSRF 校验。
| 配置项 | 字段名 | 说明 | |---|---|---| | 启用状态 | enabled | 1=启用拦截,0=禁用(默认启用) | | 豁免用户组 | exempt_gids | 逗号分隔的用户组 ID,命中即跳过拦截(默认 1,2) |
保存后通过 NeedAvatarService::saveSettings() 写入 setting 表,下次请求即时生效。
前台行为
- 普通用户未设置头像时,访问发帖页 / 回帖页会看到完整提示页(含 header/footer),引导跳转个人中心
- 直接 POST 提交发帖 / 回帖时,返回警告样式的 HTML 片段(含「去设置」链接),htmx 容器友好
- 帖子详情页的快速回复表单会被 CSS 隐藏,替换为「请先设置头像后再发帖」提示,并附「去设置」链接到
my_url() - 豁免用户组成员、已设置头像的用户无任何感知,流程与原生一致
技术细节
拦截点 hook 列表
| Hook 文件 | 触发位置 | 拦截方式 | |---|---|---| | thread_create_get_start.php | 发帖页 GET 入口 | renderBlockPage() 输出完整页并 exit | | thread_create_thread_before.php | 发帖 POST 提交前 | renderBlockHtml() 输出片段并 exit | | post_get_start.php | 回帖页 GET 入口 | renderBlockPage() 输出完整页并 exit | | post_post_start.php | 回帖 POST 提交前 | renderBlockHtml() 输出片段并 exit | | thread_quick_reply_message_before.htm | 帖子详情页快速回复表单渲染前 | CSS 隐藏表单 + 提示卡注入 | | model_inc_file.php | 核心加载模型时 | 将 NeedAvatarService.php 注册进全局 include 列表 | | lang_zh_cn_bbs.php / lang_zh_tw_bbs.php / lang_en_us_bbs.php | 语言包加载 | 注入简中 / 繁中 / 英文文案 |
所有 hook 在 conf.json 的 hooks_rank 中均设为 100,与其他插件无优先级冲突。
默认头像判定逻辑
NeedAvatarService::isDefaultAvatar($uid) 实现:
- 调用
user_read_cache($uid)读取用户缓存(含user_format处理后的avatar_url) - 若用户不存在直接返回
true(保守拦截) - 严格比较
$user['avatar_url'] === default_avatar_url(),相等即视为默认头像
这种基于「最终渲染 URL 字符串」的判定比直接读 avatar 字段数值更稳健,能覆盖 user_format 在文件缺失时回落默认头像的三种边界场景,避免误判或漏判。
拦截决策流程
NeedAvatarService::shouldBlock($uid, $gid) 按以下顺序判断:
- 读取配置,若
enabled为空 → 返回false(插件被禁用) - 解析
exempt_gids字符串为数组,若当前gid命中 → 返回false(豁免) - 否则返回
isDefaultAvatar($uid)结果
exempt_gids 解析支持任意空白与多余逗号容错(parseGids() 已做 trim 与空值过滤)。
GET vs POST 拦截的差异
- GET 入口拦截(
renderBlockPage):输出包含view/htm/header.inc.htm与footer.inc.htm的完整页面,居中显示警告图标 + 提示文案 + 「去设置」按钮,调用exit终止后续流程 - POST 提交拦截(
renderBlockHtml):仅设置Content-Type: text/html; charset=utf-8头并输出alert alert-warning样式的 HTML 片段,适合 htmx 异步刷新容器直接渲染,同样exit终止
两套输出均通过 my_url() 生成跳转链接,指向用户个人中心。
快速回复表单处理
thread_quick_reply_message_before.htm hook 在帖子详情页快速回复表单渲染前执行:
- 通过
<style>#quick_reply_form > :not(.need-avatar-tip){display:none !important}</style>隐藏表单原有元素 - 注入一个
.need-avatar-tip警告卡片,含「请先设置头像后再发帖」文案与「去设置」链接 - 不调用
exit,允许页面其余部分正常渲染
配置兜底
NeedAvatarService::getSettings() 在 setting_get 返回空或字段缺失时,会自动补齐 enabled=1、exempt_gids='1,2',确保即使 setting 表异常也不会导致 shouldBlock() 报错。
兼容性
- Xiuno BBS X 1.1+(
bbs_version: 1.1) - PHP 8.x(对
isset兜底、intval严格比较、in_array第三参数true严格模式) - Bootstrap 5(提示页与卡片使用
x-card、alert、btn等原生类) - Tabler Icons(
ti ti-photo图标,跟随主题自带图标库) - 无 jQuery 依赖
- 依赖核心函数
default_avatar_url()、user_read_cache()、my_url(),需核心版本提供 - 通过 hook 注入,核心代码无硬编码插件名,插件禁用后拦截行为自动失效
版本历史
- 1.0.0:首版发布,包含默认头像判定、发帖 / 回帖 GET+POST 双重拦截、快速回复表单替换、用户组豁免、后台启用开关、简中 / 繁中 / 英文三语言支持
版本 1.0.0 | 兼容 Xiuno 1.1+