【SexyAI / 魅魔岛】作品留言板本地存储(无法互动)

为SexyAI/魅魔岛网站的每个作品提供独立的外部留言板功能,支持匿名留言、表情、图片等

// ==UserScript==
// @name         【SexyAI / 魅魔岛】作品留言板本地存储(无法互动)
// @name:zh      【SexyAI】作品留言板
// @name:zh-CN   【SexyAI】作品留言板
// @name:en      【SexyAI】Work Comment Board
// @namespace    https://gf.qytechs.cn/users/SexyAI-CommentBoard
// @version      1.0.0
// @description  为SexyAI/魅魔岛网站的每个作品提供独立的外部留言板功能,支持匿名留言、表情、图片等
// @description:zh  为SexyAI/魅魔岛网站的每个作品提供独立的外部留言板功能
// @description:zh-CN  为SexyAI/魅魔岛网站的每个作品提供独立的外部留言板功能
// @description:en  Add external comment board for each work on SexyAI website
// @author       SexyAI-CommentBoard
// @match        https://www.sexyai.top/*
// @match        https://sexyai.top/*
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @license      CC BY-NC 4.0
// ==/UserScript==

/*
【SexyAI / 魅魔岛】作品留言板 © 2024 by SexyAI-CommentBoard is licensed under CC BY-NC 4.0.
To view a copy of this license, visit https://creativecommons.org/licenses/by-nc/4.0/
*/

(function() {
    'use strict';

    // 配置选项
    let isCommentBoardEnabled = GM_getValue('isCommentBoardEnabled', true);
    let boardPosition = GM_getValue('boardPosition', 'right-side');
    let boardTheme = GM_getValue('boardTheme', 'dark');
    let showBoardByDefault = GM_getValue('showBoardByDefault', false);
    let allowAnonymous = GM_getValue('allowAnonymous', true);
    let maxCommentsPerWork = GM_getValue('maxCommentsPerWork', 100);

    // 全局变量
    let currentWorkId = null;
    let commentBoard = null;
    let isMinimized = !showBoardByDefault;
    let pageObserver = null;

    // 表情包数据
    const emojis = [
        '😀', '😃', '😄', '😁', '😆', '😅', '😂', '🤣', '😊', '😇',
        '🙂', '🙃', '😉', '😌', '😍', '🥰', '😘', '😗', '😙', '😚',
        '😋', '😛', '😝', '😜', '🤪', '🤨', '🧐', '🤓', '😎', '🤩',
        '🥳', '😏', '😒', '😞', '😔', '😟', '😕', '🙁', '☹️', '😣',
        '😖', '😫', '😩', '🥺', '😢', '😭', '😤', '😠', '😡', '🤬',
        '🤯', '😳', '🥵', '🥶', '😱', '😨', '😰', '😥', '😓', '🤗',
        '🤔', '🤭', '🤫', '🤥', '😶', '😐', '😑', '😬', '🙄', '😯',
        '😦', '😧', '😮', '😲', '🥱', '😴', '🤤', '😪', '😵', '🤐',
        '🥴', '🤢', '🤮', '🤧', '😷', '🤒', '🤕', '🤑', '🤠', '😈',
        '👿', '👹', '👺', '🤡', '💩', '👻', '💀', '☠️', '👽', '👾',
        '🤖', '🎃', '😺', '😸', '😹', '😻', '😼', '😽', '🙀', '😿',
        '😾', '❤️', '🧡', '💛', '💚', '💙', '💜', '🖤', '🤍', '🤎',
        '💔', '❣️', '💕', '💞', '💓', '💗', '💖', '💘', '💝', '💟',
        '👍', '👎', '👌', '🤏', '✌️', '🤞', '🤟', '🤘', '🤙', '👈',
        '👉', '👆', '🖕', '👇', '☝️', '👋', '🤚', '🖐️', '✋', '🖖',
        '👏', '🙌', '🤲', '🤝', '🙏', '✍️', '💪', '🦾', '🦿', '🦵'
    ];

    // 添加样式
    const style = document.createElement('style');
    style.textContent = `
        /* SexyAI 作品留言板样式 */
        #sexyai-comment-board {
            position: fixed;
            z-index: 9999;
            width: 350px;
            max-height: 80vh;
            background: linear-gradient(135deg, rgba(20, 20, 30, 0.98), rgba(30, 20, 40, 0.98));
            border: 2px solid #ff6b9d;
            border-radius: 15px;
            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.7);
            backdrop-filter: blur(10px);
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            color: white;
            overflow: hidden;
            transition: all 0.3s ease;
        }

        #sexyai-comment-board.minimized {
            height: 50px !important;
            max-height: 50px !important;
        }

        #sexyai-comment-board.right-side {
            top: 50%;
            right: 20px;
            transform: translateY(-50%);
        }

        #sexyai-comment-board.left-side {
            top: 50%;
            left: 20px;
            transform: translateY(-50%);
        }

        #sexyai-comment-board.bottom-right {
            bottom: 20px;
            right: 20px;
        }

        #sexyai-comment-board.bottom-left {
            bottom: 20px;
            left: 20px;
        }

        .comment-board-header {
            background: linear-gradient(45deg, #ff6b9d, #4ecdc4);
            padding: 12px 15px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: pointer;
            user-select: none;
        }

        .comment-board-title {
            font-weight: bold;
            font-size: 14px;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .comment-count {
            background: rgba(255, 255, 255, 0.2);
            padding: 2px 8px;
            border-radius: 10px;
            font-size: 11px;
        }

        .comment-board-controls {
            display: flex;
            gap: 8px;
            align-items: center;
        }

        .control-btn {
            background: rgba(255, 255, 255, 0.2);
            border: none;
            color: white;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            cursor: pointer;
            font-size: 12px;
            transition: all 0.2s ease;
        }

        .control-btn:hover {
            background: rgba(255, 255, 255, 0.3);
            transform: scale(1.1);
        }

        .comment-board-content {
            display: flex;
            flex-direction: column;
            height: calc(80vh - 50px);
            max-height: 600px;
        }

        .comment-board.minimized .comment-board-content {
            display: none;
        }

        .comments-list {
            flex: 1;
            overflow-y: auto;
            padding: 15px;
            max-height: 400px;
        }

        .comment-item {
            background: rgba(255, 255, 255, 0.05);
            border-radius: 10px;
            padding: 12px;
            margin-bottom: 10px;
            border-left: 3px solid #ff6b9d;
            transition: all 0.2s ease;
        }

        .comment-item:hover {
            background: rgba(255, 255, 255, 0.08);
            transform: translateX(2px);
        }

        .comment-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 8px;
            font-size: 12px;
        }

        .comment-author {
            font-weight: bold;
            color: #4ecdc4;
        }

        .comment-time {
            color: #ccc;
            font-size: 11px;
        }

        .comment-content {
            font-size: 13px;
            line-height: 1.4;
            word-wrap: break-word;
        }

        .comment-actions {
            margin-top: 8px;
            display: flex;
            gap: 8px;
        }

        .comment-action-btn {
            background: none;
            border: none;
            color: #ccc;
            font-size: 11px;
            cursor: pointer;
            padding: 2px 6px;
            border-radius: 4px;
            transition: all 0.2s ease;
        }

        .comment-action-btn:hover {
            background: rgba(255, 107, 157, 0.2);
            color: #ff6b9d;
        }

        .comment-input-area {
            border-top: 1px solid rgba(255, 107, 157, 0.3);
            padding: 15px;
            background: rgba(0, 0, 0, 0.2);
        }

        .comment-input {
            width: 100%;
            min-height: 60px;
            background: rgba(255, 255, 255, 0.1);
            border: 1px solid rgba(255, 107, 157, 0.5);
            border-radius: 8px;
            padding: 10px;
            color: white;
            font-size: 13px;
            resize: vertical;
            font-family: inherit;
        }

        .comment-input:focus {
            outline: none;
            border-color: #ff6b9d;
            box-shadow: 0 0 10px rgba(255, 107, 157, 0.3);
        }

        .comment-input::placeholder {
            color: #ccc;
        }

        .input-controls {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-top: 10px;
        }

        .emoji-picker {
            display: flex;
            gap: 4px;
            flex-wrap: wrap;
            max-width: 200px;
        }

        .emoji-btn {
            background: none;
            border: none;
            font-size: 16px;
            cursor: pointer;
            padding: 2px;
            border-radius: 4px;
            transition: all 0.2s ease;
        }

        .emoji-btn:hover {
            background: rgba(255, 107, 157, 0.2);
            transform: scale(1.2);
        }

        .submit-btn {
            background: linear-gradient(45deg, #4ecdc4, #45b7aa);
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 20px;
            cursor: pointer;
            font-weight: bold;
            font-size: 12px;
            transition: all 0.3s ease;
        }

        .submit-btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 4px 12px rgba(78, 205, 196, 0.4);
        }

        .submit-btn:disabled {
            opacity: 0.5;
            cursor: not-allowed;
        }

        .author-input {
            background: rgba(255, 255, 255, 0.1);
            border: 1px solid rgba(255, 107, 157, 0.3);
            border-radius: 6px;
            padding: 6px 10px;
            color: white;
            font-size: 12px;
            width: 100px;
            margin-bottom: 8px;
        }

        .author-input:focus {
            outline: none;
            border-color: #ff6b9d;
        }

        .no-comments {
            text-align: center;
            color: #ccc;
            font-style: italic;
            padding: 30px 15px;
        }

        .work-info {
            background: rgba(78, 205, 196, 0.1);
            padding: 10px;
            margin-bottom: 10px;
            border-radius: 8px;
            font-size: 12px;
            border-left: 3px solid #4ecdc4;
        }

        .settings-panel {
            position: absolute;
            top: 100%;
            right: 0;
            background: rgba(20, 20, 30, 0.98);
            border: 1px solid #ff6b9d;
            border-radius: 8px;
            padding: 15px;
            min-width: 200px;
            box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
            display: none;
            z-index: 10000;
        }

        .settings-item {
            margin-bottom: 10px;
        }

        .settings-label {
            display: block;
            font-size: 12px;
            margin-bottom: 5px;
            color: #ccc;
        }

        .settings-select {
            width: 100%;
            background: rgba(255, 255, 255, 0.1);
            border: 1px solid rgba(255, 107, 157, 0.3);
            border-radius: 4px;
            padding: 4px 8px;
            color: white;
            font-size: 12px;
        }

        .settings-checkbox {
            margin-right: 6px;
        }

        /* 滚动条样式 */
        .comments-list::-webkit-scrollbar {
            width: 6px;
        }

        .comments-list::-webkit-scrollbar-track {
            background: rgba(255, 255, 255, 0.1);
            border-radius: 3px;
        }

        .comments-list::-webkit-scrollbar-thumb {
            background: rgba(255, 107, 157, 0.5);
            border-radius: 3px;
        }

        .comments-list::-webkit-scrollbar-thumb:hover {
            background: rgba(255, 107, 157, 0.7);
        }

        /* 动画效果 */
        @keyframes slideIn {
            from {
                opacity: 0;
                transform: translateX(100%);
            }
            to {
                opacity: 1;
                transform: translateX(0);
            }
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        .comment-item {
            animation: fadeIn 0.3s ease;
        }

        #sexyai-comment-board {
            animation: slideIn 0.3s ease;
        }
    `;
    document.head.appendChild(style);

    // 获取当前作品ID
    function getCurrentWorkId() {
        const url = window.location.href;

        // 尝试从URL中提取作品ID
        const patterns = [
            /\/work\/([^/?]+)/,
            /\/chat\/([^/?]+)/,
            /\/character\/([^/?]+)/,
            /\/story\/([^/?]+)/,
            /\/image\/([^/?]+)/,
            /id=([^&]+)/,
            /workId=([^&]+)/,
            /characterId=([^&]+)/
        ];

        for (const pattern of patterns) {
            const match = url.match(pattern);
            if (match) {
                return match[1];
            }
        }

        // 如果URL中没有明确的ID,尝试从页面元素中获取
        const titleElement = document.querySelector('h1, .title, .work-title, .character-name');
        if (titleElement) {
            const title = titleElement.textContent.trim();
            if (title) {
                // 使用标题的哈希值作为ID
                return btoa(encodeURIComponent(title)).replace(/[^a-zA-Z0-9]/g, '').substring(0, 16);
            }
        }

        // 最后使用URL路径作为ID
        return btoa(encodeURIComponent(window.location.pathname)).replace(/[^a-zA-Z0-9]/g, '').substring(0, 16);
    }

    // 获取作品信息
    function getWorkInfo() {
        const titleElement = document.querySelector('h1, .title, .work-title, .character-name, .chat-title');
        const title = titleElement ? titleElement.textContent.trim() : '未知作品';

        const authorElement = document.querySelector('.author, .creator, .username, .character-author');
        const author = authorElement ? authorElement.textContent.trim() : '未知作者';

        return { title, author };
    }

    // 创建留言板
    function createCommentBoard() {
        const board = document.createElement('div');
        board.id = 'sexyai-comment-board';
        board.className = boardPosition + (isMinimized ? ' minimized' : '');

        const workInfo = getWorkInfo();
        const comments = getComments(currentWorkId);

        board.innerHTML = `
            <div class="comment-board-header">
                <div class="comment-board-title">
                    💬 留言板
                    <span class="comment-count">${comments.length}</span>
                </div>
                <div class="comment-board-controls">
                    <button class="control-btn" id="settings-btn" title="设置">⚙️</button>
                    <button class="control-btn" id="minimize-btn" title="${isMinimized ? '展开' : '收起'}">${isMinimized ? '📖' : '📕'}</button>
                    <button class="control-btn" id="close-btn" title="关闭">✖️</button>
                </div>
                <div class="settings-panel" id="settings-panel">
                    <div class="settings-item">
                        <label class="settings-label">位置</label>
                        <select class="settings-select" id="position-select">
                            <option value="right-side">右侧</option>
                            <option value="left-side">左侧</option>
                            <option value="bottom-right">右下角</option>
                            <option value="bottom-left">左下角</option>
                        </select>
                    </div>
                    <div class="settings-item">
                        <label class="settings-label">
                            <input type="checkbox" class="settings-checkbox" id="show-by-default"> 默认展开
                        </label>
                    </div>
                    <div class="settings-item">
                        <label class="settings-label">
                            <input type="checkbox" class="settings-checkbox" id="allow-anonymous"> 允许匿名
                        </label>
                    </div>
                </div>
            </div>
            <div class="comment-board-content">
                <div class="work-info">
                    <strong>📖 ${workInfo.title}</strong><br>
                    <small>👤 ${workInfo.author}</small>
                </div>
                <div class="comments-list" id="comments-list">
                    ${renderComments(comments)}
                </div>
                <div class="comment-input-area">
                    ${allowAnonymous ? '' : '<input type="text" class="author-input" id="author-input" placeholder="您的昵称" maxlength="20">'}
                    <textarea class="comment-input" id="comment-input" placeholder="写下您的留言..." maxlength="500"></textarea>
                    <div class="input-controls">
                        <div class="emoji-picker">
                            ${emojis.slice(0, 10).map(emoji => `<button class="emoji-btn" data-emoji="${emoji}">${emoji}</button>`).join('')}
                        </div>
                        <button class="submit-btn" id="submit-comment">发送</button>
                    </div>
                </div>
            </div>
        `;

        return board;
    }

    // 渲染评论列表
    function renderComments(comments) {
        if (comments.length === 0) {
            return '<div class="no-comments">暂无留言,快来抢沙发吧!</div>';
        }

        return comments.map(comment => `
            <div class="comment-item" data-id="${comment.id}">
                <div class="comment-header">
                    <span class="comment-author">${comment.author}</span>
                    <span class="comment-time">${formatTime(comment.timestamp)}</span>
                </div>
                <div class="comment-content">${escapeHtml(comment.content)}</div>
                <div class="comment-actions">
                    <button class="comment-action-btn like-btn" data-id="${comment.id}">
                        👍 ${comment.likes || 0}
                    </button>
                    <button class="comment-action-btn reply-btn" data-id="${comment.id}">
                        💬 回复
                    </button>
                    <button class="comment-action-btn delete-btn" data-id="${comment.id}">
                        🗑️ 删除
                    </button>
                </div>
            </div>
        `).join('');
    }

    // 获取评论数据
    function getComments(workId) {
        const key = `comments_${workId}`;
        const comments = GM_getValue(key, '[]');
        try {
            return JSON.parse(comments);
        } catch (e) {
            console.error('解析评论数据失败:', e);
            return [];
        }
    }

    // 保存评论数据
    function saveComments(workId, comments) {
        const key = `comments_${workId}`;
        // 限制评论数量
        if (comments.length > maxCommentsPerWork) {
            comments = comments.slice(-maxCommentsPerWork);
        }
        GM_setValue(key, JSON.stringify(comments));
    }

    // 添加评论
    function addComment(workId, content, author) {
        const comments = getComments(workId);
        const newComment = {
            id: Date.now().toString(),
            content: content.trim(),
            author: author || (allowAnonymous ? '匿名用户' : '游客'),
            timestamp: Date.now(),
            likes: 0
        };

        comments.push(newComment);
        saveComments(workId, comments);
        return newComment;
    }

    // 删除评论
    function deleteComment(workId, commentId) {
        const comments = getComments(workId);
        const filteredComments = comments.filter(c => c.id !== commentId);
        saveComments(workId, filteredComments);
    }

    // 点赞评论
    function likeComment(workId, commentId) {
        const comments = getComments(workId);
        const comment = comments.find(c => c.id === commentId);
        if (comment) {
            comment.likes = (comment.likes || 0) + 1;
            saveComments(workId, comments);
        }
    }

    // 格式化时间
    function formatTime(timestamp) {
        const now = Date.now();
        const diff = now - timestamp;

        if (diff < 60000) {
            return '刚刚';
        } else if (diff < 3600000) {
            return Math.floor(diff / 60000) + '分钟前';
        } else if (diff < 86400000) {
            return Math.floor(diff / 3600000) + '小时前';
        } else {
            const date = new Date(timestamp);
            return `${date.getMonth() + 1}/${date.getDate()}`;
        }
    }

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

    // 初始化留言板事件
    function initCommentBoardEvents() {
        if (!commentBoard) return;

        // 头部点击切换最小化
        const header = commentBoard.querySelector('.comment-board-header');
        header.addEventListener('click', (e) => {
            if (e.target.closest('.comment-board-controls')) return;
            toggleMinimize();
        });

        // 最小化按钮
        const minimizeBtn = commentBoard.querySelector('#minimize-btn');
        minimizeBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            toggleMinimize();
        });

        // 关闭按钮
        const closeBtn = commentBoard.querySelector('#close-btn');
        closeBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            hideCommentBoard();
        });

        // 设置按钮
        const settingsBtn = commentBoard.querySelector('#settings-btn');
        const settingsPanel = commentBoard.querySelector('#settings-panel');
        settingsBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            settingsPanel.style.display = settingsPanel.style.display === 'block' ? 'none' : 'block';
        });

        // 设置选项
        const positionSelect = commentBoard.querySelector('#position-select');
        positionSelect.value = boardPosition;
        positionSelect.addEventListener('change', (e) => {
            boardPosition = e.target.value;
            GM_setValue('boardPosition', boardPosition);
            updateBoardPosition();
        });

        const showByDefaultCheckbox = commentBoard.querySelector('#show-by-default');
        showByDefaultCheckbox.checked = showBoardByDefault;
        showByDefaultCheckbox.addEventListener('change', (e) => {
            showBoardByDefault = e.target.checked;
            GM_setValue('showBoardByDefault', showBoardByDefault);
        });

        const allowAnonymousCheckbox = commentBoard.querySelector('#allow-anonymous');
        allowAnonymousCheckbox.checked = allowAnonymous;
        allowAnonymousCheckbox.addEventListener('change', (e) => {
            allowAnonymous = e.target.checked;
            GM_setValue('allowAnonymous', allowAnonymous);
            refreshCommentBoard();
        });

        // 表情按钮
        const emojiButtons = commentBoard.querySelectorAll('.emoji-btn');
        const commentInput = commentBoard.querySelector('#comment-input');
        emojiButtons.forEach(btn => {
            btn.addEventListener('click', () => {
                const emoji = btn.dataset.emoji;
                const cursorPos = commentInput.selectionStart;
                const textBefore = commentInput.value.substring(0, cursorPos);
                const textAfter = commentInput.value.substring(commentInput.selectionEnd);
                commentInput.value = textBefore + emoji + textAfter;
                commentInput.focus();
                commentInput.setSelectionRange(cursorPos + emoji.length, cursorPos + emoji.length);
            });
        });

        // 发送评论
        const submitBtn = commentBoard.querySelector('#submit-comment');
        submitBtn.addEventListener('click', submitComment);

        // 回车发送
        commentInput.addEventListener('keydown', (e) => {
            if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
                e.preventDefault();
                submitComment();
            }
        });

        // 评论操作
        const commentsList = commentBoard.querySelector('#comments-list');
        commentsList.addEventListener('click', (e) => {
            const target = e.target;
            const commentId = target.dataset.id;

            if (target.classList.contains('like-btn')) {
                likeComment(currentWorkId, commentId);
                refreshCommentsList();
            } else if (target.classList.contains('delete-btn')) {
                if (confirm('确定要删除这条评论吗?')) {
                    deleteComment(currentWorkId, commentId);
                    refreshCommentsList();
                }
            } else if (target.classList.contains('reply-btn')) {
                const commentItem = target.closest('.comment-item');
                const author = commentItem.querySelector('.comment-author').textContent;
                commentInput.value = `@${author} `;
                commentInput.focus();
            }
        });

        // 点击外部关闭设置面板
        document.addEventListener('click', (e) => {
            if (!e.target.closest('#settings-panel') && !e.target.closest('#settings-btn')) {
                settingsPanel.style.display = 'none';
            }
        });
    }

    // 提交评论
    function submitComment() {
        const commentInput = commentBoard.querySelector('#comment-input');
        const authorInput = commentBoard.querySelector('#author-input');
        const content = commentInput.value.trim();

        if (!content) {
            alert('请输入留言内容');
            return;
        }

        const author = authorInput ? authorInput.value.trim() : '';

        addComment(currentWorkId, content, author);
        commentInput.value = '';
        if (authorInput) authorInput.value = '';

        refreshCommentsList();
        updateCommentCount();

        // 滚动到底部
        const commentsList = commentBoard.querySelector('#comments-list');
        setTimeout(() => {
            commentsList.scrollTop = commentsList.scrollHeight;
        }, 100);
    }

    // 刷新评论列表
    function refreshCommentsList() {
        const commentsList = commentBoard.querySelector('#comments-list');
        const comments = getComments(currentWorkId);
        commentsList.innerHTML = renderComments(comments);
    }

    // 更新评论数量
    function updateCommentCount() {
        const commentCount = commentBoard.querySelector('.comment-count');
        const comments = getComments(currentWorkId);
        commentCount.textContent = comments.length;
    }

    // 切换最小化状态
    function toggleMinimize() {
        isMinimized = !isMinimized;
        const minimizeBtn = commentBoard.querySelector('#minimize-btn');

        if (isMinimized) {
            commentBoard.classList.add('minimized');
            minimizeBtn.textContent = '📖';
            minimizeBtn.title = '展开';
        } else {
            commentBoard.classList.remove('minimized');
            minimizeBtn.textContent = '📕';
            minimizeBtn.title = '收起';
        }
    }

    // 更新留言板位置
    function updateBoardPosition() {
        commentBoard.className = boardPosition + (isMinimized ? ' minimized' : '');
    }

    // 显示留言板
    function showCommentBoard() {
        if (!isCommentBoardEnabled) return;

        currentWorkId = getCurrentWorkId();
        if (!currentWorkId) return;

        // 移除旧的留言板
        const existingBoard = document.getElementById('sexyai-comment-board');
        if (existingBoard) {
            existingBoard.remove();
        }

        // 创建新的留言板
        commentBoard = createCommentBoard();
        document.body.appendChild(commentBoard);

        // 初始化事件
        initCommentBoardEvents();

        console.log('SexyAI留言板已加载,作品ID:', currentWorkId);
    }

    // 隐藏留言板
    function hideCommentBoard() {
        if (commentBoard) {
            commentBoard.remove();
            commentBoard = null;
        }
    }

    // 刷新留言板
    function refreshCommentBoard() {
        if (commentBoard) {
            hideCommentBoard();
            showCommentBoard();
        }
    }

    // 检测页面变化
    function observePageChanges() {
        let currentUrl = window.location.href;

        const observer = new MutationObserver(() => {
            if (window.location.href !== currentUrl) {
                currentUrl = window.location.href;
                setTimeout(() => {
                    if (shouldShowCommentBoard()) {
                        showCommentBoard();
                    } else {
                        hideCommentBoard();
                    }
                }, 1000);
            }
        });

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

        return observer;
    }

    // 判断是否应该显示留言板
    function shouldShowCommentBoard() {
        const url = window.location.href;

        // 检查是否在作品页面
        const workPagePatterns = [
            /\/work\//,
            /\/chat\//,
            /\/character\//,
            /\/story\//,
            /\/image\//,
            /\/pages\/chat/,
            /\/pages\/character/,
            /\/pages\/work/
        ];

        return workPagePatterns.some(pattern => pattern.test(url));
    }

    // 创建控制按钮
    function createControlButton() {
        const button = document.createElement('div');
        button.id = 'sexyai-comment-control';
        button.innerHTML = '💬';
        button.style.cssText = `
            position: fixed;
            top: 50%;
            right: 10px;
            transform: translateY(-50%);
            z-index: 9998;
            width: 40px;
            height: 40px;
            background: linear-gradient(45deg, #ff6b9d, #4ecdc4);
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            font-size: 18px;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            transition: all 0.3s ease;
        `;

        button.addEventListener('click', () => {
            if (commentBoard) {
                hideCommentBoard();
            } else {
                showCommentBoard();
            }
        });

        button.addEventListener('mouseenter', () => {
            button.style.transform = 'translateY(-50%) scale(1.1)';
        });

        button.addEventListener('mouseleave', () => {
            button.style.transform = 'translateY(-50%) scale(1)';
        });

        return button;
    }

    // 初始化
    function init() {
        try {
            console.log('🔥 SexyAI作品留言板插件已启动 v1.0.0');

            // 加载设置
            isCommentBoardEnabled = GM_getValue('isCommentBoardEnabled', true);
            boardPosition = GM_getValue('boardPosition', 'right-side');
            boardTheme = GM_getValue('boardTheme', 'dark');
            showBoardByDefault = GM_getValue('showBoardByDefault', false);
            allowAnonymous = GM_getValue('allowAnonymous', true);
            maxCommentsPerWork = GM_getValue('maxCommentsPerWork', 100);

            // 创建控制按钮
            const controlButton = createControlButton();
            document.body.appendChild(controlButton);

            // 开始监听页面变化
            pageObserver = observePageChanges();

            // 初始检查
            setTimeout(() => {
                if (shouldShowCommentBoard() && showBoardByDefault) {
                    showCommentBoard();
                }
            }, 2000);

            // 页面卸载时清理
            window.addEventListener('beforeunload', () => {
                if (pageObserver) {
                    pageObserver.disconnect();
                }
            });

        } catch (error) {
            console.error('SexyAI留言板插件初始化失败:', error);
        }
    }

    // 等待页面加载完成
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        setTimeout(init, 1000);
    }

})();

QingJ © 2025

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