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