Browse Source

语音播报改为背景音频播放

jwyu 2 years ago
parent
commit
fbd78ca03e
3 changed files with 312 additions and 75 deletions
  1. 5 0
      App.vue
  2. 235 0
      components/voiceBox/voiceBox.vue
  3. 72 75
      pages/voice/voice.vue

+ 5 - 0
App.vue

@@ -25,6 +25,11 @@
 				fail:function(res){
 				fail:function(res){
 				}
 				}
 			})
 			})
+
+			// 开启ios静音也行播放语音
+			wx.setInnerAudioOption({
+				obeyMuteSwitch:false
+			})
 		},
 		},
 		onShow: function(options) {
 		onShow: function(options) {
 			console.log('App Show')
 			console.log('App Show')

+ 235 - 0
components/voiceBox/voiceBox.vue

@@ -0,0 +1,235 @@
+<template>
+    <view class="global-voice-box">
+        <view class="flex small-box" v-if="!showBig" @click.prevent="showBig=true">
+            <view style="flex:1;overflow: hidden;">
+                <view class="van-ellipsis">{{voiceData.title}}</view>
+                <view class="time" style="font-size:24rpx;color:#666">时长 {{voiceData.duration|formatVoiceTime}}</view>
+            </view>
+            <image 
+                class="pause-img"  
+                :src="play?require('@/static/audio-doing.png'):require('@/static/audio-pause-3.png')" 
+                mode="aspectFill"
+                @click.stop="handleChangePlayStatus"
+            />
+            <van-icon @click.stop="handleClosePopAudio" name="cross" size="18" color="#BBC3C9"/>
+            <van-progress 
+                color="#D4AC78" 
+                track-color="#fff"
+                :show-pivot="false" 
+                stroke-width="2px" 
+                custom-class="bot-progress" 
+                :percentage="percentage" 
+            />
+        </view>
+        <view class="big-box" v-else>
+            <view class="flex top" style="overflow: hidden;">
+                <van-icon name="arrow-down" size="18" color="#BBC3C9" @click="showBig=false" />
+                <view class="van-ellipsis" style="flex:1;margin:0 10rpx;text-align:center">{{voiceData.title}}</view>
+                <van-icon @click.stop="handleClosePopAudio" name="cross" size="18" color="#BBC3C9"/>
+            </view>
+            <view class="flex center">
+                <image 
+                    class="pause-img"  
+                    :src="play?require('@/static/audio-doing.png'):require('@/static/audio-pause-3.png')" 
+                    mode="aspectFill"
+                    @click.stop="handleChangePlayStatus"
+                />
+                <text class="time">{{curTime|formatVoiceTime}}</text>
+                <slider
+                    activeColor="#e3b377"
+                    :max="voiceData.duration" 
+                    :value="curTime" 
+                    @change="handleAudioSliderChange($event)"
+                    block-size="16"
+                    class="slider"
+                />
+                <text class="time">{{voiceData.duration|formatVoiceTime}}</text>
+            </view>
+        </view>
+    </view>
+      
+</template>
+
+<script>
+export default {
+    filters:{
+        formatVoiceTime(e){
+            let m=parseInt(e/60)
+            let s=parseInt(e%60)
+            return `${m>9?m:'0'+m}:${s>9?s:'0'+s}`
+        }
+    },
+    props:{
+        voiceData:null,//{title:音频标题,duration:音频时长,url:音频地址,id:音频唯一id}
+    },
+    computed: {
+        percentage(){
+            return parseInt((this.curTime/this.voiceData.duration)*100)
+        },
+        reportAudioShow(){
+            return this.$store.state.report.audioData.show
+        }
+    },
+    watch:{
+        'voiceData':{
+            handler(nval){
+                console.log(nval);
+                this.init()
+            },
+            deep:true,
+            immediate:true
+        },
+        play(nval){
+            this.$emit('stateChange',nval)
+        },
+        showBig(nval){
+            this.$emit('popChange',this.showBig)
+        },
+        reportAudioShow(nval){
+            if(this.$store.state.report.audioData.show){
+                this.$emit('closeVoice')
+            }
+        }
+    },
+    data() {
+        return {
+            showBig:false,
+            curTime:0,
+            play:false
+        }
+    },
+    // mounted() {
+    //     this.listenAudio()
+    // },
+    methods: {
+        init(){
+            if(this.$store.state.report.audioData.show){
+                this.globalBgMusic.stop()
+                setTimeout(() => {
+                    this.globalBgMusic.src=this.voiceData.url 
+                    this.globalBgMusic.title=this.voiceData.title
+                    this.listenAudio()
+                }, 300);
+            }else{
+                this.globalBgMusic.src=this.voiceData.url 
+                this.globalBgMusic.title=this.voiceData.title
+                this.listenAudio()
+            }
+            
+        },
+
+        //音频播放事件
+        listenAudio(){
+            console.log('设置监听事件');
+            this.globalBgMusic.onPlay(()=>{
+                console.log('开始播放');
+                this.play=true
+            })
+            this.globalBgMusic.onPause(()=>{
+                console.log('音频暂停');
+                this.play=false
+            })
+            this.globalBgMusic.onStop(()=>{
+                console.log('音频停止');
+                this.play=false
+                this.showBig=false
+                this.handleClosePopAudio()
+            })
+            this.globalBgMusic.onEnded(()=>{
+                console.log('音频onEnded');
+                this.play=false
+                this.showBig=false
+                this.handleClosePopAudio()
+            })
+            this.globalBgMusic.onError((e)=>{
+                console.log('音频onError',e);
+                this.play=false
+                this.showBig=false
+                this.handleClosePopAudio()
+                uni.showToast({
+                    title: '音频播放错误',
+                    icon: 'none'
+                })
+            })
+            this.globalBgMusic.onTimeUpdate(()=>{
+                // console.log('时间更新');
+                this.curTime=parseInt(this.globalBgMusic.currentTime)
+            })
+        },
+
+        handleClosePopAudio(){
+            this.globalBgMusic.stop()
+            this.$emit('closeVoice')
+        },
+
+        //拖动进度条
+        handleAudioSliderChange(e){
+            const value=e.detail.value
+            this.globalBgMusic.seek(value)
+        },
+
+        //音频点击暂停播放
+        handleChangePlayStatus(){
+            if(this.play){
+                this.globalBgMusic.pause()
+            }else{
+                this.globalBgMusic.play()
+            }
+        },
+
+    },
+}
+</script>
+
+<style>
+.bot-progress{
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+}
+</style>
+
+<style lang="scss" scoped>
+.global-voice-box{
+    position: fixed;
+    background: #FFFFFF;
+    border: 1px solid #E4E4E4;
+    box-shadow: 0px 0px 40rpx rgba(50, 35, 17, 0.25);
+    left: 20rpx;
+    right: 20rpx;
+    bottom: calc(130rpx + constant(safe-area-inset-bottom));
+    bottom: calc(130rpx + env(safe-area-inset-bottom));
+    z-index: 99;
+    .small-box{
+        padding: 18rpx 48rpx 18rpx 20rpx;
+        position: relative;
+        align-items: center;
+        .pause-img{
+            width: 60rpx;
+            height: 60rpx;
+            margin-right: 44rpx;
+            margin-left: 30rpx;
+            flex-shrink: 0;
+        }
+    }
+    .big-box{
+        padding: 33rpx 30rpx;
+        .center{
+            align-items: center;
+            margin-top: 20rpx;
+            .time{
+                font-size: 24rpx;
+            }
+            .pause-img{
+                width: 60rpx;
+                height: 60rpx;
+                margin-right: 34rpx;
+            }
+            .slider{
+                flex: 1;
+            }
+        }
+    }
+}
+</style>

+ 72 - 75
pages/voice/voice.vue

@@ -12,17 +12,16 @@
             />
             />
             <view>暂无数据</view>
             <view>暂无数据</view>
         </view>
         </view>
-        <view class="list-wrap" :style="{paddingBottom:IsVoiceAdmin&&'200rpx'}" v-else>
+        <view class="list-wrap" :style="{paddingBottom:pagePaddingBot}" v-else>
             <view class="item" v-for="item in list" :key="item.BroadcastId">
             <view class="item" v-for="item in list" :key="item.BroadcastId">
                 <view class="title">{{item.BroadcastName}}</view>
                 <view class="title">{{item.BroadcastName}}</view>
                 <view class="time">发布时间:{{item.CreateTime|formatTime}}</view>
                 <view class="time">发布时间:{{item.CreateTime|formatTime}}</view>
                 <view class="flex audio-box" @click="handlePlay(item)">
                 <view class="flex audio-box" @click="handlePlay(item)">
                     <image 
                     <image 
-                        :src="item.BroadcastId==temAudio.id&&!temAudio.paused?require('@/static/voice/playing.png'):require('@/static/voice/pause.png')" 
+                        :src="item.VoiceUrl==curVoiceUrl&&item.BroadcastId==curVoiceId&&temAudio.play?require('@/static/voice/playing.png'):require('@/static/voice/pause.png')" 
                         mode="widthFix" 
                         mode="widthFix" 
                     />
                     />
-                    <text v-if="item.BroadcastId==temAudio.id">{{temAudio.curTime|formatVoiceTime}}</text>
-                    <text v-else>{{item.VoicePlaySeconds|formatVoiceTime}}</text>
+                    <text>{{item.VoicePlaySeconds|formatVoiceTime}}</text>
                 </view>
                 </view>
                 <image class="del-btn" src="@/static/voice/del.png" @click="handleDelItem(item)" mode="widthFix" v-if="item.IsAuthor" />
                 <image class="del-btn" src="@/static/voice/del.png" @click="handleDelItem(item)" mode="widthFix" v-if="item.IsAuthor" />
                 <button 
                 <button 
@@ -36,7 +35,7 @@
         </view>
         </view>
 
 
         <navigator url="/pages-voice/addVoice">
         <navigator url="/pages-voice/addVoice">
-            <view class="add-btn" v-if="IsVoiceAdmin">新建语音</view>
+            <view class="add-btn" :style="{bottom:temAudio.item?temAudio.showBig?'440rpx':'340rpx':'180rpx'}" v-if="IsVoiceAdmin">新建语音</view>
         </navigator>
         </navigator>
 
 
         <!-- 筛选弹窗 -->
         <!-- 筛选弹窗 -->
@@ -64,6 +63,15 @@
             </view>
             </view>
         </van-popup>
         </van-popup>
 
 
+        <!-- 音频悬浮 -->
+        <voiceBox 
+            @stateChange="handleVoiceStateChange" 
+            @popChange="handleVoicePopChange"
+            @closeVoice="handleCloseVoice" 
+            :voiceData="temAudio.item" 
+            v-if="temAudio.item"
+        />
+
         <van-dialog id="van-dialog" />
         <van-dialog id="van-dialog" />
     </view>
     </view>
     <noAuth :info="noAuthData" v-else/>
     <noAuth :info="noAuthData" v-else/>
@@ -73,11 +81,12 @@
 import {apiVoiceList,apiVoiceSectionList,apiVoicePlayRecord,apiVoiceDel} from '@/api/voice'
 import {apiVoiceList,apiVoiceSectionList,apiVoicePlayRecord,apiVoiceDel} from '@/api/voice'
 import {apiGetSceneToParams} from '@/api/common'
 import {apiGetSceneToParams} from '@/api/common'
 import noAuth from './components/noAuth.vue'
 import noAuth from './components/noAuth.vue'
+import voiceBox from '@/components/voiceBox/voiceBox.vue'
 const moment=require('@/utils/moment-with-locales.min')
 const moment=require('@/utils/moment-with-locales.min')
-let innerAudioContext = uni.createInnerAudioContext();//播放音频实例
 export default {
 export default {
     components:{
     components:{
-        noAuth
+        noAuth,
+        voiceBox
     },
     },
     filters:{
     filters:{
         formatTime(e){
         formatTime(e){
@@ -89,9 +98,35 @@ export default {
             return `${m>9?m:'0'+m}:${s>9?s:'0'+s}`
             return `${m>9?m:'0'+m}:${s>9?s:'0'+s}`
         }
         }
     },
     },
+    computed:{
+        curVoiceUrl(){
+            return this.temAudio.item&&this.temAudio.item.url||""
+        },
+        curVoiceId(){
+            return this.temAudio.item&&this.temAudio.item.id||""
+        },
+        pagePaddingBot(){
+            let num=34
+            if(this.IsVoiceAdmin){
+                num=num+160
+            }else{
+                num=34
+            }
+            if(this.temAudio.item){
+                if(this.temAudio.showBig){
+                    num=num+260
+                }else{
+                    num=num+180
+                }
+            }else{
+                num=num+0
+            }
+
+            return num+'rpx'
+        }
+    },
     data() {
     data() {
         return {
         return {
-            // innerAudioContext:null,//播放音频实例
             list:[],
             list:[],
             page:1,
             page:1,
             pageSize:20,
             pageSize:20,
@@ -109,11 +144,9 @@ export default {
             activeId:0,//选择的板块id
             activeId:0,//选择的板块id
 
 
             temAudio:{
             temAudio:{
-                paused:true,
-                url:'',//临时音频地址
-                duration:'',//时长
-                id:0,
-                curTime:''
+                item:null,
+                play:false,
+                showBig:false
             }
             }
         }
         }
     },
     },
@@ -127,21 +160,9 @@ export default {
         if(!this.isAuth){
         if(!this.isAuth){
             this.getVoiceList()
             this.getVoiceList()
         }
         }
-        innerAudioContext=uni.createInnerAudioContext();
-        this.listenAudio()
-    },
-    onHide(){
-        innerAudioContext.destroy()
-        this.temAudio.id=0
-        this.temAudio.paused=true
-        this.temAudio.curTime=''
     },
     },
     onUnload(){
     onUnload(){
 		uni.$off('addVoiceSuccess')
 		uni.$off('addVoiceSuccess')
-        innerAudioContext.destroy()
-        this.temAudio.id=0
-        this.temAudio.paused=true
-        this.temAudio.curTime=''
 	},
 	},
     onShareAppMessage({from,target}) {
     onShareAppMessage({from,target}) {
         console.log(from,target);
         console.log(from,target);
@@ -303,53 +324,38 @@ export default {
             }).catch(()=>{})
             }).catch(()=>{})
         },
         },
 
 
+        //点击音频 播放或者暂停
         handlePlay(item){
         handlePlay(item){
-            if(this.temAudio.id==item.BroadcastId){
-                if(innerAudioContext.paused){
-                    innerAudioContext.play()
-                }else{
-                    innerAudioContext.pause()
+            if(!this.temAudio.item||this.temAudio.item.id!=item.BroadcastId){
+                this.temAudio.item={
+                    title:item.BroadcastName,
+                    duration:item.VoicePlaySeconds,
+                    url:item.VoiceUrl,
+                    id:item.BroadcastId
                 }
                 }
+                this.handleVoicePlayRecord(item)
             }else{
             }else{
-                if(!innerAudioContext.paused){
-                    innerAudioContext.stop()
+                if(this.globalBgMusic.paused){
+                    this.globalBgMusic.play()
+                }else{
+                    this.globalBgMusic.pause()
                 }
                 }
-                this.temAudio.id=item.BroadcastId
-                this.temAudio.duration=item.VoicePlaySeconds
-                this.temAudio.curTime=item.VoicePlaySeconds
-                innerAudioContext.src=item.VoiceUrl 
-                innerAudioContext.play()
-                this.handleVoicePlayRecord(item)
             }
             }
+            
+        },
+        //关闭音频
+        handleCloseVoice(){
+            this.temAudio.item=null
+        },
+        
+        //音频播放状态
+        handleVoiceStateChange(e){
+            this.temAudio.play=e
         },
         },
 
 
-        //音频播放事件
-        listenAudio(){
-            innerAudioContext.onPlay(()=>{
-                console.log('开始播放录音');
-                this.temAudio.paused=false
-            })
-            innerAudioContext.onPause(()=>{
-                console.log('录音播放暂停');
-                this.temAudio.paused=true
-            })
-            // innerAudioContext.onStop(()=>{
-            //     console.log('录音播放停止');
-            //     this.temAudio.paused=true
-            //     // setTimeout(() => {
-            //         this.temAudio.id=0
-            //     // }, 100);
-            // })
-            innerAudioContext.onEnded(()=>{
-                console.log('录音播放自然结束');
-                this.temAudio.paused=true
-                this.temAudio.id=0
-
-            })
-            innerAudioContext.onTimeUpdate(()=>{
-                // console.log('时间更新');
-                this.temAudio.curTime=parseInt(this.temAudio.duration)-parseInt(innerAudioContext.currentTime)
-            })
+        //音频弹窗大小变化
+        handleVoicePopChange(e){
+            this.temAudio.showBig=e
         },
         },
 
 
         //上报音频播放记录
         //上报音频播放记录
@@ -396,17 +402,7 @@ export default {
 
 
 <style lang="scss" scoped>
 <style lang="scss" scoped>
 .voice-play-page{
 .voice-play-page{
-    
     .top-filter-box{
     .top-filter-box{
-        // padding-left: 34rpx;
-        // padding-bottom: 10rpx;
-        // position: sticky;
-        // top: 0;
-        // left: 0;
-        // z-index: 99;
-        // background-color: #fff;
-        // display: flex;
-        // align-items: center;
         display: flex;
         display: flex;
 		flex: auto;
 		flex: auto;
 		align-items: center;
 		align-items: center;
@@ -507,4 +503,5 @@ export default {
     box-shadow: 0px 4rpx 20rpx rgba(160, 126, 84, 0.25);
     box-shadow: 0px 4rpx 20rpx rgba(160, 126, 84, 0.25);
     border-radius: 40rpx;
     border-radius: 40rpx;
 }
 }
+
 </style>
 </style>