Browse Source

'提交'

hfll
hflllll 1 month ago
parent
commit
61b54a1ade
4 changed files with 1056 additions and 147 deletions
  1. +1
    -1
      config/index.js
  2. +57
    -5
      pages/components/SplashScreen.vue
  3. +771
    -115
      subPages/home/AudioControls.vue
  4. +227
    -26
      subPages/home/book.vue

+ 1
- 1
config/index.js View File

@ -12,7 +12,7 @@ const envParam = {
prod: 'production',
}
const env = envParam['test']
const env = envParam['dev']
// 全局配置
const config = {


+ 57
- 5
pages/components/SplashScreen.vue View File

@ -6,6 +6,8 @@
:src="splashContent"
mode="scaleToFill"
class="splash-image"
@error="onImageError"
@load="onImageLoad"
/>
</view>
@ -48,7 +50,24 @@ export default {
},
computed: {
image() {
return this.configParamContent('creen_image') || uni.getStorageSync('screen_image')
try {
//
const configImage = this.configParamContent && this.configParamContent('creen_image')
if (configImage && configImage !== 'undefined' && configImage !== '') {
return configImage
}
//
const storageImage = uni.getStorageSync('screen_image')
if (storageImage && storageImage !== 'undefined' && storageImage !== '') {
return storageImage
}
return ''
} catch (error) {
console.error('獲取開屏圖片失敗:', error)
return ''
}
}
},
mounted() {
@ -63,17 +82,38 @@ export default {
//
async initSplash() {
try {
//
this.splashContent = this.image
// store
await this.$nextTick()
//
if (this.splashContent) {
// URL使使
let imageUrl = ''
//
if (this.$store.state.configList && this.$store.state.configList['creen_image']) {
imageUrl = this.configParamContent('creen_image')
}
//
if (!imageUrl) {
imageUrl = uni.getStorageSync('screen_image')
}
console.log('開屏圖片URL:', imageUrl)
// URL
if (imageUrl && imageUrl !== 'undefined' && imageUrl !== '') {
this.splashContent = imageUrl
this.countdown = this.duration
this.showSplash = true
this.startCountdown()
} else {
console.log('沒有開屏圖片,跳過開屏動畫')
this.$emit('close')
}
} catch (error) {
console.error('獲取開動頁面內容失敗:', error)
//
this.$emit('close')
}
},
@ -103,6 +143,18 @@ export default {
clearInterval(this.timer)
this.timer = null
}
},
//
onImageLoad() {
console.log('開屏圖片加載成功')
},
//
onImageError(e) {
console.error('開屏圖片加載失敗:', e)
//
this.closeSplash()
}
}
}


+ 771
- 115
subPages/home/AudioControls.vue
File diff suppressed because it is too large
View File


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

@ -40,9 +40,9 @@
<image :src="configParamContent('highlight_icon')" class="card-line-image" mode="aspectFill" />
<text class="card-line-text">划线重点</text>
</view>
<view v-for="(item, index) in page" :key="index">
<image class="card-image" v-if="item.type === 'image'" :src="item.imageUrl" mode="aspectFill"></image>
<view class="english-text-container" v-else-if="item.type === 'text' && item.language === 'en'">
<view v-for="(item, itemIndex) in page" :key="itemIndex">
<image class="card-image" v-if="item && item.type === 'image'" :src="item.imageUrl" mode="aspectFill"></image>
<view class="english-text-container clickable-text" v-else-if="item && item.type === 'text' && item.language === 'en' && item.content" @click.stop="handleTextClick(item.content, item, index)">
<text
v-for="(token, tokenIndex) in splitEnglishSentence(item.content)"
:key="tokenIndex"
@ -52,17 +52,19 @@
user-select
>{{ token.text }}</text>
</view>
<text class="chinese-text" v-else-if="item.type === 'text' && item.language === 'zh'" user-select>{{ item.content }}</text>
<view v-else-if="item && item.type === 'text' && item.language === 'zh' && item.content" @click.stop="handleTextClick(item.content, item, index)">
<text class="chinese-text clickable-text" user-select>{{ item.content }}</text>
</view>
</view>
</view>
<view v-else>
<view v-for="(item, index) in page" :key="index">
<view v-for="(item, itemIndex) in page" :key="itemIndex">
<!-- 文本页面 -->
<view v-if="item.type === 'text'" class="text-content" >
<view :class="{ 'text-highlight': isTextHighlighted(page, index) }">
<view v-if="item && item.type === 'text' && item.content" class="text-content" >
<view :class="{ 'text-highlight': isTextHighlighted(page, itemIndex) }" @click.stop="handleTextClick(item.content, item, index)">
<text
class="content-text"
class="content-text clickable-text"
user-select
>
{{ item.content }}
@ -318,9 +320,103 @@ export default {
this.currentHighlightIndex = audioState.currentHighlightIndex;
},
onHighlightChange(highlightIndex) {
//
this.currentHighlightIndex = highlightIndex;
//
handleTextClick(textContent, item, pageIndex) {
console.log('点击文本:', textContent);
console.log('textContent类型:', typeof textContent);
console.log('textContent是否为undefined:', textContent === undefined);
console.log('完整item对象:', item);
console.log('item.content:', item ? item.content : 'item为空');
console.log('当前页面索引:', this.currentPage);
console.log('点击的页面索引:', pageIndex);
console.log('当前页面数据:', this.bookPages[this.currentPage - 1]);
console.log('页面数据长度:', this.bookPages[this.currentPage - 1] ? this.bookPages[this.currentPage - 1].length : '页面不存在');
//
if (pageIndex !== undefined && pageIndex !== this.currentPage - 1) {
console.log('点击的不是当前页面,忽略点击事件');
return;
}
//
if (!item) {
console.error('handleTextClick: item参数为空');
uni.showToast({
title: '数据错误,请刷新页面',
icon: 'none'
});
return;
}
// textContentundefineditem
if (!textContent && item && item.content) {
textContent = item.content;
console.log('从item中获取到content:', textContent);
}
// textContent
if (!textContent || typeof textContent !== 'string' || textContent.trim() === '') {
console.error('handleTextClick: 无效的文本内容', textContent);
uni.showToast({
title: '文本内容无效',
icon: 'none'
});
return;
}
//
if (!this.$refs.audioControls) {
console.log('音频控制组件未找到');
uni.showToast({
title: '音频控制组件未准备好',
icon: 'none'
});
return;
}
//
if (!this.isTextPage) {
console.log('当前页面不是文本页面');
uni.showToast({
title: '当前页面不支持音频播放',
icon: 'none'
});
return;
}
// AudioControls
const success = this.$refs.audioControls.playSpecificAudio(textContent);
if (success) {
console.log('成功播放指定音频段落');
} else {
console.log('播放指定音频段落失败');
}
},
onHighlightChange(highlightData) {
//
if (typeof highlightData === 'number') {
//
this.currentHighlightIndex = highlightData;
} else if (typeof highlightData === 'object' && highlightData !== null) {
//
this.currentHighlightIndex = highlightData.highlightIndex;
//
if (highlightData.isSegmented) {
console.log('分段音频高亮:', {
highlightIndex: highlightData.highlightIndex,
segmentIndex: highlightData.segmentIndex,
startIndex: highlightData.startIndex,
endIndex: highlightData.endIndex,
currentText: highlightData.currentText
});
}
} else {
//
this.currentHighlightIndex = -1;
}
},
@ -409,9 +505,9 @@ export default {
console.log('單詞語音API響應:', audioRes);
//
if (audioRes && audioRes.result && audioRes.result.audio) {
// 使URL
const audioUrl = audioRes.result.audio;
if (audioRes && audioRes.result && audioRes.result.url) {
// 使url
const audioUrl = audioRes.result.url;
//
const audio = uni.createInnerAudioContext();
@ -1203,9 +1299,19 @@ export default {
await this.getBookPages(this.courseIdList[this.currentPage - 1]);
}
//
//
if (this.$refs.audioControls) {
this.$refs.audioControls.resetAudioState();
//
const hasPreloadedAudio = this.$refs.audioControls.checkAudioCache(this.currentPage);
if (hasPreloadedAudio) {
//
console.log(`${this.currentPage}页音频已预加载,自动播放`);
this.$refs.audioControls.autoPlayCachedAudio();
} else {
//
this.$refs.audioControls.resetAudioState();
}
}
},
async onSwiperChange(e) {
@ -1215,9 +1321,19 @@ export default {
await this.getBookPages(this.courseIdList[this.currentPage - 1]);
}
//
//
if (this.$refs.audioControls) {
this.$refs.audioControls.resetAudioState();
//
const hasPreloadedAudio = this.$refs.audioControls.checkAudioCache(this.currentPage);
if (hasPreloadedAudio) {
//
console.log(`${this.currentPage}页音频已预加载,自动播放`);
this.$refs.audioControls.autoPlayCachedAudio();
} else {
//
this.$refs.audioControls.resetAudioState();
}
}
},
async getCourseList(id) {
@ -1241,6 +1357,8 @@ export default {
//
if (this.courseIdList.length > 0) {
await this.getBookPages(this.courseIdList[0])
//
this.preloadNextPages()
}
}
},
@ -1250,10 +1368,18 @@ export default {
})
if (res.code === 200) {
// 使$set
console.log('获取到的页面数据:', JSON.parse(res.result.content))
const rawPageData = JSON.parse(res.result.content)
console.log('获取到的原始页面数据:', rawPageData)
//
const filteredPageData = rawPageData.filter(item => {
return item && typeof item === 'object' && (item.type || item.content)
})
console.log('过滤后的页面数据:', filteredPageData)
//
if (this.currentPage - 1 < this.bookPages.length) {
this.$set(this.bookPages, this.currentPage - 1, JSON.parse(res.result.content))
this.$set(this.bookPages, this.currentPage - 1, filteredPageData)
//
this.$set(this.pageTitles, this.currentPage - 1, res.result.title || '')
//
@ -1304,6 +1430,75 @@ export default {
console.log('缓存大小已限制,删除了', keysToDelete.length, '个缓存项');
}
},
//
async preloadNextPages() {
try {
console.log('开始预加载后续页面内容');
// 2-3
const preloadCount = Math.min(3, this.courseIdList.length - 1); // 3
//
for (let i = 1; i <= preloadCount; i++) {
if (i < this.courseIdList.length && this.bookPages[i].length === 0) {
try {
console.log(`预加载第${i + 1}页内容`);
await this.preloadSinglePage(this.courseIdList[i], i);
// 800ms
if (i < preloadCount) {
await new Promise(resolve => setTimeout(resolve, 800));
}
} catch (error) {
console.error(`预加载第${i + 1}页失败:`, error);
//
}
}
}
console.log('页面内容预加载完成');
// 1.5AudioControls
setTimeout(() => {
if (this.$refs.audioControls) {
this.$refs.audioControls.startPreloadAudio();
}
}, 1500);
} catch (error) {
console.error('预加载页面内容失败:', error);
}
},
//
async preloadSinglePage(courseId, pageIndex) {
try {
const res = await this.$api.book.coursesPageDetail({
id: courseId
});
if (res.code === 200) {
const rawPageData = JSON.parse(res.result.content);
const filteredPageData = rawPageData.filter(item => {
return item && typeof item === 'object' && (item.type || item.content);
});
// 使$set
this.$set(this.bookPages, pageIndex, filteredPageData);
this.$set(this.pageTitles, pageIndex, res.result.title || '');
this.$set(this.pageTypes, pageIndex, res.result.type || '');
this.$set(this.pageWords, pageIndex, res.result.words || []);
this.$set(this.pagePay, pageIndex, res.result.pay || 'N');
console.log(`${pageIndex + 1}页内容预加载完成`);
}
} catch (error) {
console.error(`预加载第${pageIndex + 1}页失败:`, error);
throw error;
}
},
//
async autoLoadAndPlayFirstPage() {
try {
@ -1318,12 +1513,8 @@ export default {
//
if (this.currentPageAudios && this.currentPageAudios.length > 0) {
console.log('音頻加載成功,開始自動播放');
//
setTimeout(() => {
this.playAudio();
}, 500);
console.log('音頻加載成功,getCurrentPageAudio已經自動播放第一個音頻');
// getCurrentPageAudio調playAudio
} else {
console.log('第一頁沒有音頻數據');
}
@ -1635,6 +1826,16 @@ export default {
transition: all 0.3s ease;
}
.clickable-text {
cursor: pointer;
&:active {
background-color: rgba(6, 218, 220, 0.1);
border-radius: 4rpx;
}
}
.text-highlight {
background-color: $primary-color;
// color: #fff;


Loading…
Cancel
Save