Files
nodecrypt/client/index.html
T

154 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NodeCrypt</title>
<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/body.css">
<link rel="stylesheet" href="css/phone.css">
<link rel="stylesheet" href="css/form-animation.css">
<link rel="icon" type="image/svg+xml" href="assets/favicon.svg">
<meta name="description" content="NodeCrypt - 真正的端到端加密聊天系统,无数据库,所有消息本地加密,服务器仅做加密数据中转,支持 Cloudflare Workers、Docker、自托管和本地开发。">
<meta name="keywords" content="端到端加密, 安全, 聊天, WebSocket, Cloudflare Workers, JavaScript, E2EE, 匿名通信, AES, ECDH, RSA, ChaCha20, 安全, 开源, NodeCrypt, shuaiplus">
<meta name="author" content="shuaiplus">
<meta property="og:title" content="NodeCrypt - 端到端加密聊天系统">
<meta property="og:description" content="NodeCrypt 是一个零知识、端到端加密的开源聊天系统,所有加密解密均在客户端本地完成,服务器无法获取明文。支持多平台部署,安全、匿名、无历史消息。">
<meta property="og:type" content="website">
<meta property="og:url" content="https://github.com/shuaiplus/NodeCrypt">
<meta property="og:image" content="https://crypt.works/client/assets/favicon.svg">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="NodeCrypt - 端到端加密聊天系统">
<meta name="twitter:description" content="NodeCrypt 是一个零知识、端到端加密的开源聊天系统,所有加密解密均在客户端本地完成,服务器无法获取明文。">
<meta name="twitter:image" content="https://crypt.works/client/assets/favicon.svg">
<meta name="google-site-verification" content="2KGYZcUDyYzGVeYAQ9mMRUGcTiMyZqFF6D7232SyGgw" />
<style>
/* 添加一个预加载样式,避免闪烁 */
.preload * {
-webkit-transition: none !important;
-moz-transition: none !important;
-ms-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
</style>
</head>
<body class="preload"> <div class="login-container" id="login-container">
<!-- 翻转卡片容器 -->
<div class="flip-card" id="flip-card">
<div class="flip-card-inner">
<!-- 卡片正面 - 登录表单 -->
<div class="flip-card-front">
<!-- 帮助按钮 -->
<button class="help-btn" id="help-btn" type="button" title="使用说明">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<circle cx="12" cy="17" r="1" fill="currentColor"/>
</svg>
</button>
<h1 id="login-title"></h1>
<form id="login-form">
<!-- 登录表单内容将由JavaScript动态生成 -->
<!-- Login form content will be dynamically generated by JavaScript -->
</form>
</div>
<!-- 卡片背面 - 使用说明 --> <div class="flip-card-back">
<button class="help-btn back-btn" id="back-btn" type="button" title="返回登录">
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<h2>使用说明</h2>
</div>
</div>
</div>
</div>
</div><div class="container" id="chat-container" style="display:none;">
<div class="mobile-sidebar-mask" id="mobile-sidebar-mask"></div>
<div class="mobile-rightbar-mask" id="mobile-rightbar-mask"></div>
<!-- Settings panel as a sidebar replacement -->
<div class="settings-sidebar" id="settings-sidebar" style="display:none;"> <div class="settings-header"> <button class="settings-back-btn" id="settings-back-btn" title="" aria-label="">
<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15 18L9 12L15 6" stroke="#808080" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button><h2 class="settings-title" id="settings-title"></h2>
</div>
<div class="settings-content" id="settings-content">
<!-- Settings content will be populated by JavaScript -->
</div>
</div>
<div class="sidebar" id="sidebar">
<div class="sidebar-user"> <span class="avatar" id="sidebar-user-avatar"></span> <span class="sidebar-username" id="sidebar-username"></span> <button class="settings-btn" id="settings-btn" title="" aria-label=""> <svg width="30px" height="30px" viewBox="0 0 24 24" fill="none"
xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M10.65 3L9.93163 3.53449L9.32754 5.54812L7.47651 4.55141L6.5906 4.68143L4.68141 6.59062L4.55139 7.47652L5.5481 9.32755L3.53449 9.93163L3 10.65V13.35L3.53449 14.0684L5.54811 14.6725L4.55142 16.5235L4.68144 17.4094L6.59063 19.3186L7.47653 19.4486L9.32754 18.4519L9.93163 20.4655L10.65 21H13.35L14.0684 20.4655L14.6725 18.4519L16.5235 19.4486L17.4094 19.3185L19.3186 17.4094L19.4486 16.5235L18.4519 14.6724L20.4655 14.0684L21 13.35V10.65L20.4655 9.93163L18.4519 9.32754L19.4486 7.47654L19.3186 6.59063L17.4094 4.68144L16.5235 4.55142L14.6725 5.54812L14.0684 3.53449L13.35 3H10.65ZM10.4692 6.96284L11.208 4.5H12.792L13.5308 6.96284L13.8753 7.0946C13.9654 7.12908 14.0543 7.16597 14.142 7.2052L14.4789 7.35598L16.7433 6.13668L17.8633 7.25671L16.644 9.52111L16.7948 9.85803C16.834 9.9457 16.8709 10.0346 16.9054 10.1247L17.0372 10.4692L19.5 11.208V12.792L17.0372 13.5308L16.9054 13.8753C16.8709 13.9654 16.834 14.0543 16.7948 14.1419L16.644 14.4789L17.8633 16.7433L16.7433 17.8633L14.4789 16.644L14.142 16.7948C14.0543 16.834 13.9654 16.8709 13.8753 16.9054L13.5308 17.0372L12.792 19.5H11.208L10.4692 17.0372L10.1247 16.9054C10.0346 16.8709 9.94569 16.834 9.85803 16.7948L9.52111 16.644L7.25671 17.8633L6.13668 16.7433L7.35597 14.4789L7.2052 14.142C7.16597 14.0543 7.12908 13.9654 7.0946 13.8753L6.96284 13.5308L4.5 12.792L4.5 11.208L6.96284 10.4692L7.0946 10.1247C7.12907 10.0346 7.16596 9.94571 7.20519 9.85805L7.35596 9.52113L6.13666 7.2567L7.25668 6.13667L9.5211 7.35598L9.85803 7.2052C9.9457 7.16597 10.0346 7.12908 10.1247 7.0946L10.4692 6.96284ZM14.25 12C14.25 13.2426 13.2426 14.25 12 14.25C10.7574 14.25 9.75 13.2426 9.75 12C9.75 10.7574 10.7574 9.75 12 9.75C13.2426 9.75 14.25 10.7574 14.25 12ZM15.75 12C15.75 14.0711 14.0711 15.75 12 15.75C9.92893 15.75 8.25 14.0711 8.25 12C8.25 9.92893 9.92893 8.25 12 8.25C14.0711 8.25 15.75 9.92893 15.75 12Z"
fill="#808080"></path>
</g>
</svg> </button> </div> <div class="join-room"> <svg class="MuiSvgIcon-root icon-22-middle" focusable="false" viewBox="0 0 24 24" aria-hidden="true">
<path d="M21 3.01H3c-1.1 0-2 .9-2 2V9h2V4.99h18v14.03H3V15H1v4.01c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98v-14c0-1.11-.9-2-2-2zM11 16l4-4-4-4v3H1v2h10v3z"></path>
</svg> <span id="join-room-text"></span> </div>
<div class="rooms" id="room-list"> </div>
</div>
<div class="main">
<div class="main-header" id="main-header"> </div>
<div class="chat-area" id="chat-area"> </div>
<div class="chat-input-area">
<div class="rows-wrapper chat-input-wrapper chat-input-main-wrapper chat-rows-wrapper"> <div class="new-message-wrapper rows-wrapper-row" data-offset="commands"> <button class="chat-emoji-btn" type="button" title=""> <svg width="30px" height="30px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M19.5 12C19.5 16.1421 16.1421 19.5 12 19.5C7.85786 19.5 4.5 16.1421 4.5 12C4.5 7.85786 7.85786 4.5 12 4.5C16.1421 4.5 19.5 7.85786 19.5 12ZM21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12ZM9.375 10.5C9.99632 10.5 10.5 9.99632 10.5 9.375C10.5 8.75368 9.99632 8.25 9.375 8.25C8.75368 8.25 8.25 8.75368 8.25 9.375C8.25 9.99632 8.75368 10.5 9.375 10.5ZM15.75 9.375C15.75 9.99632 15.2463 10.5 14.625 10.5C14.0037 10.5 13.5 9.99632 13.5 9.375C13.5 8.75368 14.0037 8.25 14.625 8.25C15.2463 8.25 15.75 8.75368 15.75 9.375ZM12 15C10.1783 15 9 13.8451 9 12.75H7.5C7.5 14.9686 9.67954 16.5 12 16.5C14.3205 16.5 16.5 14.9686 16.5 12.75H15C15 13.8451 13.8217 15 12 15Z"
fill="#808080"></path>
</g>
</svg> </button> <div class="input-message-container">
<div class="input-message-input is-empty scrollable scrollable-y no-scrollbar input-message-input-init" contenteditable="true" dir="auto" tabindex="-1"></div> <span class="input-field-placeholder i18n is-empty"></span>
<div contenteditable="true" tabindex="-1" class="input-message-input is-empty scrollable scrollable-y no-scrollbar input-field-input-fake"></div> <button class="chat-attach-btn chat-attach-btn-abs" type="button" title=""> <svg width="30px" height="30px"
viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M10.6875 3.75C8.96439 3.75 7.5 5.23565 7.5 7.15385L7.5 15.4615C7.5 18.1444 9.55201 20.25 12 20.25C14.448 20.25 16.5 18.1444 16.5 15.4615V7.15385H18V15.4615C18 18.8963 15.351 21.75 12 21.75C8.649 21.75 6 18.8963 6 15.4615L6 7.15385C6 4.48383 8.06137 2.25 10.6875 2.25C13.3136 2.25 15.375 4.48383 15.375 7.15385V15.4615C15.375 17.3669 13.9013 18.9808 12 18.9808C10.0987 18.9808 8.625 17.3669 8.625 15.4615V7.15385H10.125V15.4615C10.125 16.615 11.0018 17.4808 12 17.4808C12.9982 17.4808 13.875 16.615 13.875 15.4615V7.15385C13.875 5.23565 12.4106 3.75 10.6875 3.75Z"
fill="#808080"></path>
</g>
</svg></button>
</div> <input type="file" multiple class="input-hidden">
</div>
</div>
<div class="send-message-btn">
<span class="text">
<svg
viewBox="0 0 16 16"
class="bi bi-send-fill"
height="22"
width="22"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471z"
></path>
</svg>
</span>
</div>
</div>
</div>
<div class="rightbar" id="rightbar">
<div class="rightbar-header"> <div class="rightbar-group">
<div class="group-info">
<div class="title" id="members-title"></div>
<div class="group-desc" id="rightbar-group-desc"></div>
</div>
</div>
</div>
<div class="rightbar-tabs tabs" id="member-tabs"> </div> <div class="members" id="member-list"> </div>
</div> </div> <div class="powered-by">
Powered by <a href="https://github.com/shuaiplus/NodeCrypt" target="_blank" rel="noopener">NodeCrypt</a>
&copy; 2025 by <a href="https://github.com/shuaiplus" target="_blank" rel="noopener">@shuaiplus</a>
</div>
<script type="module" src="./js/main.js"></script>
</body>
</html>