audioBox.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. <template>
  2. <view class="global-voice-box">
  3. <view v-if="!showBig">
  4. <view class="flex small-box" @click.prevent="showBig=true">
  5. <view style="flex:1;overflow: hidden;">
  6. <view class="van-ellipsis">{{title}}</view>
  7. <view class="time" style="font-size:24rpx;color:#666">时长 {{audioTime|formatVoiceTime}}</view>
  8. </view>
  9. <image
  10. class="pause-img"
  11. :src="play?require('@/static/audio-doing.png'):require('@/static/audio-pause-3.png')"
  12. mode="aspectFill"
  13. @click.stop="handleChangePlayStatus"
  14. />
  15. <van-icon @click.stop="handleClosePopAudio" name="cross" size="18" color="#BBC3C9"/>
  16. </view>
  17. <van-progress
  18. color="#D4AC78"
  19. track-color="#fff"
  20. :show-pivot="false"
  21. stroke-width="2px"
  22. custom-class="bot-progress"
  23. :percentage="percentage"
  24. />
  25. </view>
  26. <view class="big-box" v-else>
  27. <view class="flex top" style="overflow: hidden;">
  28. <van-icon name="arrow-down" size="18" color="#BBC3C9" @click="showBig=false" />
  29. <view class="van-ellipsis" style="flex:1;margin:0 10rpx;text-align:center">{{title}}</view>
  30. <van-icon @click.stop="handleClosePopAudio" name="cross" size="18" color="#BBC3C9"/>
  31. </view>
  32. <view class="flex center">
  33. <image
  34. class="pause-img"
  35. :src="play?require('@/static/audio-doing.png'):require('@/static/audio-pause-3.png')"
  36. mode="aspectFill"
  37. @click.stop="handleChangePlayStatus"
  38. />
  39. <text class="time">{{curTime|formatVoiceTime}}</text>
  40. <slider
  41. activeColor="#e3b377"
  42. :max="audioTime"
  43. :value="curTime"
  44. @change="handleAudioSliderChange($event)"
  45. block-size="16"
  46. class="slider"
  47. />
  48. <text class="time">{{audioTime|formatVoiceTime}}</text>
  49. </view>
  50. </view>
  51. </view>
  52. </template>
  53. <script>
  54. export default {
  55. filters:{
  56. formatVoiceTime(e){
  57. let m=parseInt(e/60)
  58. let s=parseInt(e%60)
  59. return `${m>9?m:'0'+m}:${s>9?s:'0'+s}`
  60. }
  61. },
  62. computed: {
  63. audioData(){
  64. return this.$store.state.audio
  65. },
  66. //用户监听音频是否变化了 是否需要初始化
  67. audioInit(){
  68. return {
  69. reportId:this.$store.state.audio.reportId,
  70. voiceId:this.$store.state.audio.voiceId,
  71. questionId:this.$store.state.audio.questionId
  72. }
  73. },
  74. percentage(){
  75. return parseInt((this.curTime/this.audioTime)*100)
  76. },
  77. reportAudioShow(){
  78. return this.$store.state.report.audioData.show
  79. }
  80. },
  81. watch:{
  82. audioInit:{
  83. handler(nval){
  84. console.log(nval);
  85. this.init()
  86. },
  87. immediate:true
  88. },
  89. showBig:{
  90. handler(nval){
  91. this.$store.commit('audio/showBig',nval)
  92. },
  93. immediate:true
  94. }
  95. },
  96. data() {
  97. return {
  98. showBig:false,
  99. curTime:0,
  100. audioTime:0,//当前音频总时长
  101. title:'',//当前音频标题
  102. play:false
  103. }
  104. },
  105. methods: {
  106. init(){
  107. console.log('audioBox init');
  108. let delyTime=0
  109. if(this.$store.state.report.audioData.show){
  110. this.globalBgMusic.stop()
  111. delyTime=300
  112. }
  113. console.log('audioBox init',delyTime);
  114. const curAudio=this.$store.state.audio.list[this.$store.state.audio.index]
  115. setTimeout(() => {
  116. if(this.globalBgMusic.src!=curAudio.url){
  117. this.globalBgMusic.src=curAudio.url
  118. this.globalBgMusic.title=curAudio.title
  119. }
  120. this.audioTime=curAudio.time
  121. this.title=curAudio.title
  122. this.curTime=parseInt(this.globalBgMusic.currentTime)
  123. this.play=!this.globalBgMusic.paused
  124. this.listenAudio()
  125. }, delyTime);
  126. },
  127. //音频播放事件
  128. listenAudio(){
  129. console.log('设置监听事件');
  130. this.globalBgMusic.onPlay(()=>{
  131. console.log('开始播放');
  132. this.play=true
  133. this.$store.commit('audio/updateAudioPause',false)
  134. })
  135. this.globalBgMusic.onPause(()=>{
  136. console.log('音频暂停');
  137. this.play=false
  138. this.$store.commit('audio/updateAudioPause',true)
  139. })
  140. this.globalBgMusic.onStop(()=>{
  141. console.log('音频停止');
  142. this.$store.commit('audio/removeAudio')
  143. })
  144. this.globalBgMusic.onEnded(()=>{
  145. console.log('音频onEnded');
  146. const index=this.$store.state.audio.index
  147. if(index==this.$store.state.audio.list.length-1){
  148. this.$store.commit('audio/removeAudio')
  149. }else{
  150. this.handleAudioChange('next')
  151. }
  152. })
  153. this.globalBgMusic.onError((e)=>{
  154. console.log('音频onError',e);
  155. this.$store.commit('audio/removeAudio')
  156. uni.showToast({
  157. title: '音频播放错误',
  158. icon: 'none'
  159. })
  160. })
  161. this.globalBgMusic.onTimeUpdate(()=>{
  162. // console.log('时间更新');
  163. this.curTime=parseInt(this.globalBgMusic.currentTime)
  164. this.$store.commit('audio/updateAudioTime',this.curTime)
  165. })
  166. },
  167. //关闭弹窗停止播放的音频
  168. handleClosePopAudio(){
  169. this.globalBgMusic.stop()
  170. },
  171. //音频切换(暂时没有用到因为都是一个音频 如果后期有多个 直接在页面dom调用此方法即可)
  172. handleAudioChange(type){
  173. let temIndex=this.$store.state.report.audioData.index
  174. if(type=='before'){
  175. if(temIndex>0){
  176. let index=temIndex-1
  177. this.$store.commit('audio/updateAudioIndex', index)
  178. this.init()
  179. }
  180. }else{
  181. if(temIndex<this.$store.state.report.audioData.list.length-1){
  182. let index=temIndex+1
  183. this.$store.commit('audio/updateAudioIndex', index)
  184. this.init()
  185. }
  186. }
  187. },
  188. //拖动进度条
  189. handleAudioSliderChange(e){
  190. const value=e.detail.value
  191. this.globalBgMusic.seek(value)
  192. },
  193. //音频点击暂停播放
  194. handleChangePlayStatus(){
  195. if(!this.globalBgMusic.paused){
  196. this.globalBgMusic.pause()
  197. }else{
  198. this.globalBgMusic.play()
  199. }
  200. },
  201. },
  202. }
  203. </script>
  204. <style>
  205. .bot-progress{
  206. width: 100%;
  207. }
  208. </style>
  209. <style lang="scss" scoped>
  210. .global-voice-box{
  211. position: fixed;
  212. background: #FFFFFF;
  213. border: 1px solid #E4E4E4;
  214. box-shadow: 0px 0px 40rpx rgba(50, 35, 17, 0.25);
  215. left: 20rpx;
  216. right: 20rpx;
  217. bottom: calc(130rpx + constant(safe-area-inset-bottom));
  218. bottom: calc(130rpx + env(safe-area-inset-bottom));
  219. z-index: 99;
  220. .small-box{
  221. padding: 18rpx 48rpx 18rpx 20rpx;
  222. position: relative;
  223. align-items: center;
  224. .pause-img{
  225. width: 60rpx;
  226. height: 60rpx;
  227. margin-right: 44rpx;
  228. margin-left: 30rpx;
  229. flex-shrink: 0;
  230. }
  231. }
  232. .big-box{
  233. padding: 33rpx 30rpx;
  234. .center{
  235. align-items: center;
  236. margin-top: 20rpx;
  237. .time{
  238. font-size: 24rpx;
  239. }
  240. .pause-img{
  241. width: 60rpx;
  242. height: 60rpx;
  243. margin-right: 34rpx;
  244. }
  245. .slider{
  246. flex: 1;
  247. }
  248. }
  249. }
  250. }
  251. </style>