Files
ebiz-base-ai/src/views/AI/components/message.vue
陈昱达 84ea21ea1d feat(AI): 优化消息组件和语音输入功能
- 修改消息组件,仅在非思考模式下显示消息文本
- 增加语音模式下的文本输入框- 优化语音录音和识别逻辑
- 更新思考模式的处理流程
- 调整界面样式,增加禁用状态的录音按钮
2025-06-10 13:30:05 +08:00

229 lines
5.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<section>
<div v-for="(message, index) in messagesList" :key="index" class="message-item ">
<!--用户消息-->
<div v-if="message.type === 'user'" class="user-message mb10">
<p>{{ message.text }}</p>
</div>
<!--机器人消息-->
<div v-else-if="message.type === 'bot'" class="bot-message mb10">
<span v-if="message.isThink">
<!-- loading-->
<span class="speakLoadingToast pv10">
<van-loading type="spinner" color="#2e5ca9" 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" />
</span>
<!--开启思考-->
<p v-html="md.render(message.think)" v-if="message.think && message.showThink" class="thinkText" />
</span>
<div v-if='!message.isThink '>
<p v-html="md.render(message.text)" v-if="message.text "></p>
<span class="speakLoadingToast pv10" v-else-if='!message.text && !thinkOk'>
<van-loading type="spinner" color="#2e5ca9" size="20px" v-if="!message.text" />
</span>
</div>
</div>
<!--百宝箱-->
<div v-else class='mb10'>
<treasure-box :item="message" @setProductName='setProductName'></treasure-box>
</div>
<!-- 新增点赞和踩按钮 -->
<div class="reaction-buttons mb10" v-if="message.type !== 'user'">
<button @click="handleReaction(message, 'like')" class="like">
<svg-icon :icon-class="message.isLike ? 'fillLike' : 'like'" class-name="chat-icon"></svg-icon> 有用
</button>
<button @click="handleReaction(message, 'dislike')" class="dislike">
<svg-icon :icon-class="message.isDisLike ? 'fillDislike' : 'dislike'" style="width: 15px; height: 15px"></svg-icon>无用
</button>
</div>
</div>
</section>
</template>
<script>
// icon
import { Icon } from 'vant'
import TreasureBox from '@/views/AI/components/treasureBox.vue'
import MarkdownIt from 'markdown-it'
import markdownItKatex from 'markdown-it-katex'
const md = new MarkdownIt({
html: true,
linkify: true,
typographer: true,
})
.use(markdownItKatex)
export default {
name: 'message',
components: { TreasureBox, [Icon.name]: Icon },
props: {
messagesList: {
type: Array,
default: () => [],
},
thinkOk: {
type: Boolean,
default: false,
},
isDeep: {
type: Boolean,
default: false,
},
},
data() {
return {
md,
}
},
methods: {
setProductName(e){
this.$emit('setProductName',e)
},
showThink(message) {
this.$set(message, 'showThink', !message.showThink)
console.log(message.showThink)
},
// 处理点赞和踩的逻辑
handleReaction(message, type) {
if (type === 'like') {
this.$set(message, 'isLike', !message.isLike)
this.$set(message, 'isDisLike', false)
} else if (type === 'dislike') {
this.$set(message, 'isDisLike', !message.isDisLike)
this.$set(message, 'isLike', false)
}
// 触发父组件的更新事件
this.$emit('update-message', { ...message })
},
},
}
</script>
<style scoped lang="scss">
// 主题颜色定义
$primary-color: #2e5ca9; // 修复了 SCSS 变量的定义方式
$primary-text-color: #f6aa21; // 修复了 SCSS 变量的定义方式
$primary-trans-color: rgba(135, 162, 208, 0.5); // 使用rgba定义颜色透明度为0.8
.message-item {
all: initial;
margin-bottom: 10px;
width: 100%;
font-size: unset;
.user-message,
.bot-message {
display: flex;
align-items: center;
img {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
}
p {
background-color: $primary-color;
color: #fff;
padding: 10px;
border-radius: 5px;
//max-width: 70%;
//max-width: 80%;
}
}
.user-message {
justify-content: end;
max-width: 80%;
margin-left: 20%;
}
.bot-message {
justify-content: start;
background-color: #fff;
border-radius: 5px;
max-width: calc(80% + 20px);
display: flex;
flex-wrap: wrap;
.bot-avatar {
margin-left: 10px;
margin-right: 0;
}
.thinkText {
color: $primary-trans-color;
padding-top: 0;
}
.speakLoadingToast {
display: flex;
align-items: center;
gap: 10px;
color: $primary-text-color;
margin-left: 10px;
.loading-text {
color: $primary-trans-color;
}
}
p {
background-color: #fff;
color: $primary-color;
}
}
// 新增样式:点赞和踩按钮
.reaction-buttons {
display: flex;
gap: 10px;
margin-top: 5px;
button {
display: flex;
align-items: center;
background: #fff;
border: none;
cursor: pointer;
font-size: 11px;
padding: 2px 3px;
border-radius: 5px;
color: $primary-color;
}
.dislike {
color: $primary-text-color;
}
}
}
.rate360 {
animation-duration: 0.5s;
animation-fill-mode: both;
animation-name: rate360;
}
.rate180 {
animation-duration: 0.5s;
animation-fill-mode: both;
animation-name: rate180;
}
@keyframes rate360 {
0% {
transform: rotate(180deg);
}
100% {
transform: rotate(0deg);
}
}
@keyframes rate180 {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(180deg);
}
}
</style>