blob: 979dcc0bc07777b1f54e29a2384b6efc38839bbc [file] [log] [blame]
208159515458d95702025-06-09 14:46:58 +08001<template>
vulgar5201c4345b12025-06-09 18:48:06 +08002 <Navbar />
208159515458d95702025-06-09 14:46:58 +08003 <div class="chat-room">
4 <h2>聊天室</h2>
5 <div class="chat-messages" ref="messagesRef">
6 <div v-for="(msg, idx) in messages" :key="idx" class="chat-message">
7 <span class="chat-user">{{ msg.username || '匿名' }}:</span>
8 <span class="chat-content">{{ msg.content }}</span>
9 <span class="chat-time" v-if="msg.timestamp">({{ formatTime(msg.timestamp) }})</span>
10 </div>
11 </div>
12 <div class="chat-input">
13 <el-input v-model="input" placeholder="输入消息..." @keyup.enter="sendMessage" />
14 <el-button type="primary" @click="sendMessage">发送</el-button>
15 </div>
16 </div>
17</template>
18
19<script setup>
20import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
21import { useStore } from 'vuex'
22import axios from 'axios'
vulgar5201c4345b12025-06-09 18:48:06 +080023import Navbar from '@/components/Navbar.vue';
24
25
208159515458d95702025-06-09 14:46:58 +080026
27const store = useStore()
28const wsUrl = 'ws://localhost:8081/api/ws/chat'
29const ws = ref(null)
30const messages = ref([])
31const input = ref('')
32const messagesRef = ref(null)
33
34function getToken() {
35 return localStorage.getItem('token')
36}
37
38function setCookie(name, value, days = 7) {
39 const expires = new Date()
40 expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000))
41 document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`
42}
43
44// 获取聊天历史记录
45async function loadChatHistory() {
46 try {
47 const token = getToken()
48 if (!token) return
49
50 console.log('🔄 获取聊天历史记录...')
51 const response = await axios.get('http://localhost:8081/api/chat/history', {
52 params: { roomId: 1 },
53 headers: { 'sapling-token': token }
54 })
55
56 if (response.data && Array.isArray(response.data)) {
57 messages.value = response.data
58 console.log('📚 获取到', response.data.length, '条历史消息')
59
60 // 滚动到底部
61 nextTick(() => {
62 if (messagesRef.value) {
63 messagesRef.value.scrollTop = messagesRef.value.scrollHeight
64 }
65 })
66 }
67 } catch (error) {
68 console.error('❌ 获取聊天历史失败:', error)
69 }
70}
71
72function connect() {
73 const token = getToken()
74 if (!token) {
75 console.error('无法连接WebSocket:未找到token')
76 return
77 }
78
79 // 设置cookie,这样WebSocket握手时后端可以从cookie获取token
80 setCookie('sapling-token', token)
81
82 console.log('尝试连接WebSocket:', wsUrl)
83 console.log('已设置cookie: sapling-token =', token)
84
85 ws.value = new WebSocket(wsUrl)
86
87 ws.value.onopen = async () => {
88 console.log('✅ WebSocket连接成功')
89 // 连接成功后立即获取聊天历史
90 await loadChatHistory()
91 }
92
93 ws.value.onmessage = (event) => {
94 console.log('📥 收到消息:', event.data)
95 try {
96 const msg = JSON.parse(event.data)
97 console.log('📥 解析后的消息:', msg)
98 messages.value.push(msg)
99 nextTick(() => {
100 if (messagesRef.value) {
101 messagesRef.value.scrollTop = messagesRef.value.scrollHeight
102 }
103 })
104 } catch (e) {
105 console.error('❌ 消息解析失败:', e, event.data)
106 }
107 }
108
109 ws.value.onerror = (err) => {
110 console.error('❌ WebSocket错误:', err)
111 }
112
113 ws.value.onclose = (event) => {
114 console.log('❌ WebSocket已断开, 代码:', event.code, '原因:', event.reason)
115 setTimeout(() => {
116 console.log('🔄 尝试重连...')
117 connect()
118 }, 2000)
119 }
120}
121
122function sendMessage() {
123 if (!input.value.trim()) return
124
125 if (!ws.value || ws.value.readyState !== WebSocket.OPEN) {
126 console.error('❌ WebSocket未连接')
127 return
128 }
129
130 const message = {
131 roomId: 1, // 默认房间ID为1
132 content: input.value.trim()
133 }
134
135 console.log('📤 发送消息:', message)
136 ws.value.send(JSON.stringify(message))
137 input.value = ''
138}
139
140function formatTime(timestamp) {
141 return new Date(timestamp).toLocaleTimeString()
142}
143
144onMounted(() => {
145 console.log('🚀 聊天室组件已挂载')
146 connect()
147})
148
149onBeforeUnmount(() => {
150 console.log('🔌 组件卸载,关闭WebSocket连接')
151 if (ws.value) {
152 ws.value.close()
153 }
154})
155</script>
156
157<style scoped>
158.chat-room {
159 max-width: 600px;
160 margin: 40px auto;
161 border: 1px solid #eee;
162 border-radius: 8px;
163 padding: 24px;
164 background: #fff;
165}
166.chat-messages {
167 height: 320px;
168 overflow-y: auto;
169 border: 1px solid #f0f0f0;
170 border-radius: 4px;
171 padding: 12px;
172 margin-bottom: 16px;
173 background: #fafbfc;
174}
175.chat-message {
176 margin-bottom: 8px;
177}
178.chat-user {
179 font-weight: bold;
180 color: #409eff;
181}
182.chat-time {
183 color: #999;
184 font-size: 12px;
185 margin-left: 8px;
186}
187.chat-input {
188 display: flex;
189 gap: 8px;
190}
191</style>