v0.2.0-rc2
Pre-release
Pre-release
Added
- 播放器均衡器组件:新增
EqualizerPanel,承载均衡器开关、预设选择、自定义频段增益调节,预设切换时触发触感反馈 - 定时关闭组件:新增
SleepTimerControl,将定时关闭滑块、刻度、剩余时间展示从主App.vue中拆出 - 触感反馈 composable:新增
useHaptic,统一封装light、medium、heavy、selection、success、warning、error等振动模式,并在非手机设备或prefers-reduced-motion下自动禁用 - 播放队列预测 API:播放器 store 新增
peekNext()/peekPrevious(),可在不改变当前曲目、进度和队列版本的情况下预测上一首/下一首 - 跨域音频降级播放:
useAudioPlayer新增 Web Audio CORS 失败降级路径,分析链路无法接入时会重建无crossOrigin的 audio 元素,保留播放能力并降级节拍分析 - 主封面 CORS 回退:主封面以
crossorigin="anonymous"首次加载失败时会移除crossorigin重建图片,优先保证封面显示,取色失败则回退默认主题 - 共享配置 schema:新增
shared/config-schema.ts,服务端保存配置和构建期公开配置生成共用同一套字段清洗与校验;覆盖receivePrereleaseUpdates、githubProxy、统计、站点验证、自定义 CSS/JS 等字段 - 共享环境 schema:新增
shared/env-schema.ts,统一DEVELOPMENT真值解析、GH_REPO格式校验与CONFIG_ENCRYPTION_KEY强度校验 - 共享版本工具:新增
shared/version.ts,支持严格 SemVer 解析、比较、预发布判断、v前缀 /refs/tags/规范化和最新版本选择 - 构建期公开配置生成:新增
scripts/generate-public-config.mjs与scripts/generate-public-config.d.mts,从缺失、明文或加密的public/config.json生成src/generated/public-config.ts与src/generated/admin-env.ts - 管理后台构建状态:公开配置生成时同步输出
idle、disabled、env-not-ready状态,前端可展示管理后台禁用或环境变量未就绪原因 - Pages 本地开发准备脚本:新增
scripts/prepare-pages-dev.mjs,为 Wrangler Pages Functions 本地开发创建.wrangler/pages-dev-static,让 Vite 提供页面、Wrangler 只模拟/api/* - Cloudflare Pages 静态规则:新增
public/_headers与public/_redirects,统一安全响应头、Service Worker 缓存、manifest 类型、静态资源 immutable 缓存与 SPA fallback - 一键更新状态跟踪:后台触发更新后返回
triggeredAt与triggerId,关于页持续轮询 GitHub Actions 状态并展示日志链接、失败详情和成功提交链接 - 更新状态接口:新增
GET /api/update/status?since=...&triggerId=...,归一化返回locating、queued、running、success、failed、cancelled、timed_out,并带retryAfterSeconds、Actions URL、commit URL 与失败消息 - 预发布版本开关:高级设置新增“接收预发布版本”,稳定版默认只接收稳定更新;开启后可接收 rc / beta / alpha,当前版本本身为 prerelease 时继续自动接收 prerelease
- 主分支验证 workflow:新增
.github/workflows/main-validation.yml,在mainpush 与手动触发时执行安装、测试、类型检查、Lint、格式检查、构建、自动 tag;稳定版自动创建 GitHub Release,预发布版仅打 tag - 管理后台上传常量:管理 API 新增
MAX_UPLOAD_BYTES、MAX_UPLOAD_BASE64_LENGTH、MAX_UPLOAD_SIZE_LABEL,统一前端上传限制 - 本地曲目编辑提示:本地曲目编辑器新增未补全提示,缺少 ID、标题、艺术家或音频时提示保存会被拦截
- 本地曲目删除失败展示:删除确认框新增逐项失败展示,便于看到具体失败文件
Changed
- 版本升级:
package.json版本从0.2.0-rc1升级到0.2.0-rc2 - 运行环境收紧:
package.jsonengines 从 Node>=20/ pnpm>=8调整为 Node>=22/ pnpm>=11.5.3,并固定packageManager为pnpm@11.5.3 - 生成流程拆分:
generate拆为generate:app-version与generate:public-config;predev使用开发变量生成公开配置,prebuild、pretest、pretype-check、prelint统一先生成构建产物 - 前端配置加载改为构建期公开配置:播放器从异步
/api/runtime-config改为同步读取loadMusicConfig(),并按公开apiEndpoint注入preconnect - 类型拆分公开配置和完整配置:新增
PublicMusicConfig,前端公开配置不再包含apiToken、githubProxy、receivePrereleaseUpdates等管理员/服务端字段 - Meting 请求去 token 化:前端歌单请求不再向 Meting API URL 拼接
token,只发送server、type、id - 播放器主文件瘦身:
App.vue移除内联均衡器、定时关闭、触感反馈逻辑,改为组合EqualizerPanel、SleepTimerControl、useHaptic - 空曲库体验调整:无曲目时提示改为“暂无可播放歌曲,请在管理后台添加音乐”,且不再把空曲库视为加载失败
- 切歌状态机重构:
useAudioPlayer改为明确的idle/switching状态机,使用AbortController取消过期切歌请求 - 音量淡入淡出重构:fade 动画从全局计数改为按 audio 元素独立管理,避免新旧音频淡入淡出互相取消
- 预加载目标预测统一:预加载池复用 store 的
peekNext()/peekPrevious(),保证顺序、循环、单曲、随机模式下预加载目标与实际切歌一致 - 预加载失败文案调整:后台预加载失败提示改为“预加载歌曲暂时无法播放,当前播放不受影响”,避免误报“已跳过”
- 虚拟曲库列表布局调整:
TrackList使用完整高度 spacer 包裹绝对定位条目,空列表时不渲染大高度 spacer - 封面缓存上限:
useCoverCache对 loaded / failed 封面缓存增加 512 条上限,按最近使用淘汰旧 trackId - Reduced motion 行为调整:
useBeatAnalyser在 reduced motion 下仍构建 Web Audio / EQ 图,但跳过视觉 RAF 循环和可见性监听 - Media Session 清理:无当前曲目时清空 metadata 并设置 playbackState 为
none - 开发模式显式化:服务端从“根据
GH_TOKEN是否为空/占位符推断本地模式”改为显式DEVELOPMENT=true/1/yes/on;Vercel、Cloudflare Pages、Netlify API 入口均透传DEVELOPMENT - 环境就绪校验调整:生产环境重点校验
GH_REPO格式与CONFIG_ENCRYPTION_KEY强度;GH_TOKEN不再作为公开状态页硬性校验项,需要写 GitHub 的接口仍会单独检查 token - 配置读取 fail-closed:
getConfig在 GitHub 读取失败时返回502;生产明文配置返回409;解密失败返回409并提示检查CONFIG_ENCRYPTION_KEY;保存时写入 shared schema 清洗后的配置 - 状态页改为 JSON 状态:
renderEnvNotReadyPage与renderDisabledPage不再返回完整 HTML,状态探针返回{ status, detail },由前端渲染管理后台禁用/环境未就绪状态 - 更新检查改为 POST JSON:
/api/check-update从 GET query 改为带认证、同源校验、JSON Content-Type 的 POST body,携带current、githubProxy、receivePrereleaseUpdates - 更新检查逻辑增强:同时读取 latest release 和 tags;release 不可用时 fallback 到 tag;Tags fallback 使用
per_page=100;版本选择改用严格 SemVer 排序 - 预发布策略明确:稳定版默认忽略 prerelease;当前版本为 prerelease 或显式开启“接收预发布版本”时才接收 prerelease
- GitHub 请求错误映射:更新检查统一 8 秒超时,并将 401/403/429/5xx/超时映射为可操作错误
- GitHub 代理语义收敛:检查更新可走代理且不附带
GH_TOKEN;workflow dispatch 与 Actions 状态查询始终直连 GitHub API,代理仅作为 workflow input 传给上游拉取步骤 - 更新目标精确锁定:检查更新返回
targetTag,触发 workflow 时传入target_tag、allow_prerelease、trigger_id,workflow 优先同步后台选定 tag - 更新轮询限流调整:
/api/update/status调整为 240 次 / 15 分钟,覆盖最长 10 分钟 running 轮询窗口 - 上传路径白名单收紧:
/api/upload从允许整个public/改为只允许public/music/下白名单媒体/歌词/图片扩展名,以及public/icon.png|jpg|jpeg|webp|ico - 上传大小统一:本地曲目和站点图标上传限制统一为 25MiB,base64 长度限制精确匹配 25MiB 文件边界
- 删除文件返回结构化:删除 API 从简单布尔返回改为
DeleteFilesResult,前端校验返回数量并展示逐项失败;远端文件不存在时视为已删除成功 - GitHub Contents API 编码增强:仓库、分支和文件路径按段编码,避免
?/#/&/空格等字符扭曲 URL 或注入查询参数 - 认证与密码安全增强:管理员密码 PBKDF2 迭代次数从 100k 提升到 600k;
tokenVersion缓存 TTL 从 30 秒缩短到 5 秒;开发模式 Cookie 签名密钥包含GH_REPO;限流键移除可伪造的 User-Agent - API 写请求同源校验:所有
/api/下 POST/PUT/DELETE 检查Origin或Referer;跨站返回403;开发模式允许 localhost Vite/Wrangler 代理写请求 - 本地后端开发命令调整:
dev:admin先执行prepare-pages-dev.mjs,再运行.wrangler/pages-dev-static,不再依赖旧dist - 格式化命令兼容性:
format与format:check增加--ignore-unknown - Vite base 固定:
vite.config.ts的base从process.env.BASE_PATH || '/'改为固定/ - 部署平台收敛:移除 GitHub Pages 部署假设,平台口径收敛为 Vercel、Netlify、Cloudflare Pages
- Cloudflare Pages 配置瘦身:
wrangler.toml只保留核心 Pages 配置,headers/redirects 迁移到public/_headers/public/_redirects - Netlify 构建环境固定:
PNPM_VERSION从11固定为11.5.3,并移除重复 inline build environment - TypeScript 覆盖范围扩展:
tsconfig.app.json与tsconfig.server.json纳入shared/**/*.ts;服务端 tsconfig 增加 Node types - 版本脚本 fail-fast:
generate-app-version.mjs与inject-sw-cache-name.mjs校验package.jsonversion 必须是合法 SemVer,不再静默回退0.0.0,并用JSON.stringify输出版本字符串 - Service Worker cache 注入 fail-fast:
inject-sw-cache-name.mjs在dist/sw.js缺少__SW_CACHE_NAME__占位符时直接失败 - 用户数据保留规则调整:上游同步继续保留
.dev.vars、.env、.env.local、.env.production、public/admin.json、public/config.json、public/music/、构建产物和本地目录;模板文件可随上游更新 - 站点图标上传流程调整:上传成功等待 FileReader 和网络请求均完成后再提示,默认使用
png后缀,上传类型移除 SVG - 管理员密码前端限制增强:修改密码最小长度从 6 位提升到 8 位
Fixed
- 快速切歌竞态:修复旧切歌请求继续提交状态、旧音频叠放播放、切歌异常后长期卡在过渡状态的问题
- 旧音频静音失败:修复手动切歌时旧音频淡出被新音频淡入取消,导致旧音频未及时静音的问题
- 曲库刷新同步:修复当前曲目从刷新结果中被删除后仍保留旧曲目、进度、时长或播放状态的问题;队列现在会同步删除不存在歌曲并追加新增歌曲
- pending seek 回弹:修复无 metadata 时 seek 导致进度条回弹的问题,现在先记录 pending seek 并更新 UI,待 duration 可用后再写入 audio
- 播放失败反馈:修复
skipOnError关闭或队列只有一首时错误消息被清空的问题 - 卸载后自动跳过:修复自动跳过计时器在组件卸载后仍可能触发的问题
- 跨域音频播放:修复跨域音频无法接入 Web Audio API 时播放被节拍分析拖垮的问题,现在降级分析但继续播放
- 跨域封面显示:修复跨域封面缺少 CORS 响应头时直接失败、不显示封面的问题
- 歌词缓存 abort:修复歌词缓存命中时调用方 abort signal 无法独立生效、已 abort signal 没有立即 reject 的问题
- 持久化设置清洗:修复
NaN、Infinity、越界数值、非法播放模式、非法均衡器预设等脏数据泄漏到运行时的问题 - 虚拟列表高度:修复曲库虚拟列表滚动高度不完整、空状态前出现异常大 spacer 的问题
- Media Session 兼容:修复 Safari/旧浏览器 Media Session 赋值或 handler 注册失败时可能影响播放流程的问题
- 管理后台状态识别:修复管理后台禁用或环境未就绪时可能被误判为“后端不可用”的问题
- 状态页 HTML 写入:修复
/api/setup-status返回 HTML 时前端直接document.write()替换页面的问题,改为标记 API 不可用 - 登录过期处理:修复配置加载、保存、上传、删除、改密、音乐 API 测试、更新检查/触发/状态查询遇到 401/403 后本地仍保持已登录状态的问题
- 配置提交前校验:修复无效本地曲目配置可能被提交到后端的问题
- 本地文件部分删除:修复本地曲目文件部分删除失败时仍从配置中移除曲目的问题
- 删除结果校验:修复删除文件接口未校验后端返回结果数量或逐项失败状态的问题
- 站点图标上传竞态:修复文件读取/上传尚未完成时就进入成功状态的问题
- 更新检查回写竞态:修复重复检查和组件卸载后异步状态回写的风险
- 更新触发反馈:修复触发更新后只能显示短暂提示、无法跟踪 GitHub Actions 执行结果的问题
- 后端错误 detail 展示:修复更新检查或触发失败时未优先展示后端
detail的问题 - 超大上传拦截:修复超大 base64 上传内容仍可能被发送到后端的问题
- 密钥耦合:修复
GH_TOKEN轮换会影响配置解密/签名的问题,配置加密和 Cookie 签名均改用CONFIG_ENCRYPTION_KEY派生 - 配置读取静默回落:修复生产配置读取失败、明文配置或解密失败时静默回落默认配置的问题,避免隐藏密钥错误或配置损坏
- 初始化重开风险:修复
admin.json明文或解密失败可能被误判为未初始化并重新开放 setup 的风险 - 代理 SSRF:修复
githubProxy可指向内网/本地地址的风险,同时避免通过代理检查更新时泄露GH_TOKEN - 跨站写请求:修复旧版 CORS/OPTIONS 行为与 Cookie 凭据组合可能形成跨站管理 API 风险的问题
- 更新接口非 JSON 触发:修复
/api/update、/api/check-update可接受非 JSON 请求并触发外部调用的问题 - 上传覆盖敏感文件:修复上传接口可覆盖
public/sw.js、manifest、robots、public/config.json、public/admin.json或上传可执行前端资源的风险 - 上传路径绕过:修复路径穿越、URL-like path、编码穿越、畸形 percent encoding 等路径校验绕过
- GitHub 路径编码:修复 GitHub 文件路径未编码导致特殊字符影响 Contents API URL 的问题
- 更新版本比较:修复预发布、tag fallback、非法 tag、字符串排序导致的更新误判
- 删除远端 404:修复删除远端已不存在的允许路径时被标记为删除失败的问题
- PWA API 缓存:修复 Service Worker 缓存优先策略可能让
/api/auth返回旧登录状态的问题,现在/api/*直接放行网络 - PWA 缓存清理范围:修复 activate 阶段清理过宽的问题,现在只清理
meliora-shell-前缀且非当前版本的缓存 - 更新 workflow 直写目标分支:修复上游同步后直接 push 目标分支的风险,现在先推临时分支、完成验证、合并目标分支最新状态并再次验证后才写回
- Cloudflare Pages 规则兼容:修复 headers/redirects 放在
wrangler.toml的兼容性问题,迁移到_headers/_redirects
Removed
- 移除前台更新检查服务:删除未接线的
src/services/updates.ts与src/tests/updates-cache.test.ts,更新入口统一收敛到后台关于页 - 移除
/api/runtime-config:公开运行配置改由构建期 public config 提供;就绪、禁用、环境未就绪状态下均返回 404 - 移除服务端内置 HTML 状态页模板:状态页接口只返回 JSON 状态
- 移除旧配置校验导出:删除
server/core/config-handler.ts内部validateConfig,配置校验迁移到shared/config-schema.ts - 移除
GH_TOKEN占位符本地模式推断:开发模式必须显式配置DEVELOPMENT - 移除前端运行时配置拉取路径:播放器不再请求
/api/runtime-config - 移除前端 Meting token 拼接:前端不再把
apiToken拼进歌单请求 URL - 移除
App.vue内联均衡器 / 定时关闭 / 触感反馈逻辑:对应逻辑改由新组件和 composable 接管 - 移除抽屉 opener
defineExpose引用 - 移除 GitHub Pages 部署 workflow:删除
.github/workflows/deploy-pages.yml,部署平台收敛为 Vercel、Netlify、Cloudflare Pages - 移除 GitHub Pages 文档口径和相对 base 假设:README / SUPPORT 不再宣称支持 GitHub Pages 自动部署,
vite.config.ts不再读取BASE_PATH - 移除内置 DEVOTION 示例资源:删除
public/music/DEVOTION/audio.flac、cover.jpg、lyrics.lrc - 移除 SVG 站点图标上传支持:保留 PNG、JPEG、WebP、ICO
Tests
- 播放器测试:新增
use-audio-player.test.ts,覆盖公开 API、选曲播放、快速连续下一首、暂停、pending seek、播放失败自动跳过、卸载清理计时器、当前曲目被移除后的状态清空 - 播放器 store 测试:扩展
player-store.test.ts,覆盖曲库刷新同步队列、删除当前曲目、peekNext()/peekPrevious()在循环/顺序/单曲/随机模式下的行为、纯预测不变更状态、非法持久化设置 sanitize - 预加载测试:新增
use-preload-pool.test.ts,验证预加载预测与 store 预测一致,并覆盖预加载失败提示不误报跳过 - 曲库列表测试:新增
track-list.test.ts,覆盖虚拟列表完整滚动高度和空状态不渲染 spacer - 封面缓存测试:新增
use-cover-cache.test.ts,覆盖 loaded / failed 缓存 512 条上限与旧项淘汰 - 节拍分析测试:新增
use-beat-analyser.test.ts,覆盖 reduced motion 下仍建立 EQ 图但不启动视觉 RAF - 歌词请求测试:扩展
lyrics-timeout.test.ts,覆盖缓存命中时单个调用 abort、不取消共享请求,以及已 abort signal 立即拒绝 - 音乐服务测试:扩展
music-service.test.ts,覆盖公开配置加载不请求 runtime config,以及歌单请求 URL 不包含 token - 管理 API 测试:新增
src/tests/admin-api.test.ts,覆盖 401/403 登录过期、25MiB 上传边界、部分删除失败、保存前配置校验、POST 更新检查、触发更新返回triggeredAt/triggerId、更新状态查询 - 管理组件测试:新增
src/tests/admin-components.test.ts,覆盖 8 位密码限制、部分删除失败时保留本地曲目、站点图标上传异步状态、移除 SVG 上传类型、预发布更新开关与代理提示文案 - 管理认证测试:新增
src/tests/use-admin-auth.test.ts,覆盖disabled、env-not-ready、普通初始化状态、非 JSON setup 响应、HTML setup 响应不写入文档 - 配置 schema 测试:新增
src/tests/config-schema.test.ts,覆盖内部地址拦截、远程歌单 endpoint 要求、播放列表/本地曲目字段、可选统计配置、receivePrereleaseUpdates布尔校验 - 路由安全测试:扩展
server/tests/router-security.test.ts,覆盖未认证更新检查/状态查询、跨 Origin/Referer 写请求拒绝、同源写请求、开发 localhost 代理写请求、/api/runtime-config404、非 JSON 更新请求 415、状态接口 no-store - 更新流程测试:扩展
server/tests/update-handler.test.ts,覆盖 stable / prerelease 比较、tag fallback、SemVer 排序、预发布 opt-in、私有 GitHub proxy 拒绝、缺 token 拒绝 dispatch、dispatch body、workflow run 状态归一化与 trigger id 过滤 - 上传安全测试:扩展
server/tests/upload-handler.test.ts,覆盖允许的音乐资源和 raster icon,拒绝 service worker、manifest、robots、config/admin、可执行前端扩展、SVG、URL-like path、路径穿越、畸形编码、.env、workflow 文件,并覆盖删除 404 视为成功 - 配置/环境测试:新增
server/tests/config-handler.test.ts、development-mode.test.ts、url-validation.test.ts,覆盖 fail-closed 配置读取、显式DEVELOPMENT、环境校验和公网 URL 校验 - 公开配置生成测试:新增
server/tests/generate-public-config.test.ts,覆盖缺失/明文/加密配置生成、解密失败、schema 失败、私密字段清洗、admin build status、.dev.vars显式读取和 env 优先级 - Bundle 泄漏测试:新增
server/tests/bundle-leakage.test.ts,防止构建产物泄露apiToken、githubProxy等管理员字段和测试 secret - CI 验证链路:PR、main、update workflow 均增加
pnpm format:check;update workflow 同步上游后运行安装、测试、类型检查、Lint、格式检查、构建,合并目标分支最新提交后再次运行测试、类型检查、构建
Docs
- README 本地开发说明更新:端口从 5173 改为 5175,运行要求更新为 Node 22+ 与 pnpm 11.5.3+,并说明
pnpm dev:full的 Vite + Wrangler Pages Functions 分工 - README 管理后台说明更新:高级设置补充预发布更新;保存配置说明改为构建期写入前端公开配置,首屏不再请求管理 API
- README 一键更新说明重写:补充临时分支、验证链路、失败不改目标分支、Actions 日志入口、branch protection 限制和保留用户数据规则
- README 部署平台说明更新:部署按钮表移除 GitHub Pages;Cloudflare Pages 改为说明
wrangler.toml的pages_build_output_dir与_headers/_redirects - README 环境变量表更新:补充
GITHUB_PROXY、DEVELOPMENT,更新GH_TOKEN权限、CONFIG_ENCRYPTION_KEY构建期用途,并移除/api/runtime-config例外描述 - README 加密说明更新:明确构建期会解密并清洗公开配置,
apiToken不进入前端 bundle,本地开发改用DEVELOPMENT=true .env.example/.dev.vars.example更新:明确 fine-grained PAT 需要Contents: Read and write+Actions: Write,classic token 可用repo;补充 GitHub 代理职责和api.github.com直连要求- SUPPORT 部署 FAQ 更新:从“如何部署到 GitHub Pages”改为“支持哪些部署平台”,列出 Vercel、Netlify、Cloudflare Pages
- agent.md 规范更新:部署平台从 4 个收敛到 3 个,补充公开站点配置必须构建期生成、敏感字段不得进入前端 bundle、远程歌单不得预抓取 Meting 结果,并同步开发模式与环境变量口径