Fix docx download: attach click handlers directly to file items, use iframe for reliable download
This commit is contained in:
parent
fe0a2a0611
commit
0c1d671c8d
@ -225,6 +225,7 @@ class TranscriptionApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
container.innerHTML = tree.map(folder => this.renderFolder(folder)).join('');
|
container.innerHTML = tree.map(folder => this.renderFolder(folder)).join('');
|
||||||
|
this.attachFileItemListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFolder(folder) {
|
renderFolder(folder) {
|
||||||
@ -232,10 +233,9 @@ class TranscriptionApp {
|
|||||||
const isMd = file.ext === '.md';
|
const isMd = file.ext === '.md';
|
||||||
const isDocx = file.ext === '.docx';
|
const isDocx = file.ext === '.docx';
|
||||||
const icon = isMd ? '📝' : isDocx ? '📄' : '📎';
|
const icon = isMd ? '📝' : isDocx ? '📄' : '📎';
|
||||||
const clickable = isMd || isDocx ? 'clickable' : '';
|
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="file-item ${clickable}" data-path="${this.escapeHtml(file.path)}" data-ext="${file.ext}">
|
<div class="file-item" data-path="${this.escapeHtml(file.path)}" data-ext="${file.ext}">
|
||||||
<span class="file-icon">${icon}</span>
|
<span class="file-icon">${icon}</span>
|
||||||
<span class="file-name">${this.escapeHtml(file.name)}</span>
|
<span class="file-name">${this.escapeHtml(file.name)}</span>
|
||||||
<span class="file-size">${this.formatBytes(file.size)}</span>
|
<span class="file-size">${this.formatBytes(file.size)}</span>
|
||||||
@ -288,13 +288,18 @@ class TranscriptionApp {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open file
|
});
|
||||||
const fileItem = e.target.closest('.file-item.clickable');
|
}
|
||||||
if (fileItem) {
|
|
||||||
const path = fileItem.dataset.path;
|
attachFileItemListeners() {
|
||||||
const ext = fileItem.dataset.ext;
|
const container = document.getElementById('fileTree');
|
||||||
|
container.querySelectorAll('.file-item').forEach(item => {
|
||||||
|
item.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const path = item.dataset.path;
|
||||||
|
const ext = item.dataset.ext;
|
||||||
this.loadFileContent(path, ext);
|
this.loadFileContent(path, ext);
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,30 +365,22 @@ class TranscriptionApp {
|
|||||||
} else if (ext === '.docx') {
|
} else if (ext === '.docx') {
|
||||||
viewer.innerHTML = `
|
viewer.innerHTML = `
|
||||||
<div class="file-preview">
|
<div class="file-preview">
|
||||||
<p>Скачивание DOCX...</p>
|
<p>⬇️ Скачивание DOCX...</p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
// Принудительное скачивание через Blob (браузер не блокирует)
|
// iframe method — работает без user-gesture restrictions
|
||||||
try {
|
const iframe = document.createElement('iframe');
|
||||||
const resp = await fetch(`/api/files/download?path=${encodeURIComponent(path)}`);
|
iframe.style.display = 'none';
|
||||||
if (!resp.ok) throw new Error('Download failed');
|
iframe.src = `/api/files/download?path=${encodeURIComponent(path)}`;
|
||||||
const blob = await resp.blob();
|
document.body.appendChild(iframe);
|
||||||
const url = URL.createObjectURL(blob);
|
setTimeout(() => {
|
||||||
const a = document.createElement('a');
|
iframe.remove();
|
||||||
a.href = url;
|
|
||||||
a.download = path.split('/').pop();
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
viewer.innerHTML = `
|
viewer.innerHTML = `
|
||||||
<div class="file-preview">
|
<div class="file-preview">
|
||||||
<p>✅ Файл скачан: ${this.escapeHtml(path)}</p>
|
<p>✅ Файл скачан</p>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
} catch (err) {
|
}, 3000);
|
||||||
viewer.innerHTML = `<div class="error">Ошибка скачивания: ${this.escapeHtml(err.message)}</div>`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user