Browse Source

fix(音频控制): 修复音频加载过程中参数不一致问题

在音频加载前对关键参数做快照,确保整个流程参数一致
添加元素位置缓存优化滚动性能
修复duration未定义时的默认值处理
main
前端-胡立永 3 days ago
parent
commit
3cf55eb7f2
2 changed files with 50 additions and 41 deletions
  1. +17
    -15
      subPages/home/AudioControls.vue
  2. +33
    -26
      subPages/home/book.vue

+ 17
- 15
subPages/home/AudioControls.vue View File

@ -581,7 +581,12 @@ export default {
console.log('this.audioCache:', this.audioCache);
//
const cacheKey = generateCacheKey(this.courseId, this.currentPage, this.localVoiceId);
//
const loadCourseId = this.courseId;
const loadPage = this.currentPage;
const loadVoiceId = this.localVoiceId;
const cacheKey = generateCacheKey(loadCourseId, loadPage, loadVoiceId);
if (this.audioCache[cacheKey]) {
//
@ -633,15 +638,15 @@ export default {
try {
// [] text
const currentPageData = this.bookPages[this.currentPage - 1];
console.log(`🎵 getCurrentPageAudio: 当前页面=${this.currentPage}, 音色ID=${this.localVoiceId}, 课程ID=${this.courseId}`);
const currentPageData = this.bookPages[loadPage - 1];
console.log(`🎵 getCurrentPageAudio: 当前页面=${loadPage}, 音色ID=${loadVoiceId}, 课程ID=${loadCourseId}`);
console.log(`🎵 getCurrentPageAudio: bookPages长度=${this.bookPages.length}, 当前页面数据:`, currentPageData);
//
if (!currentPageData || currentPageData.length === 0) {
console.log(`🎵 getCurrentPageAudio: 当前页面数据为空,可能还在加载中`);
//
this.$emit('page-data-needed', this.currentPage);
this.$emit('page-data-needed', loadPage);
//
this.isAudioLoading = false;
@ -681,7 +686,7 @@ export default {
// 使
const batchResult = await this.requestAudioInBatches(item.content, this.localVoiceId);
const batchResult = await this.requestAudioInBatches(item.content, loadVoiceId);
//
if (batchResult === null) {
@ -703,7 +708,7 @@ export default {
isLead : item.isLead,
url: segment.url,
text: segment.text,
duration: segment.duration,
duration: segment.duration || 0,
startIndex: segment.startIndex,
endIndex: segment.endIndex,
segmentIndex: segment.segmentIndex,
@ -759,19 +764,17 @@ export default {
}
}
//
if (this.currentPageAudios.length > 0) {
await this.calculateTotalDuration();
//
const cacheKey = generateCacheKey(this.courseId, this.currentPage, this.localVoiceId);
const cacheKey = generateCacheKey(loadCourseId, loadPage, loadVoiceId);
this.audioCache[cacheKey] = {
audios: [...this.currentPageAudios], //
totalDuration: this.totalTime,
voiceId: this.localVoiceId, // ID
pageNumber: this.currentPage, //
voiceId: loadVoiceId, // ID
pageNumber: loadPage, //
timestamp: Date.now() //
};
@ -1620,7 +1623,7 @@ export default {
const highlightData = {
highlightIndex: currentAudioData.originalTextIndex !== undefined ? currentAudioData.originalTextIndex : highlightIndex,
isSegmented: currentAudioData.isSegmented || false,
segmentIndex: currentAudioData.segmentIndex || 0,
segmentIndex: currentAudioData.segmentIndex,
startIndex: currentAudioData.startIndex || 0,
endIndex: currentAudioData.endIndex || 0,
currentText: currentAudioData.text || ''
@ -2244,7 +2247,6 @@ export default {
//
clearAudioCache() {
this.audioCache = {};
},
// 访
@ -2717,7 +2719,7 @@ export default {
isLead: item.isLead,
url: segment.url,
text: segment.text,
duration: segment.duration,
duration: segment.duration || 0,
startIndex: segment.startIndex,
endIndex: segment.endIndex,
segmentIndex: segment.segmentIndex,
@ -2725,7 +2727,7 @@ export default {
isSegmented: batchResult.audioSegments.length > 1 //
});
totalDuration += segment.duration;
totalDuration += segment.duration || 0;
}
}


+ 33
- 26
subPages/home/book.vue View File

@ -57,6 +57,7 @@
'lead-text': isCardTextHighlighted(page, itemIndex),
'introduction-text' : item.isLead,
}"
:id="`text-${itemIndex}`"
v-else-if="item && item.type === 'text' && item.content"
@click.stop="handleTextClick(item.content, item, index)">
<text v-for="(segment, segmentIndex) in processChineseText(item.content)"
@ -211,6 +212,8 @@ export default {
pageWords: [],
//
pagePay: [],
elementPositionsCache: {}, //
}
},
onShow() {
@ -519,19 +522,6 @@ export default {
});
},
//
// onScrollToText(refName) {
// try {
// console.log('🎯 onScrollToText :', refName);
//
// // scrollTo
// this.$scrollTo(refName);
//
// } catch (error) {
// console.error(' onScrollToText :', error);
// }
// },
//
handleTextClick(textContent, item, pageIndex) {
@ -724,7 +714,7 @@ export default {
//
if (this.shouldPreventAutoScroll()) {
console.log('🚫 用户正在手动滚动,跳过自动滚动到文本');
// console.log('🚫 ');
return;
}
@ -736,7 +726,7 @@ export default {
this.scrollDebounceTimer = setTimeout(() => {
//
if (this.shouldPreventAutoScroll()) {
console.log('🚫 防抖延迟后检测到用户手动滚动,跳过自动滚动到文本');
// console.log('🚫 ');
return;
}
this.performScrollToText(scrollData);
@ -747,7 +737,7 @@ export default {
performScrollToText(scrollData) {
//
if (this.shouldPreventAutoScroll()) {
console.log('🚫 执行滚动前检测到用户手动操作,取消自动滚动');
// console.log('🚫 ');
return;
}
@ -845,13 +835,13 @@ export default {
}
} else {
// 使
console.log('🔄 精确计算失败,使用备用查询方法');
this.fallbackScrollToText(selector, resetScrollingState, safetyTimeout);
console.error('🔄 精确计算失败,使用备用查询方法');
//this.fallbackScrollToText(selector, resetScrollingState, safetyTimeout);
}
} catch (error) {
console.error('❌ 精确滚动计算失败:', error);
// 使
this.fallbackScrollToText(selector, resetScrollingState, safetyTimeout);
//this.fallbackScrollToText(selector, resetScrollingState, safetyTimeout);
}
});
},
@ -966,6 +956,13 @@ export default {
//
async getAllElementPositions() {
return new Promise((resolve) => {
//
if (this.elementPositionsCache[this.currentPage - 1]) {
resolve(this.elementPositionsCache[this.currentPage - 1]);
return;
}
const currentPageData = this.bookPages[this.currentPage - 1];
if (!currentPageData || !Array.isArray(currentPageData)) {
resolve([]);
@ -993,6 +990,7 @@ export default {
query.exec((res) => {
const containerRect = res[0];
console.log('getAllElementPositions res:', res, this.scrollTops[this.currentPage - 1]);
if (!containerRect) {
resolve([]);
return;
@ -1004,12 +1002,14 @@ export default {
if (item && (item.type === 'text' || item.type === 'image' || item.type === 'video')) {
const elementRect = res[resultIndex];
if (elementRect) {
let top = elementRect.top - (containerRect.height / 2);
elementPositions.push({
id : elementRect.id,
index: index,
type: item.type,
top: elementRect.top - containerRect.top,
top: top,
height: elementRect.height,
bottom: elementRect.top - containerRect.top + elementRect.height
bottom: top + elementRect.height
});
}
resultIndex++;
@ -1018,6 +1018,12 @@ export default {
resolve(elementPositions);
});
}).then((elementPositions) => {
//
if (elementPositions.length > 0) {
this.elementPositionsCache[this.currentPage - 1] = elementPositions;
}
return elementPositions;
});
},
@ -1098,10 +1104,10 @@ export default {
let targetElementIndex = -1;
if (scrollData.segmentIndex !== undefined) {
//
targetElementIndex = scrollData.segmentIndex;
} else if (scrollData.highlightIndex !== undefined) {
// if (scrollData.segmentIndex !== undefined) {
// //
// targetElementIndex = scrollData.segmentIndex;
if (scrollData.highlightIndex !== undefined) {
//
targetElementIndex = this.findTextItemIndex(scrollData.highlightIndex);
}
@ -1114,7 +1120,7 @@ export default {
const targetElement = elementPositions.find(pos => pos.index === targetElementIndex && pos.type === 'text');
if (!targetElement) {
console.warn('未找到目标元素位置信息:', targetElementIndex);
console.error('未找到目标元素位置信息:', elementPositions, targetElementIndex);
return null;
}
@ -1859,6 +1865,7 @@ export default {
console.error('课程切换后音频加载失败:', error);
}
}
this.getAllElementPositions()
});
//


Loading…
Cancel
Save