Files

782 lines
38 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>글벗 - AI 문서 자동화 시스템</title>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700;900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/static/css/editor.css">
<link rel="stylesheet" href="/static/css/main.css">
<style>
/* 목차 애니메이션 */
.toc-display-area {
padding: 20px 32px;
overflow-y: auto;
max-height: calc(100vh - 200px);
}
.toc-anim-item {
padding: 14px 18px;
background: var(--ui-surface, #2a2f38);
border: 1px solid var(--ui-border, #363a43);
border-left: 3px solid var(--ui-accent, #4fc3f7);
border-radius: 8px;
margin-bottom: 10px;
}
.toc-anim-num {
font-size: 12px;
color: var(--ui-accent, #4fc3f7);
font-weight: 600;
margin-bottom: 4px;
}
.toc-anim-title {
font-size: 14px;
font-weight: 600;
color: var(--ui-text, #e8eaed);
margin-bottom: 6px;
}
.toc-anim-guide {
font-size: 12px;
color: var(--ui-dim, #9aa0a6);
line-height: 1.6;
}
.toc-anim-keywords {
display: flex;
gap: 6px;
flex-wrap: wrap;
margin-top: 8px;
}
.toc-anim-keyword {
font-size: 11px;
padding: 2px 8px;
background: rgba(79, 195, 247, 0.1);
color: var(--ui-accent, #4fc3f7);
border-radius: 4px;
}
.toc-anim-contents {
margin-top: 8px;
padding: 8px 10px;
background: rgba(255,255,255,0.03);
border-radius: 4px;
border: 1px solid rgba(79, 195, 247, 0.08);
}
.toc-anim-content-item {
font-size: 11px;
color: var(--ui-dim, #9aa0a6);
line-height: 1.7;
padding-left: 4px;
}
.toc-loading {
display: flex;
gap: 6px;
justify-content: center;
padding: 24px;
}
.toc-loading-dot {
width: 8px;
height: 8px;
background: var(--ui-accent, #4fc3f7);
border-radius: 50%;
animation: tocDotPulse 1.2s infinite;
}
.toc-loading-dot:nth-child(2) { animation-delay: 0.2s; }
.toc-loading-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes tocDotPulse {
0%, 60%, 100% { opacity: 0.3; transform: scale(0.8); }
30% { opacity: 1; transform: scale(1); }
}
/* 생성 진행률 */
.gen-progress-area {
padding: 16px 32px;
}
.gen-progress-header {
font-size: 13px;
font-weight: 600;
color: var(--ui-text, #e8eaed);
margin-bottom: 10px;
}
.gen-progress-bar-wrap {
height: 4px;
background: var(--ui-border, #363a43);
border-radius: 2px;
overflow: hidden;
}
.gen-progress-bar {
height: 100%;
background: linear-gradient(90deg, var(--ui-accent, #4fc3f7), #66bb6a);
border-radius: 2px;
transition: width 0.5s ease;
}
.gen-progress-text {
font-size: 12px;
color: var(--ui-dim, #9aa0a6);
margin-top: 8px;
}
/* AI 수정 버튼 활성 상태 */
#aiEditToolbarBtn.has-selection {
background: rgba(79, 195, 247, 0.15);
color: var(--ui-accent, #4fc3f7);
border-color: var(--ui-accent, #4fc3f7);
}
/* ===== 도메인 선택 ===== */
.domain-select-box {
background: var(--ui-surface, #2a2f38);
border: 1px solid var(--ui-border, #363a43);
border-radius: 8px; padding: 10px 12px; cursor: pointer;
}
.domain-select-box:hover { border-color: var(--ui-accent, #4fc3f7); }
.domain-display-text { font-size: 12px; color: var(--ui-text); margin-top: 6px; }
.domain-display-text.auto { color: var(--ui-dim, #9aa0a6); font-style: italic; }
.domain-display-text.selected { color: var(--ui-accent, #4fc3f7); }
#domainModal {
position: fixed; top:0; left:0; right:0; bottom:0;
background: rgba(0,0,0,0.65); display: none;
align-items: center; justify-content: center; z-index: 10000;
}
.domain-modal-content {
background: var(--ui-bg, #1e2228); border: 1px solid var(--ui-border);
border-radius: 14px; width: 560px; max-height: 80vh;
display: flex; flex-direction: column; box-shadow: 0 20px 60px rgba(0,0,0,0.4);
}
.domain-modal-header { display: flex; align-items: center; justify-content: space-between; padding: 18px 24px; border-bottom: 1px solid var(--ui-border); }
.domain-modal-title { font-size: 16px; font-weight: 700; color: var(--ui-text); }
.domain-modal-close { background: none; border: none; color: var(--ui-dim); font-size: 20px; cursor: pointer; }
.domain-modal-body { padding: 16px 24px; overflow-y: auto; flex: 1; }
.domain-modal-desc { font-size: 13px; color: var(--ui-dim); margin-bottom: 16px; line-height: 1.6; }
.domain-category { margin-bottom: 10px; }
.domain-cat-label {
display: flex; align-items: center; gap: 10px;
padding: 12px 14px; background: var(--ui-surface, #2a2f38);
border: 1px solid var(--ui-border); border-radius: 8px; cursor: pointer;
}
.domain-cat-label:hover { border-color: var(--ui-accent); }
.domain-cat-label.checked { background: rgba(79,195,247,0.08); border-color: var(--ui-accent); }
.domain-cat-label input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--ui-accent); }
.domain-cat-icon { font-size: 20px; }
.domain-cat-text { flex: 1; }
.domain-cat-name { display: block; font-size: 14px; font-weight: 600; color: var(--ui-text); }
.domain-cat-desc { display: block; font-size: 11px; color: var(--ui-dim); margin-top: 2px; }
.domain-cat-expand { font-size: 10px; color: var(--ui-dim); transition: transform 0.2s; }
.domain-cat-expand.open { transform: rotate(180deg); }
.domain-sub-panel { padding: 10px 14px 10px 40px; border-left: 2px solid var(--ui-accent); margin-left: 20px; margin-top: 4px; }
.domain-sub-group { margin-bottom: 10px; }
.domain-sub-group-label { font-size: 11px; font-weight: 600; color: var(--ui-dim); margin-bottom: 6px; }
.domain-sub-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.domain-chip {
display: inline-flex; align-items: center; gap: 4px;
padding: 5px 12px; background: var(--ui-surface);
border: 1px solid var(--ui-border); border-radius: 20px;
font-size: 12px; color: var(--ui-text); cursor: pointer;
}
.domain-chip:hover { border-color: var(--ui-accent); }
.domain-chip.selected { background: rgba(79,195,247,0.15); border-color: var(--ui-accent); color: var(--ui-accent); }
.domain-chip input[type="checkbox"] { display: none; }
.domain-modal-footer { padding: 14px 24px; border-top: 1px solid var(--ui-border); display: flex; align-items: center; justify-content: space-between; }
.domain-summary-text { font-size: 12px; color: var(--ui-accent); flex: 1; }
.domain-summary-text.empty { color: var(--ui-dim); font-style: italic; }
.domain-modal-actions { display: flex; gap: 8px; }
.domain-btn { padding: 8px 18px; border-radius: 6px; font-size: 13px; font-weight: 600; cursor: pointer; border: 1px solid var(--ui-border); background: var(--ui-surface); color: var(--ui-text); }
.domain-btn.primary { background: var(--ui-accent); color: #000; border-color: var(--ui-accent); }
</style>
</head>
<body>
<!-- 상단 툴바 -->
<div class="toolbar">
<div class="toolbar-logo">📝 글벗</div>
<div class="toolbar-spacer"></div>
<button class="toolbar-btn" id="editModeBtn" onclick="toggleEditMode()">✏️ 편집하기</button>
<button class="toolbar-btn" id="aiEditToolbarBtn" onclick="triggerAiEdit()" title="AI 수정 (텍스트를 먼저 선택하세요)">🤖 AI 수정</button>
<div class="toolbar-divider"></div>
<select class="zoom-select" id="zoomSelect" onchange="setZoom(this.value)">
<option value="50">50%</option>
<option value="75">75%</option>
<option value="100" selected>100%</option>
<option value="125">125%</option>
<option value="150">150%</option>
</select>
<div class="toolbar-divider"></div>
<button class="toolbar-btn" onclick="exportHwp()">📄 HWP 추출</button>
<button class="toolbar-btn" onclick="saveHtml()">💾 HTML 저장</button>
<button class="toolbar-btn" onclick="saveHtml()">📊 PPT 저장</button>
<button class="toolbar-btn" onclick="printDoc()">🖨️ PDF/인쇄</button>
</div>
<!-- 메인 앱 -->
<div class="app">
<!-- 좌측 사이드바: 입력 -->
<div class="sidebar">
<div class="sidebar-header">
<div class="sidebar-title">문서 업로드</div>
<button class="sidebar-btn" onclick="openFolderModal()">
<span class="icon">📁</span>
<span>폴더 위치</span>
</button>
<button class="sidebar-btn" onclick="openLinkModal()">
<span class="icon">🔗</span>
<span>외부 링크</span>
</button>
<button class="sidebar-btn" onclick="openHtmlModal()">
<span class="icon">📋</span>
<span>HTML 붙여넣기</span>
</button>
</div>
<div class="sidebar-content">
<!-- 참고 파일 확인 -->
<div>
<div class="section-title">업로드 파일 검토</div>
<div class="file-check-box">
<div class="file-path empty" id="folderPathDisplay">폴더 경로가 설정되지 않음</div>
<div class="file-check-row">
<span class="file-check-label">전체 파일</span>
<span class="file-check-value" id="totalCount">0개</span>
</div>
<div class="file-check-row">
<span class="file-check-label">확인 (변환 가능)</span>
<span class="file-check-value ok" id="okCount">0개 ✓</span>
</div>
<div class="file-check-row">
<span class="file-check-label">미확인</span>
<span class="file-check-value warn" id="unknownCount" onclick="toggleUnknownFiles()">0개</span>
</div>
<div class="unknown-files" id="unknownFilesBox">
<div id="unknownFilesList"></div>
<button class="open-folder-btn" onclick="openFolder()">📂 폴더 열기</button>
</div>
<div class="file-check-row" style="border-top: 1px solid var(--ui-border); margin-top: 8px; padding-top: 8px;">
<span class="file-check-label">참고 링크</span>
<span class="file-check-value" id="linkCount">0개</span>
</div>
<div class="file-check-row">
<span class="file-check-label">HTML 입력</span>
<span class="file-check-value" id="htmlInputStatus">없음</span>
</div>
</div>
</div>
<!-- 도메인 지식 선택 -->
<div id="domainSection" style="display:none;">
<div class="section-title">도메인 지식 선택</div>
<div class="domain-select-box" onclick="openDomainModal()">
<div style="display:flex; justify-content:space-between; font-size:12px; color:var(--ui-dim);">
<span>📚 업로드 자료의 성격을 선택해주세요</span>
<span></span>
</div>
<div class="domain-display-text auto" id="domainDisplayText">자동 분석 (AI 판단)</div>
</div>
</div>
<!-- 작성 방식 -->
<div>
<div class="section-title">업로드 자료 활용 범위</div>
<div class="write-mode-box">
<div class="write-mode-tabs">
<label class="write-mode-tab" onclick="selectWriteMode('format')">
<input type="radio" name="writeMode" value="format">
<div class="write-mode-icon">📄</div>
<div class="write-mode-label">형식만 <br>변경</div>
</label>
<label class="write-mode-tab selected" onclick="selectWriteMode('restructure')">
<input type="radio" name="writeMode" value="restructure" checked>
<div class="write-mode-icon">🔄</div>
<div class="write-mode-label">내용의<br>재구성</div>
</label>
<label class="write-mode-tab" onclick="selectWriteMode('new')">
<input type="radio" name="writeMode" value="new">
<div class="write-mode-icon"></div>
<div class="write-mode-label">문서 참고 <br> 신규 작성</div>
</label>
</div>
<div class="write-mode-notice">
<span>⚠️</span>
<span>문서 유형에 적합하지 않은 콘텐츠 업로드시,<br> 자동 재구성 및 신규 콘텐츠 작성 </span>
</div>
</div>
</div>
<!-- 진행 상태 -->
<div>
<div class="section-title">진행 상태</div>
<div class="step-list" id="stepList">
<div class="step-item pending" data-step="0">
<span class="status"></span>
<span>참고 파일 확인</span>
</div>
<div class="step-divider"></div>
<div class="step-item pending" data-step="1">
<span class="status"></span>
<span>Step 1: 파일 변환</span>
</div>
<div class="step-item pending" data-step="2">
<span class="status"></span>
<span>Step 2: 텍스트 추출</span>
</div>
<div class="step-item pending" data-step="3">
<span class="status"></span>
<span>Step 3: 도메인 분석</span>
</div>
<div class="step-item pending" data-step="4">
<span class="status"></span>
<span>Step 4: 청킹/요약</span>
</div>
<div class="step-item pending" data-step="5">
<span class="status"></span>
<span>Step 5: RAG 구축</span>
</div>
<div class="step-item pending" data-step="6">
<span class="status"></span>
<span>Step 6: Corpus 생성</span>
</div>
<div class="step-item pending" data-step="7">
<span class="status"></span>
<span>Step 7: 목차 구성</span>
</div>
<div class="step-divider"></div>
<div class="step-item pending" data-step="8">
<span class="status"></span>
<span>Step 8: 콘텐츠 생성</span>
</div>
<div class="step-item pending" data-step="9">
<span class="status"></span>
<span>Step 9: HTML 변환</span>
</div>
</div>
</div>
</div>
</div>
<!-- 가운데 뷰어 -->
<div class="main">
<div class="viewer" id="viewer">
<div class="a4-wrapper" id="a4Wrapper">
<div class="a4-preview" id="a4Preview">
<iframe id="previewFrame" class="preview-iframe"></iframe>
<div class="placeholder" id="placeholder">
<div class="icon">📄</div>
<div class="text">HTML을 입력하고 생성하세요</div>
<div class="sub-text">좌측에서 HTML 붙여넣기 또는 파일 업로드</div>
</div>
</div>
</div>
</div>
<!-- 목차 애니메이션 표시 영역 -->
<div class="toc-display-area" id="tocDisplayArea" style="display:none;"></div>
<!-- 생성 진행률 -->
<div class="gen-progress-area" id="genProgressArea" style="display:none;">
<div class="gen-progress-header">📝 문서 생성 중...</div>
<div class="gen-progress-bar-wrap">
<div class="gen-progress-bar" id="genProgressBar" style="width:0%"></div>
</div>
<div class="gen-progress-text" id="genProgressText">준비 중...</div>
</div>
<!-- 목차 확인 액션바 -->
<div class="toc-action-bar" id="tocActionBar">
<button class="toc-action-btn secondary" onclick="editToc()">✏️ 편집</button>
<button class="toc-action-btn primary" id="approveBtn" onclick="approveToc()">✅ 승인 & 생성하기</button>
</div>
<!-- 하단 피드백 바 -->
<div class="feedback-bar" id="feedbackBar">
<input type="text" class="feedback-input" id="feedbackInput" placeholder="수정 요청사항을 입력하세요... (예: 5 Step을 첨부로 이동해줘)">
<button class="feedback-btn primary" id="feedbackBtn" onclick="submitFeedback()">
<span id="feedbackBtnText">🔄 수정 반영</span>
<span id="feedbackSpinner" class="spinner" style="display:none;"></span>
</button>
<button class="feedback-btn secondary" onclick="regenerate()">🗑️ 다시 생성</button>
</div>
</div>
<!-- 우측 패널: 옵션 -->
<div class="right-panel">
<div class="panel-header">
<span class="panel-title">문서 설정</span>
</div>
<div class="panel-body">
<!-- ===== 문서 유형 (동적 로드) ===== -->
<div class="option-section">
<div class="option-title">문서 유형</div>
<div class="doc-type-list loading" id="docTypeList">
<!-- API에서 동적으로 로드 -->
</div>
<!-- 문서 유형 추가 버튼 -->
<button class="add-template-btn" onclick="openDocTypeModal()">+ 문서 유형 추가</button>
</div>
<!-- ===== 문서 유형별 옵션 (동적) ===== -->
<div id="docTypeOptionsContainer">
<!-- selectDocType() 호출 시 동적으로 렌더링 -->
</div>
<!-- ===== 템플릿 선택 ===== -->
<div class="option-section">
<div class="option-title">템플릿</div>
<div class="template-list">
<div class="template-item selected" data-template="default" onclick="selectTemplate('default')">
<input type="radio" name="template" checked>
<span class="label">📄 기본 템플릿</span>
</div>
<div id="userTemplatesListNew"></div>
</div>
<button class="add-template-btn" onclick="openTemplateModal()">+ 템플릿 추가</button>
<div id="templateElementOptions" class="template-elements" style="display:none;">
<div class="elements-title">적용 요소</div>
<div class="elements-list"></div>
</div>
</div>
<!-- ===== 요청사항 ===== -->
<div class="option-section">
<div class="option-title">요청사항</div>
<textarea class="request-textarea" id="globalInstructionInput"
placeholder="예: 표를 더 상세하게&#10;예: 전문 용어 풀어서 설명"></textarea>
</div>
<!-- ===== 생성 버튼 ===== -->
<button class="generate-btn" id="generateBtn" onclick="generate()" disabled>
<span id="generateBtnText">🚀 생성하기</span>
<div class="loading-spinner" id="generateSpinner" style="display:none;"></div>
</button>
</div>
</div>
</div>
<!-- 상태바 -->
<div class="status-bar">
<div class="status-left">
<span class="status-dot" id="statusDot"></span>
<span id="statusMessage">준비됨</span>
</div>
<div id="statusRight">글벗 Light v2.1</div>
</div>
<!-- HTML 입력 모달 -->
<div class="modal-overlay" id="htmlModal">
<div class="modal">
<div class="modal-header">📋 HTML 붙여넣기</div>
<div class="modal-body">
<textarea class="modal-textarea" id="htmlContent" placeholder="HTML 코드를 붙여넣으세요..."></textarea>
</div>
<div class="modal-footer">
<button class="modal-btn" onclick="closeHtmlModal()">취소</button>
<button class="modal-btn primary" onclick="submitHtml()">확인</button>
</div>
</div>
</div>
<!-- 폴더 모달 -->
<div class="modal-overlay" id="folderModal">
<div class="modal">
<div class="modal-header">📁 폴더 위치 입력</div>
<div class="modal-body">
<input type="text" id="folderPath" class="modal-input" placeholder="C:\Users\...\Documents\참고자료" style="width:100%; padding:12px; border-radius:6px; border:1px solid var(--ui-border); background:var(--ui-bg); color:var(--ui-text); font-size:13px;">
<p style="margin-top:10px; font-size:11px; color:var(--ui-dim);">* 로컬 폴더 경로를 입력하세요. (Engine 실행 필요)</p>
</div>
<div class="modal-footer">
<button class="modal-btn" onclick="closeFolderModal()">취소</button>
<button class="modal-btn primary" onclick="submitFolder()">확인</button>
</div>
</div>
</div>
<!-- 참고 링크 모달 -->
<div class="modal-overlay" id="linkModal">
<div class="modal">
<div class="modal-header">🔗 참고 링크 입력</div>
<div class="modal-body">
<div id="linkInputList">
<input type="text" class="link-input" placeholder="https://..." style="width:100%; padding:10px; border-radius:6px; border:1px solid var(--ui-border); background:var(--ui-bg); color:var(--ui-text); font-size:12px; margin-bottom:8px;">
</div>
<button onclick="addLinkInput()" style="padding:8px 12px; border-radius:4px; border:1px dashed var(--ui-border); background:transparent; color:var(--ui-dim); font-size:12px; cursor:pointer; width:100%;">+ 링크 추가</button>
</div>
<div class="modal-footer">
<button class="modal-btn" onclick="closeLinkModal()">취소</button>
<button class="modal-btn primary" onclick="submitLinks()">확인</button>
</div>
</div>
</div>
<!-- AI 부분 수정 팝업 -->
<div class="ai-edit-popup" id="aiEditPopup">
<button class="ai-edit-close" onclick="closeAiEditPopup()"></button>
<div class="ai-edit-header">🤖 AI로 수정하기</div>
<div class="ai-edit-selected">선택된 텍스트:</div>
<div class="ai-edit-selected-text" id="aiEditSelectedText"></div>
<textarea class="ai-edit-input" id="aiEditInput" rows="3" placeholder="예: 한 줄로 요약해줘&#10;예: 표 형태로 만들어줘"></textarea>
<button class="ai-edit-btn" onclick="submitAiEdit()">✨ 수정하기</button>
</div>
<!-- 도메인 선택 모달 -->
<div id="domainModal">
<div class="domain-modal-content">
<div class="domain-modal-header">
<div class="domain-modal-title">📚 도메인 지식 선택</div>
<button class="domain-modal-close" onclick="closeDomainModal()"></button>
</div>
<div class="domain-modal-body">
<div class="domain-modal-desc">
업로드 자료의 분야를 선택하면 해당 전문 지식이 AI에 전달됩니다.<br>
선택하지 않으면 AI가 자동으로 분야를 판단합니다.
</div>
<div id="domainCategoryList"></div>
</div>
<div class="domain-modal-footer">
<div class="domain-summary-text empty" id="domainSummaryText">선택된 도메인이 없습니다.</div>
<div class="domain-modal-actions">
<button class="domain-btn" onclick="clearAllDomains()">초기화</button>
<button class="domain-btn primary" onclick="submitDomainSelection()">확인</button>
</div>
</div>
</div>
</div>
<!-- 템플릿 추가 모달 -->
<div class="template-modal" id="templateModal">
<div class="template-modal-content">
<div class="template-modal-header">
<div class="template-modal-title">📁 템플릿 추가</div>
<button class="template-modal-close" onclick="closeTemplateModal()"></button>
</div>
<div class="template-input-group">
<label class="template-input-label">템플릿 이름</label>
<input type="text" class="template-name-input" id="templateNameInput"
placeholder="예: 걸포4지구 교통영향평가">
</div>
<div class="template-input-group">
<label class="template-input-label">템플릿 파일</label>
<div class="template-dropzone" id="templateDropzone" onclick="document.getElementById('templateFileInput').click()">
<div class="template-dropzone-icon">📄</div>
<div class="template-dropzone-text">파일을 드래그하거나 클릭하여 선택</div>
<div class="template-dropzone-hint">HWPX, HWP, PDF 지원</div>
</div>
<input type="file" id="templateFileInput" accept=".hwpx,.hwp,.pdf" style="display:none" onchange="handleTemplateFile(this)">
<div class="template-dropzone-file" id="templateFileInfo">
<span class="filename" id="templateFileName"></span>
<span class="remove" onclick="removeTemplateFile()"></span>
</div>
</div>
<button class="template-submit-btn" id="templateSubmitBtn" onclick="submitTemplate()" disabled>
<span class="spinner" id="templateSpinner"></span>
<span id="templateSubmitText">✨ 분석 및 추가</span>
</button>
</div>
</div>
<!-- 문서 유형 추가 모달 -->
<div class="modal-overlay" id="addDocTypeModal">
<div class="modal" style="min-width: 500px; max-width: 550px;">
<div class="modal-header">
<span id="addDocTypeModalTitle">📄 문서 유형 추가</span>
</div>
<!-- Step 1: 입력 -->
<div id="docTypeStep1" class="modal-body">
<div style="margin-bottom: 16px;">
<label style="font-size: 12px; font-weight: 600; color: var(--ui-dim); display: block; margin-bottom: 8px;">문서 유형 이름</label>
<input type="text" id="newDocTypeName" placeholder="예: 제안서, 회의록..." style="width:100%; padding:10px; border-radius:6px; border:1px solid var(--ui-border); background:var(--ui-bg); color:var(--ui-text); font-size:13px;">
</div>
<div style="margin-bottom: 16px;">
<label style="font-size: 12px; font-weight: 600; color: var(--ui-dim); display: block; margin-bottom: 8px;">설명 (선택)</label>
<input type="text" id="newDocTypeDesc" placeholder="문서 유형에 대한 간단한 설명" style="width:100%; padding:10px; border-radius:6px; border:1px solid var(--ui-border); background:var(--ui-bg); color:var(--ui-text); font-size:13px;">
</div>
<div style="margin-bottom: 16px;">
<label style="font-size: 12px; font-weight: 600; color: var(--ui-dim); display: block; margin-bottom: 8px;">샘플 문서 (HWPX 권장)</label>
<input type="file" id="newDocTypeFile" accept=".hwpx,.hwp,.pdf" style="width:100%; padding:10px; border-radius:6px; border:1px solid var(--ui-border); background:var(--ui-bg); color:var(--ui-text); font-size:12px;">
<p style="margin-top:8px; font-size:11px; color:var(--ui-dim);">샘플 문서를 분석하여 스타일과 구조를 추출합니다</p>
</div>
</div>
<!-- Step 2: 분석 진행 -->
<div id="docTypeStep2" class="modal-body" style="display:none;">
<div class="analysis-progress">
<div id="analysisSteps"></div>
<div class="progress-bar-container">
<div id="analysisProgressBar" class="progress-bar" style="width: 0%"></div>
</div>
<p id="analysisProgressText" style="text-align: center; margin-top: 12px; font-size: 12px; color: var(--ui-dim);">준비 중...</p>
</div>
</div>
<!-- Step 3: 결과 확인 -->
<div id="docTypeStep3" class="modal-body" style="display:none;">
<div class="analysis-result">
<h4 style="margin-bottom: 16px; color: var(--ui-accent);">📋 분석 완료</h4>
<div id="analysisResultSummary" class="result-summary"></div>
<div id="analysisResultToc" class="result-toc" style="margin-top: 16px;"></div>
</div>
</div>
<div class="modal-footer" id="docTypeModalFooter">
<button class="modal-btn" onclick="closeAddDocTypeModal()">취소</button>
<button class="modal-btn primary" id="docTypeActionBtn" onclick="startDocTypeAnalysis()">분석 시작</button>
</div>
</div>
</div>
<script>
// ===== 상태 변수 =====
let inputContent = '';
var generatedHTML = '';
var currentDocType = 'briefing';
let currentWriteMode = 'restructure';
let currentZoom = 100;
let folderPath = '';
let referenceLinks = [];
let currentTemplate = 'default';
let templateElements = {};
let analysisResult = null;
// ===== 문서 유형 데이터 =====
let docTypes = []; // 전체 문서 유형 (default + user)
let selectedDocTypeFile = null;
// ===== 템플릿 관련 =====
let userTemplates = [];
let selectedTemplateFile = null;
// ===== AI 부분 수정 =====
let selectedText = '';
let selectedRange = null;
// ===== 활용 범위 선택 =====
function selectWriteMode(mode) {
currentWriteMode = mode;
document.querySelectorAll('.write-mode-tab').forEach(tab => {
const radio = tab.querySelector('input[type="radio"]');
if (radio && radio.value === mode) {
tab.classList.add('selected');
radio.checked = true;
} else {
tab.classList.remove('selected');
}
});
updateDomainSectionVisibility();
}
function updateDomainSectionVisibility() {
const section = document.getElementById('domainSection');
if (!section) return;
const hasFolder = folderPath && folderPath.trim() !== '';
const hasLinks = referenceLinks && referenceLinks.length > 0;
section.style.display = (hasFolder || hasLinks) ? 'block' : 'none';
}
// ===== 썸네일 템플릿 =====
const thumbnailTemplates = {
briefing: `
<div class="page">
<div class="page-header"></div>
<div class="page-title"></div>
<div class="page-divider"></div>
<div class="page-lead"></div>
<div class="page-body"></div>
<div class="page-bottom"></div>
</div>
<div class="page">
<div class="page-header"></div>
<div class="page-attach">첨부</div>
<div class="page-body"></div>
<div class="page-body"></div>
<div class="page-bottom"></div>
</div>
`,
report: `
<div class="line h1"></div>
<div class="line body"></div>
<div class="line body" style="width:90%"></div>
<div class="line h2"></div>
<div class="line body" style="width:85%"></div>
`,
ppt: `
<div class="slide"><div class="slide-title">TITLE</div><div class="slide-body"></div></div>
<div class="slide"><div class="slide-title">CONTENT</div><div class="slide-body"></div></div>
`,
custom: `
<div class="line h1"></div>
<div class="line body"></div>
<div class="line h2"></div>
<div class="line body"></div>
`
};
// ===== 초기화 =====
document.addEventListener('DOMContentLoaded', function() {
setStatus('로딩 중...', false);
if (typeof loadDocTypes === 'function') loadDocTypes();
if (typeof loadUserTemplates === 'function') loadUserTemplates();
// 드롭존 이벤트
const dropzones = ['templateDropzone', 'docTypeDropzone'];
dropzones.forEach(id => {
const dropzone = document.getElementById(id);
if (dropzone) {
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, (e) => {
e.preventDefault();
e.stopPropagation();
});
});
['dragenter', 'dragover'].forEach(eventName => {
dropzone.addEventListener(eventName, () => dropzone.classList.add('dragover'));
});
['dragleave', 'drop'].forEach(eventName => {
dropzone.addEventListener(eventName, () => dropzone.classList.remove('dragover'));
});
}
});
// 템플릿 입력 이벤트
const templateNameInput = document.getElementById('templateNameInput');
if (templateNameInput) {
if (typeof updateTemplateSubmitBtn === 'function') {
templateNameInput.addEventListener('input', updateTemplateSubmitBtn);
}
}
setStatus('준비됨', true);
});
// Enter 키로 피드백 제출
document.getElementById('feedbackInput').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
submitFeedback();
}
});
</script>
<script src="/static/js/ui.js"></script>
<script src="/static/js/doc_type.js"></script>
<script src="/static/js/template.js"></script>
<script src="/static/js/modals.js"></script>
<script src="/static/js/generator.js"></script>
<script src="/static/js/demo_mode.js"></script>
<script src="/static/js/export.js"></script>
<script src="/static/js/ai_edit.js"></script>
<script src="/static/js/editor.js"></script>
<script src="/static/js/domain_selector.js"></script>
</body>
</html>