yuanbao-site / index.html
5672 字节
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>元宝聊天室</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:system-ui,-apple-system,sans-serif;background:#0d1117;color:#c9d1d9;height:100vh;display:flex;flex-direction:column}
#header{background:#161b22;padding:12px 16px;border-bottom:1px solid #30363d;display:flex;align-items:center;gap:10px}
#header h1{font-size:16px;color:#58a6ff}
#status{font-size:12px;color:#8b949e;margin-left:auto}
#messages{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:8px}
.msg{margin-bottom:4px}
.msg .name{font-weight:600;font-size:13px;margin-right:6px}
.msg .name.own{color:#58a6ff}
.msg .text{font-size:14px;line-height:1.5;word-break:break-all}
.msg .time{font-size:11px;color:#8b949e;margin-left:8px}
.system{text-align:center;color:#8b949e;font-size:12px;padding:4px 0}
#input-area{background:#161b22;padding:12px 16px;border-top:1px solid #30363d;display:flex;gap:8px}
#username-in{background:#0d1117;border:1px solid #30363d;color:#c9d1d9;padding:8px 12px;border-radius:6px;font-size:14px;width:100px}
#message{background:#0d1117;border:1px solid #30363d;color:#c9d1d9;padding:8px 12px;border-radius:6px;font-size:14px;flex:1}
#message:focus,#username-in:focus{outline:none;border-color:#58a6ff}
#send{background:#238636;border:none;color:#fff;padding:8px 16px;border-radius:6px;font-size:14px;cursor:pointer}
#send:hover{background:#2ea043}
#login-overlay{position:fixed;inset:0;background:#0d1117;display:flex;align-items:center;justify-content:center;z-index:100}
#login-overlay.hidden{display:none}
.login-box{background:#161b22;border:1px solid #30363d;border-radius:8px;padding:32px;width:320px}
.login-box h2{font-size:20px;margin-bottom:20px;color:#58a6ff}
.login-box input{width:100%;background:#0d1117;border:1px solid #30363d;color:#c9d1d9;padding:10px 12px;border-radius:6px;font-size:14px;margin-bottom:12px}
.login-box input:focus{outline:none;border-color:#58a6ff}
.login-box button{width:100%;background:#238636;border:none;color:#fff;padding:10px;border-radius:6px;font-size:14px;cursor:pointer}
.login-box button:hover{background:#2ea043}
</style>
</head>
<body>

<div id="login-overlay">
  <div class="login-box">
    <h2>🦆 加入聊天室</h2>
    <input type="text" id="login-name" placeholder="输入你的昵称" maxlength="20">
    <button onclick="enterChat()">进入聊天</button>
  </div>
</div>

<div id="header">
  <h1>🦆 元宝聊天室</h1>
  <span id="status">🟢 在线</span>
</div>

<div id="messages"></div>

<div id="input-area">
  <input type="text" id="username-in" placeholder="昵称" maxlength="20">
  <input type="text" id="message" placeholder="说点什么…" maxlength="500" onkeydown="if(event.key==='Enter'&&!event.shiftKey){sendMsg();event.preventDefault()}">
  <button id="send" onclick="sendMsg()">发送</button>
</div>

<script>
const ROOM = 'yuanbao-chat-v1';
const CHANNEL = new BroadcastChannel('yuanbao-chat-v1');
let myName = localStorage.getItem('chat_name') || '';
let myId = localStorage.getItem('chat_id') || Math.random().toString(36).substr(2,9);
localStorage.setItem('chat_id', myId);

function enterChat(){
  const name = document.getElementById('login-name').value.trim();
  if(!name) return;
  myName = name;
  localStorage.setItem('chat_name', name);
  document.getElementById('username-in').value = name;
  document.getElementById('login-overlay').classList.add('hidden');
  loadHistory();
  CHANNEL.postMessage({type:'join', name:myName, id:myId});
}

function loadHistory(){
  const msgs = JSON.parse(localStorage.getItem(ROOM+'-msgs') || '[]');
  msgs.forEach(renderMsg);
  scrollBottom();
}

function renderMsg(m){
  if(m.type==='system'){
    const el = document.createElement('div');
    el.className='system'; el.textContent=m.text;
    document.getElementById('messages').appendChild(el);
    return;
  }
  const div = document.createElement('div');
  div.className='msg';
  const isOwn = m.id===myId;
  const time = new Date(m.time).toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'});
  div.innerHTML='<span class="name '+(isOwn?'own':'')+'">'+(isOwn?'我':escHtml(m.name))+'</span><span class="text">'+escHtml(m.text)+'</span><span class="time">'+time+'</span>';
  document.getElementById('messages').appendChild(div);
}

function escHtml(s){return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;')}

function scrollBottom(){
  const m=document.getElementById('messages');
  m.scrollTop=m.scrollHeight;
}

function saveMsg(m){
  const msgs = JSON.parse(localStorage.getItem(ROOM+'-msgs') || '[]');
  msgs.push(m);
  if(msgs.length>200) msgs.splice(0,msgs.length-200);
  localStorage.setItem(ROOM+'-msgs', JSON.stringify(msgs));
}

function sendMsg(){
  const text = document.getElementById('message').value.trim();
  const name = document.getElementById('username-in').value.trim() || myName;
  if(!text) return;
  const msg = {type:'msg', name, text, id:myId, time:Date.now()};
  CHANNEL.postMessage(msg);
  renderMsg(msg);
  saveMsg(msg);
  scrollBottom();
  document.getElementById('message').value='';
}

CHANNEL.onmessage = e=>{
  const m=e.data;
  if(m.id===myId) return;
  if(m.type==='join'){
    renderMsg({type:'system', text:m.name+' 加入了聊天室'});
    saveMsg({type:'system', text:m.name+' 加入了聊天室'});
  } else if(m.type==='msg'){
    renderMsg(m);
    saveMsg(m);
    scrollBottom();
  }
};

if(myName){
  document.getElementById('login-name').value=myName;
  enterChat();
}
</script>
</body>
</html>
扫码访问