21945cc54f
由 163-music-dl CLI 重构为 Web 服务: - 下载流水线、歌词与标签逻辑沿用旧版(node-id3 / ffmpeg) - 网易云(chksz 接口 + music.163.com 元数据)与 QQ 音乐(VIP Cookie)provider - QQ 扫码登录与 musickey 自动续期 - SQLite 持久化的下载队列,SSE 实时进度 - 曲库工具(M3U / ZIP / 回收站 / 补全标签)、历史统计与导出、访问密码 - Vite 8 + Vue 3 前端,浅色 / 深色 - Docker 部署配置(飞牛 NAS) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.2 KiB
3.2 KiB
CLAUDE.md
声匣:自托管音乐下载 Web 服务(网易云 + QQ 音乐),本机 npm start 或 NAS Docker 运行。UI、注释、日志均为中文。
命令
npm run dev— 后端node --watch server/src/main.ts(:8066)+ Vite(:5173,代理/api)npm start— 生产模式(需先npm run build)npm run typecheck—tsc(server)+vue-tsc(web)。改动后必须通过npm run smoke -- <id|链接> [quality] [album|flat]— 端到端跑一次下载流水线(会导入 QQ Cookie)
没有测试框架;用 smoke、curl /api/*,以及无头浏览器截图验证。测试下载请用 MUSIC_DIR / DATA_DIR 指向临时目录,不要污染 ./music 与 ./data。
架构
单个 package.json:
server/src/— Koa 3,Node 原生 TypeScript 类型剥离直接运行,无构建步骤- 只能用可擦除语法(
erasableSyntaxOnly):不能用 enum / namespace / 参数属性 - 相对导入必须写
.ts;类型导入用import type(verbatimModuleSyntax) core/与平台无关:pipeline.ts(下载流水线)、tagging.ts、lyrics.ts、layout.ts、quality.ts、net/http.tscore/providers/{netease,qq}/实现MusicProvider(core/types.ts),在providers/index.ts注册;resolveLink处理分享短链- QQ:
qq/client.ts的musicu()在 comm 中带uin+authst并附 Cookie —— 缺这一步拿不到 VIP 音源 queue.ts— 任务存 SQLitetasks表,进度只在内存,经events.ts的 bus 推送;routes/api.ts的/api/events是 SSEaccounts.ts(Cookie 用secret.tsAES-GCM 加密存储)、settings.ts(运行时设置)、auth.ts(可选访问密码)、library.ts(曲库工具)、stream.ts(试听代理)db.ts—node:sqlite;history / tasks / settings 表
- 只能用可擦除语法(
web/— Vite 8 + Vue 3.5 + Vue Router 5,无 UI 库lib/store.ts全局状态 + SSE;lib/player.ts试听;lib/api.ts类型与请求components/TrackList.vue是所有曲目列表(搜索 / 专辑 / 歌单 / 歌手)的核心- 样式只用
styles/tokens.css的 CSS 变量;base.css有.page.btn.seg.badge等通用类
约定
- 统一音质键
standard|high|lossless|hires|master|spatial|effect;provider 映射到平台参数,不可用时按fallbackChain降级。QQ 只声明到 hires - 目录:
album布局 ={第一位专辑艺人}/{专辑}/{NN}. {歌名}.ext(与 NAS 曲库一致);flat={歌手} - {歌名}.ext - 下载先写
.part再改名;已存在判定:≥ 音源 99% 且 ≤ 音源 + 8MB(内嵌封面会变大) FatalError表示重试无意义;队列间隔gapMs(默认 400ms)防止打爆上游- 服务端永远不把 Cookie 原文返回前端;
relFile等路径一律用/ - 传给 TrackList 的数组必须稳定(用 computed),否则每次渲染都会清空选择
- 前端
ref<null>的接口要返回对象包一层(Koa 对nullbody 返回 204) - TypeScript 固定 6.x:TS 7 没有 JS API,vue-tsc 无法使用
- 网易云红 / QQ 绿已用 dataviz 校验器验证(深色 QQ 绿
#42a07d);二者 CVD 区分度在 6–8,必须配合文字标签使用