|
@@ -0,0 +1,189 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="flex h-screen">
|
|
|
|
+ <!-- Left Sidebar -->
|
|
|
|
+ <div class="w-64 bg-[#08002E] text-white flex flex-col">
|
|
|
|
+ <!-- Title -->
|
|
|
|
+ <div class="p-4 flex items-center justify-center bg-[#4B0082]">
|
|
|
|
+ <span class="font-bold text-xl">聊天应用</span>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- Navigation -->
|
|
|
|
+ <nav class="flex-1 p-4">
|
|
|
|
+ <div class="space-y-2">
|
|
|
|
+ <div class="mt-6">
|
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
|
+ <span class="text-sm text-gray-400">历史聊天</span>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- Chat Sessions -->
|
|
|
|
+ <div class="mt-3 space-y-2">
|
|
|
|
+ <div v-for="(session, index) in chatSessions" :key="index"
|
|
|
|
+ class="flex items-center justify-between text-sm text-gray-300 hover:text-white group">
|
|
|
|
+ <div class="flex items-center space-x-2">
|
|
|
|
+ <span>{{ session.user }}</span>
|
|
|
|
+ <span class="text-xs text-gray-500">{{ session.timestamp }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </nav>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- Main Content -->
|
|
|
|
+ <div class="flex-1 flex flex-col bg-gradient-to-b from-white to-[#800080]">
|
|
|
|
+ <!-- Chat Area -->
|
|
|
|
+ <div class="flex-1 overflow-auto p-6">
|
|
|
|
+ <div class="max-w-4xl mx-auto space-y-6">
|
|
|
|
+ <!-- Chat Messages -->
|
|
|
|
+ <div v-for="(message, index) in messages" :key="index"
|
|
|
|
+ class="bg-white rounded-lg p-4 shadow-sm"
|
|
|
|
+ :class="{ 'bg-violet-100': message.sender === 'user' }">
|
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
|
+ <span class="text-sm font-medium">{{ message.sender }}</span>
|
|
|
|
+ <span class="text-xs text-gray-500">{{ message.timestamp }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="mt-2 text-gray-600">
|
|
|
|
+ {{ message.text }}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- Input Area -->
|
|
|
|
+ <div class="border-t p-4 bg-white">
|
|
|
|
+ <div class="max-w-4xl mx-auto">
|
|
|
|
+ <div class="flex items-center space-x-2 mb-2">
|
|
|
|
+ <div class="bg-gray-100 rounded-full px-3 py-1 text-sm flex items-center space-x-1 relative">
|
|
|
|
+ <span>User Story Agent</span>
|
|
|
|
+ <button @click="toggleAgentSelection" class="text-gray-500 hover:text-gray-700">
|
|
|
|
+ <ChevronDown class="w-3 h-3" />
|
|
|
|
+ </button>
|
|
|
|
+ <div v-if="showAgentSelection" class="absolute bg-white border rounded mt-1 z-10">
|
|
|
|
+ <div v-for="(agent, index) in agents" :key="index" class="px-3 py-2 hover:bg-gray-100 cursor-pointer">
|
|
|
|
+ {{ agent }}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex items-end space-x-2">
|
|
|
|
+ <textarea
|
|
|
|
+ v-model="inputMessage"
|
|
|
|
+ class="flex-1 border rounded-lg p-3 resize-none focus:outline-none focus:ring-2 focus:ring-purple-500"
|
|
|
|
+ placeholder="输入消息..."
|
|
|
|
+ rows="1"
|
|
|
|
+ ></textarea>
|
|
|
|
+ <button @click="sendMessage" class="p-2 bg-purple-500 text-white rounded-lg hover:bg-purple-600">
|
|
|
|
+ <Send class="w-5 h-5" />
|
|
|
|
+ </button>
|
|
|
|
+ <button @click="uploadFile" class="p-2 bg-gray-300 text-white rounded-full hover:bg-gray-400">
|
|
|
|
+ <UploadIcon class="w-5 h-5" />
|
|
|
|
+ </button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- Right Panel -->
|
|
|
|
+ <div class="w-80 border-l p-4 bg-white">
|
|
|
|
+ <div class="space-y-4">
|
|
|
|
+ <h3 class="text-lg font-medium">上传的文档</h3>
|
|
|
|
+ <div class="space-y-2">
|
|
|
|
+ <div v-for="(file, index) in uploadedFiles" :key="index"
|
|
|
|
+ class="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
|
|
|
|
+ <div class="flex-1">
|
|
|
|
+ <div class="text-sm font-medium truncate">{{ file.name }}</div>
|
|
|
|
+ <div class="text-xs text-gray-500">{{ file.size }} KB, {{ file.uploadTime }}</div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="flex space-x-2">
|
|
|
|
+ <button @click="previewFile(file)" class="text-gray-400 hover:text-gray-600 cursor-pointer">
|
|
|
|
+ <Eye class="w-4 h-4" />
|
|
|
|
+ </button>
|
|
|
|
+ <button @click="downloadFile(file)" class="text-gray-400 hover:text-gray-600 cursor-pointer">
|
|
|
|
+ <Download class="w-4 h-4" />
|
|
|
|
+ </button>
|
|
|
|
+ <button @click="deleteFile(file)" class="text-red-500 hover:text-red-600 cursor-pointer">
|
|
|
|
+ <Trash2 class="w-4 h-4" />
|
|
|
|
+ </button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="mt-4">
|
|
|
|
+ <button @click="uploadFile" class="w-full bg-purple-500 text-white rounded-lg py-2 hover:bg-purple-600">
|
|
|
|
+ 上传文档
|
|
|
|
+ </button>
|
|
|
|
+ <input type="file" ref="fileInput" @change="handleFileUpload" class="hidden" />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script setup>
|
|
|
|
+import { ref } from 'vue'
|
|
|
|
+import {
|
|
|
|
+ ChevronDown,
|
|
|
|
+ Send,
|
|
|
|
+ UploadIcon,
|
|
|
|
+ Eye,
|
|
|
|
+ Download,
|
|
|
|
+ Trash2
|
|
|
|
+} from 'lucide-vue-next'
|
|
|
|
+
|
|
|
|
+const chatSessions = ref([
|
|
|
|
+ { user: 'Alice', timestamp: '10:00 AM' },
|
|
|
|
+ { user: 'Bob', timestamp: '11:30 AM' }
|
|
|
|
+])
|
|
|
|
+
|
|
|
|
+const messages = ref([
|
|
|
|
+ { sender: 'user', text: '你好,有什么我可以帮忙的吗?', timestamp: '10:01 AM' },
|
|
|
|
+ { sender: 'agent', text: '当然可以!请告诉我你需要什么帮助。', timestamp: '10:02 AM' }
|
|
|
|
+])
|
|
|
|
+
|
|
|
|
+const inputMessage = ref('')
|
|
|
|
+const uploadedFiles = ref([])
|
|
|
|
+const showAgentSelection = ref(false)
|
|
|
|
+const agents = ref(['Agent 1', 'Agent 2', 'Agent 3'])
|
|
|
|
+
|
|
|
|
+const sendMessage = () => {
|
|
|
|
+ if (inputMessage.value.trim()) {
|
|
|
|
+ messages.value.push({ sender: 'user', text: inputMessage.value, timestamp: new Date().toLocaleTimeString() })
|
|
|
|
+ inputMessage.value = ''
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const toggleAgentSelection = () => {
|
|
|
|
+ showAgentSelection.value = !showAgentSelection.value
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const uploadFile = () => {
|
|
|
|
+ fileInput.value.click()
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const handleFileUpload = (event) => {
|
|
|
|
+ const file = event.target.files[0]
|
|
|
|
+ if (file) {
|
|
|
|
+ uploadedFiles.value.push({
|
|
|
|
+ name: file.name,
|
|
|
|
+ size: (file.size / 1024).toFixed(2),
|
|
|
|
+ uploadTime: new Date().toLocaleTimeString()
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const previewFile = (file) => {
|
|
|
|
+ alert(`预览 ${file.name}`)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const downloadFile = (file) => {
|
|
|
|
+ alert(`下载 ${file.name}`)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const deleteFile = (file) => {
|
|
|
|
+ uploadedFiles.value = uploadedFiles.value.filter(f => f.name !== file.name)
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style scoped>
|
|
|
|
+/* Add any custom styles here if needed */
|
|
|
|
+</style>
|