|  | @ -272,6 +272,26 @@ export default { | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | }, |  |  | }, | 
														
													
														
															
																|  |  | methods: { |  |  | methods: { | 
														
													
														
															
																|  |  |  |  |  | // 辅助方法:查找第一个非导语音频的索引 | 
														
													
														
															
																|  |  |  |  |  | findFirstNonLeadAudio() { | 
														
													
														
															
																|  |  |  |  |  | if (!this.currentPageAudios || this.currentPageAudios.length === 0) { | 
														
													
														
															
																|  |  |  |  |  | return -1; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 从第一个音频开始查找非导语音频 | 
														
													
														
															
																|  |  |  |  |  | for (let i = 0; i < this.currentPageAudios.length; i++) { | 
														
													
														
															
																|  |  |  |  |  | const audioData = this.currentPageAudios[i]; | 
														
													
														
															
																|  |  |  |  |  | if (audioData && !audioData.isLead) { | 
														
													
														
															
																|  |  |  |  |  | console.log(`🎵 findFirstNonLeadAudio: 找到第一个非导语音频,索引=${i}, isLead=${audioData.isLead}`); | 
														
													
														
															
																|  |  |  |  |  | return i; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 如果所有音频都是导语,返回第一个音频的索引 | 
														
													
														
															
																|  |  |  |  |  | console.log('🎵 findFirstNonLeadAudio: 所有音频都是导语,返回第一个音频索引=0'); | 
														
													
														
															
																|  |  |  |  |  | return 0; | 
														
													
														
															
																|  |  |  |  |  | }, | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 检查并自动加载预加载完成的音频 |  |  | // 检查并自动加载预加载完成的音频 | 
														
													
														
															
																|  |  | checkAndLoadPreloadedAudio() { |  |  | checkAndLoadPreloadedAudio() { | 
														
													
														
															
																|  |  | // 只在需要加载音频的页面检查 |  |  | // 只在需要加载音频的页面检查 | 
														
													
												
													
														
															
																|  | @ -317,22 +337,29 @@ export default { | 
														
													
														
															
																|  |  | // 自动播放缓存的音频 |  |  | // 自动播放缓存的音频 | 
														
													
														
															
																|  |  | this.$nextTick(() => { |  |  | this.$nextTick(() => { | 
														
													
														
															
																|  |  | if (this.currentPageAudios.length > 0 && !this.isVoiceChanging) { |  |  | if (this.currentPageAudios.length > 0 && !this.isVoiceChanging) { | 
														
													
														
															
																|  |  | const firstAudioData = this.currentPageAudios[0]; |  |  |  | 
														
													
														
															
																|  |  | console.log(`🎵 自动播放缓存音频: ${firstAudioData.url}`); |  |  |  | 
														
													
														
															
																|  |  | audioManager.playAudio(firstAudioData.url, 'sentence', { playbackRate: this.playSpeed }); |  |  |  | 
														
													
														
															
																|  |  | this.isPlaying = true; |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 页面切换时需要立即更新高亮和滚动,不受防抖机制影响 |  |  |  | 
														
													
														
															
																|  |  | const highlightIndex = firstAudioData.originalTextIndex !== undefined ? firstAudioData.originalTextIndex : 0; |  |  |  | 
														
													
														
															
																|  |  | this.currentHighlightIndex = highlightIndex; |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 立即发送高亮变化事件 |  |  |  | 
														
													
														
															
																|  |  | this.emitHighlightChange(highlightIndex, firstAudioData); |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 立即发送滚动事件,传入音频数据 |  |  |  | 
														
													
														
															
																|  |  | this.emitScrollToText(highlightIndex, firstAudioData); |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | console.log(`🎵 页面切换自动播放: 高亮索引=${highlightIndex}, 页面=${this.currentPage}`); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 查找第一个非导语音频 | 
														
													
														
															
																|  |  |  |  |  | const firstNonLeadIndex = this.findFirstNonLeadAudio(); | 
														
													
														
															
																|  |  |  |  |  | if (firstNonLeadIndex >= 0 && firstNonLeadIndex < this.currentPageAudios.length) { | 
														
													
														
															
																|  |  |  |  |  | // 设置当前音频索引为第一个非导语音频 | 
														
													
														
															
																|  |  |  |  |  | this.currentAudioIndex = firstNonLeadIndex; | 
														
													
														
															
																|  |  |  |  |  | const firstAudioData = this.currentPageAudios[firstNonLeadIndex]; | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | console.log(`🎵 自动播放缓存音频(跳过导语): 索引=${firstNonLeadIndex}, isLead=${firstAudioData.isLead}, url=${firstAudioData.url}`); | 
														
													
														
															
																|  |  |  |  |  | audioManager.playAudio(firstAudioData.url, 'sentence', { playbackRate: this.playSpeed }); | 
														
													
														
															
																|  |  |  |  |  | this.isPlaying = true; | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 页面切换时需要立即更新高亮和滚动,不受防抖机制影响 | 
														
													
														
															
																|  |  |  |  |  | const highlightIndex = firstAudioData.originalTextIndex !== undefined ? firstAudioData.originalTextIndex : firstNonLeadIndex; | 
														
													
														
															
																|  |  |  |  |  | this.currentHighlightIndex = highlightIndex; | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 立即发送高亮变化事件 | 
														
													
														
															
																|  |  |  |  |  | this.emitHighlightChange(highlightIndex, firstAudioData); | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 立即发送滚动事件,传入音频数据 | 
														
													
														
															
																|  |  |  |  |  | this.emitScrollToText(highlightIndex, firstAudioData); | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | console.log(`🎵 页面切换自动播放(跳过导语): 高亮索引=${highlightIndex}, 页面=${this.currentPage}`); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | }); |  |  | }); | 
														
													
														
															
																|  |  | } else { |  |  | } else { | 
														
													
												
													
														
															
																|  | @ -431,8 +458,6 @@ export default { | 
														
													
														
															
																|  |  | let totalDuration = 0; |  |  | let totalDuration = 0; | 
														
													
														
															
																|  |  | const requestId = this.currentRequestId; // 保存当前请求ID |  |  | const requestId = this.currentRequestId; // 保存当前请求ID | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | for (let i = 0; i < segments.length; i++) { |  |  | for (let i = 0; i < segments.length; i++) { | 
														
													
														
															
																|  |  | // 检查是否应该取消请求 |  |  | // 检查是否应该取消请求 | 
														
													
														
															
																|  |  | if (this.shouldCancelRequest || this.currentRequestId !== requestId) { |  |  | if (this.shouldCancelRequest || this.currentRequestId !== requestId) { | 
														
													
												
													
														
															
																|  | @ -518,9 +543,6 @@ export default { | 
														
													
														
															
																|  |  | // 🎯 确保音色ID已加载完成后再获取音频 |  |  | // 🎯 确保音色ID已加载完成后再获取音频 | 
														
													
														
															
																|  |  | if (!this.localVoiceId || this.localVoiceId === '' || this.localVoiceId === null || this.localVoiceId === undefined) { |  |  | if (!this.localVoiceId || this.localVoiceId === '' || this.localVoiceId === null || this.localVoiceId === undefined) { | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 设置加载失败状态 |  |  | // 设置加载失败状态 | 
														
													
														
															
																|  |  | this.isAudioLoading = false; |  |  | this.isAudioLoading = false; | 
														
													
														
															
																|  |  | this.audioLoadFailed = true; |  |  | this.audioLoadFailed = true; | 
														
													
												
													
														
															
																|  | @ -732,12 +754,20 @@ export default { | 
														
													
														
															
																|  |  | currentHighlightIndex: this.currentHighlightIndex |  |  | currentHighlightIndex: this.currentHighlightIndex | 
														
													
														
															
																|  |  | }); |  |  | }); | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 立即使用audioManager播放第一个音频 |  |  |  | 
														
													
														
															
																|  |  | const firstAudioData = this.currentPageAudios[0]; |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 立即使用audioManager播放第一个非导语音频 | 
														
													
														
															
																|  |  | if (autoPlay || !this.isVoiceChanging) { |  |  | if (autoPlay || !this.isVoiceChanging) { | 
														
													
														
															
																|  |  | audioManager.playAudio(firstAudioData.url, 'sentence', { playbackRate: this.playSpeed }); |  |  |  | 
														
													
														
															
																|  |  | this.isPlaying = true; |  |  |  | 
														
													
														
															
																|  |  | this.updateHighlightIndex(); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 查找第一个非导语音频 | 
														
													
														
															
																|  |  |  |  |  | const firstNonLeadIndex = this.findFirstNonLeadAudio(); | 
														
													
														
															
																|  |  |  |  |  | if (firstNonLeadIndex >= 0 && firstNonLeadIndex < this.currentPageAudios.length) { | 
														
													
														
															
																|  |  |  |  |  | // 设置当前音频索引为第一个非导语音频 | 
														
													
														
															
																|  |  |  |  |  | this.currentAudioIndex = firstNonLeadIndex; | 
														
													
														
															
																|  |  |  |  |  | const firstAudioData = this.currentPageAudios[firstNonLeadIndex]; | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | console.log(`🎵 getCurrentPageAudio 自动播放(跳过导语): 索引=${firstNonLeadIndex}, isLead=${firstAudioData.isLead}`); | 
														
													
														
															
																|  |  |  |  |  | audioManager.playAudio(firstAudioData.url, 'sentence', { playbackRate: this.playSpeed }); | 
														
													
														
															
																|  |  |  |  |  | this.isPlaying = true; | 
														
													
														
															
																|  |  |  |  |  | this.updateHighlightIndex(); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
												
													
														
															
																|  | @ -1098,14 +1128,40 @@ export default { | 
														
													
														
															
																|  |  | return; |  |  | return; | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 如果当前索引无效,重置为第一个非导语音频 | 
														
													
														
															
																|  |  | if (this.currentAudioIndex < 0 || this.currentAudioIndex >= this.currentPageAudios.length) { |  |  | if (this.currentAudioIndex < 0 || this.currentAudioIndex >= this.currentPageAudios.length) { | 
														
													
														
															
																|  |  | console.error('🎵 playAudio: 音频索引无效', this.currentAudioIndex); |  |  |  | 
														
													
														
															
																|  |  | return; |  |  |  | 
														
													
														
															
																|  |  |  |  |  | console.log('🎵 playAudio: 音频索引无效,重置为第一个非导语音频'); | 
														
													
														
															
																|  |  |  |  |  | this.currentAudioIndex = this.findFirstNonLeadAudio(); | 
														
													
														
															
																|  |  |  |  |  | if (this.currentAudioIndex < 0) { | 
														
													
														
															
																|  |  |  |  |  | console.error('🎵 playAudio: 找不到有效的音频'); | 
														
													
														
															
																|  |  |  |  |  | return; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | let currentAudioData = this.currentPageAudios[this.currentAudioIndex]; |  |  | let currentAudioData = this.currentPageAudios[this.currentAudioIndex]; | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 如果当前音频是导语,跳转到下一个非导语音频 | 
														
													
														
															
																|  |  |  |  |  | if (currentAudioData && currentAudioData.isLead) { | 
														
													
														
															
																|  |  |  |  |  | console.log(`🎵 playAudio: 当前音频是导语(索引=${this.currentAudioIndex}),查找下一个非导语音频`); | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 从当前索引开始查找下一个非导语音频 | 
														
													
														
															
																|  |  |  |  |  | let nextNonLeadIndex = -1; | 
														
													
														
															
																|  |  |  |  |  | for (let i = this.currentAudioIndex; i < this.currentPageAudios.length; i++) { | 
														
													
														
															
																|  |  |  |  |  | const audioData = this.currentPageAudios[i]; | 
														
													
														
															
																|  |  |  |  |  | if (audioData && !audioData.isLead) { | 
														
													
														
															
																|  |  |  |  |  | nextNonLeadIndex = i; | 
														
													
														
															
																|  |  |  |  |  | break; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  | if (nextNonLeadIndex >= 0) { | 
														
													
														
															
																|  |  |  |  |  | this.currentAudioIndex = nextNonLeadIndex; | 
														
													
														
															
																|  |  |  |  |  | currentAudioData = this.currentPageAudios[this.currentAudioIndex]; | 
														
													
														
															
																|  |  |  |  |  | console.log(`🎵 playAudio: 跳转到非导语音频,新索引=${this.currentAudioIndex}, isLead=${currentAudioData.isLead}`); | 
														
													
														
															
																|  |  |  |  |  | } else { | 
														
													
														
															
																|  |  |  |  |  | console.warn('🎵 playAudio: 没有找到非导语音频,播放当前音频'); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | if (!currentAudioData || !currentAudioData.url) { |  |  | if (!currentAudioData || !currentAudioData.url) { | 
														
													
														
															
																|  |  | console.error('🎵 playAudio: 音频数据无效', currentAudioData); |  |  | console.error('🎵 playAudio: 音频数据无效', currentAudioData); | 
														
													
												
													
														
															
																|  | @ -2518,7 +2574,7 @@ export default { | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 添加小延迟,避免请求过于频繁 |  |  | // 添加小延迟,避免请求过于频繁 | 
														
													
														
															
																|  |  | if (i < allTextPages.length - 1) { |  |  | if (i < allTextPages.length - 1) { | 
														
													
														
															
																|  |  | await new Promise(resolve => setTimeout(resolve, 200)); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | await new Promise(resolve => setTimeout(resolve, 100)); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | } catch (error) { |  |  | } catch (error) { | 
														
													
														
															
																|  |  | console.error(`预加载第 ${pageInfo.pageIndex} 页音频失败:`, error); |  |  | console.error(`预加载第 ${pageInfo.pageIndex} 页音频失败:`, error); | 
														
													
												
													
														
															
																|  | @ -2572,7 +2628,7 @@ export default { | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 延迟一下,避免请求过于频繁 |  |  | // 延迟一下,避免请求过于频繁 | 
														
													
														
															
																|  |  | await new Promise(resolve => setTimeout(resolve, 300)); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | await new Promise(resolve => setTimeout(resolve, 150)); | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | } catch (error) { |  |  | } catch (error) { | 
														
													
														
															
																|  |  | console.error(`预加载第${pageInfo.pageIndex + 1}页音频失败:`, error); |  |  | console.error(`预加载第${pageInfo.pageIndex + 1}页音频失败:`, error); | 
														
													
												
													
														
															
																|  | @ -2693,9 +2749,9 @@ export default { | 
														
													
														
															
																|  |  | console.error(`第${pageIndex + 1}页第${i + 1}个文本项处理异常:`, error); |  |  | console.error(`第${pageIndex + 1}页第${i + 1}个文本项处理异常:`, error); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
														
															
																|  |  | // 每个文本项处理之间间隔300ms,避免请求过于频繁 |  |  |  | 
														
													
														
															
																|  |  |  |  |  | // 每个文本项处理之间间隔150ms,避免请求过于频繁 | 
														
													
														
															
																|  |  | if (i < textItems.length - 1) { |  |  | if (i < textItems.length - 1) { | 
														
													
														
															
																|  |  | await new Promise(resolve => setTimeout(resolve, 300)); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | await new Promise(resolve => setTimeout(resolve, 150)); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  |  |  |  |  | 
														
													
												
													
														
															
																|  | 
 |