导出DeepSeek回答为图片 | Export DeepSeek Answer to Image

将DeepSeek的回答导出为一张图片,支持选择多个聊天内容和添加用户头像

// ==UserScript==
// @name         导出DeepSeek回答为图片 | Export DeepSeek Answer to Image
// @namespace    http://github.com/byronleeeee/exportDeepseek
// @version      1.2
// @description  将DeepSeek的回答导出为一张图片,支持选择多个聊天内容和添加用户头像
// @author       ByronLeeeee
// @match        *://chat.deepseek.com/*
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // i18n translations
    const i18n = {
        'zh': {
            exportBtn: '导出AI回答为图片',
            notFound: 'AI回答区域未找到!',
            selectScheme: '选择配色方案:',
            footer: '回答来自DeepSeek,仅供参考',
            lastAnswer: '最新回答',
            multiSelectMode: '多选模式',
            exportSelected: '导出选中的对话',
            selectAll: '全选',
            deselectAll: '取消全选',
            userMessage: '用户',
            aiMessage: 'AI',
            selectItems: '请选择要导出的对话内容:',
            noItemsSelected: '请至少选择一个对话内容',
            colorSchemes: [
                { name: '白色-蓝色', top: '#FFFFFF', bottom: '#4D6BFE', textTop: '#000000', textBottom: '#FFFFFF' },
                { name: '黑色-金色', top: '#121212', bottom: '#FFD700', textTop: '#FFFFFF', textBottom: '#000000' },
                { name: '浅灰-青色', top: '#F5F5F5', bottom: '#008080', textTop: '#000000', textBottom: '#FFFFFF' },
                { name: '深灰-紫色', top: '#333333', bottom: '#800080', textTop: '#FFFFFF', textBottom: '#FFFFFF' }
            ],
            error: '生成图片失败,请查看控制台了解详情。',
            cancel: '取消',
            export: '导出',
            next: '下一步',
            back: '返回',
            addCreator: '添加生成者信息',
            creatorName: '生成者名称',
            creatorPlaceholder: '输入你的名字',
            addAvatar: '添加用户头像'
        },
        'en': {
            exportBtn: 'Export AI Answer to Image',
            notFound: 'AI answer div not found!',
            selectScheme: 'Select a color scheme:',
            footer: 'Answer from DeepSeek, for reference only',
            lastAnswer: 'Last Answer',
            multiSelectMode: 'Multi-select Mode',
            exportSelected: 'Export Selected Items',
            selectAll: 'Select All',
            deselectAll: 'Deselect All',
            userMessage: 'User',
            aiMessage: 'AI',
            selectItems: 'Please select chat items to export:',
            noItemsSelected: 'Please select at least one chat item',
            colorSchemes: [
                { name: 'White-Blue', top: '#FFFFFF', bottom: '#4D6BFE', textTop: '#000000', textBottom: '#FFFFFF' },
                { name: 'Black-Gold', top: '#121212', bottom: '#FFD700', textTop: '#FFFFFF', textBottom: '#000000' },
                { name: 'Light Gray-Teal', top: '#F5F5F5', bottom: '#008080', textTop: '#000000', textBottom: '#FFFFFF' },
                { name: 'Dark Gray-Purple', top: '#333333', bottom: '#800080', textTop: '#FFFFFF', textBottom: '#FFFFFF' }
            ],
            error: 'Failed to generate image. Check console for details.',
            cancel: 'Cancel',
            export: 'Export',
            next: 'Next',
            back: 'Back',
            addCreator: 'Add creator info',
            creatorName: 'Creator name',
            creatorPlaceholder: 'Enter your name',
            addAvatar: 'Add user avatar'
        }
    };

    const userLang = (navigator.language || navigator.userLanguage).split('-')[0];
    const lang = i18n[userLang] ? userLang : 'en';
    const texts = i18n[lang];

    // Add styles with dark mode support
    function addStyles() {
        const style = document.createElement('style');
        style.textContent = `
            .ai-export-fab {
                position: fixed;
                bottom: 24px;
                right: 24px;
                width: 56px;
                height: 56px;
                border-radius: 50%;
                background-color: #4D6BFE;
                color: white;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                box-shadow: 0 4px 8px rgba(0,0,0,0.2);
                z-index: 9999;
                transition: all 0.3s ease;
            }
            .ai-export-fab:hover {
                transform: scale(1.05);
                box-shadow: 0 6px 12px rgba(0,0,0,0.3);
            }
            .ai-export-fab-icon {
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .ai-export-tooltip {
                position: absolute;
                background: rgba(0,0,0,0.7);
                color: white;
                padding: 5px 10px;
                border-radius: 4px;
                font-size: 12px;
                white-space: nowrap;
                right: 70px;
                opacity: 0;
                transition: opacity 0.3s;
                pointer-events: none;
            }
            .ai-export-fab:hover .ai-export-tooltip {
                opacity: 1;
            }
            .ai-color-scheme-modal {
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background-color: rgba(0,0,0,0.5);
                display: flex;
                align-items: center;
                justify-content: center;
                z-index: 10000;
            }
            .ai-modal-content {
                background-color: white;
                border-radius: 8px;
                padding: 20px;
                width: 400px;
                max-width: 90%;
                color: #000000;
            }
            body.dark .ai-modal-content {
                background-color: #1e1e1e;
                color: #ffffff;
            }
            .ai-modal-header {
                font-size: 18px;
                font-weight: bold;
                margin-bottom: 15px;
            }
            .ai-scheme-options {
                display: grid;
                grid-template-columns: 1fr 1fr;
                gap: 10px;
                margin-bottom: 15px;
            }
            .ai-scheme-option {
                border: 2px solid transparent;
                border-radius: 6px;
                overflow: hidden;
                cursor: pointer;
                transition: all 0.2s;
            }
            .ai-scheme-option:hover {
                transform: translateY(-2px);
            }
            .ai-scheme-option.selected {
                border-color: #4D6BFE;
            }
            .ai-scheme-preview {
                display: flex;
                flex-direction: column;
                height: 100px;
            }
            .ai-scheme-top {
                flex: 3;
                display: flex;
                align-items: center;
                justify-content: center;
                font-weight: bold;
            }
            .ai-scheme-bottom {
                flex: 1;
                display: flex;
                align-items: center;
                justify-content: center;
                font-size: 12px;
            }
            .ai-modal-buttons {
                display: flex;
                justify-content: flex-end;
                gap: 10px;
            }
            .ai-modal-button {
                padding: 8px 16px;
                border-radius: 4px;
                border: none;
                cursor: pointer;
                font-weight: bold;
            }
            .ai-modal-button.primary {
                background-color: #4D6BFE;
                color: white;
            }
            .ai-modal-button.secondary {
                background-color: #f1f1f1;
                color: #333;
            }
            body.dark .ai-modal-button.secondary {
                background-color: #333333;
                color: #ffffff;
            }
            .ai-export-button {
                position: absolute;
                top: 10px;
                right: 10px;
                background-color: #4D6BFE;
                color: white;
                border: none;
                border-radius: 4px;
                padding: 4px 8px;
                font-size: 12px;
                cursor: pointer;
                opacity: 0;
                transition: opacity 0.2s;
                z-index: 100;
            }
            ._4f9bf79:hover .ai-export-button,
            .fbb737a4:hover .ai-export-button {
                opacity: 1;
            }
            .ai-creator-option {
                margin: 15px 0;
            }
            .ai-creator-checkbox {
                margin-right: 8px;
            }
            .ai-creator-input {
                margin-top: 8px;
                width: 100%;
                padding: 8px;
                border-radius: 4px;
                border: 1px solid #ccc;
                box-sizing: border-box;
                display: none;
            }
            body.dark .ai-creator-input {
                background-color: #333;
                color: #fff;
                border-color: #555;
            }
            .ai-chat-selection {
                max-height: 50vh;
                overflow-y: auto;
                margin: 15px 0;
                border: 1px solid #eee;
                border-radius: 8px;
                padding: 10px;
            }
            body.dark .ai-chat-selection {
                border-color: #333;
            }
            .ai-chat-item {
                display: flex;
                align-items: center;
                padding: 8px;
                margin: 5px 0;
                border-radius: 4px;
                background-color: #f9f9f9;
                border-left: 4px solid transparent;
                transition: all 0.2s;
            }
            body.dark .ai-chat-item {
                background-color: #2a2a2a;
            }
            .ai-chat-item:hover {
                background-color: #f1f1f1;
            }
            body.dark .ai-chat-item:hover {
                background-color: #333;
            }
            .ai-chat-item.ai {
                border-left-color: #4D6BFE;
            }
            .ai-chat-item.user {
                border-left-color: #6FCF97;
            }
            .ai-chat-checkbox {
                margin-right: 10px;
            }
            .ai-chat-preview {
                flex-grow: 1;
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
                font-size: 14px;
            }
            .ai-chat-type {
                font-size: 12px;
                padding: 2px 6px;
                border-radius: 10px;
                margin-left: 8px;
            }
            .ai-chat-type.ai {
                background-color: #E1E7FF;
                color: #4D6BFE;
            }
            body.dark .ai-chat-type.ai {
                background-color: #2a3a70;
                color: #8aa3ff;
            }
            .ai-chat-type.user {
                background-color: #E3F9EB;
                color: #6FCF97;
            }
            body.dark .ai-chat-type.user {
                background-color: #2a4a3a;
                color: #8ae0a9;
            }
            .ai-selection-actions {
                display: flex;
                justify-content: space-between;
                margin-bottom: 10px;
            }
            .ai-selection-buttons {
                display: flex;
                gap: 8px;
            }
            .ai-select-button {
                font-size: 12px;
                padding: 4px 8px;
                background-color: #f1f1f1;
                border: none;
                border-radius: 4px;
                cursor: pointer;
            }
            body.dark .ai-select-button {
                background-color: #333;
                color: #fff;
            }
            .ai-select-button:hover {
                background-color: #e1e1e1;
            }
            body.dark .ai-select-button:hover {
                background-color: #444;
            }
            .ai-chat-wrapper {
                display: flex;
                align-items: flex-start;
                justify-content: space-between;
                margin-bottom: 15px;
                padding: 10px;
            }
            .ai-chat-content {
                flex-grow: 1;
            }
            .ai-user-avatar {
                width: 32px;
                height: 32px;
                border-radius: 50%;
                margin-left: 10px;
            }
        `;
        document.head.appendChild(style);
    }

    // Create FAB
    function createFAB() {
        const fab = document.createElement('div');
        fab.innerHTML = `
            <div class="ai-export-fab">
                <div class="ai-export-fab-icon">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
                        <polyline points="7 10 12 15 17 10"></polyline>
                        <line x1="12" y1="15" x2="12" y2="3"></line>
                    </svg>
                </div>
                <span class="ai-export-tooltip">${texts.multiSelectMode}</span>
            </div>
        `;
        document.body.appendChild(fab);

        fab.querySelector('.ai-export-fab').addEventListener('click', () => {
            showMultiSelectModal();
        });
    }

    // Add export buttons to each message
    function addExportButtonsToMessages() {
        const observer = new MutationObserver(() => {
            const aiDivs = document.querySelectorAll('div._4f9bf79._43c05b5');
            aiDivs.forEach(aiDiv => {
                if (!aiDiv.querySelector('.ai-export-button')) {
                    const exportButton = document.createElement('button');
                    exportButton.className = 'ai-export-button';
                    exportButton.textContent = texts.exportBtn;
                    exportButton.addEventListener('click', () => {
                        showColorSchemeModal([aiDiv], false);
                    });

                    const parentDiv = aiDiv.closest('.ds-relative') || aiDiv;
                    parentDiv.style.position = 'relative';
                    parentDiv.appendChild(exportButton);
                }
            });

            const userDivs = document.querySelectorAll('div.fbb737a4');
            userDivs.forEach(userDiv => {
                if (!userDiv.querySelector('.ai-export-button')) {
                    const exportButton = document.createElement('button');
                    exportButton.className = 'ai-export-button';
                    exportButton.textContent = texts.exportBtn;
                    exportButton.addEventListener('click', () => {
                        showColorSchemeModal([userDiv], false);
                    });

                    const parentDiv = userDiv.closest('.ds-relative') || userDiv;
                    parentDiv.style.position = 'relative';
                    parentDiv.appendChild(exportButton);
                }
            });
        });

        observer.observe(document.body, { childList: true, subtree: true });

        const aiDivs = document.querySelectorAll('div._4f9bf79._43c05b5');
        aiDivs.forEach(aiDiv => {
            if (!aiDiv.querySelector('.ai-export-button')) {
                const exportButton = document.createElement('button');
                exportButton.className = 'ai-export-button';
                exportButton.textContent = texts.exportBtn;
                exportButton.addEventListener('click', () => {
                    showColorSchemeModal([aiDiv], false);
                });

                const parentDiv = aiDiv.closest('.ds-relative') || aiDiv;
                parentDiv.style.position = 'relative';
                parentDiv.appendChild(exportButton);
            }
        });

        const userDivs = document.querySelectorAll('div.fbb737a4');
        userDivs.forEach(userDiv => {
            if (!userDiv.querySelector('.ai-export-button')) {
                const exportButton = document.createElement('button');
                exportButton.className = 'ai-export-button';
                exportButton.textContent = texts.exportBtn;
                exportButton.addEventListener('click', () => {
                    showColorSchemeModal([userDiv], false);
                });

                const parentDiv = userDiv.closest('.ds-relative') || userDiv;
                parentDiv.style.position = 'relative';
                parentDiv.appendChild(exportButton);
            }
        });
    }

    // Show multi-select modal
    function showMultiSelectModal() {
        const aiDivs = Array.from(document.querySelectorAll('div._4f9bf79._43c05b5'));
        const userDivs = Array.from(document.querySelectorAll('div.fbb737a4'));

        if (!aiDivs.length && !userDivs.length) {
            alert(texts.notFound);
            return;
        }

        const allMessages = [...aiDivs, ...userDivs].sort((a, b) => {
            const position = a.compareDocumentPosition(b);
            return position & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
        });

        const modal = document.createElement('div');
        modal.className = 'ai-color-scheme-modal';

        modal.innerHTML = `
            <div class="ai-modal-content">
                <div class="ai-modal-header">${texts.selectItems}</div>

                <div class="ai-selection-actions">
                    <div class="ai-selection-buttons">
                        <button class="ai-select-button" id="ai-select-all">${texts.selectAll}</button>
                        <button class="ai-select-button" id="ai-deselect-all">${texts.deselectAll}</button>
                    </div>
                </div>

                <div class="ai-chat-selection">
                    ${allMessages.map((div, index) => {
            const isAI = div.classList.contains('_4f9bf79');
            const type = isAI ? 'ai' : 'user';
            const label = isAI ? texts.aiMessage : texts.userMessage;
            let content;
            if (isAI) {
                content = div.textContent.trim();
            } else {
                // For user messages, remove ai-export-button and afb1eea3
                const tempDiv = div.cloneNode(true);
                const exportButton = tempDiv.querySelector('.ai-export-button');
                if (exportButton) exportButton.remove();
                const afb1eea3 = tempDiv.querySelector('.afb1eea3');
                if (afb1eea3) afb1eea3.remove();
                content = tempDiv.textContent.trim();
            }
            if (content.length > 60) content = content.substring(0, 57) + '...';

            return `
                            <div class="ai-chat-item ${type}" data-index="${index}">
                                <input type="checkbox" class="ai-chat-checkbox" id="chat-item-${index}" ${isAI ? 'checked' : ''}>
                                <label class="ai-chat-preview" for="chat-item-${index}">${content}</label>
                                <span class="ai-chat-type ${type}">${label}</span>
                            </div>
                        `;
        }).join('')}
                </div>

                <div class="ai-modal-buttons">
                    <button class="ai-modal-button secondary" id="ai-cancel-btn">${texts.cancel}</button>
                    <button class="ai-modal-button primary" id="ai-continue-btn">${texts.next}</button>
                </div>
            </div>
        `;

        document.body.appendChild(modal);

        modal.querySelector('#ai-select-all').addEventListener('click', () => {
            modal.querySelectorAll('.ai-chat-checkbox').forEach(checkbox => {
                checkbox.checked = true;
            });
        });

        modal.querySelector('#ai-deselect-all').addEventListener('click', () => {
            modal.querySelectorAll('.ai-chat-checkbox').forEach(checkbox => {
                checkbox.checked = false;
            });
        });

        modal.querySelector('#ai-cancel-btn').addEventListener('click', () => {
            document.body.removeChild(modal);
        });

        modal.querySelector('#ai-continue-btn').addEventListener('click', () => {
            const selectedIndices = [];
            modal.querySelectorAll('.ai-chat-checkbox').forEach((checkbox, i) => {
                if (checkbox.checked) {
                    const itemIndex = parseInt(checkbox.closest('.ai-chat-item').dataset.index);
                    selectedIndices.push(itemIndex);
                }
            });

            if (selectedIndices.length === 0) {
                alert(texts.noItemsSelected);
                return;
            }

            const selectedDivs = selectedIndices.map(index => allMessages[index]);
            document.body.removeChild(modal);
            showColorSchemeModal(selectedDivs, true);
        });
    }

    // Show color scheme modal
    function showColorSchemeModal(selectedDivs, isMultiSelect) {
        const modal = document.createElement('div');
        modal.className = 'ai-color-scheme-modal';
        let selectedSchemeIndex = 0;
        let creatorName = '';
        let addCreatorInfo = false;
        let addUserAvatar = false;

        const profileNameElement = document.querySelector('.ds-dropdown-menu-option__label');
        const defaultCreatorName = profileNameElement ? profileNameElement.textContent.trim() : '';

        modal.innerHTML = `
            <div class="ai-modal-content">
                <div class="ai-modal-header">${texts.selectScheme}</div>
                <div class="ai-scheme-options">
                    ${texts.colorSchemes.map((scheme, index) => `
                        <div class="ai-scheme-option ${index === 0 ? 'selected' : ''}" data-index="${index}">
                            <div class="ai-scheme-preview">
                                <div class="ai-scheme-top" style="background-color:${scheme.top};color:${scheme.textTop}">AI</div>
                                <div class="ai-scheme-bottom" style="background-color:${scheme.bottom};color:${scheme.textBottom}">DeepSeek</div>
                            </div>
                        </div>
                    `).join('')}
                </div>
                <div class="ai-creator-option">
                    <label>
                        <input type="checkbox" class="ai-creator-checkbox" ${defaultCreatorName ? 'checked' : ''}>
                        ${texts.addCreator}
                    </label>
                    <input type="text" class="ai-creator-input" placeholder="${texts.creatorPlaceholder}"
                           value="${defaultCreatorName}" ${defaultCreatorName ? '' : 'disabled'}>
                </div>
                <div class="ai-creator-option">
                    <label>
                        <input type="checkbox" class="ai-avatar-checkbox">
                        ${texts.addAvatar}
                    </label>
                </div>
                <div class="ai-modal-buttons">
                    ${isMultiSelect ? `<button class="ai-modal-button secondary" id="ai-back-btn">${texts.back}</button>` : ''}
                    <button class="ai-modal-button secondary" id="ai-cancel-btn">${texts.cancel}</button>
                    <button class="ai-modal-button primary" id="ai-export-btn">${texts.export}</button>
                </div>
            </div>
        `;

        document.body.appendChild(modal);

        const schemeOptions = modal.querySelectorAll('.ai-scheme-option');
        schemeOptions.forEach(option => {
            option.addEventListener('click', () => {
                schemeOptions.forEach(opt => opt.classList.remove('selected'));
                option.classList.add('selected');
                selectedSchemeIndex = parseInt(option.dataset.index);
            });
        });

        const creatorCheckbox = modal.querySelector('.ai-creator-checkbox');
        const creatorInput = modal.querySelector('.ai-creator-input');
        const avatarCheckbox = modal.querySelector('.ai-avatar-checkbox');

        creatorCheckbox.addEventListener('change', () => {
            addCreatorInfo = creatorCheckbox.checked;
            creatorInput.disabled = !addCreatorInfo;
            creatorInput.style.display = addCreatorInfo ? 'block' : 'none';
        });

        avatarCheckbox.addEventListener('change', () => {
            addUserAvatar = avatarCheckbox.checked;
        });

        addCreatorInfo = creatorCheckbox.checked;
        creatorInput.style.display = addCreatorInfo ? 'block' : 'none';

        if (isMultiSelect) {
            modal.querySelector('#ai-back-btn').addEventListener('click', () => {
                document.body.removeChild(modal);
                showMultiSelectModal();
            });
        }

        modal.querySelector('#ai-cancel-btn').addEventListener('click', () => {
            document.body.removeChild(modal);
        });

        modal.querySelector('#ai-export-btn').addEventListener('click', async () => {
            creatorName = creatorInput.value.trim();
            document.body.removeChild(modal);
            await generateAndDownloadImage(selectedDivs, texts.colorSchemes[selectedSchemeIndex], texts, addCreatorInfo, creatorName, addUserAvatar);
        });
    }

    // Default SVG avatar (centered)
    const defaultAvatarSVG = `
<svg class="icon" style="vertical-align: middle; overflow: hidden; height: 30px; width: 30px;" viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M513 0c282.77 0 512 229.23 512 512s-229.23 512-512 512S1 794.77 1 512 230.23 0 513 0z m0 64C265.576 64 65 264.576 65 512c0 115.941 44.042 221.595 116.31 301.145 22.403-109.033 102.365-198.376 208.446-238.033l3.803-1.398-2.002-1.221C325.214 531.546 281 458.186 281 374.5 281 246.094 385.094 142 513.5 142S746 246.094 746 374.5c0 83.842-44.379 157.318-110.927 198.22l-2.012 1.223 3.804 1.405c105.77 39.776 185.46 128.986 207.816 237.803C916.953 733.606 961 627.947 961 512c0-247.424-200.576-448-448-448z" fill="#737373"></path></svg>
    `;

    // Generate and download image
    async function generateAndDownloadImage(selectedDivs, colorScheme, texts, addCreatorInfo, creatorName, addUserAvatar) {
        const container = document.createElement('div');
        container.style.width = '600px';
        container.style.borderRadius = '10px';
        container.style.overflow = 'hidden';
        container.style.boxShadow = '0 4px 8px rgba(0,0,0,0.1)';
        container.style.display = 'flex';
        container.style.flexDirection = 'column';

        const topSection = document.createElement('div');
        topSection.style.padding = '20px';
        topSection.style.backgroundColor = colorScheme.top;
        topSection.style.color = colorScheme.textTop;

        // Get user avatar if selected, otherwise use default
        let userAvatar = null;
        if (addUserAvatar) {
            const avatarImg = document.querySelector('img.fdf01f38');
            if (avatarImg) {
                userAvatar = avatarImg.cloneNode(true);
                userAvatar.className = 'ai-user-avatar';
                userAvatar.removeAttribute('aria-hidden');
            }
        }
        if (!userAvatar) {
            const avatarContainer = document.createElement('div');
            avatarContainer.innerHTML = defaultAvatarSVG;
            userAvatar = avatarContainer.firstElementChild;
        }

        selectedDivs.forEach(div => {
            const isAI = div.classList.contains('_4f9bf79');
            let contentDiv;

            const chatWrapper = document.createElement('div');
            chatWrapper.className = 'ai-chat-wrapper';

            if (isAI) {
                // For AI messages, clone the full div and remove unwanted elements
                contentDiv = div.cloneNode(true);
                const buttonDiv = contentDiv.querySelector('.ds-flex[style*="margin-top"]');
                if (buttonDiv) buttonDiv.remove();
            } else {
                // For user messages, create a new div with only the text content from fbb737a4
                contentDiv = document.createElement('div');
                contentDiv.className = 'fbb737a4 ai-chat-content';
                // Clone the div and remove export button and afb1eea3 before getting text
                const tempDiv = div.cloneNode(true);
                const exportButton = tempDiv.querySelector('.ai-export-button');
                if (exportButton) exportButton.remove();
                const afb1eea3 = tempDiv.querySelector('.afb1eea3');
                if (afb1eea3) afb1eea3.remove();
                contentDiv.textContent = tempDiv.textContent.trim();
            }

            chatWrapper.appendChild(contentDiv);

            // Add avatar on the right for user messages
            if (!isAI) {
                const avatarClone = userAvatar.cloneNode(true);
                chatWrapper.appendChild(avatarClone);
            }

            topSection.appendChild(chatWrapper);
        });

        let footerText = texts.footer;
        if (addCreatorInfo && creatorName) {
            footerText += ` — By ${creatorName}`;
        }

        const bottomSection = document.createElement('div');
        bottomSection.textContent = footerText;
        bottomSection.style.padding = '10px';
        bottomSection.style.textAlign = 'center';
        bottomSection.style.fontSize = '14px';
        bottomSection.style.fontFamily = 'Arial, sans-serif';
        bottomSection.style.backgroundColor = colorScheme.bottom;
        bottomSection.style.color = colorScheme.textBottom;

        container.appendChild(topSection);
        container.appendChild(bottomSection);

        container.style.position = 'absolute';
        container.style.left = '-9999px';
        document.body.appendChild(container);

        try {
            const canvas = await html2canvas(container, {
                scale: 2,
                backgroundColor: null,
                useCORS: true,
                logging: false
            });

            const link = document.createElement('a');
            link.download = `chat_export_${new Date().toISOString().split('T')[0]}.png`;
            link.href = canvas.toDataURL('image/png');
            link.click();
        } catch (error) {
            console.error('Error generating image:', error);
            alert(texts.error);
        }

        document.body.removeChild(container);
    }

    // Initialize
    function init() {
        addStyles();
        createFAB();
        addExportButtonsToMessages();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址