支持复制题目到剪贴板(可选是否带提示词),支持设置提示词
// ==UserScript==
// @name 51CTO题目助手
// @namespace http://tampermonkey.net/
// @homepage https://github.com/minivv/tampermonkey
// @version 0.1
// @description 支持复制题目到剪贴板(可选是否带提示词),支持设置提示词
// @author minivv
// @match https://rk.51cto.com/t/n/exam/answer/*
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @icon https://linux.do/uploads/default/optimized/3X/9/d/9dd49731091ce8656e94433a26a3ef36062b3994_2_32x32.png
// @license Apache-2.0
// ==/UserScript==
(function() {
'use strict';
// --- 默认配置 ---
const DEFAULT_PROMPT = "请作为一名资深的IT技术专家和讲师,详细分析以下选择题。请按以下结构进行解答:\n1. 题目分析:解释题目考查的核心知识点。\n2. 正确选项解析:详细说明正确选项为什么正确,并提供相关的背景知识和例子。\n3. 错误选项分析:逐个分析其他选项为什么错误。\n4. 知识点总结:总结与该题目相关的关键概念和学习要点。\n5. 扩展思考:如果适用,可以提出一些相关的扩展问题或实际应用场景。\n请确保解释清晰、准确、易于理解。题目内容如下:";
const DEFAULT_COPY_WITH_PROMPT = true;
// --- 全局变量 ---
let userPrompt = '';
let copyWithPrompt = DEFAULT_COPY_WITH_PROMPT;
// --- 加载设置 ---
function loadSettings() {
userPrompt = GM_getValue('userPrompt', DEFAULT_PROMPT);
copyWithPrompt = GM_getValue('copyWithPrompt', DEFAULT_COPY_WITH_PROMPT);
}
// --- 保存设置 ---
function saveSettings(newPrompt, newCopyWithPrompt) {
userPrompt = newPrompt;
copyWithPrompt = newCopyWithPrompt;
GM_setValue('userPrompt', userPrompt);
GM_setValue('copyWithPrompt', copyWithPrompt);
}
// --- 弹窗编辑提示词和开关 ---
function showPromptDialog() {
const dialog = document.createElement('div');
dialog.style.position = 'fixed';
dialog.style.left = '50%';
dialog.style.top = '50%';
dialog.style.transform = 'translate(-50%, -50%)';
dialog.style.background = '#fff';
dialog.style.border = '1px solid #ccc';
dialog.style.borderRadius = '8px';
dialog.style.zIndex = 99999;
dialog.style.padding = '24px 20px 16px 20px';
dialog.style.boxShadow = '0 4px 24px rgba(0,0,0,0.15)';
dialog.style.minWidth = '600px';
dialog.innerHTML = `
<div style="font-weight:bold;font-size:16px;margin-bottom:10px;">设置</div>
<label style="display:block;margin-bottom:5px;">提示词:</label>
<textarea id="tmk-prompt" style="width:100%;height:150px;border:1px solid #ccc;">${userPrompt}</textarea>
<label style="display:block;margin:10px 0 4px 0;">
<input type="checkbox" id="tmk-copywithprompt" ${copyWithPrompt ? 'checked' : ''}> 复制时自动带提示词
</label>
<div style="text-align:right;margin-top:10px;">
<button id="tmk-save" style="margin-right:10px;">保存</button>
<button id="tmk-cancel">取消</button>
</div>
`;
document.body.appendChild(dialog);
document.getElementById('tmk-save').onclick = function() {
const newPrompt = document.getElementById('tmk-prompt').value;
const newCopyWithPrompt = document.getElementById('tmk-copywithprompt').checked;
saveSettings(newPrompt, newCopyWithPrompt);
document.body.removeChild(dialog);
showTip('设置已保存!');
};
document.getElementById('tmk-cancel').onclick = function() {
document.body.removeChild(dialog);
};
}
// --- 获取当前题目文本 ---
function getCurrentQuestionText(card) {
let questionText = "";
const titleElement = card.querySelector('.exam-item-title p');
if (titleElement) {
questionText += titleElement.innerText.trim() + "\n";
}
const options = card.querySelectorAll('.exam-item-content .el-radio-group .el-radio');
if (options.length > 0) {
options.forEach(option => {
const label = option.querySelector('.el-radio__label');
if (label) questionText += label.innerText.trim() + "\n";
});
}
return questionText.trim();
}
// --- 复制题目到剪贴板 ---
function copyQuestion(card) {
const question = getCurrentQuestionText(card);
let text = question;
if (copyWithPrompt) {
text = userPrompt + "\n\n" + question;
}
navigator.clipboard.writeText(text).then(() => {
showTip('题目已复制到剪贴板!');
}).catch(err => {
showTip('复制失败: ' + err, true);
});
}
// --- 显示临时提示 ---
function showTip(msg, isErr) {
let tip = document.createElement('div');
tip.textContent = msg;
tip.style.position = 'fixed';
tip.style.left = '50%';
tip.style.top = '20%';
tip.style.transform = 'translateX(-50%)';
tip.style.background = isErr ? '#d93025' : '#28a745';
tip.style.color = '#fff';
tip.style.padding = '10px 24px';
tip.style.borderRadius = '6px';
tip.style.fontSize = '16px';
tip.style.zIndex = 99999;
document.body.appendChild(tip);
setTimeout(() => { tip.remove(); }, 1800);
}
// --- 插入按钮到每道题 ---
function insertButtons() {
// 查找每道题的操作按钮组
document.querySelectorAll('.exam-item-card-inner').forEach(card => {
const opBar = card.querySelector('.card-header-operation.flex');
if (!opBar || opBar.querySelector('.tmk-copy-btn')) return; // 已插入则跳过
// 复制题目按钮
const copyBtn = document.createElement('div');
copyBtn.className = 'card-operation-item tmk-copy-btn';
copyBtn.innerHTML = `<button type="button" class="el-button is-link"><span><img src="https://cdn-icons-png.flaticon.com/128/11238/11238246.png" style="width:16px;vertical-align:middle;">复制题目</span></button>`;
copyBtn.onclick = function(e) {
e.stopPropagation();
copyQuestion(card);
};
// 编辑提示词按钮
const promptBtn = document.createElement('div');
promptBtn.className = 'card-operation-item tmk-prompt-btn';
promptBtn.innerHTML = `<button type="button" class="el-button is-link"><span><img src="https://cdn-icons-png.flaticon.com/128/2040/2040510.png" style="width:16px;vertical-align:middle;">编辑提示词</span></button>`;
promptBtn.onclick = function(e) {
e.stopPropagation();
showPromptDialog();
};
// 插入到操作栏
opBar.appendChild(copyBtn);
opBar.appendChild(promptBtn);
});
}
// --- 添加样式使按钮一致 ---
GM_addStyle(`
.tmk-copy-btn, .tmk-prompt-btn { display:inline-block; }
.tmk-copy-btn .el-button, .tmk-prompt-btn .el-button { padding: 4px 0px; font-size: 14px; }
.tmk-copy-btn .el-button img, .tmk-prompt-btn .el-button img { margin-right: 2px; }
`);
// --- 初始化 ---
function init() {
loadSettings();
insertButtons();
// 监听动态加载(如切换题目时)
const observer = new MutationObserver(() => insertButtons());
observer.observe(document.body, { childList: true, subtree: true });
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();