前端区分任务是否提交

This commit is contained in:
xunbu
2025-07-14 18:09:00 +08:00
parent c9d18bc45c
commit 9a7f8d61d4

View File

@@ -481,7 +481,7 @@
<!-- Bootstrap JS --> <!-- Bootstrap JS -->
<script src="/static/bootstrap.bundle.min.js" crossorigin="anonymous"></script> <script src="/static/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<script type="module"> <script type="module">
const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]'); const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl)); const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
@@ -548,21 +548,8 @@
// --- Utility Functions --- // --- Utility Functions ---
const generateTaskId = () => Math.random().toString(36).substring(2, 10); const generateTaskId = () => Math.random().toString(36).substring(2, 10);
const saveToStorage = (key, value) => { const saveToStorage = (key, value) => { try { localStorage.setItem(key, value); } catch (e) { console.warn("Save to storage failed:", e); } };
try { const getFromStorage = (key, defaultValue = '') => { try { return localStorage.getItem(key) || defaultValue; } catch (e) { console.warn("Read from storage failed:", e); return defaultValue; } };
localStorage.setItem(key, value);
} catch (e) {
console.warn("Save to storage failed:", e);
}
};
const getFromStorage = (key, defaultValue = '') => {
try {
return localStorage.getItem(key) || defaultValue;
} catch (e) {
console.warn("Read from storage failed:", e);
return defaultValue;
}
};
function fileToBase64(file) { function fileToBase64(file) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@@ -680,6 +667,7 @@
file: null, file: null,
htmlUrl: null, htmlUrl: null,
fileNameStem: null, fileNameStem: null,
isSubmitted: false // MODIFICATION 1: Add isSubmitted flag
}, },
intervals: { intervals: {
log: null, log: null,
@@ -709,7 +697,7 @@
} }
function addEventListenersToCard(taskId) { function addEventListenersToCard(taskId) {
const {elements, state} = tasks[taskId]; const { elements, state } = tasks[taskId];
elements.removeBtn.addEventListener('click', () => removeTask(taskId)); elements.removeBtn.addEventListener('click', () => removeTask(taskId));
@@ -746,7 +734,7 @@
} }
function handleFileSelect(taskId) { function handleFileSelect(taskId) {
const {elements, state} = tasks[taskId]; const { elements, state } = tasks[taskId];
const file = elements.fileInput.files[0]; const file = elements.fileInput.files[0];
if (file) { if (file) {
state.file = file; state.file = file;
@@ -761,7 +749,7 @@
// --- Core Translation Logic --- // --- Core Translation Logic ---
async function startTranslation(taskId) { async function startTranslation(taskId) {
const {elements, state} = tasks[taskId]; const { elements, state } = tasks[taskId];
// --- Validation --- // --- Validation ---
if (!state.file) { if (!state.file) {
@@ -803,6 +791,8 @@
try { try {
const fileContentBase64 = await fileToBase64(state.file); const fileContentBase64 = await fileToBase64(state.file);
state.isSubmitted = true; // MODIFICATION 2: Mark task as submitted before sending request
const payload = { const payload = {
task_id: taskId, task_id: taskId,
base_url: baseUrlInput.value, base_url: baseUrlInput.value,
@@ -824,7 +814,7 @@
const response = await fetch('/service/translate', { const response = await fetch('/service/translate', {
method: 'POST', method: 'POST',
headers: {'Content-Type': 'application/json'}, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload) body: JSON.stringify(payload)
}); });
const result = await response.json(); const result = await response.json();
@@ -852,12 +842,12 @@
} }
async function cancelTranslation(taskId) { async function cancelTranslation(taskId) {
const {elements} = tasks[taskId]; const { elements } = tasks[taskId];
elements.startBtn.disabled = true; elements.startBtn.disabled = true;
elements.startBtn.innerHTML = `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 正在取消...`; elements.startBtn.innerHTML = `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 正在取消...`;
try { try {
const response = await fetch(`/service/cancel/${taskId}`, {method: 'POST'}); const response = await fetch(`/service/cancel/${taskId}`, { method: 'POST' });
const result = await response.json(); const result = await response.json();
if (response.ok && result.cancelled) { if (response.ok && result.cancelled) {
@@ -877,7 +867,7 @@
// --- Polling --- // --- Polling ---
function startPolling(taskId) { function startPolling(taskId) {
stopPolling(taskId); stopPolling(taskId);
const {intervals} = tasks[taskId]; const { intervals } = tasks[taskId];
intervals.log = setInterval(() => pollLogs(taskId), 2000); intervals.log = setInterval(() => pollLogs(taskId), 2000);
intervals.status = setInterval(() => pollStatus(taskId), 1500); intervals.status = setInterval(() => pollStatus(taskId), 1500);
pollLogs(taskId); pollLogs(taskId);
@@ -885,7 +875,7 @@
} }
function stopPolling(taskId) { function stopPolling(taskId) {
const {intervals} = tasks[taskId]; const { intervals } = tasks[taskId];
if (intervals.log) clearInterval(intervals.log); if (intervals.log) clearInterval(intervals.log);
if (intervals.status) clearInterval(intervals.status); if (intervals.status) clearInterval(intervals.status);
intervals.log = null; intervals.log = null;
@@ -893,7 +883,7 @@
} }
async function pollLogs(taskId) { async function pollLogs(taskId) {
const {elements} = tasks[taskId]; const { elements } = tasks[taskId];
try { try {
const response = await fetch(`/service/logs/${taskId}`); const response = await fetch(`/service/logs/${taskId}`);
if (!response.ok) return; if (!response.ok) return;
@@ -908,12 +898,13 @@
} }
async function pollStatus(taskId, isRestore = false) { async function pollStatus(taskId, isRestore = false) {
const {elements, state} = tasks[taskId]; const { elements, state } = tasks[taskId];
try { try {
const response = await fetch(`/service/status/${taskId}`); const response = await fetch(`/service/status/${taskId}`);
if (!response.ok) { if (!response.ok) {
// If 404 on restore, it means the task is old and gone from server. Remove it. // MODIFICATION 3: Only remove task if it was already submitted
if (response.status === 404 && isRestore) { // An unsubmitted task will have `state.isSubmitted = false`, and will not be removed.
if (response.status === 404 && isRestore && state.isSubmitted) {
removeTask(taskId); removeTask(taskId);
} }
return; return;
@@ -967,7 +958,7 @@
// --- Download and Preview --- // --- Download and Preview ---
function setupPreview(taskId) { function setupPreview(taskId) {
const {state} = tasks[taskId]; const { state } = tasks[taskId];
if (!state.htmlUrl) return; if (!state.htmlUrl) return;
// Clear previous content // Clear previous content
@@ -1021,14 +1012,12 @@
try { try {
translatedPreviewFrame.contentWindow.focus(); translatedPreviewFrame.contentWindow.focus();
translatedPreviewFrame.contentWindow.print(); translatedPreviewFrame.contentWindow.print();
} catch (e) { } catch(e) { alert('打印失败,请使用浏览器打印功能。'); }
alert('打印失败,请使用浏览器打印功能。');
}
}; };
} }
function downloadPdf(taskId) { function downloadPdf(taskId) {
const {elements, state} = tasks[taskId]; const { elements, state } = tasks[taskId];
if (!state.htmlUrl) return; if (!state.htmlUrl) return;
elements.pdfBtn.disabled = true; elements.pdfBtn.disabled = true;
@@ -1157,9 +1146,7 @@
platformSelect.addEventListener('change', updatePlatformUI); platformSelect.addEventListener('change', updatePlatformUI);
apikeyInput.addEventListener('input', e => saveToStorage(`translator_platform_${platformSelect.value}_apikey`, e.target.value)); apikeyInput.addEventListener('input', e => saveToStorage(`translator_platform_${platformSelect.value}_apikey`, e.target.value));
modelInput.addEventListener('input', e => saveToStorage(`translator_platform_${platformSelect.value}_model_id`, e.target.value)); modelInput.addEventListener('input', e => saveToStorage(`translator_platform_${platformSelect.value}_model_id`, e.target.value));
baseUrlInput.addEventListener('input', e => { baseUrlInput.addEventListener('input', e => { if (platformSelect.value === 'custom') saveToStorage('translator_platform_custom_base_url', e.target.value); });
if (platformSelect.value === 'custom') saveToStorage('translator_platform_custom_base_url', e.target.value);
});
convertEnginSelect.addEventListener('change', updateConvertEnginUI); convertEnginSelect.addEventListener('change', updateConvertEnginUI);
mineruTokenInput.addEventListener('input', e => saveToStorage('translator_mineru_token', e.target.value)); mineruTokenInput.addEventListener('input', e => saveToStorage('translator_mineru_token', e.target.value));
toLangSelect.addEventListener('change', e => saveToStorage('translator_to_lang', e.target.value)); toLangSelect.addEventListener('change', e => saveToStorage('translator_to_lang', e.target.value));
@@ -1232,6 +1219,6 @@
// --- Start the application --- // --- Start the application ---
document.addEventListener('DOMContentLoaded', init); document.addEventListener('DOMContentLoaded', init);
</script> </script>
</body> </body>
</html> </html>