微信版edit icon

创建者:
用户FOELZYVQ
Fork(复制)
下载
嵌入
BUG反馈
index.html
style.css
index.js
index.html
            
            <!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chat Interface</title>
    <script src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js" type="module"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            display: flex;
            justify-content: center;
            align-items: center;
            background-color: transparent; 
        }

        .phone-container {
            width: min(100%, 360px);
            border: 12px solid #1c1c1c; 
            border-radius: 36px;
            background-color: #ededed; 
            position: relative;
            margin: 15px;
            box-shadow: 0 10px 25px rgba(0,0,0,0.2);
            overflow: hidden;
        }
        
        .chat-container {
            width: 100%;
            height: 600px;
            background-color: #ededed; 
            border-radius: 24px;
            overflow: hidden;
            font-family: -apple-system, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", sans-serif; 
            margin: 0 auto;
        }

        .chat-header {
            height: 56px;
            background: rgba(247, 247, 247, 0.95); 
            padding: 0 16px;
            display: flex;
            align-items: center;
            justify-content: space-between; 
            border-bottom: 1px solid rgba(0,0,0,0.08);
            backdrop-filter: blur(10px);
            position: relative; 
        }

        .back-arrow-btn {
            width: 24px;
            height: 24px;
            color: #333;
            cursor: pointer;
            flex-shrink: 0; 
            z-index: 2; 
        }
        
        .chat-header h2 {
            position: absolute; 
            top: 50%; 
            left: 50px; 
            right: 50px; 
            transform: translateY(-50%); 
            margin: 0 auto; 
            text-align: center; 
            font-size: 17px; 
            color: #000; 
            font-weight: 600;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            z-index: 1; 
        }

        .header-icons {
            display: flex;
            gap: 10px; 
            flex-shrink: 0;
            z-index: 2; 
        }

        .header-icon {
            width: 24px;
            height: 24px;
            color: #333; 
        }

        .header-icon:hover {
            color: #000; 
            transform: scale(1.1); 
        }

        /* 手机刘海 */
        .phone-notch {
            position: absolute;
            top: 0;
            left: 50%;
            transform: translateX(-50%);
            width: 160px;
            height: 13px;
            background: #1c1c1c; 
            border-bottom-left-radius: 12px;
            border-bottom-right-radius: 12px;
            z-index: 999;
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 8px;
        }

        .notch-camera, .notch-speaker, .notch-sensor { 
            background: #444;
            border-radius: 50%;
        }
        .notch-camera { width: 8px; height: 8px; border: 2px solid #333; }
        .notch-speaker { width: 40px; height: 4px; border-radius: 2px; }
        .notch-sensor { width: 6px; height: 6px; border: 1px solid #333; }

        .chat-messages {
            height: 492px;
            padding: 16px;
            overflow-y: auto;
        }

        .chat-messages::-webkit-scrollbar { width: 6px; }
        .chat-messages::-webkit-scrollbar-track { background: transparent; }
        .chat-messages::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.1); border-radius: 3px; }

        .message {
            display: flex;
            margin-bottom: 8px;
            align-items: flex-start;
            position: relative;
            animation: message-pop 0.3s ease-out;
        }
        .message.message-is-card { margin-bottom: 16px; }

        @keyframes message-pop {
            from { transform: translateY(10px); opacity: 0; }
            to { transform: translateY(0); opacity: 1; }
        }
        .message.sent { flex-direction: row-reverse; }

        .avatar {
            width: 36px;
            height: 36px;
            border-radius: 8px; 
            margin-top: 4px;
            border: 1px solid rgba(0,0,0,0.05);
            transition: transform 0.2s;
        }
        .avatar:hover { transform: scale(1.1); }
        .message-wrapper { max-width: 70%; display: flex; flex-direction: column; margin: 0 10px; }

        .message-content {
            padding: 10px 14px;
            border-radius: 8px; 
            font-size: 14px;
            line-height: 1.4;
            word-wrap: break-word;
            position: relative;
            transition: transform 0.2s;
        }
        .message-content:hover { transform: translateY(-2px); }

        .received .message-content { background: #fff; color: #000; box-shadow: 0 1px 2px rgba(0,0,0,0.05); border-bottom-left-radius: 2px; }
        .sent .message-content { background: #a9e97a; color: #000; box-shadow: 0 1px 2px rgba(0,0,0,0.05); border-bottom-right-radius: 2px; }

        .message-time { font-size: 11px; color: #b2b2b2; margin-top: 4px; margin-left: 4px; margin-right: 4px; }
        .sent .message-time { text-align: right; }
        .typing-indicator { display: inline-flex; gap: 2px; padding: 2px 4px; margin-top: 2px; animation: none; }

        .typing-dot { width: 3px; height: 3px; background: #999; border-radius: 50%; animation: subtle-typing 1.5s infinite; }

        @keyframes subtle-typing {
            0%, 100% { transform: translateY(0); opacity: 0.5; }
            50% { transform: translateY(-1px); opacity: 0.8; }
        }
        
        .chat-input { height: 52px; background: #f7f7f7; padding: 8px 12px; display: flex; align-items: center; gap: 12px; border-top: 1px solid #e7e7e7; position: relative; }

        .emoji-btn { background: transparent; border: none; color: #333; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: color 0.2s; flex-shrink: 0; padding: 0; width: 28px; height: 28px; }
        .emoji-btn svg { width: 28px; height: 28px; }
        .emoji-btn:hover { color: #000; }
        
        /* 表情选择器容器样式 */
        .emoji-picker-container {
            position: absolute;
            bottom: 60px;
            left: 12px; 
            right: 12px;
            width: auto; 
            display: none; /* 【【【修改点 2: 默认隐藏】】】 */
            background: #f7f7f7; 
            border-radius: 12px;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            z-index: 1000;
        }

        /* 表情选择器内部组件样式 */
        emoji-picker {
            width: 100%; 
            height: 300px;
            /* 【【【修改点 1: 调整列数和尺寸以适应容器】】】 */
            --num-columns: 8; 
            --emoji-size: 1.2rem;
            --category-font-size: 0.9rem;
            /* 统一为灰白主题 */
            --background: #f7f7f7;
            --border-color: #e7e7e7;
            --input-background: #ffffff;
            --input-text-color: #333;
            --category-icon-color: #555;
            --category-icon-hover-color: #000;
            --search-input-focus-background: #fff;
        }

        .input-field { flex: 1; height: 38px; border: none; border-radius: 8px; background: #fff; padding: 0 12px; outline: none; font-size: 14px; color: #333; transition: all 0.2s; margin-right: 0; max-width: calc(100% - 80px); }
        .input-field:focus { border: 1px solid #a9e97a; box-shadow: none; padding: 0 11px; }
        .input-field::placeholder { color: #d1d1d1; }

        .send-btn { background: transparent; border: none; color: #333; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: color 0.2s; flex-shrink: 0; padding: 0; width: 28px; height: 28px; }
        .send-btn svg { width: 24px; height: 24px; }
        .send-btn:hover { color: #000; }
        
        /* TRANSFER MODAL STYLES */
        .transfer-modal { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 90%; max-width: 320px; background: #ffffff; border-radius: 24px; padding: 28px 24px; text-align: center; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); z-index: 1000; animation: modalSlideIn 0.4s cubic-bezier(0.16, 1, 0.3, 1); }
        .transfer-content { display: flex; flex-direction: column; align-items: center; gap: 20px; }
        .transfer-modal .transfer-avatar { width: 96px; height: 96px; border-radius: 12px; border: 2px solid #e0e0e0; padding: 3px; margin-bottom: 4px; object-fit: cover; }
        .transfer-modal .transfer-title { font-size: 16px; font-weight: 500; color: #333; margin: 0; }
        .transfer-form { width: 100%; display: flex; flex-direction: column; gap: 16px; }
        .amount-input-group { display: flex; align-items: center; border: 1px solid #e0e0e0; border-radius: 25px; padding: 0 15px; background: #fff; transition: border-color 0.2s; height: 44px; }
        .amount-input-group:focus-within { border-color: #888; }
        .amount-input { flex: 1; border: none; background: transparent; outline: none; text-align: left; font-size: 16px; color: #333; padding-left: 16px; -moz-appearance: textfield; }
        .amount-input::-webkit-inner-spin-button, .amount-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
        .amount-input::placeholder { color: #ccc; }
        .amount-symbol { font-size: 18px; color: #555; font-weight: 500; }
        .note-input { width: 100%; padding: 10px 16px; height: 44px; border: 1px solid #e0e0e0; border-radius: 25px; background: #fff; font-size: 14px; color: #333; text-align: center; outline: none; transition: border-color 0.2s; }
        .note-input:focus { border-color: #888; }
        .note-input::placeholder { color: #ccc; }
        .transfer-buttons { display: flex; gap: 16px; margin-top: 8px; justify-content: center; }
        .transfer-button { padding: 10px 32px; border-radius: 8px; border: none; font-weight: 600; cursor: pointer; transition: all 0.2s; }
        .confirm-transfer { background: #98d6d0; color: white; }
        .confirm-transfer:hover { background: #89c7c0; transform: translateY(-2px); }
        .cancel-transfer { background: #f0f0f0; color: #555; }
        .cancel-transfer:hover { background: #e0e0e0; transform: translateY(-2px); }

        /* TRANSFER MESSAGE CARD STYLES */
        .transfer-card { background: #fff; border: 1px solid #e9e4f0; border-radius: 10px; padding: 12px 16px; width: fit-content; max-width: 200px; box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08); display: flex; flex-direction: column; gap: 4px; }
        .transfer-card .transfer-header { display: flex; align-items: center; gap: 6px; }
        .transfer-card .transfer-icon { width: 18px; height: 18px; color: #555; }
        .transfer-card .transfer-title { font-size: 14px; font-weight: 500; color: #333; }
        .transfer-card .transfer-amount { font-size: 24px; font-weight: 700; color: #000; text-align: left; line-height: 1.2; margin-left: 24px; }
        .transfer-card .transfer-status-text { font-size: 13px; color: #2E8B57; text-align: left; margin-left: 24px; }
        
        @keyframes modalSlideIn {
            from { opacity: 0; transform: translate(-50%, -45%); }
            to { opacity: 1; transform: translate(-50%, -50%); }
        }

        @media screen and (max-width: 400px) {
            .phone-container { margin: 10px; border-width: 8px; }
            .chat-container { height: 580px; }
            .chat-messages { height: 472px; }
            .message-content { font-size: 13px; }
            .input-field { max-width: calc(100% - 80px); }
        }
      </style>
</head>
<body>
    <div class="phone-container">
        <div class="phone-notch">
            <div class="notch-sensor"></div>
            <div class="notch-camera"></div>
            <div class="notch-speaker"></div>
            <div class="notch-sensor"></div>
        </div>
        <div class="chat-container">
            <div class="transfer-modal" style="display: none;">
                <div class="transfer-content">
                    <img src="https://files.catbox.moe/t511iu.png" class="transfer-avatar" alt="Transfer Avatar">
                    <div class="transfer-title">转账给 $1</div>
                    <div class="transfer-form">
                        <div class="amount-input-group">
                            <input type="number" class="amount-input" placeholder="输入金额...">
                            <span class="amount-symbol">¥</span>
                        </div>
                        <input type="text" class="note-input" placeholder="输入备注...">
                        <div class="transfer-buttons">
                            <button class="transfer-button confirm-transfer">确认</button>
                            <button class="transfer-button cancel-transfer">取消</button>
                        </div>
                    </div>
                </div>
            </div>
            
            <div class="chat-header">
                <svg class="back-arrow-btn" viewBox="0 0 24 24">
                    <path fill="currentColor" d="M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"/>
                </svg>
                <h2>$1</h2>
                <div class="header-icons">
                    <svg class="header-icon transfer-btn" viewBox="0 0 24 24">
                        <path fill="currentColor" d="M20,8H4V6H20M20,18H4V12H20M20,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V6C22,4.89 21.1,4 20,4Z"/>
                    </svg>
                </div>
            </div>
            
            <div class="chat-messages">
$2
            </div>
            <div class="chat-input">
                <button class="emoji-btn">
                    <svg viewBox="0 0 24 24" width="20" height="20">
                        <path fill="currentColor" d="M12,2C6.477,2,2,6.477,2,12c0,5.523,4.477,10,10,10s10-4.477,10-10C22,6.477,17.523,2,12,2z M12,20c-4.418,0-8-3.582-8-8 s3.582-8,8-8s8,3.582,8,8S16.418,20,12,20z M15.5,11c0.828,0,1.5-0.672,1.5-1.5S16.328,8,15.5,8S14,8.672,14,9.5S14.672,11,15.5,11z M8.5,11c0.828,0,1.5-0.672,1.5-1.5S9.328,8,8.5,8S7,8.672,7,9.5S7.672,11,8.5,11z M12,17.5c2.33,0,4.31-1.46,5.11-3.5H6.89 C7.69,16.04,9.67,17.5,12,17.5z"/>
                    </svg>
                </button>
                <div class="emoji-picker-container">
                    <emoji-picker></emoji-picker>
                </div>
                <input type="text" class="input-field" placeholder="输入聊天内容...">
                <button class="send-btn">
                    <svg viewBox="0 0 24 24" width="20" height="20">
                        <path fill="currentColor" d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
                    </svg>
                </button>
            </div>
        </div>
    </div>
    <script>
document.addEventListener('DOMContentLoaded', function() {
    const emojiBtn = document.querySelector('.emoji-btn');
    const emojiPickerContainer = document.querySelector('.emoji-picker-container');
    const emojiPicker = document.querySelector('emoji-picker');
    const textInput = document.querySelector('.input-field');
    const sendBtn = document.querySelector('.send-btn');
    const chatMessages = document.querySelector('.chat-messages');

    // 转账弹窗相关
    const transferBtn = document.querySelector('.transfer-btn');
    const transferModal = document.querySelector('.transfer-modal');
    const cancelTransferBtn = document.querySelector('.cancel-transfer');
    const confirmTransferBtn = document.querySelector('.confirm-transfer');
    const amountInput = document.querySelector('.amount-input');
    const noteInput = document.querySelector('.note-input');

    // 转账按钮点击事件
    transferBtn.addEventListener('click', () => {
        playSound('click');
        transferModal.style.display = 'block';
        setTimeout(() => amountInput.focus(), 300);
    });

    cancelTransferBtn.addEventListener('click', () => {
        playSound('click');
        transferModal.style.display = 'none';
    });

    confirmTransferBtn.addEventListener('click', () => {
        const amount = amountInput.value.trim();
        const note = noteInput.value.trim();

        if (!amount || isNaN(amount) || Number(amount) <= 0) {
            amountInput.parentNode.classList.add('shake');
            setTimeout(() => amountInput.parentNode.classList.remove('shake'), 500);
            return;
        }

        playSound('send');
        transferModal.style.display = 'none';

        const chatName = document.querySelector('.chat-header h2').textContent;
        let transferCommand = note ? `[user转账给${chatName}:${amount}|${note}]` : `[user转账给${chatName}:${amount}]`;
        
        if (typeof triggerSlash === 'function') {
            triggerSlash(`/send ${transferCommand}|/trigger`);
        } else {
            // 本地测试预览逻辑
            console.log("将发送指令: ", transferCommand);
            const lastMessage = chatMessages.querySelector('.message:last-child');
            let lastTimeStr = '11:47'; 
            if (lastMessage) { lastTimeStr = lastMessage.querySelector('.message-time').textContent; }
            const [hours, minutes] = lastTimeStr.split(':').map(Number);
            let newMinutes = minutes + 1;
            let newHours = hours;
            if (newMinutes >= 60) {
                newMinutes = 0;
                newHours = (newHours + 1) % 24;
            }
            const timeString = `${newHours.toString().padStart(2, '0')}:${newMinutes.toString().padStart(2, '0')}`;
            const bankIconSvg = `<svg class="transfer-icon" viewBox="0 0 24 24"><path fill="currentColor" d="M4,10V7H6V10H4M10,10V7H12V10H10M16,10V7H18V10H16M20,20H2V12L11,3.05L20,12V20M4,18H8V14H4V18M10,18H14V14H10V18M16,18H20V14H16V18Z"/></svg>`;
            
            const messageHtml = `
                <div class="message sent message-is-card">
                    <div class="user_avatar avatar" style="background-size: cover; background-position: center;"></div>
                    <div class="message-wrapper">
                        <div class="transfer-card">
                            <div class="transfer-header">
                                ${bankIconSvg}
                                <div class="transfer-title">转账给${chatName}</div>
                            </div>
                            <div class="transfer-amount">¥${amount}</div>
                            <div class="transfer-status-text">转账成功</div>
                            ${note ? `<div class="transfer-note" style="font-size:12px;color:#888;margin-top:4px;">备注: ${note}</div>` : ''}
                        </div>
                        <div class="message-time">${timeString}</div>
                    </div>
                </div>`;
            chatMessages.insertAdjacentHTML('beforeend', messageHtml);
            chatMessages.scrollTop = chatMessages.scrollHeight;
        }
    });

    amountInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') noteInput.focus(); });
    noteInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') confirmTransferBtn.click(); });

    const shakeStyle = document.createElement('style');
    shakeStyle.textContent = `
        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            20%, 60% { transform: translateX(-5px); }
            40%, 80% { transform: translateX(5px); }
        }
        .shake { animation: shake 0.5s ease-in-out; border-color: #ff4d4f !important; }
    `;
    document.head.appendChild(shakeStyle);

    const sounds = {
        click: new Audio('https://assets.mixkit.co/active_storage/sfx/2568/2568-preview.mp3'),
        send: new Audio('https://assets.mixkit.co/active_storage/sfx/2570/2570-preview.mp3'),
        emoji: new Audio('https://files.catbox.moe/gb0so5.mp3'),
        bubble: new Audio('https://assets.mixkit.co/active_storage/sfx/2568/2568-preview.mp3'),
        avatar: new Audio('https://assets.mixkit.co/active_storage/sfx/2575/2575-preview.mp3')
    };

    function playSound(soundType) {
        if (sounds[soundType]) { 
            sounds[soundType].currentTime = 0; 
            sounds[soundType].play().catch(e => console.error("音频播放失败:", e));
        }
    }
    
    // 表情按钮点击事件 - 【【【核心修改点 2: 实现开关逻辑】】】
    emojiBtn.addEventListener('click', () => {
        playSound('emoji');
        const isVisible = emojiPickerContainer.style.display === 'block';
        emojiPickerContainer.style.display = isVisible ? 'none' : 'block';
    });

    // 选择表情事件
    emojiPicker.addEventListener('emoji-click', (event) => {
        playSound('click');
        const emoji = event.detail.unicode;
        const start = textInput.selectionStart;
        const end = textInput.selectionEnd;
        textInput.value = textInput.value.slice(0, start) + emoji + textInput.value.slice(end);
        const newCursorPosition = start + emoji.length;
        textInput.setSelectionRange(newCursorPosition, newCursorPosition);
        emojiPickerContainer.style.display = 'none';
        textInput.focus();
    });

    // 发送按钮点击事件
    sendBtn.addEventListener('click', () => {
        const messageText = textInput.value.trim();
        if (messageText) {
            playSound('send');
            if (typeof triggerSlash === 'function') {
                triggerSlash(`/send 回复和$1的聊天:${messageText}|/trigger`);
            }
            // 本地预览逻辑... (保持不变)
            const lastMessage = chatMessages.querySelector('.message:last-child');
            let lastTimeStr = '11:47';
            if (lastMessage) { lastTimeStr = lastMessage.querySelector('.message-time').textContent; }
            const [hours, minutes] = lastTimeStr.split(':').map(Number);
            let newMinutes = minutes + 1;
            let newHours = hours;
            if (newMinutes >= 60) { newMinutes = 0; newHours = (newHours + 1) % 24; }
            const timeString = `${newHours.toString().padStart(2, '0')}:${newMinutes.toString().padStart(2, '0')}`;
            const messageHtml = `
                <div class="message sent">
                    <div class="user_avatar avatar" style="background-size: cover; background-position: center;"></div>
                    <div class="message-wrapper">
                        <div class="message-content">${messageText}</div>
                        <div class="message-time">${timeString}</div>
                    </div>
                </div>`;
            chatMessages.insertAdjacentHTML('beforeend', messageHtml);
            const newAvatar = chatMessages.lastElementChild.querySelector('.avatar');
            const newContent = chatMessages.lastElementChild.querySelector('.message-content');
            newAvatar.addEventListener('click', () => playSound('avatar'));
            newContent.addEventListener('click', () => playSound('bubble'));
            chatMessages.scrollTop = chatMessages.scrollHeight;
            textInput.value = '';
        }
    });
    textInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') sendBtn.click(); });

    // 点击外部关闭表情选择器
    document.addEventListener('click', (e) => {
        if (!emojiBtn.contains(e.target) && !emojiPickerContainer.contains(e.target)) {
            emojiPickerContainer.style.display = 'none';
        }
    });

    Object.values(sounds).forEach(sound => sound.load());

    // 动态监听新消息的MutationObserver
    const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            if (mutation.addedNodes.length) {
                mutation.addedNodes.forEach((node) => {
                    if (node.nodeType === 1) { 
                        const newAvatars = node.querySelectorAll('.avatar');
                        const newContents = node.querySelectorAll('.message-content, .transfer-card');
                        newAvatars.forEach(avatar => avatar.addEventListener('click', () => playSound('avatar')));
                        newContents.forEach(content => content.addEventListener('click', () => playSound('bubble')));
                    }
                });
            }
        });
    });
    observer.observe(chatMessages, { childList: true, subtree: true });
});

(function showMessages() {
    const receivedMessages = Array.from(document.querySelectorAll('.message.received'));
    const messageSound = new Audio('https://files.catbox.moe/b4amzm.mp3');

    function isLatestInterface() {
        const currentTimestamp = Date.now();
        const lastTimestamp = parseInt(localStorage.getItem('lastInterfaceTimestamp') || '0');
        localStorage.setItem('lastInterfaceTimestamp', currentTimestamp.toString());
        return (currentTimestamp - lastTimestamp) > 100;
    }

    if (!isLatestInterface() || document.querySelectorAll('.message.sent').length === 0) {
        receivedMessages.forEach(msg => {
            msg.style.display = 'flex';
            messageSound.currentTime = 0;
            messageSound.play();
        });
        return;
    }

    receivedMessages.forEach(msg => msg.style.display = 'none');
    function getRandomTime(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); }

    function typeMessage(messageContent, originalContent, onComplete) {
        if (originalContent.includes('<div') || originalContent.includes('<img')) {
            messageContent.innerHTML = originalContent;
            messageSound.currentTime = 0;
            messageSound.play();
            onComplete();
            return;
        }
        const typingIndicator = document.createElement('div');
        typingIndicator.className = 'typing-indicator';
        typingIndicator.innerHTML = '<span class="typing-dot"></span><span class="typing-dot"></span><span class="typing-dot"></span>';
        messageContent.textContent = '';
        messageContent.appendChild(typingIndicator);
        setTimeout(() => {
            typingIndicator.style.transition = 'opacity 0.5s';
            typingIndicator.style.opacity = '0';
            setTimeout(() => {
                typingIndicator.remove();
                messageContent.textContent = '';
                let charIndex = 0;
                const typeChar = () => {
                    if (charIndex === 0) { messageSound.currentTime = 0; messageSound.play(); }
                    if (charIndex < originalContent.length) {
                        messageContent.textContent += originalContent.charAt(charIndex++);
                        setTimeout(typeChar, 50);
                    } else {
                        onComplete();
                    }
                };
                typeChar();
            }, 500);
        }, getRandomTime(1000, 3000));
    }

    function showMessagesSequentially(messages, index = 0) {
        if (index >= messages.length) return;
        const message = messages[index];
        const messageContent = message.querySelector('.message-content, .transfer-card');
        if (!messageContent) return; 
        const originalContent = messageContent.innerHTML;
        message.style.display = 'flex';
        typeMessage(messageContent, originalContent, () => {
            setTimeout(() => showMessagesSequentially(messages, index + 1), getRandomTime(500, 1500));
        });
    }
    
    setTimeout(() => showMessagesSequentially(receivedMessages), 1000);
})();
    </script>
</body>
</html>
        
编辑器加载中
预览
控制台