WebAgent/src/pages/llm-chat/index.vue

154 lines
3.6 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import type { ChatMessage } from '@/types/chat'
import { useScroll } from '@vueuse/core'
import { isDark, toggleDark } from '@/composables/dark'
const { t } = useI18n()
// Sample chat data for demonstration
const messages = ref<ChatMessage[]>([
{
id: 1,
content: 'Hello! I\'m your AI assistant. How can I help you today?',
sender: 'ai',
timestamp: new Date('2025-12-17T10:00:00'),
status: 'sent',
},
{
id: 2,
content: 'Can you explain how to use Vue 3 with TypeScript?',
sender: 'user',
timestamp: new Date('2025-12-17T10:01:00'),
status: 'sent',
},
{
id: 3,
content: 'Vue 3 with TypeScript provides excellent type safety and developer experience. You can use the Composition API with typed refs and reactive objects.',
sender: 'ai',
timestamp: new Date('2025-12-17T10:02:00'),
status: 'sent',
},
])
const inputText = ref('')
const isLoading = ref(false)
const messagesContainer = ref<HTMLElement>()
const { arrivedState } = useScroll(messagesContainer, {
offset: { bottom: 100 },
})
// Auto-scroll to bottom when new messages arrive
watch(messages, () => {
nextTick(() => {
if (messagesContainer.value && arrivedState.bottom) {
messagesContainer.value.scrollTop = messagesContainer.value.scrollHeight
}
})
}, { deep: true })
function handleSend(text: string) {
if (!text.trim()) return
// Add user message
const userMessage: ChatMessage = {
id: Date.now(),
content: text,
sender: 'user',
timestamp: new Date(),
status: 'sending',
}
messages.value.push(userMessage)
// Clear input
inputText.value = ''
// Simulate AI response after delay
isLoading.value = true
setTimeout(() => {
userMessage.status = 'sent'
const aiMessage: ChatMessage = {
id: Date.now() + 1,
content: `I received your message: "${text}". This is a simulated response.`,
sender: 'ai',
timestamp: new Date(),
status: 'sent',
}
messages.value.push(aiMessage)
isLoading.value = false
}, 1000)
}
function handleKeydown(e: KeyboardEvent) {
// You can add additional keyboard shortcuts here
console.log('Keydown event:', e.key)
}
</script>
<template>
<div class="h-screen flex flex-col bg-gray-50 dark:bg-gray-950">
<!-- Header -->
<van-nav-bar
:title="t('llmChat.title', 'AI Chat')"
fixed
placeholder
safe-area-inset-top
>
<template #right>
<van-icon
:name="isDark ? 'sun-o' : 'moon-o'"
class="text-lg"
@click="toggleDark()"
/>
</template>
</van-nav-bar>
<!-- Messages container -->
<van-list
ref="messagesContainer"
class="flex-1 p-4 pt-16 pb-24"
:finished="true"
:loading="false"
finished-text=""
loading-text=""
>
<van-empty
v-if="messages.length === 0"
description="No messages yet. Start a conversation!"
class="mt-20"
/>
<div v-else>
<ChatBubble
v-for="message in messages"
:key="message.id"
:message="message"
:show-timestamp="true"
/>
</div>
</van-list>
<!-- Input area -->
<div class="fixed bottom-0 left-0 right-0 z-10">
<ChatInput
v-model="inputText"
:disabled="isLoading"
:loading="isLoading"
placeholder="Type your message..."
@send="handleSend"
@keydown="handleKeydown"
/>
</div>
</div>
</template>
<route lang="json5">
{
name: 'LLMChat',
meta: {
title: 'AI Chat',
requiresAuth: false
}
}
</route>