mirror of
http://112.124.100.131/ebiz-ai/ebiz-base-ai.git
synced 2025-12-07 09:56:48 +08:00
feat(AI): 为 chat组件添加打字机动画效果
This commit is contained in:
@@ -90,33 +90,32 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
// isThink: {
|
||||
// type: Boolean,
|
||||
// default: false,
|
||||
// },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isThink: false,
|
||||
newMessage: '',
|
||||
// 录音相关状态
|
||||
isRecording: false,
|
||||
mediaRecorder: null,
|
||||
audioChunks: [],
|
||||
isRecognizing: false,
|
||||
// 语音模式开关
|
||||
isVoiceMode: false,
|
||||
answerMap: '',
|
||||
currentMessage: null,
|
||||
|
||||
// 打字机相关
|
||||
typingText: '',
|
||||
typingQueue: [],
|
||||
isTyping: false,
|
||||
typingSpeed: 50,
|
||||
typingTimeout: null,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
deepInternet() {
|
||||
// this.isDeep = !this.isDeep
|
||||
this.$emit('update:isDeep', !this.isDeep)
|
||||
},
|
||||
searchInternet() {
|
||||
// this.isSearching = !this.isSearching
|
||||
this.$emit('update:isSearching', !this.isSearching)
|
||||
},
|
||||
startNewConversation() {
|
||||
@@ -124,7 +123,6 @@ export default {
|
||||
this.$emit('update:conversationId', '')
|
||||
this.$emit('update:productName', '')
|
||||
},
|
||||
|
||||
async startRecording() {
|
||||
if (this.messageStatus === 'send') return
|
||||
if (this.isRecognizing) return
|
||||
@@ -173,9 +171,7 @@ export default {
|
||||
const text = await this.callVoiceRecognitionAPI(blob)
|
||||
if (text) {
|
||||
this.newMessage = text
|
||||
// this.messageStatus = 'stop'
|
||||
this.$emit('update:messageStatus', 'stop')
|
||||
// this.sendMessage()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('语音识别失败:', error)
|
||||
@@ -223,11 +219,9 @@ export default {
|
||||
conversationId: this.conversationId,
|
||||
productName: this.productName,
|
||||
}
|
||||
|
||||
if (this.$route.query.compareId) {
|
||||
params.compareResult = JSON.parse(sessionStorage.getItem('results'))
|
||||
}
|
||||
|
||||
fetch(chat(), {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
@@ -272,7 +266,6 @@ export default {
|
||||
const cleanLine = line.replace(/^data:\s*/, '')
|
||||
if (!cleanLine) return null
|
||||
const data = JSON.parse(cleanLine)
|
||||
// console.log(data)
|
||||
if (data.answer) {
|
||||
this.answerMap += data.answer
|
||||
}
|
||||
@@ -284,52 +277,62 @@ export default {
|
||||
}
|
||||
},
|
||||
updateConversationState(data) {
|
||||
// this.conversationId =
|
||||
this.$emit('update:conversationId', data.conversation_id || conversationId.value)
|
||||
this.$emit('update:conversationId', data.conversation_id || '')
|
||||
if (data.answer && data.answer.indexOf('<think>') !== -1) {
|
||||
this.isThink = true
|
||||
this.$emit('getIsThink', true)
|
||||
}
|
||||
|
||||
if (data.answer && data.answer.indexOf('</think>') !== -1) {
|
||||
this.isThink = false
|
||||
this.$emit('getIsThink', false)
|
||||
// this.$emit('update:isThink', false)
|
||||
}
|
||||
},
|
||||
updateMessageContent({ answer, event }) {
|
||||
if (event === 'message_end') {
|
||||
// this.messageStatus = 'stop'
|
||||
this.$emit('update:messageStatus', 'stop')
|
||||
}
|
||||
|
||||
// console.log(answer)
|
||||
// console.log(this.currentMessage)
|
||||
if (!this.currentMessage || !answer) return
|
||||
const mode = this.isThink ? 'think' : 'text'
|
||||
this.currentMessage[mode] += answer
|
||||
const chars = answer.split('')
|
||||
this.typingQueue.push(...chars)
|
||||
if (!this.isTyping) {
|
||||
this.startTypingAnimation(mode)
|
||||
}
|
||||
},
|
||||
startTypingAnimation(mode) {
|
||||
this.isTyping = true
|
||||
|
||||
const typeNextChar = () => {
|
||||
if (this.typingQueue.length === 0) {
|
||||
this.isTyping = false
|
||||
return
|
||||
}
|
||||
|
||||
const char = this.typingQueue.shift()
|
||||
this.currentMessage[mode] += char
|
||||
|
||||
this.typingTimeout = setTimeout(typeNextChar, this.getTypingDelay(char))
|
||||
}
|
||||
|
||||
typeNextChar()
|
||||
},
|
||||
getTypingDelay(char) {
|
||||
if (['。', '!', '?', ',', '\n'].includes(char)) {
|
||||
return this.typingSpeed * 3
|
||||
}
|
||||
return this.typingSpeed
|
||||
},
|
||||
sendMessage() {
|
||||
if (this.messageStatus === 'send') return
|
||||
if (this.newMessage.trim() === '') return
|
||||
// 防止xss
|
||||
this.newMessage = this.newMessage.replace(/<[^>]+>/g, '')
|
||||
this.messages.push({ type: 'user', text: this.newMessage })
|
||||
this.$emit('update:messageStatus', 'send')
|
||||
// this.messageStatus = 'send'
|
||||
if (this.newMessage.includes('工具箱')) {
|
||||
this.hasTreasureBox()
|
||||
return
|
||||
}
|
||||
|
||||
// if (this.newMessage.includes('产品对比')) {
|
||||
// // this.hasTreasureBox()
|
||||
// return
|
||||
// }
|
||||
|
||||
// this.autoScrollEnabled = true
|
||||
this.$emit('update:autoScrollEnabled', true)
|
||||
|
||||
this.axiosGetAiChat()
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user