homepage 集成 Jellystat 统计小组件:配置、鉴权与数据映射深度解析
【免费下载链接】homepageA highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.项目地址: https://gitcode.com/GitHub_Trending/ho/homepage
Jellystat 是 Jellyfin 生态中常用的统计分析工具,能够记录用户的播放行为并汇总歌曲、电影、剧集等媒体库的观看次数。本文基于 homepage 开源项目(仓库根目录 README.md)的官方文档 jellystat 组件文档 与对应源码实现,完整讲解如何在 homepage 服务仪表盘中接入 Jellystat 小组件,包括 API Key 的获取、widget配置项详解、days统计时间窗口的行为,以及前端渲染到后端代理请求的完整数据链路。读完本文,你将能独立完成 Jellystat 小组件的配置与排障,并理解其底层实现原理。
一、Jellystat 小组件概览
Jellystat 小组件用于在 homepage 的服务卡片上展示媒体库在指定时间范围内的观看统计,共显示四个统计维度(即官方文档中提到的 Allowed fields:["songs", "movies", "episodes", "other"]),分别对应歌曲(Songs)、电影(Movies)、剧集(Episodes)与其他(Other)的播放次数。
官方文档明确指出:该小组件至少支持Jellystat 1.1.6及以上版本(原文档表述为 "The widget supports (at least) Jellystat version 1.1.6")。在启用组件前,你需要确保 Jellystat 服务本身已正确部署并监听一个可访问的地址。
二、获取 API Key
Jellystat 小组件属于"带凭证的代理组件",访问其统计接口需要携带 API 令牌。获取方式非常简单:
- 登录 Jellystat 的 Web 管理界面;
- 进入
Settings > API Key; - 生成(或复制)一个 API Key,将其填入 homepage 的
widget配置中。
从源码实现看,这个 Key 会被直接用作请求头中的令牌。在 credentialed 代理处理器 中,jellystat与autobrr、pulse三类组件走同一条分支,统一注入如下请求头:
} else if (["autobrr", "jellystat", "pulse"].includes(widget.type)) { headers["X-API-Token"] = `${widget.key}`; }也就是说,homepage 在代理请求 Jellystat API 时会携带X-API-Token: <你的key>,与 Jellystat 服务端校验逻辑匹配。因此配置key时不需要手动设置任何额外的请求头。
三、配置项详解
在服务(service)的 YAML 配置中,为某个服务添加如下widget块即可启用 Jellystat 小组件:
widget: type: jellystat url: http://jellystat.host.or.ip key: apikeyapikeyapikeyapikeyapikey days: 30 # optional, defaults to 30各配置项说明如下:
| 配置项 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
type | 是 | string | 无 | 固定为jellystat,用于匹配 widgets 注册表 中的组件定义 |
url | 是 | string | 无 | Jellystat 实例的访问地址,如http://jellystat.host.or.ip,末尾斜杠会被自动去除 |
key | 是 | string | 无 | 在 JellystatSettings > API Key中生成的 API Key,最终以X-API-Token请求头发送 |
days | 否 | number | 30 | 统计时间窗口(天)。必须是大于 0 的整数,否则会被强制回退为默认值30 |
其中url的处理细节可以在 api-helpers.js 中看到:模板变量替换时会对{url}调用replace(/\/+$/, "")去除末尾的斜杠,所以http://jellystat.host.or.ip/与http://jellystat.host.or.ip写法等价,不会导致接口拼接出双斜杠。
days的校验逻辑位于 组件渲染入口:
// Days validation if (!(Number.isInteger(widget.days) && 0 < widget.days)) widget.days = 30;这意味着:days未配置、为0或负数、为小数、或非数字类型时,都会被重置为30。对应的单元测试 component.test.jsx 也验证了"传入非法值-1后service.widget.days被改写为30"这一行为,同时确认useWidgetAPI会以{ days: 30 }作为查询参数发起请求。
四、底层 API 映射:从配置到接口调用
Jellystat 小组件的后端数据源定义在 widget.js,完整内容如下:
import credentialedProxyHandler from "utils/proxy/handlers/credentialed"; const widget = { api: "{url}/{endpoint}", proxyHandler: credentialedProxyHandler, mappings: { getViewsByLibraryType: { endpoint: "stats/getViewsByLibraryType", params: ["days"], }, }, }; export default widget;通过这个映射声明,可以梳理出完整的数据请求链路:
- 组件定义:
type: jellystat在 widgets.js 中被导入并注册进全局组件表; - URL 模板:
api: "{url}/{endpoint}"定义了向 Jellystat 发起请求的地址模板,{url}替换为配置中的url,{endpoint}替换为具体映射的 endpoint; - 接口映射:
getViewsByLibraryType映射到 Jellystat 的stats/getViewsByLibraryType接口,并声明该接口接受days参数; - 代理处理器:
credentialedProxyHandler负责构造请求头(注入X-API-Token)并转发请求,详见 credentialed.js; - 前端发起:use-widget-api.js 通过 SWR 请求由 formatProxyUrl 生成的
/api/services/proxy?...代理地址,其中查询参数会被序列化为queryJSON 传给代理接口; - 数据校验:代理返回 200 后,会通过
validateWidgetData校验数据结构是否合法(credentialed.js)。
最终,homepage 请求的实际目标地址为:
http://jellystat.host.or.ip/stats/getViewsByLibraryType?days=30请求头中携带X-API-Token: <key>。
五、前端渲染:四个统计维度的数据映射
组件渲染逻辑位于 component.jsx。它通过useWidgetAPI拉取getViewsByLibraryType接口的数据,并将 Jellystat 返回的字段映射为四个展示块:
| 展示标签(国际化 key) | Jellystat 返回字段 | 含义 |
|---|---|---|
jellystat.songs | viewsData.Audio | 歌曲播放统计 |
jellystat.movies | viewsData.Movie | 电影播放统计 |
jellystat.episodes | viewsData.Series | 剧集(分集)播放统计 |
jellystat.other | viewsData.Other | 其他类型媒体统计 |
对应的文案在语言包 public/locales/en/common.json 中定义为 "Songs"、"Movies"、"Episodes"、"Other",而项目内置的 40 余种语言目录均包含同结构的jellystat词条,小组件会自动随界面语言切换显示。
渲染过程有三个状态:
- 加载中:数据尚未返回时,显示四个无值占位块(component.jsx);
- 请求出错:
viewsError或返回数据中携带message字段时,展示错误容器(component.jsx),错误信息会被sanitizeErrorURL脱敏(只保留主机名,完整地址记入日志); - 数据就绪:将
Audio、Movie、Series、Other四个字段分别渲染为数值块(component.jsx)。
上述行为均有测试覆盖:component.test.jsx 分别验证了"非法 days 回退为 30 并渲染四个占位块"、"接口报错时渲染错误 UI"、"数据返回后正确展示 1/2/3/4 四个数值"三种场景;widget.test.js 则通过expectWidgetConfigShape校验了组件配置结构(api、proxyHandler、mappings)的合法性。
六、常见问题与排查建议
- 401 / 无权限:确认
key与 JellystatSettings > API Key中生成的值完全一致。注意代理层发送的是X-API-Token请求头,不要在 Jellystat 端误配成其他认证方式。 - 数据始终为空或显示错误:确认
days为大于 0 的整数。按照 component.jsx 的校验逻辑,任何非法值都会被重置为 30,不会报错但可能不符合你的统计预期。 - 接口路径 404:确认 Jellystat 版本不低于 1.1.6,且
stats/getViewsByLibraryType接口可用(可先用curl -H "X-API-Token: <key>" "http://<jellystat>/stats/getViewsByLibraryType?days=30"直接验证);同时确认url未包含多余的路径前缀,因为代理层只会做"去末尾斜杠"处理。 - 错误信息脱敏:当请求失败时,homepage 只会在界面展示主机名(见 api-helpers.js),完整错误 URL 需要查看 homepage 服务端日志,其中记录了实际请求的目标地址与状态码(credentialed.js)。
七、小结
Jellystat 小组件是 homepage 服务仪表盘中"统计类"组件的典型代表:前端通过 SWR 与统一代理接口通信,代理层完成凭证注入与数据校验,最终将 Jellystat 的stats/getViewsByLibraryType响应映射为四个简洁的统计块。从配置上看,你只需要提供url、key与可选的days三个关键信息即可完成接入;从源码上看,其完整链路覆盖了 widget 映射、代理处理器、组件渲染 与配套测试,为自定义组件的开发提供了可参考的实现范式。
【免费下载链接】homepageA highly customizable homepage (or startpage / application dashboard) with Docker and service API integrations.项目地址: https://gitcode.com/GitHub_Trending/ho/homepage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考