diff --git a/server/server.js b/server/server.js index d75b597..4a74db3 100644 --- a/server/server.js +++ b/server/server.js @@ -7,7 +7,7 @@ const ws = require('ws'); const config = { rsaPrivate: crypto.createPrivateKey({ - key: Buffer.from('...generate it with key-generate.js...', 'base64'), + key: Buffer.from('MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDMqxjzmpko9umpyWFoRjP0JcdSpPBd7IJifI5VB+sNjaFqjmQCqmVTU0qn3ChyDzV7UQIVMybvlAUmEMv9n8vqDvprWxoUZ3R+Wlnarnke10ht4eaFVl3YL4IN+x++hS0uIVK8q2VvFoTSE6fely6tUU7pF7xAIHs9TtF/iN2/KXB4WNC9/vyg8b2sjW7Ok/Blh92Hbcdtgin9T882KUiMT102KvtrjN8a+gWxfOlLd4vozdmkcEbtOpRkh7EgkMf4KaelROzXePjKct8K/YGphy+s6W8aVLR8Px7EmOaiDt0JaByJY+1wjYb5LrQQ3qi4qzSWpSb2QNiW2cjBZIZpAgMBAAECggEACHpe7HpfNU/zEm4t24aq8MZe2RjNfyqEpSVBNRsAnN1czh/rWyPpUhgNa+ImB8GDBuJuamflyT9Rrke8V3t21DF+JJPPwwAdFn3SIomfKUykKq8UoDnZZdLj+YXJRRhZrINDXN7hswYVBum7BrCvBY1sbiHmUaa2zC2XZofKHbi78iAldZW/N7HxCmWv8NlxU76X6EBza6uQPwiz3aWr3lbZAE9BQVbU1T9fyW9s11auEunciP6eTrv7IYb1318SAJ5oPj2bDqMS2qr4BpdwMHw0ny6OfNJJfPlbV66J6FfM69sgxNKIgPlBW4tcYsDOXZf2+9uOLclKZJeEg9u8oQKBgQD4KDberLO+WdHs1ctgBEvQ1cdbTxcvXmlwuPo4gMOW7y6xPaC6hQil+ngnLTOTbIbWkRfYDJ0MmkUdCLmaoh6d3VecWOFny3OjpdZmlu/2DWdwLDBbBm4QrjNIEWVL682+Yx3CeiEooakD01NEVfAXWVGqvjkQRXcC1vkTcOh1UQKBgQDTIwZs9yFAW56UVlj54DGdvYq+Wcfm//yPP0tLwShZs7EnZO/a9CJ3Hx7T5wWUIYOKi5r+hLD9/HV3l/Wn8YU/nF+HvIZ6D83Wi+jbytXn15cA4v1uAQPd/JkFxoVIclbIoi8KT3NNZoyYAcpf8qUY4/mCsgPWQG7pxpTbkImZmQKBgAUhd7j04yZ9XuzBotnSXOrtcJi/suAE2LM+79V5PBID0fhSKN+SXpJn8lIFCjrzFHqdN1v9LsYS7njiNEwxK+bhq60M3WQy/aoVhLBMUJvKvSfBkiJfqKjpoR/NVEXUk0VrcTMTKVpYtVDh7qfMCxHAhAK+uhlPBl3lqfKv8+5xAoGAJBreM24DQqUoNgeaCYjcEzRhcHGb7JWj078oGhk61DQVPD5XgeKzrhklRWlBG/arLtr2s0Vvms88KypSONjlR15vO5/ygxcGxQSB2mwSLiZAzUcDvXbw+VoDtOggzKW4z3BkiOfTOM4rhqbvu36b2ujJNx9H5rB4BwQNWoqZ7SkCgYA0W1tXV92Uh+h6DEBciPChfiCjJctNpnvDUx/QZGYm5sIp6I95dF0Qu2ufQNle2zzcPz/VRnei3zkF5ZQyBcBNvd65wqGoS0bub84Qi6BXJUmIXt72HvRsRH+ztzD8gJKWBES6kS9HucdGWCmq8WOPrWBbLRmKqrLZphSqu7CgCg==', 'base64'), format: 'der', type: 'pkcs8' }), diff --git a/web/config.js b/web/config.js index cb16125..f295722 100644 --- a/web/config.js +++ b/web/config.js @@ -1,6 +1,6 @@ const config = { - rsaPublic: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsB3/iPQiU6nvQhTMfTctJb4uCazd4Vbw0pSqPa/R2wRo5i3m8qqCQa1roTJ/n3aR1wmrR4KY7ntnMVlTWza75PB2OWAY0aKWZbAj5dsrfoT6GrCo72IXQpVGCn2RerddOQs/1rART3Y0nsL3K1SnVf0yQYh3QbWqd8if0Gpa8bBaL0Of1WnXoJyUpS3p9agbXIimdP6UayNtKh/VmkztvXr+36/f4s4zZN2hhMNeRJePpQ1MtAf+oSqlyaeYiFr5w6vphkGwNRn13oqmiXzcH4t4jSxFmEPLpZozz7JyEncOU0yBTj6iyCsrIegJkabLTqJkOXn25c2QbsddPfWvcwIDAQAB', - wsAddress: 'ws://46.232.60.69:8088', + rsaPublic: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzKsY85qZKPbpqclhaEYz9CXHUqTwXeyCYnyOVQfrDY2hao5kAqplU1NKp9wocg81e1ECFTMm75QFJhDL/Z/L6g76a1saFGd0flpZ2q55HtdIbeHmhVZd2C+CDfsfvoUtLiFSvKtlbxaE0hOn3pcurVFO6Re8QCB7PU7Rf4jdvylweFjQvf78oPG9rI1uzpPwZYfdh23HbYIp/U/PNilIjE9dNir7a4zfGvoFsXzpS3eL6M3ZpHBG7TqUZIexIJDH+CmnpUTs13j4ynLfCv2BqYcvrOlvGlS0fD8exJjmog7dCWgciWPtcI2G+S60EN6ouKs0lqUm9kDYltnIwWSGaQIDAQAB', + wsAddress: 'ws://127.0.0.1:8088', debug: true }; diff --git a/web/main.js b/web/main.js index 7106b24..b57372d 100644 --- a/web/main.js +++ b/web/main.js @@ -1,5 +1,39 @@ import config from './config.js'; +// 多房间状态管理 +let roomsData = []; +let activeRoomIndex = -1; +function getNewRoomData() { + return { room: '', userList: [], userMap: {}, myId: null, myName: '', chat: null, messages: [] }; +} +// 切换房间并恢复上下文,更新 UI +function switchRoom(index) { + if (index < 0 || index >= roomsData.length) return; + activeRoomIndex = index; + const rd = roomsData[index]; + currentRoom = rd.room; + userList = rd.userList; + userMap = rd.userMap; + myId = rd.myId; + myName = rd.myName; + chat = rd.chat; + renderRooms(index); + renderMainHeader(); + renderUserList(); + renderChatArea(); +} + +// 渲染当前房间消息区 +function renderChatArea() { + const chatArea = document.getElementById('chat-area'); + if (!chatArea) return; + chatArea.innerHTML = ''; + roomsData[activeRoomIndex].messages.forEach(m => { + if (m.type === 'me') addMsg(m.text, true); + else addOtherMsg(m.text, m.name, m.avatar, true); + }); +} + // 生成简易SVG头像 function getSvgAvatar(text, size = 42) { const color = "#30a8f7"; @@ -35,9 +69,10 @@ function escapeHTML(str) { function renderUserList() { const userListEl = document.getElementById('member-list'); userListEl.innerHTML = ''; - // 不再提前 return,让 main-header 始终刷新 - let me = userList.find(u => u.clientId === myId); - let others = userList.filter(u => u.clientId !== myId); + const rd = roomsData[activeRoomIndex]; + if (!rd) return; + let me = rd.userList.find(u => u.clientId === rd.myId); + let others = rd.userList.filter(u => u.clientId !== rd.myId); if (me) userListEl.appendChild(createUserItem(me, true)); others.forEach(u => userListEl.appendChild(createUserItem(u, false))); renderMainHeader(); // 在线用户变化时刷新 @@ -57,27 +92,33 @@ function createUserItem(user, isMe) { // 处理服务器推送的在线用户列表 function handleClientList(list, selfId) { - userList = list; - userMap = {}; - userList.forEach(u => { userMap[u.clientId] = u; }); - myId = selfId; + const rd = roomsData[activeRoomIndex]; + if (!rd) return; + rd.userList = list; + rd.userMap = {}; + list.forEach(u => { rd.userMap[u.clientId] = u; }); + rd.myId = selfId; renderUserList(); } // 新用户上线或资料变更 function handleClientSecured(user) { - let idx = userList.findIndex(u => u.clientId === user.clientId); + const rd = roomsData[activeRoomIndex]; + if (!rd) return; + let idx = rd.userList.findIndex(u => u.clientId === user.clientId); if (idx === -1) { - userList.push(user); + rd.userList.push(user); } else { - userList[idx] = user; + rd.userList[idx] = user; } - userMap[user.clientId] = user; + rd.userMap[user.clientId] = user; renderUserList(); } // 用户下线 function handleClientLeft(clientId) { - userList = userList.filter(u => u.clientId !== clientId); - delete userMap[clientId]; + const rd = roomsData[activeRoomIndex]; + if (!rd) return; + rd.userList = rd.userList.filter(u => u.clientId !== clientId); + delete rd.userMap[clientId]; renderUserList(); } @@ -95,7 +136,9 @@ function setStatus(text) { statusBar.innerText = text; } -function addMsg(text) { +function addMsg(text, isHistory = false) { + // 只有新消息才记录 + if (!isHistory && activeRoomIndex >= 0) roomsData[activeRoomIndex].messages.push({ type: 'me', text }); const chatArea = document.getElementById('chat-area'); if (!chatArea) return; const div = document.createElement('div'); @@ -107,7 +150,9 @@ function addMsg(text) { chatArea.scrollTop = chatArea.scrollHeight; } -function addOtherMsg(msg, name = '匿名', avatar = '') { +function addOtherMsg(msg, name = '匿名', avatar = '', isHistory = false) { + // 只有新消息才记录 + if (!isHistory && activeRoomIndex >= 0) roomsData[activeRoomIndex].messages.push({ type: 'other', text: msg, name, avatar }); const chatArea = document.getElementById('chat-area'); if (!chatArea) return; const bubbleWrap = document.createElement('div'); @@ -126,40 +171,158 @@ function addOtherMsg(msg, name = '匿名', avatar = '') { chatArea.scrollTop = chatArea.scrollHeight; } -// 占位房间和成员数量,实际项目请用你的数据替换 -const ROOM_COUNT = 4; -const MEMBER_COUNT = 8; - -// 渲染房间列表(UI占位) +// 渲染房间列表(动态多房间) function renderRooms(activeId = 0) { - const roomList = document.getElementById("room-list"); - roomList.innerHTML = ""; - for (let i = 0; i < ROOM_COUNT; i++) { - const div = document.createElement("div"); - div.className = "room" + (i === activeId ? " active" : ""); + const roomList = document.getElementById('room-list'); + roomList.innerHTML = ''; + roomsData.forEach((rd, i) => { + const div = document.createElement('div'); + div.className = 'room' + (i === activeId ? ' active' : ''); div.innerHTML = `
请输入用户名、房间名,房间密码可选
+ +