v2.3.8
This commit is contained in:
+42
-2
@@ -767,6 +767,8 @@
|
||||
.download-icon { font-size: 12px; line-height: 1; }
|
||||
:root[data-theme="dark"] .download-btn { background: linear-gradient(135deg, #6366f1, #4f46e5); box-shadow: 0 1px 3px rgba(79,70,229,0.25); }
|
||||
:root[data-theme="dark"] .download-btn:hover { background: linear-gradient(135deg, #4f46e5, #4338ca); }
|
||||
.download-btn-error { display: inline-flex; align-items: center; gap: 4px; background: #fee2e2; color: #991b1b !important; padding: 4px 10px; border-radius: 6px; font-weight: 600; font-size: 12px; margin: 4px 2px; cursor: default; text-decoration: none !important; }
|
||||
:root[data-theme="dark"] .download-btn-error { background: #3f1515; color: #fca5a5 !important; }
|
||||
.pptx-file-row { margin: 4px 0; }
|
||||
.pptx-preview-btn { display: inline-flex; align-items: center; gap: 4px; background: linear-gradient(135deg, #10b981, #059669); color: #fff; padding: 4px 10px; border-radius: 6px; border: none; font-weight: 600; font-size: 12px; cursor: pointer; margin-left: 4px; transition: all 0.15s; box-shadow: 0 1px 3px rgba(16,185,129,0.25); }
|
||||
.pptx-preview-btn:hover { background: linear-gradient(135deg, #059669, #047857); transform: translateY(-1px); }
|
||||
@@ -4593,6 +4595,7 @@ function renderChatMessages() {
|
||||
return;
|
||||
}
|
||||
|
||||
_dlLinkCache = {}; // reset on full re-render so moved/deleted files recheck
|
||||
container.innerHTML = chatHistory.map((msg, idx) => {
|
||||
const pinClass = contextPinMode ? ' pin-selectable' : '';
|
||||
const selectedClass = (contextPinMode && pinnedMessageIndices.has(idx)) ? ' pin-selected' : '';
|
||||
@@ -4614,6 +4617,8 @@ function renderChatMessages() {
|
||||
</div>`;
|
||||
}).join('');
|
||||
|
||||
validateDownloadLinks(container);
|
||||
|
||||
if (isThinking && streamingSessionId === activeChatSessionId) {
|
||||
const progressHtml = currentProgressLines.length
|
||||
? `<div style="margin:6px 0 8px 0;font-size:11px;line-height:1.6;color:var(--muted)">
|
||||
@@ -8242,6 +8247,41 @@ function closeImageZoom() {
|
||||
if (modal) modal.style.display = 'none';
|
||||
}
|
||||
|
||||
// Cache of checked /api/files/ URLs: url -> true (exists) | false (not found)
|
||||
var _dlLinkCache = {};
|
||||
|
||||
function markDownloadLinkError(btn) {
|
||||
var href = btn.getAttribute ? btn.getAttribute('href') : (btn.href || '');
|
||||
var filename = decodeURIComponent((href || '').split('/').pop() || '파일');
|
||||
_dlLinkCache[href] = false;
|
||||
var span = document.createElement('span');
|
||||
span.className = 'download-btn-error';
|
||||
span.title = '파일을 찾을 수 없음: ' + filename;
|
||||
span.textContent = '⚠ ' + filename + ' (파일 없음)';
|
||||
if (btn.parentNode) btn.parentNode.replaceChild(span, btn);
|
||||
}
|
||||
|
||||
function validateDownloadLinks(container) {
|
||||
var buttons = (container || document).querySelectorAll('a.download-btn[href]');
|
||||
buttons.forEach(function(btn) {
|
||||
var url = btn.getAttribute('href');
|
||||
if (!url || url.indexOf('/api/files/') === -1) return;
|
||||
if (_dlLinkCache[url] === false) { markDownloadLinkError(btn); return; }
|
||||
if (_dlLinkCache[url] === true) return;
|
||||
_dlLinkCache[url] = 'pending';
|
||||
fetch(url, { method: 'HEAD', credentials: 'same-origin' })
|
||||
.then(function(r) {
|
||||
_dlLinkCache[url] = r.ok;
|
||||
if (!r.ok) {
|
||||
// btn may still be in DOM; re-query in case renderMessages rebuilt it
|
||||
var found = (container || document).querySelector('a.download-btn[href="' + url.replace(/"/g, '\\"') + '"]');
|
||||
if (found) markDownloadLinkError(found);
|
||||
}
|
||||
})
|
||||
.catch(function() { _dlLinkCache[url] = false; });
|
||||
});
|
||||
}
|
||||
|
||||
function downloadFile(e, el) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@@ -8264,7 +8304,7 @@ function downloadFile(e, el) {
|
||||
credentials: 'same-origin'
|
||||
})
|
||||
.then(function(r) {
|
||||
if (!r.ok) throw new Error('Download failed: ' + r.status);
|
||||
if (!r.ok) throw new Error(r.status);
|
||||
return r.blob();
|
||||
})
|
||||
.then(function(blob) {
|
||||
@@ -8278,7 +8318,7 @@ function downloadFile(e, el) {
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
})
|
||||
.catch(function(err) {
|
||||
alert('Download failed: ' + err.message);
|
||||
markDownloadLinkError(el);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user