为Xiuno BBS 4注入HTMX现代交互能力
Tillreetree (99) 开发者 管理团队 1月前

版权所有 Geticer 2025前言与简介

经过对Xiuno BBS 4核心机制的深度研究,我成功实现了HTMX的深度集成。以清爽蓝色主题为基底,在不破坏原生逻辑的前提下,为纯原装Xiuno BBS带来现代化近乎SPA的体验。  

版权所有 Geticer 2025这意味着什么?

意味着更流畅、更现代的用户体验,同时保持 Xiuno 一贯的简洁和高效。

版权所有 Geticer 2025技术实现亮点

版权所有 Geticer 2025非侵入式改造

  • 零核心代码修改,完全通过Hook机制实现
  • 原生功能100%覆盖(目前仅限于此,插件兼容性保留)
  • 渐进式增强:未改动验证码/附件上传等复杂交互

版权所有 Geticer 2025核心交互升级

版权所有 Geticer 2025无刷新全局导航

  • 所有GET请求保持原URL结构,但实现内容动态替换
  • 增加 `updatePagination` 事件解决分页器兼容问题
  • 新增 `setActive` 函数替代jQuery依赖

版权所有 Geticer 2025纯HTMX表单处理

  • 主题帖回帖:彻底脱离jQuery,通过 updatePostCount 事件同步计数,与HTMX本身的功能配合提供流畅体验
  • 密码交互:属性自动生成加密字段,告别jQuery-MD5  
  • 管理功能:基于Pico CSS重构模态框(这部分不依赖Bootstrap功能,但暂时依赖Bootstrap样式),删除回帖时触发 removePost 等事件实现原子化更新(普通管理操作则全页刷新确保没有奇怪的副作用)

版权所有 Geticer 2025改造后的 message.htm 成为事件中枢

大多数操作的(文字)反馈都会通过模态框和吐司框呈现。

新增事件:

  • showModalSimple:显示模态框
  • closeModal:关闭模态框
  • showToast:右上角轻量吐司框通知

版权所有 Geticer 2025智能路由识别

通过全局变量精准控制渲染逻辑

/**
 * @var bool 是HTMX发起的请求吗?
 */
$IS_HTMX = isset($_SERVER['HTTP_HX_REQUEST']) || (isset($_SERVER['HTTP_HX_REQUEST']) && $_SERVER['HTTP_HX_REQUEST'] == 'true');
/**
 * @var bool 是通过翻页器访问的吗?
 */
$IS_IN_PAGINATION = isset($_REQUEST['IS_IN_PAGINATION']) && boolval($_REQUEST['IS_IN_PAGINATION']);

.

版权所有 Geticer 2025技术选型思考

HTMX的声明式特性与Xiuno的AOP架构完美契合:  

  • 后端仅需微调输出HTML片段(通过现有Hook点)  
  • 前端交互复杂度降低60%+(移除大量jQuery回调)  
  • 传输体积减少约40%(局部更新优势)  

版权所有 Geticer 2025已知注意事项

插件页面(例如通知、排行榜、积分等页面)可能出现双重嵌套(HTMX正常工作的副作用)  

版权所有 Geticer 2025你看到的,是未来

这不是一个简单的“去 jQuery”项目,而是一次对传统论坛架构的重新思考:

我们不需要抛弃成熟的后端系统,也能拥有现代交互体验。 

HTMX 让服务端渲染应用焕发新生,而 Xiuno BBS 凭借其清晰的 Hook 机制和插件生态,完美适配这一理念。

1.4(2025年9月10日)

  • 新增:关于本站、网站规则、隐私声明、联系我们、所有论坛板块页,其中:
    • “网站规则、隐私声明、联系我们”可在“关于本站”进入
    • “关于本站”在页脚进入
    • “所有论坛板块页”在页眉导航栏进入

新路由

以下路由除非特别标注,只有HTMX

about_us 【完成】 请求方式:GET 参数:无

关于我们页面,HTMX只要页面内容本身

  • 有意模仿移动 App 的“关于”页面风格,增强产品感与品牌调性。

terms 【完成,占位】 请求方式:GET 参数:无

网站规则页面,HTMX只要页面内容本身

privacy 【完成,占位】 请求方式:GET 参数:无

隐私声明页面,HTMX只要页面内容本身

contact_us 【完成,占位】 请求方式:GET 参数:无

联系我们页面,HTMX只要页面内容本身

bbs 请求方式:GET 参数:无

展示所有论坛板块的页面,HTMX只要页面内容本身

插件兼容

  • kan_rsdjs 直接可用
  • sg_highlight 适配完成
  • nciaer_copyright 直接可用
  • mx_site_time 直接可用
  • zls_sitemap 直接可用
  • sg_group 直接可用
  • wr_direct 不兼容
  • xn_bgee_radom_thread 适配完成(注意,这个插件对性能有影响)
  • wish_gowild 直接可用(外观可能不太好)
  • xn_onlinetime 直接可用
  • cf_life_countdown 直接可用
  • hp_only_host 不考虑兼容,请用haya_post_info
  • qt_check_token 直接可用(未测试,经过查看源代码应该是兼容的)
  • cf_bugfix_emptycontent 直接可用
  • cf_bugfix_tmpfiles 直接可用
  • tianapi_dictum 直接可用
  • ccreed_poison_word 直接可用
  • xiuno_online_userlist 适配完成
  • git_online_userlist 适配完成
  • a8c5_fontlist 直接可用
  • a8c5_fontstyle 直接可用
  • a8c5_icolist 直接可用
  • cf_bottomline 直接可用
  • di_email_notice 直接可用
  • tianapi_mingyan 直接可用
  • haya_post_attach_lite 直接可用
  • xn_ipaccess 直接可用

1.3(2025年9月9日)

  • 修复:解决了当a标签同时具备data-modal-url和href的时候,两者都会触发(显示弹窗的同时会跳转到href所指的网址)
  • 修复:登录页面没有错误提醒,以及登录成功后不会跳转

插件兼容

  • huux_notice 适配完成(这个下次再说)
    • 无限滚动 ×
  • haya_post_like 25%(这个下次再说)
    • 主题贴点赞 √
    • 主题贴取消点赞 √
    • 回贴点赞
    • 回贴取消点赞
  • haya_post_info 适配完成
    • 回复排序 √
    • 回复默认排序 √
    • 只看楼主 √
    • 只看Ta √
    • 回复显示楼主 √
    • @用户提醒 √
    • 帖子列表显示浏览量 √
    • 首页帖子列表显示板块 √
    • 帖子列表分页 √
    • 首页板块自定义 √
    • 首页显示板块 √
    • 今日发帖时间高亮 √
  • nt_rename 适配完成
  • xn_screen_reader 直接可用
  • zz_iqismart_newpost 直接可用
  • zaesky_todaypost 直接可用
  • xn_recount 直接可用
  • xn_read_unread 不兼容
  • xn_nav_more 不兼容
  • xn_manual 无法兼容,作者都没写完
  • xn_antispawn 可能不兼容,未测试
  • xiuno_top_search 下一版再做,功能可能会集成
  • till_thread_passcode 适配完成
  • till_digitalclock 不兼容
  • till_editviews 适配完成
  • till_widget_monthlyProgress 直接可用
  • till_xnlog_viewer 直接可用
  • till_spoiler 直接可用
  • till_post_author_badge 直接可用
  • till_hot_thread 适配完成
  • abs_shortcode 直接可用
  • zz_iqismart_newpost 适配完成
  • zz_top 直接可用
  • xn_accesscount 直接可用
  • xu_autosurl 直接可用
  • haya_attach 直接可用
  • haya_post_sort 【建议使用haya_post_info】
  • qt_sensitive_word 直接可用

1.2(2025年9月3日)

  • 【新增】:解决了覆盖其他hook的最大难点。本插件会覆盖其他插件的更多内容,目的主要是添加HTMX支持
  • 修复:解决了process_pagination_to_htmx_trigger在特定情况下出错
  • 新增:用原生JS+HTMX实现了$('[data-modal-title]').each(function () {...}的弹窗显示属性
    • 必须拥有data-modal-url属性,这会让HTMX往这里发送GET请求
    • 可选data-modal-title属性,替代原来的弹窗标题
    • 可选data-modal-arg属性,约等于hx-include属性值,但如果你没有在这个属性里写input或textarea或select的话,会自动加上来保证可用性和兼容性
    • 推荐使用data-modal-url直接作用于按钮等控件上来打开弹窗
  • 修改:用HTMX实现了$.ajax_modal的弹窗部分功能
  • 移除:大约是xiuno bbs 3.0时期的旧函数:xn_positionxn_menuxn_dropdownxn_toggle,因为完全没有插件使用
  • 移除:“点击响应整行”.tap功能
  • 新增:应当使用“fullpage”参数来获取全页(不含页眉页脚)

插件兼容

  • art_signature 适配完成
  • ax_comment 直接可用
  • ax_notice_sx 适配完成
  • fox_prison 适配完成
  • fox_search 适配完成
  • xn_digest 适配完成
  • haya_post_like 25%
  • huux_notice 适配完成
    • 独立消息页面 √
      • 但是在当前的个人中心里是加载到右侧,因为其他的都确定了
      • 在导航栏里的是加载到页面内容
      • 消息分类切换 √
      • 翻页 √
    • 标记已读 √
    • 点击a标签设置已读 √
    • 删除单条 √
    • 全部已读 √
    • 删除本页信息 √
    • 无限滚动 ×

其他

$.fn.button的第一个参数的取值有
  • loading:将按钮变为不可点击,然后将按钮原来的文字设置到按钮的default-text属性里,然后将按钮的文字设置为按钮的data-loading-text属性值
  • disabled:将按钮变为不可点击
  • enable:将按钮变为可点击(去掉disabled状态)
  • reset:将按钮变为可点击,然后检查是否有default-text属性,如果有,则将按钮的文字设置为default-text属性值
  • 其他字符串:直接将按钮的文字设置为该值
message函数的第一个参数:
  • -101,目前具体表现为显示toast 类型为info

发掘到的未使用部分

$.ajax_modal函数中提到了if (code == -101)

这会让该函数解析JSON里的HTML\CSS\JS然后隐藏 modal-footer

class=xn-dropdown的元素会变成xiuno的dropdown,所有插件都没使用

用法:

<div class="xn-dropdown" data-pos="5" data-hidearrow="0">
    <div class="dropdown-toggle" >显示dropdown</div>
    <div class="dropdown-menu">dropdown内容</div>
</div>

点击“显示dropdown”后,会根据data-pos的值定位“dropdown内容”的位置并显示出来,并且“dropdown内容”会附带一个小三角,这个小三角则是根据data-hidearrow的值决定是否显示,如果data-hidearrow是1或其他表示true的值则不会显示

data-pos的值:

         11        12     1
        --------------------
     10 |                  | 2
        |                  |
      9 |        0         | 3
        |                  |
      8 |                  | 4
        --------------------
         7        6       5

class=xn-toggle的元素会变成xiuno的toggle开关,所有插件都没使用

用法:

<div class="xn-toggle" data-target="#toggle_demo">toggle按钮</div>
<div id="toggle_demo">toggle内容</div>

点击“toggle按钮”后,data-target属性指定的“toggle内容”会滑动显示出来,然后再次点击屏幕任何位置,“toggle内容”会滑动隐藏

如何使用fullpage参数

当链接是HTMX发起的时候,$IS_HTMX会优先响应,然后根据携带的额外参数来提供HTML片段,但有时候我们确实需要返回页面本体,但如果对该链接不使用HTMX的话就失去了用HTMX的意义。那么后端插件在写链接地址的时候这样写:

<!-- before -->
<a href="<?= url('my-notice');?>">消息</a>
<!-- after -->
<a href="<?= url('my-notice',['fullpage'=>1]);?>" hx-boost="true" hx-trigger="click" hx-target="#body" hx-swap="innerHTML" hx-push-url="true">消息</a>

然后在插件本身提供的页面里写:

<?php
if($IS_HTMX && boolval(param('fullpage',0)) === false){

    // HTMX专属逻辑,专注于输出HTML片段
    include _include(APP_PATH.'plugin/huux_notice/view/htm/my_notice_list.inc.htm');

} elseif(!$IS_HTMX || ($IS_HTMX && boolval(param('fullpage',0)))) { ?>

<?php /* 【当不是HTMX访问的时候输出】 */ if(!$IS_HTMX) {include _include(APP_PATH . 'view/htm/header.inc.htm');} ?>

<?php /* 【当是HTMX访问,并且fullpage是1的时候输出】 */ include _include(APP_PATH.'plugin/huux_notice/view/htm/my_notice_list.inc.htm'); ?>

<?php /* 【当不是HTMX访问的时候输出】 */ if(!$IS_HTMX) {include _include(APP_PATH . 'view/htm/footer.inc.htm');} ?>

<?php }/*endif*/ ?>

这样就可以兼顾HTMX的片段输出和全页输出。

1.1.0(2025年7月27日)

  • 新增:主页、论坛版块页面、个人中心、用户页面 里的“帖子列表”的无限滚动加载
  • 新增:帖子页面、个人中心、用户页面 里的“回帖列表”的无限滚动加载
  • 修改:process_pagination_to_htmx_trigger函数增肌了第二个参数,用来指示给前台的翻页器添加什么参数,为后续精细化控制打下基础。目前是写死的thread(代表threadlist,在前台会增加IS_IN_THREADLIST)和post(代表postlist,在前台会增加IS_IN_POSTLIST)
  • 新增:兼容了xiuno第一方插件“我的回帖”

外观没有变化。有人说“ui不好看”,那确实。这个的外观和原装xiuno相差无几。但从一个熟悉的起点出发可以更容易理解。

1.0.0(2025年7月24日)

初次发布。实现核心 HTMX 集成: 无刷新导航、HTMX 表单提交、事件中枢、新版Pico CSS 弹窗、替代JQuery的自动 MD5 等。

版权所有 Geticer 2025截图

版权所有 Geticer 2025源码获取

见附件。请尽可能下载版本号高的版本。

这只是一个开始。

当 HTMX 遇见 Xiuno BBS,

老树开新花,原味生未来。


如需下载请先回复并刷新本帖!
最新回复 (7)
广告推荐
Tillreetree
开发者 管理团队
广告推荐