您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
为双拼练习页面添加可设置X分钟计时和正确率统计功能,按钮更明显地放在顶部菜单区域。
// ==UserScript== // @name 双拼练习计时统计 // @namespace http://tampermonkey.net/ // @version 1.1 // @description 为双拼练习页面添加可设置X分钟计时和正确率统计功能,按钮更明显地放在顶部菜单区域。 // @author // @match https://api.ihint.me/shuang* // @grant none // @run-at document-idle // ==/UserScript== (function() { 'use strict'; let attempts = []; let timer = null; let timeLeft = 300; // 默认5分钟 let isTiming = false; let timerDisplay; let startButton; let inputMinutes; // 新增:用户输入分钟数 let waitForShuangInterval = setInterval(() => { if (window.Shuang && window.$) { clearInterval(waitForShuangInterval); initTimerUI(); patchJudgeFunction(); } }, 500); function initTimerUI() { // 尝试在页面顶部插入UI,比如与".header"同级或在header内部 const header = document.querySelector('.header'); if (!header) { console.warn('Header not found, cannot insert timer UI. Will try body.'); } // 创建一个容器,让UI更清晰 const container = document.createElement('div'); container.style.display = 'flex'; container.style.alignItems = 'center'; container.style.margin = '10px 0'; container.style.gap = '10px'; // 创建输入框用于设置分钟数 inputMinutes = document.createElement('input'); inputMinutes.type = 'number'; inputMinutes.min = 1; inputMinutes.value = 5; // 默认5分钟 inputMinutes.style.width = '50px'; inputMinutes.title = '设置练习时长(分钟)'; // 创建"开始计时"按钮 startButton = document.createElement('button'); startButton.innerText = '开始计时练习'; startButton.title = '开始倒计时并统计正确率'; startButton.onclick = startPractice; startButton.style.padding = '5px 10px'; startButton.style.cursor = 'pointer'; startButton.style.background = '#4CAF50'; startButton.style.color = '#fff'; startButton.style.border = 'none'; startButton.style.borderRadius = '4px'; // 创建显示剩余时间的元素 timerDisplay = document.createElement('div'); timerDisplay.style.fontSize = '16px'; timerDisplay.innerText = '剩余时间: 未开始'; timerDisplay.style.marginLeft = '10px'; // 将元素加入container container.appendChild(document.createTextNode('设置时长(分钟):')); container.appendChild(inputMinutes); container.appendChild(startButton); container.appendChild(timerDisplay); // 将container插入header中 if (header) { header.appendChild(container); } else { // 如果header不存在,就插入到body顶部 document.body.insertBefore(container, document.body.firstChild); } } function startPractice() { if (isTiming) return; // 根据用户输入的分钟数设置timeLeft const minutes = parseInt(inputMinutes.value, 10); if (isNaN(minutes) || minutes < 1) { alert('请输入有效的分钟数(>=1)'); return; } timeLeft = minutes * 60; isTiming = true; attempts = []; timerDisplay.innerText = `剩余时间: ${timeLeft}秒`; timer = setInterval(()=>{ timeLeft--; timerDisplay.innerText = '剩余时间: ' + timeLeft + '秒'; if (timeLeft <= 0) { clearInterval(timer); isTiming = false; timerDisplay.innerText = '时间到!'; showStatistics(); } }, 1000); } function showStatistics() { let total = attempts.length; let correctCount = attempts.filter(a=>a.correct).length; let wrongCount = total - correctCount; let accuracy = total > 0 ? ((correctCount/total)*100).toFixed(2) + '%' : 'N/A'; let wrongItems = attempts.filter(a=>!a.correct).map(a=>a.dict); // 创建遮罩层 const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.background = 'rgba(0,0,0,0.5)'; overlay.style.display = 'flex'; overlay.style.alignItems = 'center'; overlay.style.justifyContent = 'center'; overlay.style.zIndex = '9999'; // 创建对话框 const modal = document.createElement('div'); modal.style.background = '#fff'; modal.style.padding = '20px'; modal.style.borderRadius = '8px'; modal.style.maxWidth = '400px'; modal.style.width = '90%'; modal.style.boxShadow = '0 0 10px rgba(0,0,0,0.3)'; modal.style.fontFamily = 'Arial, sans-serif'; modal.style.textAlign = 'center'; // 标题 const title = document.createElement('h2'); title.innerText = '练习结束!'; title.style.marginTop = '0'; // 统计信息内容 const stats = document.createElement('div'); stats.style.textAlign = 'left'; stats.style.margin = '15px 0'; // 使用换行和特殊样式呈现信息 stats.innerHTML = ` <p><strong>总次数:</strong> ${total}</p> <p><strong>正确:</strong> ${correctCount}</p> <p><strong>错误:</strong> ${wrongCount}</p> <p><strong>正确率:</strong> ${accuracy}</p> ${ wrongCount > 0 ? `<p><strong>错误的字有:</strong> ${wrongItems.join('、')}</p>` : `<p>全部正确,棒棒哒!</p>` } `; // 关闭按钮 const closeButton = document.createElement('button'); closeButton.innerText = '关闭'; closeButton.style.padding = '8px 16px'; closeButton.style.marginTop = '10px'; closeButton.style.border = 'none'; closeButton.style.borderRadius = '4px'; closeButton.style.background = '#007BFF'; closeButton.style.color = '#fff'; closeButton.style.cursor = 'pointer'; closeButton.addEventListener('click', () => { document.body.removeChild(overlay); }); modal.appendChild(title); modal.appendChild(stats); modal.appendChild(closeButton); overlay.appendChild(modal); document.body.appendChild(overlay); } function patchJudgeFunction() { if (!Shuang.app || !Shuang.app.action || !Shuang.app.action.judge) { console.warn("Unable to patch judge function, Shuang structure changed?"); return; } const originalJudge = Shuang.app.action.judge; Shuang.app.action.judge = function() { const inputVal = $("#a").value; const correct = Shuang.core.current.judge(inputVal[0], inputVal[1]); if (isTiming && inputVal.length === 2) { attempts.push({ sheng: Shuang.core.current.sheng, yun: Shuang.core.current.yun, dict: Shuang.core.current.dict, correct: correct }); } return originalJudge.call(this); }; } })();