ux: 录音改为点击开始/点击结束

- 移除长按交互 (touchstart/touchend/mousedown/mouseup)
- 改为单击 toggle: 点击🎤开始录音, 再点击结束录音
- 按钮默认只显示🎤, 录音中显示🔴+秒数
- 下方提示改为'点击结束'
- 录音开始时清空 inputText
- 移除 suppressAutoSend 标志 (点击结束都是有意操作)
This commit is contained in:
yuzhiran
2026-07-05 19:41:21 +08:00
parent db1b3baa60
commit 50bb3c45ed
+19 -24
View File
@@ -61,14 +61,14 @@
<view class="input-bar" v-if="!isComplete">
<view class="mic-wrap">
<view class="mic-btn" :class="{ recording: isRecording }" @touchstart="startRecord" @touchend="stopRecord" @touchcancel="stopRecord" @mousedown="startRecord" @mouseup="stopRecord" @mouseleave="stopRecord">
<view class="mic-btn" :class="{ recording: isRecording }" @click="toggleRecord">
<text class="mic-icon">{{ isRecording ? '🔴' : '🎤' }}</text>
<text class="mic-label">{{ isRecording ? recordingDuration + 's' : '按住' }}</text>
<text class="mic-label" v-if="isRecording">{{ recordingDuration }}s</text>
</view>
<text class="mic-hint" v-if="isRecording">松开结束</text>
<text class="mic-hint" v-if="isRecording">点击结束</text>
</view>
<view class="input-box">
<textarea class="input-area" v-model="inputText" placeholder="按住🎤说话或输入回答..." :auto-height="true" :maxlength="2000" :disabled="aiLoading || isRecording" @confirm="sendAnswer" />
<textarea class="input-area" v-model="inputText" placeholder="点击🎤开始录音或输入回答..." :auto-height="true" :maxlength="2000" :disabled="aiLoading || isRecording" @confirm="sendAnswer" />
</view>
<view class="send-btn" :class="{ disabled: !inputText.trim() || isRecording || aiLoading }" @click="sendAnswer">
<text class="send-icon"></text>
@@ -158,7 +158,7 @@ const isRecording = ref(false)
const recordingDuration = ref(0)
let manager = null
let recordTimer = null
let suppressAutoSend = false
function initRecorder() {
// #ifdef MP-WEIXIN
@@ -169,6 +169,7 @@ function initRecorder() {
manager.onStart = () => {
console.log('[WechatSI] start')
isRecording.value = true
inputText.value = ''
recordingDuration.value = 0
recordTimer = setInterval(() => { recordingDuration.value++ }, 1000)
}
@@ -179,7 +180,6 @@ function initRecorder() {
isRecording.value = false
recordingDuration.value = 0
if (recordTimer) { clearInterval(recordTimer); recordTimer = null }
if (suppressAutoSend) { suppressAutoSend = false; return }
const text = res?.result?.trim()
if (text && text.length >= 2) {
inputText.value = text
@@ -413,33 +413,28 @@ const confirmExit = () => {
})
}
function startRecord() {
function toggleRecord() {
if (aiLoading.value || isComplete.value) return
// #ifdef MP-WEIXIN
if (isRecording.value) return
if (!manager) initRecorder()
if (!manager) {
uni.showToast({ title: '语音功能初始化失败', icon: 'none' })
if (!isRecording.value) {
if (!manager) initRecorder()
if (!manager) {
uni.showToast({ title: '语音功能初始化失败', icon: 'none' })
return
}
manager.start({ lang: 'zh_CN', duration: 60000 })
uni.vibrateShort({ type: 'medium' })
return
}
manager.start({ lang: 'zh_CN', duration: 60000 })
uni.vibrateShort({ type: 'medium' })
if (!manager) { isRecording.value = false; return }
if (recordTimer) { clearInterval(recordTimer); recordTimer = null }
recordingDuration.value = 0
manager.stop()
// #endif
// #ifndef MP-WEIXIN
uni.showToast({ title: '语音输入仅支持小程序', icon: 'none' })
// #endif
}
function stopRecord() {
if (!isRecording.value) return
if (!manager) { isRecording.value = false; return }
if (recordingDuration.value < 1) {
suppressAutoSend = true
if (recordTimer) { clearInterval(recordTimer); recordTimer = null }
recordingDuration.value = 0
}
manager.stop()
}
</script>
<style scoped>