代码拉取完成,页面将自动刷新
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>局域网文本共享</title>
<link rel="icon" href="text-logo.png" type="image/x-icon">
<style>
body {
height: calc(100% - 100px);
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
font-size: 14px;
background-color: #f6f6f6;
}
.chat-container {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.chat-window {
width: 100%;
height: calc(100% - 0px);
background-color: #fff;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
display: flex;
flex-direction: column;
}
.chat-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
background-color: #4e8cff;
color: #fff;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
padding: 0 20px;
}
.chat-header h1 {
margin: 0;
font-size: 18px;
display: inline-block;
}
.chat-body {
flex: 1;
overflow-y: scroll;
padding: 10px 20px;
display: flex;
flex-direction: column;
}
.chat-body .message {
display: flex;
align-items: flex-start;
margin-bottom: 4px;
}
.chat-body .message .content {
flex: 1;
background-color: #f6f6f6;
border-radius: 5px;
padding: 5px 10px;
white-space: pre-wrap;
word-break: break-word;
}
.chat-body .message .content a {
color: #4e8cff;
text-decoration: underline;
}
.chat-footer {
display: flex;
align-items: center;
height: 50px;
background-color: #f6f6f6;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
padding: 0 10px;
}
.chat-footer input[type="text"] {
flex: 1;
height: 100%;
border: none;
outline: none;
background-color: transparent;
font-size: 14px;
padding: 0 10px;
}
.chat-footer input[type="submit"] {
width: 80px;
height: 100%;
border: none;
outline: none;
background-color: #4e8cff;
color: #fff;
font-weight: bold;
cursor: pointer;
font-size: 14px;
margin:0px -10px 0px 0px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
}
.chat-body .message.sent {
align-items: flex-end;
}
.chat-body .message.received .avatar {
order: 2;
margin-right: 0;
margin-left: 10px;
}
.chat-body .message.received .content {
order: 1;
}
.chat-header .settings-btn {
margin-left: auto;
}
/* 手机竖屏 */
@media screen and (max-width: 480px) {
.chat-header {
padding: 0 10px;
}
.chat-header h1 {
font-size: 20px;
}
.chat-body {
padding: 10px;
}
.chat-footer {
padding: 0 5px;
}
.chat-footer input[type="text"] {
font-size: 16px;
}
.chat-footer input[type="submit"] {
font-size: 16px;
}
.modal {
width: 240px;
}
}
/* iPad 竖屏和横屏 */
@media screen and (min-width: 481px) and (max-width: 1024px) {
.chat-header {
padding: 0 15px;
}
.chat-header h1 {
font-size: 16px;
}
.chat-body {
padding: 10px;
}
.chat-footer {
padding: 0 10px;
}
}
/* 设置按钮 */
.settings-btn {
cursor: pointer;
margin-left: 10px;
}
/* 设置面板 */
.settings-panel {
position: absolute;
top: 60px;
right: 10px;
width: 200px;
background-color: #fff;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
display: none;
}
.settings-panel.active {
display: block;
}
.settings-panel .settings-item {
padding: 10px;
border-bottom: 1px solid #f6f6f6;
cursor: pointer;
}
.settings-panel .settings-item:last-child {
border-bottom: none;
}
/* 夜间模式 */
.dark-mode .chat-window {
background-color: #222;
}
.dark-mode .chat-header {
background-color: #111;
}
.dark-mode .chat-body {
background-color: #333;
}
.dark-mode .chat-body .message .content {
background-color: #3C3C3C;
}
.dark-mode .chat-footer {
background-color: #111;
}
.dark-mode .chat-footer input[type="submit"] {
background-color: #111;
}
.dark-mode .settings-panel {
background-color: #111;
}
.dark-mode .chat-header, .dark-mode .chat-footer input[type="text"] {
color: #fff;
}
/* 模态框 */
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
border-radius: 10px;
padding: 20px;
display: none;
z-index: 9999;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.3);
}
.confirm-button {
/* 这里是确定按钮的样式 */
text-align: center;
text-decoration: none;
display: inline-block;
margin: 4px 1px;
padding: 3px 6px;
cursor: pointer;
/* 设置按钮背景为透明 */
background-color: transparent;
border: 0px solid black;
border-radius: 5px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
}
.cancel-button {
/* 这里是取消按钮的样式 */
text-align: center;
text-decoration: none;
display: inline-block;
margin: 4px 10px;
padding: 3px 6px;
cursor: pointer;
/* 设置按钮背景为透明 */
background-color: transparent;
border: 0px solid black;
border-radius: 5px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
}
.modal.active {
display: block;
}
.modal input[type="text"] {
width: -webkit-fill-available;
height: 20px;
margin-bottom: 10px;
border: 1px solid #000;
border-radius: 5px;
padding: 5px;
font-size: 14px;
}
.modal button {
margin-right: 10px;
}
/*模态框震动效果*/
.shake {
animation: shake 0.5s linear;
}
@keyframes shake {
0% {
transform: translateX(0);
}
20% {
transform: translateX(-5px);
}
40% {
transform: translateX(5px);
}
60% {
transform: translateX(-5px);
}
80% {
transform: translateX(5px);
}
100% {
transform: translateX(0);
}
}
/*悬浮通知*/
.notification {
position: fixed;
top: 1.2%;
left: 50%;
transform: translateX(-50%);
padding: 10px;
width: 90px;
height: 12px;
background-color: #4CAF50;
color: #111;
text-align: center;
z-index: 9999;
border-radius: 2px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.3);
}
.notification-content {
font-weight: bold; /* 字体加粗 */
font-size: 12px;
line-height: 12px;
}
.notification.success {
background-color: #F44336;
}
.notification.info {
background-color: #f6f6f6;
}
.notification.warning {
background-color: #FF9800;
}
.notification.error {
background-color: #F44336;
}
/* 删除对话框 */
.dialog {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.3);
}
.dialog-content {
background-color: white;
padding: 20px;
border-radius: 5px;
}
#confirmYes {
/* 这里是确定按钮的样式 */
float: right;
text-align: center;
text-decoration: none;
display: inline-block;
padding: 3px 6px;
margin: 4px 8px;
cursor: pointer;
/* 设置按钮背景为透明 */
background-color: transparent;
border: 0px solid black;
border-radius: 5px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
}
#confirmNo {
/* 这里是取消按钮的样式 */
float: right;
text-align: center;
text-decoration: none;
display: inline-block;
padding: 3px 6px;
margin: 4px 10px;
cursor: pointer;
/* 设置按钮背景为透明 */
background-color: transparent;
border: 0px solid black;
border-radius: 5px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.2);
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div class="chat-container">
<div class="chat-window">
<div class="chat-header">
<h1>文本共享</h1>
<div class="settings-btn" onclick="toggleSettingsPanel()" style="font-size: 24px;">⚙</div>
</div>
<div class="chat-body"></div>
<div class="chat-footer">
<input type="text" placeholder="输入消息" />
<input type="submit" value="发送" />
</div>
</div>
</div>
<div class="settings-panel" id="settingsPanel">
<div class="settings-item" onclick="toggleDayMode()">白天模式</div>
<div class="settings-item" onclick="toggleDarkMode()">夜间模式</div>
<div class="settings-item" onclick="openAddressModal()">服务器地址</div>
</div>
<div class="modal" id="addressModal">
<input type="text" id="addressInput" placeholder="输入服务器地址" />
<button class="confirm-button" onclick="saveAddress()">确认</button>
<button class="cancel-button" onclick="closeAddressModal()">取消</button>
</div>
<div id="confirmDialog" class="dialog hidden">
<div class="dialog-content">
<p>删除后将不会出现在你的记录中,确定删除吗?</p>
<button id="confirmYes">确定</button>
<button id="confirmNo">取消</button>
</div>
</div>
<script>
const chatWindow = document.querySelector('.chat-window');
const chatHeader = document.querySelector('.chat-header');
const chatBody = document.querySelector('.chat-body');
const chatFooter = document.querySelector('.chat-footer');
const messageInput = document.querySelector('input[type="text"]');
const sendButton = document.querySelector('input[type="submit"]');
const addressModal = document.querySelector('#addressModal');
const addressInput = document.querySelector('#addressInput');
let ws = null;
let address = '127.0.0.1'; // 初始服务器IP地址
let server_address = address; // 初始ws服务器地址
function createWebSocket() {
ws = new WebSocket(`ws://${server_address}:2023/`);
// 监听WebSocket连接事件
ws.addEventListener('open', (event) => {
console.log('客户端 已连接');
});
// 监听WebSocket消息事件
ws.addEventListener('message', (event) => {
const message = JSON.parse(event.data);
if (message.type === 'message') {
const content = message.content;
const messageWindow = document.createElement('div');
messageWindow.className = 'message-window';
const messageElement = document.createElement('div');
messageElement.className = 'message';
messageElement.innerHTML = `
<div class="avatar"></div>
<div class="content">${parseMessageContent(content)}</div>
`;
const deleteButton = document.createElement('button');
deleteButton.className = 'text-neutral-300 transition hover:text-neutral-900 dark:text-neutral-600 dark:hover:text-neutral-300';
deleteButton.style.border = 'none';
deleteButton.style['background-color'] = 'transparent';
deleteButton.style.fontSize = '6px';
deleteButton.style.float = 'right';
deleteButton.style.cursor = 'pointer';
deleteButton.style['margin-bottom'] = '1px';
deleteButton.title = '删除';
deleteButton.innerHTML = '<svg t="1687940513319" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3173" width="13" height="13"><path d="M202.666667 256h-42.666667a32 32 0 0 1 0-64h704a32 32 0 0 1 0 64H266.666667v565.333333a53.333333 53.333333 0 0 0 53.333333 53.333334h384a53.333333 53.333333 0 0 0 53.333333-53.333334V352a32 32 0 0 1 64 0v469.333333c0 64.8-52.533333 117.333333-117.333333 117.333334H320c-64.8 0-117.333333-52.533333-117.333333-117.333334V256z m224-106.666667a32 32 0 0 1 0-64h170.666666a32 32 0 0 1 0 64H426.666667z m-32 288a32 32 0 0 1 64 0v256a32 32 0 0 1-64 0V437.333333z m170.666666 0a32 32 0 0 1 64 0v256a32 32 0 0 1-64 0V437.333333z" fill="#000000" p-id="3174"></path></svg>';
const confirmDialog = document.getElementById('confirmDialog');
const confirmYes = document.getElementById('confirmYes');
const confirmNo = document.getElementById('confirmNo');
deleteButton.onclick = function() {
confirmDialog.classList.remove('hidden');
};
confirmYes.onclick = function() {
deleteButton.parentNode.remove();
confirmDialog.classList.add('hidden');
};
confirmNo.onclick = function() {
confirmDialog.classList.add('hidden');
};
const copyButton = document.createElement('button');
copyButton.className = 'text-neutral-300 transition hover:text-neutral-900 dark:text-neutral-600 dark:hover:text-neutral-300';
copyButton.style.border = 'none';
copyButton.style['background-color'] = 'transparent';
copyButton.style.fontSize = '6px';
copyButton.style.float = 'right';
copyButton.style.cursor = 'pointer';
copyButton.style['margin-bottom'] = '1px';
copyButton.title = '复制';
copyButton.innerHTML = '<svg t="1687940444536" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2130" width="12" height="12"><path d="M720 192h-544A80.096 80.096 0 0 0 96 272v608C96 924.128 131.904 960 176 960h544c44.128 0 80-35.872 80-80v-608C800 227.904 764.128 192 720 192z m16 688c0 8.8-7.2 16-16 16h-544a16 16 0 0 1-16-16v-608a16 16 0 0 1 16-16h544a16 16 0 0 1 16 16v608z" p-id="2131"></path><path d="M848 64h-544a32 32 0 0 0 0 64h544a16 16 0 0 1 16 16v608a32 32 0 1 0 64 0v-608C928 99.904 892.128 64 848 64z" p-id="2132"></path><path d="M608 360H288a32 32 0 0 0 0 64h320a32 32 0 1 0 0-64zM608 520H288a32 32 0 1 0 0 64h320a32 32 0 1 0 0-64zM480 678.656H288a32 32 0 1 0 0 64h192a32 32 0 1 0 0-64z" p-id="2133"></path></svg>';
copyButton.onclick = function() {
navigator.clipboard.writeText(content);
showNotification('<div style="display: flex; align-items: center;"><span style="background-color: green; color: white; border-radius: 50%; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; text-align: center; font-size: 12px; line-height: 12px;">✔</span> <span style="font-size: 12px; line-height: 12px;">复制成功</span></div>', 'info');
};
messageWindow.appendChild(messageElement);
messageWindow.appendChild(deleteButton);
messageWindow.appendChild(copyButton);
chatBody.appendChild(messageWindow);
chatBody.scrollTop = chatBody.scrollHeight;
}
});
}
function sendMessage(event) {
event.preventDefault();
const message = messageInput.value;
if (message.trim()) {
ws.send(JSON.stringify({
type: 'message',
content: message.toString()
}));
const messageWindow = document.createElement('div');
messageWindow.className = 'message-window';
const messageElement = document.createElement('div');
messageElement.className = 'message sent';
messageElement.innerHTML = `
<div class="content">${parseMessageContent(message)}</div>
<div class="avatar"></div>
`;
const deleteButton = document.createElement('button');
deleteButton.className = 'text-neutral-300 transition hover:text-neutral-900 dark:text-neutral-600 dark:hover:text-neutral-300';
deleteButton.style.border = 'none';
deleteButton.style['background-color'] = 'transparent';
deleteButton.style.fontSize = '6px';
deleteButton.style.float = 'right';
deleteButton.style.cursor = 'pointer';
deleteButton.style['margin-bottom'] = '1px';
deleteButton.title = '删除';
deleteButton.innerHTML = '<svg t="1687940513319" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3173" width="13" height="13"><path d="M202.666667 256h-42.666667a32 32 0 0 1 0-64h704a32 32 0 0 1 0 64H266.666667v565.333333a53.333333 53.333333 0 0 0 53.333333 53.333334h384a53.333333 53.333333 0 0 0 53.333333-53.333334V352a32 32 0 0 1 64 0v469.333333c0 64.8-52.533333 117.333333-117.333333 117.333334H320c-64.8 0-117.333333-52.533333-117.333333-117.333334V256z m224-106.666667a32 32 0 0 1 0-64h170.666666a32 32 0 0 1 0 64H426.666667z m-32 288a32 32 0 0 1 64 0v256a32 32 0 0 1-64 0V437.333333z m170.666666 0a32 32 0 0 1 64 0v256a32 32 0 0 1-64 0V437.333333z" fill="#000000" p-id="3174"></path></svg>';
const confirmDialog = document.getElementById('confirmDialog');
const confirmYes = document.getElementById('confirmYes');
const confirmNo = document.getElementById('confirmNo');
deleteButton.onclick = function() {
confirmDialog.classList.remove('hidden');
};
confirmYes.onclick = function() {
deleteButton.parentNode.remove();
confirmDialog.classList.add('hidden');
};
confirmNo.onclick = function() {
confirmDialog.classList.add('hidden');
};
const copyButton = document.createElement('button');
copyButton.className = 'text-neutral-300 transition hover:text-neutral-900 dark:text-neutral-600 dark:hover:text-neutral-300';
copyButton.style.border = 'none';
copyButton.style['background-color'] = 'transparent';
copyButton.style.fontSize = '6px';
copyButton.style.float = 'right';
copyButton.style.cursor = 'pointer';
copyButton.style['margin-bottom'] = '1px';
copyButton.title = '复制';
copyButton.innerHTML = '<svg t="1687940444536" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2130" width="12" height="12"><path d="M720 192h-544A80.096 80.096 0 0 0 96 272v608C96 924.128 131.904 960 176 960h544c44.128 0 80-35.872 80-80v-608C800 227.904 764.128 192 720 192z m16 688c0 8.8-7.2 16-16 16h-544a16 16 0 0 1-16-16v-608a16 16 0 0 1 16-16h544a16 16 0 0 1 16 16v608z" p-id="2131"></path><path d="M848 64h-544a32 32 0 0 0 0 64h544a16 16 0 0 1 16 16v608a32 32 0 1 0 64 0v-608C928 99.904 892.128 64 848 64z" p-id="2132"></path><path d="M608 360H288a32 32 0 0 0 0 64h320a32 32 0 1 0 0-64zM608 520H288a32 32 0 1 0 0 64h320a32 32 0 1 0 0-64zM480 678.656H288a32 32 0 1 0 0 64h192a32 32 0 1 0 0-64z" p-id="2133"></path></svg>';
copyButton.onclick = function() {
navigator.clipboard.writeText(message);
showNotification('<div style="display: flex; align-items: center;"><span style="background-color: green; color: white; border-radius: 50%; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; text-align: center; font-size: 12px; line-height: 12px;">✔</span> <span style="font-size: 12px; line-height: 12px;">复制成功</span></div>', 'info');
};
messageWindow.appendChild(messageElement);
messageWindow.appendChild(deleteButton);
messageWindow.appendChild(copyButton);
chatBody.appendChild(messageWindow);
chatBody.scrollTop = chatBody.scrollHeight;
messageInput.value = '';
}
}
function showNotification(message, type) {
const notification = document.createElement('div');
notification.className = `notification ${type}`;
notification.style.display = 'flex';
notification.style.alignItems = 'center';
notification.style.justifyContent = 'center';
notification.innerHTML = `<div class="notification-content">${message}</div>`;
// 获取 .chat-header 元素的位置和尺寸
const chatHeader = document.querySelector('.chat-header');
const { height } = chatHeader.getBoundingClientRect();
// 计算悬浮通知应该放置的位置
notification.style.position = 'absolute';
notification.style.top = `${height / 2}px`;
document.body.appendChild(notification);
setTimeout(() => {
notification.remove();
}, 3000);
}
function parseMessageContent(content) {
// 替换特殊字符
content = content.replace(/</g, '<').replace(/>/g, '>');
// 解析链接
if (window.utools) {
content = content.replace(/(https?:\/\/[^\s]+)/g, (match, url) => {
return `<a href="#" onclick="utools.shellOpenExternal('${url}');">${url}</a>`;
});
} else {
content = content.replace(/(https?:\/\/[^\s]+)/g, '<a href="$1" target="_blank">$1</a>');
}
// 处理换行
content = content.replace(/\n/g, '<br/>');
return content;
}
sendButton.addEventListener('click', sendMessage);
messageInput.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
sendMessage(event);
}
});
// 监听设置按钮
function toggleSettingsPanel() {
const settingsPanel = document.getElementById('settingsPanel');
settingsPanel.classList.toggle('active');
}
// 监听黑夜按钮
function toggleDarkMode() {
chatWindow.classList.add('dark-mode');
chatHeader.classList.add('dark-mode');
chatBody.classList.add('dark-mode');
chatFooter.classList.add('dark-mode');
}
// 监听白天按钮
function toggleDayMode() {
chatWindow.classList.remove('dark-mode');
chatHeader.classList.remove('dark-mode');
chatBody.classList.remove('dark-mode');
chatFooter.classList.remove('dark-mode');
}
// 打开服务器地址模态框
function openAddressModal() {
addressInput.value = server_address; // 只显示IP地址
addressModal.classList.add('active');
}
// 保存服务器地址
function saveAddress() {
const newAddress = addressInput.value.trim();
if (validateIPAddress(newAddress) && !startsWith255(newAddress)) {
ws.close(); // 先关闭旧的WebSocket连接
server_address = newAddress; // 更新地址变量
createWebSocket(); // 创建新的WebSocket连接
addressModal.classList.remove('active'); // 关闭模态框
} else {
addressInput.style.borderColor = 'red'; // 设置边框颜色为红色
addressInput.classList.add('shake'); // 添加震动效果
setTimeout(() => {
addressInput.classList.remove('shake'); // 移除震动效果
}, 500);
}
}
// 关闭服务器地址模态框
function closeAddressModal() {
addressModal.classList.remove('active');
}
// 校验IP地址的格式是否合法
function validateIPAddress(ip) {
const ipRegex = /^(25[0-4]|2[0-4]\d|1\d{2}|[1-9]\d|\d)(\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)){3}$/;
return ipRegex.test(ip);
}
// 判断IP地址是否以255开头
function startsWith255(ip) {
const ipParts = ip.split('.');
return ipParts[0] === '255';
}
// 监听输入框的输入事件,重置边框颜色
addressInput.addEventListener('input', function() {
addressInput.style.borderColor = '';
});
// 创建初始的WebSocket连接
createWebSocket();
</script>
</body>
</html>
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。