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.
Project/LLRiseTabBarDemo/complete_chat_test.html

603 lines
20 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>二手交易应用 - 实时聊天测试</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background-color: #f5f5f5;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
h1 {
text-align: center;
margin-bottom: 30px;
color: #2c3e50;
}
.login-panel {
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin-bottom: 30px;
max-width: 500px;
margin-left: auto;
margin-right: auto;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #555;
}
input {
width: 100%;
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 16px;
}
input:focus {
outline: none;
border-color: #3498db;
}
.btn {
background-color: #3498db;
color: white;
border: none;
padding: 12px 20px;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
.btn:hover {
background-color: #2980b9;
}
.btn:disabled {
background-color: #bdc3c7;
cursor: not-allowed;
}
.chat-container {
display: none;
gap: 20px;
margin-bottom: 30px;
}
.chat-window {
background: white;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
overflow: hidden;
flex: 1;
display: flex;
flex-direction: column;
height: 600px;
}
.chat-header {
background-color: #3498db;
color: white;
padding: 15px 20px;
font-weight: 600;
display: flex;
justify-content: space-between;
align-items: center;
}
.connection-status {
font-size: 12px;
padding: 4px 8px;
border-radius: 12px;
background-color: rgba(255,255,255,0.2);
}
.status-connected {
background-color: #2ecc71;
}
.status-disconnected {
background-color: #e74c3c;
}
.message-area {
flex: 1;
padding: 20px;
overflow-y: auto;
background-color: #f9f9f9;
}
.message {
margin-bottom: 15px;
display: flex;
flex-direction: column;
}
.message-info {
font-size: 12px;
color: #777;
margin-bottom: 5px;
}
.message-content {
max-width: 70%;
padding: 10px 15px;
border-radius: 8px;
word-wrap: break-word;
}
.sent .message-content {
background-color: #3498db;
color: white;
align-self: flex-end;
border-bottom-right-radius: 2px;
}
.received .message-content {
background-color: #e0e0e0;
color: #333;
align-self: flex-start;
border-bottom-left-radius: 2px;
}
.system .message-content {
background-color: #f39c12;
color: white;
align-self: center;
font-style: italic;
text-align: center;
}
.input-area {
padding: 15px;
background-color: white;
border-top: 1px solid #eee;
display: flex;
gap: 10px;
}
.message-input {
flex: 1;
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 20px;
font-size: 16px;
}
.send-btn {
background-color: #3498db;
color: white;
border: none;
padding: 10px 20px;
border-radius: 20px;
cursor: pointer;
transition: background-color 0.3s;
}
.send-btn:hover {
background-color: #2980b9;
}
.send-btn:disabled {
background-color: #bdc3c7;
cursor: not-allowed;
}
.info-box {
background-color: #e8f4f8;
border-left: 4px solid #3498db;
padding: 15px;
margin-bottom: 20px;
border-radius: 5px;
}
.account-info {
background-color: #e8f8f5;
border: 1px solid #2ecc71;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
}
.account-info h3 {
color: #27ae60;
margin-bottom: 10px;
}
.account-info code {
background-color: #f0f0f0;
padding: 2px 5px;
border-radius: 3px;
font-family: monospace;
}
.instructions {
background-color: #fff9c4;
padding: 20px;
border-radius: 10px;
margin-bottom: 30px;
}
.instructions h3 {
color: #f57c00;
margin-bottom: 15px;
}
.instructions ol {
margin-left: 20px;
}
.instructions li {
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="container">
<h1>二手交易应用 - 实时聊天测试</h1>
<div class="instructions">
<h3>使用说明</h3>
<ol>
<li>请确保后端服务已在 <code>http://localhost:8080</code> 运行</li>
<li>使用提供的模拟账号登录系统</li>
<li>系统会自动建立WebSocket连接</li>
<li>可以在两个聊天窗口之间互相发送消息进行测试</li>
</ol>
</div>
<div class="account-info">
<h3>模拟测试账号</h3>
<p>账号1手机号 <code>13800138001</code>, 密码 <code>password1</code></p>
<p>账号2手机号 <code>13800138002</code>, 密码 <code>password2</code></p>
</div>
<!-- 登录面板 -->
<div class="login-panel">
<h2 style="margin-bottom: 20px; text-align: center;">用户登录</h2>
<div class="form-group">
<label for="phone">手机号:</label>
<input type="text" id="phone" placeholder="请输入手机号" value="13800138001">
</div>
<div class="form-group">
<label for="password">密码:</label>
<input type="password" id="password" placeholder="请输入密码" value="password1">
</div>
<button class="btn" id="login-btn">登录</button>
</div>
<!-- 聊天窗口容器 -->
<div class="chat-container" id="chat-container">
<!-- 用户1的聊天窗口 -->
<div class="chat-window">
<div class="chat-header">
<span>用户1的聊天窗口</span>
<span class="connection-status" id="status-user1">断开</span>
</div>
<div class="message-area" id="messages-user1"></div>
<div class="input-area">
<input type="text" class="message-input" id="input-user1" placeholder="输入消息...">
<button class="send-btn" id="send-btn1">发送</button>
</div>
</div>
<!-- 用户2的聊天窗口 -->
<div class="chat-window">
<div class="chat-header">
<span>用户2的聊天窗口</span>
<span class="connection-status" id="status-user2">断开</span>
</div>
<div class="message-area" id="messages-user2"></div>
<div class="input-area">
<input type="text" class="message-input" id="input-user2" placeholder="输入消息...">
<button class="send-btn" id="send-btn2">发送</button>
</div>
</div>
</div>
<div class="info-box" id="info-box" style="display: none;">
<h3>系统信息</h3>
<p id="system-info">正在连接...</p>
</div>
</div>
<script>
// 全局变量
let currentUser = null;
let ws1 = null; // 用户1的WebSocket连接
let ws2 = null; // 用户2的WebSocket连接
const API_BASE_URL = 'http://localhost:8080';
// 初始化DOM元素
const loginBtn = document.getElementById('login-btn');
const phoneInput = document.getElementById('phone');
const passwordInput = document.getElementById('password');
const chatContainer = document.getElementById('chat-container');
const infoBox = document.getElementById('info-box');
const systemInfo = document.getElementById('system-info');
const statusUser1 = document.getElementById('status-user1');
const statusUser2 = document.getElementById('status-user2');
const messagesUser1 = document.getElementById('messages-user1');
const messagesUser2 = document.getElementById('messages-user2');
const inputUser1 = document.getElementById('input-user1');
const inputUser2 = document.getElementById('input-user2');
const sendBtn1 = document.getElementById('send-btn1');
const sendBtn2 = document.getElementById('send-btn2');
// 登录按钮事件
loginBtn.addEventListener('click', login);
// 发送按钮事件
sendBtn1.addEventListener('click', () => sendMessage(1));
sendBtn2.addEventListener('click', () => sendMessage(2));
// 回车键发送消息
inputUser1.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendMessage(1);
});
inputUser2.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendMessage(2);
});
// 用户登录函数
async function login() {
const phone = phoneInput.value.trim();
const password = passwordInput.value.trim();
if (!phone || !password) {
alert('请输入手机号和密码');
return;
}
try {
// 禁用登录按钮
loginBtn.disabled = true;
loginBtn.textContent = '登录中...';
// 调用登录API
const response = await fetch(`${API_BASE_URL}/api/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ phone, password })
});
if (!response.ok) {
throw new Error('登录失败');
}
const data = await response.json();
currentUser = data;
// 显示系统信息
infoBox.style.display = 'block';
systemInfo.textContent = `登录成功用户ID: ${data.userId}, 用户名: ${data.username}`;
// 显示聊天容器
chatContainer.style.display = 'flex';
// 自动建立两个用户的WebSocket连接仅用于测试
connectWebSocket();
} catch (error) {
alert('登录失败:' + error.message);
console.error('登录错误:', error);
} finally {
// 恢复登录按钮
loginBtn.disabled = false;
loginBtn.textContent = '登录';
}
}
// 建立WebSocket连接
function connectWebSocket() {
// 连接用户1的WebSocket
ws1 = new WebSocket(`ws://localhost:8080/ws/chat?userId=1&username=用户1`);
setupWebSocketEvents(ws1, 1);
// 连接用户2的WebSocket
ws2 = new WebSocket(`ws://localhost:8080/ws/chat?userId=2&username=用户2`);
setupWebSocketEvents(ws2, 2);
}
// 设置WebSocket事件处理
function setupWebSocketEvents(ws, userId) {
// 连接成功
ws.onopen = () => {
console.log(`用户${userId} WebSocket连接已建立`);
updateConnectionStatus(userId, true);
addSystemMessage(userId, 'WebSocket连接已建立');
};
// 接收消息
ws.onmessage = (event) => {
try {
const message = JSON.parse(event.data);
console.log(`用户${userId} 收到消息:`, message);
// 处理不同类型的消息
if (message.type === 'CHAT') {
// 显示在对应窗口
const targetUserId = message.sender.id === userId ? userId :
message.sender.id === 1 ? 2 : 1;
addMessage(targetUserId, {
id: message.id,
content: message.content,
sender: message.sender,
receiver: message.receiver,
createdAt: message.createdAt,
sent: message.sender.id === userId
});
} else if (message.type === 'SYSTEM') {
// 系统消息显示在所有窗口
addSystemMessage(1, message.content);
addSystemMessage(2, message.content);
}
} catch (error) {
console.error('解析消息错误:', error);
}
};
// 连接关闭
ws.onclose = () => {
console.log(`用户${userId} WebSocket连接已关闭`);
updateConnectionStatus(userId, false);
addSystemMessage(userId, 'WebSocket连接已关闭');
// 尝试重连
setTimeout(() => {
console.log(`尝试重新连接用户${userId}...`);
connectWebSocket();
}, 5000);
};
// 连接错误
ws.onerror = (error) => {
console.error(`用户${userId} WebSocket错误:`, error);
updateConnectionStatus(userId, false);
addSystemMessage(userId, `WebSocket连接错误: ${error.message || '未知错误'}`);
};
}
// 更新连接状态显示
function updateConnectionStatus(userId, connected) {
const statusElement = userId === 1 ? statusUser1 : statusUser2;
statusElement.textContent = connected ? '已连接' : '断开';
statusElement.className = connected ?
'connection-status status-connected' :
'connection-status status-disconnected';
}
// 发送消息
function sendMessage(fromUserId) {
const inputElement = fromUserId === 1 ? inputUser1 : inputUser2;
const content = inputElement.value.trim();
const ws = fromUserId === 1 ? ws1 : ws2;
const toUserId = fromUserId === 1 ? 2 : 1;
if (!content || !ws || ws.readyState !== WebSocket.OPEN) {
return;
}
// 构建消息对象
const message = {
type: 'CHAT',
content: content,
receiverId: toUserId,
senderId: fromUserId
};
// 发送消息
ws.send(JSON.stringify(message));
// 清空输入框
inputElement.value = '';
// 在发送者窗口显示消息
addMessage(fromUserId, {
content: content,
sender: { id: fromUserId, username: `用户${fromUserId}` },
receiver: { id: toUserId, username: `用户${toUserId}` },
createdAt: new Date().toISOString(),
sent: true
});
}
// 添加消息到指定用户的聊天窗口
function addMessage(userId, message) {
const messagesContainer = userId === 1 ? messagesUser1 : messagesUser2;
const messageType = message.sent ? 'sent' : 'received';
// 格式化时间
const date = new Date(message.createdAt);
const timeStr = date.toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
// 创建消息元素
const messageElement = document.createElement('div');
messageElement.className = `message ${messageType}`;
// 设置消息内容
messageElement.innerHTML = `
<div class="message-info">
${message.sender.username} · ${timeStr}
</div>
<div class="message-content">
${escapeHtml(message.content)}
</div>
`;
// 添加到消息容器
messagesContainer.appendChild(messageElement);
// 滚动到底部
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
// 添加系统消息
function addSystemMessage(userId, content) {
const messagesContainer = userId === 1 ? messagesUser1 : messagesUser2;
const date = new Date();
const timeStr = date.toLocaleTimeString('zh-CN', {
hour: '2-digit',
minute: '2-digit'
});
const messageElement = document.createElement('div');
messageElement.className = 'message system';
messageElement.innerHTML = `
<div class="message-info">系统消息 · ${timeStr}</div>
<div class="message-content">${escapeHtml(content)}</div>
`;
messagesContainer.appendChild(messageElement);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
// HTML转义函数
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 页面加载完成后检查WebSocket支持
window.addEventListener('load', () => {
if (!window.WebSocket) {
alert('您的浏览器不支持WebSocket无法使用实时聊天功能');
}
});
</script>
</body>
</html>