本地临时存储
This commit is contained in:
@@ -1,21 +1,49 @@
|
||||
<template>
|
||||
<view class="talk-btns">
|
||||
<uv-button class="touch-btn" @touchstart="startRecord" @touchend="stopRecord" @touchmove="handleMove"
|
||||
v-if="!keyboardIsShow" :customStyle="{height:'92rpx'}">按住说话
|
||||
<uv-button
|
||||
class="touch-btn"
|
||||
@touchstart="startRecord"
|
||||
@touchend="stopRecord"
|
||||
@touchmove="handleMove"
|
||||
v-if="!keyboardIsShow"
|
||||
:customStyle="{ height: '92rpx' }"
|
||||
>
|
||||
按住说话
|
||||
</uv-button>
|
||||
<view class="touch-btn" v-if="keyboardIsShow">
|
||||
<uv-input class="input-box" ref="inputRef" v-model="inputText" :maxlength="props.textValueLength"
|
||||
:adjustPosition="false" placeholderStyle='color:#999999;font-size:26rpx' placeholder="请输入文字">
|
||||
</uv-input>
|
||||
<uv-input
|
||||
class="input-box"
|
||||
ref="inputRef"
|
||||
v-model="inputText"
|
||||
:maxlength="props.textValueLength"
|
||||
:adjustPosition="false"
|
||||
placeholderStyle="color:#999999;font-size:26rpx"
|
||||
placeholder="请输入文字"
|
||||
></uv-input>
|
||||
</view>
|
||||
<view class="talk-btn-box">
|
||||
<image class="talk-btn-icon" v-show="!keyboardIsShow" src="@/static/images/course/jianpan.png" mode=""
|
||||
@click="changeBtn"></image>
|
||||
<image class="talk-btn-icon" v-show="keyboardIsShow && !inputText" src="@/static/images/course/record.png"
|
||||
mode="" @click="changeBtn"></image>
|
||||
<image
|
||||
class="talk-btn-icon"
|
||||
v-show="!keyboardIsShow"
|
||||
src="@/static/images/course/jianpan.png"
|
||||
mode=""
|
||||
@click="changeBtn"
|
||||
></image>
|
||||
<image
|
||||
class="talk-btn-icon"
|
||||
v-show="keyboardIsShow && !inputText"
|
||||
src="@/static/images/course/record.png"
|
||||
mode=""
|
||||
@click="changeBtn"
|
||||
></image>
|
||||
|
||||
<image class="talk-btn-icon" v-show="keyboardIsShow && !!inputText" src="@/static/images/course/send.png"
|
||||
mode="" @click.stop="showKeyboard"></image>
|
||||
<image
|
||||
class="talk-btn-icon"
|
||||
v-show="keyboardIsShow && !!inputText"
|
||||
src="@/static/images/course/send.png"
|
||||
mode=""
|
||||
@click.stop="showKeyboard"
|
||||
></image>
|
||||
</view>
|
||||
|
||||
<uni-popup ref="popupRef" class="popup">
|
||||
@@ -27,39 +55,27 @@
|
||||
</view>
|
||||
<view class="tips-box">松开发送</view>
|
||||
<view class="btns-box">
|
||||
<view :class="['close-btn',isOut?'is-out':'']" id="circleBox">取消
|
||||
<view :class="['close-btn', isOut ? 'is-out' : '']" id="circleBox">
|
||||
取消
|
||||
<image class="btn-box" v-if="!isOut" src="@/static/images/course/close.png" mode=""></image>
|
||||
<image class="btn-box" v-else src="@/static/images/course/close-active.png" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view :class="['talk-dialog',isOut?'is-out':'']">
|
||||
<view :class="['talk-dialog', isOut ? 'is-out' : '']">
|
||||
<image src="@/static/images/course/voice-white.gif" mode="" class="gif-box"></image>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
toRefs,
|
||||
ref,
|
||||
computed,
|
||||
unref,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
nextTick,
|
||||
watch,
|
||||
reactive
|
||||
} from 'vue';
|
||||
import { toRefs, ref, computed, unref, onMounted, onUnmounted, nextTick, watch, reactive } from 'vue';
|
||||
import common from '@/common/common';
|
||||
import permission from '@/common/permission.js'
|
||||
import {
|
||||
getPhoneEnvBool
|
||||
} from '@/common/common.js'
|
||||
import permission from '@/common/permission.js';
|
||||
import { getPhoneEnvBool } from '@/common/common.js';
|
||||
|
||||
const emit = defineEmits(['submit'])
|
||||
const emit = defineEmits(['submit']);
|
||||
const props = defineProps({
|
||||
isDisabled: {
|
||||
default: true,
|
||||
@@ -85,140 +101,116 @@
|
||||
type: Number,
|
||||
default: 500
|
||||
},
|
||||
minRecordDuration: { // 最小录音间隔
|
||||
minRecordDuration: {
|
||||
// 最小录音间隔
|
||||
type: Number,
|
||||
default: 1000
|
||||
},
|
||||
|
||||
})
|
||||
const {
|
||||
isDisabled,
|
||||
} = toRefs(props)
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
const { isDisabled } = toRefs(props);
|
||||
|
||||
// 键盘还是语音
|
||||
const keyboardIsShow = ref(false)
|
||||
const popupRef = ref(null)
|
||||
|
||||
watch(() => props.isLoading, () => {}, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
watch(() => props.canAnswer, () => {}, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
|
||||
watch(() => props.isDisabled, (val) => {
|
||||
if (val) {
|
||||
keyboardIsShow.value = false
|
||||
}
|
||||
}, {
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
|
||||
const inputText = ref('')
|
||||
const keyboardIsShow = ref(false);
|
||||
const popupRef = ref(null);
|
||||
const inputText = ref('');
|
||||
let startTime = 0;
|
||||
|
||||
// not_started 未开始, preparing 准备中, in_recording 录音中,ending 结束中
|
||||
const recordingStatus = ref('not_started')
|
||||
const recordingStatus = ref('not_started');
|
||||
// 获取全局唯一的录音管理器 recorderManager
|
||||
const recorderManager = uni.getRecorderManager();
|
||||
// const innerAudioContext = uni.createInnerAudioContext();
|
||||
const startTimer = ref(null); // 延迟启动的定时器ID
|
||||
const startFlag = ref(1)
|
||||
const startRecord = (obj) => { // 开始录音
|
||||
const startFlag = ref(1);
|
||||
const startRecord = (obj) => {
|
||||
// 开始录音
|
||||
console.log('开始录音', recordingStatus.value);
|
||||
if (recordingStatus.value !== 'not_started') return;
|
||||
touchY.value = obj.changedTouches[0].pageY
|
||||
touchY.value = obj.changedTouches[0].pageY;
|
||||
startTimer.value = setTimeout(() => {
|
||||
console.log('延迟开始');
|
||||
recordingStatus.value = 'preparing'
|
||||
isMoving.value = true
|
||||
recordingStatus.value = 'preparing';
|
||||
popupRef.value.open();
|
||||
recorderManager.start();
|
||||
}, 80);
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
// 结束录音
|
||||
const stopRecord = (obj) => {
|
||||
console.log('结束录音', obj);
|
||||
const stopRecord = () => {
|
||||
console.log('结束录音');
|
||||
if (startTimer.value) {
|
||||
clearTimeout(startTimer.value);
|
||||
startTimer.value = null;
|
||||
}
|
||||
recorderManager.stop();
|
||||
popupRef.value.close()
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
recordingStatus.value = 'not_started'
|
||||
}, 300)
|
||||
})
|
||||
}
|
||||
const endTime = Date.now();
|
||||
const times = Math.max(400 - endTime + startTime, 0);
|
||||
setTimeout(() => {
|
||||
console.log('延迟数据', times);
|
||||
nextTick(() => {
|
||||
popupRef.value.close();
|
||||
recorderManager.stop();
|
||||
});
|
||||
}, times);
|
||||
nextTick(() => setTimeout(() => recordingStatus.value = 'not_started', 300));
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
recorderManager.onStop(function(res) {
|
||||
recorderManager.onStop(function (res) {
|
||||
console.log('recorder stop' + JSON.stringify(res));
|
||||
console.log('录音文件临时位置', res.tempFilePath);
|
||||
if (isOut) return; // 被划掉的语音
|
||||
console.log('录音文件临时位置', res.tempFilePath, isOut.value);
|
||||
if (isOut.value) return; // 被划掉的语音
|
||||
const endTime = Date.now();
|
||||
const recordDuration = (endTime - startTime);
|
||||
const recordDuration = endTime - startTime;
|
||||
console.log('说话时长', recordDuration);
|
||||
if (props.minRecordDuration > recordDuration) {
|
||||
return common.msg('说话时间太短,没有听清!')
|
||||
nextTick(()=>common.msg('说话时间太短,没有听清!'))
|
||||
return ;
|
||||
}
|
||||
console.log('录音结束,时长:', recordDuration, '秒');
|
||||
emit('submit', 'voice', res.tempFilePath)
|
||||
emit('submit', 'voice', res.tempFilePath);
|
||||
});
|
||||
recorderManager.onStart(function(res) {
|
||||
recorderManager.onStart(function (res) {
|
||||
// 检测是否已经抬手结束了
|
||||
console.log('检测是否已经抬手结束了', recordingStatus.value);
|
||||
if (recordingStatus.value !== 'preparing') {
|
||||
|
||||
stopRecord()
|
||||
stopRecord();
|
||||
}
|
||||
startTime = Date.now();
|
||||
popupRef.value.open()
|
||||
recordingStatus.value = 'in_recording'
|
||||
recordingStatus.value = 'in_recording';
|
||||
});
|
||||
})
|
||||
|
||||
const touchY = ref(0)
|
||||
const windowInfo = uni.getWindowInfo()
|
||||
|
||||
});
|
||||
|
||||
const touchY = ref(0);
|
||||
const windowInfo = uni.getWindowInfo();
|
||||
// 安全区域信息
|
||||
const safeArea = windowInfo.safeArea;
|
||||
|
||||
// 计算是否超出按下盒子位置
|
||||
const isOut = computed(() => {
|
||||
const btnHeight = windowInfo.screenWidth / 750 * 234;
|
||||
const btnHeight = (windowInfo.screenWidth / 750) * 234;
|
||||
return touchY.value < safeArea.bottom - btnHeight;
|
||||
});
|
||||
const activeNum = ref(1)
|
||||
|
||||
const isMoving = ref(false)
|
||||
|
||||
const activeNum = ref(1);
|
||||
const handleMove = (obj) => {
|
||||
touchY.value = obj.changedTouches[0].pageY
|
||||
}
|
||||
touchY.value = obj.changedTouches[0].pageY;
|
||||
};
|
||||
// 发送文本
|
||||
const showKeyboard = () => {
|
||||
if (keyboardIsShow.value) {
|
||||
const inputTextTram = inputText.value.trim()
|
||||
const inputTextTram = inputText.value.trim();
|
||||
if (inputTextTram) {
|
||||
emit('submit', 'text', inputTextTram)
|
||||
emit('submit', 'text', inputTextTram);
|
||||
} else {
|
||||
common.msg("不能发送空白消息!")
|
||||
common.msg('不能发送空白消息!');
|
||||
}
|
||||
} else {
|
||||
keyboardIsShow.value = !keyboardIsShow.value
|
||||
keyboardIsShow.value = !keyboardIsShow.value;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
// 切换键盘语音
|
||||
const changeBtn = () => {
|
||||
if (props.isDisabled) return
|
||||
keyboardIsShow.value = !keyboardIsShow.value
|
||||
inputText.value = ''
|
||||
}
|
||||
if (props.isDisabled) return;
|
||||
keyboardIsShow.value = !keyboardIsShow.value;
|
||||
inputText.value = '';
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -230,7 +222,7 @@
|
||||
|
||||
.touch-btn {
|
||||
height: 92rpx;
|
||||
box-shadow: 0 8rpx 20rpx 0 rgba(0, 0, 0, .06);
|
||||
box-shadow: 0 8rpx 20rpx 0 rgba(0, 0, 0, 0.06);
|
||||
text-align: center;
|
||||
line-height: 92rpx;
|
||||
color: #000;
|
||||
@@ -409,4 +401,4 @@
|
||||
::v-deep .uv-input__content__field-wrapper__field {
|
||||
padding-right: 60rpx;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<view class="nav-bar-div" >
|
||||
<view class="nav-bar" v-if="is_fixed" :style="{ backgroundColor: backgroundColor }"></view>
|
||||
<view class="nav-bar-seat" v-if="is_seat" :style="{ backgroundColor: backgroundColor }"></view>
|
||||
</view>
|
||||
<!-- <view class="nav-bar-div" >
|
||||
<view class="nav-bar" v-if="props.is_fixed" :style="{ backgroundColor: props.backgroundColor }"></view>
|
||||
<view class="nav-bar-seat" :style="{ backgroundColor: props.backgroundColor }"></view>
|
||||
</view> -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const windowInfo = uni.getWindowInfo()
|
||||
// const windowInfo = uni.getWindowInfo()
|
||||
|
||||
const props = defineProps({
|
||||
is_fixed: {
|
||||
@@ -34,11 +34,13 @@
|
||||
.nav-bar-seat {
|
||||
width: 100%;
|
||||
height: var(--status-bar-height);
|
||||
height: 200rpx;
|
||||
background-color: gold;
|
||||
}
|
||||
|
||||
.nav-bar-div {
|
||||
z-index: 1900;
|
||||
z-index: 2001;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
// position: relative;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user