四零语境前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

243 lines
5.1 KiB

<template>
<view class="custom-tabbar" :class="{ 'tabbar-hidden': !showNavbar }">
<!-- 音频控制栏组件 -->
<AudioControls
:current-page="currentPage"
:course-id="courseId"
:voice-id="voiceId"
:book-pages="bookPages"
:is-text-page="isTextPage"
:should-load-audio="shouldLoadAudio"
:is-member="isMember"
:current-page-requires-member="currentPageRequiresMember"
:page-pay="pagePay"
:is-word-audio-playing="isWordAudioPlaying"
@previous-page="previousPage"
@next-page="nextPage"
@audio-state-change="onAudioStateChange"
@highlight-change="onHighlightChange"
@scroll-to-text="onScrollToText"
@voice-change-complete="onVoiceChangeComplete"
@voice-change-error="onVoiceChangeError"
@page-data-needed="onPageDataNeeded"
ref="audioControls"
/>
<view style="background-color: #fff;position: relative;z-index: 100">
<view class="tabbar-content">
<view class="tabbar-left">
<view class="tab-button" @click="toggleCoursePopup">
<image src="/static/course-icon.png" class="tab-icon" />
<text class="tab-text">课程</text>
</view>
<view class="tab-button" @click="toggleSound">
<image src="/static/voice-switch-icon.png" class="tab-icon" />
<text class="tab-text">音色切换</text>
</view>
</view>
<view class="tabbar-right">
<view class="page-controls">
<view class="page-numbers">
<view
v-for="(page, index) in bookPages"
:key="index"
class="page-number"
:class="{ 'active': (index + 1) === currentPage }"
@click="goToPage(index + 1)"
>
{{ index + 1 }}
</view>
</view>
</view>
</view>
</view>
<uv-safe-bottom></uv-safe-bottom>
</view>
</view>
</template>
<script>
import AudioControls from '../AudioControls.vue'
export default {
name: 'CustomTabbar',
components: {
AudioControls
},
props: {
showNavbar: {
type: Boolean,
default: true
},
currentPage: {
type: Number,
default: 1
},
courseId: {
type: String,
default: ''
},
voiceId: {
type: Number,
default: null
},
bookPages: {
type: Array,
default: () => []
},
isTextPage: {
type: Boolean,
default: false
},
shouldLoadAudio: {
type: Boolean,
default: false
},
isMember: {
type: Boolean,
default: false
},
currentPageRequiresMember: {
type: Boolean,
default: false
},
pagePay: {
type: Array,
default: () => []
},
isWordAudioPlaying: {
type: Boolean,
default: false
}
},
methods: {
toggleCoursePopup() {
this.$emit('toggle-course-popup')
},
toggleSound() {
this.$emit('toggle-sound')
},
goToPage(pageNumber) {
this.$emit('go-to-page', pageNumber)
},
previousPage() {
this.$emit('previous-page')
},
nextPage() {
this.$emit('next-page')
},
onAudioStateChange(audioState) {
this.$emit('audio-state-change', audioState)
},
onHighlightChange(highlightData) {
this.$emit('highlight-change', highlightData)
},
onVoiceChangeComplete(data) {
this.$emit('voice-change-complete', data)
},
onVoiceChangeError(error) {
this.$emit('voice-change-error', error)
},
onPageDataNeeded(pageNumber) {
this.$emit('page-data-needed', pageNumber)
},
onScrollToText(scrollData) {
this.$emit('scroll-to-text', scrollData)
}
}
}
</script>
<style lang="scss" scoped>
.custom-tabbar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
border-top: 1rpx solid #EEEEEE;
z-index: 1000;
transition: transform 0.3s ease;
&.tabbar-hidden {
transform: translateY(100%);
}
}
.tabbar-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 62rpx;
height: 88rpx;
}
.tabbar-left {
display: flex;
align-items: center;
gap: 35rpx;
}
.tab-button {
display: flex;
align-items: center;
flex-direction: column;
gap: 8rpx;
}
.tab-icon {
width: 52rpx;
height: 52rpx;
}
.tab-text {
font-family: PingFang SC;
font-size: 22rpx;
color: #999;
line-height: 24rpx;
}
.tabbar-right {
flex: 1;
display: flex;
justify-content: flex-end;
}
.page-controls {
display: flex;
align-items: center;
}
.page-numbers {
display: flex;
align-items: center;
gap: 8rpx;
overflow-x: auto;
// max-width: 400rpx;
max-width: 50vw;
&::-webkit-scrollbar {
display: none;
}
}
.page-number {
min-width: 84rpx;
height: 58rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 100rpx;
font-family: PingFang SC;
font-size: 30rpx;
color: #3B3D3D;
background-color: transparent;
border: 1px solid #3B3D3D;
transition: all 0.3s ease;
&.active {
border: 1px solid #06DADC;
color: #06DADC;
}
}
</style>