主题集成

Finder API

主题模板可以通过 steamFinder 读取 Steam 数据。Finder 主要读取后台预热好的缓存,失败或超时时返回 null,模板需要判空。

可用方法

方法 返回类型 说明
steamFinder.getProfile() SteamProfile 用户资料
steamFinder.getRecentGames(limit) List<RecentGame> 最近游玩
steamFinder.getOwnedGames(page, size) ListResult<OwnedGame> 游戏库分页
steamFinder.getStats() SteamStats 游戏统计
steamFinder.getBadges() BadgeInfo 徽章信息

游戏对象字段

游戏库和最近游玩共享 OwnedGame 字段,最近游玩额外包含最近两周时长、成就和库外标识。

字段 说明
appId Steam AppID
name 游戏名称,列表优先使用 GetItems 返回的本地化名称
playtimeForever / playtimeFormatted 总游玩时长分钟数 / 格式化文本
imgIconUrl / iconUrl Steam 原始图标 hash / 拼接并套用 CDN 后的图标 URL
rtimeLastPlayed / lastPlayedFormatted 最后游玩时间戳 / 格式化日期
realHeaderImage / headerImageUrl Steam 原始真实封面 / 套用 CDN 后的展示封面
delisted GetItems 明确返回 visible=false 时为 true,表示当前地区或状态下商店不可见
playtime2Weeks / playtime2WeeksFormatted 仅最近游玩:最近两周时长
achievementProgressText / achievementsLocked 仅最近游玩:成就进度文本 / 成就是否不可用
inLibrary 仅最近游玩:是否存在于当前游戏库缓存,false 表示库外游戏

headerImageUrl 可能为 null,主题必须准备占位图。它为 null 不一定代表不可用,只有 delisted=true 才显示「不可用」标识。

示例代码

用户资料

<th:block th:with="profile=${steamFinder.getProfile()}">
  <div th:if="${profile != null}">
    <img th:src="${profile.summary?.avatarFull}" alt="头像">
    <span th:text="${profile.summary?.personaName}">用户名</span>
    <span th:text="${profile.statusText}">在线状态</span>
    <span th:text="'等级 ' + ${profile.steamLevel}">等级</span>
  </div>
</th:block>

最近游玩

<th:block th:with="recentGames=${steamFinder.getRecentGames(5)}, phImg='/themes/your-theme/assets/game-placeholder.png'">
  <div th:if="${recentGames != null}" th:each="game : ${recentGames}">
    <img th:src="${game.headerImageUrl != null ? game.headerImageUrl : phImg}" th:alt="${game.name}">
    <span th:text="${game.name}">游戏名</span>
    <span th:text="${game.playtime2WeeksFormatted}">2h 0m</span>
    <span th:if="${game.delisted}">不可用</span>
    <span th:if="${game.inLibrary != null and !game.inLibrary}">库外</span>
    <span th:if="${game.achievementProgressText != null}" th:text="${game.achievementProgressText}">15/30</span>
  </div>
</th:block>

游戏库分页

<th:block th:with="gameList=${steamFinder.getOwnedGames(1, 12)}, phImg='/themes/your-theme/assets/game-placeholder.png'">
  <div th:if="${gameList != null}">
    <div th:each="game : ${gameList.items}">
      <img th:src="${game.headerImageUrl != null ? game.headerImageUrl : phImg}" th:alt="${game.name}">
      <span th:text="${game.name}">游戏名</span>
      <span th:text="${game.playtimeFormatted}">总时长</span>
      <span th:if="${game.delisted}">不可用</span>
    </div>
    <span th:text="'第 ' + ${gameList.page} + ' 页,共 ' + ${gameList.totalPages} + ' 页'"></span>
  </div>
</th:block>

徽章

<th:block th:with="badges=${steamFinder.getBadges()}">
  <div th:if="${badges != null}">
    <span th:text="${badges.playerLevel}">等级</span>
    <span th:text="${badges.totalBadges}">徽章数</span>
    <div th:each="badge : ${badges.badges}">
      <img th:if="${badge.imageUrl != null}" th:src="${badge.imageUrl}" th:alt="${badge.displayName}">
      <span th:text="${badge.displayName}">徽章</span>
    </div>
  </div>
</th:block>

/steam 页面模板变量

插件内置 /steam 页面会传入这些变量:

变量 类型 说明
title String 页面标题
games UrlContextListResult<OwnedGame> 游戏库列表,带分页 URL
gamesLimit int 游戏库总数量限制
recentGamesLimit int 最近游玩显示数量
enableGameLink boolean 是否启用商店链接
showHeatmap boolean 是否显示热力图
heatmapDays int 热力图显示天数
heatmapColorTheme String 热力图主题
heatmapShowLegend boolean 是否显示图例
echartsUrl String ECharts 脚本地址

REST API

公开 REST API 基础路径:/apis/api.steam.timxs.com/v1alpha1

接口 方法 说明
/profile GET 用户资料
/games?page=1&size=20&sortBy=playtime_forever GET 游戏库分页,size 最大 100
/recent?limit=5 GET 最近游玩,limit 最大 20
/stats GET 统计数据
/achievements/{appid} GET 单个游戏成就进度
/badges GET 徽章信息
/game-detail/{appId}?lang=schinese GET 游戏卡片详情
/heatmap/records?startDate=&endDate= GET 每日游戏时长记录

/games/recent 在未配置或 service 返回 empty 时会返回空分页/空数组,而不是空 body。Finder API 失败时仍返回 null

缓存与性能

Finder API 日常读取后台预热好的缓存,不直接等待 Steam API。刚启动、刚刷新缓存或后台持续失败时,缓存为空可能返回 null

最近游玩成就进度在后台刷新最近游玩缓存时补全,并随列表缓存返回;页面访问缓存时不会逐个游戏重新请求成就 API。

页面列表的更新由「活跃信息刷新间隔」和「库藏信息刷新间隔」控制。「缓存过期时间」只用于游戏卡片详情等按需查询。