|
|
@@ -432,6 +432,17 @@ export struct NavidromePage {
|
|
|
return;
|
|
|
}
|
|
|
this.allVideos = [...this.allVideos, ...videos];
|
|
|
+ // 打印前20条数据
|
|
|
+ // const previewCount = Math.min(20, this.allVideos.length);
|
|
|
+ // console.info(`onecold allVideos: ${this.allVideos.length}, 打印前${previewCount}条:`);
|
|
|
+ // for (let i = 0; i < previewCount; i++) {
|
|
|
+ // const all = this.allVideos[i];
|
|
|
+ // console.info(`onecold allVideos[${i}]:`, JSON.stringify({
|
|
|
+ // id: all.id,
|
|
|
+ // name: all.name,
|
|
|
+ // pixelMapPath: all.pixelMapPath
|
|
|
+ // }));
|
|
|
+ // }
|
|
|
this.songNextStart = response.nextStart;
|
|
|
void ServerLogUtil.info('NavidromeLoad', `歌曲列表追加: 本次 ${videos.length} 首, 总数 ${this.allVideos.length}`);
|
|
|
} finally {
|
|
|
@@ -464,20 +475,20 @@ export struct NavidromePage {
|
|
|
return artist;
|
|
|
});
|
|
|
this.artists = [...this.artists, ...processed];
|
|
|
- console.info('onecold 帮我打印这个artists的前20条数据');
|
|
|
+ // console.info('onecold 帮我打印这个artists的前20条数据');
|
|
|
// 打印前20条艺术家数据
|
|
|
- const previewCount = Math.min(20, this.artists.length);
|
|
|
- console.info(`onecold artists总数: ${this.artists.length}, 打印前${previewCount}条:`);
|
|
|
- for (let i = 0; i < previewCount; i++) {
|
|
|
- const artist = this.artists[i];
|
|
|
- console.info(`onecold artist[${i}]:`, JSON.stringify({
|
|
|
- id: artist.id,
|
|
|
- name: artist.name,
|
|
|
- albumCount: artist.albumCount,
|
|
|
- songCount: artist.songCount,
|
|
|
- coverUrl: artist.coverUrl
|
|
|
- }));
|
|
|
- }
|
|
|
+ // const previewCount = Math.min(20, this.artists.length);
|
|
|
+ // console.info(`onecold artists总数: ${this.artists.length}, 打印前${previewCount}条:`);
|
|
|
+ // for (let i = 0; i < previewCount; i++) {
|
|
|
+ // const artist = this.artists[i];
|
|
|
+ // console.info(`onecold artist[${i}]:`, JSON.stringify({
|
|
|
+ // id: artist.id,
|
|
|
+ // name: artist.name,
|
|
|
+ // albumCount: artist.albumCount,
|
|
|
+ // songCount: artist.songCount,
|
|
|
+ // coverUrl: artist.coverUrl
|
|
|
+ // }));
|
|
|
+ // }
|
|
|
this.artistNextStart = response.nextStart;
|
|
|
void ServerLogUtil.info('ArtistCover', `艺术家列表追加: 本次 ${processed.length} 位, 总数 ${this.artists.length}`);
|
|
|
} finally {
|
|
|
@@ -784,42 +795,47 @@ export struct NavidromePage {
|
|
|
let generatedCoverCount = 0;
|
|
|
let failedCoverCount = 0;
|
|
|
|
|
|
- void ServerLogUtil.info('AlbumCover', `开始处理 ${albums.length} 张专辑的封面`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `📀 开始处理 ${albums.length} 张专辑的封面 - 账号: ${ServerLogUtil.sanitizeAccount(account)}`);
|
|
|
|
|
|
for (let i = 0; i < albums.length; i++) {
|
|
|
const album = albums[i];
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `处理专辑 [${i + 1}/${albums.length}] - id: ${album.id}, name: ${album.name}`);
|
|
|
+
|
|
|
tasks.push((async () => {
|
|
|
try {
|
|
|
- // 尝试获取直接嵌入的封面路径
|
|
|
- const directUrl = this.resolveEmbedCover(account, album.embedArtPath ?? album.coverArtPath);
|
|
|
- if (directUrl) {
|
|
|
- map.set(album.id, directUrl);
|
|
|
- directCoverCount++;
|
|
|
- void ServerLogUtil.debug('AlbumCover', `专辑 ${album.name} 使用直接封面: ${directUrl}`);
|
|
|
- return;
|
|
|
- }
|
|
|
+ // 注意: embedArtPath 和 coverArtPath 可能指向音频文件而非封面图片
|
|
|
+ // 所以这里不能直接使用,需要通过 buildCoverUrl 生成正确的封面URL
|
|
|
+ // const directUrl = this.resolveEmbedCover(account, album.embedArtPath ?? album.coverArtPath);
|
|
|
+ // if (directUrl) {
|
|
|
+ // map.set(album.id, directUrl);
|
|
|
+ // directCoverCount++;
|
|
|
+ // void ServerLogUtil.info('NavidromePageCover', `✅ 专辑使用直接封面 - name: ${album.name}, url: ${directUrl}`);
|
|
|
+ // return;
|
|
|
+ // }
|
|
|
|
|
|
// 生成封面URL
|
|
|
const coverId = album.coverArt ?? album.coverArtId ?? (album.id ? `al-${album.id}` : undefined);
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `专辑封面ID - name: ${album.name}, coverArt: ${album.coverArt}, coverArtId: ${album.coverArtId}, 最终coverId: ${coverId}`);
|
|
|
+
|
|
|
const url = await this.buildCoverUrl(account, coverId);
|
|
|
if (url) {
|
|
|
map.set(album.id, url);
|
|
|
generatedCoverCount++;
|
|
|
- void ServerLogUtil.debug('AlbumCover', `专辑 ${album.name} 生成封面URL: ${coverId} -> ${url}`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `✅ 专辑生成封面成功 - name: ${album.name}, coverId: ${coverId}, url: ${url}`);
|
|
|
} else {
|
|
|
failedCoverCount++;
|
|
|
- void ServerLogUtil.warn('AlbumCover', `专辑 ${album.name} 无可用封面: ${JSON.stringify({coverArt: album.coverArt, coverArtId: album.coverArtId, id: album.id})}`);
|
|
|
+ void ServerLogUtil.error('NavidromePageCover', `❌ 专辑封面失败 - name: ${album.name}, coverId: ${coverId}, 原始数据: ${JSON.stringify({coverArt: album.coverArt, coverArtId: album.coverArtId, id: album.id})}`);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
failedCoverCount++;
|
|
|
- void ServerLogUtil.warn('AlbumCover', `专辑 ${album.name} 封面解析失败: ${(error as Error).message}`);
|
|
|
+ void ServerLogUtil.error('NavidromePageCover', `❌ 专辑封面解析异常 - name: ${album.name}, error: ${(error as Error).message}`);
|
|
|
}
|
|
|
})());
|
|
|
}
|
|
|
|
|
|
await Promise.all(tasks);
|
|
|
|
|
|
- void ServerLogUtil.info('AlbumCover', `专辑封面处理完成: 直接嵌入 ${directCoverCount}, 生成URL ${generatedCoverCount}, 失败 ${failedCoverCount}`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `📊 专辑封面处理完成 - 总数: ${albums.length}, 直接嵌入: ${directCoverCount}, 生成URL: ${generatedCoverCount}, 失败: ${failedCoverCount}`);
|
|
|
return map;
|
|
|
}
|
|
|
|
|
|
@@ -830,10 +846,12 @@ export struct NavidromePage {
|
|
|
let generatedCoverCount = 0;
|
|
|
let failedCoverCount = 0;
|
|
|
|
|
|
- void ServerLogUtil.info('ArtistCover', `开始处理 ${artists.length} 位艺术家的封面`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `🎤 开始处理 ${artists.length} 位艺术家的封面 - 账号: ${ServerLogUtil.sanitizeAccount(account)}`);
|
|
|
|
|
|
for (let i = 0; i < artists.length; i++) {
|
|
|
const artist = artists[i];
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `处理艺术家 [${i + 1}/${artists.length}] - id: ${artist.id}, name: ${artist.name}`);
|
|
|
+
|
|
|
tasks.push((async () => {
|
|
|
try {
|
|
|
// 尝试获取已有图片URL
|
|
|
@@ -841,31 +859,33 @@ export struct NavidromePage {
|
|
|
if (directUrl) {
|
|
|
map.set(artist.id, directUrl);
|
|
|
directCoverCount++;
|
|
|
- void ServerLogUtil.debug('ArtistCover', `艺术家 ${artist.name} 使用已有图片: ${directUrl}`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `✅ 艺术家使用已有图片 - name: ${artist.name}, url: ${directUrl}`);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 生成封面URL
|
|
|
const coverId = artist.coverArt ?? artist.coverArtId ?? (artist.id ? `ar-${artist.id}` : undefined);
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `艺术家封面ID - name: ${artist.name}, coverArt: ${artist.coverArt}, coverArtId: ${artist.coverArtId}, 最终coverId: ${coverId}`);
|
|
|
+
|
|
|
const url = await this.buildCoverUrl(account, coverId, 256);
|
|
|
if (url) {
|
|
|
map.set(artist.id, url);
|
|
|
generatedCoverCount++;
|
|
|
- void ServerLogUtil.debug('ArtistCover', `艺术家 ${artist.name} 生成封面URL: ${coverId} -> ${url}`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `✅ 艺术家生成封面成功 - name: ${artist.name}, coverId: ${coverId}, url: ${url}`);
|
|
|
} else {
|
|
|
failedCoverCount++;
|
|
|
- void ServerLogUtil.warn('ArtistCover', `艺术家 ${artist.name} 无可用封面: ${JSON.stringify({coverArt: artist.coverArt, coverArtId: artist.coverArtId, id: artist.id})}`);
|
|
|
+ void ServerLogUtil.error('NavidromePageCover', `❌ 艺术家封面失败 - name: ${artist.name}, coverId: ${coverId}, 原始数据: ${JSON.stringify({coverArt: artist.coverArt, coverArtId: artist.coverArtId, id: artist.id})}`);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
failedCoverCount++;
|
|
|
- void ServerLogUtil.warn('ArtistCover', `艺术家 ${artist.name} 封面解析失败: ${(error as Error).message}`);
|
|
|
+ void ServerLogUtil.error('NavidromePageCover', `❌ 艺术家封面解析异常 - name: ${artist.name}, error: ${(error as Error).message}`);
|
|
|
}
|
|
|
})());
|
|
|
}
|
|
|
|
|
|
await Promise.all(tasks);
|
|
|
|
|
|
- void ServerLogUtil.info('ArtistCover', `艺术家封面处理完成: 直接链接 ${directCoverCount}, 生成URL ${generatedCoverCount}, 失败 ${failedCoverCount}`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `📊 艺术家封面处理完成 - 总数: ${artists.length}, 直接链接: ${directCoverCount}, 生成URL: ${generatedCoverCount}, 失败: ${failedCoverCount}`);
|
|
|
return map;
|
|
|
}
|
|
|
|
|
|
@@ -1120,53 +1140,95 @@ export struct NavidromePage {
|
|
|
}
|
|
|
|
|
|
private async resolveSongCover(song: NavidromeRestSong, account: WebDavAccount): Promise<string | undefined> {
|
|
|
- if (this.isNavidromeAccount(account) && song.albumId) {
|
|
|
- const albumCover = song.albumId ? this.albumCoverLookup.get(song.albumId) : undefined;
|
|
|
- if (albumCover) {
|
|
|
- return albumCover;
|
|
|
- }
|
|
|
- }
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `🎵 解析歌曲封面 - title: ${song.title}, albumId: ${song.albumId}, id: ${song.id}`);
|
|
|
+
|
|
|
+ // 注释掉这个代码可以解决NavidRome部分账号没有封面问题
|
|
|
+ // if (this.isNavidromeAccount(account) && song.albumId) {
|
|
|
+ // const albumCover = song.albumId ? this.albumCoverLookup.get(song.albumId) : undefined;
|
|
|
+ // if (albumCover) {
|
|
|
+ // void ServerLogUtil.debug('NavidromePageCover', `✅ 歌曲使用专辑封面缓存 - title: ${song.title}, albumCover: ${albumCover}`);
|
|
|
+ // return albumCover;
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
if (!this.isNavidromeAccount(account)) {
|
|
|
const fallbackId = song.albumId ?? song.id;
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `歌曲使用非Navidrome账号封面 - title: ${song.title}, fallbackId: ${fallbackId}`);
|
|
|
return this.buildCoverUrl(account, fallbackId);
|
|
|
}
|
|
|
+
|
|
|
const directUrl = this.resolveEmbedCover(account, song.embedArtPath ?? song.coverArtPath);
|
|
|
if (directUrl) {
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `✅ 歌曲使用直接封面 - title: ${song.title}, url: ${directUrl}`);
|
|
|
return directUrl;
|
|
|
}
|
|
|
+
|
|
|
const coverId = song.coverArt ?? song.coverArtId ?? song.id;
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `歌曲生成封面URL - title: ${song.title}, coverArt: ${song.coverArt}, coverArtId: ${song.coverArtId}, 最终coverId: ${coverId}`);
|
|
|
return this.buildCoverUrl(account, coverId);
|
|
|
}
|
|
|
|
|
|
private async buildCoverUrl(account: WebDavAccount, coverId?: string, size: number = 300): Promise<string | undefined> {
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `开始构建封面URL - coverId: ${coverId}, size: ${size}, 账号: ${ServerLogUtil.sanitizeAccount(account)}`);
|
|
|
+
|
|
|
if (!coverId || coverId.trim().length === 0) {
|
|
|
+ void ServerLogUtil.warn('NavidromePageCover', `封面ID为空,跳过构建 - coverId: "${coverId}"`);
|
|
|
return undefined;
|
|
|
}
|
|
|
+
|
|
|
const normalizedId = coverId.trim();
|
|
|
const cacheKey = `${normalizedId}_${size}`;
|
|
|
+
|
|
|
if (this.isNavidromeAccount(account)) {
|
|
|
const cached = this.coverUrlCache.get(cacheKey);
|
|
|
if (cached) {
|
|
|
- void ServerLogUtil.debug('CoverCache', `封面URL缓存命中: ${cacheKey} -> ${cached}`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `✅ 缓存命中 - coverId: ${coverId}, size: ${size}, url: ${cached}`);
|
|
|
return cached;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void ServerLogUtil.debug('CoverCache', `生成封面URL: ${coverId} (尺寸: ${size})`);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `⚡ 调用API生成封面URL - coverId: ${coverId}, size: ${size}`);
|
|
|
let url: string | undefined = undefined;
|
|
|
- if (this.isNavidromeAccount(account)) {
|
|
|
- url = await navidromeApi.buildCoverArtUrl(account, normalizedId, size);
|
|
|
- } else if (this.isJellyfinAccount(account)) {
|
|
|
- url = await jellyfinApi.buildPrimaryImageUrl(account, normalizedId, size, size);
|
|
|
- } else if (this.isEmbyAccount(account)) {
|
|
|
- url = await embyApi.buildPrimaryImageUrl(account, normalizedId, size, size);
|
|
|
- }
|
|
|
- if (url && this.isNavidromeAccount(account)) {
|
|
|
- this.coverUrlCache.set(cacheKey, url);
|
|
|
- void ServerLogUtil.debug('CoverCache', `封面URL已缓存: ${cacheKey} -> ${url}`);
|
|
|
- } else {
|
|
|
- void ServerLogUtil.warn('CoverCache', `封面URL生成失败: ${coverId} (尺寸: ${size})`);
|
|
|
+
|
|
|
+ try {
|
|
|
+ if (this.isNavidromeAccount(account)) {
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `[开始] 调用 navidromeApi.buildCoverArtUrl - coverId: ${normalizedId}, size: ${size}`);
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `[账号信息] host=${account.host}, port=${account.port}, enableHttps=${account.enableHttps}`);
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `[账号信息] basePath=${account.navidromeBasePath}`);
|
|
|
+
|
|
|
+ url = await navidromeApi.buildCoverArtUrl(account, normalizedId, size);
|
|
|
+
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `[完成] navidromeApi.buildCoverArtUrl 返回 - coverId: ${normalizedId}, 返回值: "${url}"`);
|
|
|
+
|
|
|
+ if (url) {
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `✅ API返回URL成功 - coverId: ${coverId}, url: ${url}`);
|
|
|
+ } else {
|
|
|
+ void ServerLogUtil.warn('NavidromePageCover', `⚠️ API返回空值 - coverId: ${coverId}`);
|
|
|
+ }
|
|
|
+ } else if (this.isJellyfinAccount(account)) {
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `调用 jellyfinApi.buildPrimaryImageUrl - coverId: ${normalizedId}, size: ${size}`);
|
|
|
+ url = await jellyfinApi.buildPrimaryImageUrl(account, normalizedId, size, size);
|
|
|
+ } else if (this.isEmbyAccount(account)) {
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `调用 embyApi.buildPrimaryImageUrl - coverId: ${normalizedId}, size: ${size}`);
|
|
|
+ url = await embyApi.buildPrimaryImageUrl(account, normalizedId, size, size);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (url && this.isNavidromeAccount(account)) {
|
|
|
+ this.coverUrlCache.set(cacheKey, url);
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `✅ 封面URL生成成功并已缓存 - coverId: ${coverId}, url: ${url}`);
|
|
|
+ void ServerLogUtil.debug('NavidromePageCover', `缓存键值 - cacheKey: ${cacheKey}`);
|
|
|
+ } else if (!url) {
|
|
|
+ void ServerLogUtil.error('NavidromePageCover', `❌ 封面URL生成失败(返回空) - coverId: ${coverId}, size: ${size}`);
|
|
|
+ } else {
|
|
|
+ void ServerLogUtil.info('NavidromePageCover', `✅ 封面URL生成成功(非Navidrome账号) - coverId: ${coverId}, url: ${url}`);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ const err = error as Error;
|
|
|
+ void ServerLogUtil.error('NavidromePageCover', `❌ 封面URL生成异常 - coverId: ${coverId}, error: ${err.message}`);
|
|
|
+ void ServerLogUtil.error('NavidromePageCover', `错误类型: ${err.name || 'Unknown'}`);
|
|
|
+ void ServerLogUtil.error('NavidromePageCover', `错误堆栈: ${err.stack || '无'}`);
|
|
|
}
|
|
|
+
|
|
|
return url;
|
|
|
}
|
|
|
|
|
|
@@ -1277,6 +1339,7 @@ export struct NavidromePage {
|
|
|
videoItem.navArtistId = song.artistId;
|
|
|
videoItem.navAlbumId = song.albumId;
|
|
|
videoItem.pixelMapPath = coverUrl;
|
|
|
+ videoItem.lyricContent = song.lyrics;
|
|
|
|
|
|
// 调试日志:检查歌曲的 albumId 和 artistId
|
|
|
if (this.allVideos.length < 3) {
|
|
|
@@ -2273,13 +2336,7 @@ export struct NavidromePage {
|
|
|
} else {
|
|
|
List({scroller:this.scroller, space: 8 }) {
|
|
|
// 详情视图模式下显示筛选后的歌曲,否则根据标签页显示对应内容
|
|
|
- if (this.isDetailView) {
|
|
|
- ForEach(this.getVisibleSongs(), (item: VideoItem, index: number) => {
|
|
|
- ListItem() {
|
|
|
- this.buildSongItem(item, index)
|
|
|
- }
|
|
|
- }, (item: VideoItem) => item.id)
|
|
|
- } else if (this.selectedTab === 0) {
|
|
|
+ if (this.selectedTab === 0||this.isDetailView) {
|
|
|
ForEach(this.getVisibleSongs(), (item: VideoItem, index: number) => {
|
|
|
ListItem() {
|
|
|
this.buildSongItem(item, index)
|