add some very nb stuff and some massive bugs
This commit is contained in:
BIN
WordDictationStudentApp/.DS_Store
vendored
BIN
WordDictationStudentApp/.DS_Store
vendored
Binary file not shown.
BIN
WordDictationStudentApp/dist/.DS_Store
vendored
BIN
WordDictationStudentApp/dist/.DS_Store
vendored
Binary file not shown.
@@ -1,92 +1,94 @@
|
||||
// main.js
|
||||
const { app, BrowserWindow, dialog, ipcMain } = require('electron'); // 1. 导入 ipcMain
|
||||
const { app, BrowserWindow, globalShortcut, screen, ipcMain } = require('electron'); // 添加 ipcMain
|
||||
const path = require('path');
|
||||
// const cv = require('opencv4nodejs'); // 已移除视觉作弊相关
|
||||
|
||||
let mainWindow;
|
||||
let switchCount = 0; // 在主进程中也维护一个计数器
|
||||
const switchLimit = 3;
|
||||
const warningLimit = 2;
|
||||
|
||||
// --- 已移除视觉作弊相关变量 ---
|
||||
|
||||
function createWindow () {
|
||||
// 获取主显示器尺寸
|
||||
const primaryDisplay = screen.getPrimaryDisplay();
|
||||
const { width, height } = primaryDisplay.size;
|
||||
|
||||
mainWindow = new BrowserWindow({
|
||||
// --- 关键修改:设置为全屏无框 ---
|
||||
width: width,
|
||||
height: height,
|
||||
fullscreen: true,
|
||||
frame: false,
|
||||
kiosk: true, // 关键:kiosk 模式,隐藏菜单栏、Dock
|
||||
alwaysOnTop: true,
|
||||
resizable: false,
|
||||
movable: false,
|
||||
fullscreenable: false,
|
||||
titleBarStyle: 'hidden',
|
||||
webPreferences: {
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true, // 2. 必须开启
|
||||
contextIsolation: true,
|
||||
enableRemoteModule: false,
|
||||
preload: path.join(__dirname, 'preload.js') // 3. 关键:加载 preload 脚本
|
||||
},
|
||||
// --- 可选:设置图标 ---
|
||||
// icon: path.join(__dirname, 'icon.png')
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
});
|
||||
|
||||
mainWindow.loadFile('student_app_fullscreen.html');
|
||||
|
||||
// --- 关键修改:监听窗口失去焦点事件 ---
|
||||
mainWindow.on('blur', () => {
|
||||
switchCount++;
|
||||
console.log(`窗口失去焦点,切屏次数: ${switchCount}`); // 控制台输出日志
|
||||
|
||||
if (switchCount <= warningLimit - 1 ) {
|
||||
// 显示警告对话框
|
||||
dialog.showMessageBox(mainWindow, {
|
||||
type: 'warning',
|
||||
title: '切屏警告',
|
||||
message: `您进行了切屏操作,此行为已被记录,如您再次进行两次切屏,则会重置考试`,
|
||||
buttons: ['确定']
|
||||
}).then(() => {
|
||||
// 警告后,将焦点重新移回主窗口
|
||||
mainWindow.focus();
|
||||
});
|
||||
} else if (switchCount < switchLimit) {
|
||||
// 第三次切屏,重置警告
|
||||
dialog.showMessageBox(mainWindow, {
|
||||
type: 'warning',
|
||||
title: '切屏警告',
|
||||
message: `您再次进行了切屏操作,此行为已被记录,如您再次进行一次切屏,则会重置考试`,
|
||||
buttons: ['确定']
|
||||
}).then(() => {
|
||||
mainWindow.focus();
|
||||
});
|
||||
} else {
|
||||
// 超过限制次数
|
||||
dialog.showMessageBox(mainWindow, {
|
||||
type: 'error',
|
||||
title: '切屏过多',
|
||||
message: `您因切屏超过误触缓冲次数,重置考试`,
|
||||
buttons: ['确定']
|
||||
}).then(() => {
|
||||
// 重置考试:重新加载页面,重置计数器
|
||||
switchCount = 0;
|
||||
mainWindow.reload();
|
||||
});
|
||||
}
|
||||
// --- 移除窗口关闭拦截,允许通过按钮退出 ---
|
||||
|
||||
// 启动时就注册全局快捷键拦截
|
||||
registerGlobalShortcuts();
|
||||
|
||||
// 添加退出应用的IPC处理程序
|
||||
ipcMain.handle('exit-app', async () => {
|
||||
app.quit();
|
||||
});
|
||||
// --- 结束监听 ---
|
||||
|
||||
// 监听窗口关闭事件
|
||||
mainWindow.on('closed', () => {
|
||||
mainWindow = null;
|
||||
});
|
||||
|
||||
// --- 已移除视觉作弊检测启动 ---
|
||||
}
|
||||
|
||||
// --- 已移除视觉作弊检测相关函数 ---
|
||||
// 注册全局快捷键拦截
|
||||
function registerGlobalShortcuts() {
|
||||
// 移除 Esc 退出功能
|
||||
|
||||
// 尝试注册其他快捷键(在无辅助功能权限时可能无效,但无害)
|
||||
const shortcuts = [
|
||||
'CommandOrControl+Tab',
|
||||
'CommandOrControl+Shift+Tab',
|
||||
'Command+Q',
|
||||
'Command+W',
|
||||
'Command+R',
|
||||
'F5',
|
||||
'F11',
|
||||
'F12',
|
||||
'Alt+Tab',
|
||||
'Alt+F4',
|
||||
'Control+Escape',
|
||||
'CommandOrControl+W',
|
||||
'CommandOrControl+R',
|
||||
'Control+R',
|
||||
'Alt+Space', // Windows打开菜单
|
||||
'Command+Space', // Mac打开Spotlight
|
||||
'Command+M', // Mac最小化
|
||||
'Command+H', // Mac隐藏
|
||||
'Command+Option+H', // Mac隐藏其他
|
||||
'Command+Option+M', // Mac最小化所有
|
||||
'Command+Option+Escape', // Mac强制退出
|
||||
'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12', // 功能键
|
||||
'F13', 'F14', 'F15', 'F16', 'F17', 'F18', 'F19', 'F20', 'F21', 'F22', 'F23', 'F24',
|
||||
'Fn' // 禁用 Fn 键
|
||||
];
|
||||
|
||||
// --- IPC 处理程序 ---
|
||||
// 处理来自渲染进程的获取切屏次数请求
|
||||
ipcMain.handle('get-switch-count', async () => {
|
||||
return switchCount; // 返回当前计数
|
||||
});
|
||||
shortcuts.forEach(key => {
|
||||
try {
|
||||
globalShortcut.register(key, () => {
|
||||
// 吃掉事件,什么都不做
|
||||
console.log(`⚠️ 阻止了快捷键:`, key);
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('Failed to register:', key);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// --- 已移除未认真答题次数相关 IPC ---
|
||||
// 注销全局快捷键拦截
|
||||
function unregisterGlobalShortcuts() {
|
||||
globalShortcut.unregisterAll();
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
@@ -97,16 +99,7 @@ app.whenReady().then(() => {
|
||||
});
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
// --- 已移除应用退出时停止色码检测 ---
|
||||
// 注销所有快捷键
|
||||
unregisterGlobalShortcuts();
|
||||
if (process.platform !== 'darwin') app.quit();
|
||||
});
|
||||
|
||||
// --- 注释掉或移除旧的 IPC 代码 ---
|
||||
// const { ipcMain } = require('electron');
|
||||
// ipcMain.on('get-switch-count', (event) => {
|
||||
// event.reply('switch-count-reply', switchCount);
|
||||
// });
|
||||
// ipcMain.on('reset-switch-count', () => {
|
||||
// switchCount = 0;
|
||||
// });
|
||||
// --- 结束注释 ---
|
||||
});
|
||||
@@ -1,12 +1,8 @@
|
||||
// preload.js
|
||||
const { contextBridge, ipcRenderer } = require('electron');
|
||||
|
||||
// 安全地暴露 API 到渲染进程
|
||||
// 安全地暴露退出应用的 API 到渲染进程
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
// 向主进程请求获取切屏次数
|
||||
getSwitchCount: () => ipcRenderer.invoke('get-switch-count'),
|
||||
// 已移除未认真答题次数相关 API
|
||||
// 如果需要,也可以暴露重置计数的 API
|
||||
// resetSwitchCount: () => ipcRenderer.invoke('reset-switch-count'),
|
||||
// resetOffTaskCount: () => ipcRenderer.invoke('reset-off-task-count'),
|
||||
// 退出应用
|
||||
exitApp: () => ipcRenderer.invoke('exit-app')
|
||||
});
|
||||
@@ -965,9 +965,40 @@
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 添加全局退出按钮样式 */
|
||||
#exitButton {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 10000;
|
||||
background: linear-gradient(45deg, #FF3B30, #ff6b6b);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
#exitButton:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- 全局退出按钮 -->
|
||||
<button id="exitButton" title="退出程序">
|
||||
<i class="fas fa-power-off"></i>
|
||||
</button>
|
||||
|
||||
<!-- 鼠标跟随小圈 -->
|
||||
<div class="cursor-follower"></div>
|
||||
<!-- 背景粒子 -->
|
||||
@@ -1155,17 +1186,6 @@
|
||||
<div class="result-stat-number" id="totalCount">0</div>
|
||||
<div class="result-stat-label">总计</div>
|
||||
</div>
|
||||
<!-- --- 添加切屏次数统计 --- -->
|
||||
<div class="result-stat-card">
|
||||
<div class="result-stat-number" id="switchCountFinal">0</div>
|
||||
<div class="result-stat-label">切屏次数</div>
|
||||
</div>
|
||||
<!-- --- 添加未认真答题次数统计 --- -->
|
||||
<div class="result-stat-card">
|
||||
<div class="result-stat-number" id="offTaskCountFinal">0</div>
|
||||
<div class="result-stat-label">未认真答题次数</div>
|
||||
</div>
|
||||
<!-- --- 结束添加 --- -->
|
||||
</div>
|
||||
<div id="errorDetails" class="error-details">
|
||||
<h3><i class="fas fa-times-circle"></i> 错误详情</h3>
|
||||
@@ -1181,50 +1201,17 @@
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// 内置词典 - 与教师端保持一致
|
||||
let toeflWords = [
|
||||
{ "word": "instrument", "translation": "n. 工具、手段" },
|
||||
{ "word": "therefore", "translation": "adv. 因此" },
|
||||
{ "word": "tradition", "translation": "n. 传统" },
|
||||
{ "word": "represent", "translation": "v. 代表、描绘" },
|
||||
{ "word": "iceberg", "translation": "n. 冰山" },
|
||||
{ "word": "store", "translation": "v. 储存" },
|
||||
{ "word": "depend", "translation": "v. 依赖" },
|
||||
{ "word": "general", "translation": "adj. 整体的、普遍的、大体的" },
|
||||
{ "word": "contrast", "translation": "n. 对比、差别" },
|
||||
{ "word": "predator", "translation": "n. 捕食者" },
|
||||
{ "word": "against", "translation": "prep. 与……相反、违背、对比、以…为背景" },
|
||||
{ "word": "survive", "translation": "v. 存活、挺过、比……活的长" },
|
||||
{ "word": "nature", "translation": "n. 自然、本质" },
|
||||
{ "word": "solar", "translation": "adj. 太阳的" },
|
||||
{ "word": "architecture", "translation": "n. 建筑" },
|
||||
{ "word": "primarily", "translation": "adv. 主要地" },
|
||||
{ "word": "observe", "translation": "v. 观察(到)、遵从(法律等)" },
|
||||
{ "word": "canal", "translation": "n. 运河" },
|
||||
{ "word": "craft", "translation": "n. 手艺" },
|
||||
{ "word": "reflect", "translation": "v. 反映、反射、反思" },
|
||||
{ "word": "argue", "translation": "v. 论证" },
|
||||
{ "word": "draw", "translation": "v. 画、得出、提取、轻拉" },
|
||||
{ "word": "theater", "translation": "n. 剧院、戏剧表演" },
|
||||
{ "word": "especially", "translation": "adv. 特别是、尤其" },
|
||||
{ "word": "aggressive", "translation": "adj. 攻击性的" },
|
||||
{ "word": "extreme", "translation": "adj.&n. 极度、极端、极大(的)" },
|
||||
{ "word": "sense", "translation": "n. 意识" },
|
||||
{ "word": "single", "translation": "adj. 单一的、单身的 v. 选中" },
|
||||
{ "word": "previous", "translation": "adj. 先前的" },
|
||||
{ "word": "obtain", "translation": "v. 获得" }
|
||||
];
|
||||
// 移除内置词库,因为我们现在只使用导入的配置
|
||||
// let toeflWords = []; // 不再需要内置词库
|
||||
|
||||
// 全局变量
|
||||
let selectedWords = []; // 存储选中的单词对象 { word, translation }
|
||||
let importedWords = []; // 存储从配置文件导入的单词对象 { word, translation }
|
||||
let currentWordIndex = 0;
|
||||
let dictationStarted = false;
|
||||
let userAnswers = []; // 存储用户答案 (字符串)
|
||||
let correctAnswers = []; // 存储正确答案 (字符串) - 修复:存储英文单词字符串
|
||||
let correctAnswers = []; // 存储正确答案 (字符串)
|
||||
// --- 新增:用于存储用户输入的当前单词 ---
|
||||
let currentInput = '';
|
||||
// --- 新增:用于存储切屏次数 (仅用于重置) ---
|
||||
let switchCountLocal = 0; // 仅用于本地重置,主进程中的计数由 Electron IPC 获取
|
||||
// --- 结束新增 ---
|
||||
|
||||
// --- 新增:用于提取 .js 文件中的 Base64 字符串 ---
|
||||
@@ -1244,8 +1231,6 @@
|
||||
|
||||
// 页面加载时初始化
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// renderWordGrid(); // 移除教师端初始化
|
||||
// updateStats(); // 移除教师端初始化
|
||||
createParticles();
|
||||
initCursorFollower();
|
||||
// 直接显示学生端界面
|
||||
@@ -1262,15 +1247,32 @@
|
||||
}
|
||||
// --- 新增:设置按键监听器 ---
|
||||
document.addEventListener('keydown', handleKeyDown);
|
||||
// --- 添加更严格的键盘事件拦截 ---
|
||||
// 阻止右键菜单
|
||||
document.addEventListener('contextmenu', (e) => e.preventDefault());
|
||||
// 阻止拖拽
|
||||
document.addEventListener('dragstart', (e) => e.preventDefault());
|
||||
// 阻止文本选择
|
||||
document.addEventListener('selectstart', (e) => e.preventDefault());
|
||||
// --- 结束新增 ---
|
||||
|
||||
// 添加全局退出按钮事件监听器
|
||||
document.getElementById('exitButton').addEventListener('click', function() {
|
||||
// 直接退出应用
|
||||
if (window.electronAPI && typeof window.electronAPI.exitApp === 'function') {
|
||||
window.electronAPI.exitApp();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// --- 新增:处理按键输入 ---
|
||||
function handleKeyDown(event) {
|
||||
// 只在默写进行时处理
|
||||
if (!dictationStarted) return;
|
||||
|
||||
// 防止默认行为(如 F5 刷新、Ctrl+R 等)
|
||||
// 阻止所有默认行为,包括 Esc 键
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
// 如果没有开始默写,不处理其他按键
|
||||
if (!dictationStarted) return;
|
||||
|
||||
const key = event.key.toLowerCase();
|
||||
|
||||
@@ -1292,10 +1294,7 @@
|
||||
else if (key === ' ') {
|
||||
// 忽略空格
|
||||
}
|
||||
// 处理其他键(如方向键、功能键等,可以忽略或记录)
|
||||
else {
|
||||
// console.log('未处理的按键:', key); // 调试用
|
||||
}
|
||||
// 忽略所有其他键,包括 Esc 键
|
||||
}
|
||||
|
||||
function updateInputDisplay() {
|
||||
@@ -1406,153 +1405,54 @@
|
||||
}
|
||||
}
|
||||
// 渲染单词网格 - 移除
|
||||
function renderWordGrid(filteredWords = toeflWords) {
|
||||
function renderWordGrid(filteredWords = []) {
|
||||
const wordGrid = document.getElementById('wordGrid');
|
||||
wordGrid.innerHTML = '';
|
||||
filteredWords.forEach(wordObj => {
|
||||
const wordItem = document.createElement('div');
|
||||
wordItem.className = `word-item ${selectedWords.some(w => w.word === wordObj.word) ? 'selected' : ''}`;
|
||||
wordItem.className = `word-item`;
|
||||
// 修改:显示单词和翻译
|
||||
wordItem.innerHTML = `
|
||||
<div class="word-text">${wordObj.word}</div>
|
||||
<div class="word-translation">${wordObj.translation}</div>
|
||||
`;
|
||||
wordItem.onclick = () => toggleWordSelection(wordObj); // 传递整个对象
|
||||
wordGrid.appendChild(wordItem);
|
||||
});
|
||||
}
|
||||
// 切换单词选择状态 - 移除
|
||||
function toggleWordSelection(wordObj) {
|
||||
const index = selectedWords.findIndex(w => w.word === wordObj.word);
|
||||
if (index > -1) {
|
||||
selectedWords.splice(index, 1);
|
||||
} else {
|
||||
selectedWords.push(wordObj);
|
||||
}
|
||||
renderWordGrid();
|
||||
updateStats();
|
||||
}
|
||||
// 更新统计信息 - 移除
|
||||
function updateStats() {
|
||||
const total = toeflWords.length;
|
||||
const selected = selectedWords.length;
|
||||
const percentage = total > 0 ? Math.round((selected / total) * 100) : 0;
|
||||
document.getElementById('selectedCount').textContent = selected;
|
||||
document.getElementById('totalWords').textContent = total;
|
||||
document.getElementById('percentage').textContent = percentage + '%';
|
||||
}
|
||||
// 全选单词 - 移除
|
||||
function selectAllWords() {
|
||||
// 确保 selectedWords 包含 toeflWords 中的所有单词对象
|
||||
selectedWords = [...toeflWords];
|
||||
renderWordGrid(); // 重新渲染网格以反映选择状态
|
||||
updateStats(); // 更新统计信息
|
||||
// 不再需要这个功能
|
||||
alert('此功能已禁用');
|
||||
}
|
||||
// 取消全选 - 移除
|
||||
function deselectAllWords() {
|
||||
selectedWords = []; // 清空已选单词数组
|
||||
renderWordGrid(); // 重新渲染网格
|
||||
updateStats(); // 更新统计信息
|
||||
// 不再需要这个功能
|
||||
alert('此功能已禁用');
|
||||
}
|
||||
// 随机选择60个单词 - 移除
|
||||
function randomSelectWords() {
|
||||
selectedWords = [];
|
||||
// 创建一个 toeflWords 的副本并随机打乱
|
||||
const shuffled = [...toeflWords].sort(() => 0.5 - Math.random());
|
||||
// 选取前60个(或如果总数不足60个,则全部选取)
|
||||
selectedWords = shuffled.slice(0, Math.min(60, shuffled.length));
|
||||
renderWordGrid(); // 重新渲染网格
|
||||
updateStats(); // 更新统计信息
|
||||
// 不再需要这个功能
|
||||
alert('此功能已禁用');
|
||||
}
|
||||
// 搜索单词 - 移除
|
||||
function filterWords() {
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
||||
if (searchTerm === '') {
|
||||
renderWordGrid();
|
||||
document.getElementById('addWordSuggestion').style.display = 'none';
|
||||
} else {
|
||||
// 修改:在单词和翻译中搜索
|
||||
const filtered = toeflWords.filter(wordObj =>
|
||||
wordObj.word.toLowerCase().includes(searchTerm) ||
|
||||
wordObj.translation.toLowerCase().includes(searchTerm)
|
||||
);
|
||||
renderWordGrid(filtered);
|
||||
// 如果没有找到匹配的单词,显示添加单词提示
|
||||
if (filtered.length === 0) {
|
||||
document.getElementById('addWordSuggestion').style.display = 'block';
|
||||
// 不再直接设置 newWordText,而是预填充输入框
|
||||
document.getElementById('newWordInput').value = searchTerm;
|
||||
document.getElementById('newTranslationInput').value = '';
|
||||
} else {
|
||||
document.getElementById('addWordSuggestion').style.display = 'none';
|
||||
}
|
||||
}
|
||||
// 不再需要这个功能
|
||||
alert('此功能已禁用');
|
||||
}
|
||||
// 添加新单词 (带翻译) - 移除
|
||||
function addNewWordWithTranslation() {
|
||||
const newWord = document.getElementById('newWordInput').value.trim().toLowerCase();
|
||||
const newTranslation = document.getElementById('newTranslationInput').value.trim();
|
||||
if (newWord && newTranslation) {
|
||||
// 检查是否已存在
|
||||
if (!toeflWords.some(w => w.word === newWord)) {
|
||||
const newWordObj = { word: newWord, translation: newTranslation };
|
||||
toeflWords.push(newWordObj);
|
||||
toeflWords.sort((a, b) => a.word.localeCompare(b.word)); // 按字母排序
|
||||
renderWordGrid();
|
||||
updateStats();
|
||||
document.getElementById('addWordSuggestion').style.display = 'none';
|
||||
document.getElementById('searchInput').value = '';
|
||||
document.getElementById('newWordInput').value = '';
|
||||
document.getElementById('newTranslationInput').value = '';
|
||||
// 显示添加成功提示
|
||||
alert(`单词 "${newWord}" (${newTranslation}) 已成功添加到词库中!`);
|
||||
} else {
|
||||
alert(`单词 "${newWord}" 已存在于词库中!`);
|
||||
}
|
||||
} else {
|
||||
alert('请输入英文单词和中文翻译!');
|
||||
}
|
||||
// 不再需要这个功能
|
||||
alert('此功能已禁用');
|
||||
}
|
||||
// 清除搜索 - 移除
|
||||
function clearSearch() {
|
||||
document.getElementById('searchInput').value = '';
|
||||
document.getElementById('addWordSuggestion').style.display = 'none';
|
||||
renderWordGrid();
|
||||
// 不再需要这个功能
|
||||
alert('此功能已禁用');
|
||||
}
|
||||
// 导出配置文件 - 移除
|
||||
function exportConfig() {
|
||||
if (selectedWords.length === 0) {
|
||||
alert('请先选择单词!');
|
||||
return;
|
||||
}
|
||||
const config = {
|
||||
words: selectedWords, // 导出包含 word 和 translation 的对象数组
|
||||
createdTime: new Date().toISOString(),
|
||||
version: '1.1' // 更新版本号
|
||||
};
|
||||
// 创建Blob对象
|
||||
const blob = new Blob([JSON.stringify(config, null, 2)], {type: 'application/json'});
|
||||
// 创建下载链接
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'toefl_words_config_with_translation.json';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
// 清理
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
}, 100);
|
||||
// 添加成功动画
|
||||
const exportBtn = event.target.closest('.action-btn');
|
||||
const originalText = exportBtn.innerHTML;
|
||||
exportBtn.innerHTML = '<i class="fas fa-check"></i> 已导出';
|
||||
exportBtn.classList.add('btn-success');
|
||||
setTimeout(() => {
|
||||
exportBtn.innerHTML = originalText;
|
||||
exportBtn.classList.remove('btn-success');
|
||||
}, 2000);
|
||||
// 不再需要这个功能
|
||||
alert('此功能已禁用');
|
||||
}
|
||||
// 处理文件选择 (修改版,支持 .js 文件,解码 Base64 英文数组并查找翻译)
|
||||
function handleFileSelect(event) {
|
||||
@@ -1575,19 +1475,12 @@
|
||||
if (Array.isArray(decodedWordsJson)) {
|
||||
console.log("成功从 .js 文件解析并解码 Base64 英文单词数组。"); // 调试信息
|
||||
|
||||
// --- 核心修改:根据解码出的英文单词,在内置词典中查找翻译 ---
|
||||
// --- 核心修改:根据解码出的英文单词,创建对象数组 ---
|
||||
importedWords = decodedWordsJson.map(word => {
|
||||
const foundWordObj = toeflWords.find(item => item.word === word);
|
||||
if (foundWordObj) {
|
||||
return { word: foundWordObj.word, translation: foundWordObj.translation };
|
||||
} else {
|
||||
// 如果在内置词典中找不到,翻译为空字符串
|
||||
console.warn(`在内置词典中未找到单词: ${word}`);
|
||||
return { word: word, translation: '' };
|
||||
}
|
||||
return { word: word, translation: '' }; // 没有内置词库,翻译为空
|
||||
});
|
||||
|
||||
// 检查是否有成功找到翻译的单词
|
||||
// 检查是否有成功解析的单词
|
||||
if (importedWords.length > 0) {
|
||||
// 使用第一个单词的创建时间(或当前时间)作为配置时间
|
||||
const createdTime = new Date().toISOString(); // 或者可以从 .js 文件中也编码时间,但这里简化处理
|
||||
@@ -1595,7 +1488,7 @@
|
||||
document.getElementById('importedTime').textContent = new Date(createdTime).toLocaleString();
|
||||
document.getElementById('importInfo').style.display = 'block';
|
||||
} else {
|
||||
throw new Error('从 .js 文件解码出的单词列表在内置词典中均未找到匹配项');
|
||||
throw new Error('从 .js 文件解码出的单词列表为空');
|
||||
}
|
||||
} else {
|
||||
throw new Error('解码出的 Base64 内容不是有效的单词数组');
|
||||
@@ -1630,14 +1523,11 @@
|
||||
correctAnswers = importedWords.map(w => w.word);
|
||||
currentWordIndex = 0;
|
||||
dictationStarted = true;
|
||||
// --- 重置输入和切屏计数 (本地) ---
|
||||
// --- 重置输入 ---
|
||||
currentInput = '';
|
||||
updateInputDisplay();
|
||||
switchCountLocal = 0; // 重置本地计数,主进程计数由 Electron 管理
|
||||
// --- 结束重置 ---
|
||||
showCurrentWord();
|
||||
// --- 移除聚焦 ---
|
||||
// document.getElementById('answerInput').focus(); // 移除对输入框的聚焦
|
||||
}
|
||||
// 显示当前单词(横杠形式)和翻译,并显示首字母
|
||||
function showCurrentWord() {
|
||||
@@ -1660,18 +1550,11 @@
|
||||
Math.round(((currentWordIndex + 1) / importedWords.length) * 100) : 0;
|
||||
document.getElementById('progressFill').style.width = progress + '%';
|
||||
// --- 回填答案到显示区域 ---
|
||||
// document.getElementById('answerInput').value = userAnswers[currentWordIndex] || ''; // 移除
|
||||
currentInput = userAnswers[currentWordIndex] || '';
|
||||
updateInputDisplay(); // 更新显示
|
||||
// --- 结束回填 ---
|
||||
}
|
||||
}
|
||||
// 处理键盘按键 - 移除 (已在 handleKeyDown 中处理)
|
||||
// function handleKeyPress(event) {
|
||||
// if (event.key === 'Enter') {
|
||||
// submitAnswer();
|
||||
// }
|
||||
// }
|
||||
// 提交答案
|
||||
function submitAnswer() {
|
||||
if (dictationStarted) {
|
||||
@@ -1735,38 +1618,6 @@
|
||||
document.getElementById('wrongCount').textContent = totalCount - correctCount;
|
||||
document.getElementById('totalCount').textContent = totalCount;
|
||||
|
||||
// --- 从主进程获取切屏次数并更新显示 ---
|
||||
// 现在使用正确的 IPC 调用
|
||||
let switchCountValue = 0; // 初始化变量
|
||||
let offTaskCountValue = 0; // 初始化变量
|
||||
|
||||
const switchCountPromise = (window.electronAPI && typeof window.electronAPI.getSwitchCount === 'function')
|
||||
? window.electronAPI.getSwitchCount()
|
||||
: Promise.resolve(0); // 如果 API 不可用,返回 0
|
||||
|
||||
const offTaskCountPromise = (window.electronAPI && typeof window.electronAPI.getOffTaskCount === 'function')
|
||||
? window.electronAPI.getOffTaskCount()
|
||||
: Promise.resolve(0); // 如果 API 不可用,返回 0
|
||||
|
||||
Promise.all([switchCountPromise, offTaskCountPromise])
|
||||
.then(([switchCount, offTaskCount]) => {
|
||||
// 确保获取到的是数字
|
||||
switchCountValue = typeof switchCount === 'number' ? switchCount : 0;
|
||||
offTaskCountValue = typeof offTaskCount === 'number' ? offTaskCount : 0;
|
||||
|
||||
document.getElementById('switchCountFinal').textContent = switchCountValue;
|
||||
document.getElementById('offTaskCountFinal').textContent = offTaskCountValue;
|
||||
console.log("成功获取主进程切屏次数:", switchCountValue, "未认真答题次数:", offTaskCountValue); // 调试信息
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("获取次数失败:", error);
|
||||
// 如果 IPC 调用失败,回退到本地计数(虽然不准确)
|
||||
// 注意:这里需要确保本地没有定义同名的全局变量
|
||||
document.getElementById('switchCountFinal').textContent = '获取失败';
|
||||
document.getElementById('offTaskCountFinal').textContent = '获取失败';
|
||||
});
|
||||
// --- 结束更新 ---
|
||||
|
||||
// 根据正确率显示等级
|
||||
let gradeClass = '';
|
||||
let gradeText = '';
|
||||
@@ -1828,10 +1679,9 @@
|
||||
userAnswers = new Array(importedWords.length).fill('');
|
||||
currentWordIndex = 0;
|
||||
dictationStarted = true;
|
||||
// --- 重置输入和切屏计数 (本地) ---
|
||||
// --- 重置输入 ---
|
||||
currentInput = '';
|
||||
updateInputDisplay();
|
||||
switchCountLocal = 0; // 重置本地计数
|
||||
// --- 结束重置 ---
|
||||
showCurrentWord();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user