audioBox.vue 8.4 KB

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