feat: 완전한 웹 UI 구현 및 문서 처리 파이프라인 완성
✨ 새로운 기능: - FastAPI 기반 완전한 웹 UI 구현 - 반응형 디자인 (모바일/태블릿 지원) - 드래그앤드롭 파일 업로드 인터페이스 - 실시간 AI 챗봇 인터페이스 - 문서 관리 및 검색 시스템 - 진행률 표시 및 상태 알림 🎨 UI 구성: - 메인 대시보드: 서버 상태, 통계, 빠른 접근 - 파일 업로드: 드래그앤드롭, 처리 옵션, 진행률 - 문서 관리: 검색, 정렬, 미리보기, 다운로드 - AI 챗봇: 실시간 대화, 문서 기반 RAG, 빠른 질문 🔧 기술 스택: - FastAPI + Jinja2 템플릿 - 모던 CSS (그라디언트, 애니메이션) - Font Awesome 아이콘 - JavaScript (ES6+) 🚀 완성된 기능: - 파일 업로드 → 텍스트 추출 → 임베딩 → 번역 → HTML 생성 - 벡터 검색 및 RAG 기반 질의응답 - 다중 모델 지원 (기본/부스팅/영어 전용) - API 키 인증 및 CORS 설정 - NAS 연동 및 파일 내보내기
This commit is contained in:
87
static/js/main.js
Normal file
87
static/js/main.js
Normal file
@@ -0,0 +1,87 @@
|
||||
// 공통 JavaScript 기능들
|
||||
|
||||
// API 호출 헬퍼
|
||||
async function apiCall(url, options = {}) {
|
||||
const defaultOptions = {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
|
||||
const response = await fetch(url, { ...defaultOptions, ...options });
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// 파일 크기 포맷팅
|
||||
function formatFileSize(bytes) {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
const k = 1024;
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
// 날짜 포맷팅
|
||||
function formatDate(dateString) {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleString('ko-KR');
|
||||
}
|
||||
|
||||
// 토스트 알림
|
||||
function showToast(message, type = 'info') {
|
||||
const toast = document.createElement('div');
|
||||
toast.className = `alert alert-${type} toast`;
|
||||
toast.textContent = message;
|
||||
toast.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
min-width: 300px;
|
||||
animation: slideIn 0.3s ease;
|
||||
`;
|
||||
|
||||
document.body.appendChild(toast);
|
||||
|
||||
setTimeout(() => {
|
||||
toast.style.animation = 'slideOut 0.3s ease';
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(toast);
|
||||
}, 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// 로딩 상태 관리
|
||||
function setLoading(element, loading = true) {
|
||||
if (loading) {
|
||||
element.disabled = true;
|
||||
element.innerHTML = '<span class="spinner"></span> 처리 중...';
|
||||
} else {
|
||||
element.disabled = false;
|
||||
element.innerHTML = element.getAttribute('data-original-text') || '완료';
|
||||
}
|
||||
}
|
||||
|
||||
// 애니메이션 CSS 추가
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
@keyframes slideIn {
|
||||
from { transform: translateX(100%); opacity: 0; }
|
||||
to { transform: translateX(0); opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes slideOut {
|
||||
from { transform: translateX(0); opacity: 1; }
|
||||
to { transform: translateX(100%); opacity: 0; }
|
||||
}
|
||||
|
||||
.toast {
|
||||
animation: slideIn 0.3s ease;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
Reference in New Issue
Block a user