论坛,聊天室前后端对接
Change-Id: I90740329ab40dc050e8a791a382ab187900d673a
diff --git a/src/views/ChatRoom.vue b/src/views/ChatRoom.vue
new file mode 100644
index 0000000..ad63f9d
--- /dev/null
+++ b/src/views/ChatRoom.vue
@@ -0,0 +1,187 @@
+<template>
+ <div class="chat-room">
+ <h2>聊天室</h2>
+ <div class="chat-messages" ref="messagesRef">
+ <div v-for="(msg, idx) in messages" :key="idx" class="chat-message">
+ <span class="chat-user">{{ msg.username || '匿名' }}:</span>
+ <span class="chat-content">{{ msg.content }}</span>
+ <span class="chat-time" v-if="msg.timestamp">({{ formatTime(msg.timestamp) }})</span>
+ </div>
+ </div>
+ <div class="chat-input">
+ <el-input v-model="input" placeholder="输入消息..." @keyup.enter="sendMessage" />
+ <el-button type="primary" @click="sendMessage">发送</el-button>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { useStore } from 'vuex'
+import axios from 'axios'
+
+const store = useStore()
+const wsUrl = 'ws://localhost:8081/api/ws/chat'
+const ws = ref(null)
+const messages = ref([])
+const input = ref('')
+const messagesRef = ref(null)
+
+function getToken() {
+ return localStorage.getItem('token')
+}
+
+function setCookie(name, value, days = 7) {
+ const expires = new Date()
+ expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000))
+ document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`
+}
+
+// 获取聊天历史记录
+async function loadChatHistory() {
+ try {
+ const token = getToken()
+ if (!token) return
+
+ console.log('🔄 获取聊天历史记录...')
+ const response = await axios.get('http://localhost:8081/api/chat/history', {
+ params: { roomId: 1 },
+ headers: { 'sapling-token': token }
+ })
+
+ if (response.data && Array.isArray(response.data)) {
+ messages.value = response.data
+ console.log('📚 获取到', response.data.length, '条历史消息')
+
+ // 滚动到底部
+ nextTick(() => {
+ if (messagesRef.value) {
+ messagesRef.value.scrollTop = messagesRef.value.scrollHeight
+ }
+ })
+ }
+ } catch (error) {
+ console.error('❌ 获取聊天历史失败:', error)
+ }
+}
+
+function connect() {
+ const token = getToken()
+ if (!token) {
+ console.error('无法连接WebSocket:未找到token')
+ return
+ }
+
+ // 设置cookie,这样WebSocket握手时后端可以从cookie获取token
+ setCookie('sapling-token', token)
+
+ console.log('尝试连接WebSocket:', wsUrl)
+ console.log('已设置cookie: sapling-token =', token)
+
+ ws.value = new WebSocket(wsUrl)
+
+ ws.value.onopen = async () => {
+ console.log('✅ WebSocket连接成功')
+ // 连接成功后立即获取聊天历史
+ await loadChatHistory()
+ }
+
+ ws.value.onmessage = (event) => {
+ console.log('📥 收到消息:', event.data)
+ try {
+ const msg = JSON.parse(event.data)
+ console.log('📥 解析后的消息:', msg)
+ messages.value.push(msg)
+ nextTick(() => {
+ if (messagesRef.value) {
+ messagesRef.value.scrollTop = messagesRef.value.scrollHeight
+ }
+ })
+ } catch (e) {
+ console.error('❌ 消息解析失败:', e, event.data)
+ }
+ }
+
+ ws.value.onerror = (err) => {
+ console.error('❌ WebSocket错误:', err)
+ }
+
+ ws.value.onclose = (event) => {
+ console.log('❌ WebSocket已断开, 代码:', event.code, '原因:', event.reason)
+ setTimeout(() => {
+ console.log('🔄 尝试重连...')
+ connect()
+ }, 2000)
+ }
+}
+
+function sendMessage() {
+ if (!input.value.trim()) return
+
+ if (!ws.value || ws.value.readyState !== WebSocket.OPEN) {
+ console.error('❌ WebSocket未连接')
+ return
+ }
+
+ const message = {
+ roomId: 1, // 默认房间ID为1
+ content: input.value.trim()
+ }
+
+ console.log('📤 发送消息:', message)
+ ws.value.send(JSON.stringify(message))
+ input.value = ''
+}
+
+function formatTime(timestamp) {
+ return new Date(timestamp).toLocaleTimeString()
+}
+
+onMounted(() => {
+ console.log('🚀 聊天室组件已挂载')
+ connect()
+})
+
+onBeforeUnmount(() => {
+ console.log('🔌 组件卸载,关闭WebSocket连接')
+ if (ws.value) {
+ ws.value.close()
+ }
+})
+</script>
+
+<style scoped>
+.chat-room {
+ max-width: 600px;
+ margin: 40px auto;
+ border: 1px solid #eee;
+ border-radius: 8px;
+ padding: 24px;
+ background: #fff;
+}
+.chat-messages {
+ height: 320px;
+ overflow-y: auto;
+ border: 1px solid #f0f0f0;
+ border-radius: 4px;
+ padding: 12px;
+ margin-bottom: 16px;
+ background: #fafbfc;
+}
+.chat-message {
+ margin-bottom: 8px;
+}
+.chat-user {
+ font-weight: bold;
+ color: #409eff;
+}
+.chat-time {
+ color: #999;
+ font-size: 12px;
+ margin-left: 8px;
+}
+.chat-input {
+ display: flex;
+ gap: 8px;
+}
+</style>
\ No newline at end of file