修复了重新翻译时没有释放资源的问题

This commit is contained in:
xunbu
2025-07-15 19:54:32 +08:00
parent 5cf401657c
commit d39cc7c9f4

View File

@@ -39,7 +39,6 @@
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
/* === 修改点: 为等待ID的状态添加样式 === */
.task-id-placeholder { .task-id-placeholder {
color: var(--bs-secondary-color); color: var(--bs-secondary-color);
font-style: italic; font-style: italic;
@@ -122,7 +121,6 @@
overflow: auto; overflow: auto;
} }
/* MODIFIED: Redefined gutter styles for both directions */
.gutter { .gutter {
background-color: var(--bs-tertiary-bg); background-color: var(--bs-tertiary-bg);
background-repeat: no-repeat; background-repeat: no-repeat;
@@ -163,39 +161,32 @@
z-index: 1050; z-index: 1050;
} }
/* === MODIFIED: Added Responsive Styles === */
/* Make the main layout responsive for mobile (stacks below lg breakpoint) */
@media (max-width: 991.98px) { @media (max-width: 991.98px) {
.main-container { .main-container {
height: auto; /* Allow natural page height */ height: auto;
padding-bottom: 6rem; /* Add padding at the bottom for floating theme switch */ padding-bottom: 6rem;
} }
.settings-panel, .task-area { .settings-panel, .task-area {
height: auto; /* Remove fixed height to allow natural flow */ height: auto;
overflow-y: visible; overflow-y: visible;
} }
.settings-panel { .settings-panel {
padding-right: 0; /* No scrollbar space needed */ padding-right: 0;
margin-bottom: 2rem; /* Add space when panels stack */ margin-bottom: 2rem;
} }
} }
/* Adjustments for smaller screens (tablets and phones) */
@media (max-width: 767.98px) { @media (max-width: 767.98px) {
/* Add space between file area and log area when they stack on mobile */
.task-card .col-md-7 { .task-card .col-md-7 {
margin-top: 1.5rem; margin-top: 1.5rem;
} }
/* Make preview offcanvas full width on mobile */
#previewOffcanvas { #previewOffcanvas {
--bs-offcanvas-width: 100vw; --bs-offcanvas-width: 100vw;
} }
} }
</style> </style>
</head> </head>
<body> <body>
@@ -432,7 +423,6 @@
<template id="taskCardTemplate"> <template id="taskCardTemplate">
<div class="card mb-3 task-card"> <div class="card mb-3 task-card">
<div class="card-header d-flex justify-content-between align-items-center"> <div class="card-header d-flex justify-content-between align-items-center">
<!-- === 修改点: 初始显示占位符而不是ID === -->
<span class="fw-bold">任务 ID: <code class="task-id-display"><span class="task-id-placeholder">等待提交...</span></code></span> <span class="fw-bold">任务 ID: <code class="task-id-display"><span class="task-id-placeholder">等待提交...</span></code></span>
<button type="button" class="btn-close remove-task-btn" aria-label="Close"></button> <button type="button" class="btn-close remove-task-btn" aria-label="Close"></button>
</div> </div>
@@ -741,7 +731,7 @@
}; };
if (restoreState && backendTaskId) { if (restoreState && backendTaskId) {
elements.taskIdDisplay.textContent = backendTaskId; elements.taskIdDisplay.innerHTML = `<code>${backendTaskId}</code>`;
} }
tasks[cardId] = { tasks[cardId] = {
@@ -770,6 +760,23 @@
} }
} }
/**
* Notifies the backend to release a task's resources.
* @param {string} backendTaskId - The ID of the task to release.
*/
async function releaseTask(backendTaskId) {
try {
fetch(`/service/release/${backendTaskId}`, { method: 'POST' });
console.log(`[${backendTaskId}] Release request sent to backend.`);
} catch (error) {
console.error(`[${backendTaskId}] Failed to send release request:`, error);
}
}
/**
* Removes a task card from the UI and releases its backend resources.
* @param {string} cardId - The local ID of the card to remove.
*/
async function removeTask(cardId) { async function removeTask(cardId) {
const task = tasks[cardId]; const task = tasks[cardId];
if (!task) return; if (!task) return;
@@ -777,11 +784,12 @@
const backendTaskId = task.state.backendTaskId; const backendTaskId = task.state.backendTaskId;
if (backendTaskId) { if (backendTaskId) {
stopPolling(backendTaskId); stopPolling(backendTaskId);
await fetch(`/service/release/${backendTaskId}`,{method: 'POST'}); await releaseTask(backendTaskId);
} }
task.elements.card.remove(); task.elements.card.remove();
delete tasks[cardId]; delete tasks[cardId];
saveTaskIds(); saveTaskIds();
updateTaskPlaceholderVisibility(); updateTaskPlaceholderVisibility();
} }
@@ -863,6 +871,17 @@
return; return;
} }
// ======================== FIX: RELEASE OLD TASK ON RETRY ========================
// If a previous backend task exists for this card, release it before starting a new one.
const oldBackendTaskId = state.backendTaskId;
if (oldBackendTaskId) {
console.log(`[${oldBackendTaskId}] Re-translating. Releasing resources for the old task.`);
await releaseTask(oldBackendTaskId);
// Immediately reset the backend ID in the state.
state.backendTaskId = null;
}
// ==============================================================================
state.isTranslating = true; state.isTranslating = true;
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> 初始化...`;
@@ -901,9 +920,9 @@
if (response.ok && result.task_started) { if (response.ok && result.task_started) {
const backendTaskId = result.task_id; const backendTaskId = result.task_id;
state.backendTaskId = backendTaskId; state.backendTaskId = backendTaskId; // Store the NEW task ID
state.isSubmitted = true; state.isSubmitted = true;
elements.taskIdDisplay.textContent = backendTaskId; elements.taskIdDisplay.innerHTML = `<code>${backendTaskId}</code>`;
elements.taskIdDisplay.classList.remove('task-id-placeholder'); elements.taskIdDisplay.classList.remove('task-id-placeholder');
saveTaskIds(); saveTaskIds();
@@ -1012,12 +1031,13 @@
return; return;
} }
const { elements, state } = card; const { elements, state } = card;
const cardId = card.elements.card.dataset.cardId; const cardId = elements.card.dataset.cardId;
try { try {
const response = await fetch(`/service/status/${backendTaskId}`); const response = await fetch(`/service/status/${backendTaskId}`);
if (!response.ok) { if (!response.ok) {
if (response.status === 404 && isRestore) { if (response.status === 404 && isRestore) {
console.warn(`Task ${backendTaskId} not found on server (404). Removing from UI.`);
await removeTask(cardId); await removeTask(cardId);
} }
return; return;
@@ -1166,19 +1186,14 @@
}); });
} }
// MODIFIED: This function now handles responsive layout for the preview panes.
function setPreviewDisplayMode(mode) { function setPreviewDisplayMode(mode) {
if (previewSplitInstance) { if (previewSplitInstance) {
previewSplitInstance.destroy(); previewSplitInstance.destroy();
previewSplitInstance = null; previewSplitInstance = null;
} }
// Check screen size to determine layout (true for mobile, false for desktop) const isMobileView = window.innerWidth < 992;
const isMobileView = window.innerWidth < 992; // Using Bootstrap's 'lg' breakpoint
const splitContainer = document.querySelector('.preview-split-container'); const splitContainer = document.querySelector('.preview-split-container');
// Reset element styles
originalPreviewContainer.style.display = 'flex'; originalPreviewContainer.style.display = 'flex';
translatedPreviewContainer.style.display = 'flex'; translatedPreviewContainer.style.display = 'flex';
[originalPreviewContainer, translatedPreviewContainer].forEach(el => { [originalPreviewContainer, translatedPreviewContainer].forEach(el => {
@@ -1191,22 +1206,12 @@
previewOffcanvasLabel.textContent = '双语预览'; previewOffcanvasLabel.textContent = '双语预览';
if (isMobileView) { if (isMobileView) {
// Mobile: Vertical Split
previewSplitInstance = Split(['#originalPreviewContainer', '#translatedPreviewContainer'], { previewSplitInstance = Split(['#originalPreviewContainer', '#translatedPreviewContainer'], {
direction: 'vertical', direction: 'vertical', sizes: [50, 50], minSize: 150, gutterSize: 10, cursor: 'row-resize',
sizes: [50, 50],
minSize: 150, // Smaller min-size for vertical layout
gutterSize: 10,
cursor: 'row-resize',
}); });
} else { } else {
// Desktop: Horizontal Split
previewSplitInstance = Split(['#originalPreviewContainer', '#translatedPreviewContainer'], { previewSplitInstance = Split(['#originalPreviewContainer', '#translatedPreviewContainer'], {
direction: 'horizontal', direction: 'horizontal', sizes: [50, 50], minSize: 200, gutterSize: 10, cursor: 'col-resize',
sizes: [50, 50],
minSize: 200,
gutterSize: 10,
cursor: 'col-resize',
}); });
} }