feat: PDF/HTML 폴더 분리 및 필터링 개선

- 업로드 시 HTML과 PDF를 별도 폴더에 저장 (/documents/, /pdfs/)
- 프론트엔드 필터링을 폴더 경로 기준으로 단순화
- PDF 삭제 시 외래키 참조 해제 로직 추가
- book-documents.js, book-editor.js 필터링 통일
- HTML 문서 목록에서 PDF 완전 분리
This commit is contained in:
Hyungi Ahn
2025-08-26 07:44:25 +09:00
parent 4038040faa
commit 04ae64fc4d
20 changed files with 1334 additions and 73 deletions

View File

@@ -261,8 +261,11 @@ window.uploadApp = () => ({
console.log('📄 HTML 파일:', htmlFiles.length, '개');
console.log('📕 PDF 파일:', pdfFiles.length, '개');
// HTML 파일 업로드 (백엔드 API에 맞게)
const uploadPromises = htmlFiles.map(async (file, index) => {
// 업로드할 파일들 처리
const uploadPromises = [];
// HTML 파일 업로드 (PDF 파일이 있으면 함께 업로드)
htmlFiles.forEach(async (file, index) => {
const formData = new FormData();
formData.append('html_file', file); // 백엔드가 요구하는 필드명
formData.append('title', file.name.replace(/\.[^/.]+$/, "")); // 확장자 제거
@@ -270,52 +273,96 @@ window.uploadApp = () => ({
formData.append('language', 'ko');
formData.append('is_public', 'false');
// 같은 이름의 PDF 파일이 있는지 확인
const htmlBaseName = file.name.replace(/\.[^/.]+$/, "");
const matchingPdf = pdfFiles.find(pdfFile => {
const pdfBaseName = pdfFile.name.replace(/\.[^/.]+$/, "");
return pdfBaseName === htmlBaseName;
});
if (matchingPdf) {
formData.append('pdf_file', matchingPdf);
console.log('📎 매칭된 PDF 파일 함께 업로드:', matchingPdf.name);
}
if (bookId) {
formData.append('book_id', bookId);
}
try {
const response = await window.api.uploadDocument(formData);
console.log('✅ HTML 파일 업로드 완료:', file.name);
return response;
} catch (error) {
console.error('❌ HTML 파일 업로드 실패:', file.name, error);
throw error;
const uploadPromise = (async () => {
try {
const response = await window.api.uploadDocument(formData);
console.log('✅ HTML 파일 업로드 완료:', file.name);
return response;
} catch (error) {
console.error('❌ HTML 파일 업로드 실패:', file.name, error);
throw error;
}
})();
uploadPromises.push(uploadPromise);
});
// HTML과 매칭되지 않은 PDF 파일들을 별도로 업로드
const unmatchedPdfs = pdfFiles.filter(pdfFile => {
const pdfBaseName = pdfFile.name.replace(/\.[^/.]+$/, "");
return !htmlFiles.some(htmlFile => {
const htmlBaseName = htmlFile.name.replace(/\.[^/.]+$/, "");
return htmlBaseName === pdfBaseName;
});
});
unmatchedPdfs.forEach(async (file, index) => {
const formData = new FormData();
formData.append('html_file', file); // PDF도 html_file로 전송 (백엔드에서 처리)
formData.append('title', file.name.replace(/\.[^/.]+$/, "")); // 확장자 제거
formData.append('description', `PDF 파일: ${file.name}`);
formData.append('language', 'ko');
formData.append('is_public', 'false');
if (bookId) {
formData.append('book_id', bookId);
}
const uploadPromise = (async () => {
try {
const response = await window.api.uploadDocument(formData);
console.log('✅ PDF 파일 업로드 완료:', file.name);
return response;
} catch (error) {
console.error('❌ PDF 파일 업로드 실패:', file.name, error);
throw error;
}
})();
uploadPromises.push(uploadPromise);
});
// PDF 파일은 별도로 처리 (나중에 HTML과 매칭)
const pdfUploadPromises = pdfFiles.map(async (file, index) => {
// PDF 전용 업로드 로직 (임시로 HTML 파일로 처리하지 않음)
console.log('📕 PDF 파일 대기 중:', file.name);
return {
id: `pdf-${Date.now()}-${index}`,
title: file.name.replace(/\.[^/.]+$/, ""),
original_filename: file.name,
file_type: 'pdf',
file: file // 실제 파일 객체 보관
};
});
// 모든 업로드 완료 대기
const uploadedDocs = await Promise.all(uploadPromises);
// HTML 파일 업로드 완료 대기
const uploadedHtmlDocs = await Promise.all(uploadPromises);
// HTML 문서와 PDF 문서 분리
const htmlDocuments = uploadedDocs.filter(doc =>
doc.html_path && doc.html_path !== null
);
// PDF 파일 처리 (실제 업로드는 하지 않고 매칭용으로만 보관)
const pdfDocs = await Promise.all(pdfUploadPromises);
const pdfDocuments = uploadedDocs.filter(doc =>
(doc.original_filename && doc.original_filename.toLowerCase().endsWith('.pdf')) ||
(doc.pdf_path && !doc.html_path)
);
// 업로드된 HTML 문서 정리
this.uploadedDocuments = uploadedHtmlDocs.map((doc, index) => ({
// 업로드된 HTML 문서들만 정리 (순서 조정용)
this.uploadedDocuments = htmlDocuments.map((doc, index) => ({
...doc,
display_order: index + 1,
matched_pdf_id: null,
file_type: 'html'
matched_pdf_id: null
}));
// PDF 파일 목록 (매칭용)
this.pdfFiles = pdfDocs;
// PDF 파일들을 매칭용으로 저장
this.pdfFiles = pdfDocuments;
console.log('🎉 모든 파일 업로드 완료!');
console.log('📄 HTML 문서:', this.uploadedDocuments.filter(doc => doc.file_type === 'html').length, '개');
console.log('📄 HTML 문서:', this.uploadedDocuments.length, '개');
console.log('📕 PDF 문서:', this.pdfFiles.length, '개');
// 3단계로 이동