Skip to content

Commit 76149e6

Browse files
committed
增加昵称支持
1 parent b52881d commit 76149e6

File tree

6 files changed

+181
-20
lines changed

6 files changed

+181
-20
lines changed

server/data.js

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
function getCookieValue(socket) {
2+
try {
3+
// 尝试从不同的可能位置获取 cookie
4+
const cookie = socket.request?.headers?.cookie ||
5+
socket.handshake?.headers?.cookie ||
6+
socket._socket?.request?.headers?.cookie ||
7+
socket.upgradeReq?.headers?.cookie;
8+
9+
if (!cookie) return null;
10+
11+
const match = cookie.match(/nickname=([^;]+)/);
12+
return match ? decodeURIComponent(match[1]) : null;
13+
} catch (e) {
14+
console.log('Error getting cookie:', e);
15+
return null;
16+
}
17+
}
118

219
const data = {
320

@@ -35,12 +52,12 @@ function registerUser(ip, socket) {
3552
if (!room) {
3653
data[key] = []
3754
}
38-
//id:2位秒数(不够用0补齐)+3位毫秒(不够用0补齐)+随机2数
3955
let id = `${Math.floor(Math.random() * 1000000).toString().substring(3,5).padStart(2, '0')}${(new Date()).getMilliseconds().toString().padStart(3, '0')}`
4056
while (data[id]) {
4157
id = `${Math.floor(Math.random() * 1000000).toString().substring(3,5).padStart(2, '0')}${(new Date()).getMilliseconds().toString().padStart(3, '0')}`
4258
}
43-
data[key].push({ id, socket, targets: {} })
59+
const nickname = getCookieValue(socket);
60+
data[key].push({ id, socket, targets: {}, nickname })
4461
return id;
4562
}
4663

@@ -68,4 +85,17 @@ function getUser(ip, uid) {
6885
return room.find(user => user.id === uid)
6986
}
7087

71-
module.exports = { registerUser, unregisterUser, getUserList, getUser }
88+
function updateNickname(ip, id, nickname) {
89+
const key = getKey(ip);
90+
const room = data[key];
91+
if (room) {
92+
const user = room.find(user => user.id === id);
93+
if (user) {
94+
user.nickname = nickname;
95+
return true;
96+
}
97+
}
98+
return false;
99+
}
100+
101+
module.exports = { registerUser, unregisterUser, getUserList, getUser, updateNickname }

server/index.js

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ const SEND_TYPE_JOINED_ROOM = '1003'; // 加入房间后的通知,比如对于
2222
const SEND_TYPE_NEW_CANDIDATE = '1004'; // offer
2323
const SEND_TYPE_NEW_CONNECTION = '1005'; // new connection
2424
const SEND_TYPE_CONNECTED = '1006'; // new connection
25+
const SEND_TYPE_NICKNAME_UPDATED = '1007'; // 昵称更新通知
2526

2627
const RECEIVE_TYPE_NEW_CANDIDATE = '9001'; // offer
2728
const RECEIVE_TYPE_NEW_CONNECTION = '9002'; // new connection
2829
const RECEIVE_TYPE_CONNECTED = '9003'; // joined
2930
const RECEIVE_TYPE_KEEPALIVE = '9999'; // keep-alive
31+
const RECEIVE_TYPE_UPDATE_NICKNAME = '9004'; // 更新昵称请求
3032

3133

3234
console.log(`Signaling server running on ws://localhost:${PORT}`);
@@ -84,6 +86,16 @@ server.on('connection', (socket, request) => {
8486
if (type === RECEIVE_TYPE_KEEPALIVE) {
8587
return;
8688
}
89+
if (type === RECEIVE_TYPE_UPDATE_NICKNAME) {
90+
const success = service.updateNickname(ip, uid, data.nickname);
91+
if (success) {
92+
// 通知所有用户昵称更新
93+
service.getUserList(ip).forEach(user => {
94+
socketSend_NicknameUpdated(user.socket, { id: uid, nickname: data.nickname });
95+
});
96+
}
97+
return;
98+
}
8799

88100
});
89101

@@ -115,7 +127,10 @@ function socketSend_UserId(socket, id) {
115127
send(socket, SEND_TYPE_REG, { id });
116128
}
117129
function socketSend_RoomInfo(socket, ip, currentId) {
118-
const result = service.getUserList(ip).map(user => ({ id: user.id }));
130+
const result = service.getUserList(ip).map(user => ({
131+
id: user.id,
132+
nickname: user.nickname
133+
}));
119134
send(socket, SEND_TYPE_ROOM_INFO, result);
120135
}
121136
function socketSend_JoinedRoom(socket, id) {
@@ -133,3 +148,7 @@ function socketSend_ConnectInvite(socket, data) {
133148
function socketSend_Connected(socket, data) {
134149
send(socket, SEND_TYPE_CONNECTED, data);
135150
}
151+
152+
function socketSend_NicknameUpdated(socket, data) {
153+
send(socket, SEND_TYPE_NICKNAME_UPDATED, data);
154+
}

www/index.html

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>局域网文字/文件P2P传输工具</title>
7-
<script src="./xchatuser.js?v=15"></script>
8-
<link rel="stylesheet" href="./style.css?v=15">
7+
<script src="./xchatuser.js?v=16"></script>
8+
<link rel="stylesheet" href="./style.css?v=16">
99
</head>
1010
<body>
1111
<div class="dragtip">
@@ -16,6 +16,11 @@ <h1>松开发送文件</h1>
1616
</div>
1717
<div class="toolbar">
1818
<div class="toolbar-left">
19+
<button class="toolbar-btn nickname-btn" title="设置昵称">
20+
<svg viewBox="0 0 24 24" width="20" height="20">
21+
<path fill="currentColor" d="M12 6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2m0 10c2.7 0 5.8 1.29 6 2H6c.23-.72 3.31-2 6-2m0-12C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 10c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
22+
</svg>
23+
</button>
1924
<button class="toolbar-btn file-btn" title="发送文件">
2025
<svg viewBox="0 0 24 24" width="20" height="20">
2126
<path fill="currentColor" d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z"/>
@@ -55,6 +60,19 @@ <h3>选择接收用户</h3>
5560
</div>
5661
</div>
5762

58-
<script src="./index.js?v=15"></script>
63+
<div class="modal" id="nicknameModal">
64+
<div class="modal-content">
65+
<h3>设置昵称</h3>
66+
<div class="nickname-input-container">
67+
<input type="text" id="nicknameInput" maxlength="10" placeholder="请输入昵称(最多10个字符)">
68+
</div>
69+
<div class="modal-footer">
70+
<button onclick="closeNicknameModal()">取消</button>
71+
<button onclick="saveNickname()">保存</button>
72+
</div>
73+
</div>
74+
</div>
75+
76+
<script src="./index.js?v=16"></script>
5977
</body>
6078
</html>

www/index.js

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var me = new XChatUser();
55

66
// 添加当前传输用户的引用
77
let currentTransferUser = null;
8+
let currentNickname = '';
89

910
function setRemote() {
1011
me.setRemoteSdp(remoteSDP.value);
@@ -13,8 +14,12 @@ function addLinkItem(uid, file) {
1314
const chatBox = document.querySelector('.chat-wrapper');
1415
const chatItem = document.createElement('div');
1516
chatItem.className = 'chat-item';
17+
18+
const user = users.find(u => u.id === uid);
19+
const displayName = user?.nickname || uid;
20+
1621
chatItem.innerHTML = `
17-
<div class="chat-item_user">${uid === me.id ? '(我)': ''}${uid} :</div>
22+
<div class="chat-item_user">${uid === me.id ? '(我)': ''}${displayName} :</div>
1823
<div class="chat-item_content"><a class="file" href="${file.url}" download="${file.name}">[文件] ${file.name}</a></div>
1924
`;
2025
chatBox.appendChild(chatItem);
@@ -33,13 +38,15 @@ function addChatItem(uid, message) {
3338
});
3439
}
3540

41+
const user = users.find(u => u.id === uid);
42+
const displayName = user?.nickname || uid;
43+
3644
chatItem.innerHTML = `
37-
<div class="chat-item_user">${uid === me.id ? '(我)': ''}${uid} :</div>
45+
<div class="chat-item_user">${uid === me.id ? '(我)': ''}${displayName} :</div>
3846
<div class="chat-item_content"><pre>${msg}</pre></div>
3947
`;
4048
chatBox.appendChild(chatItem);
4149
chatBox.scrollTop = chatBox.scrollHeight;
42-
4350
}
4451
function sendMessage(msg) {
4552
const message = msg ?? messageInput.value;
@@ -141,16 +148,18 @@ function refreshUsers(data) {
141148
u => {
142149
let uOld = users.find(uOld => uOld.id === u.id)
143150
if (uOld) {
151+
// 保持原有昵称
152+
u.nickname = u.nickname || uOld.nickname;
144153
return uOld;
145154
}
146155
let xchatUser = new XChatUser();
147156
xchatUser.id = u.id;
148157
xchatUser.isMe = u.id === me.id;
158+
xchatUser.nickname = u.nickname; // 设置昵称
149159

150-
// 添加连接状态变化监听
151160
xchatUser.onConnectionStateChange = (state) => {
152161
console.log(`User ${xchatUser.id} connection state: ${state}`);
153-
refreshUsersHTML(); // 更新用户列表显示
162+
refreshUsersHTML();
154163
};
155164

156165
return xchatUser;
@@ -212,12 +221,14 @@ function refreshUsersHTML() {
212221
`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>` :
213222
`<svg viewBox="0 0 24 24" fill="currentColor"><path d="M17 7h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1 0 1.43-.98 2.63-2.31 2.98l1.46 1.46C20.88 15.61 22 13.95 22 12c0-2.76-2.24-5-5-5zm-1 4h-2.19l2 2H16zM2 4.27l3.11 3.11C3.29 8.12 2 9.91 2 12c0 2.76 2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1 0-1.59 1.21-2.9 2.76-3.07L8.73 11H8v2h2.73L13 15.27V17h1.73l4.01 4L20 19.74 3.27 3 2 4.27z"/></svg>`;
214223

224+
const displayName = u.nickname || u.id;
225+
215226
return `
216227
<li>
217228
<span class="connection-status ${statusClass}">
218229
${statusIcon}
219230
</span>
220-
${u.id}${u.isMe?'(我)':''}
231+
${displayName}${u.isMe?'(我)':''}
221232
</li>
222233
`;
223234
}).join('');
@@ -237,6 +248,13 @@ function enterTxt(event) {
237248
const signalingServer = new WebSocket(wsUrl);
238249
signalingServer.onopen = () => {
239250
console.log('Connected to signaling server');
251+
252+
// 读取保存的昵称
253+
const match = document.cookie.match(/nickname=([^;]+)/);
254+
if (match) {
255+
currentNickname = decodeURIComponent(match[1]);
256+
}
257+
240258
setInterval(() => {
241259
signalingServer.send(JSON.stringify({type: '9999'}));
242260
}, 1000 * 10);
@@ -248,6 +266,15 @@ signalingServer.onmessage = ({ data: responseStr }) => {
248266

249267
if (type === '1001') {
250268
me.id = data.id;
269+
// 如果有保存的昵称,发送给服务器
270+
if (currentNickname) {
271+
signalingServer.send(JSON.stringify({
272+
uid: me.id,
273+
targetId: me.id,
274+
type: '9004',
275+
data: { nickname: currentNickname }
276+
}));
277+
}
251278
return;
252279
}
253280
if (type === '1002') {
@@ -270,6 +297,14 @@ signalingServer.onmessage = ({ data: responseStr }) => {
270297
joinedConnection(data);
271298
return;
272299
}
300+
if (type === '1007') {
301+
const user = users.find(u => u.id === data.id);
302+
if (user) {
303+
user.nickname = data.nickname;
304+
refreshUsersHTML();
305+
}
306+
return;
307+
}
273308
}
274309

275310
function showUserSelectModal() {
@@ -284,24 +319,21 @@ function showUserSelectModal() {
284319
if (!user.isMe) {
285320
const item = document.createElement('div');
286321
item.className = 'user-select-item';
287-
const id = `user-${user.id}`;
322+
const displayName = user.nickname || user.id;
288323

289-
// 不使用 label 的 for 属性,改用包裹的方式
290324
item.innerHTML = `
291325
<label>
292326
<input type="checkbox" value="${user.id}">
293-
<span>${user.id}</span>
327+
<span>${displayName}</span>
294328
</label>
295329
`;
296330

297331
// 点击整行时切换复选框状态
298332
item.addEventListener('click', (e) => {
299333
const checkbox = item.querySelector('input[type="checkbox"]');
300-
// 如果点击的是复选框本身,不需要额外处理
301334
if (e.target === checkbox) return;
302-
303335
checkbox.checked = !checkbox.checked;
304-
e.preventDefault(); // 阻止事件冒泡
336+
e.preventDefault();
305337
});
306338

307339
userList.appendChild(item);
@@ -415,4 +447,46 @@ document.querySelector('.send-btn').addEventListener('click', () => {
415447
if (messageInput.value.trim()) { // 只有当消息不为空时才发送
416448
sendMessage();
417449
}
418-
});
450+
});
451+
452+
function showNicknameModal() {
453+
const modal = document.getElementById('nicknameModal');
454+
const input = document.getElementById('nicknameInput');
455+
input.value = currentNickname;
456+
modal.style.display = 'block';
457+
}
458+
459+
function closeNicknameModal() {
460+
const modal = document.getElementById('nicknameModal');
461+
modal.style.display = 'none';
462+
}
463+
464+
function saveNickname() {
465+
const input = document.getElementById('nicknameInput');
466+
const nickname = input.value.trim();
467+
468+
if (nickname) {
469+
currentNickname = nickname;
470+
document.cookie = `nickname=${encodeURIComponent(nickname)}; path=/; max-age=31536000`; // 保存一年
471+
472+
// 更新本地显示
473+
const user = users.find(u => u.id === me.id);
474+
if (user) {
475+
user.nickname = nickname;
476+
refreshUsersHTML();
477+
}
478+
479+
// 发送到服务器
480+
signalingServer.send(JSON.stringify({
481+
uid: me.id,
482+
targetId: me.id,
483+
type: '9004',
484+
data: { nickname }
485+
}));
486+
}
487+
488+
closeNicknameModal();
489+
}
490+
491+
// ... 添加昵称按钮事件监听
492+
document.querySelector('.nickname-btn').addEventListener('click', showNicknameModal);

www/style.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,4 +361,23 @@ pre {
361361

362362
.connection-status.disconnected {
363363
color: #F44336;
364+
}
365+
366+
.nickname-input-container {
367+
margin: 20px 0;
368+
}
369+
370+
.nickname-input-container input {
371+
width: 100%;
372+
padding: 8px;
373+
border: 1px solid #363636;
374+
background: #2a2a2a;
375+
color: #e0e0e0;
376+
border-radius: 4px;
377+
font-size: 14px;
378+
}
379+
380+
.nickname-input-container input:focus {
381+
outline: none;
382+
border-color: #64B5F6;
364383
}

www/xchatuser.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ connOption =
1515
class XChatUser {
1616
id = null;
1717
isMe = false;
18+
nickname = null;
1819

1920
rtcConn = null;
2021
connAddressTarget = null;

0 commit comments

Comments
 (0)