🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
693 lines
30 KiB
JavaScript
693 lines
30 KiB
JavaScript
/**
|
||
* 방화셔터 견적 시스템 - 웹 기획서/스토리보드 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();
|