diff --git a/subPages/home/AudioControls.vue b/subPages/home/AudioControls.vue index e5df1a0..41bab23 100644 --- a/subPages/home/AudioControls.vue +++ b/subPages/home/AudioControls.vue @@ -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; } } diff --git a/subPages/home/book.vue b/subPages/home/book.vue index ebad9bd..0cb8dc2 100644 --- a/subPages/home/book.vue +++ b/subPages/home/book.vue @@ -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)"> { // 再次检查是否应该阻止自动滚动 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() }); // 预加载后续几页的内容(异步执行,不阻塞当前页面显示)