表设计:
CREATE TABLE chat (
id INT PRIMARY KEY AUTO_INCREMENT,
from_userid INT NOT NULL,
to_user_id INT NOT NULL,
from_companyId INT,
to_companyId INT,
from_company_name VARCHAR(255),
to_company_name VARCHAR(255),
from_role VARCHAR(50) NOT NULL,
to_role VARCHAR(50) NOT NULL,
create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
type ENUM('text', 'image', 'file', 'audio', 'video') NOT NULL,
text TEXT,
withdraw BOOLEAN DEFAULT FALSE,
withdraw_at TIMESTAMP NULL,
view_flag BOOLEAN DEFAULT FALSE,
from_user_avatar VARCHAR(255),
to_user_avatar VARCHAR(255),
from_company_avatar VARCHAR(255),
to_company_avatar VARCHAR(255)
);
CREATE TABLE chat_order (
id INT PRIMARY KEY AUTO_INCREMENT,
order_id VARCHAR(50) NOT NULL,
chat_id INT NOT NULL,
type ENUM('product', 'service') NOT NULL,
price DECIMAL(10, 2) NOT NULL,
customer_phone VARCHAR(20),
status ENUM('pending', 'completed', 'cancelled', 'failed') NOT NULL,
create_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (chat_id) REFERENCES chat(id)
);
CREATE INDEX idx_from_userid ON chat(from_userid);
CREATE INDEX idx_to_user_id ON chat(to_user_id);
CREATE INDEX idx_create_at ON chat(create_at);
CREATE INDEX idx_order_id ON chat_order(order_id);
CREATE INDEX idx_chat_id ON chat_order(chat_id);
CREATE INDEX idx_type ON chat_order(type);
CREATE INDEX idx_status ON chat_order(status);
相关的界面代码:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket 聊天室</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
margin: 0;
padding: 0;
}
.chat-container {
width: 50%;
margin: 50px auto;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
}
.chat-header {
background-color: #007bff;
color: white;
padding: 15px;
text-align: center;
font-size: 18px;
font-weight: bold;
}
.chat-messages {
height: 400px;
overflow-y: auto;
padding: 20px;
background-color: #f9f9f9;
border-bottom: 1px solid #ddd;
}
.message {
display: flex;
margin-bottom: 10px;
padding: 10px;
border-radius: 8px;
max-width: 70%;
}
.message.sent {
background-color: #dcf8c6;
margin-left: auto;
text-align: right;
flex-direction: row-reverse;
}
.message.received {
background-color: #e1f5fe;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
}
.message-content {
max-width: 100%;
word-wrap: break-word;
}
.chat-footer {
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.chat-footer input[type="text"] {
width: 70%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
.chat-footer button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.chat-footer button:hover {
background-color: #0056b3;
}
.file-input {
display: none;
}
.extra-options {
display: none;
flex-direction: column;
}
.extra-options button {
margin-top: 5px;
background-color: #17a2b8;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-header">聊天室</div>
<div class="chat-messages" id="chatMessages"></div>
<div class="chat-footer">
<div>
<button id="attachBtn">📎</button>
<div class="extra-options" id="extraOptions">
<button id="uploadImageBtn">发送图片</button>
<button id="uploadFileBtn">发送文件</button>
<button id="sendAudioBtn">发送语音</button>
<button id="sendVideoBtn">发送视频</button>
</div>
<input type="file" id="imageInput" class="file-input" accept="image/*">
<input type="file" id="fileInput" class="file-input" accept="*/*">
</div>
<input type="text" id="messageInput" placeholder="输入消息...">
<button id="sendMessageBtn">发送</button>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).ready(function() {
let ws = new WebSocket("ws://localhost:3000");
let userName = prompt("请输入您的用户名:");
let groupName = "defaultGroup";
let userAvatar = "https://i.pravatar.cc/40";
ws.onopen = function() {
ws.send(JSON.stringify({
action: "joinGroup",
groupName: groupName,
userName: userName
}));
};
ws.onmessage = function(event) {
let data = JSON.parse(event.data);
if (data.action === "sendMessage") {
appendMessage(data.user_name, data.message, data.user_avatar, 'received');
}
if (data.type === "join" || data.type === "left") {
appendSystemMessage(data.content);
}
};
$('#sendMessageBtn').click(function() {
let messageText = $('#messageInput').val().trim();
if (messageText !== '') {
let messageData = {
action: "sendMessage",
group_name: groupName,
user_name: userName,
message: messageText,
user_avatar: userAvatar
};
ws.send(JSON.stringify(messageData));
appendMessage(userName, messageText, userAvatar, 'sent');
$('#messageInput').val('');
}
});
$('#attachBtn').click(function() {
$('#extraOptions').toggle();
});
$('#uploadImageBtn').click(function() {
$('#imageInput').click();
});
$('#imageInput').change(function() {
let file = this.files[0];
let reader = new FileReader();
reader.onload = function(e) {
ws.send(JSON.stringify({
action: "sendMessage",
group_name: groupName,
user_name: userName,
message: e.target.result,
user_avatar: userAvatar,
fileType: 'image'
}));
appendMessage(userName, '<img src="' + e.target.result + '" width="100">', userAvatar, 'sent');
};
reader.readAsDataURL(file);
});
$('#uploadFileBtn').click(function() {
$('#fileInput').click();
});
$('#fileInput').change(function() {
let file = this.files[0];
let reader = new FileReader();
reader.onload = function(e) {
ws.send(JSON.stringify({
action: "sendMessage",
group_name: groupName,
user_name: userName,
message: file.name,
fileData: e.target.result,
user_avatar: userAvatar,
fileType: 'file'
}));
appendMessage(userName, '<a href="' + e.target.result + '" download>' + file.name + '</a>', userAvatar, 'sent');
};
reader.readAsDataURL(file);
});
function appendMessage(name, message, avatar, messageType) {
let messageHtml = `
<div class="message ${messageType}">
<img src="${avatar}" class="avatar">
<div class="message-content">
<strong>${name}</strong><br>${message}
</div>
</div>
`;
$('#chatMessages').append(messageHtml);
scrollToBottom();
}
function appendSystemMessage(content) {
let systemMessageHtml = `<div class="system-message">${content}</div>`;
$('#chatMessages').append(systemMessageHtml);
scrollToBottom();
}
function scrollToBottom() {
$('#chatMessages').scrollTop($('#chatMessages')[0].scrollHeight);
}
$('#messageInput').keypress(function(e) {
if (e.which == 13) {
$('#sendMessageBtn').click();
}
});
});
</script>
</body>
</html>