/** * 방화셔터 견적 시스템 - 웹 기획서/스토리보드 PPTX 생성 * script.md 인터뷰 내용 기반 IA 및 화면 설계 */ const PptxGenJS = require('pptxgenjs'); const fs = require('fs'); const path = require('path'); // 색상 정의 (# 없이) const colors = { primary: '0d9488', // Teal secondary: '1e293b', // Slate 800 accent: '95C11F', // 라임 그린 (Description용) warning: 'f59e0b', // 경고 danger: 'dc2626', // 위험 white: 'FFFFFF', lightGray: 'f1f5f9', darkGray: '64748b', black: '1a1a1a', wireframeBg: 'f8fafc', wireframeBorder: 'e2e8f0' }; // 프레젠테이션 생성 const pptx = new PptxGenJS(); // 레이아웃 설정 (16:9) pptx.defineLayout({ name: 'CUSTOM_16x9', width: 10, height: 5.625 }); pptx.layout = 'CUSTOM_16x9'; // 메타데이터 pptx.title = '방화셔터 견적 시스템 - 웹 기획서'; pptx.subject = '시스템 기획 및 UI/UX 설계'; pptx.author = 'SAM'; pptx.company = 'SAM'; // ======================================== // 슬라이드 1: 표지 // ======================================== function createCoverSlide() { const slide = pptx.addSlide(); slide.background = { color: colors.secondary }; // 상단 악센트 라인 slide.addShape('rect', { x: 0, y: 0, w: 10, h: 0.1, fill: { color: colors.primary } }); // SAM 로고 slide.addShape('rect', { x: 0.5, y: 0.4, w: 1.2, h: 0.5, fill: { color: colors.primary } }); slide.addText('SAM', { x: 0.5, y: 0.4, w: 1.2, h: 0.5, fontSize: 16, bold: true, color: colors.white, align: 'center', valign: 'middle' }); // 메인 제목 slide.addText('방화셔터 견적 시스템', { x: 0.5, y: 1.8, w: 9, h: 0.8, fontSize: 40, bold: true, color: colors.white, align: 'center' }); // 부제목 slide.addText('웹 기획서 및 스토리보드', { x: 0.5, y: 2.6, w: 9, h: 0.5, fontSize: 22, color: colors.primary, align: 'center' }); // 버전 정보 slide.addText('Version D1.0', { x: 0.5, y: 3.3, w: 9, h: 0.3, fontSize: 14, color: colors.darkGray, align: 'center' }); // 하단 정보 slide.addText('2024.10.24 | IT 혁신팀', { x: 0.5, y: 5, w: 9, h: 0.3, fontSize: 12, color: colors.darkGray, align: 'center' }); console.log('✅ 슬라이드 1: 표지 생성 완료'); } // ======================================== // 슬라이드 2: Document History // ======================================== function createHistorySlide() { const slide = pptx.addSlide(); slide.background = { color: colors.white }; // 헤더 slide.addShape('rect', { x: 0, y: 0, w: 10, h: 0.7, fill: { color: colors.secondary } }); slide.addText('Document History', { x: 0.5, y: 0.15, w: 5, h: 0.4, fontSize: 20, bold: true, color: colors.white }); // 히스토리 테이블 const historyData = [ ['날짜', '버전', '주요 내용', '상세 내용', '비고'], ['2024.10.24', 'D1.0', '초안 작성', '방화셔터 견적 시스템 기획서 초안 작성\n- IA 설계\n- 화면 설계', ''], ['', '', '', '', ''], ['', '', '', '', ''] ]; slide.addTable(historyData, { x: 0.5, y: 1.2, w: 9, h: 2.5, fontSize: 10, color: colors.secondary, border: { pt: 0.5, color: colors.darkGray }, colW: [1.2, 0.8, 1.5, 4, 1.5], align: 'center', valign: 'middle' }); console.log('✅ 슬라이드 2: Document History 생성 완료'); } // ======================================== // 슬라이드 3: 목차 // ======================================== function createTOCSlide() { const slide = pptx.addSlide(); slide.background = { color: colors.white }; // 헤더 slide.addShape('rect', { x: 0, y: 0, w: 10, h: 0.7, fill: { color: colors.secondary } }); slide.addText('목차 (Table of Contents)', { x: 0.5, y: 0.15, w: 5, h: 0.4, fontSize: 20, bold: true, color: colors.white }); const tocItems = [ { num: '01', title: '프로젝트 개요', desc: '시스템 목적 및 범위' }, { num: '02', title: '메뉴 구조 (IA)', desc: 'Information Architecture' }, { num: '03', title: '견적 입력 화면', desc: '셔터 타입, 규격, 옵션 선택' }, { num: '04', title: '견적 계산 화면', desc: '단가 계산 및 부가비용' }, { num: '05', title: '견적서 미리보기', desc: 'PPT 양식 프리뷰' }, { num: '06', title: '견적서 관리', desc: '목록 조회 및 이력 관리' } ]; tocItems.forEach((item, idx) => { const y = 1.1 + idx * 0.7; // 번호 박스 slide.addShape('rect', { x: 0.8, y: y, w: 0.6, h: 0.5, fill: { color: colors.primary } }); slide.addText(item.num, { x: 0.8, y: y, w: 0.6, h: 0.5, fontSize: 14, bold: true, color: colors.white, align: 'center', valign: 'middle' }); // 제목 slide.addText(item.title, { x: 1.6, y: y, w: 3, h: 0.5, fontSize: 14, bold: true, color: colors.secondary, valign: 'middle' }); // 설명 slide.addText(item.desc, { x: 4.8, y: y, w: 4, h: 0.5, fontSize: 11, color: colors.darkGray, valign: 'middle' }); }); console.log('✅ 슬라이드 3: 목차 생성 완료'); } // ======================================== // 슬라이드 4: 프로젝트 개요 // ======================================== function createOverviewSlide() { const slide = pptx.addSlide(); slide.background = { color: colors.white }; // 헤더 slide.addShape('rect', { x: 0, y: 0, w: 10, h: 0.7, fill: { color: colors.secondary } }); slide.addText('01. 프로젝트 개요', { x: 0.5, y: 0.15, w: 5, h: 0.4, fontSize: 20, bold: true, color: colors.white }); // 목적 slide.addText('프로젝트 목적', { x: 0.5, y: 1, w: 4, h: 0.4, fontSize: 14, bold: true, color: colors.secondary }); slide.addShape('rect', { x: 0.5, y: 1.4, w: 4.3, h: 1.8, fill: { color: colors.lightGray } }); slide.addText([ { text: '현장 영업사원의 전화 견적 요청을\n', options: { fontSize: 11 } }, { text: 'AI 기반으로 자동화', options: { fontSize: 12, bold: true, color: colors.primary } }, { text: '하여\n엑셀 정리 → PPT 견적서 생성\n과정을 시스템화', options: { fontSize: 11 } } ], { x: 0.7, y: 1.5, w: 4, h: 1.6, valign: 'top' }); // 주요 기능 slide.addText('주요 기능', { x: 5.2, y: 1, w: 4, h: 0.4, fontSize: 14, bold: true, color: colors.secondary }); const features = [ '셔터 타입 선택 (철재/스크린/하향식)', '규격 입력 → 면적 자동 계산', '모터 사양 자동 선택', '지역/층고별 설치/운반비 가산', '할인율 적용 및 PPT 자동 생성' ]; features.forEach((feat, idx) => { slide.addText('✓ ' + feat, { x: 5.2, y: 1.4 + idx * 0.35, w: 4.3, h: 0.35, fontSize: 10, color: colors.secondary }); }); // 기대 효과 slide.addText('기대 효과', { x: 0.5, y: 3.5, w: 9, h: 0.4, fontSize: 14, bold: true, color: colors.secondary }); const effects = [ { icon: '⏱️', title: '시간 단축', desc: '견적서 작성 시간 80% 감소' }, { icon: '✅', title: '정확성 향상', desc: '계산 오류 제로화' }, { icon: '📊', title: '표준화', desc: 'PPT 양식 통일' } ]; effects.forEach((eff, idx) => { const x = 0.5 + idx * 3.1; slide.addShape('rect', { x: x, y: 3.9, w: 2.9, h: 1.4, fill: { color: colors.lightGray }, line: { color: colors.primary, width: 1 } }); slide.addText(eff.icon, { x: x, y: 4, w: 2.9, h: 0.5, fontSize: 24, align: 'center' }); slide.addText(eff.title, { x: x, y: 4.5, w: 2.9, h: 0.35, fontSize: 11, bold: true, color: colors.secondary, align: 'center' }); slide.addText(eff.desc, { x: x, y: 4.85, w: 2.9, h: 0.35, fontSize: 9, color: colors.darkGray, align: 'center' }); }); console.log('✅ 슬라이드 4: 프로젝트 개요 생성 완료'); } // ======================================== // 슬라이드 5: 메뉴 구조 (IA) // ======================================== function createIASlide() { const slide = pptx.addSlide(); slide.background = { color: colors.white }; // 헤더 slide.addShape('rect', { x: 0, y: 0, w: 10, h: 0.7, fill: { color: colors.secondary } }); slide.addText('02. 메뉴 구조 (Information Architecture)', { x: 0.5, y: 0.15, w: 6, h: 0.4, fontSize: 20, bold: true, color: colors.white }); // 루트 노드 slide.addShape('rect', { x: 4, y: 1, w: 2, h: 0.6, fill: { color: colors.secondary } }); slide.addText('견적 시스템', { x: 4, y: 1, w: 2, h: 0.6, fontSize: 12, bold: true, color: colors.white, align: 'center', valign: 'middle' }); // 연결선 (세로) slide.addShape('line', { x: 5, y: 1.6, w: 0, h: 0.4, line: { color: colors.darkGray, width: 1 } }); // 연결선 (가로) slide.addShape('line', { x: 1.5, y: 2, w: 7, h: 0, line: { color: colors.darkGray, width: 1 } }); // 1차 메뉴 const level1 = [ { x: 0.5, title: '견적 입력', children: ['셔터 타입 선택', '규격 입력', '옵션 선택'] }, { x: 2.8, title: '견적 계산', children: ['단가 계산', '모터 선택', '부가비용'] }, { x: 5.1, title: '견적서 생성', children: ['미리보기', 'PPT 다운로드', '이메일 전송'] }, { x: 7.4, title: '견적 관리', children: ['목록 조회', '이력 관리', '통계'] } ]; level1.forEach((menu, idx) => { // 세로 연결선 slide.addShape('line', { x: menu.x + 1.1, y: 2, w: 0, h: 0.3, line: { color: colors.darkGray, width: 1 } }); // 1차 메뉴 박스 slide.addShape('rect', { x: menu.x, y: 2.3, w: 2.2, h: 0.5, fill: { color: colors.primary } }); slide.addText(menu.title, { x: menu.x, y: 2.3, w: 2.2, h: 0.5, fontSize: 11, bold: true, color: colors.white, align: 'center', valign: 'middle' }); // 2차 메뉴 menu.children.forEach((child, cIdx) => { const y = 3 + cIdx * 0.45; slide.addShape('rect', { x: menu.x, y: y, w: 2.2, h: 0.4, fill: { color: colors.lightGray }, line: { color: colors.wireframeBorder, width: 0.5 } }); slide.addText(child, { x: menu.x, y: y, w: 2.2, h: 0.4, fontSize: 9, color: colors.secondary, align: 'center', valign: 'middle' }); }); }); // 범례 slide.addText('※ 견적서 유효기간 15일 명시 필수', { x: 0.5, y: 5.2, w: 5, h: 0.3, fontSize: 9, color: colors.danger, bold: true }); console.log('✅ 슬라이드 5: 메뉴 구조 (IA) 생성 완료'); } // ======================================== // 슬라이드 6-9: 상세 화면 설계 (스토리보드) // ======================================== function createStoryboardSlide(screenInfo) { const slide = pptx.addSlide(); slide.background = { color: colors.white }; // 헤더 정보 테이블 const headerData = [ ['Task Name', screenInfo.taskName, 'Ver.', 'D1.0', 'Page', screenInfo.page], ['Route', screenInfo.route, 'Screen Name', screenInfo.screenName, 'Screen ID', screenInfo.screenId] ]; slide.addTable(headerData, { x: 0.2, y: 0.1, w: 9.6, h: 0.5, fontSize: 8, color: colors.secondary, border: { pt: 0.5, color: colors.darkGray }, fill: { color: colors.lightGray }, colW: [0.8, 2.5, 0.8, 2.5, 0.8, 2.2] }); // 와이어프레임 영역 (좌측) slide.addShape('rect', { x: 0.2, y: 0.7, w: 6.8, h: 4.75, fill: { color: colors.wireframeBg }, line: { color: colors.wireframeBorder, width: 1 } }); // 와이어프레임 헤더 slide.addShape('rect', { x: 0.3, y: 0.8, w: 6.6, h: 0.4, fill: { color: colors.secondary } }); slide.addText('SAM 견적 시스템', { x: 0.4, y: 0.8, w: 2, h: 0.4, fontSize: 10, bold: true, color: colors.white, valign: 'middle' }); // 와이어프레임 내용 (화면별 다르게) screenInfo.wireframeElements.forEach(el => { if (el.type === 'rect') { slide.addShape('rect', { x: el.x, y: el.y, w: el.w, h: el.h, fill: { color: el.fill || colors.white }, line: { color: colors.wireframeBorder, width: 0.5 } }); } if (el.text) { slide.addText(el.text, { x: el.x, y: el.y, w: el.w, h: el.h, fontSize: el.fontSize || 8, color: el.color || colors.secondary, align: el.align || 'center', valign: 'middle', bold: el.bold || false }); } }); // Description 영역 (우측) slide.addShape('rect', { x: 7.1, y: 0.7, w: 2.7, h: 4.75, fill: { color: colors.black } }); // Description 헤더 slide.addShape('rect', { x: 7.2, y: 0.8, w: 2.5, h: 0.35, fill: { color: colors.accent } }); slide.addText('Description', { x: 7.2, y: 0.8, w: 2.5, h: 0.35, fontSize: 9, bold: true, color: colors.white, align: 'center', valign: 'middle' }); // Description 항목 screenInfo.descriptions.forEach((desc, idx) => { const y = 1.25 + idx * 0.85; // 번호 원 slide.addShape('ellipse', { x: 7.25, y: y, w: 0.25, h: 0.25, fill: { color: colors.accent } }); slide.addText(String(idx + 1), { x: 7.25, y: y, w: 0.25, h: 0.25, fontSize: 7, bold: true, color: colors.white, align: 'center', valign: 'middle' }); // 제목 slide.addText(desc.title, { x: 7.55, y: y, w: 2.1, h: 0.25, fontSize: 8, bold: true, color: colors.white }); // 설명 slide.addText(desc.content, { x: 7.25, y: y + 0.28, w: 2.4, h: 0.5, fontSize: 7, color: colors.darkGray }); }); console.log(`✅ 슬라이드 ${screenInfo.page}: ${screenInfo.screenName} 생성 완료`); } // ======================================== // 메인 실행 // ======================================== async function main() { console.log('🚀 방화셔터 견적 시스템 - 웹 기획서 PPTX 생성 시작\n'); try { // 기본 슬라이드 createCoverSlide(); createHistorySlide(); createTOCSlide(); createOverviewSlide(); createIASlide(); // 스토리보드 슬라이드들 const screens = [ { page: '6', taskName: '견적 입력', route: '/estimate/input', screenName: '견적 입력 화면', screenId: 'EST_INPUT_001', wireframeElements: [ // 사이드바 { type: 'rect', x: 0.3, y: 1.3, w: 1.2, h: 4, fill: colors.lightGray }, { type: 'rect', x: 0.35, y: 1.4, w: 1.1, h: 0.3, fill: colors.primary, text: '견적 입력', fontSize: 7, color: colors.white, bold: true }, { type: 'rect', x: 0.35, y: 1.75, w: 1.1, h: 0.25, text: '견적 계산', fontSize: 7 }, { type: 'rect', x: 0.35, y: 2.05, w: 1.1, h: 0.25, text: '견적서 생성', fontSize: 7 }, { type: 'rect', x: 0.35, y: 2.35, w: 1.1, h: 0.25, text: '견적 관리', fontSize: 7 }, // 메인 콘텐츠 { type: 'rect', x: 1.6, y: 1.3, w: 5.3, h: 0.4, text: '셔터 타입 선택', fontSize: 10, bold: true, align: 'left' }, // 셔터 타입 카드 { type: 'rect', x: 1.6, y: 1.8, w: 1.6, h: 1.2, fill: colors.lightGray }, { type: 'rect', x: 1.6, y: 1.8, w: 1.6, h: 0.3, fill: colors.primary, text: '철재 방화셔터', fontSize: 7, color: colors.white }, { type: 'rect', x: 1.6, y: 2.15, w: 1.6, h: 0.8, text: '85,000원/㎡', fontSize: 9 }, { type: 'rect', x: 3.3, y: 1.8, w: 1.6, h: 1.2, fill: colors.lightGray }, { type: 'rect', x: 3.3, y: 1.8, w: 1.6, h: 0.3, fill: colors.secondary, text: '스크린 셔터', fontSize: 7, color: colors.white }, { type: 'rect', x: 5, y: 1.8, w: 1.6, h: 1.2, fill: colors.lightGray }, { type: 'rect', x: 5, y: 1.8, w: 1.6, h: 0.3, fill: colors.secondary, text: '하향식 스크린', fontSize: 7, color: colors.white }, // 규격 입력 { type: 'rect', x: 1.6, y: 3.2, w: 5.3, h: 0.3, text: '규격 입력 (W x H)', fontSize: 10, bold: true, align: 'left' }, { type: 'rect', x: 1.6, y: 3.6, w: 2.4, h: 0.4, fill: colors.white, text: '가로 (m)', fontSize: 8, align: 'left' }, { type: 'rect', x: 4.2, y: 3.6, w: 2.4, h: 0.4, fill: colors.white, text: '높이 (m)', fontSize: 8, align: 'left' }, // 수량 { type: 'rect', x: 1.6, y: 4.2, w: 2.4, h: 0.4, fill: colors.white, text: '수량', fontSize: 8, align: 'left' }, // 다음 버튼 { type: 'rect', x: 5.4, y: 4.9, w: 1.4, h: 0.4, fill: colors.primary, text: '다음 단계', fontSize: 9, color: colors.white } ], descriptions: [ { title: '셔터 타입 선택', content: '철재(85,000/㎡), 스크린(단가 변동), 하향식 스크린 중 선택' }, { title: '규격 입력', content: '가로(W) × 높이(H) 미터 단위로 입력, 면적 자동 계산' }, { title: '수량 입력', content: '동일 규격 셔터 수량 입력 (1개소 이상)' }, { title: '입력 검증', content: '필수 항목 미입력 시 경고 표시, 다음 단계 진행 불가' } ] }, { page: '7', taskName: '견적 계산', route: '/estimate/calculate', screenName: '견적 계산 화면', screenId: 'EST_CALC_001', wireframeElements: [ // 사이드바 { type: 'rect', x: 0.3, y: 1.3, w: 1.2, h: 4, fill: colors.lightGray }, { type: 'rect', x: 0.35, y: 1.4, w: 1.1, h: 0.25, text: '견적 입력', fontSize: 7 }, { type: 'rect', x: 0.35, y: 1.7, w: 1.1, h: 0.3, fill: colors.primary, text: '견적 계산', fontSize: 7, color: colors.white, bold: true }, // 모터 선택 { type: 'rect', x: 1.6, y: 1.3, w: 5.3, h: 0.3, text: '모터 사양 선택', fontSize: 10, bold: true, align: 'left' }, { type: 'rect', x: 1.6, y: 1.7, w: 1.5, h: 0.8, fill: colors.lightGray }, { type: 'rect', x: 1.6, y: 1.7, w: 1.5, h: 0.25, text: '400kg', fontSize: 8, bold: true }, { type: 'rect', x: 1.6, y: 2, w: 1.5, h: 0.45, text: '450,000원', fontSize: 9 }, { type: 'rect', x: 3.2, y: 1.7, w: 1.5, h: 0.8, fill: colors.primary }, { type: 'rect', x: 3.2, y: 1.7, w: 1.5, h: 0.25, text: '600kg', fontSize: 8, bold: true, color: colors.white }, { type: 'rect', x: 3.2, y: 2, w: 1.5, h: 0.45, text: '650,000원', fontSize: 9, color: colors.white }, { type: 'rect', x: 4.8, y: 1.7, w: 1.5, h: 0.8, fill: colors.lightGray }, { type: 'rect', x: 4.8, y: 1.7, w: 1.5, h: 0.25, text: '1000kg', fontSize: 8, bold: true }, // 부가비용 { type: 'rect', x: 1.6, y: 2.7, w: 5.3, h: 0.3, text: '부가 비용', fontSize: 10, bold: true, align: 'left' }, { type: 'rect', x: 1.6, y: 3.1, w: 5.3, h: 0.35, fill: colors.lightGray, text: '기본 설치비: 300,000원/개소', fontSize: 8, align: 'left' }, { type: 'rect', x: 1.6, y: 3.5, w: 5.3, h: 0.35, fill: colors.lightGray, text: '고소작업비 (5m 이상): 250,000원/일', fontSize: 8, align: 'left' }, { type: 'rect', x: 1.6, y: 3.9, w: 5.3, h: 0.35, fill: colors.lightGray, text: '운반비: 서울/경기 무료, 지방 150,000~300,000원', fontSize: 8, align: 'left' }, // 합계 { type: 'rect', x: 1.6, y: 4.5, w: 5.3, h: 0.7, fill: colors.secondary }, { type: 'rect', x: 1.6, y: 4.5, w: 5.3, h: 0.35, text: '예상 견적 금액', fontSize: 9, color: colors.white, align: 'left' }, { type: 'rect', x: 1.6, y: 4.85, w: 5.3, h: 0.35, text: '₩ 23,450,000', fontSize: 14, color: colors.white, bold: true } ], descriptions: [ { title: '모터 자동 선택', content: '셔터 무게 기준 자동 추천, 수동 변경 가능' }, { title: '기본 설치비', content: '1개소당 30만원, 수량에 따라 자동 계산' }, { title: '고소작업비', content: '층고 5m 이상 시 렌탈비 25만원/일 추가' }, { title: '운반비', content: '서울/경기 무료, 지방 거리별 15~30만원 청구' } ] }, { page: '8', taskName: '견적서 생성', route: '/estimate/preview', screenName: '견적서 미리보기', screenId: 'EST_PREVIEW_001', wireframeElements: [ // 사이드바 { type: 'rect', x: 0.3, y: 1.3, w: 1.2, h: 4, fill: colors.lightGray }, { type: 'rect', x: 0.35, y: 2, w: 1.1, h: 0.3, fill: colors.primary, text: '견적서 생성', fontSize: 7, color: colors.white, bold: true }, // PPT 미리보기 { type: 'rect', x: 1.6, y: 1.3, w: 5.3, h: 0.3, text: 'PPT 견적서 미리보기', fontSize: 10, bold: true, align: 'left' }, // 슬라이드 썸네일 { type: 'rect', x: 1.6, y: 1.7, w: 1.2, h: 0.8, fill: colors.secondary }, { type: 'rect', x: 1.6, y: 1.7, w: 1.2, h: 0.2, text: '1. 표지', fontSize: 6, color: colors.white }, { type: 'rect', x: 2.9, y: 1.7, w: 1.2, h: 0.8, fill: colors.lightGray }, { type: 'rect', x: 2.9, y: 1.7, w: 1.2, h: 0.2, text: '2. 요약', fontSize: 6 }, { type: 'rect', x: 4.2, y: 1.7, w: 1.2, h: 0.8, fill: colors.primary }, { type: 'rect', x: 4.2, y: 1.7, w: 1.2, h: 0.2, text: '3. 내역', fontSize: 6, color: colors.white }, { type: 'rect', x: 5.5, y: 1.7, w: 1.2, h: 0.8, fill: colors.lightGray }, { type: 'rect', x: 5.5, y: 1.7, w: 1.2, h: 0.2, text: '4. 인증', fontSize: 6 }, // 메인 프리뷰 영역 { type: 'rect', x: 1.6, y: 2.7, w: 5.3, h: 2, fill: colors.wireframeBg }, { type: 'rect', x: 2, y: 2.9, w: 4.5, h: 0.3, text: '견적서', fontSize: 12, bold: true }, { type: 'rect', x: 2, y: 3.3, w: 4.5, h: 0.2, text: 'OO빌딩 방화셔터 교체공사', fontSize: 8 }, { type: 'rect', x: 2, y: 3.6, w: 4.5, h: 0.8, fill: colors.lightGray }, // 액션 버튼 { type: 'rect', x: 1.6, y: 4.9, w: 1.5, h: 0.4, fill: colors.secondary, text: 'PPT 다운로드', fontSize: 8, color: colors.white }, { type: 'rect', x: 3.2, y: 4.9, w: 1.5, h: 0.4, fill: colors.primary, text: '이메일 전송', fontSize: 8, color: colors.white }, { type: 'rect', x: 4.8, y: 4.9, w: 1.5, h: 0.4, fill: colors.darkGray, text: '수정하기', fontSize: 8, color: colors.white } ], descriptions: [ { title: 'PPT 구성', content: '표지 → 요약 → 세부내역 → 성적서 → 회사소개 (5장)' }, { title: '실시간 미리보기', content: '슬라이드 썸네일 클릭 시 해당 페이지 확대 표시' }, { title: '다운로드/전송', content: 'PPT 파일 다운로드 또는 고객사 이메일 직접 전송' }, { title: '유효기간 자동 삽입', content: '제출일 기준 15일 유효기간 빨간색 문구 자동 추가' } ] }, { page: '9', taskName: '견적 관리', route: '/estimate/list', screenName: '견적 관리 목록', screenId: 'EST_LIST_001', wireframeElements: [ // 사이드바 { type: 'rect', x: 0.3, y: 1.3, w: 1.2, h: 4, fill: colors.lightGray }, { type: 'rect', x: 0.35, y: 2.3, w: 1.1, h: 0.3, fill: colors.primary, text: '견적 관리', fontSize: 7, color: colors.white, bold: true }, // 헤더 { type: 'rect', x: 1.6, y: 1.3, w: 5.3, h: 0.3, text: '견적 목록', fontSize: 10, bold: true, align: 'left' }, // 필터 { type: 'rect', x: 1.6, y: 1.7, w: 1.2, h: 0.35, fill: colors.lightGray, text: '전체 ▼', fontSize: 8 }, { type: 'rect', x: 2.9, y: 1.7, w: 1.2, h: 0.35, fill: colors.lightGray, text: '최신순 ▼', fontSize: 8 }, { type: 'rect', x: 5.5, y: 1.7, w: 1.2, h: 0.35, fill: colors.primary, text: '+ 새 견적', fontSize: 8, color: colors.white }, // 테이블 헤더 { type: 'rect', x: 1.6, y: 2.2, w: 5.3, h: 0.35, fill: colors.secondary }, { type: 'rect', x: 1.6, y: 2.2, w: 0.6, h: 0.35, text: 'No', fontSize: 7, color: colors.white }, { type: 'rect', x: 2.2, y: 2.2, w: 1.5, h: 0.35, text: '프로젝트명', fontSize: 7, color: colors.white }, { type: 'rect', x: 3.7, y: 2.2, w: 1, h: 0.35, text: '금액', fontSize: 7, color: colors.white }, { type: 'rect', x: 4.7, y: 2.2, w: 0.8, h: 0.35, text: '상태', fontSize: 7, color: colors.white }, { type: 'rect', x: 5.5, y: 2.2, w: 1.2, h: 0.35, text: '작성일', fontSize: 7, color: colors.white }, // 테이블 행 { type: 'rect', x: 1.6, y: 2.6, w: 5.3, h: 0.35, fill: colors.white }, { type: 'rect', x: 1.6, y: 2.6, w: 0.6, h: 0.35, text: '1', fontSize: 7 }, { type: 'rect', x: 2.2, y: 2.6, w: 1.5, h: 0.35, text: 'OO빌딩', fontSize: 7 }, { type: 'rect', x: 3.7, y: 2.6, w: 1, h: 0.35, text: '23,450,000', fontSize: 7 }, { type: 'rect', x: 4.7, y: 2.6, w: 0.8, h: 0.35, text: '완료', fontSize: 7, color: colors.primary }, { type: 'rect', x: 5.5, y: 2.6, w: 1.2, h: 0.35, text: '2024.10.24', fontSize: 7 }, // 추가 행 { type: 'rect', x: 1.6, y: 3, w: 5.3, h: 0.35, fill: colors.lightGray }, { type: 'rect', x: 1.6, y: 3.4, w: 5.3, h: 0.35, fill: colors.white }, { type: 'rect', x: 1.6, y: 3.8, w: 5.3, h: 0.35, fill: colors.lightGray }, // 통계 { type: 'rect', x: 1.6, y: 4.4, w: 1.6, h: 0.8, fill: colors.primary }, { type: 'rect', x: 1.6, y: 4.4, w: 1.6, h: 0.3, text: '전체 견적', fontSize: 8, color: colors.white }, { type: 'rect', x: 1.6, y: 4.7, w: 1.6, h: 0.5, text: '127건', fontSize: 14, color: colors.white, bold: true }, { type: 'rect', x: 3.3, y: 4.4, w: 1.6, h: 0.8, fill: colors.secondary }, { type: 'rect', x: 3.3, y: 4.4, w: 1.6, h: 0.3, text: '이번 달', fontSize: 8, color: colors.white }, { type: 'rect', x: 3.3, y: 4.7, w: 1.6, h: 0.5, text: '23건', fontSize: 14, color: colors.white, bold: true }, { type: 'rect', x: 5, y: 4.4, w: 1.6, h: 0.8, fill: colors.warning }, { type: 'rect', x: 5, y: 4.4, w: 1.6, h: 0.3, text: '총 금액', fontSize: 8, color: colors.white }, { type: 'rect', x: 5, y: 4.7, w: 1.6, h: 0.5, text: '12.5억', fontSize: 14, color: colors.white, bold: true } ], descriptions: [ { title: '견적 목록', content: '프로젝트명, 금액, 상태, 작성일 기준 조회' }, { title: '필터/정렬', content: '상태별 필터, 날짜/금액 정렬 기능' }, { title: '통계 대시보드', content: '전체 건수, 이번 달 건수, 총 금액 실시간 표시' }, { title: '할인 권한', content: '1,000만원 이상 시 5% 할인 가능 (부장 결재 시 추가)' } ] } ]; screens.forEach(screen => { createStoryboardSlide(screen); }); // 파일 저장 const outputPath = path.join(__dirname, 'pptx', 'fire_shutter_storyboard.pptx'); await pptx.writeFile({ fileName: outputPath }); console.log('\n🎉 스토리보드 PPTX 생성 완료!'); console.log(`📁 저장 위치: ${outputPath}`); // 파일 크기 확인 const stats = fs.statSync(outputPath); console.log(`📏 파일 크기: ${(stats.size / 1024).toFixed(1)} KB`); console.log(`📊 총 슬라이드: 9장`); } catch (error) { console.error('❌ 생성 실패:', error.message); throw error; } } main();