feat: 打字练习支持自动朗读与选区朗读

This commit is contained in:
guoqingshan
2026-08-02 22:37:29 +08:00
parent 2ee9e9c564
commit 40782435fe
3 changed files with 48 additions and 0 deletions
+41
View File
@@ -6,6 +6,7 @@ var typed = '';
var typingStartedAt = 0;
var typingFinished = false;
var typingSession = { mode: '', categoryId: '', categoryName: '', itemCount: 0 };
var typingSelectionTimer = null;
var KEY_ROWS = [
[
@@ -195,6 +196,7 @@ function renderPractice() {
}
var item = typingItems[typingIndex];
var target = item.es;
speakText(item.es, 'es');
var targetHtml = '';
for (var i = 0; i < target.length; i++) {
var ch = escTyping(target[i]);
@@ -312,6 +314,35 @@ function showSetupView() {
loadTypingLogs();
}
function readCurrentTarget() {
var item = typingItems[typingIndex];
if (item && item.es) speakText(item.es, 'es');
}
function getTypingSelectedSpanish() {
var input = document.getElementById('typing-input');
if (document.activeElement === input && input.selectionStart !== input.selectionEnd) {
return input.value.substring(input.selectionStart, input.selectionEnd).trim();
}
var selection = window.getSelection();
if (!selection || selection.isCollapsed || !selection.toString().trim()) return '';
var node = selection.anchorNode;
var container = node && node.nodeType === 3 ? node.parentNode : node;
var target = document.getElementById('target-text');
return container && target && target.contains(container)
? selection.toString().trim()
: '';
}
function handleTypingSelection() {
var text = getTypingSelectedSpanish();
if (!text || !typingItems[typingIndex]) return;
if (typingSelectionTimer) clearTimeout(typingSelectionTimer);
typingSelectionTimer = setTimeout(function() {
speakText(text, 'es');
}, 150);
}
function renderKeyboard(target) {
var next = target[typed.length] || '';
var press = keyPressForChar(next);
@@ -422,7 +453,17 @@ document.getElementById('btn-start').addEventListener('click', startTyping);
document.getElementById('btn-restart').addEventListener('click', startTyping);
document.getElementById('btn-choose').addEventListener('click', showSetupView);
document.getElementById('btn-refresh-records').addEventListener('click', loadTypingLogs);
document.getElementById('btn-typing-speak').addEventListener('click', readCurrentTarget);
document.getElementById('typing-input').addEventListener('input', handleTypingInput);
document.getElementById('typing-input').addEventListener('mouseup', handleTypingSelection);
document.getElementById('typing-input').addEventListener('keyup', handleTypingSelection);
document.addEventListener('selectionchange', handleTypingSelection);
document.addEventListener('keydown', function(e) {
if (e.key === 'F6') {
e.preventDefault();
readCurrentTarget();
}
});
renderCategories();
loadTypingLogs();