feat: AI对话

This commit is contained in:
zhangyh
2025-10-28 11:33:20 +08:00
parent 2a1023aea0
commit 0ce0c41dac
12 changed files with 358 additions and 111 deletions

View File

@@ -1,17 +1,15 @@
<template>
<div
class="chat-message"
:class="{ 'user-message': isMyself, 'ai-message': !isMyself }"
>
<div class="chat-message" :class="{ 'user-message': isMyself, 'ai-message': !isMyself }">
<!-- AI消息显示头像 -->
<div v-if="!isMyself" class="chat-avatar">
<img :src="value.thumb" alt="AI Avatar" />
<img src="@/assets/images/asistant.png" alt="AI Avatar" />
</div>
<!-- 消息内容 -->
<div class="message-content">
<div class="message-text">
{{ value.content }}
<div class="message-text" :class="{ streaming: isStreaming }">
<div v-html="content"></div>
<span v-if="isStreaming" class="streaming-cursor">|</span>
</div>
<!-- <div v-if="!isMyself" class="message-actions flex">
<SvgIcon
@@ -28,13 +26,18 @@
<script setup lang="ts">
import { computed } from 'vue'
import MarkdownIt from 'markdown-it'
const md = new MarkdownIt()
// 定义消息类型
interface ChatMessage {
id: string
sessionId: string | number
type: string
content: string
userId: string
time: string
thumb: string
timestamp: string
id?: string
self?: boolean
}
// 定义操作项类型
@@ -46,12 +49,17 @@ interface ActionItem {
// 定义组件props类型
interface NoticeItemProps {
value: ChatMessage
isStreaming?: boolean
}
const props = defineProps<NoticeItemProps>()
const isMyself = computed(()=>{
return props.value.userId === '1'
const isMyself = computed(() => {
return props.value.self || false
})
const content = computed(() => {
return md.render(props.value.content)
})
const handleClickAction = (value: string): void => {
@@ -117,6 +125,7 @@ const actionList: ActionItem[] = [
.message-text {
color: #000;
border-radius: 0 2rem 2rem 2rem;
word-break: break-word;
}
}
}
@@ -127,12 +136,14 @@ const actionList: ActionItem[] = [
height: 7.4rem;
border-radius: 50%;
margin-right: 1.88rem;
border: 2px solid #000;
padding: 1.4rem;
img {
width: 100%;
height: 100%;
width: 4.9rem;
height: 4.9rem;
border-radius: 50%;
object-fit: cover;
// object-fit: cover;
}
}
@@ -150,4 +161,21 @@ const actionList: ActionItem[] = [
cursor: pointer;
}
}
.streaming-cursor {
animation: blink 1s infinite;
font-weight: bold;
color: #000;
}
@keyframes blink {
0%,
50% {
opacity: 1;
}
51%,
100% {
opacity: 0;
}
}
</style>