|
|
|
@ -6,13 +6,13 @@ |
|
|
|
</view> |
|
|
|
|
|
|
|
<!-- 音频加载中 --> |
|
|
|
<view v-else-if="isTextPage && isAudioLoading" class="audio-loading-container"> |
|
|
|
<view v-else-if="shouldLoadAudio && isAudioLoading" class="audio-loading-container"> |
|
|
|
<uv-loading-icon mode="spinner" size="30" color="#06DADC"></uv-loading-icon> |
|
|
|
<text class="loading-text">第{{currentPage}}页音频加载中,请稍等...</text> |
|
|
|
</view> |
|
|
|
|
|
|
|
<!-- 正常音频控制栏 --> |
|
|
|
<view v-else-if="isTextPage && hasAudioData" class="audio-controls"> |
|
|
|
<view v-else-if="shouldLoadAudio && hasAudioData" class="audio-controls"> |
|
|
|
<!-- 加载指示器 --> |
|
|
|
<view v-if="isAudioLoading" class="loading-indicator"> |
|
|
|
<uv-loading-icon mode="spinner" size="16" color="#06DADC"></uv-loading-icon> |
|
|
|
@ -274,6 +274,16 @@ export default { |
|
|
|
} |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
// 查找第一个非导语音频的索引 |
|
|
|
findFirstNonLeadAudioIndex() { |
|
|
|
for (let i = 0; i < this.currentPageAudios.length; i++) { |
|
|
|
if (!this.currentPageAudios[i].isLead) { |
|
|
|
return i; |
|
|
|
} |
|
|
|
} |
|
|
|
return -1; // 如果所有音频都是导语,返回-1 |
|
|
|
}, |
|
|
|
|
|
|
|
// 创建HTML5 Audio实例并包装为uni-app兼容接口 |
|
|
|
createHTML5Audio() { |
|
|
|
const audio = new Audio(); |
|
|
|
@ -426,7 +436,9 @@ export default { |
|
|
|
this.totalTime = cachedAudio.totalDuration || 0; |
|
|
|
this.hasAudioData = true; |
|
|
|
this.isAudioLoading = false; |
|
|
|
this.currentAudioIndex = 0; |
|
|
|
// 设置初始音频索引为第一个非导语音频 |
|
|
|
const firstNonLeadIndex = this.findFirstNonLeadAudioIndex(); |
|
|
|
this.currentAudioIndex = firstNonLeadIndex >= 0 ? firstNonLeadIndex : 0; |
|
|
|
this.currentTime = 0; |
|
|
|
this.currentHighlightIndex = -1; |
|
|
|
|
|
|
|
@ -768,9 +780,27 @@ export default { |
|
|
|
} |
|
|
|
|
|
|
|
if (currentPageData) { |
|
|
|
// 收集所有text类型的元素 |
|
|
|
const textItems = currentPageData.filter(item => item.type === 'text'); |
|
|
|
console.log(`🎵 getCurrentPageAudio: 找到${textItems.length}个文本项:`, textItems.map(item => item.content?.substring(0, 50) + '...')); |
|
|
|
// 收集所有text类型的元素,但排除导语(isLead为true的元素) |
|
|
|
// 对于重点卡片页面,还需要检查language属性 |
|
|
|
const textItems = currentPageData.filter(item => { |
|
|
|
if (item.type !== 'text' || item.isLead) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// 检查当前页面类型 |
|
|
|
const currentPageType = this.bookPages && this.bookPages[this.currentPage - 1] |
|
|
|
? (this.bookPages[this.currentPage - 1].some(pageItem => pageItem.type === 'image') ? '1' : '0') |
|
|
|
: '0'; |
|
|
|
|
|
|
|
// 如果是重点卡片页面,需要有language属性 |
|
|
|
if (currentPageType === '1') { |
|
|
|
return item.content && (item.language === 'en' || item.language === 'zh'); |
|
|
|
} |
|
|
|
|
|
|
|
// 普通文本页面,只需要有content |
|
|
|
return item.content; |
|
|
|
}); |
|
|
|
console.log(`🎵 getCurrentPageAudio: 找到${textItems.length}个文本项(已排除导语):`, textItems.map(item => item.content?.substring(0, 50) + '...')); |
|
|
|
|
|
|
|
if (textItems.length > 0) { |
|
|
|
let firstAudioPlayed = false; // 标记是否已播放第一个音频 |
|
|
|
@ -811,7 +841,8 @@ export default { |
|
|
|
endIndex: segment.endIndex, |
|
|
|
segmentIndex: segment.segmentIndex, |
|
|
|
originalTextIndex: index, // 标记属于哪个原始文本项 |
|
|
|
isSegmented: batchResult.audioSegments.length > 1 // 标记是否为分段音频 |
|
|
|
isSegmented: batchResult.audioSegments.length > 1, // 标记是否为分段音频 |
|
|
|
isLead: item.isLead || false // 标记是否为导语 |
|
|
|
}; |
|
|
|
this.currentPageAudios.push(audioData); |
|
|
|
loadedAudiosCount++; |
|
|
|
@ -822,7 +853,9 @@ export default { |
|
|
|
if (!firstAudioPlayed && this.currentPageAudios.length > 0) { |
|
|
|
firstAudioPlayed = true; |
|
|
|
this.hasAudioData = true; |
|
|
|
this.currentAudioIndex = 0; |
|
|
|
// 设置初始音频索引为第一个非导语音频 |
|
|
|
const firstNonLeadIndex = this.findFirstNonLeadAudioIndex(); |
|
|
|
this.currentAudioIndex = firstNonLeadIndex >= 0 ? firstNonLeadIndex : 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -1828,6 +1861,13 @@ export default { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 如果当前音频是导语,不进行高亮 |
|
|
|
if (currentAudio.isLead) { |
|
|
|
this.currentHighlightIndex = -1; |
|
|
|
this.emitHighlightChange(-1); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 检查音频数据是否属于当前页面,防止页面切换时的数据错乱 |
|
|
|
const audioCacheKey = `${this.courseId}_${this.currentPage}_${this.localVoiceId}`; |
|
|
|
const currentPageCache = this.audioCache[audioCacheKey]; |
|
|
|
@ -1921,9 +1961,24 @@ export default { |
|
|
|
// 音频播放结束处理 |
|
|
|
onAudioEnded() { |
|
|
|
if (this.currentAudioIndex < this.currentPageAudios.length - 1) { |
|
|
|
// 播放下一个音频 |
|
|
|
this.currentAudioIndex++; |
|
|
|
this.playAudio(); |
|
|
|
// 查找下一个非导语音频 |
|
|
|
let nextIndex = this.currentAudioIndex + 1; |
|
|
|
while (nextIndex < this.currentPageAudios.length && this.currentPageAudios[nextIndex].isLead) { |
|
|
|
console.log(`🎵 跳过导语音频: ${this.currentPageAudios[nextIndex].text}`); |
|
|
|
nextIndex++; |
|
|
|
} |
|
|
|
|
|
|
|
if (nextIndex < this.currentPageAudios.length) { |
|
|
|
// 找到下一个非导语音频,播放它 |
|
|
|
this.currentAudioIndex = nextIndex; |
|
|
|
this.playAudio(); |
|
|
|
} else { |
|
|
|
// 没有更多非导语音频,结束播放 |
|
|
|
this.isPlaying = false; |
|
|
|
this.currentTime = this.totalTime; |
|
|
|
this.currentHighlightIndex = -1; |
|
|
|
this.$emit('highlight-change', -1); |
|
|
|
} |
|
|
|
|
|
|
|
// 滚动到下一段音频对应的文字 |
|
|
|
// setTimeout(() => { |
|
|
|
@ -1933,9 +1988,22 @@ export default { |
|
|
|
} else { |
|
|
|
// 所有音频播放完毕 |
|
|
|
if (this.isLoop) { |
|
|
|
// 循环播放 |
|
|
|
this.currentAudioIndex = 0; |
|
|
|
this.playAudio(); |
|
|
|
// 循环播放,从第一个非导语音频开始 |
|
|
|
let firstNonLeadIndex = 0; |
|
|
|
while (firstNonLeadIndex < this.currentPageAudios.length && this.currentPageAudios[firstNonLeadIndex].isLead) { |
|
|
|
firstNonLeadIndex++; |
|
|
|
} |
|
|
|
|
|
|
|
if (firstNonLeadIndex < this.currentPageAudios.length) { |
|
|
|
this.currentAudioIndex = firstNonLeadIndex; |
|
|
|
this.playAudio(); |
|
|
|
} else { |
|
|
|
// 所有音频都是导语,停止播放 |
|
|
|
this.isPlaying = false; |
|
|
|
this.currentTime = this.totalTime; |
|
|
|
this.currentHighlightIndex = -1; |
|
|
|
this.$emit('highlight-change', -1); |
|
|
|
} |
|
|
|
|
|
|
|
// 滚动到第一段音频对应的文字 |
|
|
|
// setTimeout(() => { |
|
|
|
|