收到了用户反馈,需要加上键盘快捷键,不能点 enter 就发送。
和大模型通信的后续版本,有语音输入的需求,问了下某代码生成很厉害的模型,这里做一个记录。
键盘快捷键
原来使用@keyup.enter="handleSubmit"
,这样用户只要输入 enter 就发送请求,很有可能只输入了半句话,或者需要换行,导致用户体验不好。
新增了一个函数handleMultiLineNewline
作为换行处理。测试了@keydown.meta.enter
,可以在 mac 系统下使用 cmd + enter/windows 系统下使用 win + enter 触发换行。@keydown.ctrl.enter
和@keydown.shift.enter
可以触发换行。
但是以上连用不知道为啥消息又自动发出去了。。。
索性自己写了一个函数handleEnter
来处理换行。
另一个需求是中文输入法下,未输入完时,使用 enter 键,默认不发送消息,整体如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <template> <el-input v-model="userInput" placeholder="请输入您的问题" @compositionstart="onCompositionStart" @compositionend="onCompositionEnd" @keydown.enter="handleEnter" type="textarea" :rows="5" maxlength="2048" show-word-limit /> </template> <script lang="ts" setup> const handleEnter = async (event: KeyboardEvent) => { if ( (event.shiftKey && event.key === 'Enter') || (event.ctrlKey && event.key === 'Enter') || (event.metaKey && event.key === 'Enter') ) { const start = (event.target as HTMLTextAreaElement).selectionStart const end = (event.target as HTMLTextAreaElement).selectionEnd const value = userInput.value userInput.value = value.slice(0, start) + '\n' + value.slice(end) ;(event.target as HTMLTextAreaElement).selectionStart = ( event.target as HTMLTextAreaElement ).selectionEnd = start + 1 event.preventDefault() // 阻止默认行为 } else if (!isComposing.value && event.key === 'Enter') { // 发送消息 handleSubmit(event) event.preventDefault() } }
// 标记输入法是否处于输入候选状态 const isComposing = ref(false) const onCompositionStart = () => { isComposing.value = true } const onCompositionEnd = () => { isComposing.value = false } </script>
|
当用户输入为空时,不做处理;当大模型在输出时,禁止用户再次提交信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const handleSubmit = async (event: any) => { console.log('handleSubmit', event) if (!userInput.value || userInput.value.trim().length === 0) { return } else if (loadingSend.value == true) { event.preventDefault() return } else { if (abortController.signal.aborted) { abortController = new AbortController() } loadingSend.value = true let text = userInput.value if (text.endsWith('\n')) { text = text.trimEnd() } chatList.value.push({ role: 'user', message: text }) userInput.value = '' scrollToBottom() handleChat(text) } }
|
语音输入
在 vue3 项目中,语音输入试用useSpeechRecognition
这个库,实现语音输入转文字功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| <template> <div id="app"> <el-input v-model="inputText" placeholder="请输入问题" :suffix-icon="VoiceIcon" @click:append="startVoiceInput" /> <el-button @click="sendRequest">发送请求</el-button> <el-button @click="generateImage">生成图片</el-button> <el-card v-if="responseText" :title="responseText" style="margin-top: 20px;"></el-card> <img v-if="imageUrl" :src="imageUrl" alt="Generated Image" style="margin-top: 20px; max-width: 100%;"> </div> </template>
<script lang="ts" setup> import { useSpeechRecognition } from '@vueuse/core' import { Microphone } from '@element-plus/icons-vue'
// 语音输入 const { start, stop, result } = useSpeechRecognition({ language: 'zh-CN', })
const inputText = ref('') const responseText = ref('') const imageUrl = ref('') const VoiceIcon = Microphone
const startVoiceInput = async () => { await start() inputText.value = result.value }
const sendRequest = async () => { try { const response = await axios.post( 'https://api.openai.com/v1/chat/completions', { messages: [ { role: 'user', content: inputText.value, }, ], } ) responseText.value = response.data.choices[0].message.content; } catch (error) { console.error('请求出错:', error) } }
const generateImage = async () => { try { const response = await axios.post( 'https://api.openai.com/v1/images/generations', { prompt: inputText.value, n: 1, size: '512x512', } ) imageUrl.value = response.data.data[0].url; } catch (error) { console.error('图片生成出错:', error) } } </script>
|