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. 24
      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,"文件"),
IMAGE(1,"图片"),
VIDEO(2,"视频");
VIDEO(2,"视频"),
AUDIO(3,"声音");
private Integer code;

2
im-ui/package.json

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

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

@ -48,7 +48,7 @@
</el-aside>
</el-container>
<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>
</template>
@ -231,6 +231,31 @@
closeVoiceBox(){
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) {
if (this.chat.type == "GROUP") {
msgInfo.groupId = targetId;

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

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

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

@ -32,6 +32,9 @@
</div>
<span title="发送失败" v-show="loadFail" @click="handleSendFail" class="send-fail el-icon-warning"></span>
</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>
@ -65,6 +68,12 @@
required: true
}
},
data(){
return {
audioPlayState: 'STOP',
}
},
methods:{
handleSendFail(){
this.$message.error("该文件已发送失败,目前不支持自动重新发送,建议手动重新发送")
@ -74,7 +83,15 @@
if(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:{
loading(){
@ -229,6 +246,11 @@
}
}
.im-msg-voice {
font-size: 14px;
cursor: pointer;
}
}
}

Loading…
Cancel
Save