// ==UserScript== // @name 学习通编辑器智能粘贴神器 // @namespace https://mooc1-api.chaoxing.com/ // @match *://*.chaoxing.com/* // @version 12.0 // @description 支持多编辑器识别、选择、批量粘贴 // @icon http://pan-yz.chaoxing.com/favicon.ico // @author User // @match https://mooc1-api.chaoxing.com/mooc-ans/mooc2/work/* // @match https://mooc1.chaoxing.com/mooc-ans/mooc2/work/* // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; console.log('%c[多编辑器神器] 已加载', 'background: #ff00ff; color: white; font-size: 16px; font-weight: bold;'); // ==================== 核心功能:暴力注入 ==================== const pasteToUEditor = (content, targetIndex = null) => { const iframes = getAllEditors(); // 使用智能识别函数 if (iframes.length === 0) { console.error('[暴力粘贴] 未找到任何UEditor编辑器'); alert('未检测到编辑器,请确保已进入答题页面'); return false; } if (targetIndex !== null && iframes[targetIndex]) { return injectToIframe(iframes[targetIndex].iframe, content, targetIndex); } // 批量粘贴 iframes.forEach((info, i) => { injectToIframe(info.iframe, content, i); }); return true; }; const injectToIframe = (iframe, content, index) => { try { const doc = iframe.contentDocument; const body = doc.body; body.onpaste = null; iframe.contentWindow.editorPaste = () => true; const htmlContent = content.replace(/\n/g, '

'); body.innerHTML = `

${htmlContent}

`; if (window.UE && window.UE.instants) { const editorKey = Object.keys(window.UE.instants).find(k => window.UE.instants[k].document === doc ); if (editorKey) { const editor = window.UE.instants[editorKey]; editor.fireEvent('contentchange'); editor.fireEvent('afterpaste'); } } console.log(`✅ [暴力粘贴] 成功注入编辑器${index}`); return true; } catch(e) { console.error(`❌ [暴力粘贴] 编辑器${index}注入失败:`, e.message); return false; } }; // ==================== 智能识别所有编辑器 ==================== const getAllEditors = () => { const iframes = Array.from(document.querySelectorAll('iframe[id^="ueditor_"]')); const editors = []; iframes.forEach((iframe, index) => { try { const doc = iframe.contentDocument; const body = doc.body; const questionText = findQuestionText(iframe, index); // 查找对应题目 editors.push({ index: index, iframe: iframe, body: body, question: questionText, element: iframe, visible: iframe.offsetParent !== null }); } catch(e) { console.warn(`[识别] 编辑器${index}无法访问`); } }); return editors; }; // 查找编辑器对应的题目文本 const findQuestionText = (iframe, index) => { try { // 超星常见结构:iframe前或父元素中有题目 const parent = iframe.parentElement; const prev = iframe.previousElementSibling; // 查找包含"题"字的文本 const questionElement = parent.querySelector('.mark_name, .questionName, .Zy_question') || prev?.querySelector('.mark_name, .questionName, .Zy_question'); if (questionElement) { return questionElement.textContent.trim().substring(0, 20) + '...'; } // 备用:使用索引 return `第${index + 1}题`; } catch(e) { return `第${index + 1}题`; } }; // ==================== 功能:输入框UI(增强版) ==================== let clipboardCache = ''; const addUI = () => { const panel = document.createElement('div'); panel.innerHTML = `

🚀 多编辑器智能粘贴

正在识别编辑器...
0 字符
`; document.body.appendChild(panel); // 获取元素引用 const input = document.getElementById('paste-input'); const count = document.getElementById('char-count'); const status = document.getElementById('status'); const selector = document.getElementById('editor-selector'); const editorList = document.getElementById('editor-list'); // 字符计数 input.addEventListener('input', () => { count.textContent = input.value.length; localStorage.setItem('superPaste_content', input.value); }); // 恢复保存的内容 const saved = localStorage.getItem('superPaste_content'); if (saved) { input.value = saved; count.textContent = saved.length; } // 更新编辑器列表 const updateEditorList = () => { const editors = getAllEditors(); if (editors.length === 0) { editorList.innerHTML = '
未找到编辑器
'; return; } // 清空选择器(保留前两项) while (selector.options.length > 2) { selector.remove(2); } // 填充列表 editorList.innerHTML = editors.map(info => `
编辑器${info.index}: ${info.question} ${info.visible ? '✅' : '⏸️'}
`).join(''); // 添加到选择器 editors.forEach(info => { const option = document.createElement('option'); option.value = info.index; option.textContent = `📝 编辑器${info.index}: ${info.question}`; selector.appendChild(option); }); }; // 初始化 updateEditorList(); // 每5秒自动刷新一次 setInterval(updateEditorList, 5000); // 手动刷新 document.getElementById('refresh-editors').onclick = updateEditorList; // 读取剪贴板 document.getElementById('load-clipboard').onclick = async () => { try { const text = await navigator.clipboard.readText(); if (text) { input.value = text; count.textContent = text.length; clipboardCache = text; status.textContent = '✅ 剪贴板内容已读取'; status.style.color = '#0c0'; localStorage.setItem('superPaste_content', text); } else { status.textContent = '❌ 剪贴板为空'; status.style.color = '#f00'; } } catch(err) { status.textContent = '❌ 无法访问剪贴板'; status.style.color = '#f00'; } setTimeout(() => { status.textContent = ''; status.style.color = '#666'; }, 3000); }; // 清空 document.getElementById('clear-input').onclick = () => { input.value = ''; count.textContent = '0'; localStorage.removeItem('superPaste_content'); status.textContent = '🗑️ 已清空'; status.style.color = '#f90'; setTimeout(() => { status.textContent = ''; status.style.color = '#666'; }, 2000); }; // 执行粘贴 document.getElementById('execute-paste').onclick = async () => { const content = input.value.trim() || clipboardCache; if (!content) { status.textContent = '❌ 请输入内容'; status.style.color = '#f00'; input.focus(); return; } const target = selector.value; let success = false; if (target === 'all') { success = pasteToUEditor(content); status.textContent = success ? '✅ 已粘贴到全部' : '❌ 粘贴失败'; } else if (target === 'current') { // 智能检测当前编辑器 const active = document.activeElement; const editors = getAllEditors(); let currentIndex = null; // 检测方法1:焦点在iframe上 if (active.tagName === 'IFRAME') { const match = editors.find(e => e.iframe === active); if (match) currentIndex = match.index; } // 检测方法2:查找最近点击的编辑器(基于点击事件) if (currentIndex === null && window.lastClickedEditor !== undefined) { currentIndex = window.lastClickedEditor; } // 检测方法3:使用可见的第一个 if (currentIndex === null) { const visible = editors.find(e => e.visible); if (visible) currentIndex = visible.index; } success = pasteToUEditor(content, currentIndex); status.textContent = success ? `✅ 已粘贴到编辑器${currentIndex}` : '❌ 粘贴失败'; } else { // 指定索引 success = pasteToUEditor(content, parseInt(target)); status.textContent = success ? `✅ 已粘贴到编辑器${target}` : '❌ 粘贴失败'; } status.style.color = success ? '#0c0' : '#f00'; setTimeout(() => { status.textContent = ''; status.style.color = '#666'; }, 3000); }; // 记录点击的编辑器 document.addEventListener('click', (e) => { const iframe = e.target.closest('iframe[id^="ueditor_"]'); if (iframe) { const editors = getAllEditors(); const match = editors.find(info => info.iframe === iframe); if (match) { window.lastClickedEditor = match.index; console.log(`[暴力粘贴] 记录点击: 编辑器${match.index}`); } } }, true); }; // 延迟添加UI setTimeout(addUI, 1500); // ==================== 快捷键 ==================== document.addEventListener('keydown', async (e) => { // Ctrl+Shift+V if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'v') { e.preventDefault(); try { const text = await navigator.clipboard.readText(); if (text) { clipboardCache = text; pasteToUEditor(text); showNotification('✅ 内容已粘贴到全部'); } } catch(err) { showNotification('❌ 无法访问剪贴板'); } } // Ctrl+Shift+C 清空 if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'c') { document.getElementById('clear-input')?.click(); } }); // ==================== 通知 ==================== const showNotification = (message) => { const div = document.createElement('div'); div.textContent = message; div.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #00ff00; color: #000; padding: 15px 25px; border-radius: 8px; z-index: 999999; font-size: 16px; font-weight: bold; box-shadow: 0 0 20px rgba(0,255,0,0.5); animation: fadeOut 2s forwards; `; const style = document.createElement('style'); style.textContent = ` @keyframes fadeOut { 0% { opacity: 1; transform: translate(-50%, -50%) scale(1); } 70% { opacity: 1; transform: translate(-50%, -50%) scale(1); } 100% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); pointer-events: none; } } `; if (!document.querySelector('#superPaste_animation')) { style.id = 'superPaste_animation'; document.head.appendChild(style); } document.body.appendChild(div); setTimeout(() => div.remove(), 2000); }; // ==================== API ==================== window.superPaste = { all: (content) => pasteToUEditor(content), to: (content, index) => pasteToUEditor(content, index), count: () => getAllEditors().length, status: () => { const editors = getAllEditors(); console.log(`[暴力粘贴] 找到 ${editors.length} 个编辑器`); editors.forEach(info => { try { console.log(`编辑器${info.index}: ${info.question} ${info.visible ? '✅' : '⏸️'}`); } catch(e) { console.log(`编辑器${info.index}: 无法访问`); } }); }, clearAll: () => { document.querySelectorAll('iframe[id^="ueditor_"]').forEach((iframe, i) => { try { iframe.contentDocument.body.innerHTML = ''; console.log(`编辑器${i}已清空`); } catch(e) {} }); }, // 新增:获取编辑器信息 getEditors: () => getAllEditors() }; })();