// ==UserScript== // @name 超星多编辑器智能粘贴神器 // @namespace https://mooc1-api.chaoxing.com/ // @match *://*.chaoxing.com/* // @version 1.0.1 // @description 支持多编辑器识别、选择、批量粘贴(修复重复加载,带拖拽功能) // @icon http://pan-yz.chaoxing.com/favicon.ico // @author User // @author Muyue -imuyue.com // @connect mooc1-1.chaoxing.com // @connect mooc1-1.neauce.com // @connect mooc1.chaoxing.com // @connect mooc1.neauce.com // @connect mooc1-2.chaoxing.com // @connect mooc1-2.neauce.com // @connect mooc1-api.chaoxing.com // @connect mooc2-ans.chaoxing.com // @connect passport2-api.chaoxing.com // @connect sso.chaoxing.com // @grant none // @tag 学习通 // ==/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(function(k) { return 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(function(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 { const parent = iframe.parentElement; const prev = iframe.previousElementSibling; const questionElement = parent.querySelector('.mark_name, .questionName, .Zy_question') || (prev ? prev.querySelector('.mark_name, .questionName, .Zy_question') : null); if (questionElement) { return questionElement.textContent.trim().substring(0, 20) + '...'; } return '第' + (index + 1) + '题'; } catch(e) { return '第' + (index + 1) + '题'; } }; // ==================== 拖拽功能核心(独立函数) ==================== function initDragFunction(dragPanel) { if (!dragPanel) { console.warn('拖拽面板元素未找到'); return; } const dragHandle = dragPanel.querySelector('#drag-handle'); if (!dragHandle) return; var isDragging = false; var startX = 0; var startY = 0; var panelLeft = 0; var panelTop = 0; dragHandle.addEventListener('mousedown', function(e) { e.preventDefault(); e.stopPropagation(); isDragging = true; startX = e.clientX; startY = e.clientY; panelLeft = parseInt(window.getComputedStyle(dragPanel).left, 10) || 0; panelTop = parseInt(window.getComputedStyle(dragPanel).top, 10) || 0; dragHandle.style.background = 'rgba(255, 0, 255, 0.1)'; dragPanel.style.userSelect = 'none'; }); document.addEventListener('mousemove', function(e) { if (!isDragging) return; var dx = e.clientX - startX; var dy = e.clientY - startY; var maxLeft = window.innerWidth - dragPanel.offsetWidth - 20; var maxTop = window.innerHeight - dragPanel.offsetHeight - 20; var newLeft = Math.max(0, Math.min(panelLeft + dx, maxLeft)); var newTop = Math.max(0, Math.min(panelTop + dy, maxTop)); dragPanel.style.left = newLeft + 'px'; dragPanel.style.top = newTop + 'px'; dragPanel.style.right = 'auto'; }); function endDrag() { if (!isDragging) return; isDragging = false; dragHandle.style.background = ''; dragPanel.style.userSelect = ''; } document.addEventListener('mouseup', endDrag); document.addEventListener('mouseleave', endDrag); } // ==================== 功能:输入框UI(增强版) ==================== let clipboardCache = ''; const addUI = () => { const panel = document.createElement('div'); panel.innerHTML = `

🚀 多编辑器智能粘贴

正在识别编辑器...
0 字符
`; document.body.appendChild(panel); const dragPanel = document.getElementById('draggable-paste-panel'); initDragFunction(dragPanel); 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', function() { count.textContent = this.value.length; localStorage.setItem('superPaste_content', this.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); } var listHtml = ''; editors.forEach(function(info) { var opacityStyle = info.visible ? '' : 'opacity: 0.6;'; listHtml += '
' + '编辑器' + info.index + ': ' + info.question + (info.visible ? '✅' : '⏸️') + '
'; }); editorList.innerHTML = listHtml; editors.forEach(function(info) { const option = document.createElement('option'); option.value = info.index; option.textContent = '📝 编辑器' + info.index + ': ' + info.question; selector.appendChild(option); }); }; updateEditorList(); setInterval(updateEditorList, 5000); document.getElementById('refresh-editors').onclick = updateEditorList; document.getElementById('load-clipboard').onclick = async function() { 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(function() { status.textContent = ''; status.style.color = '#666'; }, 3000); }; document.getElementById('clear-input').onclick = function() { input.value = ''; count.textContent = '0'; localStorage.removeItem('superPaste_content'); status.textContent = '🗑️ 已清空'; status.style.color = '#f90'; setTimeout(function() { status.textContent = ''; status.style.color = '#666'; }, 2000); }; document.getElementById('execute-paste').onclick = async function() { 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; if (active.tagName === 'IFRAME') { var match = null; for (var i = 0; i < editors.length; i++) { if (editors[i].iframe === active) { match = editors[i]; break; } } if (match) currentIndex = match.index; } if (currentIndex === null && window.lastClickedEditor !== undefined) { currentIndex = window.lastClickedEditor; } if (currentIndex === null) { var visible = null; for (var j = 0; j < editors.length; j++) { if (editors[j].visible) { visible = editors[j]; break; } } 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(function() { status.textContent = ''; status.style.color = '#666'; }, 3000); }; document.addEventListener('click', function(e) { const iframe = e.target.closest('iframe[id^="ueditor_"]'); if (iframe) { const editors = getAllEditors(); var match = null; for (var k = 0; k < editors.length; k++) { if (editors[k].iframe === iframe) { match = editors[k]; break; } } if (match) { window.lastClickedEditor = match.index; console.log('[暴力粘贴] 记录点击: 编辑器' + match.index); } } }, true); }; // 延迟添加UI,先检查是否已存在面板(防重复加载) setTimeout(() => { if (document.getElementById('draggable-paste-panel')) { console.warn('[多编辑器神器] 检测到重复加载,已跳过'); return; } addUI(); }, 1500); // ==================== 快捷键 ==================== document.addEventListener('keydown', async function(e) { 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('❌ 无法访问剪贴板'); } } if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'c') { var clearBtn = document.getElementById('clear-input'); if (clearBtn) clearBtn.click(); } }); // ==================== 通知 ==================== const showNotification = function(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(function() { div.remove(); }, 2000); }; // ==================== API ==================== window.superPaste = { all: function(content) { return pasteToUEditor(content); }, to: function(content, index) { return pasteToUEditor(content, index); }, count: function() { return getAllEditors().length; }, status: function() { const editors = getAllEditors(); console.log('[暴力粘贴] 找到 ' + editors.length + ' 个编辑器'); editors.forEach(function(info) { try { console.log('编辑器' + info.index + ': ' + info.question + ' ' + (info.visible ? '✅' : '⏸️')); } catch(e) { console.log('编辑器' + info.index + ': 无法访问'); } }); }, clearAll: function() { var iframes = document.querySelectorAll('iframe[id^="ueditor_"]'); iframes.forEach(function(iframe, i) { try { iframe.contentDocument.body.innerHTML = ''; console.log('编辑器' + i + '已清空'); } catch(e) {} }); }, getEditors: function() { return getAllEditors(); } }; })();