mirror of
https://github.com/algerkong/AlgerMusicPlayer.git
synced 2026-07-06 17:07:29 +08:00
fix(local-music): 封面落盘 + URL 编码统一,修复持久化配额与编码边界
- 新增 src/shared/localUrl.ts 共用 local:// 编码:按路径段 encodeURIComponent, 避免整体编码把 / 转成 %2F 引发 Chromium 解析边界差异,同时正确处理 空格/中文/# 等特殊字符(封面落到含空格目录时 Image loader 会加载失败) - 封面从内嵌 base64 Data URL 改为 userData/AudioCovers/<sha256>.<ext> 落盘, MAX_COVER_BYTES 1MB→8MB;老条目(无 coverPath 字段)扫描时一次性自愈 - playlist minify 剥离 base64 picUrl 并仅持久化 local:// 永不过期的 playMusicUrl, 防止单张 base64 封面撑爆 localStorage 5MB 配额导致整个 playList 写入失败; localStorage 写入加 try/catch 兜底,避免配额超限时直接抛异常
This commit is contained in:
@@ -6,6 +6,10 @@ import { SUPPORTED_AUDIO_FORMATS } from '@/types/localMusic';
|
||||
import type { ILyric, ILyricText, IWordData, SongResult } from '@/types/music';
|
||||
import { parseLyrics as parseYrcLyrics } from '@/utils/yrcParser';
|
||||
|
||||
import { filePathToLocalUrl } from '../../shared/localUrl';
|
||||
|
||||
export { filePathToLocalUrl };
|
||||
|
||||
/**
|
||||
* 判断文件路径是否为支持的音频格式
|
||||
* 通过提取文件扩展名(不区分大小写)与支持格式列表比对
|
||||
@@ -47,7 +51,7 @@ export function buildFallbackMeta(filePath: string): LocalMusicMeta {
|
||||
artist: '未知艺术家',
|
||||
album: '未知专辑',
|
||||
duration: 0,
|
||||
cover: null,
|
||||
coverPath: null,
|
||||
lyrics: null,
|
||||
fileSize: 0,
|
||||
modifiedTime: 0
|
||||
@@ -111,10 +115,15 @@ export function toSongResult(entry: LocalMusicEntry): SongResult {
|
||||
// 解析内嵌歌词为 ILyric 对象
|
||||
const lyric = parseLrcToILyric(entry.lyrics);
|
||||
|
||||
// 封面统一走落盘文件 + local:// 协议;缺 coverPath 时给空串,
|
||||
// SongItem 模板用 v-if="item.picUrl" 自动跳过渲染。
|
||||
// 用户重新扫描会让主进程落盘新封面(参见 scanFolders 的自愈条件)
|
||||
const coverUrl = entry.coverPath ? filePathToLocalUrl(entry.coverPath) : '';
|
||||
|
||||
return {
|
||||
id: entry.id,
|
||||
name: entry.title,
|
||||
picUrl: entry.cover || '/images/default_cover.png',
|
||||
picUrl: coverUrl,
|
||||
ar: [
|
||||
{
|
||||
name: entry.artist,
|
||||
@@ -140,7 +149,7 @@ export function toSongResult(entry: LocalMusicEntry): SongResult {
|
||||
blurPicUrl: '',
|
||||
companyId: 0,
|
||||
pic: 0,
|
||||
picUrl: entry.cover || '',
|
||||
picUrl: coverUrl,
|
||||
publishTime: 0,
|
||||
description: '',
|
||||
tags: '',
|
||||
@@ -176,7 +185,7 @@ export function toSongResult(entry: LocalMusicEntry): SongResult {
|
||||
artists: [{ name: entry.artist }],
|
||||
album: { name: entry.album }
|
||||
},
|
||||
playMusicUrl: `local:///${entry.filePath}`,
|
||||
playMusicUrl: filePathToLocalUrl(entry.filePath),
|
||||
duration: entry.duration,
|
||||
dt: entry.duration,
|
||||
source: 'netease' as const,
|
||||
@@ -189,17 +198,6 @@ export function toSongResult(entry: LocalMusicEntry): SongResult {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 将封面图片 Buffer 转换为 base64 Data URL
|
||||
* @param buffer 图片二进制数据
|
||||
* @param mime MIME 类型(如 image/jpeg、image/png)
|
||||
* @returns base64 Data URL 字符串
|
||||
*/
|
||||
export function coverToDataUrl(buffer: Buffer, mime: string): string {
|
||||
const base64 = buffer.toString('base64');
|
||||
return `data:${mime};base64,${base64}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按关键词搜索过滤本地音乐列表
|
||||
* 不区分大小写,匹配歌曲标题或艺术家名称
|
||||
|
||||
Reference in New Issue
Block a user