jiuyiUniapp/jiuyi2/pages/news/chat/jy-voice.vue

289 lines
5.6 KiB
Vue
Raw Normal View History

2024-12-18 15:46:27 +08:00
<!-- 语音 -->
<template>
2025-01-08 21:01:16 +08:00
<view class="voice_box" @touchstart="sv.touchstartVoice" @touchmove.stop.prevent="sv.touchmoveVoice"
@touchend="sv.touchendVoice" @touchcancel="sv.touchcancelVoice">
2024-12-18 15:46:27 +08:00
<text class="voice_text c000">{{ voiceText }}</text>
</view>
<!-- 语音状态显示 -->
<template v-if="voiceFlg">
<!-- 录音UI效果 -->
<view class="record" :class="voiceFlg ? '' : 'hidden'">
<uni-icons :class="[voiceStop ? 'cancel' : 'ing']" :type="voiceStop ? 'micoff' : 'mic'" size="100" />
<view class="tis" :class="voiceStop ? 'change' : ''">{{ voiceTis }}</view>
</view>
</template>
</template>
<script setup>
2025-02-25 18:38:24 +08:00
import {
ref,
defineEmits
} from 'vue'
// 腾讯云聊天
import TencentCloudChat from '@tencentcloud/chat';
const props = defineProps({
msg: {
type: Object
},
})
const emit = defineEmits(['send'])
//录音
// #ifdef APP-PLUS
const recorderManager = uni.getRecorderManager();
// #endif
// 录音时长
const voiceLength = ref(0);
// 录音定时器
const voiceTimer = ref(null);
// 录音文本
const voiceText = ref('按住 说话');
// 录音提示
const voiceTis = ref('手指上滑 取消发送');
// 录音图标显示
const voiceFlg = ref(false);
// 录音开始Y坐标
const voicePageY = ref(0);
// 录音结束
const voiceStop = ref(false);
const str = '';
// 录音相关
const sv = {
// 按下触发
touchstartVoice: (e) => {
voicePageY.value = (e.changedTouches[0].pageY).toFixed(2);
recorderManager.start({
duration: 60000, // 录音的时长,单位 ms最大值 60000010 分钟)
sampleRate: 44100, // 采样率
numberOfChannels: 1, // 录音通道数
encodeBitRate: 192000, // 编码码率
format: "mp3"
});
voiceLength.value = 0;
voiceFlg.value = true
console.log('recorder start success');
//录音开始,
voiceTimer.value = setInterval(() => {
voiceLength.value += 0.1;
}, 100);
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
console.log('touchstartVoice', voicePageY.value);
},
// 滑动触发
touchmoveVoice: (e) => {
// 没有展示UI不触发
if (!voiceFlg.value) {
return;
2024-12-18 15:46:27 +08:00
}
2025-02-25 18:38:24 +08:00
let numTemp = voicePageY.value - ((e.changedTouches[0].pageY).toFixed(2));
if (numTemp >= 60) {
console.log('取消发送');
voiceStop.value = true
voiceTis.value = '松开手指 取消发送'
} else {
console.log('继续发送');
voiceStop.value = false
voiceTis.value = '手指上滑 取消发送'
2024-12-18 15:46:27 +08:00
}
2025-02-25 18:38:24 +08:00
},
// 松开触发
touchendVoice: () => {
// 没有展示UI不触发
if (!voiceFlg.value) {
return;
2024-12-18 15:46:27 +08:00
}
2025-02-25 18:38:24 +08:00
clearInterval(voiceTimer.value);
voiceText.value = '按住 说话'
voiceTis.value = "手指上滑 取消发送"
console.log('touchendVoice');
sv.stop();
},
// 打断触发
touchcancelVoice: () => {
clearInterval(voiceTimer.value);
// 关闭UI
voiceText.value = '按住 说话'
voiceTis.value = "手指上滑 取消发送"
// 不发送语音
voiceStop.value = true
console.log('touchcancelVoice');
sv.stop();
},
stop: () => {
voiceTimer.value = null;
voiceFlg.value = false
recorderManager.stop(); // 录音结束
console.log('录音结束');
}
};
// #ifdef APP-PLUS
// 监听录音停止事件
recorderManager.onStop((res) => {
// 被打断等情况不发送
if (voiceStop.value) {
return
}
// 正常情况
if (voiceStop.value) {
uni.showToast({
icon: "none",
title: "取消发送",
duration: 2000
})
return
}
if (voiceLength.value < 1) {
uni.showToast({
icon: "none",
title: "语音时长过短",
duration: 2000
})
return
}
if (voiceLength.value > 60) {
uni.showToast({
icon: "none",
title: "语音时长过长",
duration: 2000
})
return
}
console.log('file', res)
try {
let message = uni.$chat.createAudioMessage({
to: props.msg.id,
conversationType: props.msg.type,
payload: {
file: res
},
// 音频上传进度回调
onProgress: function (event) {
console.log('file uploading:', event)
}
})
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
let obj = {
query: {
toUserId: message.to,
formId: message.from,
msgType: message.type,
},
data: message
2024-12-18 15:46:27 +08:00
}
2025-02-25 18:38:24 +08:00
emit('send', obj)
} catch (e) {
console.log('message catch', e)
}
//
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
})
// #endif
2024-12-18 15:46:27 +08:00
</script>
<style scoped lang="scss">
2025-02-25 18:38:24 +08:00
.voice_box {
padding: 20rpx 0;
margin: 0 20rpx;
border-radius: 50rpx;
background: #fff;
flex: 1;
display: flex;
align-items: center;
justify-content: center;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
.hidden {
display: none !important;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
.record {
width: 40vw;
height: 40vw;
position: fixed;
top: 55%;
left: 30%;
background-color: rgba(0, 0, 0, .6);
border-radius: 20rpx;
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
.ing {
width: 100%;
height: 30vw;
display: flex;
justify-content: center;
align-items: center;
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
// 模拟录音音效动画
@keyframes volatility {
0% {
background-position: 0% 130%;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
20% {
background-position: 0% 150%;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
30% {
background-position: 0% 155%;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
40% {
background-position: 0% 150%;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
50% {
background-position: 0% 145%;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
70% {
background-position: 0% 150%;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
80% {
background-position: 0% 155%;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
90% {
background-position: 0% 140%;
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
100% {
background-position: 0% 135%;
2024-12-18 15:46:27 +08:00
}
2025-02-25 18:38:24 +08:00
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
background-image: linear-gradient(to bottom, #f09b37, #fff 50%);
background-size: 100% 200%;
animation: volatility 1.5s ease-in-out -1.5s infinite alternate;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 150rpx;
color: #f09b37;
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
.cancel {
width: 100%;
height: 30vw;
display: flex;
justify-content: center;
align-items: center;
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
color: #fff;
font-size: 150rpx;
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
}
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
.tis {
width: 100%;
height: 10vw;
display: flex;
justify-content: center;
font-size: 28rpx;
color: #fff;
2024-12-18 15:46:27 +08:00
2025-02-25 18:38:24 +08:00
&.change {
color: #f09b37;
2024-12-18 15:46:27 +08:00
}
}
2025-02-25 18:38:24 +08:00
}
2024-12-18 15:46:27 +08:00
</style>