在线收音机内容管理
详情介绍
在线收音机插件(onlineRadio)使用文档
版本:1.0.0 | 作者:kuakeba.cn
一、插件简介
把整个站点变成一台车载收音机:访客在 87.5–108.0MHz(国内 FM 调频标准频段)上调频收听网络电台,站内翻页时音乐不中断。
- 像真机一样调频:上一个 / 播放暂停 / 下一个 三个按钮,频率数字逐格跳动
- 空号段自动跳过(在 87.5 按「下一个」直接跳到下一个有台的频率),到频段首尾自动循环
- 手输频率:
98.5、985、FM98.5、98.5MHz均可,回车即跳转;该频率空号时提示并自动落到最近电台 - 状态反馈:播放中 / 缓冲中 / 无信号 / 已被屏蔽,配合呼吸灯;音量可调
- 换页不断:站内跳转采用局部换页,播放器不被销毁,音乐持续播放
- 位置:电脑端、手机端固定悬浮在页面正下方(适配安全区),可点 × 在本次访问中临时隐藏
- 记忆:上次频率、音量、播放状态记在本地,刷新后自动恢复
二、环境要求
| 项目 | 要求 |
|---|---|
| Zsens Admin | 含社区(community)前台 |
| 主题 layout | 需输出 {:plugin_assets()} 钩子(宿主 view/front/layout.html 与 pansou、duanju 主题均已包含) |
| 浏览器 | 支持 HTML5 Audio、fetch、DOMParser、history.pushState 的现代浏览器(PC / 移动端 / 各主流内核) |
| 音频源 | 推荐 HTTPS 直链音频流(mp3 / aac)。站点为 HTTPS 时使用 HTTP 流会被浏览器按混合内容拦截 |
插件为纯前端插件:不建数据表、不注册后台接口,仅在主题 {:plugin_assets()} 位置注入播放器 DOM 与 CSS/JS。
三、安装步骤
- 将
onlineRadio目录整体放入项目plugins/下 - 进入后台 应用中心,找到「在线收音机」,点击 安装
- 安装时自动把
plugins/onlineRadio/static/复制到public/static/onlineRadio/ - 进入 应用中心 → 在线收音机 → 配置,按需调整配置项
- 前台打开任意社区页面,即可看到页面底部悬浮的收音机面板
插件通过前台渲染钩子自动挂载,无需修改主题模板。若前台不显示,请先确认配置中的总开关为开启状态。
四、配置项说明
后台 应用中心 → 在线收音机 → 配置:
| 配置项 | 键名 | 默认值 | 说明 |
|---|---|---|---|
| 启用在线收音机 | enabled | 开启 | 总开关。关闭后前台不再注入播放器 DOM,也不加载 CSS/JS |
| 默认频率 | default_freq | 98.5 | 首次访问时停留的频率,取值 87.5–108.0;超出范围自动回退 98.5 |
| 电台列表(JSON) | stations_json | 16 个内置电台 | JSON 数组,格式见下节。为空或解析失败时回退内置默认电台表 |
五、电台列表配置
stations_json 为 JSON 数组,每项三个字段:
[
{ "f": 98.5, "name": "Beat Blender · 深夜浩室", "url": "https://ice1.somafm.com/beatblender-128-mp3" },
{ "f": 100.3, "name": "KEXP · 西雅图另类", "url": "https://kexp-mp3-128.streamguys1.com/kexp128.mp3" }
]| 字段 | 类型 | 说明 |
|---|---|---|
f | number | 频率,一位小数,取值 87.5–108.0,代表该台在刻度盘上的位置 |
name | string | 台名,显示在频率下方,建议「台名 · 风格」格式 |
url | string | 音频流地址,推荐 HTTPS 直链 mp3 / aac,需支持跨域直接播放 |
校验规则:
f会被规整为一位小数;不在 87.5–108.0 范围内、或name/url为空的行直接忽略- 电台列表按
f升序排序后输出,输入顺序不影响显示 - 整表为空或 JSON 解析失败时,自动回退到内置的 16 个默认电台
- 只能配置单频点电台;不带小数点的整数频点会被规范为
.0(如98→98.0)
建议:内置默认电台为境外流(SomaFM / Radio Paradise / FIP / KEXP 等),用于演示与开箱可用。正式运营建议替换为面向国内网络优化的电台直链,以获得更稳定的连接与更低的缓冲时间。
六、前台使用说明
1、面板结构
| 区域 | 说明 |
|---|---|
上一个(or-prev) | 向低频方向扫描,自动跳过空号段 |
播放 / 暂停(or-toggle) | 播放时显示暂停图标,暂停时显示播放图标 |
下一个(or-next) | 向高频方向扫描,自动跳过空号段 |
| 液晶屏 | 状态灯 + 状态文字;频率输入框(单位 MHz);当前台名 |
音量(or-vol) | 滑杆,0–100,默认 80 |
×(or-close) | 本次访问内隐藏面板;隐藏后右下角出现「收音机」按钮(or-reopen)可随时唤回 |
2、调频规则
- 频段:87.5 – 108.0,步长 0.1
- 按「上一个 / 下一个」时,从当前频率出发跳过所有空号段,直接落到下一个/上一个有台的频率
- 到达频段首尾自动循环(87.5 继续上一个会绕到频段高端;108.0 继续下一个会绕到频段低端)
- 换台时频率数字逐格滚动跳动,到达目标后开始加载音频
3、手输频率
在频率输入框内输入后按回车即跳转,以下写法均被识别:
| 输入 | 解析结果 | 说明 |
|---|---|---|
98.5 | 98.5 | 标准写法 |
985 | 98.5 | 三位整数按 ×0.1 解析 |
9850 | 98.5 | 四位整数按 ×0.01 解析 |
98 | 98.0 | 落在 87.5–108.0 区间内时按原值取整频点 |
FM98.5 | 98.5 | 自动忽略 FM、MHz 等前后缀与非数字字符 |
98.5MHz | 98.5 | 同上 |
异常处理:
- 格式无效或超出频段:输入框抖动并提示「频率无效,请输入 87.5 – 108.0 之间的频率」,随后恢复为当前频率
- 该频率空号:提示「FM90.0 无信号,已收到 FM89.8 · Radio Swiss Pop · 瑞士流行」,并自动落到最近的电台
4、状态灯含义
| 状态文字 | 灯效 | 含义 |
|---|---|---|
| 播放中 | 绿灯呼吸 | 音频正常播放 |
| 缓冲中 | 黄灯快闪 | 正在建立连接或等待数据 |
| 无信号 | 红灯常亮 | 音频流加载失败(地址失效、被墙、断网等) |
| 已被屏蔽 | 灰灯常亮 | HTTPS 站点加载 HTTP 音频流,被浏览器按混合内容拦截 |
| 待机 | 灰灯常亮 | 已调准频率但未播放,或自动播放被浏览器策略拦截 |
5、记忆与恢复
| 存储位置 | 键 | 内容 | 生效范围 |
|---|---|---|---|
| localStorage | or_freq | 上次频率 | 长期,刷新 / 重开浏览器均恢复 |
| localStorage | or_vol | 上次音量 | 长期 |
| localStorage | or_playing | 上次播放状态(1 / 0) | 长期,刷新后自动续播 |
| sessionStorage | or_hidden | 本次访问是否隐藏面板(1) | 仅当前标签页会话 |
说明:
- 刷新页面会自动恢复上次频率与音量;若上次处于播放状态,会尝试自动续播
- 浏览器「自动播放策略」可能拦截自动播放,此时状态降级为「待机」,用户点一次播放按钮即可正常收听(播放状态会被重置为
0,避免每次刷新反复尝试) - 点 × 隐藏仅在本次访问内有效,关闭标签页后重新打开会自动恢复显示
6、换页不断(局部换页)
插件拦截站内同源链接,只替换页面主体容器,播放器位于容器之外,因此不被销毁,音乐全程连续播放。
- 容器优先级:
#or-pjax(主题可在主体容器上声明该 id)→ 回退main - 支持浏览器前进 / 后退(
popstate同样走局部换页) - 换页后自动重新执行新页面内的
<script>(同src的脚本会去重,避免重复加载) - 局部换页失败、或页面缺少可用容器时,自动回退为整页跳转,不影响任何既有功能
不参与局部换页的链接(自动走整页跳转):
- 跨域链接,以及
javascript:/mailto:/tel:/data:/blob:协议 - 带
target且不为_self的链接、带download属性的链接 - 指向静态资源文件(
.php / .xml / .txt / .json / .css / .js / 图片 / 音视频 / 压缩包 / 文档等)的链接 - 以下路径前缀:
/admin、/login、/register、/logout、/captcha、/download-guard、/member、/user、/users、/vip、/pay、/payment、/api、/attach、/uploads、/static - 下载守卫入口(位于
[data-dg-open]内的链接,交由下载守卫插件自行处理) - 播放器自身范围内的链接
如需让某个链接强制整页跳转,给该 <a> 标签加 data-or-full 属性即可。
其他插件如需在局部换页完成后执行逻辑,可监听 document 上的自定义事件 or:pjax(event.detail.url 为新页面地址)。
7、与其他插件的兼容性
- 下载守卫(download_guard):守卫入口链接被显式排除在局部换页之外,下载流程完全不受影响;守卫的弹窗与提示逻辑运行在
document级事件委托上,换页后依然生效 - 主题样式:面板固定定位在最上层(
z-index高于常规内容),并为页面底部预留 92px(移动端 104px)空间,避免遮挡页脚 - 性能:播放器 DOM 与资源全站只注入一次;JS 以
defer方式加载、不阻塞首屏渲染;音频节点preload="none",未点播放前不产生流量消耗
七、目录结构
plugins/onlineRadio/
├── plugin.json 插件元信息
├── OnlineRadioPlugin.php 电台表解析校验、后台配置表单、前台资源注入
├── static/
│ ├── radio.css 播放器样式(悬浮定位、液晶屏、呼吸灯、安全区、移动端适配)
│ └── radio.js 调频状态机、手输频率解析、局部换页引擎、本地记忆
└── README.md 本文档安装后静态资源会发布到 public/static/onlineRadio/,前台按 /static/onlineRadio/radio.css、/static/onlineRadio/radio.js 引用。
八、常见问题
1. 前台看不到收音机面板?
- 确认后台配置中「启用在线收音机」为开启
- 确认所用主题的
layout.html中存在{:plugin_assets()}钩子 - 确认
public/static/onlineRadio/下存在radio.css与radio.js(缺失时对插件执行「升级」或重新安装以发布) - 强制刷新浏览器缓存(
Ctrl+F5)
2. 点了播放没声音,状态显示「待机」?
浏览器的自动播放策略拦截了自动播放。手动点击播放按钮即可(首次交互后同一会话内不再受限制)。若手动点击后仍无声音,请检查电台流地址是否有效、是否被网络限制。
3. 状态显示「已被屏蔽」?
站点为 HTTPS,而电台流地址是 HTTP,被浏览器按混合内容拦截。请把该电台的 url 换成 HTTPS 地址。
4. 状态显示「无信号」?
该电台流地址已失效、被网络限制访问,或本地网络异常。可在浏览器直接访问该流地址验证,或后台更换电台。
5. 换页后音乐中断了?
该链接命中了局部换页排除规则(如 /member、/vip、/download-guard 等),或目标页缺少 main / #or-pjax 容器,已按设计回退为整页跳转。属于预期行为,不影响站点功能。
6. 想新增 / 替换电台?
后台 配置 → 电台列表(JSON) 编辑即可,保存后刷新前台页面生效。注意 JSON 必须合法(逗号、引号、括号),非法时插件会自动回退内置默认电台。
7. 修改了 plugins/onlineRadio/static/ 下的文件不生效?
静态资源在安装时复制到 public/static/onlineRadio/。修改源文件后,请在后台对插件执行「升级」,或手动把文件复制到 public/static/onlineRadio/,并强制刷新浏览器缓存。
8. 收音机会遮挡页面底部的按钮或页脚吗?
不会。插件为 html 添加 or-space 标记,为 body 预留底部空间(PC 92px / 移动端 104px),并适配 iOS 安全区(env(safe-area-inset-bottom))。若主题对底部做了特殊定制,可点 × 临时隐藏面板。
9. 用户把面板隐藏后找不回来?
隐藏是本次访问级的(存在 sessionStorage),关闭标签页重新打开即恢复;本次访问内可点右下角「收音机」悬浮按钮随时唤回。
版本历史
| 版本 | 日期 | 说明 |
|---|---|---|
| 1.0.0 | 2026-10-19 | 初始版本:87.5–108.0MHz 调频、空号段自动跳过与首尾循环、手输频率智能解析与最近台回落、四态呼吸灯、音量调节、局部换页持续播放、频率 / 音量 / 播放状态本地记忆、本次访问隐藏与唤回 |
更新记录 (1)
-
v1.0.0
2026-10-19
正式发布
QQ官方交流群