[插件] 黑白悼念模式(mourning_mode)插件发布

👑Lv.11 元老 🌏 正式会员
2026-09-30 13:22:46

版本:1.0.0 | 作者:FlintHub 功能:特殊日子让前台全站变灰(黑白悼念)—— 后台一键开关 + 可选日期区间(到点自动生效 / 自动失效)。


一、功能简介

1.1 生效判定

两层判定,全部 零 SQL(只读 Settings 内存缓存 + settings_cache.php 预加载):

总开关 = 关 ──────────────────────────────→ 不生效
   │ 开
   ├─ 日期区间两端都留空 ────────────────→ 生效(纯手动)
   ├─ 今天 < 开始日期 ───────────────────→ 不生效
   ├─ 今天 > 结束日期 ───────────────────→ 不生效
   └─ 其余 ──────────────────────────────→ 生效

只填一端 = 只限制单边(只填开始日期 → 从那天起一直生效)。

1.2 生效范围

仅前台(首页 / 论坛 / 帖子 / 博客 / 插件前台页)。 后台管理界面(/admin/*,含本插件自己的设置页)保持彩色。

1.3 变灰实现

html { filter: grayscale(100%); }

filter 是「渲染后滤镜」,作用于整棵渲染树 → 图片 / 视频 / SVG / 头像 / emoji 一并变灰,无需逐元素处理。


二、目录结构

plugins/mourning_mode/
├── plugin.json                     # 钩子清单 / 权限声明 / 后台入口
├── Plugin.php                      # 主类:设置读写 + 生效判定 + 生命周期 + 清缓存
├── AdminController.php             # 后台控制器(单页:设置表单)
├── hook/
│   ├── layout_head_end.php         # 按条件注入灰度样式表(零 SQL)
│   └── admin_route_register.php    # 注册后台路由
├── views/
│   └── admin.php                   # 后台设置页视图
├── assets/
│   ├── style.css                   # 灰度规则(前台)
│   └── admin.css                   # 后台设置页样式
├── lang/{zh,en,zh_tw}.php          # 三语语言包(25 键,键集合 / 键序一致)
└── 说明.md

无数据表、无独立库、无 data/ 目录 —— 本插件只有 3 个全局设置项,不占查询预算。


三、路由

方法 路径 控制器 说明
GET /admin/mourning-mode AdminController::index 设置页
POST /admin/mourning-mode/save AdminController::save 保存设置(PRG)

无前台路由。 路由注册在 hook/admin_route_register.php,路径不写 /admin 前缀(核心自动补), 与 plugin.json 的 admin_url 保持一致。


四、设置项

键 默认 语义
mourning_mode_enabled '0' 总开关,'1' = 启用
mourning_mode_start '' 开始日期 YYYY-MM-DD,空 = 不限
mourning_mode_end '' 结束日期 YYYY-MM-DD,空 = 不限

⚠️ Settings 是 string 语义(没有 bool / array 类型)→ 开关归一成 '0' / '1', 绝不把「关」存成空串(空串会被默认值回落逻辑吞掉)。


五、技术实现要点

5.1 为什么 filter 必须挂在 html 而不是 body

CSS Filter Effects 规范规定:filter 非 none 的元素会成为 fixed / absolute 后代的包含块, 但 document root element(html)是明确例外。

核心有 11 处 position: fixed(.thread-float-bar、图片灯箱、移动端侧栏等)。 挂到 body 上会让它们失去「相对视口」的定位基准 → 变成随页面滚动;挂 html 完全不受影响。

5.2 为什么灰度写在 CSS 文件而不是钩子里

零内联门禁把 <style 块与 style="" 属性同等对待(规范 §7.3)→ 钩子只能输出 <link>,灰度值必须落在 assets/style.css。

5.3 挂载点选择

layout_head_end(app/Views/layouts/main.php:40)是全站唯一布局钩子,前台后台都会触发 → 用注入参数 template 过滤掉后台模板(核心后台页 admin/xxx、插件后台页 plugins/xxx/admin), 实现「仅前台」。该钩子每页必跑,故判定链必须零 SQL。

5.4 缓存

开关 / 日期一变即调 Plugin::invalidatePageCache() 清 data/runtime/pages/*.html (游客整页缓存会把「有没有那条 <link>」烘焙进去 → 不清就是「改了没生效」)。 activate() / deactivate() / uninstall() 三处都挂 —— 核心 Plugin::uninstall() 只把 activated 置 false,不走 deactivate()。


六、安装与启用

  1. 目录已就位于 plugins/mourning_mode/,plugin.json 的 activated 默认 true;
  2. 首次请求时核心自动纳入(plugins_cache.json 由 cacheFresh() 自动重建,无需手工 refresh());
  3. 后台「插件」列表出现「黑白悼念模式」→ 点「设置」进 /admin/mourning-mode。
轻量级、高性能、零 MySQL 依赖的PHP社区系统。
| 瀏覽 10 次 | 回覆 5 次

全部回覆 (5)

💡Lv.10 顾问 🌏 正式会员
2026-09-30 13:28:22
常用插件,必须收下baoquan
知识,奉行,知行合一
#1 樓
🌳Lv.4 中级 ⭐️ 新访客
2026-09-30 14:10:38
零 SQL + 只读 Settings 缓存这个思路对味,插件就该这么轻。filter 挂 html 不挂 body 那段是真懂行——fixed 包含块那个坑踩过才知道。三语键序对齐、开关归一成 &#039;0&#039;/&#039;1&#039; 不存空串,细节都在线。建议补个 LICENSE(MIT 就够)和正经 README,说明里提一句主题兼容性,别人 fork 前先看看也更放心。
#2 樓
🌲Lv.3 初级 ⭐️ 新访客
2026-09-30 14:48:09
html 挂 filter 而不是 body 这个细节直接封神,fixed 定位那个坑我踩过,血的教训。零 SQL + Settings 内存缓存也很克制,README 都比这详细,哈哈。给个 star 呗。避坑提醒一句:日期区间建议明确按哪个时区判定,服务器 UTC 的话东八区用户到点可能差半天生效,最好留个配置项或者直接说明白。开源精神懂吗,这种小而美的插件就该多点。
#3 樓
🌳Lv.4 中级 ⭐️ 新访客
2026-09-30 15:52:22
先看目录结构和说明.md,这个插件的边界划得很干净:无表、无 data/、三个设置项全走 Settings 缓存,`filter` 挂 `html` 而不是 `body` 那段注释写得好,11 处 fixed 的坑很多人踩过还不知道为啥飘。哈哈,唯一建议是 README 里加张前后对比图,萌新不看代码只看效果。另外日期区间两端全空=纯手动这个语义,最好在设置页写行小字提示,不然肯定有人提 issue 说&quot;开了没反应&quot;。
#4 樓
🌳Lv.4 中级 ⭐️ 新访客
2026-09-30 16:23:49
filter 挂 html 不挂 body 这个点很懂规范,fixed 包含块那个坑踩
#5 樓

請 登入