Browse Source

'链接阅读函数和二维码函数'

hfll
hflllll 1 month ago
parent
commit
649c866766
2 changed files with 365 additions and 41 deletions
  1. +264
    -34
      subPages/home/book.vue
  2. +101
    -7
      subPages/user/share.vue

+ 264
- 34
subPages/home/book.vue View File

@ -17,6 +17,7 @@
<swiper
class="content-swiper"
:current="currentPage - 1"
:disable-touch="isAudioLoading"
@change="onSwiperChange"
>
<swiper-item
@ -38,8 +39,15 @@
</view>
<!-- 文本页面 -->
<view v-else-if="item.type === 'text'" class="text-content">
<text class="content-text" user-select>{{ item.content }}</text>
<view v-else-if="item.type === 'text'" class="text-content" >
<view :class="{ 'text-highlight': isTextHighlighted(page, index) }">
<text
class="content-text"
user-select
>
{{ item.content }}
</text>
</view>
</view>
<!-- 文本页面 -->
@ -68,7 +76,22 @@
<!-- 自定义底部控制栏 -->
<view class="custom-tabbar" :class="{ 'tabbar-hidden': !showNavbar }">
<!-- 音频控制栏 -->
<view class="audio-controls" :class="{ 'audio-hidden': !isTextPage }">
<!-- 获取音频按钮 -->
<view v-if="!hasAudioData && !isAudioLoading && isTextPage" class="audio-get-button-container">
<view class="get-audio-btn" @click="handleGetAudio">
<uv-icon name="play-circle" size="24" color="#06DADC"></uv-icon>
<text class="get-audio-text">获取第{{currentPage}}页音频</text>
</view>
</view>
<!-- 音频加载状态 -->
<view v-else-if="isAudioLoading && isTextPage" 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="hasAudioData" class="audio-controls" :class="{ 'audio-hidden': !isTextPage }">
<view class="audio-time">
<text class="time-text">{{ formatTime(currentTime) }}</text>
<view class="progress-container">
@ -245,6 +268,11 @@ export default {
currentAudio: null, //
//
audioCache: {}, // {pageIndex: {audios: [], totalDuration: 0}}
//
isAudioLoading: false, //
hasAudioData: false, //
//
currentHighlightIndex: -1, //
courseIdList: [],
bookTitle: '',
courseList: [
@ -273,6 +301,7 @@ export default {
progressPercent() {
return this.totalTime > 0 ? (this.currentTime / this.totalTime) * 100 : 0;
},
//
currentPageTitle() {
return this.pageTitles[this.currentPage - 1] || this.bookTitle;
@ -294,6 +323,9 @@ export default {
return;
}
//
this.isAudioLoading = true;
//
this.currentPageAudios = [];
this.currentAudioIndex = 0;
@ -376,15 +408,74 @@ export default {
this.limitCacheSize(10);
}
}
//
this.isAudioLoading = false;
//
this.hasAudioData = this.currentPageAudios.length > 0;
},
//
resetAudioState() {
//
const pageKey = `${this.courseId}_${this.currentPage}`;
const cachedAudio = this.audioCache[pageKey];
if (cachedAudio && cachedAudio.audios && cachedAudio.audios.length > 0) {
//
this.currentPageAudios = cachedAudio.audios;
this.totalTime = cachedAudio.totalDuration || 0;
this.hasAudioData = true;
} else {
//
this.currentPageAudios = [];
this.totalTime = 0;
this.hasAudioData = false;
}
//
this.currentAudioIndex = 0;
this.isPlaying = false;
this.currentTime = 0;
this.isAudioLoading = false;
this.currentHighlightIndex = -1;
},
//
async handleGetAudio() {
// ID
if (!this.voiceId) {
uni.showToast({
title: '音色未加载,请稍后重试',
icon: 'none'
});
return;
}
//
if (!this.isTextPage) {
uni.showToast({
title: '当前页面没有文本内容',
icon: 'none'
});
return;
}
//
if (this.isAudioLoading) {
return;
}
//
await this.getCurrentPageAudio();
},
// id
async getVoiceList() {
const voiceRes = await this.$api.music.list()
if(voiceRes.code === 200){
this.voiceId = voiceRes.result.id
console.log('111');
await this.getCurrentPageAudio()
this.voiceId = voiceRes.result[0].id
console.log('获取默认音色ID:', this.voiceId);
}
},
toggleNavbar() {
@ -500,6 +591,8 @@ export default {
this.currentAudio.play();
this.isPlaying = true;
//
this.updateHighlightIndex();
},
//
@ -508,6 +601,8 @@ export default {
this.currentAudio.pause();
}
this.isPlaying = false;
//
this.currentHighlightIndex = -1;
},
//
@ -566,6 +661,43 @@ export default {
totalTime += this.currentAudio.currentTime;
this.currentTime = totalTime;
//
this.updateHighlightIndex();
},
//
updateHighlightIndex() {
if (!this.isPlaying || this.currentPageAudios.length === 0) {
this.currentHighlightIndex = -1;
return;
}
//
this.currentHighlightIndex = this.currentAudioIndex;
console.log('更新高亮索引:', this.currentHighlightIndex, '当前音频索引:', this.currentAudioIndex);
},
//
isTextHighlighted(page, index) {
//
if (page !== this.bookPages[this.currentPage - 1]) return false;
// text
let textIndex = 0;
for (let i = 0; i <= index; i++) {
if (page[i].type === 'text') {
if (i === index) {
const shouldHighlight = textIndex === this.currentHighlightIndex;
if (shouldHighlight) {
console.log('高亮文本:', textIndex, '当前高亮索引:', this.currentHighlightIndex);
}
return shouldHighlight;
}
textIndex++;
}
}
return false;
},
//
@ -584,6 +716,7 @@ export default {
//
this.isPlaying = false;
this.currentTime = this.totalTime;
this.currentHighlightIndex = -1;
}
}
},
@ -604,6 +737,11 @@ export default {
//
previousAudio() {
//
if (this.isAudioLoading) {
return;
}
if (this.currentPageAudios.length === 0) return;
if (this.currentAudioIndex > 0) {
@ -616,6 +754,11 @@ export default {
//
nextAudio() {
//
if (this.isAudioLoading) {
return;
}
if (this.currentPageAudios.length === 0) return;
if (this.currentAudioIndex < this.currentPageAudios.length - 1) {
@ -626,6 +769,11 @@ export default {
}
},
async previousPage() {
//
if (this.isAudioLoading) {
return;
}
if (this.currentPage > 1) {
//
this.pauseAudio();
@ -636,11 +784,16 @@ export default {
await this.getBookPages(this.courseIdList[this.currentPage - 1]);
}
//
await this.getCurrentPageAudio();
//
this.resetAudioState();
}
},
async nextPage() {
//
if (this.isAudioLoading) {
return;
}
if (this.currentPage < this.bookPages.length) {
//
this.pauseAudio();
@ -651,8 +804,8 @@ export default {
await this.getBookPages(this.courseIdList[this.currentPage - 1]);
}
//
await this.getCurrentPageAudio();
//
this.resetAudioState();
}
},
formatTime(seconds) {
@ -674,6 +827,11 @@ export default {
})
},
async goToPage(page) {
//
if (this.isAudioLoading) {
return;
}
//
this.pauseAudio();
@ -684,10 +842,15 @@ export default {
await this.getBookPages(this.courseIdList[this.currentPage - 1]);
}
//
await this.getCurrentPageAudio();
//
this.resetAudioState();
},
async onSwiperChange(e) {
//
if (this.isAudioLoading) {
return;
}
//
this.pauseAudio();
@ -697,8 +860,8 @@ export default {
await this.getBookPages(this.courseIdList[this.currentPage - 1]);
}
//
await this.getCurrentPageAudio();
//
this.resetAudioState();
},
async getCourseList(id) {
const res = await this.$api.book.coursePage({
@ -710,6 +873,8 @@ export default {
this.bookPages = this.courseIdList.map(() => [])
//
this.pageTitles = this.courseIdList.map(() => '')
//
this.resetAudioState()
//
if (this.courseIdList.length > 0) {
await this.getBookPages(this.courseIdList[0])
@ -743,10 +908,31 @@ export default {
index,
}))
}
},
//
clearAudioCache() {
this.audioCache = {};
console.log('音频缓存已清理');
},
// 访
limitCacheSize(maxSize = 10) {
const cacheKeys = Object.keys(this.audioCache);
if (cacheKeys.length > maxSize) {
//
const keysToDelete = cacheKeys.slice(0, cacheKeys.length - maxSize);
keysToDelete.forEach(key => {
delete this.audioCache[key];
});
console.log('缓存大小已限制,删除了', keysToDelete.length, '个缓存项');
}
}
},
async onLoad(args) {
this.courseId = args.courseId
//
this.resetAudioState()
//
await Promise.all([this.getCourseList(this.courseId), this.getCoursePageList(args.bookId)])
await this.getVoiceList()
@ -767,25 +953,6 @@ export default {
//
onHide() {
this.pauseAudio();
},
//
clearAudioCache() {
this.audioCache = {};
console.log('音频缓存已清理');
},
// 访
limitCacheSize(maxSize = 10) {
const cacheKeys = Object.keys(this.audioCache);
if (cacheKeys.length > maxSize) {
//
const keysToDelete = cacheKeys.slice(0, cacheKeys.length - maxSize);
keysToDelete.forEach(key => {
delete this.audioCache[key];
});
console.log('缓存大小已限制,删除了', keysToDelete.length, '个缓存项');
}
}
}
</script>
@ -1003,6 +1170,15 @@ export default {
letter-spacing: 0;
text-align: justify;
word-break: break-all;
transition: all 0.3s ease;
}
.text-highlight {
background-color: $primary-color;
// color: #fff;
// padding: 8rpx 16rpx;
// border-radius: 8rpx;
// box-shadow: 0 2rpx 8rpx rgba(6, 218, 220, 0.3);
}
.custom-tabbar {
@ -1394,4 +1570,58 @@ export default {
justify-content: center;
padding: 10rpx;
}
/* 音频加载状态样式 */
.audio-loading-container {
background: #fff;
padding: 40rpx;
border-bottom: 1rpx solid #eee;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20rpx;
position: relative;
z-index: 10;
}
.loading-text {
font-size: 28rpx;
color: #999;
}
/* 获取音频按钮样式 */
.audio-get-button-container {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
padding: 30rpx;
border-radius: 20rpx;
border: 2rpx solid #E5E5E5;
transition: all 0.3s ease;
position: relative;
z-index: 10;
}
.get-audio-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 16rpx;
padding: 20rpx 40rpx;
background: linear-gradient(135deg, #06DADC 0%, #04B8BA 100%);
border-radius: 50rpx;
box-shadow: 0 8rpx 20rpx rgba(6, 218, 220, 0.3);
transition: all 0.3s ease;
}
.get-audio-btn:active {
transform: scale(0.95);
box-shadow: 0 4rpx 10rpx rgba(6, 218, 220, 0.2);
}
.get-audio-text {
font-size: 32rpx;
color: #FFFFFF;
font-weight: 500;
}
</style>

+ 101
- 7
subPages/user/share.vue View File

@ -44,22 +44,116 @@ export default {
icon: 'none'
})
},
save() {
async save() {
try {
//
const authResult = await this.checkPhotoAlbumAuth();
if (authResult.authSetting['scope.writePhotosAlbum'] === true) {
//
this.saveToAlbum();
} else if (authResult.authSetting['scope.writePhotosAlbum'] === false) {
//
this.showAuthGuide();
} else {
//
this.requestPhotoAlbumAuth();
}
} catch (error) {
console.error('权限检查失败:', error);
//
this.saveToAlbum();
}
},
//
checkPhotoAlbumAuth() {
return new Promise((resolve, reject) => {
uni.getSetting({
success: (res) => {
resolve(res);
},
fail: (err) => {
reject(err);
}
});
});
},
//
requestPhotoAlbumAuth() {
uni.authorize({
scope: 'scope.writePhotosAlbum',
success: () => {
//
this.saveToAlbum();
},
fail: () => {
//
this.showAuthGuide();
}
});
},
//
showAuthGuide() {
uni.showModal({
title: '需要相册权限',
content: '保存图片需要访问您的相册权限,请在设置中开启相册权限后重试',
confirmText: '去设置',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
//
uni.openSetting({
success: (settingRes) => {
if (settingRes.authSetting['scope.writePhotosAlbum']) {
//
this.saveToAlbum();
} else {
uni.showToast({
title: '未开启相册权限',
icon: 'none'
});
}
}
});
}
}
});
},
//
saveToAlbum() {
if (!this.Qrcode) {
uni.showToast({
title: '图片还未加载完成',
icon: 'none'
});
return;
}
uni.saveImageToPhotosAlbum({
filePath: this.Qrcode,
success: (res) => {
uni.showToast({
title: '保存成功',
icon: 'success'
})
});
},
fail: (err) => {
uni.showToast({
title: '保存失败',
icon: 'none'
})
console.error('保存失败:', err);
if (err.errMsg.includes('auth')) {
//
this.showAuthGuide();
} else {
uni.showToast({
title: '保存失败,请重试',
icon: 'none'
});
}
}
})
});
},
async getQrcode() {
// const res = await this.$api.promotion.qrCode()


Loading…
Cancel
Save