mirror of
http://112.124.100.131/ebiz-ai/ebiz-base-ai.git
synced 2025-12-07 01:46:48 +08:00
feat: 新增AI聊天界面及消息组件,支持语音输入和markdown渲染
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
.card {
|
||||
border-radius: 5px;
|
||||
margin: 10px 0;
|
||||
padding: 5px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 5%;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, .05);
|
||||
}
|
||||
|
||||
.card > div {
|
||||
@@ -30,15 +33,21 @@
|
||||
}
|
||||
|
||||
.card > section > :nth-child(2) > div {
|
||||
font-size: 12px;
|
||||
background-color: #0065ff;
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
padding: 0px 3px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* 选择遇到的第一个 div */
|
||||
.render-container > div:nth-of-type(1) > img {
|
||||
width: 100%;
|
||||
background-color: red;
|
||||
/* background-color: red; */
|
||||
}
|
||||
|
||||
.render-container > ul {
|
||||
/* background-color: red; */
|
||||
list-style: none !important;
|
||||
}
|
||||
|
||||
.render-container > div {
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
:class="{ disabled: messageStatus === 'send' }" class="ml10 active send">
|
||||
发送
|
||||
</button>
|
||||
<!-- <button @click="cancelSend">取消</button> -->
|
||||
</div>
|
||||
<!-- 语音按钮:按住说话 -->
|
||||
<button @click="isVoiceMode = !isVoiceMode" class="mic-button ml10 mr10" v-if="false">
|
||||
@@ -218,7 +219,7 @@ export default {
|
||||
|
||||
// 重置 answerMap
|
||||
this.answerMap = ''
|
||||
|
||||
this.typingQueue = []
|
||||
this.currentMessage = JSON.parse(JSON.stringify(this.messageInfo))
|
||||
let params = {
|
||||
appType: "gwcsHelper",
|
||||
@@ -241,7 +242,6 @@ export default {
|
||||
|
||||
if (this.single) {
|
||||
// this.messages[this.messages.length - 1]
|
||||
|
||||
this.messages.splice(this.messages.length - 1, 1, this.currentMessage)
|
||||
} else {
|
||||
this.messages.push(this.currentMessage)
|
||||
@@ -301,6 +301,7 @@ export default {
|
||||
},
|
||||
parseStreamLine(line) {
|
||||
try {
|
||||
|
||||
const cleanLine = line.replace(/^data:\s*/, '')
|
||||
if (!cleanLine) return null
|
||||
const data = JSON.parse(cleanLine)
|
||||
@@ -373,6 +374,7 @@ export default {
|
||||
answer: answer,
|
||||
isThink: isThink,
|
||||
}
|
||||
// debugger
|
||||
this.typingQueue.push(chars)
|
||||
if (!this.isTyping) {
|
||||
this.startTypingAnimation(mode)
|
||||
@@ -401,7 +403,6 @@ export default {
|
||||
return
|
||||
}
|
||||
const char = chars.shift() || ''
|
||||
// if (this.single)
|
||||
this.$set(this.currentMessage, isThink ? 'think' : 'text', this.currentMessage[isThink ? 'think' : 'text'] + char)
|
||||
const delay = this.getTypingDelay(char)
|
||||
setTimeout(outputChar, delay)
|
||||
@@ -435,6 +436,10 @@ export default {
|
||||
this.$emit('update:autoScrollEnabled', true)
|
||||
this.axiosGetAiChat()
|
||||
},
|
||||
|
||||
cancelSend() {
|
||||
this.requestSingle.abort()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<section>
|
||||
<!-- {{ messagesList }} -->
|
||||
{{ messagesList }}
|
||||
<div v-for="(message, index) in messagesList" :key="index" class="message-item">
|
||||
<!-- {{ message }} -->
|
||||
<!--用户消息-->
|
||||
@@ -14,7 +14,8 @@
|
||||
<span class="speakLoadingToast pv10">
|
||||
<van-loading type="spinner" :color="primaryColor" size="20px" v-if="!message.text" />
|
||||
<span class="loading-text">{{ message.text ? '思考完成' : '思考中...' }}</span>
|
||||
<van-icon name="arrow-up" :class="message.showThink ? 'rate360' : 'rate180'" @click="showThink(message)" v-if="message.think" />
|
||||
<van-icon name="arrow-up" :class="message.showThink ? 'rate360' : 'rate180'" @click="showThink(message)"
|
||||
v-if="message.think" />
|
||||
</span>
|
||||
<!--开启思考-->
|
||||
<p v-html="md.render(message.think)" v-if="message.think && message.showThink" class="thinkText" />
|
||||
@@ -90,13 +91,15 @@ export default {
|
||||
if (new RegExp('^[\u4e00-\u9fa5]+', 'g').test(text)) return text
|
||||
|
||||
// 捕获 不包含 < 的后置标签 span> /span> a</span>
|
||||
text = text.replace(/^[\/]?[a-zA-z0-9]+[</\w>]+/g, '')
|
||||
text = text.replace(/^[/]?[a-zA-z0-9]+[</\w>]+/g, '')
|
||||
// 尝试匹配 </abc> 标签
|
||||
text = text.replace(/^<\/\w+>/g, '')
|
||||
text = text.replace(/^<\w+>/g, '')
|
||||
// 尝试把 </ 标签去除
|
||||
text = text.replace(/[<\/]+$/g, '')
|
||||
console.log(text);
|
||||
|
||||
// text = text.replace(/[</]+$/g, '')
|
||||
text = text.replace(/<[^>]*>/g, '')
|
||||
// console.log(text);
|
||||
|
||||
|
||||
return text
|
||||
}
|
||||
// 只把 text 标签内容渲染
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
:is-search="isSearching"
|
||||
:think-ok="isThink"
|
||||
@setProductName="setProductName"
|
||||
@reload-message="reloadMessage"
|
||||
v-if="messages.length > 1"
|
||||
></messageComponent>
|
||||
<div class="mb20" v-else>
|
||||
@@ -137,6 +138,9 @@ export default {
|
||||
},
|
||||
initBotMessage() {
|
||||
this.messages = []
|
||||
},
|
||||
reloadMessage({message,index}){
|
||||
this.$refs.chatMessage.reloadMessage({message,index})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
Reference in New Issue
Block a user