331 lines
8.9 KiB
Vue
331 lines
8.9 KiB
Vue
<template>
|
|
<view
|
|
:class="{
|
|
'focus': inputOnFocus
|
|
}"
|
|
:style="{
|
|
'transform': 'translateY(-' + (keyboardHeight + 'px') + ')'
|
|
}"
|
|
class="fix-page-bottom"
|
|
>
|
|
<view v-if="inputModel === 'input'" class="bottom-body flex-center-between">
|
|
<view class="history-wrap" @click="historyViewHandle">
|
|
历史
|
|
</view>
|
|
<view class="input-container">
|
|
<!-- 输入模式切换 -->
|
|
<view
|
|
class="input-model"
|
|
@click="toggleInputModel"
|
|
>
|
|
<image
|
|
:src="webUrl + '/aiChat/microphone.png'"
|
|
class="icon"
|
|
mode="widthFix"
|
|
/>
|
|
</view>
|
|
<!-- 输入框 -->
|
|
<view class="input-wrap flex-center-between">
|
|
<input
|
|
v-model.trim="prompt"
|
|
:show-confirm-bar="false"
|
|
:adjust-position="false"
|
|
:disabled="loading"
|
|
:maxlength="-1"
|
|
class="inp"
|
|
@confirm="sendHandle"
|
|
@focus="promptInputFocusHandle"
|
|
@blur="promptInputBlurHandle"
|
|
/>
|
|
<view v-if="!prompt && !inputOnFocus" class="placeholder-txt">发消息...</view>
|
|
</view>
|
|
<view
|
|
class="send-btn"
|
|
@click="sendHandle"
|
|
>
|
|
<image
|
|
:src="webUrl + '/aiChat/send.png'"
|
|
class="icon"
|
|
mode="widthFix"
|
|
/>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<!-- 语音输入 -->
|
|
<view
|
|
v-if="inputModel === 'sound'"
|
|
class="sound-input-wrap"
|
|
>
|
|
<view class="toggle-btn">
|
|
<image
|
|
:src="webUrl + '/aiChat/icon-06.png'"
|
|
class="input-icon"
|
|
mode="widthFix"
|
|
@click="toggleInputModel"
|
|
/>
|
|
</view>
|
|
<view
|
|
class="sound-wrap"
|
|
@touchstart="startRecord"
|
|
@touchend="stopRecord"
|
|
>
|
|
<view v-if="startTaskFlag" class="music-wrap">
|
|
<view class="item one" />
|
|
<view class="item two" />
|
|
<view class="item three" />
|
|
<view class="item four" />
|
|
<view class="item five" />
|
|
<view class="item six" />
|
|
<view class="item seven" />
|
|
</view>
|
|
<image
|
|
:src="webUrl + '/aiChat/microphone-big.png'"
|
|
class="icon"
|
|
mode="widthFix"
|
|
/>
|
|
<view v-if="startTaskFlag" class="music-wrap music-wrap2">
|
|
<view class="item one" />
|
|
<view class="item two" />
|
|
<view class="item three" />
|
|
<view class="item four" />
|
|
<view class="item five" />
|
|
<view class="item six" />
|
|
<view class="item seven" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
makeFileTransTask,
|
|
getFileTransResult
|
|
} from '@/api/voiceToText/index'
|
|
import { VUE_APP_API_URL } from '@/config'
|
|
import cookie from '@/utils/store/cookie'
|
|
export default {
|
|
name: 'BottomSend',
|
|
props: {
|
|
loading: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
keyboardHeight: {
|
|
type: Number,
|
|
default: 0
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
token: cookie.get('login_status'),
|
|
userInfo: cookie.get('userInfo'),
|
|
webUrl: this.$VUE_APP_RESOURCES_URL,
|
|
// 输入模式:input-键盘,sound-语音
|
|
inputModel: 'input',
|
|
prompt: '',
|
|
recordManager: null,
|
|
// 录音权限是否开通
|
|
recordPermission: false,
|
|
taskId: '',
|
|
taskTimer: null,
|
|
startTaskFlag: false,
|
|
// 输入框是否聚焦
|
|
inputOnFocus: false
|
|
}
|
|
},
|
|
beforeDestroy() {
|
|
this.clearIntervalFn()
|
|
},
|
|
created() {
|
|
uni.getSetting({
|
|
success: res => {
|
|
if (res.authSetting['scope.record']) {
|
|
this.recordPermission = true
|
|
}
|
|
}
|
|
})
|
|
},
|
|
methods: {
|
|
promptInputFocusHandle() {
|
|
setTimeout(() => {
|
|
this.inputOnFocus = true
|
|
this.$emit('focus', 1)
|
|
}, 200)
|
|
},
|
|
promptInputBlurHandle() {
|
|
setTimeout(() => {
|
|
this.inputOnFocus = false
|
|
this.$emit('focus', 0)
|
|
}, 200)
|
|
},
|
|
toggleInputModel() {
|
|
if (!this.token) {
|
|
uni.reLaunch({ url: '/pages/auth/login' })
|
|
return
|
|
}
|
|
if (this.loading) return
|
|
if (this.inputModel === 'input') {
|
|
uni.getSetting({
|
|
success: res => {
|
|
if (!res.authSetting['scope.record']) {
|
|
uni.authorize({
|
|
scope: 'scope.record',
|
|
success: () => {
|
|
console.log('获取录音权限成功')
|
|
this.recordPermission = true
|
|
this.inputModel = 'sound'
|
|
},
|
|
fail: () => {
|
|
console.log('获取录音权限失败')
|
|
this.recordPermission = false
|
|
uni.showModal({
|
|
title: '提示',
|
|
content: '需要获取麦克风权限',
|
|
confirmText: '前往设置',
|
|
confirmColor: '#3D4CF1',
|
|
success(res2) {
|
|
if (res2.confirm) {
|
|
wx.openSetting()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
} else {
|
|
this.recordPermission = true
|
|
this.inputModel = 'sound'
|
|
}
|
|
}
|
|
})
|
|
return
|
|
}
|
|
if (this.inputModel === 'sound') {
|
|
this.clearIntervalFn()
|
|
this.inputModel = 'input'
|
|
return
|
|
}
|
|
},
|
|
startRecord() {
|
|
if (this.loading) {
|
|
this.$toast('正在检索')
|
|
return
|
|
}
|
|
// 正在识别,不触发相关动作
|
|
if (this.startTaskFlag || this.taskTimer) {
|
|
return
|
|
}
|
|
this.recordManager = uni.getRecorderManager()
|
|
console.log('启动录音')
|
|
this.startTaskFlag = true
|
|
this.recordManager.start({
|
|
duration: 60 * 1000,
|
|
frameSize: 1,
|
|
sampleRate: 16000,
|
|
format: 'wav'
|
|
})
|
|
},
|
|
stopRecord() {
|
|
const _this = this
|
|
// 正在识别,不触发相关动作
|
|
if (this.taskTimer) {
|
|
return
|
|
}
|
|
if (_this.recordManager) {
|
|
_this.recordManager.stop()
|
|
console.log('停止录音')
|
|
_this.startTaskFlag = false
|
|
_this.recordManager.onStop((res) => {
|
|
console.log('录音结束------------')
|
|
console.log(res)
|
|
const { tempFilePath, fileSize, duration } = res
|
|
if (tempFilePath && fileSize && duration) {
|
|
_this.taskId = ''
|
|
_this.clearIntervalFn()
|
|
uni.showLoading({ title: '识别中...' })
|
|
uni.uploadFile({
|
|
url: `${VUE_APP_API_URL}/api/upload`,
|
|
filePath: tempFilePath,
|
|
header: {
|
|
Authorization: 'Bearer ' + (_this.token || '')
|
|
},
|
|
name: 'file',
|
|
success: uploadRes => {
|
|
console.log(JSON.parse(uploadRes.data))
|
|
_this.renderTransTask(uploadRes)
|
|
},
|
|
fail: err => {
|
|
console.log(err)
|
|
uni.hideLoading()
|
|
}
|
|
})
|
|
} else {
|
|
_this.$toast('没有听清您说了什么,请再说一遍')
|
|
}
|
|
})
|
|
}
|
|
},
|
|
renderTransTask(uploadRes) {
|
|
const _this = this
|
|
const file = JSON.parse(uploadRes.data).link || ''
|
|
if (!file) return
|
|
makeFileTransTask({
|
|
file
|
|
}).then(taskRes => {
|
|
_this.taskId = taskRes.data
|
|
_this.getTransResultReq()
|
|
}).catch(() => {
|
|
_this.$toast('没有听清您说了什么,请再说一遍')
|
|
uni.hideLoading()
|
|
})
|
|
},
|
|
getTransResultReq() {
|
|
const _this = this
|
|
_this.taskTimer = setInterval(() => {
|
|
getFileTransResult({
|
|
taskId: _this.taskId
|
|
}).then(res => {
|
|
const { success, data = [] } = res
|
|
if (success && data) {
|
|
uni.hideLoading()
|
|
_this.clearIntervalFn()
|
|
if (data === '__NULL__') {
|
|
_this.$toast('没有听清您说了什么,请再说一遍')
|
|
} else {
|
|
if (data.length > 0) {
|
|
const prompt = data[0].Text
|
|
if (prompt) {
|
|
_this.$emit('send', { prompt: prompt.replace('。', '') })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}).catch(() => {
|
|
uni.hideLoading()
|
|
})
|
|
}, 1000)
|
|
},
|
|
clearIntervalFn() {
|
|
this.taskTimer && clearInterval(this.taskTimer)
|
|
this.taskTimer = null
|
|
setTimeout(() => {
|
|
this.startTaskFlag = false
|
|
}, 300)
|
|
},
|
|
sendHandle() {
|
|
if (this.loading) return
|
|
if (!this.prompt) {
|
|
this.$toast('请输入您想问的内容')
|
|
return
|
|
}
|
|
this.$emit('send', { prompt: this.prompt })
|
|
this.prompt = ''
|
|
this.inputOnFocus = false
|
|
},
|
|
historyViewHandle() {
|
|
this.$emit('history')
|
|
}
|
|
}
|
|
}
|
|
</script>
|