Browse Source

发送语音功能初步实现

master
xie.bx 3 years ago
parent
commit
2ad211cefe
  1. 4
      commom/src/main/java/com/bx/common/enums/FileTypeEnum.java
  2. 2
      im-ui/package.json
  3. 27
      im-ui/src/components/chat/ChatBox.vue
  4. 109
      im-ui/src/components/chat/ChatVoice.vue
  5. 22
      im-ui/src/components/chat/MessageItem.vue

4
commom/src/main/java/com/bx/common/enums/FileTypeEnum.java

@ -4,7 +4,9 @@ public enum FileTypeEnum {
FILE(0,"文件"), FILE(0,"文件"),
IMAGE(1,"图片"), IMAGE(1,"图片"),
VIDEO(2,"视频"); VIDEO(2,"视频"),
AUDIO(3,"声音");
private Integer code; private Integer code;

2
im-ui/package.json

@ -11,7 +11,7 @@
"axios": "^1.1.3", "axios": "^1.1.3",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"element-ui": "^2.15.10", "element-ui": "^2.15.10",
"recorderx": "^2.0.2", "js-audio-recorder": "^1.0.7",
"sass": "^1.47.0", "sass": "^1.47.0",
"sass-loader": "^7.3.1", "sass-loader": "^7.3.1",
"vue": "^2.6.11", "vue": "^2.6.11",

27
im-ui/src/components/chat/ChatBox.vue

@ -48,7 +48,7 @@
</el-aside> </el-aside>
</el-container> </el-container>
<emotion v-show="showEmotion" :pos="emoBoxPos" @emotion="handleEmotion"></Emotion> <emotion v-show="showEmotion" :pos="emoBoxPos" @emotion="handleEmotion"></Emotion>
<chat-voice :visible="showVoice" @close="closeVoiceBox()"></chat-voice> <chat-voice :visible="showVoice" @close="closeVoiceBox" @send="handleSendVoice"></chat-voice>
</el-container> </el-container>
</template> </template>
@ -231,6 +231,31 @@
closeVoiceBox(){ closeVoiceBox(){
this.showVoice = false; this.showVoice = false;
}, },
handleSendVoice(data){
let msgInfo = {
content: JSON.stringify(data),
type: 3
}
// id
this.setTargetId(msgInfo, this.chat.targetId);
this.$http({
url: this.messageAction,
method: 'post',
data: msgInfo
}).then(() => {
this.$message.success("发送成功");
msgInfo.sendTime = new Date().getTime();
msgInfo.sendId = this.$store.state.userStore.userInfo.id;
msgInfo.selfSend = true;
this.$store.commit("insertMessage", msgInfo);
//
this.$refs.sendBox.focus();
//
this.scrollToBottom();
//
this.showVoice = false;
})
},
setTargetId(msgInfo, targetId) { setTargetId(msgInfo, targetId) {
if (this.chat.type == "GROUP") { if (this.chat.type == "GROUP") {
msgInfo.groupId = targetId; msgInfo.groupId = targetId;

109
im-ui/src/components/chat/ChatVoice.vue

@ -1,15 +1,21 @@
<template> <template>
<el-dialog class="chat-voice" title="语言录制" :visible.sync="visible" width="35%" :before-close="handleClose"> <el-dialog class="chat-voice" title="语音录制" :visible.sync="visible" width="600px" :before-close="handleClose">
<div> <div v-show="mode=='RECORD'">
录音时长:{{duration}} <div class="chat-voice-tip">{{stateTip}}</div>
<div>时长: {{state=='STOP'?0:parseInt(rc.duration)}}s</div>
</div> </div>
<audio v-show="mode=='PLAY'" :src="url" controls ref="audio" @ended="handleStopAudio()"></audio>
<el-row> <el-divider content-position="center"></el-divider>
<el-row class="chat-voice-btn-group">
<el-button round type="primary" v-show="state=='STOP'" @click="handleStartRecord()">开始录音</el-button> <el-button round type="primary" v-show="state=='STOP'" @click="handleStartRecord()">开始录音</el-button>
<el-button round type="warning" v-show="state=='RUNNING'" @click="handlePauseRecord()">暂停录音</el-button> <el-button round type="warning" v-show="state=='RUNNING'" @click="handlePauseRecord()">暂停录音</el-button>
<el-button round type="primary" v-show="state=='PAUSE'" @click="handleResumeRecord()">继续录音</el-button> <el-button round type="primary" v-show="state=='PAUSE'" @click="handleResumeRecord()">继续录音</el-button>
<el-button round type="danger" v-show="state=='RUNNING'||state=='PAUSE'" @click="handleCompleteRecord()">结束录音</el-button> <el-button round type="danger" v-show="state=='RUNNING'||state=='PAUSE'" @click="handleCompleteRecord()">
<el-button round type="success" v-show="state=='COMPLETE'" @click="handlePlayRecord()">播放录音</el-button> 结束录音</el-button>
<el-button round type="success" v-show="state=='COMPLETE' && mode!='PLAY'" @click="handlePlayAudio()">播放录音
</el-button>
<el-button round type="warning" v-show="state=='COMPLETE' && mode=='PLAY'" @click="handleStopAudio()">停止播放
</el-button>
<el-button round type="primary" v-show="state=='COMPLETE'" @click="handleRestartRecord()">重新录音</el-button> <el-button round type="primary" v-show="state=='COMPLETE'" @click="handleRestartRecord()">重新录音</el-button>
<el-button round type="primary" v-show="state=='COMPLETE'" @click="handleSendRecord()">立即发送</el-button> <el-button round type="primary" v-show="state=='COMPLETE'" @click="handleSendRecord()">立即发送</el-button>
</el-row> </el-row>
@ -19,9 +25,7 @@
</template> </template>
<script> <script>
import Recorderx, { import Recorder from 'js-audio-recorder';
ENCODE_TYPE
} from 'recorderx';
export default { export default {
name: 'chatVoice', name: 'chatVoice',
@ -32,51 +36,72 @@
}, },
data() { data() {
return { return {
rc: new Recorderx(), rc: new Recorder(),
state: 'STOP', //STOPRUNNINGPAUSECOMPLETE audio: new Audio(),
duration: 0 state: 'STOP', // STOPRUNNINGPAUSECOMPLETE
stateTip: "未开始",
mode: 'RECORD', // RECORD PLAY
duration: 0,
url: ""
} }
}, },
methods: { methods: {
handleClose() { handleClose() {
//
this.rc.stop();
this.audio.pause();
this.mode = 'RECORD';
this.state = 'STOP';
this.stateTip = '未开始';
this.$emit("close"); this.$emit("close");
}, },
handleStartRecord() { handleStartRecord() {
this.rc.start().then(() => { this.rc.start().then((stream) => {
this.$message.success("开始录音"); this.state = 'RUNNING';
this.stateTip = "正在录音...";
}).catch(error => { }).catch(error => {
this.$message.error("录音失败" + error.message); this.$message.error("录音失败");
console.log(error);
}); });
console.log(this.rc)
this.state = 'RUNNING';
}, },
handlePauseRecord() { handlePauseRecord() {
this.rc.pause();
this.state = 'PAUSE'; this.state = 'PAUSE';
this.stateTip = "已暂停录音";
}, },
handleResumeRecord() { handleResumeRecord() {
this.rc.resume();
this.state = 'RUNNING'; this.state = 'RUNNING';
this.stateTip = "正在录音...";
}, },
handleCompleteRecord() { handleCompleteRecord() {
this.rc.pause() this.rc.pause();
let wav = this.rc.getRecord({
encodeTo: ENCODE_TYPE.WAV,
});
console.log(wav);
this.state = 'COMPLETE'; this.state = 'COMPLETE';
this.stateTip = "已结束录音";
}, },
handlePlayRecord() { handlePlayAudio() {
let wav = this.rc.getWAVBlob();
let url = URL.createObjectURL(wav);
this.$refs.audio.src = url;
this.$refs.audio.play();
this.mode = 'PLAY';
},
handleStopAudio() {
console.log(this.$refs.audio);
this.$refs.audio.pause();
this.mode = 'RECORD';
}, },
handleRestartRecord() { handleRestartRecord() {
this.rc.destroy();
this.rc.start();
this.state = 'RUNNING'; this.state = 'RUNNING';
this.mode = 'RECORD';
this.stateTip = "正在录音...";
}, },
handleSendRecord() { handleSendRecord() {
this.upload(); let wav = this.rc.getWAVBlob();
},
upload() {
let wav = this.rc.getRecord({
encodeTo: ENCODE_TYPE.WAV,
});
let name = new Date().getDate() + '.wav'; let name = new Date().getDate() + '.wav';
var formData = new window.FormData() var formData = new window.FormData()
formData.append('file', wav, name); formData.append('file', wav, name);
@ -87,14 +112,28 @@
headers: { headers: {
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
} }
}).then((url)=>{ }).then((url) => {
this.$message.success("上传成功"); let data = {
console.log(url); duration: parseInt(this.rc.duration),
url: url
}
this.$emit("send", data);
}) })
} }
} }
} }
</script> </script>
<style> <style lang="scss">
.chat-voice {
.chat-voice-tip {
font-size: 18px;
}
.chat-voice-btn-group {
margin-bottom: 20px;
}
}
</style> </style>

22
im-ui/src/components/chat/MessageItem.vue

@ -32,6 +32,9 @@
</div> </div>
<span title="发送失败" v-show="loadFail" @click="handleSendFail" class="send-fail el-icon-warning"></span> <span title="发送失败" v-show="loadFail" @click="handleSendFail" class="send-fail el-icon-warning"></span>
</div> </div>
<div class="im-msg-voice" v-if="msgInfo.type==3" @click="handlePlayVoice()">
<audio controls :src="JSON.parse(msgInfo.content).url"></audio>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -65,6 +68,12 @@
required: true required: true
} }
}, },
data(){
return {
audioPlayState: 'STOP',
}
},
methods:{ methods:{
handleSendFail(){ handleSendFail(){
this.$message.error("该文件已发送失败,目前不支持自动重新发送,建议手动重新发送") this.$message.error("该文件已发送失败,目前不支持自动重新发送,建议手动重新发送")
@ -74,6 +83,14 @@
if(imageUrl){ if(imageUrl){
this.$store.commit('showFullImageBox',imageUrl); this.$store.commit('showFullImageBox',imageUrl);
} }
},
handlePlayVoice(){
if(!this.audio){
this.audio = new Audio();
}
this.audio.src = JSON.parse(this.msgInfo.content).url;
this.audio.play();
this.handlePlayVoice = 'RUNNING';
} }
}, },
computed:{ computed:{
@ -229,6 +246,11 @@
} }
} }
.im-msg-voice {
font-size: 14px;
cursor: pointer;
}
} }
} }

Loading…
Cancel
Save