// ==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()
};
})();