作者 徐浩

添加音频功能

1 <template> 1 <template>
2 <view class="RecordingDevice"> 2 <view class="RecordingDevice">
3 - <view class="RecordingDevice-2">  
4 - <VoicePlayback ref="voicePlayback"/> 3 + <view class="RecordingDevice-2" v-if="speech.url">
  4 + <VoicePlayback ref="voicePlayback" />
5 </view> 5 </view>
6 <view class="RecordingDevice-1"> 6 <view class="RecordingDevice-1">
7 <view class="RecordingDevice-1-i"> 7 <view class="RecordingDevice-1-i">
@@ -67,10 +67,33 @@ @@ -67,10 +67,33 @@
67 } 67 }
68 export default { 68 export default {
69 name: 'RecordingDevice', 69 name: 'RecordingDevice',
  70 + props: {
  71 + value: {
  72 + type: Object,
  73 + default: () => {
  74 + return {
  75 + duration: 0,
  76 + url: ''
  77 + }
  78 + }
  79 + }
  80 + },
  81 + model: {
  82 + event: 'input',
  83 + prop: 'value'
  84 + },
70 components: { 85 components: {
71 VoicePlayback 86 VoicePlayback
72 }, 87 },
73 computed: { 88 computed: {
  89 + speech: {
  90 + get() {
  91 + return this.value
  92 + },
  93 + set(val) {
  94 + this.$emit('input', val)
  95 + }
  96 + },
74 formattedTime() { 97 formattedTime() {
75 const hours = this.padDigits(this.hours); 98 const hours = this.padDigits(this.hours);
76 const minutes = this.padDigits(this.minutes); 99 const minutes = this.padDigits(this.minutes);
@@ -84,6 +107,7 @@ @@ -84,6 +107,7 @@
84 // 是否正在录制 107 // 是否正在录制
85 isTape: RECORDINGSTATUS.NOTSTARTEDYET, 108 isTape: RECORDINGSTATUS.NOTSTARTEDYET,
86 recorder: null, 109 recorder: null,
  110 + totalTime: 0,
87 seconds: 0, 111 seconds: 0,
88 minutes: 0, 112 minutes: 0,
89 hours: 0, 113 hours: 0,
@@ -115,6 +139,7 @@ @@ -115,6 +139,7 @@
115 }, 139 },
116 startTimer() { 140 startTimer() {
117 this.timer = setInterval(() => { 141 this.timer = setInterval(() => {
  142 + this.totalTime++
118 this.seconds++; 143 this.seconds++;
119 if (this.seconds >= 60) { 144 if (this.seconds >= 60) {
120 this.seconds = 0; 145 this.seconds = 0;
@@ -129,6 +154,7 @@ @@ -129,6 +154,7 @@
129 resetTimer() { 154 resetTimer() {
130 clearInterval(this.timer); 155 clearInterval(this.timer);
131 this.timer = null; 156 this.timer = null;
  157 + this.totalTime = 0
132 this.seconds = 0 158 this.seconds = 0
133 this.minutes = 0 159 this.minutes = 0
134 this.hours = 0 160 this.hours = 0
@@ -179,12 +205,23 @@ @@ -179,12 +205,23 @@
179 }) 205 })
180 return 206 return
181 } 207 }
  208 + let result = {
  209 + duration: this.totalTime
  210 + }
  211 + this.speech = { ...this.speech, ...result }
182 this.resetTimer() 212 this.resetTimer()
183 this.recorder.stop(); 213 this.recorder.stop();
184 }, 214 },
185 uploadFiles(tempFilePath) { 215 uploadFiles(tempFilePath) {
186 this.$service.wx_upload(tempFilePath, 'video').then(res => { 216 this.$service.wx_upload(tempFilePath, 'video').then(res => {
187 - this.$refs.voicePlayback.setUrl(res.data) 217 + this.$set(this.speech, 'url', res.data)
  218 + let result = {
  219 + url: res.data
  220 + }
  221 + this.speech = { ...this.speech, ...result }
  222 + this.$nextTick(() => {
  223 + this.$refs.voicePlayback.init(this.speech)
  224 + })
188 }) 225 })
189 } 226 }
190 } 227 }
@@ -22,7 +22,6 @@ @@ -22,7 +22,6 @@
22 } 22 }
23 }, 23 },
24 mounted() { 24 mounted() {
25 - this.init()  
26 }, 25 },
27 onUnload() { 26 onUnload() {
28 this.audioContext.stop(); 27 this.audioContext.stop();
@@ -36,12 +35,13 @@ @@ -36,12 +35,13 @@
36 this.audioContext.pause() 35 this.audioContext.pause()
37 } 36 }
38 }, 37 },
39 - setUrl(url) { 38 + setUrl({url, duration}) {
40 this.audioContext.src = url 39 this.audioContext.src = url
  40 + this.duration = duration
41 }, 41 },
42 - init() { 42 + init({ url, duration }) {
43 this.audioContext = wx.createInnerAudioContext(); 43 this.audioContext = wx.createInnerAudioContext();
44 - this.audioContext.src = require("@/static/imagesV2/test.mp3") 44 + this.audioContext.src = url
45 this.audioContext.onPlay(() => { 45 this.audioContext.onPlay(() => {
46 this.isPlay = true 46 this.isPlay = true
47 }); 47 });
@@ -58,12 +58,11 @@ @@ -58,12 +58,11 @@
58 this.audioContext.play() 58 this.audioContext.play()
59 this.audioContext.pause() 59 this.audioContext.pause()
60 setTimeout(() => { 60 setTimeout(() => {
61 - this.duration = this.audioContext.duration 61 + this.duration = duration
62 this.remainingTime = this.duration 62 this.remainingTime = this.duration
63 }, 100) 63 }, 100)
64 }) 64 })
65 this.audioContext.onTimeUpdate(() => { 65 this.audioContext.onTimeUpdate(() => {
66 - this.duration = this.audioContext.duration  
67 this.currentTime = this.audioContext.currentTime 66 this.currentTime = this.audioContext.currentTime
68 this.remainingTime = this.duration - this.currentTime 67 this.remainingTime = this.duration - this.currentTime
69 }); 68 });
@@ -52,7 +52,7 @@ @@ -52,7 +52,7 @@
52 <view class="myQuestion-2-i-3-c-1-r">{{info.answer_time}}</view> 52 <view class="myQuestion-2-i-3-c-1-r">{{info.answer_time}}</view>
53 </view> 53 </view>
54 <view style="margin-top: 28rpx;" v-if="isVoiceReply"> 54 <view style="margin-top: 28rpx;" v-if="isVoiceReply">
55 - <VoicePlayback /> 55 + <VoicePlayback ref="voicePlaybackRef"/>
56 </view> 56 </view>
57 <view class="myQuestion-2-i-3-c-2" v-else> 57 <view class="myQuestion-2-i-3-c-2" v-else>
58 {{info.answer}} 58 {{info.answer}}
@@ -74,7 +74,7 @@ @@ -74,7 +74,7 @@
74 <textarea class="onLineDetails-1-2-c" placeholder="请输入" v-model="answer"></textarea> 74 <textarea class="onLineDetails-1-2-c" placeholder="请输入" v-model="answer"></textarea>
75 </view> 75 </view>
76 <view v-else> 76 <view v-else>
77 - <RecordingDevice /> 77 + <RecordingDevice v-model="speech" />
78 </view> 78 </view>
79 </view> 79 </view>
80 80
@@ -103,7 +103,11 @@ @@ -103,7 +103,11 @@
103 answerType: MESSAGETYPE.TEXTANSWER, 103 answerType: MESSAGETYPE.TEXTANSWER,
104 value: 5, 104 value: 5,
105 answer: '', 105 answer: '',
106 - info: {} 106 + info: {},
  107 + speech: {
  108 + duration: 0,
  109 + url: ''
  110 + }
107 }; 111 };
108 }, 112 },
109 computed: { 113 computed: {
@@ -113,7 +117,7 @@ @@ -113,7 +117,7 @@
113 }, 117 },
114 // 是否查看 118 // 是否查看
115 isWatch() { 119 isWatch() {
116 - return this.info.answer_type === ANSWERTYPE.ANSWERED 120 + return this.info.answer_type !== ANSWERTYPE.TOBEANSWERED
117 }, 121 },
118 // 是否语音回复 122 // 是否语音回复
119 isVoiceReply() { 123 isVoiceReply() {
@@ -145,6 +149,15 @@ @@ -145,6 +149,15 @@
145 uni.hideLoading(); 149 uni.hideLoading();
146 if (res.code == 1) { 150 if (res.code == 1) {
147 this.info = res.data; 151 this.info = res.data;
  152 + if(this.info.answer_type === MESSAGETYPE.VOICEANSWERS) {
  153 + let result = this.info.answer
  154 + if(result) {
  155 + result = JSON.parse(result)
  156 + this.$nextTick(() => {
  157 + this.$refs.voicePlaybackRef.init(result)
  158 + })
  159 + }
  160 + }
148 }else { 161 }else {
149 if (res.msg) { 162 if (res.msg) {
150 uni.showToast({ 163 uni.showToast({
@@ -174,15 +187,23 @@ @@ -174,15 +187,23 @@
174 title: '提交中', 187 title: '提交中',
175 mask: true 188 mask: true
176 }) 189 })
177 - const { answerType, answer, id } = this; 190 + let { answerType, answer, id } = this;
178 if(answerType === MESSAGETYPE.TEXTANSWER && !answer) { 191 if(answerType === MESSAGETYPE.TEXTANSWER && !answer) {
179 uni.showToast({ 192 uni.showToast({
180 title: '请输入解答内容', 193 title: '请输入解答内容',
181 icon: 'none' 194 icon: 'none'
182 }); 195 });
183 return false; 196 return false;
  197 + } else if(answerType === MESSAGETYPE.VOICEANSWERS && !this.speech.url) {
  198 + uni.showToast({
  199 + title: '请录制音频',
  200 + icon: 'none'
  201 + });
  202 + return false;
  203 + }
  204 + if(answerType === MESSAGETYPE.VOICEANSWERS) {
  205 + answer = JSON.stringify(this.speech)
184 } 206 }
185 -  
186 this.$service.P_post('/lecturer/answer', { 207 this.$service.P_post('/lecturer/answer', {
187 answer_type: answerType, 208 answer_type: answerType,
188 answer, 209 answer,