# 声明式插件开发指南(A 型) > 本文档面向**声明式插件**:只有一份 `plugin.json`,用 `hooks` 描述"要往哪里注入什么", > 由内核解释执行。**无需写代码、无需编译**,适合轻量扩展。 > > 需要独立页面、数据表、后台菜单、定时任务?请改用**应用型插件** → [PLUGIN-APP.md](PLUGIN-APP.md)。 > 通用部分(打包、安装、配置项、权限、调试)见 [PLUGIN.md](PLUGIN.md)。 --- ## 1. 插件包结构 ``` your-plugin.zip ├── plugin.json # 必需:插件清单(放在根目录或任意子目录均可) └── (可选)其他静态资源,如 @片段.html ``` 打包要求: - 必须是 zip 格式,`plugin.json` 需为 **UTF-8 无 BOM** - 插件名(`name`)会被用作目录名,建议避免 `/`、`\` 等字符 - 单包不超过 50MB - 各系统打包命令、开发调试循环(全程无需源码)见 [PLUGIN.md](PLUGIN.md) 2.0 节 安装后在后台「插件管理」点击**启用**才生效。 --- ## 2. plugin.json 完整字段 ```json { "name": "插件名(必需,唯一)", "version": "1.0.0", "author": "作者", "description": "一句话说明", "requires": "2.0.0", "config": [ ... ], "hooks": [ ... ] } ``` | 字段 | 必填 | 说明 | |---|---|---| | `name` | ✅ | 插件名,同时作为安装目录名 | | `version` | | 版本号,展示用 | | `author` | | 作者名 | | `description` | | 简介,展示在插件列表与插件市场 | | `requires` | | 建议的最低表白墙版本(不满足时后台显示 ⚠,不阻止启用) | | `config` | | 配置项声明,见第 3 节 | | `hooks` | ✅ | 钩子列表,见第 4 节 | > 清单里**不要**写 `kind` 字段(那是应用型插件的标识);写了 `"kind": "app"` 会走另一套运行时。 --- ## 3. 配置项(config) 插件可以声明若干配置项,表白墙会**自动在后台「插件管理 → 插件设置」渲染表单**, 管理员填写后立即生效,无需重新安装插件。 ```json "config": [ { "key": "nicknames", "label": "专享昵称", "type": "textarea", "default": "官方,公告", "help": "多个昵称用逗号或换行分隔" }, { "key": "badge", "label": "帖子标识", "type": "text", "default": "官方" }, { "key": "enable", "label": "启用提示", "type": "switch", "default": "1" }, { "key": "position", "label": "显示位置", "type": "select", "default": "bottom", "options": ["top", "bottom"] } ] ``` | 字段 | 说明 | |---|---| | `key` | 字段名,供 `{config:key}` 引用 | | `label` | 后台表单里显示的名称 | | `type` | `text` / `textarea` / `switch`(值 `1`/`0`)/ `select` / `number` / `audio`(音频上传)/ `file` | | `default` | 未配置时的默认值 | | `help` | 表单下方的说明文字 | | `options` | 仅 `select` 使用,候选项数组 | ### 上传型字段(audio / file) `type: "audio"` 会渲染成「试听 + 选择文件」的上传控件,保存后配置值即为文件的可访问地址 (形如 `/uploads/plugins/<插件名>/audio-xxxxxxxx.mp3`),可直接用于 `{config:key}`: ```json { "key": "music", "label": "背景音乐文件", "type": "audio", "default": "", "help": "支持 mp3 / m4a / aac / ogg / opus / wav / flac,单个文件不超过 20MB" } ``` - 文件名由服务端生成,不使用上传时的原始文件名 - 重新上传或勾选「删除」会自动清理旧文件 - 配置值会被清除引号与尖括号等危险字符 —— 因为它会被原样注入页面 ### 在钩子里引用配置 任意字符串字段都支持 `{config:字段名}` 占位符,运行时替换为管理员填写的值: ```json { "hook": "compose_guard", "type": "guard", "nicknames": "{config:nicknames}", "label": "{config:badge}" } ``` ```json { "hook": "footer_html", "type": "html", "html": "" } ``` 配置值保存在 `settings` 表(键名 `plugin.<插件名>.<字段名>`),随站点一起备份。 --- ## 4. 钩子一览 `hooks` 是一个数组,每个元素至少包含 `hook` 与 `type`: | type | hook | 作用 | 关键字段 | |---|---|---|---| | `html` | `header_html` | 前台页面 `` 后(body 起始处)注入 HTML | `html` | | `html` | `footer_html` | 前台页面页脚注入 HTML | `html` | | `html` | `admin_plugins_top` | 后台「插件管理」页顶部注入 HTML | `html` | | `filter` | `content_filter` | 用正则改写帖子 / 评论内容 | `match`、`replace` | | `http` | `post_created` | 发帖成功后回调 Webhook | `url` | | `http` | `comment_created` | 评论后回调 Webhook | `url` | | `http` | `report_created` | 举报后回调 Webhook | `url` | | `guard` | `compose_guard` | **发帖前置守卫**:命中昵称时强制验证后台账号 | `nicknames`、`require`、`label`、`message` | | `badge` | `post_badge` | 给指定昵称的帖子打上标识 | `nicknames`、`label` | > 内核遇到**不认识的钩子类型会跳过该钩子而不报错**,详见第 8 节"能力边界"。 ### 4.1 html:注入片段 ```json { "hook": "footer_html", "type": "html", "html": "
今天也要加油鸭
" } ``` 注入内容会被原样输出到页面,因此**可以包含 `" } ] } ``` 打包与安装(三平台打包命令见 [PLUGIN.md](PLUGIN.md) 2.0 节): ```bash cd your-plugin zip -r official-guard.zip . # macOS / Linux tar -a -c -f official-guard.zip * # Windows 10/11 自带命令 ``` 后台「插件管理 → 上传并安装」选择 zip → 点「启用」→ 在「插件设置」里填写专享昵称 → 用该昵称发帖,验证弹出管理员验证弹窗、通过后帖子带上标识。 > 表白墙内置了「管理员专享昵称」(网站设置),覆盖最常见的官方身份保护场景; > 这个插件演示的是如何用插件实现同类能力,并支持自定义标识文字与多插件组合。 ### 6.1 另一个完整例子:每日一言(注入 + 配置 + 前端 JS) 只需两个文件,演示 `footer_html` 注入、`{config:key}` 引用与注入脚本中的原生 JS: `plugin.json`: ```json { "name": "每日一言", "version": "1.0.0", "author": "yourname", "description": "在每个前台页面底部随机展示一句语录,语录可在后台配置", "config": [ { "key": "quotes", "label": "语录列表", "type": "textarea", "default": "今天也要加油鸭\n慢慢来,比较快\n你笑起来真好看", "help": "每行一句,访客每次刷新随机显示其中一条" } ], "hooks": [ { "hook": "footer_html", "type": "html", "html": "@quote.html" } ] } ``` `quote.html`(与 plugin.json 同级,避免在 JSON 里转义大段内容,见 4.2 节): ```html
``` 说明: - `{config:quotes}` 在**服务端**就替换为管理员填写的文本(`@文件` 片段同样支持占位符展开) - 多行文本放进 `type="text/plain"` 的脚本块而不是 JS 字符串字面量——字符串里出现真实换行会导致语法错误,这是注入多行配置的推荐写法 - 注入内容原样输出到页面,可以写 `