[开发]FlintHub 公告插件「样式增强版」规划方案

👑Lv.11 元老 🌞 骨干会员
2026-10-26 02:02:37

本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:WWW/待办事宜/FlintHub_公告插件_样式增强_方案.md。

FlintHub 公告插件「样式增强版」规划方案

状态:待拍板(未动一行代码)

对象:plugins/announcements(已启用,plugin.json version 1.3.0)

依据:docs/插件开发规范.md、docs/插件审计报告.md、本机实测

编写:2026-10-11


0. 一句话结论

在现有 plugins/announcements 上做增强(不新建插件):把「样式」从一维配色升级为

二维正交模型(容器模式 × 条目布局),新增 4 种容器模式 + 5 种条目布局 + 7 种配色 + 每条可选图标,

并顺手整改 4 处既有缺陷。全部走主题变量、零内联、向后兼容(老数据零迁移成本)。


1. 现状盘点(有据)

事实证据
插件已存在且已启用plugins/announcements/plugin.json → "activated": true, "version": "1.3.0"
前台注入点 3 处app/Views/home/index_default.php:17、app/Views/forum/index.php:22、app/Views/blog/index.php:20
现有「样式」= 6 种配色Plugin.php:123-133 getStyles() → yellow/red/gray/bluegray/blue/green
现有「模式」= 2 种Settings::get('announcement_mode') → normal(堆叠)/ scroll(上下滚动),见 AdminController.php:37-46
数据表结构announcements(id, content, url, style, sort_order, created_at) —— 无 layout / icon / title 列
现存真实数据3 条:id1 green、id2 red、id3 blue,sort_order = 1/2/3
现外观唯一assets/style.css:2 .announcement-bar —— 圆角 8px 彩色底条 + 右侧 ×
图标能力核心 TemplateCompiler::icon() 的 $map 有 492 项,其中 announcement = (喇叭)✅
字体子集覆盖assets/fonts/fontawesome-webfont.subset.v2.{ttf,woff2} 448 字形,实测含 F0A1/F0F3/F05A/F071/F1EA/F0EB/F135/F053/F054 ✅

1.1 顺带发现的 4 处既有缺陷(本次一并整改)

#问题位置后果
D1说明.md 与实现严重脱节说明.md:3,21,28,37,49写了 status 字段、admin_sidebar_links 钩子、版本 1.2.0 —— 实际都没有(表里无 status,plugin.json 无该钩子,版本是 1.3.0)。下一个人会照文档改错
D2后台编辑弹窗在 </main> 之外views/admin.php:94(</main>)→ :98(#editModal)违反「后台弹层 markup 必须在 .admin-content 内」。当前靠 .fl-modal .form-input 自含样式硬撑(:47-77),能跑但脆:核心一改后台控件样式,弹窗就脱相
D36 套配色全是硬编码浅色assets/style.css:5-10(#fff8e1 等)违反 §11.7「样式必须变量化」。暗夜星辰主题下 = 白底发光。审计报告已记为 announcements 4 处(插件审计报告.md:189)
D4钩子在正文区输出 <link> + <script>hook/announcements_display.php:19-20<script> 无 defer,阻塞解析;且资源标签落在 body 中部


2. 设计原则(5 条硬约束)

  1. 零内联:配色走 class(ann-style-*),图标写字面量 <i class="fa mn-fs-16">&#xf0a1;</i>。

⚠️ 不用 $view->icon() —— 它返回值恒带 style="font-size:Npx",是零内联门禁的漏网点(规范 §9.3 模板本身就有这个毛病)。

  1. **颜色一律 --mn-* 变量 + fallback**(§11.7)。已实测 10/10 样式源都有定义的:

--mn-bg-card / --mn-border / --mn-border-light / --mn-text / --mn-text-secondary /

--mn-text-muted / --mn-primary / --mn-primary-subtle / --mn-success / --mn-warning /

--mn-error / --mn-shadow-sm / --mn-bg-body / --mn-bg-input / --mn-tag-bg。

⚠️ --mn-danger 不存在(0/10),别用;要红色用 --mn-error。

  1. 向后兼容:style 字段语义不变(仍是配色),老数据 green/red/blue 渲染结果逐像素不变;

新增列全部有 DEFAULT,老行自动取值。

  1. 极简:默认不出现无意义控件 —— 无 url 不出链接/箭头;只有 1 条不出切换器;布局本身不需要关闭按钮的就不给。
  2. 不动核心:不新增钩子、不改 app/。现有 3 个注入点够用。

3. 样式体系设计(核心)

3.1 两个正交维度

                    条目布局(每条 1 个)              配色(每条 1 个)
容器模式(全局 1 个)  ── 一条公告「长什么样」    ×    ── 强调色是什么
  └ 多条公告「怎么排」

为什么拆两维而不是做「样式模板」:模板是「布局 × 配色」的笛卡尔积,12 个模板 = 12 份 CSS 且不能混搭;

两维只需 5 份布局 CSS + 13 份配色变量,任意组合且 CSS 不膨胀。

3.2 容器模式(全局,announcement_mode,5 种)

key名称形态条目布局是否生效状态
normal堆叠多条纵向排列,各自可关✅ 生效现有
scroll上下滚动单条轮播,4s 切换,无控件✅ 生效现有
carousel箭头轮播单条轮播 + ‹ › 箭头 + 圆点指示器 + 自动播放 + hover 暂停✅ 生效新增
list公告列表卡一个卡片容器,多条各占一行(图标 + 文本 + 日期 + ›),可折叠❌ 忽略新增
marquee横向跑马灯单行横向滚动(纯 CSS animation)❌ 忽略新增

carousel 就是图 1(FlatBB)右侧那对箭头的正确归属 —— 它是「多条怎么排」,不是「一条长什么样」。

3.3 条目布局(每条,layout 字段,6 种)

L1 notice — 通知条(图 1 FlatBB 同款)

┌────────────────────────────────────────────────────────────────┐
│  🔊  Notice:  站点将于今晚 23:00 维护    2026-09-06      ‹  ›  │
└────────────────────────────────────────────────────────────────┘

  • 容器:--mn-bg-card 底 + --mn-border 细边 + 圆角 999px(胶囊),padding: 9px 18px
  • 左:图标(默认 announcement 喇叭,16px,色 = 强调色)
  • 前缀标签:加粗 + 强调色,文案取全局设置 announcement_label(默认「公告」)
  • 正文:--mn-text,600 字重
  • 右:日期(--mn-text-muted,13px,取 created_at 的 Y-m-d)
  • 最右:‹ › 箭头(仅当 mode=carousel 且条数 > 1)
  • 无 ×(图 1 没有)

L2 badge — 标签式(图 2 XIUNOX 同款)

┌────────────────────────────────────────────────────────────────┐
│  [ 📢 公告 ]  XIUNOX站点出错了怎么办?怎么反馈 Bug?            │
└────────────────────────────────────────────────────────────────┘

  • 容器:--mn-bg-card 底 + --mn-border 细边 + 圆角 8px,padding: 8px 14px
  • 左:实心圆角色块徽章(底 = 强调色,白字,圆角 6px,padding: 4px 10px,内为 14px 图标 + 标签文案)
  • 右:文本,色 = 强调色,hover 下划线(整条可点,有 url 时)
  • 无 ×、无日期(图 2 没有)

L3 bar — 经典条(现有默认,视觉不变)

┌────────────────────────────────────────────────────────────────┐
│  站点将于今晚 23:00 维护,预计 30 分钟。                    ×  │
└────────────────────────────────────────────────────────────────┘

  • 完全沿用 assets/style.css:2 的现有定义 → 老数据零视觉变更
  • 配色决定整条「底色 + 边框 + 文字色」

L4 minimal — 极简左边框

┃ 站点将于今晚 23:00 维护,预计 30 分钟。

  • 无图标、无边框、无背景;左侧 4px 强调色竖条(border-left),圆角 0
  • 文字 --mn-text;最不打扰的一种,适合「常驻但不抢眼」

L5 alert — 图标提示条(类 Bootstrap alert)

┌────────────────────────────────────────────────────────────────┐
│  ( ⓘ )   站点维护通知                                     ×    │
│          今晚 23:00–23:30 暂停访问                              │
└────────────────────────────────────────────────────────────────┘

  • 左:36px 圆形强调色底 + 白图标
  • 右侧两行:标题(title 字段,粗,--mn-text)+ 描述(content,--mn-text-secondary)
  • 右:× 关闭
  • ⚠️ 需要新字段 title

L6 card — 图文卡片

┌────────────────────────────────────────────────────────────────┐
│  [ 📰 ]   站点全面升级 FlintHub                        查看 →  │
│           基于 PHP + SplitDB 的新一代社区系统                   │
└────────────────────────────────────────────────────────────────┘

  • 左:48px 方形圆角强调色淡底(--mn-primary-subtle 类)+ 强调色图标
  • 右:标题(title)+ 一行摘要(content 截断,Content::excerpt)
  • 最右:查看 →(有 url 才出现)
  • ⚠️ 需要新字段 title

3.4 配色(每条,style 字段,13 种)

配色统一只定义 4 个 CSS 变量:--ann-accent(强调色)/ --ann-bg / --ann-border / --ann-text。

布局类决定怎么用这 4 个变量 → 布局 × 配色 = 6 × 13 = 78 种组合,零额外 CSS。

key名称来源状态
yellow / red / gray / bluegray / blue / green现有 6 色硬编码保持原值(向后兼容,视觉零变更)现有
theme跟随主题全用 --mn-*(--mn-bg-card / --mn-border / --mn-text / --mn-primary)→ 暗色主题自动适配新增(推荐默认)
primary主题主色--mn-primary / --mn-primary-subtle新增
success成功绿--mn-success新增
warning警告黄--mn-warning新增
danger危险红--mn-error新增
dark深色通栏#1f2937 底 + 白字(不随主题变)新增

设计要点:notice / badge / minimal / alert / card 这 5 种布局的底色统一走 --mn-bg-card,

配色只决定强调色(图标/徽章/左边框/链接色)。这样:

① 暗色主题下这 5 种布局天然可读(不会白底发光);② 配色切换只换强调色,观感克制。

3.5 图标(每条,icon 字段,新增)

  • 下拉选 20 个已在核心 $map 内的公告向图标(已实测 448 字形子集全覆盖):

announcement(喇叭) / bell / info / warning / newspaper / flag / lightbulb / rocket /

gift / star / tag / tags / heart / comment / book-open / clock / calendar /

check / plus / fire

  • 空值 → 按布局给默认(notice/badge/alert → announcement;card → newspaper;minimal/bar → 无图标)
  • ⚠️ 只从 $map 里挑,不自造码点(陷阱 §A.14:自造码点 = 静默方块,须重跑 build_font_subset.py)

3.6 其余行为约定

项约定
前缀标签文案全局设置 announcement_label(默认「公告」);notice 布局默认显示为 公告:
日期取 created_at → Y-m-d;仅 notice / list 显示
关闭按钮bar / alert 有;其余无(跟随参考图)
关闭行为保持现状:前端 dismiss,不持久化(刷新重现)
链接url 非空才渲染 <a>;target="_blank" rel="noopener" 保持
转义保持 Content::decode() + htmlspecialchars(..., ENT_QUOTES, 'UTF-8')
移动端notice 在 ≤768px 隐藏日期与箭头(flex-wrap 兜底);alert/card 图标缩到 32px


4. 数据模型变更

ALTER TABLE announcements ADD COLUMN layout TEXT NOT NULL DEFAULT 'bar';   -- 条目布局
ALTER TABLE announcements ADD COLUMN icon   TEXT NOT NULL DEFAULT '';      -- 图标名(空=按布局默认)
ALTER TABLE announcements ADD COLUMN title  TEXT NOT NULL DEFAULT '';      -- alert/card 的标题行

迁移方式(三步,缺一即静默失效 —— 规范 §11.33 / 陷阱 142):

  1. Plugin.php 的 ddl() 里的 CREATE TABLE 同步加上这 3 列(只对新装站点生效);
  2. 新增 ensureColumnPatches():PRAGMA table_info 判存在 → 缺则 ALTER TABLE ADD COLUMN(对存量库生效,幂等);
  3. 改门控标记:现有 hook/init_after.php:14 用 Settings::get('_announcements_migrated') 门控

→ 改成 _announcements_schema_v = '2'(值随版本变,否则老站覆盖上传后补丁根本不跑)。

⚠️ 现有 init_after.php 无「戳文件」门控,每次请求都跑一遍 activate()(内含 CREATE TABLE IF NOT EXISTS)

→ 已超「单插件每请求所有 hook 查询总和 ≤ 5」红线。本次顺带补上戳文件门控(照 points_mall / qa 范式)。


5. 文件改动清单

文件改动量级
plugins/announcements/Plugin.php新增 LAYOUTS / ICONS 常量与 getLayouts() / getIcons();getStyles() 扩到 13 项;add()/update() 增 3 参;新增 ensureColumnPatches();SCHEMA_VERSION = 2~+120 行
plugins/announcements/hook/announcements_display.php按 mode 分流 5 种容器;按 layout 渲染 6 种条目;<script> 加 defer重写,~+160 行
plugins/announcements/hook/init_after.php改门控标记 + 戳文件 + 调 ensureColumnPatches()~+25 行
plugins/announcements/assets/style.css新增 5 种布局 CSS + 7 组配色变量 + 容器模式 CSS;把现有 6 色抽成 4 变量;修 D3(D2 的弹窗样式保留)~+260 行
plugins/announcements/assets/script.jscarousel(箭头/圆点/自动播放/hover 暂停);现有 scroll 的 style.display 改 class(去内联);list 折叠~+90 行
plugins/announcements/views/admin.php新增「布局 / 图标 / 标题」表单控件 + 布局缩略预览;全局「展示模式」下拉扩到 5 项 + 「标签文案」输入;弹窗移入 .admin-content(修 D2)~+130 行
plugins/announcements/AdminController.php白名单校验新字段;setMode 扩到 5 值;新增 setLabel~+40 行
plugins/announcements/lang/{zh,en,zh_tw}.php新增 ~26 个键(5 模式 + 6 布局 + 13 配色名 + 图标名 + 提示)三语同步
plugins/announcements/plugin.jsonversion → 1.4.01 行
plugins/announcements/说明.md按实现重写(修 D1)重写

不改动:app/ 任何文件、assets/css/*、其他插件。


6. 后台 UI 设计

┌─ 站点公告管理 ────────────────────────────────────────────────┐
│                                                               │
│ ① 添加公告                                                    │
│   内容 *  [__________________________]                        │
│   标题    [__________________]  ← 仅 alert / card 布局用      │
│   链接    [https://...]                                       │
│   条目布局 [经典条 ▾]   配色 [跟随主题 ▾]   图标 [🔊 喇叭 ▾]  │
│   排序     [0]                                                │
│           ┌──────────────────────────────────────────────┐    │
│           │ 🔊 公告:  预览文本…             2026-10-11   │    │  ← 实时预览
│           └──────────────────────────────────────────────┘    │
│                              [ 添加公告 ]                     │
│                                                               │
│ ② 展示设置(全局)                                            │
│   展示模式 [箭头轮播 ▾]   标签文案 [公告]   [ 保存 ]          │
│   提示:箭头轮播 / 列表卡 / 跑马灯 会忽略每条公告的条目布局    │
│                                                               │
│ ③ 已有公告(共 3 条)                                         │
│   [经典条·浅绿] 本站全面升级 FlintHub…        [编辑] [删除]   │
│   …                                                           │
└───────────────────────────────────────────────────────────────┘

布局选择器要点:下拉每项显示「名称 + 一句话说明」;下方给实时预览条(用当前表单值渲染,纯 CSS,无网络请求)。

选 list / marquee 容器模式时,条目布局下拉置灰并提示「该模式下不生效」(避免「选了没反应」的困惑)。


7. 风险与红线(写代码时必须逐条对)

#风险对策
R1零内联:$view->icon() 带内联 style图标一律写字面量 <i class="fa mn-fs-16">&#xf0a1;</i>
R2暗色主题白底发光(D3 同类)新布局底色全走 --mn-bg-card;--mn-danger 不存在,红用 --mn-error
R3改 CSS 后用户拿不到新样式?v=filemtime 已具备(announcements_display.php:16-17),保持
R4插件 CSS 早于核心注入(main.php:40)同权重核心后胜 → 只写核心没定义的属性;隐藏类一律 display:none !important
R5钩子文件声明顶层符号 → 双触发静默丢一次announcements_display 被规范列为双触发钩子(插件开发规范.md:1989)→ 钩子文件所有逻辑写在顶层语句,不包函数
R6同一页面出现重复 id新布局的箭头/圆点容器 id 加渲染序号(陷阱 50 范式)
R7游客页永久缓存导致「改了没生效」改完必须清 data/runtime/pages/*.html;⚠️ 先查 sessions.sqlite 有无近几分钟会话,站长在浏览时不清
R8新增列对老库无效三步迁移(§4),并回读 PRAGMA table_info + 标记文件内容验证
R9后台保存静默写最小值数值/文本键用 array_key_exists() 判缺失即跳过(陷阱 75)
R10i18n 三语键不一致新增 ~26 键三语同步,键集合零差异 + 键序一致,跑 fh_i18n_check.php
R11改动影响正在运行的生产站本机先跑通;出包走增量包流程;.htaccess 只拦 plugins/*/data/,assets 可直读
R12list 模式下的「每条配色」列表卡每行用自己的强调色(小圆点/图标着色),不做整卡换色


8. 分阶段实施计划(建议)

P0 — 骨架 + 二维模型落地(最小可用)

  • 数据模型三步迁移(layout / icon / title)
  • Plugin.php 常量与取值函数;AdminController 校验
  • hook/announcements_display.php 按 layout 分流,先实现 bar(现有)+ badge(图 2)+ notice(图 1)
  • CSS:抽 4 变量 + 3 种布局
  • 后台:3 个新控件 + 预览条
  • 验收:老 3 条数据渲染逐像素不变;图 1 / 图 2 效果可复现

P1 — 容器模式扩充

  • 新增 carousel(箭头/圆点/自动播放)、list、marquee
  • 后台「展示模式」下拉 5 项 + 联动置灰
  • 验收:5 种模式各跑一遍;单条时不出现切换器;hover 暂停生效

P2 — 布局与配色补全 + 既有缺陷整改

  • 新增 minimal / alert / card 布局
  • 配色扩到 13 项(含 theme 跟随主题)
  • 修 D1(重写 说明.md)、D2(弹窗移入 .admin-content)、D3(配色变量化)、D4(defer)
  • 验收:暗夜星辰主题下 6 种布局逐一走查可读

P3(可选,需你拍板)— 全站通栏注入

  • 新增 layout_body_end 注入点,让公告可显示在全站每页顶部(不限于 3 个列表页)
  • ⚠️ 代价:游客页永久缓存会缓存公告 → 每次改公告都要清缓存;且会出现在后台页(需按 template 排除)

工作量粗估:P0 ≈ 半天,P1 ≈ 半天,P2 ≈ 半天,P3 ≈ 2 小时。总计 1.5~2 个工作日(不含你验收与出包)。


9. 验证方案

层手段断言要点
静态php -l(8.2 + 8.0 双版本)零语法错误
静态plugin_hygiene.py三语键 / 零内联 / BOM / CRLF / hooks 文件存在,FAIL = 0
静态fh_i18n_check.php视图引用键 ↔ 三语字典零缺失
静态`grep -nE '<style\<script>\
静态CSS 变量核对脚本新增 CSS 里每个 var(--x) 都在 10 个样式源有定义
逻辑CLI 探针迁移幂等(跑两次列数不变);getLayouts/getStyles/getIcons 白名单过滤;非法 layout/icon 回落默认
HTTP真实请求 3 个注入页每页含公告;id 唯一;&#xf128;(问号兜底)出现 0 次
HTTP后台页3 个新控件渲染;保存后同时回读 DB + settings_cache.php;非法值被拒
反证A/B老 3 条数据在改动前后渲染 HTML 逐字节比对(证明向后兼容)
视觉交你自测浅色 + 暗夜星辰双主题、PC + 移动端


10. 待你拍板的 6 个点

#问题我的建议
Q1增强现有插件,还是新建一个(如 notice_bar)?增强现有 —— 避免两套公告功能并存;老数据零迁移
Q2采用二维模型(容器模式 × 条目布局),还是单一「样式模板」下拉?二维 —— 灵活且 CSS 不膨胀;后台只是多两个下拉
Q3图 1 的 ‹ › 箭头归到「容器模式 carousel」还是「布局 notice 自带」?容器模式 —— 箭头是「多条怎么排」,单条时不该出现
Q4保留现有 6 个硬编码浅色配色吗?保留(向后兼容,视觉零变更)+ 新增 7 个变量化配色,并把 theme 设为新公告默认
Q5新增 title 字段(alert / card 需要标题行)吗?新增 —— 不加的话这两种布局只能拿正文首行当标题,很脏
Q6要不要做 P3「全站通栏」?先不做 —— 与游客页缓存冲突,且你现在的公告只挂 3 个列表页


附:两张参考图的样式归属

参考图特征本方案对应
图 1(FlatBB Notice)白底胶囊 + 🔊 喇叭 + 橙色加粗 Notice: + 正文 + 日期 + 右侧 ‹ ›layout = notice + mode = carousel + style = warning
图 2(XIUNOX 公告)白底细边 + 蓝色实心圆角「📢 公告」徽章 + 蓝色链接文本layout = badge + mode = normal + style = primary

轻量级、高性能、零 MySQL 依赖的PHP社区系统。
| Views 5 | Replies 0

All Replies (0)

No replies yet

Please Log in