diff --git a/7th.zip b/7th.zip new file mode 100644 index 0000000..ef8cd9f Binary files /dev/null and b/7th.zip differ diff --git a/README.md b/README.md index d221f83..69a8688 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -# 글벗 (Geulbeot) v6.0 +# 글벗 (Geulbeot) v7.0 -**HWPX 템플릿 분석·저장·관리** +**UI 고도화 — 템플릿 관리·작성 방식·문서 유형 선택 UI** 다양한 형식의 자료(PDF·HWP·이미지·Excel 등)를 입력하면, AI가 RAG 파이프라인으로 분석한 뒤 선택한 문서 유형(기획서·보고서·발표자료 등)에 맞는 표준 HTML 문서를 자동 생성합니다. 생성된 문서는 웹 편집기에서 수정하고, HTML / PDF / HWP로 출력합니다. -v6에서는 HWPX 템플릿 관리 기능을 추가했습니다. -HWPX 파일을 업로드하면 XML을 파싱하여 폰트·색상·여백·표 구조·테두리 등을 자동 분석하고, -재사용 가능한 템플릿으로 저장합니다. +v7에서는 프론트엔드 UI를 고도화했습니다. +v6에서 백엔드로만 존재하던 템플릿 관리를 화면에서 직접 조작할 수 있게 되었고, +자료 활용 방식(형식 변경·재구성·신규 작성)과 문서 유형을 시각적으로 선택하는 UI가 추가되었습니다. --- @@ -20,17 +20,20 @@ HWPX 파일을 업로드하면 XML을 파싱하여 폰트·색상·여백·표 자료 입력 (파일/폴더) │ ▼ +작성 방식 선택 ─── 형식만 변경 / 내용 재구성 / 신규 작성 (v7 신규) + │ + ▼ RAG 파이프라인 (9단계) ─── 공통 처리 │ ▼ -문서 유형 선택 +문서 유형 선택 ─── UI 리스트 (v7 신규) ├─ 기획서 (기본) ├─ 보고서 (기본) ├─ 발표자료 (기본) └─ 사용자 등록 (확장 가능) │ ▼ -글벗 표준 HTML 생성 ◀── 템플릿 스타일 참조 (v6 신규) +글벗 표준 HTML 생성 ◀── 템플릿 스타일 참조 + 요소 선택 (v7 신규) │ ▼ 웹 편집기 (수기 편집 / AI 편집) @@ -48,11 +51,11 @@ RAG 파이프라인 (9단계) ─── 공통 처리 - OpenAI API — RAG 임베딩, 인덱싱, 텍스트 추출 - Gemini API — 보고서 콘텐츠·HTML 생성 - **Features**: - - 자료 입력 → 9단계 RAG 파이프라인 (파일 변환 → 추출 → 도메인 분석 → 청킹 → 임베딩 → 코퍼스 → 인덱싱 → 콘텐츠 생성 → HTML 조립) + - 자료 입력 → 9단계 RAG 파이프라인 - 문서 유형별 생성: 기획서 (Claude 3단계), 보고서 (Gemini 2단계) - AI 편집: 전체 수정 (`/refine`), 부분 수정 (`/refine-selection`) - - HWPX 템플릿 분석·저장·관리 (v6 신규) - - HWP 변환: 하이브리드 방식 — pyhwpx 기본 생성 → HWPX 스타일 주입 → 표 열 너비 수정 + - HWPX 템플릿 분석·저장·관리 + - HWP 변환: 하이브리드 방식 — pyhwpx → HWPX 스타일 주입 → 표 열 너비 수정 - PDF 변환: WeasyPrint 기반 ### 2. Frontend (순수 JavaScript) @@ -61,6 +64,9 @@ RAG 파이프라인 (9단계) ─── 공통 처리 - 웹 WYSIWYG 편집기 — 브라우저에서 생성된 문서 직접 수정 - 페이지 넘김·들여쓰기·정렬 등 서식 도구 - HTML / PDF / HWP 다운로드 + - **작성 방식 선택 탭 (v7 신규)**: 📄 형식만 변경 / 🔄 내용의 재구성 / ✨ 문서 참고 신규 작성 + - **문서 유형 선택 UI (v7 신규)**: 기획서·보고서 라디오 리스트 + 배지 스타일 + - **템플릿 관리 UI (v7 신규)**: 사이드바에서 템플릿 업로드·선택·삭제, 적용할 요소 체크박스 ### 3. 변환 엔진 (Converters) @@ -68,25 +74,23 @@ RAG 파이프라인 (9단계) ─── 공통 처리 - **분량 자동 판단**: 5,000자 기준 — 긴 문서는 전체 파이프라인, 짧은 문서는 축약 파이프라인 - **HWP 변환 (하이브리드 방식)**: HTML 분석 → pyhwpx 변환 → HWPX 스타일 주입 → 표 열 너비 수정 -### 4. 템플릿 관리 (v6 신규) +### 4. 템플릿 관리 - **HWPX 파싱**: 업로드된 HWPX를 압축 해제하여 header.xml + section*.xml 구조 분석 -- **자동 추출 항목**: - - 폰트 정보 (이름·크기·굵기·색상) - - 문단 스타일 (정렬·줄간격·들여쓰기·번호 체계) - - 표 구조 (열 너비·행 수·셀 병합·테두리 스타일·선 종류) - - 배경 (색상·이미지 채우기) - - 테두리 (ARGB 8자리 색상 정규화, NONE 제외) - - 페이지 설정 (여백·용지 크기) -- **CSS 자동 생성**: 분석된 스타일을 CSS로 변환하여 HTML 생성 시 참조 가능 -- **저장소**: `templates_store/` 디렉토리에 메타데이터(meta.json) + 원본 파일 + 분석 결과 저장 +- **자동 추출**: 폰트·문단·표·배경·테두리·페이지 설정 +- **CSS 자동 생성**: 분석된 스타일 → CSS 변환 +- **저장소**: `templates_store/` — meta.json + 원본 + 분석 결과 +- **UI 연동 (v7 신규)**: 사이드바에서 목록 조회·선택·삭제, 요소별 적용 체크박스 ### 5. 주요 시나리오 (Core Scenarios) 1. **기획서 생성**: 텍스트 또는 파일을 입력하면, RAG 분석 후 Claude API가 구조 추출 → 페이지 배치 계획 → 글벗 표준 HTML 기획서를 생성. 1~N페이지 옵션 지원 2. **보고서 생성**: 폴더 경로의 자료들을 RAG 파이프라인으로 분석하고, Gemini API가 섹션별 콘텐츠 초안 → 표지·목차·간지·별첨이 포함된 다페이지 HTML 보고서를 생성 -3. **AI 편집**: 생성된 문서를 웹 편집기에서 확인 후, 피드백으로 전체 또는 선택 부분을 AI가 수정 -4. **템플릿 등록 (v6 신규)**: HWPX 파일을 업로드하면 XML을 파싱하여 폰트·표·테두리·색상 등을 자동 분석하고, 재사용 가능한 템플릿으로 저장. 등록된 템플릿은 조회·삭제 가능 +3. **작성 방식 선택 (v7 신규)**: 업로드 자료를 어떻게 활용할지 3가지 모드 중 선택 + - 📄 **형식만 변경** — 원본 내용 유지, 글벗 양식으로만 변환 + - 🔄 **내용의 재구성** — 원본 기반으로 구조와 내용을 재구성 (기본값) + - ✨ **문서 참고 신규 작성** — 원본을 참고 자료로만 활용, 새로 작성 +4. **템플릿 적용**: 등록된 HWPX 템플릿을 선택하고, 적용할 요소(제목 스타일·표 스타일·색상 등)를 체크박스로 선택 5. **HWP 내보내기**: pyhwpx 변환 후 HWPX 스타일 주입 + 표 열 너비 정밀 수정 ### 프로세스 플로우 @@ -119,87 +123,18 @@ flowchart TD I --> J ``` -#### 문서 유형별 생성 → 편집 → 출력 - -```mermaid -flowchart TD - classDef decision fill:#fffde7,stroke:#f9a825,stroke-width:2px,color:#333 - classDef aiClaude fill:#fff3cd,stroke:#d97706,stroke-width:2px,color:#856404 - classDef aiGemini fill:#d6eaf8,stroke:#4285f4,stroke-width:2px,color:#1a4d8f - classDef editStyle fill:#fff3e0,stroke:#ef6c00,stroke-width:1.5px,color:#e65100 - classDef exportStyle fill:#f3e5f5,stroke:#7b1fa2,stroke-width:1.5px,color:#4a148c - classDef startEnd fill:#1a365d,stroke:#1a365d,color:#fff,stroke-width:2px - classDef planned fill:#f5f5f5,stroke:#999,stroke-width:1px,stroke-dasharray: 5 5,color:#999 - classDef newModule fill:#e0f2f1,stroke:#00695c,stroke-width:2px,color:#004d40 - - A(["📋 RAG 분석 결과"]):::startEnd - B{"문서 유형 선택"}:::decision - - C["기획서 생성\n구조추출→배치→HTML\n⚡ Claude API"]:::aiClaude - D["보고서 생성\n콘텐츠→HTML 조립\n⚡ Gemini API"]:::aiGemini - E["발표자료 생성\n예정"]:::planned - F["사용자 등록 유형\n확장 가능"]:::planned - - T["📋 템플릿 스타일 참조\ntemplates_store/\n(v6 신규)"]:::newModule - - G["글벗 표준 HTML\nA4·Navy·Noto Sans KR"]:::startEnd - - H{"편집 방식"}:::decision - I["웹 편집기\n수기 편집"]:::editStyle - J["AI 편집\n전체·부분 수정\n⚡ Claude API"]:::aiClaude - - K{"출력 형식"}:::decision - L["HTML / PDF"]:::exportStyle - M["HWP 변환 (하이브리드)\npyhwpx→스타일주입→표주입"]:::exportStyle - N["PPT 변환\n예정"]:::planned - O(["✅ 최종 산출물"]):::startEnd - - A --> B - B -->|"기획서"| C --> G - B -->|"보고서"| D --> G - B -->|"발표자료"| E -.-> G - B -->|"확장"| F -.-> G - - T -.->|"스타일 참조"| G - - G --> H - H -->|"수기"| I --> K - H -->|"AI"| J --> K - K -->|"웹/인쇄"| L --> O - K -->|"HWP"| M --> O - K -->|"PPT"| N -.-> O -``` - -#### 템플릿 분석 (v6 신규) - -```mermaid -flowchart LR - classDef process fill:#e8f4fd,stroke:#1a365d,stroke-width:1.5px,color:#1a365d - classDef newModule fill:#fff3e0,stroke:#ef6c00,stroke-width:2px,color:#e65100 - classDef dataStore fill:#e0f2f1,stroke:#00695c,stroke-width:1.5px,color:#004d40 - classDef startEnd fill:#1a365d,stroke:#1a365d,color:#fff,stroke-width:2px - - A(["📄 HWPX 업로드"]):::startEnd - B["압축 해제\nheader.xml\nsection*.xml"]:::process - C["XML 파싱\n폰트·표·테두리·색상\n페이지 설정"]:::newModule - D["CSS 자동 생성\n스타일 요약"]:::newModule - E[("📋 templates_store/\nmeta.json\n+ 분석 결과")]:::dataStore - - A --> B --> C --> D --> E -``` - --- -## 🔄 v5 → v6 변경사항 +## 🔄 v6 → v7 변경사항 -| 영역 | v5 | v6 | +| 영역 | v6 | v7 | |------|------|------| -| 템플릿 관리 | 없음 | **handlers/template/ 패키지 신규** | -| HWPX 분석 | 없음 | header.xml·section.xml 파싱 (폰트·표·테두리·배경·페이지) | -| CSS 자동 생성 | 없음 | 분석된 스타일 → CSS 변환 | -| 신규 API | — | `GET /templates` · `POST /analyze-template` · `DELETE /delete-template/` | -| 저장소 | — | `templates_store/` (meta.json + 원본 + 분석 결과) | -| AI 프롬프트 | — | `analyze_template.txt` — 구조 분석 보조 | +| 작성 방식 | 없음 (무조건 재구성) | **3가지 모드 UI**: 형식 변경 / 재구성 / 신규 작성 | +| 문서 유형 선택 | 기획서·보고서 구분 없이 탭 | **문서 유형 라디오 리스트** + 배지 스타일 | +| 템플릿 관리 UI | API만 존재 (화면 없음) | **사이드바 UI**: 목록·선택·삭제 + 요소별 체크박스 | +| 템플릿 업로드 | API 직접 호출 | **모달 UI**: 파일 선택 + 이름 입력 + 업로드 | +| index.html | 2,974줄 | 3,400줄 (+426) | +| Python | 변경 없음 | 변경 없음 | --- @@ -210,8 +145,8 @@ flowchart LR - **Phase 3**: 출력 — HTML/PDF 다운로드, HWP 변환 (🔧 기본 구현) - **Phase 4**: HWP/HWPX/HTML 매핑 — 스타일 분석·HWPX 생성·스타일 주입·표 주입 (🔧 기본 구현) - **Phase 5**: 문서 유형 분석·등록 — HWPX 업로드 → AI 구조 분석 → 유형 CRUD + 확장 (예정) -- **Phase 6**: HWPX 템플릿 관리 — 파싱·스타일 추출·CSS 생성·저장·조회·삭제 (🔧 기본 구현 · 현재 버전) -- **Phase 7**: UI 고도화 — 프론트 모듈화, 데모 모드, AI 편집 개선, 도메인 선택기 (예정) +- **Phase 6**: HWPX 템플릿 관리 — 파싱·스타일 추출·CSS 생성·저장·조회·삭제 (🔧 기본 구현) +- **Phase 7**: UI 고도화 — 작성 방식 선택, 문서 유형 UI, 템플릿 관리 UI (🔧 기본 구현 · 현재 버전) - **Phase 8**: 백엔드 재구조화 + 배포 — 패키지 정리, API 키 공통화, 로깅, Docker (예정) --- @@ -230,8 +165,8 @@ flowchart LR ```bash # 저장소 클론 및 설정 -git clone http://[Gitea주소]/kei/geulbeot-v6.git -cd geulbeot-v6 +git clone http://[Gitea주소]/kei/geulbeot-v7.git +cd geulbeot-v7 # 가상환경 python -m venv venv @@ -265,7 +200,7 @@ python app.py ## 📂 프로젝트 구조 ``` -geulbeot_6th/ +geulbeot_7th/ ├── app.py # Flask 웹 서버 — API 라우팅 ├── api_config.py # .env 환경변수 로더 │ @@ -273,36 +208,31 @@ geulbeot_6th/ │ ├── common.py # Claude API 호출, JSON/HTML 추출 │ ├── briefing/ # 기획서 처리 (구조추출 → 배치 → HTML) │ ├── report/ # 보고서 처리 (RAG 파이프라인 연동) -│ └── template/ # ★ v6 신규 — 템플릿 관리 -│ ├── processor.py # HWPX 파싱·분석·CSS 생성·CRUD -│ └── prompts/ -│ └── analyze_template.txt # AI 구조 분석 프롬프트 +│ └── template/ # 템플릿 관리 (HWPX 파싱·분석·CRUD) │ ├── converters/ # 변환 엔진 │ ├── pipeline/ # 9단계 RAG 파이프라인 -│ │ ├── router.py # 분량 판단 (5,000자 기준) -│ │ └── step1 ~ step9 # 변환→추출→분석→청킹→임베딩→코퍼스→인덱싱→콘텐츠→HTML │ ├── style_analyzer.py # HTML 요소 역할 분류 │ ├── hwpx_generator.py # HWPX 파일 직접 생성 │ ├── hwp_style_mapping.py # 역할 → HWP 스타일 매핑 │ ├── hwpx_style_injector.py # HWPX 커스텀 스타일 주입 │ ├── hwpx_table_injector.py # HWPX 표 열 너비 정밀 수정 -│ ├── html_to_hwp.py # 보고서 → HWP 변환 (하이브리드 워크플로우) +│ ├── html_to_hwp.py # 보고서 → HWP 변환 │ └── html_to_hwp_briefing.py # 기획서 → HWP 변환 │ -├── templates_store/ # ★ v6 신규 — 등록된 템플릿 저장소 +├── templates_store/ # 등록된 템플릿 저장소 │ ├── static/ │ ├── js/editor.js # 웹 WYSIWYG 편집기 │ └── css/editor.css # 편집기 스타일 ├── templates/ -│ ├── index.html # 메인 UI +│ ├── index.html # ★ v7 고도화 — 작성 방식·문서 유형·템플릿 UI │ └── hwp_guide.html # HWP 변환 가이드 │ ├── .env / .env.sample # API 키 관리 ├── .gitignore ├── requirements.txt -├── Procfile # 배포 설정 (Gunicorn) +├── Procfile └── README.md ``` @@ -326,7 +256,8 @@ geulbeot_6th/ - API 키 분산: 파이프라인 각 step에 개별 정의 (공통화 미완) - HWP 변환: Windows + pyhwpx + 한글 프로그램 필수 - 문서 유형: 기획서·보고서만 구현, 발표자료·사용자 등록 유형 미구현 -- 템플릿 → 문서 생성 연동: 아직 미연결 (분석·저장만 가능, 생성 시 자동 적용은 예정) +- 작성 방식: UI만 구현, 백엔드 로직 미연동 (모드별 프롬프트 분기 예정) +- 템플릿 → 문서 생성 연동: 아직 미연결 (선택·체크는 가능, 생성 시 자동 적용은 예정) - 레거시 잔존: prompts/ 디렉토리 --- @@ -335,9 +266,9 @@ geulbeot_6th/ | 영역 | 줄 수 | |------|-------| -| Python 전체 | 11,406 (+624) | -| 프론트엔드 (JS + CSS + HTML) | 3,859 | -| **합계** | **~15,300** | +| Python 전체 | 11,500 | +| 프론트엔드 (JS + CSS + HTML) | 4,904 (+1,045) | +| **합계** | **~16,400** | --- @@ -350,7 +281,8 @@ geulbeot_6th/ | v3 | 9단계 RAG 파이프라인 + HWP 변환 | | v4 | 코드 모듈화 (handlers 패키지) + 스타일 분석기·HWPX 생성기 | | v5 | HWPX 스타일 주입 + 표 열 너비 정밀 변환 | -| **v6** | **HWPX 템플릿 분석·저장·관리** | +| v6 | HWPX 템플릿 분석·저장·관리 | +| **v7** | **UI 고도화 — 작성 방식·문서 유형·템플릿 관리 UI** | --- diff --git a/templates/index.html b/templates/index.html index 6a61fba..150d13a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -303,6 +303,103 @@ animation: spin 0.8s linear infinite; } + /* 템플릿 리스트 */ + .template-list { + display: flex; + flex-direction: column; + gap: 4px; + margin-bottom: 10px; + } + + .template-item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + background: var(--ui-panel); + border: 1px solid var(--ui-border); + border-radius: 6px; + cursor: pointer; + transition: all 0.15s; + } + + .template-item:hover { + background: var(--ui-hover); + border-color: var(--ui-dim); + } + + .template-item.selected { + border-color: var(--ui-accent); + background: rgba(0, 200, 83, 0.1); + } + + .template-item input[type="radio"] { + accent-color: var(--ui-accent); + } + + .template-item .label { + flex: 1; + font-size: 13px; + font-weight: 500; + } + + .template-item .delete-btn { + opacity: 0; + background: transparent; + border: none; + color: var(--ui-dim); + cursor: pointer; + font-size: 14px; + } + + .template-item:hover .delete-btn { + opacity: 1; + } + + .template-item .delete-btn:hover { + color: var(--ui-error); + } + + /* 템플릿 요소 체크박스 */ + .template-elements { + margin-top: 12px; + padding: 12px; + background: var(--ui-bg); + border: 1px solid var(--ui-border); + border-radius: 6px; + } + + .elements-title { + font-size: 10px; + font-weight: 600; + color: var(--ui-dim); + margin-bottom: 8px; + text-transform: uppercase; + } + + .elements-list { + display: flex; + flex-direction: column; + gap: 6px; + } + + .element-checkbox { + display: flex; + align-items: center; + gap: 8px; + font-size: 12px; + color: var(--ui-text); + cursor: pointer; + } + + .element-checkbox input[type="checkbox"] { + accent-color: var(--ui-accent); + } + + .element-checkbox .element-icon { + font-size: 14px; + } + /* 사용자 템플릿 프리뷰 */ .user-template-preview { display: none; @@ -494,7 +591,7 @@ flex-direction: column; gap: 15px; } - + .section-title { font-size: 11px; font-weight: 700; @@ -503,7 +600,7 @@ letter-spacing: 0.5px; margin-bottom: 8px; } - + /* 참고 파일 확인 */ .file-check-box { background: var(--ui-panel); @@ -572,7 +669,72 @@ border-color: var(--ui-accent); color: var(--ui-accent); } - + + /* 작성 방식 선택 (가로 탭) */ + .write-mode-box { + background: var(--ui-panel); + border: 1px solid var(--ui-border); + border-radius: 8px; + padding: 10px; + } + + .write-mode-tabs { + display: flex; + gap: 4px; + } + + .write-mode-tab { + flex: 1; + padding: 10px 8px; + border: 1px solid var(--ui-border); + border-radius: 6px; + background: transparent; + cursor: pointer; + transition: all 0.15s; + text-align: center; + } + + .write-mode-tab:hover { + background: var(--ui-hover); + border-color: var(--ui-dim); + } + + .write-mode-tab.selected { + background: rgba(0, 200, 83, 0.15); + border-color: var(--ui-accent); + } + + .write-mode-tab input[type="radio"] { + display: none; + } + + .write-mode-icon { + font-size: 16px; + margin-bottom: 4px; + } + + .write-mode-label { + font-size: 11px; + font-weight: 600; + color: var(--ui-text); + } + + .write-mode-tab.selected .write-mode-label { + color: var(--ui-accent); + } + + .write-mode-notice { + margin-top: 8px; + padding: 6px 8px; + background: rgba(255, 152, 0, 0.1); + border-radius: 4px; + font-size: 10px; + color: var(--ui-warning); + display: flex; + align-items: center; + gap: 5px; + } + /* 진행 상태 */ .step-list { display: flex; @@ -756,6 +918,45 @@ align-items: center; gap: 12px; } + + /* 목차 확인 액션바 */ + .toc-action-bar { + background: var(--ui-panel); + border-top: 1px solid var(--ui-border); + padding: 12px 20px; + display: none; + align-items: center; + justify-content: flex-end; + gap: 12px; + } + .toc-action-bar.show { display: flex; } + + .toc-action-btn { + padding: 10px 24px; + border-radius: 6px; + border: none; + font-size: 13px; + font-weight: 600; + cursor: pointer; + transition: all 0.15s; + } + .toc-action-btn.primary { + background: var(--ui-accent); + color: #003300; + } + .toc-action-btn.primary:hover { + background: #00e676; + } + .toc-action-btn.secondary { + background: var(--ui-hover); + color: var(--ui-text); + border: 1px solid var(--ui-border); + } + .toc-action-btn.secondary:hover { + border-color: var(--ui-accent); + color: var(--ui-accent); + } + .feedback-bar.show { display: flex; } .feedback-input { @@ -1437,14 +1638,14 @@ - + + +
+ + +
+
@@ -1577,9 +1807,8 @@
문서 설정
-
- +
문서 유형
@@ -1587,65 +1816,13 @@
📋 기획서 - - -
-
-
- -
-
-
-
-
-
-
-
-
- -
[첨부]
-
-
-
-
-
-
-
-
기획서 (보고자료)
-
임원보고용 정형화된 1~2페이지 문서
-
-
📄 1p 본문만 / 1p+1p첨부 / 1p+np첨부
-
🎨 Navy 양식 (A4 인쇄 최적화)
-
✍️ 개조식 자동 변환
-
-
+
-
- - 📄 보고서 - -
-
-
-
-
-
-
-
-
-
-
-
-
보고서 (HWP)
-
RAG 기반 장문 보고서 → HWPX 출력
-
-
🏷️ AI 스타일 자동 태깅
-
📝 대제목/중제목/소제목/본문
-
한글에서 스타일 일괄 변경
-
-
+
+ + 📄 보고서
@@ -1653,73 +1830,35 @@ 📊 발표자료 준비중 - -
-
-
-
제목
-
-
-
-
-
본문
-
-
-
-
-
-
결론
-
-
-
-
발표자료 (PPT)
-
프레젠테이션 형식 슬라이드
-
-
📊 슬라이드 자동 구성
-
🎯 핵심 내용 추출
-
🖼️ 도식화 자동 생성
-
-
+ + +
- - - - - + + +
- +
-
페이지 구성
- +
- +
- +
- - -
-
요청사항
- -
@@ -1746,33 +1885,55 @@
- - - - - -
-
요청사항
- -
+ - - - - - + +
+
템플릿
+
+ +
+ + 📄 기본 템플릿 +
+ + +
+
+ + + + + + +
+ + +
+
요청사항
+ +
+ + - + @@ -1837,9 +1998,14 @@ let generatedHTML = ''; let currentDocType = 'briefing'; let currentPageOption = '2'; + let currentWriteMode = 'restructure'; // format, restructure, new let currentZoom = 100; let folderPath = ''; let referenceLinks = []; + let customDocTypes = []; // [{id, name, structure, created_at}, ...] + let currentTemplate = 'default'; + let templateElements = {}; // {templateId: {cover: true, divider: false, ...}} + // ===== AI 부분 수정 관련 ===== let selectedText = ''; @@ -2069,6 +2235,121 @@ document.getElementById('briefingOptions').style.display = isBriefing ? 'block' : 'none'; document.getElementById('reportOptions').style.display = isReport ? 'block' : 'none'; document.getElementById('templateOptions').style.display = isTemplate ? 'block' : 'none'; + const generateBtnText = document.getElementById('generateBtnText'); + + if (type === 'report' || type === 'presentation') { + generateBtnText.textContent = '📋 목차 확인하기'; + } else { + generateBtnText.textContent = '🚀 생성하기'; + } + } + + // ===== 문서 유형 추가 모달 ===== + function openDocTypeModal() { + document.getElementById('docTypeModal').classList.add('active'); + } + + function closeDocTypeModal() { + document.getElementById('docTypeModal').classList.remove('active'); + } + + // ===== 템플릿 선택 ===== + function selectTemplate(templateId) { + currentTemplate = templateId; + + // 모든 템플릿 선택 해제 + document.querySelectorAll('.template-item').forEach(item => { + item.classList.remove('selected'); + const radio = item.querySelector('input[type="radio"]'); + if (radio) radio.checked = false; + }); + + // 선택한 템플릿 활성화 + const selectedItem = document.querySelector(`.template-item[data-template="${templateId}"]`); + if (selectedItem) { + selectedItem.classList.add('selected'); + const radio = selectedItem.querySelector('input[type="radio"]'); + if (radio) radio.checked = true; + } + + // 템플릿 요소 옵션 표시/숨김 + const elementsPanel = document.getElementById('templateElementOptions'); + if (templateId === 'default') { + elementsPanel.style.display = 'none'; + } else { + showTemplateElements(templateId); + elementsPanel.style.display = 'block'; + } + + console.log('템플릿 선택:', templateId); + } + + // ===== 템플릿 요소 표시 (AI 분석 결과) ===== + function showTemplateElements(templateId) { + const template = userTemplates.find(t => t.id === templateId); + if (!template || !template.elements) return; + + const container = document.querySelector('#templateElementOptions .elements-list'); + container.innerHTML = template.elements.map(el => ` + + `).join(''); + } + + // ===== 템플릿 요소 토글 ===== + function toggleTemplateElement(templateId, elementType, checked) { + if (!templateElements[templateId]) { + templateElements[templateId] = {}; + } + templateElements[templateId][elementType] = checked; + console.log('템플릿 요소 변경:', templateId, elementType, checked); + } + + // ===== 사용자 템플릿 렌더링 (수정) ===== + function renderUserTemplates() { + const container = document.getElementById('userTemplatesListNew'); + + if (userTemplates.length === 0) { + container.innerHTML = ''; + return; + } + + container.innerHTML = userTemplates.map(tpl => ` +
+ + 📑 ${tpl.name} + +
+ `).join(''); + } + + + + + // ===== 작성 방식 선택 ===== + function selectWriteMode(mode) { + currentWriteMode = mode; + + // 모든 탭 선택 해제 + document.querySelectorAll('.write-mode-tab').forEach(tab => { + tab.classList.remove('selected'); + tab.querySelector('input[type="radio"]').checked = false; + }); + + // 선택한 탭 활성화 + const selectedTab = document.querySelector(`.write-mode-tab input[value="${mode}"]`); + if (selectedTab) { + selectedTab.checked = true; + selectedTab.closest('.write-mode-tab').classList.add('selected'); + } + + console.log('작성 방식 선택:', mode); } // ===== HWP 추출 ===== @@ -2351,7 +2632,6 @@ // 생성 버튼 활성화 (HTML 입력이 있거나, 폴더/링크가 있으면) const canGenerate = hasHtml || hasFolder || hasLinks; - document.getElementById('generateBtnSide').disabled = !canGenerate; document.getElementById('generateBtn').disabled = !canGenerate; // Step 0 상태 업데이트 @@ -2503,11 +2783,118 @@ async function generate() { if (currentDocType === 'briefing') { await generateBriefing(); - } else if (currentDocType === 'report') { - await generateReport(); + } else if (currentDocType === 'report' || currentDocType === 'presentation') { + await generateDraft(); // ← 목차 확인 플로우 } else if (currentDocType.startsWith('template_')) { - // ⭐ 사용자 템플릿: 보고서와 동일하게 처리 + await generateBriefing(); // 템플릿은 바로 생성 + } + } + + + // ===== 초안/목차 생성 (보고서/발표자료용) ===== + async function generateDraft() { + if (!folderPath && !inputContent && referenceLinks.length === 0) { + alert('먼저 폴더 위치, 참고 링크, 또는 HTML을 입력해주세요.'); + return; + } + + const btn = document.getElementById('generateBtn'); + const btnText = document.getElementById('generateBtnText'); + const spinner = document.getElementById('generateSpinner'); + + btn.disabled = true; + btnText.textContent = '분석 중...'; + spinner.style.display = 'block'; + resetSteps(); + updateStep(0, 'done'); + setStatus('목차 생성 중...', true); + + try { + // Step 1~7 실행 + for (let i = 1; i <= 7; i++) { + updateStep(i, 'running'); + await new Promise(r => setTimeout(r, 500)); + updateStep(i, 'done'); + } + + // 목차 테이블 표시 + document.getElementById('placeholder').style.display = 'none'; + const frame = document.getElementById('previewFrame'); + frame.classList.remove('active'); + + let tocContainer = document.getElementById('tocContainer'); + if (!tocContainer) { + tocContainer = document.createElement('div'); + tocContainer.id = 'tocContainer'; + document.getElementById('a4Preview').appendChild(tocContainer); + } + + const tableContent = document.getElementById('embedded-table-context'); + if (tableContent) { + tocContainer.innerHTML = tableContent.innerHTML; + tocContainer.style.display = 'block'; + } + + // 액션바 표시 + document.getElementById('tocActionBar').classList.add('show'); + document.getElementById('feedbackBar').classList.remove('show'); + + setStatus('목차 생성 완료 - 확인 후 승인해주세요', true); + + } catch (error) { + alert('목차 생성 오류: ' + error.message); + setStatus('오류 발생', false); + } finally { + btn.disabled = false; + btnText.textContent = '📋 목차 확인하기'; + spinner.style.display = 'none'; + } + } + + // ===== 목차 편집 ===== + function editToc() { + const tocContainer = document.getElementById('tocContainer'); + if (tocContainer) { + tocContainer.contentEditable = true; + tocContainer.style.outline = '2px solid var(--ui-accent)'; + } + setStatus('목차 편집 모드 - 직접 수정 가능합니다', true); + } + + // ===== 목차 승인 & 최종 생성 ===== + async function approveToc() { + const btn = document.getElementById('approveBtn'); + btn.disabled = true; + btn.textContent = '⏳ 생성 중...'; + + document.getElementById('tocActionBar').classList.remove('show'); + setStatus('최종 문서 생성 중...', true); + + // 목차 컨테이너 숨기기 + const tocContainer = document.getElementById('tocContainer'); + if (tocContainer) { + tocContainer.style.display = 'none'; + tocContainer.contentEditable = false; + } + + try { + // Step 8~9 실행 + for (let i = 8; i <= 9; i++) { + updateStep(i, 'running'); + await new Promise(r => setTimeout(r, 800)); + updateStep(i, 'done'); + } + + // TODO: 실제 API 호출 (generateReport 로직 활용) + // 지금은 generateReport() 호출 await generateReport(); + + } catch (error) { + alert('문서 생성 오류: ' + error.message); + setStatus('오류 발생', false); + } finally { + btn.disabled = false; + btn.textContent = '✅ 승인 & 생성하기'; } } @@ -2522,10 +2909,8 @@ const btn = document.getElementById('generateBtn'); const btnText = document.getElementById('generateBtnText'); const spinner = document.getElementById('generateSpinner'); - const sideBtn = document.getElementById('generateBtnSide'); btn.disabled = true; - sideBtn.disabled = true; btnText.textContent = '생성 중...'; spinner.style.display = 'block'; resetSteps(); @@ -2588,7 +2973,6 @@ } } finally { btn.disabled = false; - sideBtn.disabled = false; btnText.textContent = '🚀 생성하기'; spinner.style.display = 'none'; } @@ -2971,5 +3355,47 @@ + + + + +
+
+
+
📁 문서 유형 추가
+ +
+ +
+ + +
+ +
+ +
+
📄
+
샘플 문서를 업로드하면 AI가 구조를 분석합니다
+
HWPX, HWP, PDF, DOCX 지원
+
+
+ + +
+
\ No newline at end of file