You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
5.4 KiB
194 lines
5.4 KiB
// P2P 聊天程序 - Web 客户端
|
|
let ws = null;
|
|
let username = '';
|
|
let connected = false;
|
|
|
|
// DOM 元素
|
|
const connectPanel = document.getElementById('connectPanel');
|
|
const chatPanel = document.getElementById('chatPanel');
|
|
const usernameInput = document.getElementById('username');
|
|
const serverHostInput = document.getElementById('serverHost');
|
|
const serverPortInput = document.getElementById('serverPort');
|
|
const connectBtn = document.getElementById('connectBtn');
|
|
const disconnectBtn = document.getElementById('disconnectBtn');
|
|
const messageArea = document.getElementById('messageArea');
|
|
const messageInput = document.getElementById('messageInput');
|
|
const sendBtn = document.getElementById('sendBtn');
|
|
const peerList = document.getElementById('peerList');
|
|
const onlineCount = document.getElementById('onlineCount');
|
|
const userInfo = document.getElementById('userInfo');
|
|
const statusBar = document.getElementById('statusBar');
|
|
|
|
// 连接到服务器
|
|
connectBtn.addEventListener('click', () => {
|
|
username = usernameInput.value.trim();
|
|
const host = serverHostInput.value.trim();
|
|
const port = serverPortInput.value.trim();
|
|
|
|
if (!username) {
|
|
showStatus('请输入用户名', 'error');
|
|
return;
|
|
}
|
|
|
|
if (!host || !port) {
|
|
showStatus('请输入服务器地址和端口', 'error');
|
|
return;
|
|
}
|
|
|
|
connect(host, port);
|
|
});
|
|
|
|
// 断开连接
|
|
disconnectBtn.addEventListener('click', () => {
|
|
disconnect();
|
|
});
|
|
|
|
// 发送消息
|
|
sendBtn.addEventListener('click', sendMessage);
|
|
messageInput.addEventListener('keypress', (e) => {
|
|
if (e.key === 'Enter') {
|
|
sendMessage();
|
|
}
|
|
});
|
|
|
|
function sendMessage() {
|
|
const message = messageInput.value.trim();
|
|
if (!message || !connected) return;
|
|
|
|
// 发送到服务器
|
|
ws.send('MESSAGE:' + message);
|
|
|
|
// 显示自己的消息
|
|
addMessage(username, message, true);
|
|
|
|
messageInput.value = '';
|
|
}
|
|
|
|
// 连接 WebSocket
|
|
function connect(host, port) {
|
|
try {
|
|
ws = new WebSocket(`ws://${host}:${port}`);
|
|
|
|
ws.onopen = () => {
|
|
connected = true;
|
|
ws.send('USERNAME:' + username);
|
|
|
|
connectPanel.style.display = 'none';
|
|
chatPanel.style.display = 'flex';
|
|
userInfo.textContent = `用户: ${username}`;
|
|
|
|
showStatus('连接成功!', 'success');
|
|
addSystemMessage('已连接到服务器');
|
|
};
|
|
|
|
ws.onmessage = (event) => {
|
|
handleMessage(event.data);
|
|
};
|
|
|
|
ws.onerror = (error) => {
|
|
showStatus('连接错误', 'error');
|
|
console.error('WebSocket error:', error);
|
|
};
|
|
|
|
ws.onclose = () => {
|
|
connected = false;
|
|
showStatus('连接已断开', 'error');
|
|
addSystemMessage('与服务器的连接已断开');
|
|
};
|
|
|
|
} catch (error) {
|
|
showStatus('连接失败: ' + error.message, 'error');
|
|
}
|
|
}
|
|
|
|
// 断开连接
|
|
function disconnect() {
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
connected = false;
|
|
connectPanel.style.display = 'block';
|
|
chatPanel.style.display = 'none';
|
|
messageArea.innerHTML = '';
|
|
peerList.innerHTML = '';
|
|
}
|
|
|
|
// 处理接收到的消息
|
|
function handleMessage(data) {
|
|
if (data.startsWith('SYSTEM:')) {
|
|
const msg = data.substring(7);
|
|
addSystemMessage(msg);
|
|
} else if (data.startsWith('PEERS:')) {
|
|
const peers = data.substring(6).split(',').filter(p => p);
|
|
updatePeerList(peers);
|
|
} else if (data.startsWith('[')) {
|
|
// 格式: [用户名]: 消息
|
|
const match = data.match(/\[(.+?)\]: (.+)/);
|
|
if (match) {
|
|
addMessage(match[1], match[2], false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 添加消息到聊天区域
|
|
function addMessage(user, message, isOwn) {
|
|
const messageDiv = document.createElement('div');
|
|
messageDiv.className = 'message message-user' + (isOwn ? ' own' : '');
|
|
|
|
const header = document.createElement('div');
|
|
header.className = 'message-header';
|
|
header.textContent = user;
|
|
|
|
const content = document.createElement('div');
|
|
content.className = 'message-content';
|
|
content.textContent = message;
|
|
|
|
messageDiv.appendChild(header);
|
|
messageDiv.appendChild(content);
|
|
messageArea.appendChild(messageDiv);
|
|
|
|
// 滚动到底部
|
|
messageArea.scrollTop = messageArea.scrollHeight;
|
|
}
|
|
|
|
// 添加系统消息
|
|
function addSystemMessage(message) {
|
|
const messageDiv = document.createElement('div');
|
|
messageDiv.className = 'message message-system';
|
|
messageDiv.textContent = message;
|
|
messageArea.appendChild(messageDiv);
|
|
|
|
messageArea.scrollTop = messageArea.scrollHeight;
|
|
}
|
|
|
|
// 更新对等端列表
|
|
function updatePeerList(peers) {
|
|
peerList.innerHTML = '';
|
|
|
|
peers.forEach(peer => {
|
|
if (peer !== username) {
|
|
const peerDiv = document.createElement('div');
|
|
peerDiv.className = 'peer-item';
|
|
peerDiv.textContent = peer;
|
|
peerList.appendChild(peerDiv);
|
|
}
|
|
});
|
|
|
|
onlineCount.textContent = `在线: ${peers.length}`;
|
|
}
|
|
|
|
// 显示状态提示
|
|
function showStatus(message, type = 'success') {
|
|
statusBar.textContent = message;
|
|
statusBar.className = 'status-bar show ' + type;
|
|
|
|
setTimeout(() => {
|
|
statusBar.className = 'status-bar';
|
|
}, 3000);
|
|
}
|
|
|
|
// 页面加载完成后自动聚焦用户名输入框
|
|
window.addEventListener('load', () => {
|
|
usernameInput.focus();
|
|
});
|