95 lines
2.3 KiB
Vue
95 lines
2.3 KiB
Vue
<template>
|
||
<div class="flex flex-col w-full h-full bg-base-200 overflow-hidden">
|
||
<!-- 消息气泡列表 -->
|
||
<div ref="bubbleListRef" class="flex-1 overflow-y-auto p-4 ">
|
||
<!-- 空状态 -->
|
||
<div v-if="bubbles.length === 0" class="flex items-center justify-center h-full">
|
||
<p class="text-base-content opacity-50">暂无消息,发送第一条消息开始对话吧~</p>
|
||
</div>
|
||
|
||
<!-- 消息列表 -->
|
||
<template v-else>
|
||
<ChatBubble v-for="bubble in bubbles" :key="bubble.id" :content="bubble.content" :is-self="bubble.isSelf"
|
||
:time="bubble.time" :avatar="getAvatar(bubble.isSelf)" />
|
||
</template>
|
||
</div>
|
||
|
||
<!-- 输入框区域 -->
|
||
<ChatInput @send="handleSend" />
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, watch } from 'vue'
|
||
import ChatBubble from './ChatBubble.vue'
|
||
import ChatInput from './ChatInput.vue'
|
||
import type { ChatBubble as ChatBubbleType } from '@/composables/useChat'
|
||
|
||
const props = defineProps<{
|
||
// 消息气泡列表
|
||
bubbles: ChatBubbleType[]
|
||
}>()
|
||
|
||
const emit = defineEmits<{
|
||
send: [content: string]
|
||
}>()
|
||
|
||
const bubbleListRef = ref<HTMLDivElement | null>(null)
|
||
|
||
// 获取头像(根据是否为自己发送的消息)
|
||
const getAvatar = (isSelf: boolean): string => {
|
||
return isSelf
|
||
? 'https://api.dicebear.com/7.x/avataaars/svg?seed=User'
|
||
: 'https://api.dicebear.com/7.x/avataaars/svg?seed=Assistant'
|
||
}
|
||
|
||
// 滚动到底部
|
||
const scrollToBottom = () => {
|
||
const el = bubbleListRef.value
|
||
if (el) {
|
||
// 使用平滑滚动
|
||
el.scrollTo({
|
||
top: el.scrollHeight,
|
||
behavior: 'smooth'
|
||
})
|
||
}
|
||
}
|
||
|
||
// 监听消息变化,自动滚动到底部
|
||
watch(
|
||
() => props.bubbles.length,
|
||
() => {
|
||
// 下一帧滚动,确保 DOM 已更新
|
||
setTimeout(() => {
|
||
scrollToBottom()
|
||
}, 0)
|
||
},
|
||
{ immediate: true }
|
||
)
|
||
|
||
// 处理发送消息
|
||
const handleSend = (content: string) => {
|
||
emit('send', content)
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 自定义滚动条样式 */
|
||
.overflow-y-auto::-webkit-scrollbar {
|
||
width: 6px;
|
||
}
|
||
|
||
.overflow-y-auto::-webkit-scrollbar-track {
|
||
background: #f1f1f1;
|
||
}
|
||
|
||
.overflow-y-auto::-webkit-scrollbar-thumb {
|
||
background: #c1c1c1;
|
||
border-radius: 3px;
|
||
}
|
||
|
||
.overflow-y-auto::-webkit-scrollbar-thumb:hover {
|
||
background: #a8a8a8;
|
||
}
|
||
</style>
|