吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 211|回复: 6
收起左侧

[其他原创] 宜省互传-轻松安全快速传文本、传文件 html版

[复制链接]
小鸡眯眼 发表于 2026-1-11 13:42
简单、好用,在不方便的登录各种账号的时候直接访问网页打开即用。
image.png
支持在线聊天、在线传文件

体验地址:
https://diuta.com/chuan3.html
html代码如下,保存就可以,大佬可以继续修复优化下。
[Asm] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>宜省互传-轻松安全快速传文本、传文件 - chuan.diuta.com</title>
    <style>
        /* 基础变量 - 支持深色/浅色模式 */
        :root {
            --primary: #6366f1;
            --primary-light: #a5b4fc;
            --primary-dark: #4f46e5;
            --secondary: #8b5cf6;
            --success: #10b981;
            --danger: #ef4444;
            --warning: #f59e0b;
            --info: #3b82f6;
            
            /* 浅色主题 */
            --bg-color: #f8fafc;
            --surface-color: #ffffff;
            --text-primary: #1e293b;
            --text-secondary: #64748b;
            --text-tertiary: #94a3b8;
            --border-color: #e2e8f0;
            --border-light: #f1f5f9;
            --shadow-color: rgba(15, 23, 42, 0.1);
            
            --radius-sm: 8px;
            --radius: 12px;
            --radius-lg: 16px;
            --radius-xl: 24px;
            
            --shadow-xs: 0 1px 3px 0 var(--shadow-color);
            --shadow-sm: 0 2px 4px 0 var(--shadow-color);
            --shadow: 0 4px 8px 0 var(--shadow-color);
            --shadow-md: 0 6px 12px 0 var(--shadow-color);
            --shadow-lg: 0 10px 20px 0 var(--shadow-color);
            
            --transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
            --transition-slow: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            
            --font-sans: 'Inter', 'SF Pro Display', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
            --font-mono: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', 'Courier New', monospace;
        }

        /* 深色主题 */
        [url=home.php?mod=space&uid=945662]@media[/url] (prefers-color-scheme: dark) {
            :root {
                --bg-color: #0f172a;
                --surface-color: #1e293b;
                --text-primary: #f1f5f9;
                --text-secondary: #cbd5e1;
                --text-tertiary: #94a3b8;
                --border-color: #334155;
                --border-light: #1e293b;
                --shadow-color: rgba(0, 0, 0, 0.3);
            }
        }

        /* 重置样式 */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: var(--font-sans);
            background-color: var(--bg-color);
            color: var(--text-primary);
            line-height: 1.5;
            font-weight: 400;
            overflow-x: hidden;
            transition: var(--transition-slow);
        }

        /* 滚动条样式 */
        ::-webkit-scrollbar {
            width: 8px;
            height: 8px;
        }

        ::-webkit-scrollbar-track {
            background: transparent;
        }

        ::-webkit-scrollbar-thumb {
            background: var(--border-color);
            border-radius: 4px;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: var(--text-tertiary);
        }

        /* 应用容器 */
        .app-container {
            min-height: 100vh;
            display: flex;
            flex-direction: column;
        }

        @media (min-width: 769px) {
            .app-container {
                max-width: 1400px;
                margin: 0 auto;
                padding: 24px;
            }
        }

        /* 头部样式 */
        .app-header {
            padding: 24px 0;
            border-bottom: 1px solid var(--border-color);
            margin-bottom: 24px;
            position: relative;
        }

        .header-content {
            display: flex;
            flex-direction: column;
            gap: 16px;
        }

        @media (min-width: 769px) {
            .header-content {
                flex-direction: row;
                justify-content: space-between;
                align-items: center;
            }
        }

        .app-title {
            font-size: 2rem;
            font-weight: 700;
            background: linear-gradient(135deg, var(--primary), var(--secondary));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
            display: flex;
            align-items: center;
            gap: 12px;
            letter-spacing: -0.025em;
        }

        .app-title i {
            font-size: 1.8rem;
            background: linear-gradient(135deg, var(--primary), var(--secondary));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .app-subtitle {
            color: var(--text-secondary);
            font-size: 1rem;
            font-weight: 400;
            max-width: 600px;
        }

        /* 连接状态指示器 */
        .connection-status {
            display: inline-flex;
            align-items: center;
            gap: 12px;
            padding: 12px 20px;
            background: var(--surface-color);
            border-radius: var(--radius-lg);
            box-shadow: var(--shadow-sm);
            border: 1px solid var(--border-color);
            transition: var(--transition);
        }

        .connection-status:hover {
            box-shadow: var(--shadow);
        }

        .status-dot {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: var(--danger);
            position: relative;
        }

        .status-dot.connected {
            background: var(--success);
            box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.2);
        }

        .status-dot.connecting {
            background: var(--warning);
            animation: pulse 1.5s infinite;
        }

        @keyframes pulse {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.5; }
        }

        /* 主内容区 */
        .main-content {
            flex: 1;
            padding: 0 16px 24px;
            display: flex;
            flex-direction: column;
            gap: 24px;
        }

        /* PC端布局 */
        @media (min-width: 769px) {
            .main-content {
                display: grid;
                grid-template-columns: repeat(2, 1fr);
                grid-template-rows: auto auto;
                grid-template-areas: 
                    "connection chat"
                    "files transfers";
                gap: 24px;
                padding: 0 0 24px;
            }
            
            .connection-panel {
                grid-area: connection;
            }
            
            .chat-panel {
                grid-area: chat;
            }
            
            .file-panel {
                grid-area: files;
            }
            
            .transfer-panel {
                grid-area: transfers;
            }
        }

        /* 面板通用样式 */
        .panel {
            background: var(--surface-color);
            border-radius: var(--radius-lg);
            padding: 24px;
            box-shadow: var(--shadow-sm);
            border: 1px solid var(--border-color);
            display: flex;
            flex-direction: column;
            transition: var(--transition-slow);
            position: relative;
            overflow: hidden;
        }

        .panel:hover {
            box-shadow: var(--shadow);
        }

        .panel-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            margin-bottom: 24px;
            padding-bottom: 16px;
            border-bottom: 1px solid var(--border-color);
        }

        .panel-title {
            font-size: 1.25rem;
            font-weight: 600;
            color: var(--text-primary);
            display: flex;
            align-items: center;
            gap: 12px;
        }

        .panel-title i {
            color: var(--primary);
            font-size: 1.1rem;
        }

        .panel-actions {
            display: flex;
            gap: 8px;
        }

        .panel-content {
            flex: 1;
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }

        /* 连接管理面板 */
        .my-id-section {
            background: linear-gradient(135deg, var(--bg-color), var(--surface-color));
            border-radius: var(--radius);
            padding: 20px;
            margin-bottom: 24px;
            border: 1px solid var(--border-color);
        }

        .my-id-label {
            font-size: 0.9rem;
            color: var(--text-secondary);
            margin-bottom: 12px;
            font-weight: 500;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .my-id-value {
            font-family: var(--font-mono);
            font-size: 1rem;
            font-weight: 600;
            color: var(--primary);
            word-break: break-all;
            padding: 16px;
            background: var(--bg-color);
            border-radius: var(--radius-sm);
            border: 1px solid var(--border-color);
            margin-bottom: 16px;
            line-height: 1.4;
        }

        /* 连接表单 */
        .connect-form {
            margin-top: 16px;
        }

        .form-group {
            margin-bottom: 20px;
        }

        .form-label {
            display: block;
            margin-bottom: 8px;
            font-weight: 500;
            color: var(--text-primary);
            font-size: 0.95rem;
        }

        .form-input {
            width: 100%;
            padding: 14px 16px;
            border: 1px solid var(--border-color);
            border-radius: var(--radius);
            font-size: 1rem;
            font-family: var(--font-sans);
            transition: var(--transition);
            background: var(--surface-color);
            color: var(--text-primary);
        }

        .form-input:focus {
            border-color: var(--primary);
            outline: none;
            box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
        }

        /* 已连接设备列表 */
        .connected-devices {
            margin-top: 24px;
            flex: 1;
            display: flex;
            flex-direction: column;
        }

        .devices-title {
            font-size: 1rem;
            font-weight: 600;
            margin-bottom: 16px;
            color: var(--text-primary);
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .devices-list {
            flex: 1;
            overflow-y: auto;
            max-height: 300px;
            background: var(--bg-color);
            border-radius: var(--radius);
            padding: 16px;
            border: 1px solid var(--border-color);
        }

        .device-item {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 16px;
            background: var(--surface-color);
            border-radius: var(--radius-sm);
            margin-bottom: 10px;
            border: 1px solid var(--border-color);
            transition: var(--transition);
        }

        .device-item:hover {
            border-color: var(--primary);
            box-shadow: var(--shadow-xs);
        }

        .device-info {
            display: flex;
            align-items: center;
            gap: 12px;
            flex: 1;
        }

        .device-avatar {
            width: 40px;
            height: 40px;
            border-radius: 50%;
            background: linear-gradient(135deg, var(--primary), var(--secondary));
            display: flex;
            align-items: center;
            justify-content: center;
            color: white;
            font-weight: 600;
            font-size: 0.9rem;
        }

        .device-details {
            flex: 1;
        }

        .device-name {
            font-weight: 600;
            margin-bottom: 4px;
        }

        .device-id {
            font-size: 0.85rem;
            color: var(--text-secondary);
            font-family: var(--font-mono);
        }

        .device-status {
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .status-indicator {
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background: var(--success);
        }

        .status-indicator.disconnected {
            background: var(--danger);
        }

        /* 聊天面板 */
        .chat-panel {
            display: flex;
            flex-direction: column;
            min-height: 500px;
        }

        @media (max-width: 768px) {
            .chat-panel {
                min-height: 400px;
            }
        }

        .chat-messages {
            flex: 1;
            overflow-y: auto;
            padding: 20px;
            background: var(--bg-color);
            border-radius: var(--radius);
            margin-bottom: 20px;
            border: 1px solid var(--border-color);
            display: flex;
            flex-direction: column;
            gap: 16px;
        }

        .message {
            max-width: 85%;
            animation: messageIn 0.3s ease;
        }

        @keyframes messageIn {
            from {
                opacity: 0;
                transform: translateY(10px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        .message.received {
            align-self: flex-start;
        }

        .message.sent {
            align-self: flex-end;
        }

        .message-bubble {
            padding: 14px 18px;
            border-radius: 18px;
            position: relative;
            word-wrap: break-word;
            line-height: 1.5;
        }

        .message.received .message-bubble {
            background: var(--surface-color);
            border: 1px solid var(--border-color);
            border-bottom-left-radius: 6px;
        }

        .message.sent .message-bubble {
            background: linear-gradient(135deg, var(--primary), var(--secondary));
            color: white;
            border-bottom-right-radius: 6px;
        }

        .message-meta {
            display: flex;
            justify-content: space-between;
            margin-top: 6px;
            font-size: 0.8rem;
            opacity: 0.7;
        }

        .message-sender {
            font-weight: 500;
        }

        .chat-input-area {
            display: flex;
            gap: 12px;
            flex-shrink: 0;
        }

        .chat-input {
            flex: 1;
            padding: 16px;
            border: 1px solid var(--border-color);
            border-radius: var(--radius);
            font-size: 1rem;
            resize: none;
            height: 60px;
            font-family: var(--font-sans);
            transition: var(--transition);
            background: var(--surface-color);
            color: var(--text-primary);
        }

        .chat-input:focus {
            border-color: var(--primary);
            outline: none;
            box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
        }

        /* 文件传输面板 */
        .file-drop-zone {
            border: 2px dashed var(--border-color);
            border-radius: var(--radius);
            padding: 40px 20px;
            text-align: center;
            cursor: pointer;
            transition: var(--transition);
            background: var(--surface-color);
            margin-bottom: 24px;
            position: relative;
            overflow: hidden;
        }

        .file-drop-zone:hover {
            border-color: var(--primary);
            background: rgba(99, 102, 241, 0.05);
        }

        .file-drop-zone.dragover {
            background: rgba(99, 102, 241, 0.1);
            border-color: var(--primary);
            transform: scale(1.02);
        }

        .file-drop-zone-icon {
            font-size: 3rem;
            color: var(--primary);
            margin-bottom: 16px;
            opacity: 0.8;
        }

        .file-input {
            display: none;
        }

        .files-list {
            flex: 1;
            overflow-y: auto;
            max-height: 300px;
        }

        .file-item {
            background: var(--surface-color);
            padding: 16px;
            border-radius: var(--radius-sm);
            margin-bottom: 12px;
            display: flex;
            align-items: center;
            gap: 16px;
            border: 1px solid var(--border-color);
            transition: var(--transition);
        }

        .file-item:hover {
            border-color: var(--primary);
            box-shadow: var(--shadow-xs);
        }

        .file-icon {
            font-size: 1.8rem;
            color: var(--primary);
            width: 48px;
            height: 48px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: var(--bg-color);
            border-radius: 12px;
        }

        .file-info {
            flex: 1;
            min-width: 0;
        }

        .file-name {
            font-weight: 600;
            margin-bottom: 6px;
            word-break: break-all;
        }

        .file-details {
            display: flex;
            align-items: center;
            gap: 12px;
            font-size: 0.9rem;
            color: var(--text-secondary);
        }

        .file-progress {
            width: 100%;
            height: 6px;
            background: var(--bg-color);
            border-radius: 3px;
            margin-top: 12px;
            overflow: hidden;
        }

        .file-progress-bar {
            height: 100%;
            background: linear-gradient(90deg, var(--success), var(--primary));
            width: 0%;
            transition: width 0.3s ease;
            border-radius: 3px;
        }

        /* 传输列表面板 */
        .transfers-list {
            flex: 1;
            overflow-y: auto;
            max-height: 400px;
        }

        .transfer-item {
            background: var(--surface-color);
            padding: 16px;
            border-radius: var(--radius-sm);
            margin-bottom: 12px;
            display: flex;
            align-items: center;
            gap: 16px;
            border: 1px solid var(--border-color);
            transition: var(--transition);
        }

        .transfer-item:hover {
            border-color: var(--primary);
            box-shadow: var(--shadow-xs);
        }

        .transfer-icon {
            font-size: 1.8rem;
            width: 48px;
            height: 48px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 12px;
        }

        .transfer-icon.sending {
            color: var(--warning);
            background: rgba(245, 158, 11, 0.1);
        }

        .transfer-icon.receiving {
            color: var(--info);
            background: rgba(59, 130, 246, 0.1);
        }

        .transfer-icon.completed {
            color: var(--success);
            background: rgba(16, 185, 129, 0.1);
        }

        .transfer-info {
            flex: 1;
            min-width: 0;
        }

        .transfer-name {
            font-weight: 600;
            margin-bottom: 6px;
            word-break: break-all;
        }

        .transfer-details {
            display: flex;
            justify-content: space-between;
            align-items: center;
            flex-wrap: wrap;
            gap: 12px;
            font-size: 0.9rem;
            color: var(--text-secondary);
        }

        .transfer-status {
            padding: 4px 12px;
            border-radius: 20px;
            font-size: 0.8rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .transfer-status.sending {
            background: rgba(245, 158, 11, 0.1);
            color: var(--warning);
        }

        .transfer-status.receiving {
            background: rgba(59, 130, 246, 0.1);
            color: var(--info);
        }

        .transfer-status.completed {
            background: rgba(16, 185, 129, 0.1);
            color: var(--success);
        }

        .transfer-status.failed {
            background: rgba(239, 68, 68, 0.1);
            color: var(--danger);
        }

        .transfer-progress {
            width: 100%;
            height: 6px;
            background: var(--bg-color);
            border-radius: 3px;
            margin-top: 12px;
            overflow: hidden;
        }

        .transfer-progress-bar {
            height: 100%;
            background: linear-gradient(90deg, var(--success), var(--primary));
            width: 0%;
            transition: width 0.3s ease;
            border-radius: 3px;
        }

        /* 按钮样式 */
        .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 10px;
            padding: 12px 24px;
            border: none;
            border-radius: var(--radius);
            font-size: 0.95rem;
            font-weight: 600;
            cursor: pointer;
            transition: var(--transition);
            text-decoration: none;
            white-space: nowrap;
            font-family: var(--font-sans);
            position: relative;
            overflow: hidden;
        }

        .btn::after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 5px;
            height: 5px;
            background: rgba(255, 255, 255, 0.5);
            opacity: 0;
            border-radius: 100%;
            transform: scale(1, 1) translate(-50%);
            transform-origin: 50% 50%;
        }

        .btn:active::after {
            animation: ripple 0.6s ease-out;
        }

        @keyframes ripple {
            0% {
                transform: scale(0, 0);
                opacity: 0.5;
            }
            100% {
                transform: scale(20, 20);
                opacity: 0;
            }
        }

        .btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
            transform: none !important;
        }

        .btn-primary {
            background: linear-gradient(135deg, var(--primary), var(--secondary));
            color: white;
            border: none;
        }

        .btn-primary:hover:not(:disabled) {
            transform: translateY(-2px);
            box-shadow: var(--shadow-lg);
        }

        .btn-success {
            background: linear-gradient(135deg, var(--success), #34d399);
            color: white;
            border: none;
        }

        .btn-success:hover:not(:disabled) {
            transform: translateY(-2px);
            box-shadow: 0 6px 12px -1px rgba(16, 185, 129, 0.3);
        }

        .btn-outline {
            background: transparent;
            color: var(--primary);
            border: 1px solid var(--border-color);
        }

        .btn-outline:hover:not(:disabled) {
            background: rgba(99, 102, 241, 0.1);
            border-color: var(--primary);
            transform: translateY(-2px);
            box-shadow: var(--shadow);
        }

        .btn-sm {
            padding: 8px 16px;
            font-size: 0.9rem;
        }

        .btn-lg {
            padding: 16px 32px;
            font-size: 1.1rem;
        }

        .btn-block {
            width: 100%;
        }

        .btn-icon {
            padding: 10px;
            border-radius: 50%;
            width: 44px;
            height: 44px;
        }

        .btn-icon-sm {
            padding: 8px;
            border-radius: 50%;
            width: 36px;
            height: 36px;
            font-size: 0.9rem;
        }

        /* 移动端底部导航 */
        .mobile-nav {
            position: fixed;
            bottom: 0;
            left: 0;
            right: 0;
            background: var(--surface-color);
            display: flex;
            justify-content: space-around;
            padding: 12px 0;
            box-shadow: 0 -2px 20px var(--shadow-color);
            z-index: 1000;
            border-top: 1px solid var(--border-color);
            display: none;
        }

        @media (max-width: 768px) {
            .mobile-nav {
                display: flex;
            }
            
            .main-content {
                padding-bottom: 80px;
            }
        }

        .nav-item {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 6px;
            background: none;
            border: none;
            color: var(--text-secondary);
            font-size: 0.8rem;
            cursor: pointer;
            transition: var(--transition);
            padding: 8px 0;
            flex: 1;
            border-radius: 8px;
            margin: 0 4px;
        }

        .nav-item.active {
            color: var(--primary);
            background: rgba(99, 102, 241, 0.1);
        }

        .nav-item i {
            font-size: 1.4rem;
        }

        /* 通知系统 */
        .notifications {
            position: fixed;
            top: 24px;
            right: 24px;
            z-index: 2000;
            max-width: 400px;
            width: 100%;
        }

        .notification {
            background: var(--surface-color);
            border-radius: var(--radius);
            padding: 16px;
            margin-bottom: 12px;
            box-shadow: var(--shadow-lg);
            display: flex;
            align-items: flex-start;
            gap: 12px;
            animation: slideIn 0.3s ease;
            border-left: 4px solid var(--primary);
            position: relative;
            overflow: hidden;
            transform-origin: top right;
            border: 1px solid var(--border-color);
        }

        @keyframes slideIn {
            from {
                transform: translateX(100%);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }

        .notification.success {
            border-left-color: var(--success);
        }

        .notification.error {
            border-left-color: var(--danger);
        }

        .notification.warning {
            border-left-color: var(--warning);
        }

        .notification.info {
            border-left-color: var(--info);
        }

        .notification-icon {
            font-size: 1.2rem;
            flex-shrink: 0;
            margin-top: 2px;
        }

        .notification-content {
            flex: 1;
        }

        .notification-title {
            font-weight: 600;
            margin-bottom: 4px;
            font-size: 0.95rem;
        }

        .notification-message {
            font-size: 0.9rem;
            color: var(--text-secondary);
            line-height: 1.4;
        }

        .notification-close {
            background: none;
            border: none;
            color: var(--text-tertiary);
            cursor: pointer;
            font-size: 1.1rem;
            padding: 4px;
            border-radius: 50%;
            transition: var(--transition);
            flex-shrink: 0;
        }

        .notification-close:hover {
            background: var(--bg-color);
            color: var(--text-primary);
        }

        /* 二维码弹窗模态框 - 重新设计 */
        .modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(15, 23, 42, 0.7);
            display: flex;
            align-items: center;
            justify-content: center;
            z-index: 3000;
            padding: 20px;
            opacity: 0;
            visibility: hidden;
            transition: var(--transition-slow);
            backdrop-filter: blur(8px);
        }

        .modal-overlay.active {
            opacity: 1;
            visibility: visible;
        }

        .modal-container {
            background: var(--surface-color);
            border-radius: var(--radius-xl);
            padding: 0;
            max-width: 800px;
            width: 100%;
            max-height: 90vh;
            overflow: hidden;
            position: relative;
            transform: translateY(20px) scale(0.95);
            transition: transform 0.3s ease;
            box-shadow: var(--shadow-xl);
            border: 1px solid var(--border-color);
        }

        .modal-overlay.active .modal-container {
            transform: translateY(0) scale(1);
        }

        .modal-header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 24px 32px;
            border-bottom: 1px solid var(--border-color);
        }

        .modal-title {
            font-size: 1.5rem;
            font-weight: 700;
            color: var(--text-primary);
            display: flex;
            align-items: center;
            gap: 12px;
        }

        .modal-close {
            background: none;
            border: none;
            font-size: 1.8rem;
            color: var(--text-tertiary);
            cursor: pointer;
            padding: 4px;
            border-radius: 50%;
            transition: var(--transition);
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .modal-close:hover {
            background: var(--bg-color);
            color: var(--text-primary);
        }

        /* 二维码弹窗内容 */
        .qr-modal-content {
            display: flex;
            flex-direction: column;
            height: 100%;
        }

        .qr-tabs {
            display: flex;
            background: var(--bg-color);
            border-bottom: 1px solid var(--border-color);
        }

        .qr-tab {
            flex: 1;
            padding: 20px;
            background: none;
            border: none;
            border-bottom: 3px solid transparent;
            font-size: 1rem;
            font-weight: 600;
            color: var(--text-secondary);
            cursor: pointer;
            transition: var(--transition);
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 8px;
        }

        .qr-tab:hover {
            background: rgba(99, 102, 241, 0.05);
            color: var(--primary);
        }

        .qr-tab.active {
            color: var(--primary);
            border-bottom-color: var(--primary);
            background: rgba(99, 102, 241, 0.1);
        }

        .qr-tab i {
            font-size: 1.5rem;
        }

        .qr-tab-content {
            display: none;
            padding: 32px;
            flex: 1;
            overflow-y: auto;
        }

        .qr-tab-content.active {
            display: block;
        }

        /* 生成二维码选项卡 */
        .qr-generate-container {
            text-align: center;
        }

        .qr-header {
            text-align: center;
            margin-bottom: 24px;
        }

        .qr-title {
            font-size: 1.25rem;
            font-weight: 600;
            margin-bottom: 8px;
            color: var(--text-primary);
        }

        .qr-subtitle {
            color: var(--text-secondary);
            font-size: 0.95rem;
            line-height: 1.5;
            max-width: 500px;
            margin: 0 auto;
        }

        .qr-code-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 24px;
            margin: 32px 0;
        }

        .qr-display {
            background: white;
            padding: 20px;
            border-radius: var(--radius);
            box-shadow: var(--shadow);
            border: 1px solid var(--border-color);
            display: inline-block;
        }

        .qr-actions {
            display: flex;
            gap: 12px;
            justify-content: center;
            margin-top: 24px;
        }

        .qr-share-options {
            display: flex;
            flex-direction: column;
            gap: 12px;
            margin-top: 24px;
            text-align: left;
        }

        .qr-share-option {
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px 16px;
            border: 1px solid var(--border-color);
            border-radius: var(--radius);
            cursor: pointer;
            transition: var(--transition);
        }

        .qr-share-option:hover {
            background: var(--bg-color);
            border-color: var(--primary);
        }

        .qr-share-option i {
            font-size: 1.2rem;
            color: var(--primary);
        }

        .qr-share-option div {
            flex: 1;
        }

        .qr-share-option h4 {
            font-size: 0.95rem;
            font-weight: 600;
            margin-bottom: 4px;
            color: var(--text-primary);
        }

        .qr-share-option p {
            font-size: 0.85rem;
            color: var(--text-secondary);
        }

        /* 扫描二维码选项卡 */
        .qr-scan-container {
            text-align: center;
        }

        .scan-preview-container {
            width: 100%;
            height: 300px;
            background: var(--bg-color);
            border-radius: var(--radius);
            margin: 0 auto 24px;
            position: relative;
            overflow: hidden;
            border: 1px solid var(--border-color);
        }

        .scan-preview {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .scan-overlay {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: rgba(15, 23, 42, 0.7);
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .scan-frame {
            width: 200px;
            height: 200px;
            border: 2px solid var(--primary);
            border-radius: var(--radius);
            position: relative;
            box-shadow: 0 0 0 1000px rgba(0, 0, 0, 0.5);
        }

        .scan-frame::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 4px;
            background: var(--primary);
            border-radius: 4px;
            animation: scanLine 2s infinite linear;
        }

        @keyframes scanLine {
            0% {
                top: 0;
            }
            100% {
                top: 100%;
            }
        }

        .scan-frame::after {
            content: '请将二维码放入框内';
            position: absolute;
            bottom: -40px;
            left: 0;
            right: 0;
            text-align: center;
            color: white;
            font-size: 0.9rem;
            font-weight: 500;
        }

        .scan-controls {
            display: flex;
            gap: 12px;
            justify-content: center;
            margin-top: 24px;
        }

        .scan-message {
            margin-top: 16px;
            padding: 12px 16px;
            background: rgba(99, 102, 241, 0.1);
            border-radius: var(--radius);
            color: var(--primary);
            font-size: 0.9rem;
            display: none;
            border: 1px solid rgba(99, 102, 241, 0.2);
        }

        .scan-message.active {
            display: block;
            animation: fadeIn 0.3s ease;
        }

        .manual-input-section {
            margin-top: 32px;
            padding-top: 24px;
            border-top: 1px solid var(--border-color);
        }

        /* 移动端选项卡内容 */
        .mobile-tabs {
            display: none;
        }

        @media (max-width: 768px) {
            .mobile-tabs {
                display: block;
            }
            
            .desktop-layout {
                display: none;
            }
            
            .mobile-tab-content {
                display: none;
            }
            
            .mobile-tab-content.active {
                display: block;
            }
        }

        /* 空状态 */
        .empty-state {
            text-align: center;
            padding: 40px 20px;
            color: var(--text-tertiary);
        }

        .empty-state i {
            font-size: 3rem;
            margin-bottom: 16px;
            opacity: 0.5;
        }

        .empty-state h4 {
            font-size: 1.1rem;
            font-weight: 600;
            margin-bottom: 8px;
            color: var(--text-secondary);
        }

        .empty-state p {
            margin-bottom: 8px;
            line-height: 1.5;
            font-size: 0.95rem;
        }

        /* 文件操作按钮组 */
        .file-actions {
            display: flex;
            gap: 12px;
            margin-top: 24px;
        }

        /* 传输统计 */
        .transfer-stats {
            display: flex;
            justify-content: space-between;
            margin-top: 20px;
            padding-top: 20px;
            border-top: 1px solid var(--border-color);
            font-size: 0.9rem;
            color: var(--text-secondary);
        }

        /* 响应式调整 */
        @media (max-width: 768px) {
            .app-header {
                padding: 16px 16px 24px;
            }
            
            .app-title {
                font-size: 1.5rem;
            }
            
            .main-content {
                padding: 0 16px 24px;
                gap: 20px;
            }
            
            .panel {
                padding: 20px;
            }
            
            .panel-title {
                font-size: 1.1rem;
            }
            
            .modal-container {
                margin: 0 16px;
            }
            
            .qr-tab-content {
                padding: 24px;
            }
            
            .scan-preview-container {
                height: 250px;
            }
            
            .scan-frame {
                width: 180px;
                height: 180px;
            }
        }

        /* 加载动画 */
        .loader {
            display: inline-block;
            width: 40px;
            height: 40px;
            border: 4px solid var(--border-color);
            border-top: 4px solid var(--primary);
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        /* 工具类 */
        .text-center { text-align: center; }
        .mt-1 { margin-top: 4px; }
        .mt-2 { margin-top: 8px; }
        .mt-3 { margin-top: 12px; }
        .mt-4 { margin-top: 16px; }
        .mt-5 { margin-top: 20px; }
        .mb-1 { margin-bottom: 4px; }
        .mb-2 { margin-bottom: 8px; }
        .mb-3 { margin-bottom: 12px; }
        .mb-4 { margin-bottom: 16px; }
        .mb-5 { margin-bottom: 20px; }
        .d-flex { display: flex; }
        .align-items-center { align-items: center; }
        .justify-content-center { justify-content: center; }
        .justify-content-between { justify-content: space-between; }
        .flex-column { flex-direction: column; }
        .gap-1 { gap: 4px; }
        .gap-2 { gap: 8px; }
        .gap-3 { gap: 12px; }
        .gap-4 { gap: 16px; }
        .gap-5 { gap: 20px; }
        .w-100 { width: 100%; }
        .h-100 { height: 100%; }
    </style>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
    <div class="app-container">
        <!-- 头部 -->
        <header class="app-header">
            <div class="header-content">
                <div>
                    <h1 class="app-title">
                        <i class="fas fa-bolt"></i>
                        宜省互传
                    </h1>
                    <p class="app-subtitle">轻松安全快速传文本、传文件</p>
                </div>
                <div class="connection-status">
                    <div class="status-dot" id="status-dot"></div>
                    <span id="status-text">正在连接...</span>
                </div>
            </div>
        </header>

        <!-- 移动端导航 -->
        <nav class="mobile-nav">
            <button class="nav-item active" data-tab="connection">
                <i class="fas fa-link"></i>
                <span>连接</span>
            </button>
            <button class="nav-item" data-tab="chat">
                <i class="fas fa-comments"></i>
                <span>聊天</span>
            </button>
            <button class="nav-item" data-tab="files">
                <i class="fas fa-file-import"></i>
                <span>文件</span>
            </button>
            <button class="nav-item" data-tab="transfers">
                <i class="fas fa-exchange-alt"></i>
                <span>传输</span>
            </button>
        </nav>

        <!-- 主内容区 -->
        <main class="main-content">
            <!-- 连接管理 (桌面版) -->
            <section class="panel connection-panel desktop-layout">
                <div class="panel-header">
                    <h2 class="panel-title">
                        <i class="fas fa-link"></i>
                        连接管理
                    </h2>
                    <div class="panel-actions">
                        <!-- 二维码入口按钮 -->
                        <button class="btn btn-icon-sm btn-outline" id="qr-modal-btn" title="二维码连接">
                            <i class="fas fa-qrcode"></i>
                        </button>
                        <button class="btn btn-sm btn-primary" id="copy-btn">
                            <i class="far fa-copy"></i> 复制ID
                        </button>
                    </div>
                </div>
                <div class="panel-content">
                    <div class="my-id-section">
                        <div class="my-id-label">
                            <i class="fas fa-id-card"></i> 我的设备ID
                        </div>
                        <div class="my-id-value" id="my-id">正在生成设备ID...</div>
                    </div>
                    
                    <!-- 移除了connection-tools部分 -->
                    
                    <div class="connect-form">
                        <div class="form-group">
                            <label class="form-label">手动连接其他设备</label>
                            <div class="d-flex gap-2">
                                <input type="text" 
                                       class="form-input" 
                                       id="peer-id-input" 
                                       placeholder="输入对方设备ID"
                                       autocomplete="off">
                                <button class="btn btn-primary btn-icon" id="connect-btn" title="连接">
                                    <i class="fas fa-plug"></i>
                                </button>
                            </div>
                        </div>
                    </div>
                    
                    <div class="connected-devices">
                        <div class="devices-title">
                            <i class="fas fa-users"></i> 已连接设备 (<span id="connected-count">0</span>)
                        </div>
                        <div class="devices-list" id="devices-list">
                            <div class="empty-state">
                                <i class="fas fa-user-friends"></i>
                                <h4>暂无已连接的设备</h4>
                                <p>连接其他设备后,可以开始聊天和传输文件</p>
                            </div>
                        </div>
                    </div>
                </div>
            </section>

            <!-- 聊天面板 (桌面版) -->
            <section class="panel chat-panel desktop-layout">
                <div class="panel-header">
                    <h2 class="panel-title">
                        <i class="fas fa-comments"></i>
                        实时聊天
                    </h2>
                    <div class="panel-actions">
                        <span class="chat-count" id="chat-count">0 条消息</span>
                        <button class="btn btn-sm btn-outline">
                            <i class="fas fa-trash"></i> 清空
                        </button>
                    </div>
                </div>
                <div class="panel-content">
                    <div class="chat-messages" id="chat-messages">
                        <div class="empty-state">
                            <i class="fas fa-comment-dots"></i>
                            <h4>暂无聊天消息</h4>
                            <p>连接设备后即可开始聊天</p>
                        </div>
                    </div>
                    <div class="chat-input-area">
                        <textarea class="chat-input" 
                                  id="chat-input" 
                                  placeholder="输入消息...按Enter发送,Shift+Enter换行"
                                  rows="2"></textarea>
                        <button class="btn btn-primary btn-icon" id="send-chat-btn">
                            <i class="fas fa-paper-plane"></i>
                        </button>
                    </div>
                </div>
            </section>

            <!-- 文件传输面板 (桌面版) -->
            <section class="panel file-panel desktop-layout">
                <div class="panel-header">
                    <h2 class="panel-title">
                        <i class="fas fa-file-import"></i>
                        文件传输
                    </h2>
                    <div class="panel-actions">
                        <button class="btn btn-sm btn-outline">
                            <i class="fas fa-trash"></i> 清空
                        </button>
                    </div>
                </div>
                <div class="panel-content">
                    <div class="file-drop-zone" id="drop-zone">
                        <div class="file-drop-zone-icon">
                            <i class="fas fa-cloud-upload-alt"></i>
                        </div>
                        <h3>拖放文件到此处</h3>
                        <p>或点击选择文件,支持多选</p>
                        <input type="file" class="file-input" id="file-input" multiple>
                        <p class="qr-instruction">最大支持2GB文件</p>
                    </div>
                    
                    <div class="files-list" id="files-list">
                        <div class="empty-state">
                            <i class="fas fa-file-import"></i>
                            <h4>暂无待传输文件</h4>
                            <p>添加文件并发送给已连接的设备</p>
                        </div>
                    </div>
                    
                    <div class="file-actions">
                        <div class="form-group w-100 mb-0">
                            <select class="form-input" id="send-to-select">
                                <option value="all">发送给所有设备</option>
                            </select>
                        </div>
                        <button class="btn btn-success" id="send-files-btn" disabled>
                            <i class="fas fa-paper-plane"></i> 发送文件
                        </button>
                    </div>
                </div>
            </section>

            <!-- 传输列表面板 (桌面版) -->
            <section class="panel transfer-panel desktop-layout">
                <div class="panel-header">
                    <h2 class="panel-title">
                        <i class="fas fa-exchange-alt"></i>
                        传输列表
                    </h2>
                    <div class="panel-actions">
                        <button class="btn btn-sm btn-outline">
                            <i class="fas fa-sync-alt"></i> 刷新
                        </button>
                    </div>
                </div>
                <div class="panel-content">
                    <div class="transfers-list" id="transfers-list">
                        <div class="empty-state">
                            <i class="fas fa-exchange-alt"></i>
                            <h4>暂无传输任务</h4>
                            <p>文件传输将在此显示进度</p>
                        </div>
                    </div>
                    <div class="transfer-stats">
                        <div>正在传输: <span id="active-transfers">0</span></div>
                        <div>已完成: <span id="completed-transfers">0</span></div>
                        <div>失败: <span id="failed-transfers">0</span></div>
                    </div>
                </div>
            </section>

            <!-- 移动端选项卡内容 -->
            <div class="mobile-tabs">
                <!-- 连接选项卡 -->
                <section class="panel mobile-tab-content active" id="mobile-connection">
                    <div class="panel-content">
                        <div class="my-id-section">
                            <div class="my-id-label">
                                <i class="fas fa-id-card"></i> 我的设备ID
                            </div>
                            <div class="my-id-value" id="mobile-my-id">正在生成设备ID...</div>
                        </div>
                        
                        <!-- 移动端二维码按钮 -->
                        <div style="margin-bottom: 24px;">
                            <button class="btn btn-outline btn-block">
                                <i class="fas fa-qrcode"></i> 二维码连接
                            </button>
                        </div>
                        
                        <div class="connect-form">
                            <div class="form-group">
                                <label class="form-label">手动连接其他设备</label>
                                <div class="d-flex gap-2">
                                    <input type="text" 
                                           class="form-input" 
                                           id="mobile-peer-id-input" 
                                           placeholder="输入对方设备ID"
                                           autocomplete="off">
                                    <button class="btn btn-primary btn-icon" id="mobile-connect-btn" title="连接">
                                        <i class="fas fa-plug"></i>
                                    </button>
                                </div>
                            </div>
                        </div>
                        
                        <div class="connected-devices">
                            <div class="devices-title">
                                <i class="fas fa-users"></i> 已连接设备 (<span id="mobile-connected-count">0</span>)
                            </div>
                            <div class="devices-list" id="mobile-devices-list">
                                <div class="empty-state">
                                    <i class="fas fa-user-friends"></i>
                                    <h4>暂无已连接的设备</h4>
                                    <p>连接其他设备后,可以开始聊天和传输文件</p>
                                </div>
                            </div>
                        </div>
                    </div>
                </section>

                <!-- 聊天选项卡 -->
                <section class="panel mobile-tab-content" id="mobile-chat">
                    <div class="panel-content" style="height: 100%; display: flex; flex-direction: column;">
                        <div class="chat-messages" id="mobile-chat-messages" style="flex: 1;">
                            <div class="empty-state">
                                <i class="fas fa-comment-dots"></i>
                                <h4>暂无聊天消息</h4>
                                <p>连接设备后即可开始聊天</p>
                            </div>
                        </div>
                        <div class="chat-input-area">
                            <textarea class="chat-input" 
                                      id="mobile-chat-input" 
                                      placeholder="输入消息..."
                                      rows="2"></textarea>
                            <button class="btn btn-primary btn-icon" id="mobile-send-chat-btn">
                                <i class="fas fa-paper-plane"></i>
                            </button>
                        </div>
                    </div>
                </section>

                <!-- 文件选项卡 -->
                <section class="panel mobile-tab-content" id="mobile-files">
                    <div class="panel-content">
                        <div class="file-drop-zone" id="mobile-drop-zone">
                            <div class="file-drop-zone-icon">
                                <i class="fas fa-cloud-upload-alt"></i>
                            </div>
                            <h3>选择文件</h3>
                            <p>点击上传文件,支持多选</p>
                            <input type="file" class="file-input" id="mobile-file-input" multiple>
                            <p class="qr-instruction">最大支持2GB文件</p>
                        </div>
                        
                        <div class="files-list" id="mobile-files-list">
                            <div class="empty-state">
                                <i class="fas fa-file-import"></i>
                                <h4>暂无待传输文件</h4>
                                <p>添加文件并发送给已连接的设备</p>
                            </div>
                        </div>
                        
                        <div class="file-actions">
                            <div class="form-group w-100 mb-0">
                                <select class="form-input" id="mobile-send-to-select">
                                    <option value="all">发送给所有设备</option>
                                </select>
                            </div>
                            <button class="btn btn-success btn-block" id="mobile-send-files-btn" disabled>
                                <i class="fas fa-paper-plane"></i> 发送文件
                            </button>
                        </div>
                    </div>
                </section>

                <!-- 传输列表选项卡 -->
                <section class="panel mobile-tab-content" id="mobile-transfers">
                    <div class="panel-content">
                        <div class="transfers-list" id="mobile-transfers-list" style="flex: 1;">
                            <div class="empty-state">
                                <i class="fas fa-exchange-alt"></i>
                                <h4>暂无传输任务</h4>
                                <p>文件传输将在此显示进度</p>
                            </div>
                        </div>
                        <div class="transfer-stats">
                            <div>正在传输: <span id="mobile-active-transfers">0</span></div>
                            <div>已完成: <span id="mobile-completed-transfers">0</span></div>
                            <div>失败: <span id="mobile-failed-transfers">0</span></div>
                        </div>
                    </div>
                </section>
            </div>
        </main>
    </div>

    <!-- 通知区域 -->
    <div class="notifications" id="notifications"></div>

    <!-- 二维码连接弹窗 -->
    <div class="modal-overlay" id="qr-connect-modal">
        <div class="modal-container">
            <div class="modal-header">
                <div class="modal-title">
                    <i class="fas fa-qrcode"></i> 二维码连接
                </div>
                <button class="modal-close">×</button>
            </div>
            <div class="qr-modal-content">
                <div class="qr-tabs">
                    <button class="qr-tab active">
                        <i class="fas fa-qrcode"></i>
                        <span>生成二维码</span>
                    </button>
                    <button class="qr-tab">
                        <i class="fas fa-camera"></i>
                        <span>扫描二维码</span>
                    </button>
                </div>
                
                <!-- 生成二维码选项卡 -->
                <div class="qr-tab-content active" id="generate-tab">
                    <div class="qr-generate-container">
                        <div class="qr-header">
                            <h3 class="qr-title">我的连接二维码</h3>
                            <p class="qr-subtitle">使用另一台设备扫描此二维码即可快速连接到您的设备</p>
                        </div>
                        <div class="qr-code-container">
                            <div class="qr-display" id="qrcode"></div>
                            <div class="my-id-value" style="margin: 0 auto; max-width: 300px;" id="qr-my-id"></div>
                        </div>
                        <div class="qr-actions">
                            <button class="btn btn-outline">
                                <i class="far fa-copy"></i> 复制设备ID
                            </button>
                            <button class="btn btn-primary">
                                <i class="fas fa-download"></i> 保存二维码
                            </button>
                        </div>
                        <div class="qr-share-options">
                            <div class="qr-share-option">
                                <i class="fas fa-share-alt"></i>
                                <div>
                                    <h4>分享连接</h4>
                                    <p>复制连接信息到剪贴板</p>
                                </div>
                                <i class="fas fa-chevron-right"></i>
                            </div>
                            <div class="qr-share-option">
                                <i class="fas fa-info-circle"></i>
                                <div>
                                    <h4>连接说明</h4>
                                    <p>查看二维码连接详细步骤</p>
                                </div>
                                <i class="fas fa-chevron-right"></i>
                            </div>
                        </div>
                    </div>
                </div>
                
                <!-- 扫描二维码选项卡 -->
                <div class="qr-tab-content" id="scan-tab">
                    <div class="qr-scan-container">
                        <div class="scan-preview-container">
                            <video class="scan-preview" id="scan-video" autoplay playsinline></video>
                            <div class="scan-overlay">
                                <div class="scan-frame"></div>
                            </div>
                        </div>
                        <div class="scan-message" id="scan-message">
                            正在扫描二维码...
                        </div>
                        <div class="scan-controls">
                            <button class="btn btn-outline" id="switch-camera-btn">
                                <i class="fas fa-sync-alt"></i> 切换摄像头
                            </button>
                            <button class="btn btn-primary" id="stop-scan-btn">
                                <i class="fas fa-stop"></i> 停止扫描
                            </button>
                        </div>
                        <div class="manual-input-section">
                            <p class="qr-subtitle" style="text-align: left; margin-bottom: 12px;">或者手动输入二维码内容:</p>
                            <div class="d-flex gap-2">
                                <input type="text" 
                                       class="form-input" 
                                       id="manual-qr-input" 
                                       placeholder="粘贴二维码内容..."
                                       style="flex: 1;">
                                <button class="btn btn-outline">
                                    <i class="fas fa-plug"></i> 连接
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 引入PeerJS库 -->
    <script src="https://unpkg.com/peerjs@1.4.7/dist/peerjs.min.js"></script>
    <!-- 引入二维码生成库 -->
    <script src="https://cdn.jsdelivr.net/npm/qrcodejs/qrcode.min.js"></script>
    <!-- 引入二维码扫描库 -->
    <script src="https://cdn.jsdelivr.net/npm/jsqr/dist/jsQR.min.js"></script>

    <script>
        // 全局变量
        let peer = null;
        let myPeerId = null;
        let connections = new Map(); // peerId -> connection
        let chatMessages = [];
        let selectedFiles = [];
        let transfers = new Map(); // transferId -> transfer info
        let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
        
        // 二维码弹窗相关变量
        let scanVideo = null;
        let scanCanvas = null;
        let scanContext = null;
        let scanStream = null;
        let scanAnimation = null;
        let currentFacingMode = 'environment'; // 默认后置摄像头
        let isScanning = false;

        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            initApp();
            setupEventListeners();
        });

        // 初始化应用
        function initApp() {
            // 生成或获取设备ID
            let deviceId = localStorage.getItem('deviceId');
            if (!deviceId) {
                deviceId = generateDeviceId();
                localStorage.setItem('deviceId', deviceId);
            }
            
            // 初始化PeerJS
            initializePeer(deviceId);
            
            // 更新UI
            updateMyIdDisplay();
            updateStatus('正在连接服务器...', 'connecting');
            
            // 如果是移动端,设置移动端特定逻辑
            if (isMobile) {
                setupMobileFeatures();
            }
            
            // 初始化传输统计
            updateTransferStats();
            
            // 初始化聊天统计
            updateChatStats();
            
            // 添加网络状态监听
            window.addEventListener('online', () => {
                showNotification('网络已恢复', 'success', '网络状态');
                if (peer && peer.disconnected) {
                    setTimeout(() => {
                        if (peer && !peer.destroyed) {
                            peer.reconnect();
                        }
                    }, 1000);
                }
            });
            
            window.addEventListener('offline', () => {
                showNotification('网络已断开', 'error', '网络状态');
                updateStatus('网络断开', 'disconnected');
            });
            
            // 页面卸载时清理资源
            window.addEventListener('beforeunload', cleanupResources);
        }

        // 初始化PeerJS
        function initializePeer(peerId) {
            // 使用更稳定的WebRTC配置
            const options = {
                host: '0.peerjs.com',
                port: 443,
                path: '/',
                secure: true,
                config: {
                    'iceServers': [
                        { 
                            urls: [
                                'stun:stun.l.google.com:19302',
                                'stun:stun1.l.google.com:19302',
                                'stun:global.stun.twilio.com:3478'
                            ]
                        },
                        {
                            urls: 'turn:openrelay.metered.ca:80',
                            username: 'openrelayproject',
                            credential: 'openrelayproject'
                        },
                        {
                            urls: 'turn:openrelay.metered.ca:443',
                            username: 'openrelayproject',
                            credential: 'openrelayproject'
                        },
                        {
                            urls: 'turn:openrelay.metered.ca:443?transport=tcp',
                            username: 'openrelayproject',
                            credential: 'openrelayproject'
                        }
                    ],
                    'iceCandidatePoolSize': 10,
                    'iceTransportPolicy': 'all'
                },
                debug: 1
            };
            
            try {
                // 如果存在旧的peer实例,先销毁
                if (peer && !peer.destroyed) {
                    peer.destroy();
                }
                
                peer = new Peer(peerId, options);
                
                peer.on('open', (id) => {
                    console.log('PeerJS连接成功,ID:', id);
                    myPeerId = id;
                    updateMyIdDisplay();
                    updateStatus('已连接', 'connected');
                    showNotification('连接成功!可以开始连接其他设备', 'success', '连接成功');
                });
                
                peer.on('connection', (conn) => {
                    console.log('收到连接请求:', conn.peer);
                    handleNewConnection(conn);
                });
                
                peer.on('error', (err) => {
                    console.error('PeerJS错误:', err);
                    
                    let errorMsg = '连接错误';
                    let shouldReconnect = false;
                    
                    switch (err.type) {
                        case 'peer-unavailable':
                            errorMsg = '对方设备不可用或ID错误';
                            break;
                        case 'network':
                            errorMsg = '网络连接错误,请检查网络';
                            shouldReconnect = true;
                            break;
                        case 'server-error':
                            errorMsg = '服务器错误,尝试重新连接';
                            shouldReconnect = true;
                            break;
                        case 'disconnected':
                            errorMsg = '连接已断开';
                            shouldReconnect = true;
                            break;
                        case 'browser-incompatible':
                            errorMsg = '浏览器不兼容WebRTC,请使用Chrome/Firefox/Safari等现代浏览器';
                            break;
                        default:
                            errorMsg = err.message || `连接错误: ${err.type}`;
                    }
                    
                    updateStatus('连接错误', 'error');
                    showNotification(errorMsg, 'error', '连接错误');
                    
                    // 需要重连的情况
                    if (shouldReconnect && peer && peer.disconnected) {
                        setTimeout(() => {
                            if (peer && !peer.destroyed) {
                                console.log('尝试重新连接...');
                                peer.reconnect();
                            }
                        }, 3000);
                    }
                });
                
                peer.on('disconnected', () => {
                    console.log('PeerJS连接断开');
                    updateStatus('连接断开', 'disconnected');
                    showNotification('连接断开,正在重新连接...', 'warning', '连接断开');
                    
                    // 尝试重新连接
                    setTimeout(() => {
                        if (peer && !peer.destroyed) {
                            peer.reconnect();
                        }
                    }, 2000);
                });
                
                peer.on('close', () => {
                    console.log('PeerJS连接关闭');
                    updateStatus('连接已关闭', 'disconnected');
                });
                
            } catch (error) {
                console.error('初始化PeerJS失败:', error);
                showNotification('初始化连接失败: ' + error.message, 'error', '初始化失败');
                updateStatus('连接失败', 'error');
            }
        }

        // 处理新连接
        function handleNewConnection(conn) {
            console.log('处理新连接:', conn.peer);
            
            // 设置序列化选项
            conn.serialization = 'json';
            
            // 设置连接事件处理
            conn.on('open', () => {
                console.log('连接已建立:', conn.peer);
                
                // 添加到连接列表
                connections.set(conn.peer, conn);
                updateConnectedDevicesList();
                
                // 修复数据监听
                conn.on('data', (data) => {
                    try {
                        // 确保数据是对象
                        if (typeof data === 'string') {
                            data = JSON.parse(data);
                        }
                        handleIncomingData(data, conn.peer);
                    } catch (error) {
                        console.error('解析数据失败:', error);
                    }
                });
                
                // 连接关闭
                conn.on('close', () => {
                    console.log('连接关闭:', conn.peer);
                    connections.delete(conn.peer);
                    updateConnectedDevicesList();
                    showNotification(`设备 ${conn.peer} 已断开连接`, 'warning', '连接断开');
                });
                
                // 连接错误
                conn.on('error', (err) => {
                    console.error('连接错误:', err);
                    showNotification(`与 ${conn.peer} 的连接错误: ${err.message}`, 'error', '连接错误');
                });
                
                showNotification(`设备 ${conn.peer} 已连接`, 'success', '新连接');
                
                // 发送欢迎消息
                setTimeout(() => {
                    if (conn.open) {
                        const welcomeMsg = {
                            type: 'chat-message',
                            content: '连接成功!可以开始聊天和传输文件了。',
                            timestamp: Date.now(),
                            sender: myPeerId,
                            messageId: 'welcome_' + Date.now()
                        };
                        conn.send(JSON.stringify(welcomeMsg));
                    }
                }, 1000);
            });
            
            // 处理连接错误
            conn.on('error', (err) => {
                console.error('建立连接时出错:', err);
                showNotification(`连接 ${conn.peer} 失败: ${err.message}`, 'error', '连接失败');
            });
        }

        // 连接到其他设备
        function connectToPeer() {
            const peerId = document.getElementById('peer-id-input').value.trim();
            if (!peerId) {
                showNotification('请输入设备ID', 'error', '输入错误');
                return;
            }
            
            connectToPeerById(peerId);
        }

        function connectToPeerMobile() {
            const peerId = document.getElementById('mobile-peer-id-input').value.trim();
            if (!peerId) {
                showNotification('请输入设备ID', 'error', '输入错误');
                return;
            }
            
            connectToPeerById(peerId);
            document.getElementById('mobile-peer-id-input').value = '';
        }

        function connectToPeerById(peerId) {
            if (peerId === myPeerId) {
                showNotification('不能连接到自己', 'warning', '连接错误');
                return;
            }
            
            if (connections.has(peerId)) {
                showNotification('已连接到该设备', 'info', '连接状态');
                return;
            }
            
            showNotification(`正在连接设备 ${peerId}...`, 'info', '连接中');
            
            try {
                // 创建连接配置
                const conn = peer.connect(peerId, {
                    reliable: true,
                    serialization: 'json',
                    metadata: {
                        type: 'file-transfer',
                        timestamp: Date.now(),
                        version: '1.0'
                    }
                });
                
                if (!conn) {
                    showNotification('创建连接失败', 'error', '连接失败');
                    return;
                }
                
                // 设置连接事件
                conn.on('open', () => {
                    console.log('主动连接成功:', peerId);
                    connections.set(peerId, conn);
                    updateConnectedDevicesList();
                    
                    // 修复数据监听
                    conn.on('data', (data) => {
                        try {
                            if (typeof data === 'string') {
                                data = JSON.parse(data);
                            }
                            handleIncomingData(data, peerId);
                        } catch (error) {
                            console.error('解析数据失败:', error);
                        }
                    });
                    
                    conn.on('close', () => {
                        connections.delete(peerId);
                        updateConnectedDevicesList();
                        showNotification(`设备 ${peerId} 已断开连接`, 'warning', '连接断开');
                    });
                    
                    conn.on('error', (err) => {
                        console.error('连接错误:', err);
                        showNotification(`与 ${peerId} 的连接错误: ${err.message}`, 'error', '连接错误');
                    });
                    
                    showNotification(`成功连接设备 ${peerId}`, 'success', '连接成功');
                    
                    // 清空输入框
                    if (!isMobile) {
                        document.getElementById('peer-id-input').value = '';
                    }
                });
                
                conn.on('error', (err) => {
                    console.error('连接错误:', err);
                    showNotification(`连接失败: ${err.message}`, 'error', '连接失败');
                });
                
            } catch (error) {
                console.error('创建连接时异常:', error);
                showNotification(`连接失败: ${error.message}`, 'error', '连接失败');
            }
        }

        // 处理传入数据
        function handleIncomingData(data, fromPeer) {
            console.log('收到数据:', data.type, '来自:', fromPeer);
            
            try {
                switch (data.type) {
                    case 'chat-message':
                        handleChatMessage(data, fromPeer);
                        break;
                    case 'file-start':
                        handleFileStart(data, fromPeer);
                        break;
                    case 'file-chunk':
                        handleFileChunk(data, fromPeer);
                        break;
                    case 'file-end':
                        handleFileEnd(data, fromPeer);
                        break;
                    case 'file-error':
                        handleFileError(data, fromPeer);
                        break;
                    case 'ping':
                        // 心跳包,回复pong
                        const conn = connections.get(fromPeer);
                        if (conn && conn.open) {
                            conn.send(JSON.stringify({ type: 'pong', timestamp: Date.now() }));
                        }
                        break;
                    default:
                        console.warn('未知数据类型:', data.type);
                }
            } catch (error) {
                console.error('处理数据时出错:', error);
                showNotification('处理数据时出错', 'error', '数据错误');
            }
        }

        // 处理聊天消息
        function handleChatMessage(data, fromPeer) {
            const message = {
                id: data.messageId || Date.now() + Math.random(),
                content: data.content,
                sender: fromPeer,
                timestamp: data.timestamp || Date.now(),
                type: 'received'
            };
            
            chatMessages.push(message);
            updateChatDisplay();
            updateChatStats();
            
            // 如果当前不在聊天标签页,显示通知
            if (isMobile && !document.querySelector('[data-tab="chat"]').classList.contains('active')) {
                const shortContent = data.content.length > 30 ? data.content.substring(0, 30) + '...' : data.content;
                showNotification(`新消息来自 ${fromPeer.substring(0, 8)}...: ${shortContent}`, 'info', '新消息');
            }
        }

        // 处理文件开始传输
        function handleFileStart(data, fromPeer) {
            const transferId = data.transferId;
            const fileId = data.fileId;
            
            console.log('开始接收文件:', data.fileName);
            
            // 创建传输记录
            const transferInfo = {
                id: transferId,
                fileId: fileId,
                name: data.fileName,
                size: data.fileSize,
                type: data.fileType,
                direction: 'receiving',
                peerId: fromPeer,
                status: 'receiving',
                progress: 0,
                chunks: [],
                totalChunks: data.totalChunks,
                receivedChunks: 0,
                startTime: Date.now(),
                chunksReceived: new Array(data.totalChunks).fill(false)
            };
            
            transfers.set(transferId, transferInfo);
            updateTransfersList();
            updateTransferStats();
            
            showNotification(`开始接收文件: ${data.fileName}`, 'info', '文件接收');
        }

        // 处理文件块
        function handleFileChunk(data, fromPeer) {
            const transferId = data.transferId;
            const transferInfo = transfers.get(transferId);
            
            if (!transferInfo) {
                console.error('找不到传输记录:', transferId);
                return;
            }
            
            // 标记块已接收
            transferInfo.chunksReceived[data.chunkIndex] = true;
            transferInfo.receivedChunks++;
            
            // 更新进度
            const progress = Math.round((transferInfo.receivedChunks / transferInfo.totalChunks) * 100);
            transferInfo.progress = progress;
            
            // 存储块数据
            transferInfo.chunks[data.chunkIndex] = data.data;
            
            // 更新传输列表显示
            updateTransferProgress(transferId, progress);
            
            // 如果收到所有块,组装文件
            if (transferInfo.receivedChunks === transferInfo.totalChunks) {
                assembleAndSaveFile(transferInfo);
            }
        }

        // 处理文件传输结束
        function handleFileEnd(data, fromPeer) {
            const transferId = data.transferId;
            const transferInfo = transfers.get(transferId);
            
            if (transferInfo) {
                transferInfo.status = 'completed';
                transferInfo.endTime = Date.now();
                transferInfo.progress = 100;
                
                updateTransfersList();
                updateTransferStats();
                
                showNotification(`文件 ${transferInfo.name} 接收完成`, 'success', '文件接收完成');
                
                // 发送确认
                const conn = connections.get(fromPeer);
                if (conn && conn.open) {
                    conn.send(JSON.stringify({
                        type: 'file-ack',
                        transferId: transferId,
                        status: 'success'
                    }));
                }
            }
        }

        // 处理文件传输错误
        function handleFileError(data, fromPeer) {
            const transferId = data.transferId;
            const transferInfo = transfers.get(transferId);
            
            if (transferInfo) {
                transferInfo.status = 'failed';
                transferInfo.error = data.error;
                
                updateTransfersList();
                updateTransferStats();
                
                showNotification(`文件 ${transferInfo.name} 传输失败: ${data.error}`, 'error', '传输失败');
            }
        }

        // 组装并保存文件
        function assembleAndSaveFile(transferInfo) {
            try {
                console.log('开始组装文件:', transferInfo.name);
                
                // 按顺序组装块
                const sortedChunks = [];
                for (let i = 0; i < transferInfo.totalChunks; i++) {
                    if (transferInfo.chunks[i]) {
                        sortedChunks.push(transferInfo.chunks[i]);
                    }
                }
                
                const base64Data = sortedChunks.join('');
                const binaryString = atob(base64Data);
                const bytes = new Uint8Array(binaryString.length);
                
                for (let i = 0; i < binaryString.length; i++) {
                    bytes[i] = binaryString.charCodeAt(i);
                }
                
                const blob = new Blob([bytes], { type: transferInfo.type });
                const url = URL.createObjectURL(blob);
                
                // 创建下载链接
                const a = document.createElement('a');
                a.href = url;
                a.download = transferInfo.name;
                a.style.display = 'none';
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                
                // 清理URL对象
                setTimeout(() => URL.revokeObjectURL(url), 1000);
                
                console.log('文件保存成功:', transferInfo.name);
                
            } catch (error) {
                console.error('组装文件失败:', error);
                transferInfo.status = 'failed';
                transferInfo.error = error.message;
                updateTransfersList();
                updateTransferStats();
                
                showNotification(`文件 ${transferInfo.name} 保存失败: ${error.message}`, 'error', '保存失败');
            }
        }

        // 发送聊天消息
        function sendChatMessage() {
            const input = document.getElementById('chat-input');
            sendChatMessageFromInput(input);
        }

        function sendChatMessageMobile() {
            const input = document.getElementById('mobile-chat-input');
            sendChatMessageFromInput(input);
        }

        function sendChatMessageFromInput(input) {
            const message = input.value.trim();
            
            if (!message) {
                showNotification('消息不能为空', 'warning', '发送错误');
                return;
            }
            
            if (connections.size === 0) {
                showNotification('没有连接的设备', 'error', '发送错误');
                return;
            }
            
            const messageData = {
                type: 'chat-message',
                content: message,
                timestamp: Date.now(),
                sender: myPeerId,
                messageId: Date.now() + '_' + Math.random().toString(36).substr(2, 9)
            };
            
            // 添加到本地消息列表
            const localMessage = {
                id: messageData.messageId,
                content: message,
                sender: '我',
                timestamp: Date.now(),
                type: 'sent'
            };
            
            chatMessages.push(localMessage);
            updateChatDisplay();
            updateChatStats();
            
            // 发送给所有连接的设备
            let sentCount = 0;
            const messageString = JSON.stringify(messageData);
            
            connections.forEach((conn, peerId) => {
                if (conn && conn.open) {
                    try {
                        conn.send(messageString);
                        sentCount++;
                    } catch (error) {
                        console.error('发送消息失败:', error);
                        showNotification(`发送给 ${peerId} 失败: ${error.message}`, 'error', '发送失败');
                    }
                }
            });
            
            if (sentCount === 0) {
                showNotification('消息发送失败,无可用连接', 'error', '发送失败');
                // 移除刚才添加的消息
                chatMessages.pop();
                updateChatDisplay();
                updateChatStats();
            } else {
                // 清空输入框
                input.value = '';
                input.focus();
                
                // 滚动到最新消息
                setTimeout(() => {
                    const chatContainer = isMobile ? 
                        document.getElementById('mobile-chat-messages') : 
                        document.getElementById('chat-messages');
                    if (chatContainer) {
                        chatContainer.scrollTop = chatContainer.scrollHeight;
                    }
                }, 100);
            }
        }

        // 清空聊天记录
        function clearChat() {
            if (chatMessages.length === 0) {
                showNotification('聊天记录已为空', 'info', '操作提示');
                return;
            }
            
            if (confirm(`确定要清空 ${chatMessages.length} 条聊天记录吗?`)) {
                chatMessages = [];
                updateChatDisplay();
                updateChatStats();
                showNotification('聊天记录已清空', 'success', '操作完成');
            }
        }

        // 发送文件
        async function sendSelectedFiles() {
            if (selectedFiles.length === 0) {
                showNotification('请先选择文件', 'warning', '发送错误');
                return;
            }
            
            if (connections.size === 0) {
                showNotification('没有连接的设备', 'error', '发送错误');
                return;
            }
            
            const sendTo = document.getElementById('send-to-select').value;
            const recipients = sendTo === 'all' ? Array.from(connections.keys()) : [sendTo];
            
            if (recipients.length === 0) {
                showNotification('没有可发送的设备', 'error', '发送错误');
                return;
            }
            
            // 发送每个文件
            for (const file of selectedFiles) {
                await sendFile(file, recipients);
                // 每个文件之间延迟1秒,避免网络拥塞
                await new Promise(resolve => setTimeout(resolve, 1000));
            }
        }

        async function sendSelectedFilesMobile() {
            if (selectedFiles.length === 0) {
                showNotification('请先选择文件', 'warning', '发送错误');
                return;
            }
            
            if (connections.size === 0) {
                showNotification('没有连接的设备', 'error', '发送错误');
                return;
            }
            
            const sendTo = document.getElementById('mobile-send-to-select').value;
            const recipients = sendTo === 'all' ? Array.from(connections.keys()) : [sendTo];
            
            if (recipients.length === 0) {
                showNotification('没有可发送的设备', 'error', '发送错误');
                return;
            }
            
            // 发送每个文件
            for (const file of selectedFiles) {
                await sendFile(file, recipients);
                // 每个文件之间延迟1秒,避免网络拥塞
                await new Promise(resolve => setTimeout(resolve, 1000));
            }
        }

        // 发送单个文件
        async function sendFile(file, recipients) {
            const transferId = 'transfer_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
            const fileId = 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
            
            try {
                // 创建传输记录
                const transferInfo = {
                    id: transferId,
                    fileId: fileId,
                    name: file.name,
                    size: file.size,
                    type: file.type,
                    direction: 'sending',
                    recipients: recipients,
                    status: 'sending',
                    progress: 0,
                    startTime: Date.now()
                };
                
                transfers.set(transferId, transferInfo);
                updateTransfersList();
                updateTransferStats();
                
                // 读取文件为Base64 - 减小块大小提高稳定性
                const base64Data = await readFileAsBase64(file.file);
                const pureBase64 = base64Data.split(',')[1];
                
                // 减小块大小为16KB以提高稳定性
                const chunkSize = 16 * 1024;
                const totalChunks = Math.ceil(pureBase64.length / chunkSize);
                
                // 发送文件信息给每个接收者
                recipients.forEach(peerId => {
                    const conn = connections.get(peerId);
                    if (conn && conn.open) {
                        try {
                            conn.send(JSON.stringify({
                                type: 'file-start',
                                transferId: transferId,
                                fileId: fileId,
                                fileName: file.name,
                                fileSize: file.size,
                                fileType: file.type,
                                totalChunks: totalChunks,
                                chunkSize: chunkSize,
                                timestamp: Date.now()
                            }));
                        } catch (error) {
                            console.error('发送文件开始信息失败:', error);
                        }
                    }
                });
                
                // 分块发送文件数据,增加延迟避免拥塞
                for (let i = 0; i < totalChunks; i++) {
                    const start = i * chunkSize;
                    const end = Math.min(start + chunkSize, pureBase64.length);
                    const chunk = pureBase64.substring(start, end);
                    
                    const chunkData = {
                        type: 'file-chunk',
                        transferId: transferId,
                        chunkIndex: i,
                        data: chunk,
                        totalChunks: totalChunks
                    };
                    
                    // 发送给所有接收者
                    let sentToAll = true;
                    recipients.forEach(peerId => {
                        const conn = connections.get(peerId);
                        if (conn && conn.open) {
                            try {
                                conn.send(JSON.stringify(chunkData));
                            } catch (error) {
                                console.error('发送文件块失败:', error);
                                sentToAll = false;
                            }
                        } else {
                            sentToAll = false;
                        }
                    });
                    
                    if (!sentToAll) {
                        throw new Error('部分设备连接丢失');
                    }
                    
                    // 更新进度
                    const progress = Math.round(((i + 1) / totalChunks) * 100);
                    transferInfo.progress = progress;
                    updateTransferProgress(transferId, progress);
                    
                    // 每发送10个块休息一下,避免拥塞
                    if (i % 10 === 0) {
                        await new Promise(resolve => setTimeout(resolve, 50));
                    }
                }
                
                // 发送完成标记
                recipients.forEach(peerId => {
                    const conn = connections.get(peerId);
                    if (conn && conn.open) {
                        try {
                            conn.send(JSON.stringify({
                                type: 'file-end',
                                transferId: transferId,
                                success: true
                            }));
                        } catch (error) {
                            console.error('发送文件结束信息失败:', error);
                        }
                    }
                });
                
                // 更新传输状态
                transferInfo.status = 'completed';
                transferInfo.endTime = Date.now();
                transferInfo.progress = 100;
                updateTransfersList();
                updateTransferStats();
                
                showNotification(`文件 ${file.name} 发送完成`, 'success', '文件发送完成');
                
                // 从选中文件列表中移除
                removeFileFromList(file.id);
                
            } catch (error) {
                console.error('发送文件失败:', error);
                
                // 更新传输状态为失败
                const transferInfo = transfers.get(transferId);
                if (transferInfo) {
                    transferInfo.status = 'failed';
                    transferInfo.error = error.message;
                    transferInfo.endTime = Date.now();
                    updateTransfersList();
                    updateTransferStats();
                }
                
                // 发送错误通知给接收者
                recipients.forEach(peerId => {
                    const conn = connections.get(peerId);
                    if (conn && conn.open) {
                        try {
                            conn.send(JSON.stringify({
                                type: 'file-error',
                                transferId: transferId,
                                error: error.message
                            }));
                        } catch (error) {
                            console.error('发送错误信息失败:', error);
                        }
                    }
                });
                
                showNotification(`文件 ${file.name} 发送失败: ${error.message}`, 'error', '发送失败');
            }
        }

        // 文件处理函数
        function readFileAsBase64(file) {
            return new Promise((resolve, reject) => {
                const reader = new FileReader();
                reader.onload = () => resolve(reader.result);
                reader.onerror = reject;
                reader.readAsDataURL(file);
            });
        }

        // 更新我的ID显示
        function updateMyIdDisplay() {
            if (myPeerId) {
                document.getElementById('my-id').textContent = myPeerId;
                if (isMobile) {
                    document.getElementById('mobile-my-id').textContent = myPeerId;
                }
                document.getElementById('qr-my-id').textContent = myPeerId;
            }
        }

        // 更新状态显示
        function updateStatus(text, status) {
            const statusElement = document.getElementById('status-text');
            const statusDot = document.getElementById('status-dot');
            
            statusElement.textContent = text;
            statusDot.className = 'status-dot';
            statusDot.classList.add(status);
        }

        // 更新已连接设备列表
        function updateConnectedDevicesList() {
            const desktopList = document.getElementById('devices-list');
            const mobileList = document.getElementById('mobile-devices-list');
            const sendToSelect = document.getElementById('send-to-select');
            const mobileSendToSelect = document.getElementById('mobile-send-to-select');
            const connectedCount = connections.size;
            
            document.getElementById('connected-count').textContent = connectedCount;
            document.getElementById('mobile-connected-count').textContent = connectedCount;
            
            if (connectedCount === 0) {
                desktopList.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-user-friends"></i>
                        <h4>暂无已连接的设备</h4>
                        <p>连接其他设备后,可以开始聊天和传输文件</p>
                    </div>
                `;
                
                mobileList.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-user-friends"></i>
                        <h4>暂无已连接的设备</h4>
                        <p>连接其他设备后,可以开始聊天和传输文件</p>
                    </div>
                `;
                
                sendToSelect.innerHTML = '<option value="all">发送给所有设备</option>';
                mobileSendToSelect.innerHTML = '<option value="all">发送给所有设备</option>';
                
                // 禁用发送按钮
                document.getElementById('send-files-btn').disabled = true;
                document.getElementById('mobile-send-files-btn').disabled = true;
                
                return;
            }
            
            // 更新设备列表
            let devicesHtml = '';
            let selectHtml = '<option value="all">发送给所有设备</option>';
            
            connections.forEach((conn, peerId) => {
                const shortPeerId = peerId.length > 12 ? peerId.substring(0, 12) + '...' : peerId;
                const avatarText = peerId.substring(0, 2).toUpperCase();
                
                devicesHtml += `
                    <div class="device-item">
                        <div class="device-info">
                            <div class="device-avatar">${avatarText}</div>
                            <div class="device-details">
                                <div class="device-name">设备 ${peerId.substring(0, 6)}...</div>
                                <div class="device-id">${shortPeerId}</div>
                            </div>
                        </div>
                        <div class="device-status">
                            <div class="status-indicator ${conn.open ? '' : 'disconnected'}"></div>
                            <span style="color: var(--text-secondary); font-size: 0.85rem;">
                                ${conn.open ? '在线' : '离线'}
                            </span>
                            <button class="btn btn-sm btn-outline" style="margin-left: 10px;">
                                <i class="fas fa-times"></i>
                            </button>
                        </div>
                    </div>
                `;
                
                if (conn.open) {
                    const displayName = peerId.length > 8 ? peerId.substring(0, 8) + '...' : peerId;
                    selectHtml += `<option value="${peerId}">发送给 ${displayName}</option>`;
                }
            });
            
            desktopList.innerHTML = devicesHtml;
            mobileList.innerHTML = devicesHtml;
            sendToSelect.innerHTML = selectHtml;
            mobileSendToSelect.innerHTML = selectHtml;
            
            // 启用发送按钮
            document.getElementById('send-files-btn').disabled = false;
            document.getElementById('mobile-send-files-btn').disabled = false;
        }

        // 更新聊天显示
        function updateChatDisplay() {
            const desktopChat = document.getElementById('chat-messages');
            const mobileChat = document.getElementById('mobile-chat-messages');
            
            if (chatMessages.length === 0) {
                desktopChat.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-comment-dots"></i>
                        <h4>暂无聊天消息</h4>
                        <p>连接设备后即可开始聊天</p>
                    </div>
                `;
                
                mobileChat.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-comment-dots"></i>
                        <h4>暂无聊天消息</h4>
                        <p>连接设备后即可开始聊天</p>
                    </div>
                `;
                
                return;
            }
            
            // 显示消息
            let html = '';
            chatMessages.forEach(msg => {
                const time = new Date(msg.timestamp).toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
                const senderDisplay = msg.type === 'sent' ? '我' : (msg.sender.length > 8 ? msg.sender.substring(0, 8) + '...' : msg.sender);
                
                html += `
                    <div class="message ${msg.type}">
                        <div class="message-bubble">${escapeHtml(msg.content)}</div>
                        <div class="message-meta">
                            <span class="message-sender">${senderDisplay}</span>
                            <span class="message-time">${time}</span>
                        </div>
                    </div>
                `;
            });
            
            desktopChat.innerHTML = html;
            mobileChat.innerHTML = html;
            
            // 滚动到底部
            setTimeout(() => {
                desktopChat.scrollTop = desktopChat.scrollHeight;
                mobileChat.scrollTop = mobileChat.scrollHeight;
            }, 100);
        }

        // 更新聊天统计
        function updateChatStats() {
            const chatCount = document.getElementById('chat-count');
            chatCount.textContent = `${chatMessages.length} 条消息`;
        }

        // 更新传输列表
        function updateTransfersList() {
            const desktopList = document.getElementById('transfers-list');
            const mobileList = document.getElementById('mobile-transfers-list');
            
            if (transfers.size === 0) {
                desktopList.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-exchange-alt"></i>
                        <h4>暂无传输任务</h4>
                        <p>文件传输将在此显示进度</p>
                    </div>
                `;
                
                mobileList.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-exchange-alt"></i>
                        <h4>暂无传输任务</h4>
                        <p>文件传输将在此显示进度</p>
                    </div>
                `;
                
                return;
            }
            
            // 更新传输列表
            let desktopHtml = '';
            let mobileHtml = '';
            
            transfers.forEach((transfer, transferId) => {
                const iconClass = transfer.direction === 'sending' ? 'sending' : 
                                 transfer.status === 'receiving' ? 'receiving' : 'completed';
                const icon = transfer.direction === 'sending' ? 'fa-upload' : 'fa-download';
                const directionText = transfer.direction === 'sending' ? '发送给' : '来自';
                const peerDisplay = transfer.direction === 'sending' ? 
                    (transfer.recipients && transfer.recipients.length > 0 ? 
                     (transfer.recipients.length === 1 ? transfer.recipients[0].substring(0, 8) + '...' : '多个设备') : '未知设备') : 
                    (transfer.peerId ? transfer.peerId.substring(0, 8) + '...' : '未知设备');
                
                const fileSize = formatBytes(transfer.size);
                const transferItem = `
                    <div class="transfer-item" id="transfer-${transferId}">
                        <div class="transfer-icon ${iconClass}">
                            <i class="fas ${icon}"></i>
                        </div>
                        <div class="transfer-info">
                            <div class="transfer-name">${transfer.name}</div>
                            <div class="transfer-details">
                                <span>${fileSize} &#8226; ${directionText} ${peerDisplay}</span>
                                <span class="transfer-status ${transfer.status}">${getStatusText(transfer.status)}</span>
                            </div>
                            <div class="transfer-progress">
                                <div class="transfer-progress-bar" id="progress-${transferId}" style="width: ${transfer.progress}%"></div>
                            </div>
                        </div>
                        <div class="transfer-actions">
                            ${transfer.status === 'completed' ? 
                                `<button class="btn btn-sm btn-outline" title="打开文件">
                                    <i class="fas fa-folder-open"></i>
                                </button>` : ''}
                            <button class="btn btn-sm btn-outline" title="删除记录">
                                <i class="fas fa-trash"></i>
                            </button>
                        </div>
                    </div>
                `;
                
                desktopHtml += transferItem;
                mobileHtml += transferItem;
            });
            
            desktopList.innerHTML = desktopHtml;
            mobileList.innerHTML = mobileHtml;
        }

        // 更新传输进度
        function updateTransferProgress(transferId, progress) {
            const progressBar = document.getElementById(`progress-${transferId}`);
            if (progressBar) {
                progressBar.style.width = `${progress}%`;
            }
        }

        // 更新传输统计
        function updateTransferStats() {
            let active = 0;
            let completed = 0;
            let failed = 0;
            
            transfers.forEach(transfer => {
                if (transfer.status === 'sending' || transfer.status === 'receiving') {
                    active++;
                } else if (transfer.status === 'completed') {
                    completed++;
                } else if (transfer.status === 'failed') {
                    failed++;
                }
            });
            
            document.getElementById('active-transfers').textContent = active;
            document.getElementById('completed-transfers').textContent = completed;
            document.getElementById('failed-transfers').textContent = failed;
            
            document.getElementById('mobile-active-transfers').textContent = active;
            document.getElementById('mobile-completed-transfers').textContent = completed;
            document.getElementById('mobile-failed-transfers').textContent = failed;
        }

        // 获取状态文本
        function getStatusText(status) {
            const statusMap = {
                'sending': '发送中',
                'receiving': '接收中',
                'completed': '已完成',
                'failed': '失败'
            };
            return statusMap[status] || status;
        }

        // 断开连接
        function disconnectPeer(peerId) {
            const conn = connections.get(peerId);
            if (conn) {
                conn.close();
                connections.delete(peerId);
                updateConnectedDevicesList();
                showNotification(`已断开与 ${peerId} 的连接`, 'info', '连接断开');
            }
        }

        // 复制我的ID
        function copyMyId() {
            if (!myPeerId) {
                showNotification('ID还未生成', 'error', '复制失败');
                return;
            }
            
            navigator.clipboard.writeText(myPeerId).then(() => {
                const copyBtn = document.getElementById('copy-btn');
                if (copyBtn) {
                    const originalHtml = copyBtn.innerHTML;
                    
                    copyBtn.innerHTML = '<i class="fas fa-check"></i> 已复制';
                    copyBtn.style.background = 'linear-gradient(135deg, var(--success), #34d399)';
                    copyBtn.style.color = 'white';
                    copyBtn.style.border = 'none';
                    
                    // 3秒后恢复原状
                    setTimeout(() => {
                        copyBtn.innerHTML = originalHtml;
                        copyBtn.style.background = '';
                        copyBtn.style.color = '';
                        copyBtn.style.border = '';
                    }, 3000);
                }
                
                showNotification('设备ID已复制到剪贴板', 'success', '复制成功');
            }).catch(err => {
                console.error('复制失败:', err);
                showNotification('复制失败,请手动复制', 'error', '复制失败');
            });
        }

        // 打开二维码连接弹窗
        function openQRConnectModal() {
            const modal = document.getElementById('qr-connect-modal');
            modal.classList.add('active');
            
            // 默认切换到生成二维码选项卡
            switchQRTab('generate');
            
            // 生成二维码
            generateQRCode();
        }

        // 切换二维码选项卡
        function switchQRTab(tab) {
            // 更新选项卡按钮状态
            document.querySelectorAll('.qr-tab').forEach(tabElement => {
                tabElement.classList.remove('active');
            });
            
            document.querySelectorAll('.qr-tab-content').forEach(content => {
                content.classList.remove('active');
            });
            
            // 激活选中的选项卡
            document.querySelectorAll('.qr-tab').forEach(tabElement => {
                if (tabElement.querySelector('span').textContent.includes(tab === 'generate' ? '生成' : '扫描')) {
                    tabElement.classList.add('active');
                }
            });
            
            document.getElementById(`${tab}-tab`).classList.add('active');
            
            // 如果切换到扫描选项卡,初始化扫码器
            if (tab === 'scan') {
                setTimeout(() => {
                    initQRCodeScanner();
                }, 100);
            } else {
                // 如果切换到生成选项卡,停止扫码
                stopScanning();
            }
        }

        // 生成二维码
        function generateQRCode() {
            if (!myPeerId) {
                showNotification('ID还未生成', 'error', '二维码生成失败');
                return;
            }
            
            const qrContainer = document.getElementById('qrcode');
            
            // 清空之前的二维码
            qrContainer.innerHTML = '';
            
            // 生成二维码数据(包含服务器信息以便连接)
            const qrData = JSON.stringify({
                type: 'peerjs-connect',
                peerId: myPeerId,
                server: '0.peerjs.com',
                port: 443,
                path: '/',
                timestamp: Date.now(),
                app: '零流量互传'
            });
            
            // 生成二维码
            new QRCode(qrContainer, {
                text: qrData,
                width: 200,
                height: 200,
                colorDark: "#000000",
                colorLight: "#ffffff",
                correctLevel: QRCode.CorrectLevel.H
            });
        }

        // 复制二维码到剪贴板
        function copyQRCodeToClipboard() {
            const qrCanvas = document.querySelector('#qrcode canvas');
            if (qrCanvas) {
                qrCanvas.toBlob((blob) => {
                    const item = new ClipboardItem({ "image/png": blob });
                    navigator.clipboard.write([item]).then(() => {
                        showNotification('二维码已复制到剪贴板', 'success', '复制成功');
                    }).catch(err => {
                        console.error('复制二维码失败:', err);
                        showNotification('复制失败,请手动保存', 'error', '复制失败');
                    });
                });
            }
        }

        // 显示分享说明
        function showShareInstructions() {
            alert('连接说明:\n\n1. 确保两台设备都在线并打开此应用\n2. 在设备A上点击"生成二维码"\n3. 在设备B上点击"扫描二维码",扫描设备A的二维码\n4. 连接成功后即可开始聊天和传输文件');
        }

        // 下载二维码
        function downloadQRCode() {
            const qrCanvas = document.querySelector('#qrcode canvas');
            if (qrCanvas) {
                const link = document.createElement('a');
                link.download = `qrcode-${myPeerId}.png`;
                link.href = qrCanvas.toDataURL('image/png');
                link.click();
                showNotification('二维码已保存', 'success', '保存成功');
            }
        }

        // 初始化二维码扫描器
        function initQRCodeScanner() {
            scanVideo = document.getElementById('scan-video');
            
            if (!scanVideo) {
                console.error('扫码组件未找到');
                return;
            }
            
            // 创建Canvas用于扫描
            if (!scanCanvas) {
                scanCanvas = document.createElement('canvas');
                scanContext = scanCanvas.getContext('2d');
            }
            
            // 请求摄像头权限
            const constraints = {
                video: {
                    facingMode: currentFacingMode,
                    width: { ideal: 1280 },
                    height: { ideal: 720 }
                }
            };
            
            navigator.mediaDevices.getUserMedia(constraints)
                .then((stream) => {
                    scanStream = stream;
                    scanVideo.srcObject = stream;
                    scanVideo.play();
                    
                    // 开始扫描
                    startScanning();
                    showScanMessage('正在扫描二维码...');
                })
                .catch((error) => {
                    console.error('摄像头访问失败:', error);
                    showNotification('摄像头访问失败,请检查权限', 'error', '扫码失败');
                    showScanMessage('摄像头访问失败,请检查权限');
                    
                    // 显示手动输入区域
                    document.getElementById('manual-qr-input').style.display = 'block';
                });
        }

        // 开始扫描
        function startScanning() {
            if (!scanVideo || !scanCanvas || !scanContext) {
                return;
            }
            
            // 设置Canvas尺寸与视频一致
            scanCanvas.width = scanVideo.videoWidth;
            scanCanvas.height = scanVideo.videoHeight;
            
            // 扫描函数
            function scan() {
                if (scanVideo.readyState === scanVideo.HAVE_ENOUGH_DATA) {
                    // 绘制视频帧到Canvas
                    scanContext.drawImage(scanVideo, 0, 0, scanCanvas.width, scanCanvas.height);
                    
                    // 获取图像数据
                    const imageData = scanContext.getImageData(0, 0, scanCanvas.width, scanCanvas.height);
                    
                    // 使用jsQR解析二维码
                    const code = jsQR(imageData.data, imageData.width, imageData.height, {
                        inversionAttempts: 'dontInvert',
                    });
                    
                    // 如果找到二维码
                    if (code) {
                        console.log('找到二维码:', code.data);
                        handleScannedQR(code.data);
                        stopScanning();
                    }
                }
                
                // 继续扫描
                scanAnimation = requestAnimationFrame(scan);
            }
            
            // 开始扫描循环
            isScanning = true;
            scanAnimation = requestAnimationFrame(scan);
        }

        // 处理扫描到的二维码
        function handleScannedQR(decodedText) {
            console.log('扫描到二维码:', decodedText);
            showScanMessage('二维码扫描成功,正在处理...');
            
            try {
                // 尝试解析JSON
                const qrData = JSON.parse(decodedText);
                if (qrData.type === 'peerjs-connect' && qrData.peerId) {
                    // 自动连接
                    showScanMessage('正在连接设备...');
                    setTimeout(() => {
                        connectToPeerById(qrData.peerId);
                        showNotification('扫描成功,正在连接...', 'success', '扫码成功');
                        closeQRConnectModal();
                    }, 500);
                } else {
                    showScanMessage('无效的二维码数据');
                }
            } catch (error) {
                // 如果不是JSON,尝试直接作为Peer ID连接
                if (decodedText.length >= 10 && decodedText.length <= 50) {
                    showScanMessage('正在连接设备...');
                    setTimeout(() => {
                        connectToPeerById(decodedText);
                        showNotification('扫描成功,正在连接...', 'success', '扫码成功');
                        closeQRConnectModal();
                    }, 500);
                } else {
                    showScanMessage('无法识别的二维码格式');
                }
            }
        }

        // 显示扫描消息
        function showScanMessage(message) {
            const scanMessage = document.getElementById('scan-message');
            scanMessage.textContent = message;
            scanMessage.classList.add('active');
            
            // 3秒后隐藏消息
            setTimeout(() => {
                scanMessage.classList.remove('active');
            }, 3000);
        }

        // 切换摄像头
        function switchCamera() {
            currentFacingMode = currentFacingMode === 'environment' ? 'user' : 'environment';
            
            // 停止当前流
            stopScanning();
            
            // 重新初始化扫码器
            setTimeout(() => {
                initQRCodeScanner();
            }, 100);
        }

        // 停止扫描
        function stopScanning() {
            if (scanAnimation) {
                cancelAnimationFrame(scanAnimation);
                scanAnimation = null;
            }
            
            isScanning = false;
        }

        // 关闭二维码弹窗
        function closeQRConnectModal() {
            stopScanning();
            
            if (scanStream) {
                scanStream.getTracks().forEach(track => track.stop());
                scanStream = null;
            }
            
            if (scanVideo) {
                scanVideo.srcObject = null;
            }
            
            const modal = document.getElementById('qr-connect-modal');
            modal.classList.remove('active');
        }

        // 从手动输入连接
        function connectFromManualInput() {
            const input = document.getElementById('manual-qr-input');
            const text = input.value.trim();
            
            if (!text) {
                showNotification('请输入二维码内容', 'error', '输入错误');
                return;
            }
            
            handleScannedQR(text);
            input.value = '';
        }

        // 切换移动端选项卡
        function switchMobileTab(tab) {
            // 更新导航按钮状态
            document.querySelectorAll('.nav-item').forEach(item => {
                item.classList.remove('active');
                if (item.getAttribute('data-tab') === tab) {
                    item.classList.add('active');
                }
            });
            
            // 更新选项卡内容
            document.querySelectorAll('.mobile-tab-content').forEach(content => {
                content.classList.remove('active');
            });
            
            document.getElementById(`mobile-${tab}`).classList.add('active');
        }

        // 设置移动端特定功能
        function setupMobileFeatures() {
            // 为聊天输入框添加发送快捷键
            const mobileChatInput = document.getElementById('mobile-chat-input');
            if (mobileChatInput) {
                mobileChatInput.addEventListener('keydown', (e) => {
                    if (e.key === 'Enter' && !e.shiftKey) {
                        e.preventDefault();
                        sendChatMessageMobile();
                    }
                });
            }
            
            // 为桌面版聊天输入框添加发送快捷键
            const desktopChatInput = document.getElementById('chat-input');
            if (desktopChatInput) {
                desktopChatInput.addEventListener('keydown', (e) => {
                    if (e.key === 'Enter' && !e.shiftKey) {
                        e.preventDefault();
                        sendChatMessage();
                    }
                });
            }
            
            // 为文件输入框添加监听
            const mobileFileInput = document.getElementById('mobile-file-input');
            if (mobileFileInput) {
                mobileFileInput.addEventListener('change', (e) => {
                    handleFileSelect(e, true);
                });
            }
            
            // 拖放区域
            const mobileDropZone = document.getElementById('mobile-drop-zone');
            if (mobileDropZone) {
                mobileDropZone.addEventListener('dragover', handleDragOver);
                mobileDropZone.addEventListener('dragleave', handleDragLeave);
                mobileDropZone.addEventListener('drop', (e) => {
                    handleDrop(e, true);
                });
            }
            
            // 自动切换到连接标签页
            switchMobileTab('connection');
        }

        // 处理文件选择
        function handleFileSelect(event, isMobile = false) {
            const files = Array.from(event.target.files);
            if (files.length > 0) {
                addFilesToTransferList(files, isMobile);
            }
            event.target.value = '';
        }

        // 处理拖放
        function handleDragOver(event) {
            event.preventDefault();
            event.stopPropagation();
            event.currentTarget.classList.add('dragover');
        }

        function handleDragLeave(event) {
            event.preventDefault();
            event.stopPropagation();
            event.currentTarget.classList.remove('dragover');
        }

        function handleDrop(event, isMobile = false) {
            event.preventDefault();
            event.stopPropagation();
            event.currentTarget.classList.remove('dragover');
            
            const files = Array.from(event.dataTransfer.files);
            if (files.length > 0) {
                addFilesToTransferList(files, isMobile);
            }
        }

        // 添加文件到传输列表
        function addFilesToTransferList(files, isMobile = false) {
            files.forEach(file => {
                const fileId = 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
                
                selectedFiles.push({
                    id: fileId,
                    file: file,
                    name: file.name,
                    size: file.size,
                    type: file.type
                });
                
                addFileToUI({
                    id: fileId,
                    name: file.name,
                    size: file.size,
                    type: file.type
                }, isMobile);
            });
            
            showNotification(`已添加 ${files.length} 个文件`, 'success', '文件添加');
            
            // 启用发送按钮
            if (!isMobile) {
                document.getElementById('send-files-btn').disabled = false;
            } else {
                document.getElementById('mobile-send-files-btn').disabled = false;
            }
        }

        // 添加文件到UI
        function addFileToUI(file, isMobile = false) {
            const fileList = isMobile ? 
                document.getElementById('mobile-files-list') : 
                document.getElementById('files-list');
            
            // 移除空状态
            if (fileList.querySelector('.empty-state')) {
                fileList.innerHTML = '';
            }
            
            const fileElement = document.createElement('div');
            fileElement.className = 'file-item';
            fileElement.id = `file-${file.id}`;
            
            const size = formatBytes(file.size);
            const icon = getFileIcon(file.type);
            
            fileElement.innerHTML = `
                <div class="file-icon">
                    <i class="${icon}"></i>
                </div>
                <div class="file-info">
                    <div class="file-name">${file.name}</div>
                    <div class="file-details">
                        <span>${size}</span>
                        <span>${getFileType(file.type)}</span>
                    </div>
                    <div class="file-progress">
                        <div class="file-progress-bar" id="progress-${file.id}" style="width: 0%"></div>
                    </div>
                </div>
                <button class="btn btn-sm btn-outline">
                    <i class="fas fa-times"></i>
                </button>
            `;
            
            fileList.appendChild(fileElement);
        }

        // 获取文件图标
        function getFileIcon(type) {
            if (type.startsWith('image/')) return 'fas fa-file-image';
            if (type.startsWith('video/')) return 'fas fa-file-video';
            if (type.startsWith('audio/')) return 'fas fa-file-audio';
            if (type === 'application/pdf') return 'fas fa-file-pdf';
            if (type.includes('word')) return 'fas fa-file-word';
            if (type.includes('excel') || type.includes('sheet')) return 'fas fa-file-excel';
            if (type.includes('powerpoint') || type.includes('presentation')) return 'fas fa-file-powerpoint';
            if (type.includes('zip') || type.includes('compressed')) return 'fas fa-file-archive';
            if (type.includes('text/')) return 'fas fa-file-alt';
            return 'fas fa-file';
        }

        // 获取文件类型
        function getFileType(type) {
            if (type.startsWith('image/')) return '图片';
            if (type.startsWith('video/')) return '视频';
            if (type.startsWith('audio/')) return '音频';
            if (type === 'application/pdf') return 'PDF文档';
            if (type.includes('word')) return 'Word文档';
            if (type.includes('excel') || type.includes('sheet')) return 'Excel文档';
            if (type.includes('powerpoint') || type.includes('presentation')) return 'PPT文档';
            if (type.includes('zip') || type.includes('compressed')) return '压缩文件';
            if (type.includes('text/')) return '文本文件';
            return '文件';
        }

        // 从列表中移除文件
        function removeFileFromList(fileId, isMobile = false) {
            // 从selectedFiles中移除
            const index = selectedFiles.findIndex(f => f.id === fileId);
            if (index > -1) {
                selectedFiles.splice(index, 1);
            }
            
            // 从UI中移除
            const fileElement = document.getElementById(`file-${fileId}`);
            if (fileElement) {
                fileElement.remove();
            }
            
            // 如果列表为空,显示空状态
            const desktopList = document.getElementById('files-list');
            const mobileList = document.getElementById('mobile-files-list');
            
            if (selectedFiles.length === 0) {
                if (desktopList.children.length === 0) {
                    desktopList.innerHTML = `
                        <div class="empty-state">
                            <i class="fas fa-file-import"></i>
                            <h4>暂无待传输文件</h4>
                            <p>添加文件并发送给已连接的设备</p>
                        </div>
                    `;
                }
                
                if (mobileList.children.length === 0) {
                    mobileList.innerHTML = `
                        <div class="empty-state">
                            <i class="fas fa-file-import"></i>
                            <h4>暂无待传输文件</h4>
                            <p>添加文件并发送给已连接的设备</p>
                        </div>
                    `;
                }
                
                // 禁用发送按钮
                document.getElementById('send-files-btn').disabled = true;
                document.getElementById('mobile-send-files-btn').disabled = true;
            }
        }

        // 清空文件列表
        function clearFileList() {
            if (selectedFiles.length === 0) {
                showNotification('文件列表已为空', 'info', '操作提示');
                return;
            }
            
            if (confirm(`确定要清空 ${selectedFiles.length} 个文件吗?`)) {
                selectedFiles = [];
                
                const desktopList = document.getElementById('files-list');
                const mobileList = document.getElementById('mobile-files-list');
                
                desktopList.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-file-import"></i>
                        <h4>暂无待传输文件</h4>
                        <p>添加文件并发送给已连接的设备</p>
                    </div>
                `;
                
                mobileList.innerHTML = `
                    <div class="empty-state">
                        <i class="fas fa-file-import"></i>
                        <h4>暂无待传输文件</h4>
                        <p>添加文件并发送给已连接的设备</p>
                    </div>
                `;
                
                // 禁用发送按钮
                document.getElementById('send-files-btn').disabled = true;
                document.getElementById('mobile-send-files-btn').disabled = true;
                
                showNotification('文件列表已清空', 'success', '操作完成');
            }
        }

        // 打开传输文件
        function openTransferFile(transferId) {
            const transfer = transfers.get(transferId);
            if (transfer && transfer.status === 'completed') {
                showNotification('文件已保存在下载文件夹中', 'info', '文件位置');
            }
        }

        // 移除传输记录
        function removeTransfer(transferId) {
            if (confirm('确定要删除此传输记录吗?')) {
                transfers.delete(transferId);
                updateTransfersList();
                updateTransferStats();
                showNotification('传输记录已删除', 'success', '操作完成');
            }
        }

        // 刷新传输列表
        function refreshTransfers() {
            updateTransfersList();
            updateTransferStats();
            showNotification('传输列表已刷新', 'success', '刷新完成');
        }

        // 显示通知
        function showNotification(message, type = 'info', title = '通知') {
            const notifications = document.getElementById('notifications');
            
            const notification = document.createElement('div');
            notification.className = `notification ${type}`;
            
            let icon = 'fas fa-info-circle';
            if (type === 'success') icon = 'fas fa-check-circle';
            if (type === 'error') icon = 'fas fa-exclamation-circle';
            if (type === 'warning') icon = 'fas fa-exclamation-triangle';
            
            notification.innerHTML = `
                <div class="notification-icon">
                    <i class="${icon}"></i>
                </div>
                <div class="notification-content">
                    <div class="notification-title">${title}</div>
                    <div class="notification-message">${message}</div>
                </div>
                <button class="notification-close">
                    <i class="fas fa-times"></i>
                </button>
            `;
            
            notifications.appendChild(notification);
            
            // 自动移除通知
            setTimeout(() => {
                if (notification.parentNode) {
                    notification.remove();
                }
            }, 5000);
        }

        // 清理资源
        function cleanupResources() {
            // 关闭所有连接
            connections.forEach((conn, peerId) => {
                if (conn && conn.open) {
                    conn.close();
                }
            });
            
            // 销毁peer实例
            if (peer && !peer.destroyed) {
                peer.destroy();
            }
            
            // 停止扫码
            stopScanning();
        }

        // 工具函数
        function generateDeviceId() {
            return 'YS_' + Math.random().toString(36).substr(2, 8).toUpperCase();
        }

        function formatBytes(bytes) {
            if (bytes === 0) return '0 B';
            const k = 1024;
            const sizes = ['B', 'KB', 'MB', 'GB'];
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
        }

        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        // 设置事件监听器
        function setupEventListeners() {
            // 桌面版文件输入
            const fileInput = document.getElementById('file-input');
            if (fileInput) {
                fileInput.addEventListener('change', (e) => handleFileSelect(e, false));
            }
            
            // 桌面版拖放区域
            const dropZone = document.getElementById('drop-zone');
            if (dropZone) {
                dropZone.addEventListener('dragover', handleDragOver);
                dropZone.addEventListener('dragleave', handleDragLeave);
                dropZone.addEventListener('drop', (e) => handleDrop(e, false));
            }
            
            // 桌面版连接输入框回车连接
            const peerIdInput = document.getElementById('peer-id-input');
            if (peerIdInput) {
                peerIdInput.addEventListener('keydown', (e) => {
                    if (e.key === 'Enter') {
                        connectToPeer();
                    }
                });
            }
            
            // 移动版连接输入框回车连接
            const mobilePeerIdInput = document.getElementById('mobile-peer-id-input');
            if (mobilePeerIdInput) {
                mobilePeerIdInput.addEventListener('keydown', (e) => {
                    if (e.key === 'Enter') {
                        connectToPeerMobile();
                    }
                });
            }
            
            // 手动输入二维码内容回车连接
            const manualQrInput = document.getElementById('manual-qr-input');
            if (manualQrInput) {
                manualQrInput.addEventListener('keydown', (e) => {
                    if (e.key === 'Enter') {
                        connectFromManualInput();
                    }
                });
            }
            
            // 页面可见性变化时更新状态
            document.addEventListener('visibilitychange', () => {
                if (!document.hidden) {
                    updateConnectedDevicesList();
                    updateTransfersList();
                }
            });
        }

        // 全局函数导出
        window.copyMyId = copyMyId;
        window.connectToPeer = connectToPeer;
        window.connectToPeerMobile = connectToPeerMobile;
        window.sendChatMessage = sendChatMessage;
        window.sendChatMessageMobile = sendChatMessageMobile;
        window.clearChat = clearChat;
        window.sendSelectedFiles = sendSelectedFiles;
        window.sendSelectedFilesMobile = sendSelectedFilesMobile;
        window.clearFileList = clearFileList;
        window.removeFileFromList = removeFileFromList;
        window.disconnectPeer = disconnectPeer;
        window.openQRConnectModal = openQRConnectModal;
        window.closeQRConnectModal = closeQRConnectModal;
        window.switchQRTab = switchQRTab;
        window.downloadQRCode = downloadQRCode;
        window.switchCamera = switchCamera;
        window.stopScanning = stopScanning;
        window.connectFromManualInput = connectFromManualInput;
        window.switchMobileTab = switchMobileTab;
        window.openTransferFile = openTransferFile;
        window.removeTransfer = removeTransfer;
        window.refreshTransfers = refreshTransfers;
        window.copyQRCodeToClipboard = copyQRCodeToClipboard;
        window.showShareInstructions = showShareInstructions;
    </script>
</body>
</html>

免费评分

参与人数 3吾爱币 +9 热心值 +3 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
kiwo + 1 + 1 用心讨论,共获提升!
良有益 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 小鸡眯眼 发表于 2026-1-11 21:39
另外修改的一个版本:https://chuan.diuta.com/
良有益 发表于 2026-1-12 08:14
kiwo 发表于 2026-1-12 08:56
不用登录社交账号就可以使用,在很多场景用还可以
serpentking 发表于 2026-1-12 09:30
是使用蓝牙连接还是必须无线网络连接?
 楼主| 小鸡眯眼 发表于 2026-1-12 21:18
serpentking 发表于 2026-1-12 09:30
是使用蓝牙连接还是必须无线网络连接?

不是,需要网络呢
fandazong 发表于 2026-1-12 23:24
文件大小有限制吗?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-1-13 15:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表