// ==UserScript== // @name DeepSeek 功能增强工具箱 // @namespace https://github.com/yourname/deepseek-tools // @version 4.0.1 // @description 一站式管理:代码块折叠、表格优化导出、自动折叠AI思考过程。所有设置即时生效。 // @tag 工具 // @tag 优化 // @tag DeepSeek // @author 友野YouyEr // @icon https://fe-static.deepseek.com/chat/favicon.svg // @match https://chat.deepseek.com/* // @match https://www.deepseek.com/* // @match https://deepseek.com/* // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @require https://cdn.jsdelivr.net/npm/html2canvas@1.4.1/dist/html2canvas.min.js // @run-at document-end // ==/UserScript== (function() { 'use strict'; // ==================== 存储键与全局变量 ==================== const STORAGE_FOLD_THRESHOLD = 'deepseek_fold_threshold'; const STORAGE_PREVIEW_LINES = 'deepseek_fold_preview_lines'; const STORAGE_TABLE_BUTTONS_ENABLED = 'deepseek_table_buttons_enabled'; const STORAGE_AUTO_COLLAPSE_THINKING = 'deepseek_auto_collapse_thinking'; const STORAGE_SIMULATE_CLICK_THINKING = 'deepseek_simulate_click_thinking'; let foldThreshold = GM_getValue(STORAGE_FOLD_THRESHOLD, 20); let previewLines = GM_getValue(STORAGE_PREVIEW_LINES, 0); let enablePreviewLines = previewLines > 0; let tableButtonsEnabled = GM_getValue(STORAGE_TABLE_BUTTONS_ENABLED, true); let autoCollapseThinking = GM_getValue(STORAGE_AUTO_COLLAPSE_THINKING, true); let simulateClickThinking = GM_getValue(STORAGE_SIMULATE_CLICK_THINKING, true); const btnTextFold = '折叠'; const btnTextUnfold = '展开'; // ==================== SVG 图标 (代码块折叠) ==================== const ICON_CHEVRON_DOWN = ``; const ICON_CHEVRON_UP = ``; // ==================== 通用 Toast ==================== function showToast(message, duration = 2000) { const existingToast = document.getElementById('ds-fold-toast'); if (existingToast) existingToast.remove(); const toast = document.createElement('div'); toast.id = 'ds-fold-toast'; toast.textContent = message; toast.style.cssText = ` position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.8); backdrop-filter: blur(8px); color: white; padding: 10px 20px; border-radius: 8px; font-size: 14px; font-family: system-ui, -apple-system, sans-serif; z-index: 10001; opacity: 0; transition: opacity 0.2s; pointer-events: none; white-space: nowrap; box-shadow: 0 2px 8px rgba(0,0,0,0.2); `; document.body.appendChild(toast); setTimeout(() => toast.style.opacity = '1', 10); setTimeout(() => { toast.style.opacity = '0'; setTimeout(() => toast.remove(), 200); }, duration); } // ==================== 统一控制面板 ==================== function openControlPanel() { const existingOverlay = document.getElementById('ds-control-panel-overlay'); if (existingOverlay) existingOverlay.remove(); const overlay = document.createElement('div'); overlay.id = 'ds-control-panel-overlay'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); backdrop-filter: blur(4px); z-index: 10001; display: flex; align-items: center; justify-content: center; `; const panel = document.createElement('div'); panel.style.cssText = ` background: var(--ds-bg-primary, #1e1e2f); border-radius: 16px; box-shadow: 0 12px 32px rgba(0,0,0,0.3); width: 440px; max-width: 90%; padding: 28px; font-family: system-ui, -apple-system, sans-serif; color: var(--ds-text-primary, #e2e2e2); max-height: 80vh; overflow-y: auto; `; // 标题 const title = document.createElement('h2'); title.textContent = '⚙️ DeepSeek 全功能增强设置'; title.style.cssText = 'margin:0 0 24px 0; font-size:20px; font-weight:600;'; // --- 代码块折叠部分 --- const codeSectionTitle = createSectionTitle('代码块折叠'); panel.appendChild(codeSectionTitle); panel.appendChild(createNumberSetting( '自动折叠阈值', '代码块行数超过该值时自动折叠(0 = 禁用)', foldThreshold, value => { foldThreshold = value; GM_setValue(STORAGE_FOLD_THRESHOLD, value); reapplyFoldToAllCodeBlocks(); showToast(`折叠阈值已更新为 ${value === 0 ? '关闭' : value}`); } )); panel.appendChild(createNumberSetting( '折叠预览行数', '折叠后显示的行数(0 = 完全隐藏)', previewLines, value => { previewLines = value; enablePreviewLines = value > 0; GM_setValue(STORAGE_PREVIEW_LINES, value); reapplyFoldToAllCodeBlocks(); showToast(`预览行数已更新为 ${value === 0 ? '关闭(完全隐藏)' : value}`); } )); // --- 表格优化部分 --- const tableSectionTitle = createSectionTitle('表格优化导出'); panel.appendChild(tableSectionTitle); const switchLabel1 = document.createElement('label'); switchLabel1.style.cssText = 'display:flex; align-items:center; gap:12px; cursor:pointer; margin-bottom: 24px;'; switchLabel1.innerHTML = ` 表格导出按钮 悬停表格显示 PNG/CSV 导出按钮 `; panel.appendChild(switchLabel1); const tableSwitch = switchLabel1.querySelector('input'); tableSwitch.addEventListener('change', () => { tableButtonsEnabled = tableSwitch.checked; GM_setValue(STORAGE_TABLE_BUTTONS_ENABLED, tableButtonsEnabled); toggleTableButtons(tableButtonsEnabled); showToast(`表格导出按钮已${tableButtonsEnabled ? '开启' : '关闭'}`); }); // --- AI思考区域自动折叠 --- const thinkSectionTitle = createSectionTitle('AI思考过程折叠'); panel.appendChild(thinkSectionTitle); const switchLabel2 = document.createElement('label'); switchLabel2.style.cssText = 'display:flex; align-items:center; gap:12px; cursor:pointer; margin-bottom: 12px;'; switchLabel2.innerHTML = ` 自动折叠思考区域 AI开始思考后自动收起“已思考”过程 `; panel.appendChild(switchLabel2); const thinkSwitch = switchLabel2.querySelector('input'); thinkSwitch.addEventListener('change', () => { autoCollapseThinking = thinkSwitch.checked; GM_setValue(STORAGE_AUTO_COLLAPSE_THINKING, autoCollapseThinking); reapplyThinkingSections(); showToast(`自动折叠思考区域已${autoCollapseThinking ? '开启' : '关闭'}`); }); const switchLabel3 = document.createElement('label'); switchLabel3.style.cssText = 'display:flex; align-items:center; gap:12px; cursor:pointer; margin-bottom: 24px;'; switchLabel3.innerHTML = ` 模拟点击折叠 通过模拟点击箭头折叠(保持原生交互) `; panel.appendChild(switchLabel3); const simulateSwitch = switchLabel3.querySelector('input'); simulateSwitch.addEventListener('change', () => { simulateClickThinking = simulateSwitch.checked; GM_setValue(STORAGE_SIMULATE_CLICK_THINKING, simulateClickThinking); showToast(`模拟点击折叠已${simulateClickThinking ? '开启' : '关闭'}(新产生的思考生效)`); }); // 关闭按钮 const closeBtn = document.createElement('button'); closeBtn.textContent = '关闭面板'; closeBtn.style.cssText = ` width:100%; padding:10px; border:none; border-radius:10px; background:#4f46e5; color:white; font-size:15px; cursor:pointer; transition: background 0.2s; `; closeBtn.onmouseenter = () => closeBtn.style.background = '#6366f1'; closeBtn.onmouseleave = () => closeBtn.style.background = '#4f46e5'; closeBtn.addEventListener('click', () => overlay.remove()); panel.appendChild(closeBtn); overlay.appendChild(panel); document.body.appendChild(overlay); overlay.addEventListener('click', e => { if (e.target === overlay) overlay.remove(); }); } function createSectionTitle(text) { const el = document.createElement('h3'); el.textContent = text; el.style.cssText = 'margin: 24px 0 12px 0; font-size:16px; font-weight:600; border-top: 1px solid rgba(128,128,128,0.2); padding-top: 12px;'; return el; } function createNumberSetting(labelText, description, currentValue, onChange) { const section = document.createElement('div'); section.style.marginBottom = '16px'; const label = document.createElement('div'); label.style.cssText = 'display:flex; justify-content:space-between; align-items:center; margin-bottom:6px;'; label.innerHTML = `${labelText}`; const desc = document.createElement('div'); desc.textContent = description; desc.style.cssText = 'font-size:13px; opacity:0.7; margin-bottom:8px; line-height:1.4;'; const input = document.createElement('input'); input.type = 'number'; input.value = currentValue; input.min = 0; input.step = 1; input.style.cssText = ` width:100%; padding:10px 12px; border-radius:8px; border:1px solid rgba(128,128,128,0.3); background: var(--ds-bg-secondary, #2a2a36); color: var(--ds-text-primary, #e2e2e2); font-size:14px; box-sizing:border-box; outline:none; transition: border-color 0.2s; `; input.onfocus = () => input.style.borderColor = 'rgba(128,128,128,0.6)'; input.onblur = () => input.style.borderColor = 'rgba(128,128,128,0.3)'; input.addEventListener('change', () => { let val = parseInt(input.value, 10); if (isNaN(val) || val < 0) val = 0; input.value = val; onChange(val); }); section.appendChild(label); section.appendChild(desc); section.appendChild(input); return section; } // 设置变动后的刷新函数 function reapplyFoldToAllCodeBlocks() { document.querySelectorAll('pre').forEach(pre => { pre.removeAttribute('data-fold-processed'); if (pre.dataset.origDisplay) { pre.style.display = pre.dataset.origDisplay; delete pre.dataset.origDisplay; } if (pre.dataset.origMaxHeight) { pre.style.maxHeight = pre.dataset.origMaxHeight; pre.style.overflow = pre.dataset.origOverflow || ''; delete pre.dataset.origMaxHeight; delete pre.dataset.origOverflow; } pre.classList.remove('ds-fold-preview'); const btn = pre.parentElement?.querySelector('.ds-fold-btn'); if (btn) btn.remove(); addFoldButtonToCodeBlock(pre); }); } function toggleTableButtons(enabled) { document.querySelectorAll('.ds-markdown table').forEach(table => { const btnContainer = table.querySelector('.table-internal-buttons'); if (enabled) { if (!btnContainer) { table.removeAttribute('data-internal-buttons-added'); addButtonsToTable(table); } } else { if (btnContainer) { btnContainer.remove(); table.removeAttribute('data-internal-buttons-added'); } } }); } function reapplyThinkingSections() { if (autoCollapseThinking) { processAllThinkingSections(); } } // ==================== 菜单命令 ==================== GM_registerMenuCommand('⚙️ 脚本设置', openControlPanel); // ==================== 全局样式 ==================== GM_addStyle(` /* 代码块折叠 */ .ds-fold-btn { background: transparent; border: none; border-radius: 12px; font-size: 13px; padding: 4px 8px; cursor: pointer; transition: all 0.2s; font-family: system-ui, sans-serif; user-select: none; display: inline-flex; align-items: center; gap: 2px; opacity: 0.7; } .ds-fold-btn:hover { background: rgba(128,128,128,0.2); opacity: 1; } .ds-fold-btn .fold-icon { width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; } .ds-fold-btn svg { width: 20px; height: 20px; display: block; } .efa13877 .ds-fold-btn { margin-left: 4px; } .ds-fold-preview::after { content: " ..."; display: block; text-align: center; color: inherit; opacity: 0.6; margin-top: 4px; } /* 表格样式 */ .ds-markdown table { width: 100% !important; border-collapse: separate !important; border-spacing: 0 !important; margin: 1em 0 !important; background-color: var(--ds-bg-primary, #ffffff) !important; border-radius: 12px !important; overflow: hidden !important; box-shadow: 0 1px 3px rgba(0,0,0,0.05) !important; position: relative; } .ds-markdown th, .ds-markdown td { border: 1px solid #e5e7eb !important; padding: 12px 16px !important; vertical-align: top !important; font-size: 14px !important; line-height: 1.5 !important; } .ds-markdown th { background: linear-gradient(135deg, #f9fafb, #f3f4f6) !important; font-weight: 600 !important; color: #1f2937 !important; border-bottom: 1px solid #e5e7eb !important; letter-spacing: 0.02em !important; } .ds-markdown tbody tr:nth-child(even) { background-color: #fafafa !important; } .ds-markdown tbody tr:hover { background-color: #eff6ff !important; transition: background-color 0.2s !important; } .table-internal-buttons { position: absolute; bottom: 12px; right: 12px; display: flex; flex-direction: column; gap: 8px; z-index: 10; opacity: 0; visibility: hidden; transition: opacity 0.2s, visibility 0.2s; pointer-events: none; } .ds-markdown table:hover .table-internal-buttons, .table-internal-buttons:hover { opacity: 1; visibility: visible; pointer-events: auto; } .internal-export-btn { width: 32px; height: 32px; background: rgba(255,255,255,0.95); backdrop-filter: blur(4px); border: 1px solid #e2e8f0; border-radius: 8px; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 6px rgba(0,0,0,0.1); transition: all 0.2s; font-size: 16px; position: relative; } .internal-export-btn:hover { background: #fff; transform: scale(1.05); box-shadow: 0 4px 10px rgba(0,0,0,0.15); border-color: #cbd5e1; } .internal-export-btn:active { transform: scale(0.98); } .internal-export-btn::after { content: attr(data-tooltip); position: absolute; right: 40px; top: 50%; transform: translateY(-50%); background: #1f2937; color: white; font-size: 12px; padding: 4px 8px; border-radius: 6px; white-space: nowrap; opacity: 0; visibility: hidden; transition: 0.1s; pointer-events: none; } .internal-export-btn:hover::after { opacity: 1; visibility: visible; } `); // ==================== 代码块折叠逻辑 ==================== const processedAttr = 'data-fold-processed'; function getLineCount(preEl) { const text = preEl.innerText || preEl.textContent || ''; let lines = text.split('\n'); if (lines.length && lines[lines.length-1] === '') lines.pop(); return lines.length; } function getLineHeight(preEl) { const style = window.getComputedStyle(preEl); let lh = style.lineHeight; if (lh === 'normal') lh = parseFloat(style.fontSize) * 1.2 + 'px'; return parseFloat(lh); } function shouldUsePreviewMode(preEl) { if (!enablePreviewLines) return false; return getLineCount(preEl) > previewLines; } function collapseBlock(preEl, btn) { if (shouldUsePreviewMode(preEl)) { const lh = getLineHeight(preEl); const maxH = lh * previewLines; if (!preEl.dataset.origMaxHeight) { preEl.dataset.origMaxHeight = preEl.style.maxHeight || ''; preEl.dataset.origOverflow = preEl.style.overflow || ''; } preEl.style.maxHeight = maxH + 'px'; preEl.style.overflow = 'hidden'; preEl.classList.add('ds-fold-preview'); } else { if (!preEl.dataset.origDisplay) { preEl.dataset.origDisplay = window.getComputedStyle(preEl).display; } preEl.style.display = 'none'; preEl.classList.remove('ds-fold-preview'); } const iconDiv = btn.querySelector('.fold-icon'); if (iconDiv) iconDiv.innerHTML = ICON_CHEVRON_UP; btn.querySelector('span').textContent = btnTextUnfold; btn.setAttribute('aria-label', '展开代码块'); } function expandBlock(preEl, btn) { if (preEl.dataset.origMaxHeight !== undefined) { preEl.style.maxHeight = preEl.dataset.origMaxHeight || ''; preEl.style.overflow = preEl.dataset.origOverflow || ''; preEl.classList.remove('ds-fold-preview'); } if (preEl.dataset.origDisplay !== undefined) { preEl.style.display = preEl.dataset.origDisplay || ''; } else { preEl.style.display = ''; } const iconDiv = btn.querySelector('.fold-icon'); if (iconDiv) iconDiv.innerHTML = ICON_CHEVRON_DOWN; btn.querySelector('span').textContent = btnTextFold; btn.setAttribute('aria-label', '折叠代码块'); } function findButtonContainer(preEl) { let parent = preEl.closest('.md-code-block'); if (!parent) return null; return parent.querySelector('.efa13877') || parent.querySelector('[class*="button-group"], [class*="actions"], [class*="buttons"]') || null; } function createFoldButton(preEl) { if (!preEl.dataset.origDisplay) preEl.dataset.origDisplay = window.getComputedStyle(preEl).display; const shouldAutoFold = foldThreshold > 0 && getLineCount(preEl) > foldThreshold; let isFolded = false; if (shouldAutoFold) { if (shouldUsePreviewMode(preEl)) { const lh = getLineHeight(preEl); const maxH = lh * previewLines; if (!preEl.dataset.origMaxHeight) { preEl.dataset.origMaxHeight = preEl.style.maxHeight || ''; preEl.dataset.origOverflow = preEl.style.overflow || ''; } preEl.style.maxHeight = maxH + 'px'; preEl.style.overflow = 'hidden'; preEl.classList.add('ds-fold-preview'); } else { preEl.style.display = 'none'; preEl.classList.remove('ds-fold-preview'); } isFolded = true; } const btn = document.createElement('button'); btn.className = 'ds-fold-btn'; const iconDiv = document.createElement('div'); iconDiv.className = 'fold-icon'; iconDiv.innerHTML = isFolded ? ICON_CHEVRON_UP : ICON_CHEVRON_DOWN; const textSpan = document.createElement('span'); textSpan.textContent = isFolded ? btnTextUnfold : btnTextFold; btn.appendChild(iconDiv); btn.appendChild(textSpan); btn.setAttribute('aria-label', isFolded ? '展开代码块' : '折叠代码块'); btn.addEventListener('click', (e) => { e.stopPropagation(); let currentlyFolded; if (preEl.dataset.origMaxHeight !== undefined && preEl.style.maxHeight && preEl.style.maxHeight !== 'none') { currentlyFolded = true; } else if (preEl.style.display === 'none') { currentlyFolded = true; } else { currentlyFolded = false; } if (currentlyFolded) expandBlock(preEl, btn); else collapseBlock(preEl, btn); }); return btn; } function addFoldButtonToCodeBlock(preEl) { if (preEl.hasAttribute(processedAttr)) return; const targetContainer = findButtonContainer(preEl); if (targetContainer) { if (targetContainer.querySelector('.ds-fold-btn')) { preEl.setAttribute(processedAttr, 'true'); return; } targetContainer.appendChild(createFoldButton(preEl)); } else { const wrapper = document.createElement('div'); wrapper.className = 'ds-fold-btn-wrapper'; wrapper.style.textAlign = 'right'; wrapper.style.marginBottom = '6px'; wrapper.appendChild(createFoldButton(preEl)); preEl.parentNode.insertBefore(wrapper, preEl); } preEl.setAttribute(processedAttr, 'true'); } function processAllExistingCodeBlocks() { document.querySelectorAll('pre').forEach(block => { if (!block.hasAttribute(processedAttr)) addFoldButtonToCodeBlock(block); }); } function cleanupLegacyWrappers() { document.querySelectorAll('.ds-fold-btn-wrapper').forEach(w => w.remove()); } function deduplicateButtons() { document.querySelectorAll('.efa13877').forEach(container => { const btns = container.querySelectorAll('.ds-fold-btn'); if (btns.length > 1) for (let i = 1; i < btns.length; i++) btns[i].remove(); }); } function observeCodeBlocks() { const observer = new MutationObserver(mutations => { for (const m of mutations) { if (m.type === 'childList' && m.addedNodes.length) { for (const node of m.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE) { if (node.matches && node.matches('pre')) addFoldButtonToCodeBlock(node); if (node.querySelectorAll) node.querySelectorAll('pre').forEach(addFoldButtonToCodeBlock); } } } } }); observer.observe(document.body, { childList: true, subtree: true }); } // ==================== 表格优化逻辑 ==================== function applyTableStyles(table) { const vc = document.querySelector('.ds-virtual-list-visible-items'); if (vc) { table.style.maxWidth = vc.clientWidth + 'px'; vc.style.overflowX = 'visible'; vc.style.maxWidth = '100%'; } else { table.style.maxWidth = '100%'; } table.style.width = '100%'; table.style.tableLayout = 'fixed'; if (getComputedStyle(table).position !== 'relative') table.style.position = 'relative'; table.querySelectorAll('th,td').forEach(cell => { cell.style.whiteSpace = 'normal'; cell.style.wordWrap = 'break-word'; cell.style.overflowWrap = 'break-word'; cell.style.wordBreak = 'break-word'; }); const headerRow = table.querySelector('thead tr') || table.querySelector('tr'); if (headerRow && headerRow.cells.length) { const per = (100 / headerRow.cells.length).toFixed(2) + '%'; for (let i = 0; i < headerRow.cells.length; i++) headerRow.cells[i].style.width = per; } let parent = table.parentElement; while (parent && parent !== document.body) { const comp = window.getComputedStyle(parent); if (comp.overflowX === 'auto' || comp.overflowX === 'scroll') parent.style.overflowX = 'visible'; if (parent.style.maxWidth && parent.style.maxWidth !== 'none') parent.style.maxWidth = '100%'; parent = parent.parentElement; } } async function exportTableAsPNG(table) { if (!window.html2canvas) { alert('html2canvas 未加载'); return; } try { const bc = table.querySelector('.table-internal-buttons'); let orig = null; if (bc) { orig = bc.style.display; bc.style.display = 'none'; } const canvas = await html2canvas(table, { scale: 2, backgroundColor: '#ffffff', logging: false, useCORS: false }); if (bc) bc.style.display = orig; const a = document.createElement('a'); a.download = `table_${Date.now()}.png`; a.href = canvas.toDataURL('image/png'); a.click(); } catch (e) { console.error(e); alert('导出PNG失败'); } } function exportTableAsCSV(table) { const rows = []; const thead = table.querySelector('thead'); if (thead) thead.querySelectorAll('tr').forEach(tr => { const rd = []; tr.querySelectorAll('th').forEach(th => rd.push(getCellText(th))); if (rd.length) rows.push(rd); }); const tbody = table.querySelector('tbody'); if (tbody) tbody.querySelectorAll('tr').forEach(tr => { const rd = []; tr.querySelectorAll('td').forEach(td => rd.push(getCellText(td))); if (rd.length) rows.push(rd); }); else table.querySelectorAll('tr').forEach(tr => { const rd = []; tr.querySelectorAll('td,th').forEach(c => rd.push(getCellText(c))); if (rd.length) rows.push(rd); }); if (!rows.length) { alert('无数据'); return; } const csv = rows.map(r => r.map(c => { if (c.includes(',') || c.includes('"') || c.includes('\n')) c = '"' + c.replace(/"/g,'""') + '"'; return c; }).join(',')).join('\n'); const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' }); const a = document.createElement('a'); a.href = URL.createObjectURL(blob); a.download = `table_${Date.now()}.csv`; a.click(); setTimeout(() => URL.revokeObjectURL(a.href), 100); } function getCellText(cell) { let t = ''; cell.childNodes.forEach(n => { if (n.nodeType === Node.TEXT_NODE) t += n.textContent; else if (n.nodeName === 'BR') t += '\n'; else if (n.nodeType === Node.ELEMENT_NODE) t += getCellText(n); }); return t.replace(/\s+/g,' ').trim(); } function addButtonsToTable(table) { if (!tableButtonsEnabled || table.getAttribute('data-internal-buttons-added') === 'true') return; table.setAttribute('data-internal-buttons-added', 'true'); const bc = document.createElement('div'); bc.className = 'table-internal-buttons'; const pngBtn = document.createElement('button'); pngBtn.className = 'internal-export-btn'; pngBtn.innerHTML = '📸'; pngBtn.setAttribute('data-tooltip', '导出为 PNG'); pngBtn.addEventListener('click', e => { e.stopPropagation(); exportTableAsPNG(table); }); const csvBtn = document.createElement('button'); csvBtn.className = 'internal-export-btn'; csvBtn.innerHTML = '📄'; csvBtn.setAttribute('data-tooltip', '导出为 CSV'); csvBtn.addEventListener('click', e => { e.stopPropagation(); exportTableAsCSV(table); }); bc.appendChild(pngBtn); bc.appendChild(csvBtn); table.appendChild(bc); } function processAllTables() { document.querySelectorAll('.ds-markdown').forEach(container => { container.style.overflowX = 'visible'; container.style.maxWidth = '100%'; container.querySelectorAll('table').forEach(table => { applyTableStyles(table); addButtonsToTable(table); }); }); } function observeTables() { const observer = new MutationObserver(() => processAllTables()); observer.observe(document.body, { childList: true, subtree: true }); window.addEventListener('load', processAllTables); window.addEventListener('resize', () => { clearTimeout(window._resizeFix); window._resizeFix = setTimeout(processAllTables, 100); }); processAllTables(); } // ==================== AI思考区域自动折叠逻辑 ==================== function collapseThinkingSection(container) { if (!autoCollapseThinking || container.hasAttribute('data-thinking-collapsed')) return; if (!simulateClickThinking) return; let clickableArrow = null; const icons = container.querySelectorAll('.ds-icon'); if (icons.length >= 2) clickableArrow = icons[icons.length-1]; else if (icons.length === 1) clickableArrow = icons[0]; if (!clickableArrow) { const svg = container.querySelector('svg'); if (svg && svg.parentElement) clickableArrow = svg.parentElement; } if (clickableArrow && typeof clickableArrow.click === 'function') { container.setAttribute('data-thinking-collapsed', 'true'); setTimeout(() => clickableArrow.click(), 100); } } function processAllThinkingSections() { if (!autoCollapseThinking) return; const spans = document.querySelectorAll('span[class*="5255ff8"], span[class*="4d41763"]'); spans.forEach(span => { if (span.textContent && span.textContent.includes('已思考')) { let container = span.closest('div[class*="_5ab5d64"]') || span.parentElement; if (container) collapseThinkingSection(container); } }); document.querySelectorAll('*').forEach(el => { if (el.childNodes.length === 1 && el.childNodes[0].nodeType === Node.TEXT_NODE && el.textContent.includes('已思考')) { if (!el.hasAttribute('data-thinking-processed')) { let container = el.closest('div[class*="_5ab5d64"]') || el.parentElement; if (container) collapseThinkingSection(container); el.setAttribute('data-thinking-processed', 'true'); } } }); } // ==================== 统一 DOM 监听 ==================== function observeDynamicContent() { const observer = new MutationObserver(mutations => { let needThink = false; for (const m of mutations) { if (m.type === 'childList') { for (const node of m.addedNodes) { if (node.nodeType === Node.ELEMENT_NODE) { if (autoCollapseThinking && (node.textContent && node.textContent.includes('已思考') || (node.querySelector && node.querySelector('span') && node.querySelector('span').textContent?.includes('已思考')))) { needThink = true; } } } } } if (needThink) setTimeout(processAllThinkingSections, 150); }); observer.observe(document.body, { childList: true, subtree: true }); } // ==================== 初始化 ==================== function init() { cleanupLegacyWrappers(); deduplicateButtons(); processAllExistingCodeBlocks(); observeCodeBlocks(); observeTables(); if (autoCollapseThinking) processAllThinkingSections(); observeDynamicContent(); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();