在家开发了录音按钮功能

This commit is contained in:
终究是寂寞
2026-03-05 00:25:04 +08:00
parent 696a48f3d6
commit 015af519fb
7 changed files with 50 additions and 29 deletions
+2 -3
View File
@@ -2,11 +2,10 @@
ENV = 'development' ENV = 'development'
# 'development' # 'development'
#VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001' VITE_APP_BASE_API_Url = 'https://aits.jlbank.com.cn:7001'
VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002' #VITE_APP_BASE_API_Url = 'https://aitstest.jlbank.com.cn:7002'
# DEV # DEV
#VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001' #VITE_APP_BASE_API_Url = 'http://25.18.122.65:7001'
+19 -8
View File
@@ -243,6 +243,16 @@
.gif-box { .gif-box {
display: none; display: none;
} }
.textarea {
visibility: visible;
pointer-events: none;
user-select: none;
}
}
&.is-translate.success .textarea {
visibility: visible;
pointer-events: auto;
user-select: auto;
} }
&::after { &::after {
content: ''; content: '';
@@ -262,7 +272,11 @@
&.success::after { &.success::after {
left: 78% !important; left: 78% !important;
} }
// 输入框默认并不可见
.textarea {
visibility: hidden;
}
&.failed,&.networkError { &.failed,&.networkError {
width: 506rpx; width: 506rpx;
height: 114rpx; height: 114rpx;
@@ -275,17 +289,14 @@
.error-tip-div { .error-tip-div {
display: flex !important; display: flex !important;
visibility: visible; // 激活后可见 visibility: visible; // 激活后可见
// animation: fadeIn 0.4s ease-out 0.1s forwards;
} }
.textarea { .textarea {
visibility: hidden; // 初始不可见且不占交互位置 visibility: hidden;
}
}
&.init{
.textarea {
visibility: hidden; // 初始不可见且不占交互位置
} }
} }
} }
.talk-dialog { .talk-dialog {
width: 100%; width: 100%;
+2 -2
View File
@@ -8,8 +8,8 @@ const IsAndEnv = getPhoneEnvBool('AND')
// const url = '/traapp/asrAiModelSocket/open'; // const url = '/traapp/asrAiModelSocket/open';
const url = '/traapp/asrAiModelSocket/open'; const url = '/traapp/asrAiModelSocket/open';
const _baseUrl = get_base_url(url).split('http').join('ws'); const _baseUrl = get_base_url(url).split('http').join('ws');
export const wsUrl = _baseUrl + url + '?summary=' + getToken(); // export const wsUrl = _baseUrl + url + '?summary=' + getToken();
// export const wsUrl = 'wss://ty_chat_test.home.tymas.cn:8000/ws/audio'; export const wsUrl = 'ws://10.10.10.8:8000/ws/asr';
const windowInfo = uni.getWindowInfo(); const windowInfo = uni.getWindowInfo();
// 安全区域信息 // 安全区域信息
const safeArea = windowInfo.safeArea; const safeArea = windowInfo.safeArea;
@@ -9,6 +9,7 @@
*/ */
export type StatusType = 'default' | 'voice_recording' | 'text_input' | 'voice_to_text' | 'voice_send_ing' | 'send_over'; export type StatusType = 'default' | 'voice_recording' | 'text_input' | 'voice_to_text' | 'voice_send_ing' | 'send_over';
/** /**
* 语音转文字的子状态(仅当主状态为 voice_to_text 时生效) * 语音转文字的子状态(仅当主状态为 voice_to_text 时生效)
*/ */
@@ -20,6 +21,7 @@ export type VoiceToTextSubStatus =
| 'failed' // 转换失败(网络/识别错误等) | 'failed' // 转换失败(网络/识别错误等)
| 'networkError'; // 转换失败(网络错误等) | 'networkError'; // 转换失败(网络错误等)
export type WorkModeType = 'both' | 'text-only' | 'voice-only' ;
/** 错误码枚举 - 直接映射提示文本 */ /** 错误码枚举 - 直接映射提示文本 */
export enum ErrorCode { export enum ErrorCode {
+19 -10
View File
@@ -19,7 +19,7 @@
ref="inputRef" ref="inputRef"
v-model="inputText" v-model="inputText"
:maxlength="props.maxlength" :maxlength="props.maxlength"
:adjustPosition="false" :adjustPosition="props.adjustPosition"
placeholderStyle="color:#999999;font-size:26rpx" placeholderStyle="color:#999999;font-size:26rpx"
placeholder="请输入文字" placeholder="请输入文字"
:disabled="props.isDisabled" :disabled="props.isDisabled"
@@ -110,7 +110,7 @@
<script setup lang="ts"> <script setup lang="ts">
import * as TouchBtnImages from './touch-btn.images'; // 导出图片 import * as TouchBtnImages from './touch-btn.images'; // 导出图片
import { StatusType, VoiceToTextSubStatus, ErrorCode } from './touch-btn.types'; import { StatusType, VoiceToTextSubStatus, ErrorCode,WorkModeType } from './touch-btn.types';
import type { TouchBtnEmits } from './touch-btn.types'; import type { TouchBtnEmits } from './touch-btn.types';
import { wsUrl, bottomAreaTopBoundary, horizontalSplitX, initWebSocket, showErrorTip, vibrateLight } from './touch-btn'; import { wsUrl, bottomAreaTopBoundary, horizontalSplitX, initWebSocket, showErrorTip, vibrateLight } from './touch-btn';
import { ref, computed, onMounted, nextTick, watch, reactive } from 'vue'; import { ref, computed, onMounted, nextTick, watch, reactive } from 'vue';
@@ -161,6 +161,10 @@
type: Number, type: Number,
default: 1000 default: 1000
}, },
adjustPosition:{
default: true,
type: Boolean
},
answerMethod:{ answerMethod:{
type: String, type: String,
default: '01', default: '01',
@@ -170,7 +174,7 @@
} }
} }
}); });
const workMode = computed(() => { const workMode = computed<WorkModeType>(() => {
const modeMap = { const modeMap = {
'01': 'both', '01': 'both',
'02': 'text-only', '02': 'text-only',
@@ -254,6 +258,7 @@
voice_to_text_status.value = ''; voice_to_text_status.value = '';
tempText.value = ''; tempText.value = '';
allText.value = ''; allText.value = '';
console.log('都清空了');
initWebSocket(wsUrl) initWebSocket(wsUrl)
.then((socketTask) => { .then((socketTask) => {
ws.value = socketTask; ws.value = socketTask;
@@ -267,7 +272,7 @@
tempText.value = ''; tempText.value = '';
allText.value = allText.value + body; allText.value = allText.value + body;
} else if (msgType === MessageType.TIP_MESSAGE) { } else if (msgType === MessageType.TIP_MESSAGE) {
tempText.value = body as string; tempText.value += body as string;
} else if (msgType === MessageType.CONTROL_CMD) { } else if (msgType === MessageType.CONTROL_CMD) {
// 返回结束消息 // 返回结束消息
const controlBody = body as ControlBody; const controlBody = body as ControlBody;
@@ -305,7 +310,7 @@
}); });
}) })
.catch(() => { .catch(() => {
// stopRecord('networkError'); stopRecord('networkError');
console.log('网络出现问题'); console.log('网络出现问题');
}); });
pressTimer.value = setTimeout(() => { pressTimer.value = setTimeout(() => {
@@ -321,6 +326,7 @@
startAudioRecord({ startAudioRecord({
onFrame: (pcmData: any) => { onFrame: (pcmData: any) => {
if (wsStatus.value && ws.value) { if (wsStatus.value && ws.value) {
console.log('pcmData', pcmData.length);
ws.value.send({ data: ProtocolCodec.pack(MessageType.AUDIO_DATA, pcmData) }); ws.value.send({ data: ProtocolCodec.pack(MessageType.AUDIO_DATA, pcmData) });
} }
}, },
@@ -439,9 +445,14 @@
}; };
// 切换键盘语音 // 切换键盘语音
const changeBtn = () => { const changeBtn = (_isInputVisible = true) => {
if (props.isDisabled) return; if (props.isDisabled) return;
isInputVisible.value = !isInputVisible.value; // 只要不是仅录音,就可以切换到录音按钮
if(workMode.value === 'text-only') {
isInputVisible.value = false
}
// 否则为true
isInputVisible.value = _isInputVisible;
inputText.value = ''; inputText.value = '';
}; };
// 按钮右侧图标(三个功能) // 按钮右侧图标(三个功能)
@@ -454,8 +465,6 @@
} else { } else {
isInputVisible.value = !isInputVisible.value; isInputVisible.value = !isInputVisible.value;
} }
inputText.value = '';
}; };
// 禁用时点击给的提示 // 禁用时点击给的提示
const disabled_click = () => { const disabled_click = () => {
@@ -471,7 +480,7 @@
closePopup(); closePopup();
} }
}; };
setupKeyboardHeightListener((height: number) => { setupKeyboardHeightListener((height: number) => {
const _height = Math.max(height - 100, 0); const _height = Math.max(height - 100, 0);
pageBoxMarginBottom.value = `${_height}px`; pageBoxMarginBottom.value = `${_height}px`;
+5 -5
View File
@@ -135,7 +135,7 @@
</view> </view>
</scroll-view> </scroll-view>
</view> </view>
<TouchBtn <!-- <TouchBtn
class="talk-btns" class="talk-btns"
@uploadVoice="uploadRecordNow" @uploadVoice="uploadRecordNow"
@submitAnswer="submitAnswerNow" @submitAnswer="submitAnswerNow"
@@ -144,10 +144,10 @@
:isLoading="!answerIsOver" :isLoading="!answerIsOver"
:adjustPosition="true" :adjustPosition="true"
:isDisabled="isHistory" :isDisabled="isHistory"
/> /> -->
<!-- <touch-btn @uploadVoice="uploadRecordNow" @submitAnswer="submitAnswerNow" <touch-btn @uploadVoice="uploadRecordNow" @submitAnswer="submitAnswerNow"
@startRecord="startRecordCallback" :loadingText="sendLoadingText" :isLoading="!answerIsOver" @startRecord="startRecordCallback" :loadingText="sendLoadingText" :isLoading="!answerIsOver"
:adjustPosition="true" :isDisabled="isHistory" /> --> :adjustPosition="true" :isDisabled="isHistory" />
<History ref="historyRef" @showDetail="showHistoryDetail"></History> <History ref="historyRef" @showDetail="showHistoryDetail"></History>
<PreviewVue ref="previewRef" /> <PreviewVue ref="previewRef" />
@@ -167,7 +167,7 @@
import { ref, unref, onMounted, watch, nextTick, computed, onActivated } from 'vue'; import { ref, unref, onMounted, watch, nextTick, computed, onActivated } from 'vue';
import common from '@/common/common'; import common from '@/common/common';
import { setupKeyboardHeightListener } from '@/common/common'; import { setupKeyboardHeightListener } from '@/common/common';
import TouchBtn from '@/pages/course/components/touchBtn.vue'; // import TouchBtn from '@/pages/course/components/touchBtn.vue';
import TalkingItem from './components/talking-item.vue'; import TalkingItem from './components/talking-item.vue';
import PreviewVue from './components/preview.vue'; import PreviewVue from './components/preview.vue';
import { useSocketStore } from '@/store/socket.js'; import { useSocketStore } from '@/store/socket.js';
@@ -14,7 +14,7 @@ import AtomicBoolean from "java.util.concurrent.atomic.AtomicBoolean";
const isRecording = new AtomicBoolean(false); // 原子布尔值,保证线程安全 const isRecording = new AtomicBoolean(false); // 原子布尔值,保证线程安全
// 1. 音频采集参数(极简配置,适配大部分设备) // 1. 音频采集参数(极简配置,适配大部分设备)
const sampleRate : Int = 48000; // 采样率 const sampleRate : Int = 16000; // 采样率
const channelConfig = AudioFormat.CHANNEL_IN_MONO; // 单声道 const channelConfig = AudioFormat.CHANNEL_IN_MONO; // 单声道
const audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 16位PCM const audioFormat = AudioFormat.ENCODING_PCM_16BIT; // 16位PCM
const minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat); const minBufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);