@@ -4,9 +4,11 @@ import { isElectron } from "@/utils/env";
44import { saveAs } from "file-saver" ;
55import { cloneDeep } from "lodash-es" ;
66import { songDownloadUrl , songLyric , songLyricTTML , songUrl , unlockSongUrl } from "@/api/song" ;
7+ import { qqMusicMatch } from "@/api/qqmusic" ;
78
89import { songLevelData } from "@/utils/meta" ;
910import { getPlayerInfoObj } from "@/utils/format" ;
11+ import { getConverter , type ConverterMode } from "@/utils/opencc" ;
1012
1113interface DownloadTask {
1214 song : SongType ;
@@ -379,7 +381,7 @@ class DownloadManager {
379381
380382 if ( downloadLyric ) {
381383 const lyricResult = ( await songLyric ( song . id ) ) as LyricResult ;
382- lyric = this . processLyric ( lyricResult ) ;
384+ lyric = await this . processLyric ( lyricResult ) ;
383385
384386 // 获取逐字歌词内容用于另存
385387 if ( downloadMakeYrc ) {
@@ -397,6 +399,26 @@ class DownloadManager {
397399 console . log (
398400 `[Download] YRC fetched from lrcResult: ${ ! ! yrcLyric } , len: ${ yrcLyric ?. length } ` ,
399401 ) ;
402+
403+ // Fallback: 如果官方没有 YRC,尝试从 QM 获取
404+ if ( ! yrcLyric ) {
405+ try {
406+ const artistsStr = Array . isArray ( song . artists )
407+ ? song . artists . map ( ( a ) => a . name ) . join ( "/" )
408+ : String ( song . artists || "" ) ;
409+ const keyword = `${ song . name } -${ artistsStr } ` ;
410+ console . log ( `[Download] Trying QM fallback with keyword: ${ keyword } ` ) ;
411+ const qmResult = await qqMusicMatch ( keyword ) ;
412+ if ( qmResult ?. code === 200 && qmResult ?. qrc ) {
413+ yrcLyric = qmResult . qrc ;
414+ console . log (
415+ `[Download] QM QRC fetched as fallback, len: ${ yrcLyric ?. length } ` ,
416+ ) ;
417+ }
418+ } catch ( e ) {
419+ console . error ( "[Download] Error fetching QM lyrics as fallback:" , e ) ;
420+ }
421+ }
400422 }
401423 } catch ( e ) {
402424 console . error ( "[Download] Error fetching verbatim lyrics:" , e ) ;
@@ -424,6 +446,9 @@ class DownloadManager {
424446 let content = ttmlLyric || yrcLyric ;
425447 if ( content ) {
426448 try {
449+ // 繁体转换
450+ content = await this . _convertToTraditionalIfNeeded ( content ) ;
451+
427452 const ext = ttmlLyric ? "ttml" : "yrc" ;
428453 const fileName = `${ safeFileName } .${ ext } ` ;
429454 const encoding = settingStore . downloadLyricEncoding || "utf-8" ;
@@ -479,7 +504,7 @@ class DownloadManager {
479504 * @param lyricResult 歌词结果
480505 * @returns 处理后的歌词字符串
481506 */
482- private processLyric ( lyricResult : LyricResult ) : string {
507+ private async processLyric ( lyricResult : LyricResult ) : Promise < string > {
483508 const settingStore = useSettingStore ( ) ;
484509 try {
485510 const rawLyric = lyricResult ?. lrc ?. lyric || "" ;
@@ -595,7 +620,12 @@ class DownloadManager {
595620 }
596621 }
597622 }
598- return lines . join ( "\n" ) ;
623+ const result = lines . join ( "\n" ) ;
624+
625+ // 繁体转换
626+ return await this . _convertToTraditionalIfNeeded ( result ) ;
627+
628+
599629 } catch ( e ) {
600630 console . error ( "Lyric processing failed" , e ) ;
601631 return "" ;
@@ -659,6 +689,20 @@ class DownloadManager {
659689 this . retryDownload ( id ) ;
660690 } ) ;
661691 }
692+ /**
693+ * 繁体转换辅助方法
694+ * @param text 需要转换的文本
695+ * @returns 转换后的文本
696+ */
697+ private async _convertToTraditionalIfNeeded ( text : string ) : Promise < string > {
698+ const settingStore = useSettingStore ( ) ;
699+ if ( settingStore . downloadLyricToTraditional && text ) {
700+ const variant = ( settingStore . traditionalChineseVariant || "s2t" ) as ConverterMode ;
701+ const converter = await getConverter ( variant ) ;
702+ return converter ( text ) ;
703+ }
704+ return text ;
705+ }
662706}
663707
664708let instance : DownloadManager | null = null ;
0 commit comments