在线收音机

在线收音机内容管理

版本 v1.0.0· 胡思乱想 · 2 次获取 · 内容管理
把整个站点变成一台**车载收音机**:访客在 87.5–108.0MHz(国内 FM 调频标准频段)上调频收听网络电台,站内翻页时音乐不中断。
¥1.00抵扣
一次购买,永久使用

详情介绍

在线收音机插件(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。

三、安装步骤

  1. 将 onlineRadio 目录整体放入项目 plugins/ 下
  2. 进入后台 应用中心,找到「在线收音机」,点击 安装
  3. 安装时自动把 plugins/onlineRadio/static/ 复制到 public/static/onlineRadio/
  4. 进入 应用中心 → 在线收音机 → 配置,按需调整配置项
  5. 前台打开任意社区页面,即可看到页面底部悬浮的收音机面板
插件通过前台渲染钩子自动挂载,无需修改主题模板。若前台不显示,请先确认配置中的总开关为开启状态。

四、配置项说明

后台 应用中心 → 在线收音机 → 配置:

配置项键名默认值说明
启用在线收音机enabled开启总开关。关闭后前台不再注入播放器 DOM,也不加载 CSS/JS
默认频率default_freq98.5首次访问时停留的频率,取值 87.5–108.0;超出范围自动回退 98.5
电台列表(JSON)stations_json16 个内置电台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" }
]
字段类型说明
fnumber频率,一位小数,取值 87.5–108.0,代表该台在刻度盘上的位置
namestring台名,显示在频率下方,建议「台名 · 风格」格式
urlstring音频流地址,推荐 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.598.5标准写法
98598.5三位整数按 ×0.1 解析
985098.5四位整数按 ×0.01 解析
9898.0落在 87.5–108.0 区间内时按原值取整频点
FM98.598.5自动忽略 FM、MHz 等前后缀与非数字字符
98.5MHz98.5同上

异常处理:

  • 格式无效或超出频段:输入框抖动并提示「频率无效,请输入 87.5 – 108.0 之间的频率」,随后恢复为当前频率
  • 该频率空号:提示「FM90.0 无信号,已收到 FM89.8 · Radio Swiss Pop · 瑞士流行」,并自动落到最近的电台

4、状态灯含义

状态文字灯效含义
播放中绿灯呼吸音频正常播放
缓冲中黄灯快闪正在建立连接或等待数据
无信号红灯常亮音频流加载失败(地址失效、被墙、断网等)
已被屏蔽灰灯常亮HTTPS 站点加载 HTTP 音频流,被浏览器按混合内容拦截
待机灰灯常亮已调准频率但未播放,或自动播放被浏览器策略拦截

5、记忆与恢复

存储位置键内容生效范围
localStorageor_freq上次频率长期,刷新 / 重开浏览器均恢复
localStorageor_vol上次音量长期
localStorageor_playing上次播放状态(1 / 0)长期,刷新后自动续播
sessionStorageor_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.02026-10-19初始版本:87.5–108.0MHz 调频、空号段自动跳过与首尾循环、手输频率智能解析与最近台回落、四态呼吸灯、音量调节、局部换页持续播放、频率 / 音量 / 播放状态本地记忆、本次访问隐藏与唤回


更新记录 (1)

  • v1.0.0 2026-10-19
    正式发布
微信客服 微信客服 QQ官方交流群 QQ官方交流群