资源分享 【插件】发帖时间切换

发帖时间切换(xnx_posttime_toggle)

让用户在「我的-用户中心-基本资料」自由切换发帖时间显示格式:相对时间(如「3 分钟前」)或绝对时间(如「2026-07-04 15:30:00」),偏好按账号持久化保存,互不影响。

功能简介

XIUNOX BBS 默认在主帖(thread)页面以「相对时间」格式展示发帖时间(如「3 小时前」),便于快速感知新鲜度。但部分用户(尤其是归档查阅、数据核对场景)更希望看到精确的年月日时分秒。本插件在不修改核心代码的前提下,通过 Xiuno 的 hook 机制为每位登录用户提供独立的「时间显示偏好」开关,选择后立即在主帖发帖时间生效,且仅对当前账号起作用,不影响其他用户。

核心功能

  1. 两种时间格式切换

    • 相对时间(默认):保留 Xiuno 原生 xn_date() 输出,如「3 分钟前」「昨天 14:30」

    • 绝对时间:Y-m-d H:i:s 标准格式,如「2026-07-04 15:30:00」

  2. 按账号生效:偏好存储在 user 表的 xnx_ptt_mode 字段,每个账号独立设置

  3. 零侵入核心:通过 model_thread_format_end hook 在 thread_format() 函数末尾改写 create_date_fmt,不修改任何核心文件

  4. 可视化设置入口:在「我的-用户中心-基本资料」页面注入设置卡片,使用 htmx 提交,无刷新保存

  5. CSRF 防护:表单包含 CsrfService::input() 令牌,后端在 CsrfService::check() 之后处理

  6. 多语言支持:内置简体中文、繁体中文、英文三种语言包

  7. 插件图标没设计,不喜欢设计图片😂

安装与启用

安装前提

  • XIUNOX BBS(XIUNO BBS X 重构版)4.5+

  • PHP 8.0+

  • MySQL(pdo_mysql 扩展)

  • user 表有写入权限(用于新增 xnx_ptt_mode 字段)

安装步骤

  1. xnx_posttime_toggle 目录整体放入 plugin/ 目录

  2. 登录后台 → 「插件管理」→ 找到「发帖时间切换」

  3. 点击「安装」→ 系统自动执行 install.php,向 user 表添加 xnx_ptt_mode 字段

  4. 点击「启用」→ 插件开始生效

卸载说明

  1. 后台「插件管理」→ 点击「禁用」

  2. 点击「卸载」→ 系统自动执行 uninstall.php,幂等删除 xnx_ptt_mode 字段

  3. 卸载后所有用户的时间显示偏好会被清空,回退到默认相对时间

使用指南

用户端操作

  1. 登录账号

  2. 点击右上角用户名 → 进入「我的」

  3. 在「用户中心」中找到「基本资料」页面

  4. 滚动到「时间显示偏好」卡片

  5. 在「发帖时间显示格式」下拉框中选择:

    • 相对时间(如 3分钟前):Xiuno 默认行为

    • 绝对时间(如 2026-07-04 15:30:00):精确时间格式

  6. 点击「保存」按钮,页面顶部出现绿色「偏好已保存」提示

  7. 进入任意帖子详情页,主帖的发帖时间立即按新格式显示

生效范围

  • ✅ 主帖(thread)的发帖时间 create_date_fmt

  • ❌ 回帖列表(post)的时间(保留 Xiuno 原生相对时间)

  • ❌ 帖子列表页的时间(保留 Xiuno 原生相对时间)

  • ❌ 游客(未登录用户):始终显示相对时间

注意事项

  • 偏好按账号存储,同一账号在多设备登录会同步生效

  • 切换后立即生效,无需清缓存

  • 卸载插件后字段被删除,所有用户回退到默认相对时间

技术实现

数据库设计

user 表新增字段:

ALTER TABLE `xn_user` ADD COLUMN `xnx_ptt_mode` tinyint(1) unsigned
  NOT NULL DEFAULT 0
  COMMENT '发帖时间显示偏好:0=相对,1=绝对'
  AFTER `logins`;

字段名

类型

默认值

说明

xnx_ptt_mode

tinyint(1) unsigned

0

0=相对时间,1=绝对时间

Hook 注册清单

conf.jsonhooks_rank 注册 6 个 hook:

Hook 文件

触发位置

作用

model_thread_format_end.php

thread_format() 函数末尾

改写 $thread['create_date_fmt']

my_profile_end.htm

「基本资料」页面末尾

注入设置卡片 HTML

my_profile_post_start.php

「基本资料」POST 处理入口

拦截 xnx_ptt_action=save 保存偏好

lang_zh_cn_bbs.php

简体中文语言包加载

注入 6 个 $lang

lang_zh_tw_bbs.php

繁体中文语言包加载

注入 6 个 $lang

lang_en_us_bbs.php

英文语言包加载

注入 6 个 $lang

时间格式改写逻辑

hook/model_thread_format_end.php 核心代码:

global $user;
$ptt_mode = isset($user['xnx_ptt_mode']) ? intval($user['xnx_ptt_mode']) : 0;
if ($ptt_mode === 1 && isset($thread['create_date'])) {
    $thread['create_date_fmt'] = date('Y-m-d H:i:s', intval($thread['create_date']));
}
  • 编译进 thread_format() 函数末尾,$thread 为引用参数

  • 仅当 xnx_ptt_mode === 1 时才覆盖默认的相对时间

  • 游客($user 为空)走默认分支,不受影响

前端表单(htmx 实现)

hook/my_profile_end.htm 注入一个独立 htmx 表单:

<form hx-post="{my_profile_url}" hx-target="#xnx-ptt-msg" hx-swap="innerHTML">
    {CsrfService::input()}
    <input type="hidden" name="xnx_ptt_action" value="save">
    <select name="xnx_ptt_mode">...</select>
    <button type="submit">保存</button>
</form>
  • 使用 hx-post 提交到「基本资料」URL

  • hx-target="#xnx-ptt-msg" 将响应 HTML 注入到消息容器

  • hx-swap="innerHTML" 替换容器内容

  • 后端返回纯 HTML 片段(<div class="alert alert-success">偏好已保存</div>),符合 htmx 规范

后端保存逻辑

hook/my_profile_post_start.phpCsrfService::check() 之后、昵称/签名处理之前执行:

if (param('xnx_ptt_action') === 'save') {
    $ptt_mode = intval(param('xnx_ptt_mode', 0));
    if ($ptt_mode !== 0) $ptt_mode = 1; // 只允许 0 或 1
    if (db_check_column_exists('user', 'xnx_ptt_mode')) {
        user_update($uid, array('xnx_ptt_mode' => $ptt_mode));
    }
    echo '<div class="alert alert-success mb-3">偏好已保存</div>';
    exit;
}
  • 通过 xnx_ptt_action=save 隐藏字段区分本表单与其他资料保存

  • 强制 xnx_ptt_mode 只能为 01,防注入

  • 二次校验字段是否存在,避免字段缺失时报错

  • 调用 user_update() 自动触发 cache_delete + hook,下次请求立即生效

  • exit 阻止后续资料处理逻辑,避免误改昵称等

幂等性保证

  • install.php:先 db_check_column_exists 检查,再 ALTER TABLE ADD COLUMN

  • uninstall.php:先 db_check_column_exists 检查,再 ALTER TABLE DROP COLUMN

  • 重复安装/卸载不会报错,安全可重复执行

多语言支持

插件内置三种语言包,覆盖所有用户可见文案:

语言

Hook 文件

适用地区

简体中文

hook/lang_zh_cn_bbs.php

中国大陆

繁体中文

hook/lang_zh_tw_bbs.php

港台地区

英文

hook/lang_en_us_bbs.php

海外用户

语言键清单

键名

简体中文

繁体中文

英文

xnx_ptt_title

时间显示偏好

時間顯示偏好

Time Display Preference

xnx_ptt_choose

发帖时间显示格式

發帖時間顯示格式

Post Time Format

xnx_ptt_mode_relative

相对时间(如 3分钟前)

相對時間(如 3分鐘前)

Relative (e.g., 3 minutes ago)

xnx_ptt_mode_absolute

绝对时间(如 2026-07-04 15:30:00)

絕對時間(如 2026-07-04 15:30:00)

Absolute (e.g., 2026-07-04 15:30:00)

xnx_ptt_tip

选择后在主帖发帖时间立即生效,对当前账号生效

選擇後在主帖發帖時間立即生效,對當前賬號生效

Takes effect immediately on thread pages for your account

xnx_ptt_saved

偏好已保存

偏好已保存

Preference saved

⚠️ 语言 hook 文件位于 lang_*_bbs.php(非 lang_*_bbs_admin.php),因为它们位于 return array(...) 之外,使用 $lang['key'] = 'value'; 语法。每行以 ; 结尾,禁止尾随注释。

常见问题

Q1:为什么切换后帖子列表页的时间没变?

A:本插件只改写主帖(thread)详情页的发帖时间 create_date_fmt,不影响帖子列表页和回帖列表。这是设计上的取舍——列表页通常需要相对时间快速感知新鲜度,详情页才需要精确时间。

Q2:游客能看到绝对时间吗?

A:不能。游客未登录,$user 为空,xnx_ptt_mode 字段不存在,默认走相对时间分支。这是有意为之,避免影响未注册用户的浏览体验。

Q3:卸载插件后我的偏好还在吗?

A:不在。uninstall.php 会删除 xnx_ptt_mode 字段,所有用户的偏好记录被清空。重新安装后所有人回退到默认相对时间(mode=0)。

Q4:管理员能强制所有用户使用绝对时间吗?

A:当前版本不支持。本插件定位为「用户个性化偏好」,每位用户独立选择。若需全站强制,可通过 SQL 批量更新:UPDATE xn_user SET xnx_ptt_mode = 1;,但插件本身不提供此开关。

Q5:保存后页面没有提示?

A:请检查浏览器是否拦截了 htmx 请求(如广告屏蔽插件)。打开开发者工具 Network 面板,查看 my-*.htm 请求是否返回 200 和 HTML 片段。若返回 403,可能是 CSRF 令牌缺失。

Q6:可以扩展到回帖时间也切换吗?

A:可以。在 hook/ 目录新增 model_post_format_end.php,复用相同逻辑改写 $post['create_date_fmt'],并在 conf.jsonhooks_rank 中注册。当前版本未做此扩展以保持插件轻量。

注意事项

  1. 生产环境部署前:先在测试环境验证 install.phpALTER TABLE 语句不与大表锁表冲突(user 表通常较小,无影响)

  2. 字段保护xnx_ptt_mode 不在 USER_UPDATE_PROTECTED_FIELDS 中,user_update() 可正常写入

  3. 缓存影响user_update() 会自动 cache_delete("user-$uid"),下次请求重新读取,无需手动清缓存

  4. tmp 缓存:修改 hook 文件后需清理 tmp/ 目录,确保新改动重新编译

  5. PHP 版本:兼容 PHP 8.0+,无废弃函数调用

  6. MySQL 字符集:字段为整型,与 utf8mb4 字符集无冲突

  7. htmx 依赖:前端表单依赖 htmx 4.x,确保主题模板已加载 htmx.min.js

版本历史

版本

日期

变更说明

1.1

2026-07

初始版本:实现用户中心时间显示偏好切换,支持简繁英三语,htmx 无刷新保存

下载地址:

请登录后查看此内容

管理员标记为「资源分享」,奖励 +20 金币
最新回复
  • leostudio 内测用户站长VIP Lv3
    第一个开发者分享xiunox插件,有里程碑意义
    25天前
  • 大佬👍👍👍
    25天前
  • sunkille Lv1
    厉害👍👍👍
    25天前
  • AI Lv1

    感谢扣扣小妖分享这款实用的插件!👏

    该插件精准解决了“相对时间”在归档查阅时的不便,且通过 hook 机制实现零侵入,技术思路清晰。特别是利用 htmx 实现无刷新保存偏好,既提升了用户体验,又保持了代码轻量,值得肯定。

    关于作者提到的图标问题,其实可以使用 Unicode Emoji(如 ⏰ 或 🕒)作为临时替代,既美观又无需设计资源。

    期待更多开发者加入 XiunoX 生态,共同丰富插件库!如有后续优化需求(如扩展至回帖时间),欢迎继续交流。【以上由 AI 自动回复,仅供参考】

    11天前
  • 权威 Lv1
    努力 赚积分。
    1天前

请先登录后再回复 登录