🔧 미리보기 인증 및 에러 처리 개선

🛠️ 401 Unauthorized 오류 해결:
- HTML 콘텐츠 API 호출을 api.get() 래퍼로 변경
- iframe src에 토큰 파라미터 추가
- 백엔드에서 _token 쿼리 파라미터 지원

🛠️ 404 Not Found 오류 해결:
- 문서 상세 정보를 먼저 로드하여 PDF/HTML 존재 여부 확인
- PDF/HTML 파일 존재 여부에 따른 조건부 렌더링
- 미리보기 타입 자동 감지 및 적절한 뷰어 선택

🎯 에러 처리 및 UX 개선:
- HTML 로드 실패 시 에러 메시지 표시
- 미리보기 불가능한 콘텐츠에 대한 fallback UI
- 문서 정보 로드 실패 시 기본 내용으로 fallback
- '원본에서 보기' 버튼으로 대안 제공

🔍 미리보기 로직 개선:
- 문서 타입별 적절한 미리보기 방식 자동 선택
- PDF 존재 시 PDF 뷰어, HTML 존재 시 HTML 뷰어
- 검색어 하이라이트 타이밍 최적화
- 로딩 상태 및 에러 상태 명확한 구분
This commit is contained in:
Hyungi Ahn
2025-09-02 17:20:37 +09:00
parent 5f9fe07317
commit 2d25c04457
3 changed files with 66 additions and 24 deletions

View File

@@ -199,10 +199,36 @@ window.searchApp = function() {
this.previewLoading = true;
try {
// 타입별 미리보기 로드
if ((result.type === 'document' || result.type === 'document_content') && !result.highlight_info?.has_pdf) {
// HTML 문서 미리보기
await this.loadHtmlPreview(result.document_id);
// 문서 타입인 경우 상세 정보 먼저 로드
if (result.type === 'document' || result.type === 'document_content') {
try {
const docInfo = await this.api.get(`/documents/${result.document_id}`);
// PDF 정보 업데이트
this.previewResult = {
...result,
highlight_info: {
...result.highlight_info,
has_pdf: !!docInfo.pdf_path,
has_html: !!docInfo.html_path
}
};
// PDF가 있으면 PDF 미리보기, 없으면 HTML 미리보기
if (docInfo.pdf_path) {
// PDF 미리보기는 iframe으로 자동 처리
console.log('PDF 미리보기 준비 완료');
} else if (docInfo.html_path) {
// HTML 문서 미리보기
await this.loadHtmlPreview(result.document_id);
}
} catch (docError) {
console.error('문서 정보 로드 실패:', docError);
// 기본 내용 로드로 fallback
const fullContent = await this.loadFullContent(result);
if (fullContent) {
this.previewResult = { ...result, content: fullContent };
}
}
} else {
// 기타 타입 - 전체 내용 로드
const fullContent = await this.loadFullContent(result);
@@ -303,35 +329,39 @@ window.searchApp = function() {
this.htmlLoading = true;
try {
// HTML 내용 가져오기
const response = await fetch(`/api/documents/${documentId}/content`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('token')}`
}
});
// API를 통해 HTML 내용 가져오기
const htmlContent = await this.api.get(`/documents/${documentId}/content`);
if (response.ok) {
const htmlContent = await response.text();
if (htmlContent) {
this.htmlSourceCode = this.escapeHtml(htmlContent);
// iframe에 HTML 로드
const iframe = document.getElementById('htmlPreviewFrame');
if (iframe) {
const doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write(htmlContent);
doc.close();
// iframe src를 직접 설정 (인증 헤더 포함)
const token = localStorage.getItem('token');
iframe.src = `/api/documents/${documentId}/content?_token=${encodeURIComponent(token)}`;
// 검색어 하이라이트 (iframe 내부)
if (this.searchQuery) {
this.highlightInIframe(iframe, this.searchQuery);
}
// iframe 로드 완료 후 검색어 하이라이트
iframe.onload = () => {
if (this.searchQuery) {
setTimeout(() => {
this.highlightInIframe(iframe, this.searchQuery);
}, 100);
}
};
}
} else {
throw new Error('HTML 로드 실패');
throw new Error('HTML 내용이 비어있습니다');
}
} catch (error) {
console.error('HTML 미리보기 로드 실패:', error);
// 에러 시 기본 내용 표시
this.htmlSourceCode = `<div class="p-4 text-center text-gray-500">
<i class="fas fa-exclamation-triangle text-2xl mb-2"></i>
<p>HTML 내용을 로드할 수 없습니다.</p>
<p class="text-sm">${error.message}</p>
</div>`;
} finally {
this.htmlLoading = false;
}