inside drop area */
margin: 0.5rem 0;
color: #555;
- }
+ } \
+
/* #fileDropPrompt will be hidden/shown by JS using .hidden class */
@@ -167,7 +168,8 @@ HTML_TEMPLATE = """
#fileDropArea.input-error {
border-color: var(--pico-form-element-invalid-border-color, #d32f2f) !important;
- }
+ } \
+
#fileNameDisplay.input-error-text {
color: var(--pico-form-element-invalid-border-color, #d32f2f) !important;
font-weight: bold;
@@ -315,17 +317,15 @@ HTML_TEMPLATE = """
const closePreviewBtn = document.getElementById('closePreviewBtn');
const printFromPreview = document.getElementById('printFromPreview');
- // File input and drag-drop elements
const fileInput = document.getElementById('file');
const fileDropArea = document.getElementById('fileDropArea');
const fileNameDisplay = document.getElementById('fileNameDisplay');
- const fileDropPrompt = document.getElementById('fileDropPrompt'); // <-- 获取提示文字元素
-
+ const fileDropPrompt = document.getElementById('fileDropPrompt');
let logPollIntervalId = null;
let statusPollIntervalId = null;
- let lastLogCount = 0;
- let isTranslating = false; // Flag to track translation state for cancel button
+ // let lastLogCount = 0; // No longer needed for fetching logs
+ let isTranslating = false;
function saveToStorage(key, value) {
try {
@@ -387,9 +387,8 @@ HTML_TEMPLATE = """
}
});
- // --- Drag and Drop File Handling ---
fileDropArea.addEventListener('click', () => {
- fileInput.click(); // Trigger click on hidden file input
+ fileInput.click();
});
fileInput.addEventListener('change', () => {
@@ -397,7 +396,7 @@ HTML_TEMPLATE = """
fileNameDisplay.textContent = `已选择: ${fileInput.files[0].name}`;
fileDropArea.classList.add('file-selected');
fileNameDisplay.classList.add('has-file');
- fileDropPrompt.classList.add('hidden'); // <-- 隐藏提示文字
+ fileDropPrompt.classList.add('hidden');
fileDropArea.classList.remove('input-error');
fileNameDisplay.classList.remove('input-error-text');
statusMsg.textContent = '';
@@ -406,7 +405,7 @@ HTML_TEMPLATE = """
fileNameDisplay.textContent = '未选择文件';
fileDropArea.classList.remove('file-selected');
fileNameDisplay.classList.remove('has-file');
- fileDropPrompt.classList.remove('hidden'); // <-- 显示提示文字
+ fileDropPrompt.classList.remove('hidden');
}
});
@@ -422,7 +421,7 @@ HTML_TEMPLATE = """
['dragenter', 'dragover'].forEach(eventName => {
fileDropArea.addEventListener(eventName, () => {
if (!fileDropArea.classList.contains('file-selected')) {
- fileDropArea.classList.add('drag-over');
+ fileDropArea.classList.add('drag-over');
}
}, false);
});
@@ -444,12 +443,10 @@ HTML_TEMPLATE = """
}
}, false);
- // --- End Drag and Drop ---
-
-
async function pollLogs() {
try {
- const response = await fetch(`/get-logs?since=${lastLogCount}`);
+ // const response = await fetch(`/get-logs?since=${lastLogCount}`); // OLD
+ const response = await fetch('/get-logs'); // NEW: No 'since' parameter
if (!response.ok) {
console.warn(`Log polling failed: ${response.status}`);
return;
@@ -460,9 +457,9 @@ HTML_TEMPLATE = """
const escapedLog = log.replace(/&/g, "&").replace(//g, ">");
logArea.innerHTML += escapedLog + "
";
});
- logArea.scrollTop = logArea.scrollHeight;
+ logArea.scrollTop = logArea.scrollHeight; // Scroll to bottom
}
- lastLogCount = data.total_count;
+ // lastLogCount = data.total_count; // OLD: No longer tracking count this way
} catch (error) {
console.warn("Error polling logs:", error);
}
@@ -574,159 +571,155 @@ HTML_TEMPLATE = """
} else {
downloadBtns.style.display = 'none';
}
- } else { // Task is still processing
- submitButton.textContent = '取消翻译';
- submitButton.classList.remove('primary');
- submitButton.classList.add('secondary');
- isTranslating = true;
- submitButton.disabled = false;
- submitButton.removeAttribute('aria-busy');
- downloadBtns.style.display = 'none';
- }
- } catch (error) {
- console.error("Error polling status:", error);
- statusMsg.textContent = '状态更新出错。';
- statusMsg.className = 'error-message';
- }
- }
+ } else {
+ submitButton.textContent = '取消翻译';
+ submitButton.classList.remove('primary');
+ submitButton.classList.add('secondary');
+ isTranslating = true;
+ submitButton.disabled = false;
+ submitButton.removeAttribute('aria-busy');
+ downloadBtns.style.display = 'none';
+ }
+ } catch (error) {
+ console.error("Error polling status:", error);
+ statusMsg.textContent = '状态更新出错。';
+ statusMsg.className = 'error-message';
+ }
+ }
- function startPolling() {
- stopPolling();
- lastLogCount = 0;
- logArea.innerHTML = '';
- pollLogs();
- pollStatus();
- logPollIntervalId = setInterval(pollLogs, 2000);
- statusPollIntervalId = setInterval(pollStatus, 1500);
- }
+ function startPolling() {
+ stopPolling();
+ // lastLogCount = 0; // No longer needed
+ logArea.innerHTML = ''; // Clear log area for new task
+ pollLogs(); // Initial poll for logs
+ pollStatus(); // Initial poll for status
+ logPollIntervalId = setInterval(pollLogs, 2000);
+ statusPollIntervalId = setInterval(pollStatus, 1500);
+ }
- function stopPolling() {
- if (logPollIntervalId) clearInterval(logPollIntervalId);
- if (statusPollIntervalId) clearInterval(statusPollIntervalId);
- logPollIntervalId = null;
- statusPollIntervalId = null;
- setTimeout(pollLogs, 100);
- }
+ function stopPolling() {
+ if (logPollIntervalId) clearInterval(logPollIntervalId);
+ if (statusPollIntervalId) clearInterval(statusPollIntervalId);
+ logPollIntervalId = null;
+ statusPollIntervalId = null;
+ }
- function loadSettings() {
- platformSelect.value = getFromStorage('translator_last_platform', 'custom');
- updatePlatformUI();
- toLangSelect.value = getFromStorage('translator_to_lang', '中文');
- formulaCheckbox.checked = getFromStorage('translator_formula_ocr') === 'true';
- codeCheckbox.checked = getFromStorage('translator_code_ocr') === 'true';
- refineCheckbox.checked = getFromStorage('translator_refine_markdown') === 'true';
- }
+ function loadSettings() {
+ platformSelect.value = getFromStorage('translator_last_platform', 'custom');
+ updatePlatformUI();
+ toLangSelect.value = getFromStorage('translator_to_lang', '中文');
+ formulaCheckbox.checked = getFromStorage('translator_formula_ocr') === 'true';
+ codeCheckbox.checked = getFromStorage('translator_code_ocr') === 'true';
+ refineCheckbox.checked = getFromStorage('translator_refine_markdown') === 'true';
+ }
+ async function cancelTranslation() {
+ submitButton.disabled = true;
+ submitButton.textContent = '正在取消...';
+ submitButton.setAttribute('aria-busy', 'true');
- async function cancelTranslation() {
- submitButton.disabled = true;
- submitButton.textContent = '正在取消...';
- submitButton.setAttribute('aria-busy', 'true');
+ try {
+ const response = await fetch('/cancel-translate', {method: 'POST'});
+ const result = await response.json();
- try {
- const response = await fetch('/cancel-translate', {method: 'POST'});
- const result = await response.json();
+ if (response.ok && result.cancelled) {
+ statusMsg.textContent = result.message || '取消请求已发送。';
+ statusMsg.className = '';
+ } else {
+ statusMsg.textContent = result.message || '取消失败。';
+ statusMsg.className = 'error-message';
+ submitButton.disabled = false;
+ submitButton.textContent = '取消翻译';
+ submitButton.removeAttribute('aria-busy');
+ }
+ } catch (error) {
+ console.error('取消请求失败:', error);
+ statusMsg.textContent = '取消请求发送失败。';
+ statusMsg.className = 'error-message';
+ submitButton.disabled = false;
+ submitButton.textContent = '取消翻译';
+ submitButton.removeAttribute('aria-busy');
+ }
+ }
- if (response.ok && result.cancelled) {
- statusMsg.textContent = result.message || '取消请求已发送。';
- statusMsg.className = '';
- } else {
- statusMsg.textContent = result.message || '取消失败。';
- statusMsg.className = 'error-message';
- submitButton.disabled = false;
- submitButton.textContent = '取消翻译';
- submitButton.removeAttribute('aria-busy');
- }
- } catch (error) {
- console.error('取消请求失败:', error);
- statusMsg.textContent = '取消请求发送失败。';
- statusMsg.className = 'error-message';
- submitButton.disabled = false;
- submitButton.textContent = '取消翻译';
- submitButton.removeAttribute('aria-busy');
- }
- }
+ form.addEventListener('submit', async function (event) {
+ event.preventDefault();
- form.addEventListener('submit', async function (event) {
- event.preventDefault();
+ if (isTranslating) {
+ await cancelTranslation();
+ return;
+ }
- if (isTranslating) {
- await cancelTranslation();
- return;
- }
+ if (fileInput.files.length === 0) {
+ statusMsg.textContent = '请选择一个文件进行翻译。';
+ statusMsg.className = 'error-message';
+ fileNameDisplay.textContent = '请选择文件!';
+ fileNameDisplay.classList.add('input-error-text');
+ fileDropArea.classList.add('input-error');
+ fileDropPrompt.classList.remove('hidden');
+ setTimeout(() => {
+ fileDropArea.classList.remove('input-error');
+ fileNameDisplay.classList.remove('input-error-text');
+ if (fileNameDisplay.textContent === '请选择文件!') {
+ fileNameDisplay.textContent = '未选择文件';
+ }
+ if (fileInput.files.length === 0) {
+ fileDropPrompt.classList.remove('hidden');
+ }
- if (fileInput.files.length === 0) {
- statusMsg.textContent = '请选择一个文件进行翻译。';
- statusMsg.className = 'error-message';
- fileNameDisplay.textContent = '请选择文件!';
- fileNameDisplay.classList.add('input-error-text');
- fileDropArea.classList.add('input-error');
- fileDropPrompt.classList.remove('hidden'); // 确保错误时提示文字可见
- setTimeout(() => {
- fileDropArea.classList.remove('input-error');
- fileNameDisplay.classList.remove('input-error-text');
- if (fileNameDisplay.textContent === '请选择文件!') {
- fileNameDisplay.textContent = '未选择文件';
- }
- // 如果没有文件被选中,提示文字应该保持可见
- if (fileInput.files.length === 0) {
- fileDropPrompt.classList.remove('hidden');
- }
+ }, 3000);
+ return;
+ }
- }, 3000);
- return;
- }
+ stopPolling();
+ submitButton.disabled = true;
+ submitButton.setAttribute('aria-busy', 'true');
+ submitButton.textContent = '初始化...';
+ logArea.innerHTML = '';
+ statusMsg.textContent = '正在提交任务...';
+ statusMsg.className = '';
+ downloadBtns.style.display = 'none';
+ // lastLogCount = 0; // No longer needed
-
- stopPolling();
- submitButton.disabled = true;
- submitButton.setAttribute('aria-busy', 'true');
- submitButton.textContent = '初始化...';
- logArea.innerHTML = '';
- statusMsg.textContent = '正在提交任务...';
- statusMsg.className = '';
- downloadBtns.style.display = 'none';
- lastLogCount = 0;
-
- const formData = new FormData(form);
- try {
- const response = await fetch('/translate', {method: 'POST', body: formData});
- const result = await response.json();
- if (response.ok && result.task_started) {
- statusMsg.textContent = result.message || '任务已开始,正在处理...';
- statusMsg.className = '';
- submitButton.textContent = '取消翻译';
- submitButton.classList.remove('primary');
- submitButton.classList.add('secondary');
- isTranslating = true;
- submitButton.removeAttribute('aria-busy');
- startPolling();
- } else {
- statusMsg.textContent = result.message || `请求失败 (${response.status})`;
- statusMsg.className = 'error-message';
- submitButton.disabled = false;
- submitButton.removeAttribute('aria-busy');
- submitButton.textContent = '开始翻译';
- isTranslating = false;
- }
- } catch (error) {
- console.error('请求失败:', error);
- statusMsg.textContent = '请求翻译失败,请检查网络或服务状态。';
- statusMsg.className = 'error-message';
- submitButton.disabled = false;
- submitButton.removeAttribute('aria-busy');
- submitButton.textContent = '开始翻译';
- isTranslating = false;
- }
- });
-
+ const formData = new FormData(form);
+ try {
+ const response = await fetch('/translate', {method: 'POST', body: formData});
+ const result = await response.json();
+ if (response.ok && result.task_started) {
+ statusMsg.textContent = result.message || '任务已开始,正在处理...';
+ statusMsg.className = '';
+ submitButton.textContent = '取消翻译';
+ submitButton.classList.remove('primary');
+ submitButton.classList.add('secondary');
+ isTranslating = true;
+ submitButton.removeAttribute('aria-busy');
+ startPolling();
+ } else {
+ statusMsg.textContent = result.message || `请求失败 (${response.status})`;
+ statusMsg.className = 'error-message';
+ submitButton.disabled = false;
+ submitButton.removeAttribute('aria-busy');
+ submitButton.textContent = '开始翻译';
+ isTranslating = false;
+ }
+ } catch (error) {
+ console.error('请求失败:', error);
+ statusMsg.textContent = '请求翻译失败,请检查网络或服务状态。';
+ statusMsg.className = 'error-message';
+ submitButton.disabled = false;
+ submitButton.removeAttribute('aria-busy');
+ submitButton.textContent = '开始翻译';
+ isTranslating = false;
+ }
+ });
+