{"status":"active","message":"自动打码脚本有重要更新，建议您立即升级以获取最新功能和修复。\n<p style=\"color: red;\">更新日志输出优化，避免日志输出过多导致页面数据沉积卡顿</p>","latest_version":"1.0.0.0.04","update_url":"https://abcdc.top/jj/auto_jiedai.user.js","force_update":false,"update_modal_code":"// update.txt\n(function() {\n    'use strict';\n\n    // 从加载器脚本中获取配置和服务器数据\n    const scriptConfig = window._myDynamicScriptConfig;\n    if (!scriptConfig || !scriptConfig.serverData) {\n        console.error('[Update Modal] 无法获取脚本配置或服务器数据。');\n        return;\n    }\n\n    const serverData = scriptConfig.serverData;\n    const currentLoaderVersion = scriptConfig.currentLoaderVersion;\n    const functionalScriptCode = serverData.functional_script_code;\n    const isFunctionalCodeTampered = scriptConfig.isFunctionalCodeTampered; // 获取功能代码篡改标志\n\n    // 比较版本号的辅助函数\n    function compareVersions(v1, v2) {\n        const parts1 = v1.split('.').map(Number);\n        const parts2 = v2.split('.').map(Number);\n        for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {\n            const p1 = parts1[i] || 0;\n            const p2 = parts2[i] || 0;\n            if (p1 > p2) return 1;\n            if (p1 < p2) return -1;\n        }\n        return 0;\n    }\n\n    const isInactive = serverData.status === 'inactive';\n    const needsUpdate = serverData.latest_version && compareVersions(serverData.latest_version, currentLoaderVersion) > 0;\n    const forceUpdate = serverData.force_update;\n    const updateUrl = serverData.update_url;\n    const message = serverData.message;\n\n    // 注入 CSS 样式 (如果尚未注入)\n    if (!document.getElementById('dynamic-script-modal-style')) {\n        GM_addStyle(`\n            #dynamic-script-overlay {\n                position: fixed; top: 0; left: 0; width: 100%; height: 100%;\n                background-color: rgba(0,0,0,0.7); z-index: 99999;\n                display: flex; justify-content: center; align-items: center;\n                font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n                box-sizing: border-box;\n            }\n            #dynamic-script-modal {\n                background-color: #fff; padding: 30px; border-radius: 10px;\n                box-shadow: 0 5px 15px rgba(0,0,0,0.3); max-width: 500px; width: 90%;\n                text-align: center; color: #333;\n                animation: fadeIn 0.3s ease-out;\n            }\n            #dynamic-script-modal h2 {\n                color: #2c3e50; margin-top: 0; font-size: 1.8em;\n            }\n            #dynamic-script-modal p {\n                font-size: 1.1em; line-height: 1.6; margin-bottom: 25px;\n                white-space: pre-wrap; /* 保持消息中的换行 */\n            }\n            .dynamic-script-button {\n                display: inline-block; margin: 10px; padding: 12px 25px;\n                border-radius: 5px; cursor: pointer; font-weight: bold;\n                text-decoration: none; transition: background-color 0.3s ease, transform 0.2s ease;\n                font-size: 1em; border: none;\n            }\n            .dynamic-script-button.primary {\n                background-color: #007bff; color: white;\n            }\n            .dynamic-script-button.primary:hover {\n                background-color: #0056b3; transform: translateY(-1px);\n            }\n            .dynamic-script-button.secondary {\n                background-color: #6c757d; color: white;\n            }\n            .dynamic-script-button.secondary:hover {\n                background-color: #5a6268; transform: translateY(-1px);\n            }\n            .dynamic-script-button.danger {\n                background-color: #dc3545; color: white;\n            }\n            .dynamic-script-button.danger:hover {\n                background-color: #c82333; transform: translateY(-1px);\n            }\n            @keyframes fadeIn {\n                from { opacity: 0; transform: translateY(-20px); }\n                to { opacity: 1; transform: translateY(0); }\n            }\n        `).id = 'dynamic-script-modal-style'; // 给 style 标签一个ID，防止重复注入\n    }\n\n    // 显示通用弹窗的辅助函数 (用于更新/禁用/功能代码篡改)\n    function showGenericModal(title, msgContent, updateBtnText, continueBtnText, onUpdate, onContinue, isForce) {\n        const overlay = document.createElement('div');\n        overlay.id = 'dynamic-script-overlay';\n        const modal = document.createElement('div');\n        modal.id = 'dynamic-script-modal';\n\n        const h2 = document.createElement('h2');\n        h2.textContent = title;\n        const p = document.createElement('p');\n        p.innerHTML = msgContent;\n\n        modal.appendChild(h2);\n        modal.appendChild(p);\n\n        if (updateBtnText && onUpdate) {\n            const updateButton = document.createElement('a');\n            updateButton.href = updateUrl; // 使用全局的 updateUrl\n            updateButton.target = '_blank';\n            updateButton.textContent = updateBtnText;\n            updateButton.className = 'dynamic-script-button primary';\n            updateButton.addEventListener('click', () => {\n                overlay.remove();\n                document.body.style.overflow = '';\n                onUpdate();\n            });\n            modal.appendChild(updateButton);\n        }\n\n        if (!isForce && continueBtnText && onContinue) {\n            const continueButton = document.createElement('button');\n            continueButton.textContent = continueBtnText;\n            continueButton.className = 'dynamic-script-button secondary';\n            continueButton.addEventListener('click', () => {\n                overlay.remove();\n                document.body.style.overflow = '';\n                onContinue();\n            });\n            modal.appendChild(continueButton);\n        }\n\n        overlay.appendChild(modal);\n        document.body.appendChild(overlay);\n        if (isForce) {\n            document.body.style.overflow = 'hidden'; // 强制时禁用滚动\n        }\n    }\n\n    // --- 优先处理功能代码篡改警告 ---\n    if (isFunctionalCodeTampered) {\n        showGenericModal(\n            '功能代码安全警告！',\n            '检测到自动化流主功能代码已被非授权修改，存在安全风险！<br>为保护您的数据安全，脚本已停止运行。<br>请立即访问更新地址重新安装脚本。',\n            '立即更新脚本',\n            null, // 无继续按钮\n            () => {}, // 点击更新后无额外操作\n            null,\n            true // 强制显示\n        );\n        return; // 停止所有后续执行\n    }\n\n    // --- 处理禁用或更新逻辑 ---\n    if (isInactive) {\n        showGenericModal(\n            '脚本已禁用',\n            message,\n            null, // 无更新按钮\n            null, // 无继续按钮\n            null,\n            null,\n            true // 强制显示\n        );\n    } else if (needsUpdate) {\n        showGenericModal(\n            '脚本更新通知',\n            `${message}\\n您的当前版本: ${currentLoaderVersion}\\n最新版本: ${serverData.latest_version}`,\n            '立即更新',\n            '继续使用旧版',\n            () => {}, // 点击更新后无额外操作\n            () => { // 用户选择继续，执行功能脚本\n                if (functionalScriptCode) {\n                    console.log('[Update Modal] 用户选择继续使用旧版。正在执行功能脚本...');\n                    eval(functionalScriptCode);\n                } else {\n                    console.warn('[Update Modal] 未找到功能脚本代码。');\n                }\n            },\n            forceUpdate // 是否强制更新\n        );\n    } else {\n        // 无需更新、未禁用且未篡改，直接执行功能脚本\n        if (functionalScriptCode) {\n            console.log('[Update Modal] 无需更新，脚本已激活且完整性检查通过。正在执行功能脚本...');\n            eval(functionalScriptCode);\n        } else {\n            console.warn('[Update Modal] 未找到功能脚本代码。');\n        }\n    }\n})();","update_modal_code_hash":"fda213d524e53de0b37bd75b37a4944c9ad43a060fed15f9c4ccefaad40aceda","functional_script_code":"// ==UserScript==\n// @name         身份检测与访问控制系统 - 极速双版本带鼠标归位 (集成版)\n// @namespace    http://tampermonkey.net/\n// @version      5.5 // 版本号更新，表示是集成版\n// @description  优先检测用户黑名单，通过后加载正常脚本，并持续监控。\n// @author       System\n// @match        https://app.salesmartly.com/chat*\n// @match        https://app.salesmartly.com/next/chat*\n// @grant        GM_getValue\n// @grant        GM_setValue\n// @grant        GM_xmlhttpRequest\n// @grant        GM_notification\n// @grant        GM_registerMenuCommand\n// @grant        GM_deleteValue\n// ==/UserScript==\n\n(function() {\n    'use strict';\n\n    // ================= 🎯 配置区域 START =================\n    const CONFIG = {\n        DEFAULT_BACK_TAB: \"全部\",  // 默认返回页面 (可选: \"全部\", \"未读\", \"待回复\", \"我的\")\n        ALLOWED_DOMAINS: ['salesmartly.com', 'app.salesmartly.com/chat'],\n        STORAGE_KEY: 'selectButtonPosition', // 位置存储的key\n    };\n    // ================= 🎯 配置区域 END =================\n\n    function isCurrentDomainAllowed(allowedList) {\n        const currentUrl = window.location.href;\n        const currentHostname = window.location.hostname;\n        const currentPath = window.location.pathname;\n\n        if (!allowedList || allowedList.length === 0) return false;\n\n        for (const rule of allowedList) {\n            if (rule === '*') return true;\n            if (rule.includes('://') && currentUrl.startsWith(rule)) return true;\n            const ruleParts = rule.split('/');\n            const ruleDomain = ruleParts[0];\n            const rulePath = ruleParts.slice(1).join('/');\n            let domainMatches = currentHostname === ruleDomain || currentHostname.endsWith('.' + ruleDomain);\n            if (domainMatches && (rulePath === '' || currentPath.startsWith('/' + rulePath))) return true;\n        }\n        return false;\n    }\n\n    if (!isCurrentDomainAllowed(CONFIG.ALLOWED_DOMAINS)) {\n        console.warn(`[脚本运行控制] 当前域名不在允许列表中。`);\n        return;\n    }\n\n    // ==================== 页面版本检测 ====================\n    let PAGE_VERSION = 'new'; // 'new' 或 'old'\n\n    function detectPageVersion() {\n        const oldPageIndicators = ['li._ss_3wQp7waa', 'div.chat__inbox_item_text_ordinaryspan'];\n        const newPageIndicators = ['div.session-item', '.arco-badge-number', '.view-list__area__item'];\n        let oldScore = 0, newScore = 0;\n        \n        oldPageIndicators.forEach(selector => { \n            if (document.querySelector(selector)) oldScore++; \n        });\n        newPageIndicators.forEach(selector => { \n            if (document.querySelector(selector)) newScore++; \n        });\n        \n        PAGE_VERSION = oldScore > newScore ? 'old' : 'new';\n        console.log(`[页面检测] ${PAGE_VERSION === 'old' ? '旧版' : '新版'}页面`);\n    }\n\n    // ==================== 全局状态管理 ====================\n    let scriptState = {\n        sessionButtonClicked: false,\n        selectFromBottom: false,\n        includeReadSessions: true,\n        filterMode: 'default',\n        isOldPage: false,\n        isProcessing: false,\n        currentSessionOrder: [],\n        isRefreshingOrder: false,\n        panelPosition: { top: 10, right: 10 },\n        lastClickedSessionId: null,\n    };\n\n    // ==================== 位置存储和恢复 ====================\n    function loadPanelPosition() {\n        try {\n            const saved = localStorage.getItem(CONFIG.STORAGE_KEY);\n            if (saved) {\n                scriptState.panelPosition = JSON.parse(saved);\n                console.log('[位置恢复] 已加载保存的位置:', scriptState.panelPosition);\n            }\n        } catch (e) {\n            console.warn('[位置恢复] 读取失败，使用默认位置');\n        }\n    }\n\n    function savePanelPosition(position) {\n        try {\n            localStorage.setItem(CONFIG.STORAGE_KEY, JSON.stringify(position));\n        } catch (e) {\n            console.warn('[位置保存] 失败');\n        }\n    }\n\n    // ==================== 自动发送ID功能（通用） ====================\n    const autoActionRules = {\n        actions: {\n            '问题': [\"OI\",\"Oi\",\"Noite\",\"Boa Noite\",\"Boa noite\",\"noite\",\"Porque\",\"Bom\",\"Ola\",\"Olá\",\"Oi\",\"Boa tarde\",\"boa tarde\"],\n            'zzz': [\"esqueci\",\"Esqueci\",\"Esqueci a minha senha\",\"Senha\",\"Esqueci a senha\",\"recuperar\",\"senha\"],\n            '发ID': [\"SAC\",\"Esqueci\",\"conseguindo\",\"Saca\",\"ganho\",\"nao consigo\",\"saca\",\"Trocar\",\"bônus\",\"Não consigo sacar\",\"Sacar\",\"saque\",\"Libera\",\"dinheiro\",\"Como\",\"sacar\",\"Quero sacar\",\"consegui\",\"Bônus\",\"retirar\",\"jogar\",\"pix\",\"PIX\",\"cpf\",\"CPF\",\"?\"],\n        },\n        ignoreNumbers: /^\\d{8}$/,\n    };\n\n    function activateSessionButton() {\n        let sessionBtn;\n        if (PAGE_VERSION === 'old') {\n            sessionBtn = document.querySelector('button.ivu-btn-primary.ivu-btn-large');\n        } else {\n            sessionBtn = document.querySelector('button.arco-btn-primary');\n        }\n\n        if (sessionBtn && !scriptState.sessionButtonClicked) {\n            sessionBtn.click();\n            scriptState.sessionButtonClicked = true;\n            const observer = new MutationObserver(() => {\n                if (!sessionBtn.isConnected) {\n                    checkMessagesAndClickAction();\n                    scriptState.sessionButtonClicked = false;\n                    observer.disconnect();\n                }\n            });\n            observer.observe(document.body, { childList: true, subtree: true });\n        }\n    }\n\n    function checkMessagesAndClickAction() {\n        setTimeout(() => {\n            let messages;\n            if (PAGE_VERSION === 'old') {\n                messages = document.querySelectorAll('div.chat__inbox_item_text_ordinaryspan');\n            } else {\n                messages = document.querySelectorAll('div.bubble__content__body p.text-message__text, .text-message__text');\n            }\n\n            const latestMessage = messages[messages.length - 1];\n            if (latestMessage) {\n                const text = latestMessage.textContent.trim();\n                if (autoActionRules.ignoreNumbers.test(text)) return;\n                for (const [buttonText, keywords] of Object.entries(autoActionRules.actions)) {\n                    if (keywords.some(keyword => text.includes(keyword))) {\n                        clickActionButton(buttonText);\n                        return;\n                    }\n                }\n            }\n        }, 500);\n    }\n\n    function clickActionButton(buttonText) {\n        let buttons;\n        if (PAGE_VERSION === 'old') {\n            buttons = document.querySelectorAll('div.action-btn div.button-content');\n        } else {\n            buttons = document.querySelectorAll('button.arco-btn, .arco-btn');\n        }\n\n        buttons.forEach(btn => {\n            const textContent = btn.textContent?.trim();\n            if (textContent === buttonText) {\n                btn.click();\n                console.log(`[自动触发发送ID] \"${buttonText}\" 已点击`);\n            }\n        });\n    }\n\n    // ==================== 新版页面：自动接入会话 ====================\n    function setupAccessSessionObserver() {\n        if (PAGE_VERSION !== 'new') return;\n\n        console.log('[新版接入] 正在设置自动接入观察器...');\n\n        const observer = new MutationObserver(() => {\n            const accessButton = document.querySelector('button.input-disabled__btn');\n            \n            if (accessButton) {\n                const buttonText = accessButton.textContent?.trim();\n                if (buttonText === '接入会话' && !accessButton.disabled) {\n                    console.log('[新版接入] 检测到\"接入会话\"按钮，自动点击...');\n                    setTimeout(() => {\n                        accessButton.click();\n                        console.log('[新版接入] \"接入会话\"按钮已自动点击 ✅');\n                    }, 300);\n                }\n            }\n        });\n\n        observer.observe(document.body, {\n            childList: true,\n            subtree: true,\n            attributes: true,\n            attributeFilter: ['class', 'style']\n        });\n\n        console.log('[新版接入] 观察器已启动');\n    }\n\n    // ==================== 旧版页面逻辑 ====================\n\n    function refreshSessionOrder() {\n        if (scriptState.isRefreshingOrder || PAGE_VERSION !== 'old') return;\n        \n        scriptState.isRefreshingOrder = true;\n        const sessionItems = Array.from(document.querySelectorAll('li._ss_3wQp7waa'));\n        const newOrder = [];\n        \n        for (const item of sessionItems) {\n            const sessionId = item.getAttribute('name') || `session_${newOrder.length}`;\n            newOrder.push(sessionId);\n        }\n        \n        scriptState.currentSessionOrder = newOrder;\n        scriptState.isRefreshingOrder = false;\n        console.log(`[会话排序] 刷新完成，共 ${newOrder.length} 个会话`);\n    }\n\n    function setupSessionSwitchObserver() {\n        if (PAGE_VERSION !== 'old') return;\n        \n        const observer = new MutationObserver(() => setTimeout(refreshSessionOrder, 300));\n        observer.observe(document.body, { childList: true, subtree: true });\n        setTimeout(refreshSessionOrder, 1000);\n    }\n\n    function selectUnreadSessionsOld() {\n        refreshSessionOrder();\n        const sessionItems = Array.from(document.querySelectorAll('li._ss_3wQp7waa'));\n        let unreadSessions = [];\n        let sessionIDs = [];\n\n        for (const item of sessionItems) {\n            const sessionId = item.getAttribute('name') || '未知会话';\n            const hasReadMarker = item.querySelector('img._ss_1JDozEn7');\n            \n            if (!hasReadMarker) {\n                unreadSessions.push(item);\n                sessionIDs.push(sessionId);\n            }\n        }\n\n        if (scriptState.filterMode === 'access') {\n            unreadSessions = unreadSessions.filter(item => !item.querySelector('span._ss_Tny_c4mb'));\n        } else if (scriptState.filterMode === 'unread') {\n            unreadSessions = unreadSessions.filter(item => item.querySelector('span._ss_Tny_c4mb'));\n        }\n\n        let selectedCount = unreadSessions.length;\n\n        if (scriptState.selectFromBottom) {\n            unreadSessions.reverse();\n        }\n\n        for (const sessionItem of unreadSessions) {\n            sessionItem.click();\n            sessionItem.style.border = '2px solid #ec4899';\n            sessionItem.style.boxSizing = 'border-box';\n            setTimeout(() => {\n                sessionItem.style.border = 'none';\n            }, 100);\n        }\n\n        showSelectionNotification(selectedCount, sessionIDs.slice(0, 10));\n        console.log(`[旧版会话选择] 选择了 ${selectedCount} 个会话`);\n    }\n\n    // ==================== 新版页面逻辑 ====================\n\n    function findTabByName(name) {\n        const tabs = document.querySelectorAll('.view-list__area__item');\n        for (let tab of tabs) {\n            const tabName = tab.querySelector('.view-list__area__item__left__name')?.textContent?.trim();\n            if (tabName === name) return tab;\n        }\n        return null;\n    }\n\n    function isOnPage(name) {\n        const tab = findTabByName(name);\n        return tab && tab.classList.contains('view-list__area__item--active');\n    }\n\n    function getUnallocatedCount() {\n        const tab = findTabByName(\"待分配\");\n        if (!tab) return 0;\n        const countSpan = tab.querySelector('.view-list__area__item__left__count span');\n        return countSpan ? parseInt(countSpan.textContent) || 0 : 0;\n    }\n\n    function switchToPage(name) {\n        if (isOnPage(name)) {\n            console.log(`[页面检查] 已在 \"${name}\" 页面`);\n            return true;\n        }\n        const tab = findTabByName(name);\n        if (!tab) {\n            console.warn(`[页面切换] 未找到 \"${name}\" 标签`);\n            return false;\n        }\n        tab.click();\n        console.log(`[页面切换] 已点击 \"${name}\" 标签，等待加载...`);\n        return false;\n    }\n\n    function isInAllowedUnreadPage() {\n        const allowedPages = [\"我的\", \"未读\", \"全部\", \"待回复\"];\n        return allowedPages.some(page => isOnPage(page));\n    }\n\n    function getCurrentPageName() {\n        const activeTab = document.querySelector('.view-list__area__item--active .view-list__area__item__left__name');\n        return activeTab ? activeTab.textContent.trim() : '未知';\n    }\n\n    function waitForPageLoad(delay = 800) {\n        return new Promise(resolve => setTimeout(resolve, delay));\n    }\n\n    async function handleDefaultMode() {\n        console.log('[默认模式] 开始执行...');\n        const unallocatedCount = getUnallocatedCount();\n        \n        if (unallocatedCount > 0) {\n            console.log(`[默认模式] 检测到待分配: ${unallocatedCount} 个，前往处理`);\n            if (!isOnPage(\"待分配\")) {\n                switchToPage(\"待分配\");\n                await waitForPageLoad(1200);\n            }\n            performSelection('access');\n        } else {\n            console.log(`[默认模式] 待分配为0，切换到配置的默认页面: \"${CONFIG.DEFAULT_BACK_TAB}\"`);\n            if (!isOnPage(CONFIG.DEFAULT_BACK_TAB)) {\n                switchToPage(CONFIG.DEFAULT_BACK_TAB);\n                await waitForPageLoad(1200);\n            }\n            performSelection('unread');\n        }\n    }\n\n    async function handleUnreadMode() {\n        console.log('[未读模式] 开始执行...');\n        const currentPage = getCurrentPageName();\n        console.log(`[未读模式] 当前页面: \"${currentPage}\"`);\n        \n        if (isInAllowedUnreadPage()) {\n            console.log(`[未读模式] 在允许页面\"${currentPage}\"，直接处理未读`);\n            performSelection('unread');\n        } else {\n            console.log(`[未读模式] 不在允许页面，切换到配置的默认页面: \"${CONFIG.DEFAULT_BACK_TAB}\"`);\n            if (!isOnPage(CONFIG.DEFAULT_BACK_TAB)) {\n                switchToPage(CONFIG.DEFAULT_BACK_TAB);\n                await waitForPageLoad(1200);\n            }\n            performSelection('unread');\n        }\n    }\n\n    async function handleAccessMode() {\n        console.log('[接入模式] 开始执行...');\n        if (!isOnPage(\"待分配\")) {\n            switchToPage(\"待分配\");\n            await waitForPageLoad(1200);\n        }\n        performSelection('access');\n    }\n\n    /**\n     * 执行会话筛选和点击\n     * @param {string} mode - 筛选模式: 'access' 或 'unread'\n     */\n    function performSelection(mode) {\n        let sessionItems = Array.from(document.querySelectorAll('div.session-item'));\n        let targetSessions = [];\n        let sessionIDs = [];\n\n        console.log(`[会话筛选] 模式: ${mode}, 总数: ${sessionItems.length}`);\n\n        for (const item of sessionItems) {\n            const sessionName = item.querySelector('.session-item__content__top__left__name')?.textContent?.trim() || '未知';\n            const unreadBadge = item.querySelector('.arco-badge-number');\n            const readCheckIcon = item.querySelector('.session-item__content__center__prefix__icon__check');\n            const userName = item.querySelector('.session-item__content__user__name')?.textContent?.trim();\n\n            const hasUnread = !!unreadBadge;\n            const isReadReplied = !!readCheckIcon; // 有打钩标志 = 已读已回\n            const isUnallocated = userName === '未接待';\n\n            let shouldSelect = false;\n            \n            if (mode === 'access') {\n                // 接入模式：只选未接待的会话\n                // 但要遵守\"未读未回\"开关的设置\n                if (isUnallocated) {\n                    // 未接待的会话，再根据\"未读未回\"开关决定是否选择\n                    if (scriptState.includeReadSessions) {\n                        // 包含已读已回，所有未接待都选\n                        shouldSelect = true;\n                    } else {\n                        // 仅未读未回，只选没有打钩（未读已回）的\n                        shouldSelect = !isReadReplied;\n                    }\n                }\n            } else {\n                // 未读模式：要有未读，并遵守\"未读未回\"开关\n                shouldSelect = hasUnread && (scriptState.includeReadSessions || !isReadReplied);\n            }\n\n            if (shouldSelect) {\n                targetSessions.push(item);\n                sessionIDs.push(sessionName);\n            }\n        }\n\n        const count = targetSessions.length;\n        console.log(`[筛选完成] 符合条件: ${count} 个`);\n\n        sessionItems.forEach(item => {\n            item.style.outline = '';\n            item.style.backgroundColor = '';\n            item.style.boxShadow = '';\n        });\n\n        if (count > 0) {\n            targetSessions.forEach(session => {\n                session.style.outline = '3px solid #ec4899';\n                session.style.outlineOffset = '-3px';\n                session.style.boxShadow = '0 0 0 3px rgba(236,72,153,0.3)';\n            });\n\n            const targetSession = scriptState.selectFromBottom ? \n                targetSessions[targetSessions.length - 1] : \n                targetSessions[0];\n            \n            targetSession.style.backgroundColor = 'rgba(236,72,153,0.2)';\n            targetSession.style.outline = '3px solid #db2777';\n            \n            setTimeout(() => {\n                targetSession.click();\n                console.log(`[执行点击] ${scriptState.selectFromBottom ? '最后' : '最前'} → ${sessionIDs[scriptState.selectFromBottom ? count - 1 : 0]}`);\n            }, 100);\n        }\n\n        setTimeout(() => {\n            sessionItems.forEach(item => {\n                item.style.outline = '';\n                item.style.backgroundColor = '';\n                item.style.boxShadow = '';\n            });\n        }, 3000);\n\n        const modeText = mode === 'access' ? '接入' : '未读';\n        const currentPage = getCurrentPageName();\n        showSelectionNotification(count, sessionIDs.slice(0, 8), scriptState.selectFromBottom, modeText, currentPage);\n    }\n\n    function showSelectionNotification(count, sessionIDs, fromBottom, mode = '', currentPage = '') {\n        const oldNotification = document.getElementById('sessionSelectionNotification');\n        if (oldNotification) oldNotification.remove();\n\n        const notification = document.createElement('div');\n        notification.id = 'sessionSelectionNotification';\n\n        const directionText = fromBottom ? '最后一条' : '最前一条';\n        const filterText = scriptState.includeReadSessions ? '（包含已读已回）' : '（仅未读未回）';\n\n        if (PAGE_VERSION === 'old') {\n            // 旧版通知\n            if (count > 0) {\n                notification.innerHTML = `\n                    <div style=\"display:flex;align-items:center;margin-bottom:8px;\">\n                        <i class=\"ivu-icon ivu-icon-md-mail-unread\" style=\"font-size:20px;margin-right:10px;\"></i>\n                        <div style=\"font-weight:600;\">已选择 ${count} 个会话${scriptState.selectFromBottom ? '（从下到上）' : '（从上到下）'}</div>\n                    </div>\n                `;\n                notification.style.backgroundColor = '#8b5cf6';\n            } else {\n                notification.innerHTML = `\n                    <div style=\"display:flex;align-items:center;\">\n                        <i class=\"ivu-icon ivu-icon-md-mail-open\" style=\"font-size:20px;margin-right:10px;\"></i>\n                        <div>未找到符合条件的会话</div>\n                    </div>\n                `;\n                notification.style.backgroundColor = '#6b7280';\n            }\n            Object.assign(notification.style, {\n                position: 'fixed', bottom: '30px', right: '30px', padding: '16px 20px',\n                borderRadius: '12px', color: 'white', fontWeight: '500',\n                boxShadow: '0 6px 16px rgba(0,0,0,0.2)', zIndex: '20000',\n                opacity: '0', transform: 'translateY(20px)',\n                transition: 'all 0.4s cubic-bezier(0.175,0.885,0.32,1.275)',\n                maxWidth: '400px', fontFamily: 'system-ui, sans-serif', lineHeight: '1.5'\n            });\n        } else {\n            // 新版通知\n            if (count > 0) {\n                notification.innerHTML = `\n                    <div style=\"display:flex;align-items:center;margin-bottom:10px;\">\n                        <i class=\"arco-icon icon-mail-unread\" style=\"font-size:22px;margin-right:12px;color:#ec4899;\"></i>\n                        <div style=\"font-weight:600;font-size:16px;\">\n                            ✅ [${currentPage}] 框选 <span style=\"color:#ec4899\">${count}</span> 个${mode}会话<br>\n                            <span style=\"font-size:13px;color:#666;\">点击 ${directionText} ${filterText}</span>\n                        </div>\n                    </div>\n                    ${sessionIDs.length > 0 ? `<div style=\"font-size:12px;opacity:0.8;max-height:80px;overflow-y:auto;\">${sessionIDs.map(id => `• ${id}`).join('<br>')}</div>` : ''}\n                `;\n                notification.style.backgroundColor = '#ecfdf5';\n                notification.style.borderLeft = '4px solid #ec4899';\n                notification.style.color = '#166534';\n            } else {\n                notification.innerHTML = `\n                    <div style=\"display:flex;align-items:center;\">\n                        <i class=\"arco-icon icon-mail-open\" style=\"font-size:20px;margin-right:10px;color:#6b7280;\"></i>\n                        <div>[${currentPage}] 未找到符合条件的${mode}会话 ${filterText}</div>\n                    </div>\n                `;\n                notification.style.backgroundColor = '#fef2f2';\n                notification.style.borderLeft = '4px solid #f87171';\n                notification.style.color = '#991b1b';\n            }\n            Object.assign(notification.style, {\n                position: 'fixed', bottom: '30px', right: '30px', padding: '20px 24px',\n                borderRadius: '12px', fontWeight: '500', boxShadow: '0 10px 30px rgba(0,0,0,0.15)',\n                zIndex: '20000', opacity: '0', transform: 'translateY(20px)', transition: 'all .4s',\n                maxWidth: '400px', fontFamily: 'system-ui, sans-serif', lineHeight: '1.4'\n            });\n        }\n\n        document.body.appendChild(notification);\n        setTimeout(() => { notification.style.opacity = '1'; notification.style.transform = 'translateY(0)'; }, 100);\n        setTimeout(() => {\n            notification.style.opacity = '0';\n            setTimeout(() => notification.remove(), 300);\n        }, 4000);\n    }\n\n    // ==================== UI创建（带拖动） ====================\n\n    function createSelectButton() {\n        if (document.getElementById('selectUnreadSessionsBtn')) return;\n\n        loadPanelPosition();\n\n        const container = document.createElement('div');\n        container.id = 'selectButtonContainer';\n        container.style.cssText = `\n            position:fixed;\n            top:${scriptState.panelPosition.top}px;\n            right:${scriptState.panelPosition.right}px;\n            z-index:9999;\n            background:white;\n            padding:12px;\n            border-radius:12px;\n            box-shadow:0 8px 24px rgba(0,0,0,0.15);\n            border:1px solid #e5e7eb;\n            display:flex;\n            align-items:center;\n            gap:10px;\n            cursor:move;\n            user-select:none;\n        `;\n\n        const switches = document.createElement('div');\n        switches.style.cssText = 'display:flex;flex-direction:column;gap:6px;';\n\n        // 方向开关\n        const dirHtml = `\n            <div class=\"toggle-container\">\n                <span class=\"switch-label top\">从上到下</span>\n                <label class=\"toggle-switch\">\n                    <input type=\"checkbox\" id=\"dirTgl\">\n                    <span class=\"toggle-slider\"></span>\n                </label>\n                <span class=\"switch-label bottom\">从下到上</span>\n            </div>\n        `;\n\n        // 未读未回开关 - 现在在所有模式下都有效\n        const unreadHtml = `\n            <div class=\"toggle-container\">\n                <label class=\"toggle-switch\">\n                    <input type=\"checkbox\" id=\"unrTgl\" checked>\n                    <span class=\"toggle-slider\"></span>\n                </label>\n                <span style=\"font-size:9px;color:#8b5cf6;margin-left:4px;font-weight:500;\">未读未回</span>\n            </div>\n        `;\n\n        // 过滤模式\n        const filterHtml = `\n            <div class=\"filter-container\">\n                <div class=\"filter-option selected\" data-value=\"default\">默认</div>\n                <div class=\"filter-option\" data-value=\"unread\">未读</div>\n                <div class=\"filter-option\" data-value=\"access\">接入</div>\n            </div>\n        `;\n\n        switches.innerHTML = dirHtml + unreadHtml + filterHtml;\n\n        // 主按钮\n        const btn = document.createElement('div');\n        btn.id = 'selectUnreadSessionsBtn';\n        btn.innerHTML = PAGE_VERSION === 'old' ? \n            '<i class=\"ivu-icon ivu-icon-md-mail-unread\" style=\"font-size:20px;color:white;\"></i>' :\n            '<i class=\"arco-icon icon-mail-unread\" style=\"font-size:20px;color:white;\"></i>';\n        btn.style.cssText = `\n            width:36px;height:36px;background:linear-gradient(135deg,#ec4899,#db2777);\n            border-radius:10px;cursor:pointer;display:flex;align-items:center;justify-content:center;\n            box-shadow:0 4px 12px rgba(236,72,153,.4);transition:all .3s;\n            pointer-events:auto;\n        `;\n\n        btn.onmouseenter = () => {\n            btn.style.transform = 'scale(1.1) rotate(5deg)';\n            btn.style.boxShadow = '0 8px 24px rgba(236,72,153,.6)';\n        };\n        btn.onmouseleave = () => {\n            btn.style.transform = 'scale(1) rotate(0)';\n            btn.style.boxShadow = '0 4px 12px rgba(236,72,153,.4)';\n        };\n        btn.onclick = handleSelectClick;\n\n        container.append(switches, btn);\n        document.body.appendChild(container);\n\n        // 事件绑定\n        document.getElementById('dirTgl').onchange = (e) => {\n            scriptState.selectFromBottom = e.target.checked;\n            updateDirectionLabels();\n        };\n\n        document.getElementById('unrTgl').onchange = (e) => {\n            scriptState.includeReadSessions = e.target.checked;\n            console.log(`[未读未回切换] 当前状态: ${scriptState.includeReadSessions ? '包含已读已回' : '仅未读未回'}`);\n        };\n\n        document.querySelectorAll('.filter-option').forEach(opt => {\n            opt.onclick = (e) => {\n                document.querySelectorAll('.filter-option').forEach(o => o.classList.remove('selected'));\n                e.target.classList.add('selected');\n                scriptState.filterMode = e.target.dataset.value;\n                console.log(`[模式切换] 当前模式: ${scriptState.filterMode}`);\n            };\n        });\n\n        // ==================== 拖动功能 ====================\n        let isDragging = false;\n        let dragOffsetX = 0;\n        let dragOffsetY = 0;\n\n        container.addEventListener('mousedown', (e) => {\n            // 如果点击的是开关或按钮，不启用拖动\n            if (e.target.closest('input') || e.target.closest('#selectUnreadSessionsBtn')) {\n                return;\n            }\n            isDragging = true;\n            const rect = container.getBoundingClientRect();\n            dragOffsetX = e.clientX - rect.left;\n            dragOffsetY = e.clientY - rect.top;\n            container.style.cursor = 'grabbing';\n        });\n\n        document.addEventListener('mousemove', (e) => {\n            if (!isDragging) return;\n\n            const newX = e.clientX - dragOffsetX;\n            const newY = e.clientY - dragOffsetY;\n\n            // 限制在视口内\n            const maxX = window.innerWidth - container.offsetWidth;\n            const maxY = window.innerHeight - container.offsetHeight;\n\n            const boundX = Math.max(0, Math.min(newX, maxX));\n            const boundY = Math.max(0, Math.min(newY, maxY));\n\n            container.style.left = boundX + 'px';\n            container.style.right = 'auto';\n            container.style.top = boundY + 'px';\n        });\n\n        document.addEventListener('mouseup', () => {\n            if (!isDragging) return;\n            isDragging = false;\n            container.style.cursor = 'move';\n\n            // 保存位置\n            const rect = container.getBoundingClientRect();\n            scriptState.panelPosition = {\n                top: rect.top,\n                right: window.innerWidth - rect.right\n            };\n            savePanelPosition(scriptState.panelPosition);\n            console.log('[位置保存] 当前位置:', scriptState.panelPosition);\n        });\n\n        updateDirectionLabels();\n        console.log('[UI创建] ✅ 按钮已创建（可拖动）');\n    }\n\n    function updateDirectionLabels() {\n        const topLabel = document.querySelector('.switch-label.top');\n        const bottomLabel = document.querySelector('.switch-label.bottom');\n        if (!topLabel || !bottomLabel) return;\n\n        if (scriptState.selectFromBottom) {\n            topLabel.style.color = '#888';\n            bottomLabel.style.color = '#8b5cf6';\n        } else {\n            topLabel.style.color = '#8b5cf6';\n            bottomLabel.style.color = '#888';\n        }\n    }\n\n    function handleSelectClick() {\n        if (scriptState.isProcessing) {\n            console.log('[防护] 正在处理中，请稍候...');\n            return;\n        }\n\n        scriptState.isProcessing = true;\n        const button = document.getElementById('selectUnreadSessionsBtn');\n        button.style.transform = 'scale(0.95) rotate(-5deg)';\n        button.style.background = 'linear-gradient(135deg,#8b5cf6,#7c3aed)';\n\n        setTimeout(async () => {\n            try {\n                if (PAGE_VERSION === 'old') {\n                    selectUnreadSessionsOld();\n                } else {\n                    if (scriptState.filterMode === 'default') {\n                        await handleDefaultMode();\n                    } else if (scriptState.filterMode === 'unread') {\n                        await handleUnreadMode();\n                    } else if (scriptState.filterMode === 'access') {\n                        await handleAccessMode();\n                    }\n                }\n            } finally {\n                button.style.transform = 'scale(1) rotate(0)';\n                button.style.background = 'linear-gradient(135deg,#ec4899,#db2777)';\n                scriptState.isProcessing = false;\n            }\n        }, 150);\n    }\n\n    // 样式注入\n    const style = document.createElement('style');\n    style.textContent = `\n        .toggle-container{display:flex;align-items:center;gap:4px;font-size:10px;color:#666}\n        .filter-container{display:flex;gap:3px;font-size:9px;}\n        .filter-option{flex:1;text-align:center;padding:4px 6px;border-radius:4px;background:#f8fafc;cursor:pointer;transition:all .2s;border:1px solid #e2e8f0}\n        .filter-option:hover{background:#f1f5f9}\n        .filter-option.selected{background:#8b5cf6;color:white;border-color:#7c4dff;font-weight:600}\n        .toggle-switch{position:relative;display:inline-block;width:32px;height:14px;vertical-align:middle}\n        .toggle-switch input{opacity:0;width:0;height:0}\n        .toggle-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background:#cbd5e1;transition:.3s;border-radius:34px}\n        .toggle-slider:before{content:\"\";position:absolute;height:10px;width:10px;left:2px;bottom:2px;background:white;transition:.3s;border-radius:50%}\n        input:checked+.toggle-slider{background:#8b5cf6}\n        input:checked+.toggle-slider:before{transform:translateX(18px)}\n        .switch-label{font-size:9px;transition:color .2s;white-space:nowrap}\n    `;\n    document.head.appendChild(style);\n\n    // ==================== 初始化 ====================\n\n    function initialize() {\n        detectPageVersion();\n        scriptState.isOldPage = PAGE_VERSION === 'old';\n\n        // 启动自动发送ID功能\n        setInterval(activateSessionButton, 250);\n\n        if (PAGE_VERSION === 'old') {\n            setupSessionSwitchObserver();\n        } else {\n            // 新版：启动自动接入观察器\n            setupAccessSessionObserver();\n        }\n\n        const obs = new MutationObserver(() => {\n            if (!document.getElementById('selectUnreadSessionsBtn')) createSelectButton();\n        });\n        obs.observe(document.body, { childList: true, subtree: true });\n\n        setTimeout(createSelectButton, 1500);\n        console.log(`[脚本初始化] ✅ 完成 | 版本: ${PAGE_VERSION === 'old' ? '旧版' : '新版'} | 默认返回页面: ${CONFIG.DEFAULT_BACK_TAB}`);\n    }\n\n    if (document.readyState === 'complete') {\n        setTimeout(initialize, 800);\n    } else {\n        window.addEventListener('load', () => setTimeout(initialize, 800));\n    }\n\n    console.log('[增强脚本 v4.2] ✅ 接入模式支持未读未回开关');\n\n})();","functional_script_code_hash":"c18b790a32804e6895a69a59eae052e954aef8a16d601f6bd312be7b5722f87c","loader_script_hash":"36ef33d3febd0344eb435225697aad3659cd0579452187a8083f08f3e5d37163","config":{"feature_x_enabled":true,"keyword_list":["example","test"],"salesmartly_api_key":"YOUR_SALESMARTLY_API_KEY_IF_NEEDED"}}