|
@@ -1,5 +1,8 @@
|
|
|
<script setup>
|
|
|
+// const plugin = requirePlugin("WechatSI")
|
|
|
+
|
|
|
import { ref, unref, onMounted } from 'vue';
|
|
|
+import { baseURL } from '@/utils/https';
|
|
|
|
|
|
const modelInpValue = defineModel();
|
|
|
const emit = defineEmits(['on-submit']);
|
|
@@ -12,11 +15,16 @@ const volumeLevel = ref(50); // 模拟音量级别
|
|
|
let recorderManager = null;
|
|
|
const audioPath = ref(null);
|
|
|
|
|
|
+// 实时语音识别
|
|
|
+// const manager = plugin.getRecordRecognitionManager();
|
|
|
+
|
|
|
+
|
|
|
+console.log( "manager", manager );
|
|
|
|
|
|
const innerAudioContext = wx.createInnerAudioContext();
|
|
|
|
|
|
// 类型 input|voice
|
|
|
-const inpType = ref('input');
|
|
|
+const inpType = ref('input');
|
|
|
|
|
|
// 提交问题
|
|
|
const onSubmit = () => {
|
|
@@ -43,17 +51,51 @@ const onChangeInpType = () => {
|
|
|
inpType.value = inpType.value === 'input' ? 'voice' : 'input';
|
|
|
}
|
|
|
|
|
|
+const uploadAudio = (filePath) => {
|
|
|
+ uni.showLoading({
|
|
|
+ title: '上传中...'
|
|
|
+ });
|
|
|
+ uni.uploadFile({
|
|
|
+ url: 'https://your-server.com/upload',
|
|
|
+ filePath: filePath,
|
|
|
+ name: 'audio', // 后端接收文件的字段名
|
|
|
+ formData: {
|
|
|
+ // 可以附加其他表单数据
|
|
|
+ 'userId': '123',
|
|
|
+ 'timestamp': new Date().getTime()
|
|
|
+ },
|
|
|
+ success: (uploadRes) => {
|
|
|
+ uni.hideLoading();
|
|
|
+ console.log('上传成功', uploadRes);
|
|
|
+ // 处理服务器返回的数据
|
|
|
+ const data = JSON.parse(uploadRes.data);
|
|
|
+ uni.showToast({
|
|
|
+ title: '上传成功',
|
|
|
+ icon: 'success'
|
|
|
+ });
|
|
|
+ },
|
|
|
+ fail: (error) => {
|
|
|
+ uni.hideLoading();
|
|
|
+ console.log('上传失败', error);
|
|
|
+ uni.showToast({
|
|
|
+ title: '上传失败',
|
|
|
+ icon: 'none'
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
const playRecording = () => {
|
|
|
-
|
|
|
+
|
|
|
if (innerAudioContext) {
|
|
|
innerAudioContext.src = audioPath.value;
|
|
|
innerAudioContext.play();
|
|
|
-
|
|
|
+
|
|
|
innerAudioContext.onPlay(() => {
|
|
|
console.log('开始播放');
|
|
|
});
|
|
|
-
|
|
|
+
|
|
|
innerAudioContext.onError((err) => {
|
|
|
console.error('播放错误:', err);
|
|
|
uni.showToast({ title: '播放失败', icon: 'none' });
|
|
@@ -65,7 +107,7 @@ const playRecording = () => {
|
|
|
const startRecording = e => {
|
|
|
isRecording.value = true;
|
|
|
showVolume.value = true;
|
|
|
-
|
|
|
+
|
|
|
recorderManager.start({
|
|
|
format: 'mp3',
|
|
|
duration: 60000, // 最长1分钟
|
|
@@ -78,45 +120,53 @@ const startRecording = e => {
|
|
|
|
|
|
function setupRecorderEvents() {
|
|
|
if (!recorderManager) return;
|
|
|
-
|
|
|
- recorderManager.onStart(() => {
|
|
|
- console.log('录音开始');
|
|
|
- });
|
|
|
-
|
|
|
- recorderManager.onPause(() => {
|
|
|
- console.log('录音暂停');
|
|
|
- });
|
|
|
-
|
|
|
- recorderManager.onStop((res) => {
|
|
|
- // audioPath.value = 'https://web-ext-storage.dcloud.net.cn/uni-app/ForElise.mp3';
|
|
|
-
|
|
|
- audioPath.value = res.tempFilePath;
|
|
|
-
|
|
|
- // setTimeout(() => {
|
|
|
- // innerAudioContext.src = 'https://dlink.host/musics/aHR0cHM6Ly9vbmVkcnYtbXkuc2hhcmVwb2ludC5jb20vOnU6L2cvcGVyc29uYWwvc3Rvcl9vbmVkcnZfb25taWNyb3NvZnRfY29tL0VjYzBzQUxiWFk5TWdHQl9GUVNkV2pJQm5wRmM0MktDZWpURnhhMjhELUdXeVE.mp3';
|
|
|
- // innerAudioContext.play();
|
|
|
- // }, 1000)
|
|
|
|
|
|
- console.log('录音停止', res);
|
|
|
- // 这里可以处理录音结果,如上传或播放
|
|
|
- });
|
|
|
- recorderManager.onFrameRecorded((res) => {
|
|
|
- // 可以在这里获取实时音量等信息
|
|
|
- const volume = res.volumn; // 注意微信可能是volumn而不是volume
|
|
|
- if (volume !== undefined) {
|
|
|
- volumeLevel.value = Math.min(100, volume * 200); // 调整音量显示比例
|
|
|
- }
|
|
|
+ uni.authorize({
|
|
|
+ scope: 'scope.record',
|
|
|
+ success() {
|
|
|
+ recorderManager.onStart(() => {
|
|
|
+ console.log('录音开始');
|
|
|
+ });
|
|
|
+
|
|
|
+ recorderManager.onPause(() => {
|
|
|
+ console.log('录音暂停');
|
|
|
+ });
|
|
|
+
|
|
|
+ recorderManager.onStop((res) => {
|
|
|
+
|
|
|
+ audioPath.value = res.tempFilePath;
|
|
|
+
|
|
|
+ // setTimeout(() => {
|
|
|
+ // innerAudioContext.src = 'https://dlink.host/musics/aHR0cHM6Ly9vbmVkcnYtbXkuc2hhcmVwb2ludC5jb20vOnU6L2cvcGVyc29uYWwvc3Rvcl9vbmVkcnZfb25taWNyb3NvZnRfY29tL0VjYzBzQUxiWFk5TWdHQl9GUVNkV2pJQm5wRmM0MktDZWpURnhhMjhELUdXeVE.mp3';
|
|
|
+ // innerAudioContext.play();
|
|
|
+ // }, 1000)
|
|
|
+
|
|
|
+ console.log('录音停止', res);
|
|
|
+ // 这里可以处理录音结果,如上传或播放
|
|
|
+ });
|
|
|
+ recorderManager.onFrameRecorded((res) => {
|
|
|
+ // 可以在这里获取实时音量等信息
|
|
|
+ const volume = res.volumn; // 注意微信可能是volumn而不是volume
|
|
|
+ if (volume !== undefined) {
|
|
|
+ volumeLevel.value = Math.min(100, volume * 200); // 调整音量显示比例
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ fail() {
|
|
|
+ uni.showToast({ title: '用户拒绝授权录音权限', icon: 'none' });
|
|
|
+ },
|
|
|
});
|
|
|
+
|
|
|
}
|
|
|
|
|
|
function stopRecording() {
|
|
|
if (!isRecording.value) return;
|
|
|
-
|
|
|
+
|
|
|
isRecording.value = false;
|
|
|
showVolume.value = false;
|
|
|
-
|
|
|
+
|
|
|
recorderManager.stop();
|
|
|
-
|
|
|
+
|
|
|
// 停止音量检测
|
|
|
// stopVolumeDetection();
|
|
|
}
|
|
@@ -126,6 +176,8 @@ onMounted(() => {
|
|
|
recorderManager = wx.getRecorderManager();
|
|
|
|
|
|
setupRecorderEvents();
|
|
|
+
|
|
|
+
|
|
|
});
|
|
|
</script>
|
|
|
|
|
@@ -134,14 +186,17 @@ onMounted(() => {
|
|
|
<view class="voice-inner">
|
|
|
<view class="voice-card">
|
|
|
<view class="voice-tip">
|
|
|
+ <view class="la-line-scale-pulse-out">
|
|
|
+ <view></view>
|
|
|
+ <view></view>
|
|
|
+ <view></view>
|
|
|
+ <view></view>
|
|
|
+ <view></view>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</view>
|
|
|
- <view
|
|
|
- class="vocie-btn_wrapper"
|
|
|
- @touchstart="startRecording"
|
|
|
- @touchend="stopRecording"
|
|
|
- @touchcancel="stopRecording"
|
|
|
- >
|
|
|
+ <view class="vocie-btn_wrapper" @touchstart="startRecording" @touchend="stopRecording"
|
|
|
+ @touchcancel="stopRecording">
|
|
|
<view class="tips">{{ recordingTip }}</view>
|
|
|
<view class="btn">
|
|
|
<uni-icons type="sound" size="20" color="#777"></uni-icons>
|
|
@@ -157,26 +212,13 @@ onMounted(() => {
|
|
|
<TheSvgIcon class="icon" src="icon-voice" size="42"></TheSvgIcon>
|
|
|
</view>
|
|
|
<view class="inp-inner">
|
|
|
- <textarea
|
|
|
- v-model.trim="modelInpValue"
|
|
|
- :show-confirm-bar="false"
|
|
|
- :cursor-spacing="30"
|
|
|
- auto-height
|
|
|
- :maxlength="2000"
|
|
|
- class="chat-inp"
|
|
|
- placeholder="输入您的问题或需求"
|
|
|
- placeholder-style="color:#9A9A9A"
|
|
|
- v-show="inpType == 'input'"
|
|
|
- >
|
|
|
+ <textarea v-model.trim="modelInpValue" :show-confirm-bar="false" :cursor-spacing="30" auto-height
|
|
|
+ :maxlength="2000" class="chat-inp" placeholder="输入您的问题或需求" placeholder-style="color:#9A9A9A"
|
|
|
+ v-show="inpType == 'input'">
|
|
|
</textarea>
|
|
|
|
|
|
- <view
|
|
|
- class="chat-voice"
|
|
|
- v-show="inpType == 'voice'"
|
|
|
- @touchstart="startRecording"
|
|
|
- @touchend="stopRecording"
|
|
|
- @touchcancel="stopRecording"
|
|
|
- >
|
|
|
+ <view class="chat-voice" v-show="inpType == 'voice'" @touchstart="startRecording" @touchend="stopRecording"
|
|
|
+ @touchcancel="stopRecording">
|
|
|
<text>按住 说话</text>
|
|
|
</view>
|
|
|
</view>
|
|
@@ -243,6 +285,7 @@ onMounted(() => {
|
|
|
height: 56rpx;
|
|
|
border-radius: 100%;
|
|
|
background: #212121;
|
|
|
+
|
|
|
.icon {
|
|
|
transition: all 0.3s ease-in-out;
|
|
|
}
|
|
@@ -266,18 +309,23 @@ onMounted(() => {
|
|
|
height: 100%;
|
|
|
|
|
|
.voice-card {
|
|
|
- flex:1;
|
|
|
+ flex: 1;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
width: 100vw;
|
|
|
+
|
|
|
.voice-tip {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 10rpx 20rpx;
|
|
|
width: 100px;
|
|
|
- height: 30px;
|
|
|
- background: red;
|
|
|
+ border-radius: 10rpx;
|
|
|
+ background: #00aa5b;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
.vocie-btn_wrapper {
|
|
|
position: relative;
|
|
|
display: flex;
|
|
@@ -288,6 +336,7 @@ onMounted(() => {
|
|
|
height: 200rpx;
|
|
|
width: 100vw;
|
|
|
overflow: hidden;
|
|
|
+
|
|
|
.tips {
|
|
|
padding-bottom: 10rpx;
|
|
|
flex-shrink: 0;
|
|
@@ -295,6 +344,7 @@ onMounted(() => {
|
|
|
font-size: 24rpx;
|
|
|
text-align: center;
|
|
|
}
|
|
|
+
|
|
|
.btn {
|
|
|
flex: 1;
|
|
|
display: flex;
|