533 lines
61 KiB
HTML
533 lines
61 KiB
HTML
<!doctype html>
|
||
<html lang="ko">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>AI Webmaker</title>
|
||
<link rel="stylesheet" href="/style.css">
|
||
<link rel="stylesheet" href="/theme.css">
|
||
</head>
|
||
<body>
|
||
<!-- [Ariweb Suite 변경] 포털 SSO 로 들어온 세션의 배너: 어느 그룹·어느 운영 사이트의 "프로젝트" 를 편집 중인지 항상 보인다(§9.1). public/app.js 가 /api/config 의 ariweb 값으로 채운다 -->
|
||
<div id="ariwebBanner" class="ariweb-banner hidden" role="status"></div>
|
||
<!-- =====================================================================================================
|
||
v1.6.40 (요구 1) 사용자 화면 전면 재구성 — "작업 흐름" 중심의 세 칸 구조
|
||
① 왼쪽 레일(.rail) : 제품명 · 작업 중인 사이트 선택 · 작업 흐름 내비게이션(홈 / 사이트: 만들기·수정·배포·운영 / 주소·메일: 도메인·DNS·메일 / 계정: 캐시·충전·설정)
|
||
각 항목 오른쪽에 그 작업의 상태 점·짧은 배지가 붙어, 어디까지 되었고 다음이 무엇인지 한눈에 보인다 (public/flow-ui.js 가 채움).
|
||
② 가운데 작업 칸(.left): 위(.top-pane) = 화면 이름·설명 + 진행 상태·메시지창(모든 화면 공통), 아래(.bottom-pane) = 고른 화면의 작업 카드.
|
||
③ 오른쪽 캔버스(.right): 미리보기(+소스 편집기) 또는 운영 화면에서는 사이트 관리 창.
|
||
1.4.14~1.6.39 의 "생성/수정/관리/도메인/설정" 다섯 탭은 아래처럼 나뉘고 늘어났다 (카드의 요소 ID 는 그대로라 wizard.js·modules-ui.js 등 기존 화면 코드는 바뀌지 않는다):
|
||
생성 → 만들기(create) · 수정 → 수정(edit) + 배포(deploy: 발행·원본 서버 반영·검색 등록) · 관리 → 운영(manage)
|
||
도메인 → 도메인(domains: 구매·등록·연결) + DNS(dns: 레코드·전파·확인) + 메일(mail: MX 자동 설정·웹메일) · 설정 → 캐시·충전(credits) + 설정(settings) · 새로 홈(home: 작업 흐름 지도)
|
||
===================================================================================================== -->
|
||
<div class="app">
|
||
<div class="rail" id="rail">
|
||
<div class="rail-brand"><span class="rail-logo" aria-hidden="true"></span><h1>AI Webmaker <span class="ver" id="verBadge"></span></h1></div>
|
||
<!-- 작업 중인 사이트: 여기서 고르면 가운데 작업 칸과 오른쪽 캔버스가 그 사이트로 바뀐다 (v1.2.0 사이트 선택 상자, 1.6.40 에서 레일로 이동) -->
|
||
<div class="rail-site">
|
||
<div class="rail-label">작업 중인 사이트 <button type="button" class="help right" data-tip="작업할 사이트를 여기서 고릅니다. 생성 중인 사이트는 만들기 화면, 완성된 사이트는 보고 있던 화면(홈·수정·배포·운영)에서 이어집니다. '새 사이트 만들기'를 고르면 만들기 화면에서 새로 시작합니다.">?</button></div>
|
||
<div class="site-picker"><select id="siteSelect" title="작업할 사이트"><option value="">+ 새 사이트 만들기</option></select></div>
|
||
<!-- v1.4.14 (요구 4): 상태·운영 주소 줄은 항상 같은 높이 (사이트를 고르기 전에는 안내 한 줄) -->
|
||
<div class="site-meta-top" id="siteMetaBox"><b id="siteTitle"></b><span class="pill idle small" id="siteStatePill"></span><span class="muted small" id="siteLiveLine">사이트를 고르면 상태와 운영 주소가 여기에 표시됩니다</span></div>
|
||
</div>
|
||
<!-- 작업 흐름 내비게이션. data-tab 값은 app.js TABS 와 같다. .nb(배지)·data-state(점 색) 는 flow-ui.js 가 채운다 -->
|
||
<nav class="rail-nav" id="mainTabs" aria-label="작업 흐름">
|
||
<button type="button" data-tab="home"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M3 9.5 10 3l7 6.5V17H12v-5H8v5H3z"/></svg><span>홈</span><em class="nb"></em></button>
|
||
<div class="rail-group">사이트</div>
|
||
<button type="button" data-tab="create"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 3v14M3 10h14"/></svg><span>만들기</span><em class="nb"></em></button>
|
||
<button type="button" data-tab="edit"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4 14.5 13.5 5l1.5 1.5L5.5 16H4zM12 6.5l1.5 1.5"/></svg><span>수정</span><em class="nb"></em></button>
|
||
<button type="button" data-tab="deploy"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 15V5M5.5 9.5 10 5l4.5 4.5M4 17h12"/></svg><span>배포</span><em class="nb"></em></button>
|
||
<button type="button" data-tab="manage"><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M4 16V9M10 16V4M16 16v-6"/></svg><span>운영</span><em class="nb"></em></button>
|
||
<div class="rail-group">주소 · 메일</div>
|
||
<button type="button" data-tab="domains"><svg viewBox="0 0 20 20" aria-hidden="true"><circle cx="10" cy="10" r="7"/><path d="M3 10h14M10 3c2.5 2.5 2.5 11.5 0 14M10 3c-2.5 2.5-2.5 11.5 0 14"/></svg><span>도메인</span><em class="nb"></em></button>
|
||
<button type="button" data-tab="dns"><svg viewBox="0 0 20 20" aria-hidden="true"><rect x="3" y="4" width="14" height="4.5" rx="1.2"/><rect x="3" y="11.5" width="14" height="4.5" rx="1.2"/><path d="M6 6.2h.01M6 13.7h.01"/></svg><span>DNS</span><em class="nb"></em></button>
|
||
<button type="button" data-tab="mail"><svg viewBox="0 0 20 20" aria-hidden="true"><rect x="3" y="5" width="14" height="10" rx="1.5"/><path d="m3.5 6 6.5 5 6.5-5"/></svg><span>메일</span><em class="nb"></em></button>
|
||
<div class="rail-group">계정</div>
|
||
<button type="button" data-tab="credits"><svg viewBox="0 0 20 20" aria-hidden="true"><rect x="3" y="5.5" width="14" height="9" rx="1.5"/><path d="M3 9h14"/></svg><span>캐시 · 충전</span><em class="nb"></em></button>
|
||
<button type="button" data-tab="settings"><svg viewBox="0 0 20 20" aria-hidden="true"><circle cx="10" cy="10" r="2.6"/><path d="M10 3v2M10 15v2M3 10h2M15 10h2M5.2 5.2l1.4 1.4M13.4 13.4l1.4 1.4M5.2 14.8l1.4-1.4M13.4 6.6l1.4-1.4"/></svg><span>설정</span><em class="nb"></em></button>
|
||
</nav>
|
||
<div class="rail-foot">
|
||
<!-- 잔여 캐시: 누르면 캐시·충전 화면. 작업 중에는 실시간으로 바뀐다 (app.js renderRunTokens) -->
|
||
<button type="button" class="credit-pill" id="creditPill" title="잔여 캐시 — 누르면 캐시·충전 화면이 열립니다"><span>캐시</span><b id="creditBadge">-</b></button>
|
||
<span class="muted small" id="creditNote"></span>
|
||
<div class="rail-user"><span class="user"><b id="userName"></b> <span class="muted" id="userId"></span></span></div>
|
||
<div class="rail-actions"><a id="adminLink" class="btn ghost small-btn hidden" href="/admin">관리자</a><button id="btnFeedback" class="ghost small-btn" title="사용 문의, 개선 제안, 오류를 운영팀에 보냅니다">문의 · 제안 · 오류</button><span class="lang-switch" style="display:none"><select id="langSelect" title="화면 언어 / Language"></select></span><button id="btnLogout" class="ghost small-btn">로그아웃</button></div>
|
||
</div>
|
||
</div>
|
||
|
||
<aside class="left">
|
||
<!-- ===== 위쪽: 화면 이름·설명(레일에서 고른 화면) + 진행 상태·메시지창 (모든 화면 공통) ===== -->
|
||
<div class="top-pane">
|
||
<header class="hdr v12 pane-head">
|
||
<div class="hdr-line"><h1 class="pane-title" id="paneTitle">홈</h1><span class="spacer"></span><span id="paneSite" class="muted small pane-site"></span></div>
|
||
<p class="muted small pane-desc" id="paneDesc"></p>
|
||
</header>
|
||
<!-- 현재 상태: 어느 탭에서 지시를 내려도 여기서 즉시 바뀐다 (생성·수정·배포·검증 공통) -->
|
||
<section class="status-strip" id="logCard">
|
||
<div class="ss-head"><span class="muted small">진행 상태</span><span id="ssSite" class="ss-site muted small"></span><span id="statusPill" class="pill idle">대기</span></div>
|
||
<ol class="steps-strip hidden" id="progressSteps"><li>지시 전달</li><li>AI 작업</li><li>버전 저장</li><li>완료</li></ol>
|
||
<!-- v1.5.31 (요구 1·3): 진행 상자는 한 줄 — 아이콘 · 상태(progressText) · 오른쪽 정렬 보조 문구(progressSub). 진행 중 메시지(progressMsg)만 아래 작은 줄.
|
||
배포 결과 상자(progressDeploy)는 없애고 결과는 메시지창에 시각과 함께 쌓인다. -->
|
||
<div id="progress" class="progress idle">
|
||
<div class="pi"><span class="spinner"></span><span class="check">✓</span><span class="bang">!</span><span class="dot"></span></div>
|
||
<div class="pt">
|
||
<div class="pt-line"><span id="progressText">대기 중</span><span id="progressSub" class="muted small"></span></div>
|
||
<div id="progressMsg" class="pmsg"></div>
|
||
</div>
|
||
<button id="btnCancel" class="ghost small-btn cancel hidden" title="실행 중인 AI 작업을 중단합니다">작업 중단</button>
|
||
</div>
|
||
<!-- v1.5.27 (요구 1·2): 메시지창 — 아래 작업 영역에서 한 일의 결과(배포·발행 취소·도메인·문의 메일 등)가 여기에 쌓인다. 크기 고정, 최신이 맨 위, 지난 메시지는 아래로 스크롤.
|
||
메시지마다 × 로 지우고 "모두 지우기" 로 비운다. 1.5.19 까지의 경고 한 줄 상자(progressWarn)는 지워지지 않고 계속 남아 있었다. -->
|
||
<div id="msgBox" class="msg-box hidden">
|
||
<div class="mb-head"><span class="muted small">메시지</span><span class="muted small" id="msgCount"></span><span class="spacer"></span><button type="button" class="ghost small-btn" id="msgClear" title="메시지를 모두 지웁니다">모두 지우기</button></div>
|
||
<ul id="msgList" class="mb-list"></ul>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- ===== 아래쪽: 작업 영역 (스크롤) ===== -->
|
||
<div class="bottom-pane">
|
||
<!-- ===== 홈 (v1.6.40): 작업 흐름 지도 — 만들기 → 수정 → 도메인 → DNS·메일 → 배포 → 운영 의 상태와 다음 할 일. public/flow-ui.js 가 그린다 ===== -->
|
||
<div class="tabpane" id="pane-home"><div id="homeBody"></div></div>
|
||
|
||
<!-- ===== 만들기(create): 새 사이트 생성 ~ 생성 완료 (수정·운영 화면의 사이트 선택과 무관) ===== -->
|
||
<div class="tabpane" id="pane-create">
|
||
<div class="model-row">
|
||
<span class="muted small">모델 등급 <button type="button" class="help" data-tip="기본: HTML5, CSS3, 자바스크립트 구조의 정적 웹페이지 생성. 중급: 웹페이지의 시각적 완성도(UI/UX)와 심미성 우수. 고급: 복잡한 UI/UX의 프런트엔드 아키텍쳐 구현. 등급별 예상 비용은 아래 표에 있습니다.">?</button></span>
|
||
<select id="tierSelect" title="이 사이트 생성에 사용할 AI 모델 등급"></select>
|
||
</div>
|
||
<div class="tier-guide" id="tierGuideBox"></div>
|
||
|
||
<section class="card" id="modeCard">
|
||
<h2>1. 어떻게 만들까요? <button type="button" class="help" data-tip="AI에게 맡기기: 설명만 적으면 AI 가 분석 후 필요한 정보만 묻고 끝까지 자동 생성합니다. 내가 고르기: 업종·목적·페이지·디자인·문구를 단계별로 직접 고릅니다. 기존 사이트의 모양을 살려 새로 만들려면 아래 '2. 기존 사이트 모양으로 시작'을 고르세요.">?</button></h2>
|
||
<div class="mode-grid">
|
||
<button type="button" class="mode-opt" data-mode="ai"><span class="mode-title">AI에게 맡기기</span><span class="mode-desc">설명 + 추가 정보 입력 → 자동 생성</span></button>
|
||
<button type="button" class="mode-opt" data-mode="manual"><span class="mode-title">내가 고르기</span><span class="mode-desc">구성·디자인·문구를 직접 선택</span></button>
|
||
<button type="button" class="mode-opt" data-mode="template"><span class="mode-title">템플릿에서 시작</span><span class="mode-desc">업종별·해시태그로 고른 완성 사이트를 바탕으로</span></button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- v1.3.4: 기존 사이트로 시작하기 — "사이트 복사하기" 만 남김 ("사이트 관리하기(서버에서 가져오기)" 는 삭제) -->
|
||
<section class="card" id="existingCard">
|
||
<h2>2. 기존 사이트 모양으로 시작 <button type="button" class="help" data-tip="이미 있는 사이트의 모양(디자인·구성·문구)을 최대한 살려 새 사이트를 만들 때 씁니다. 웹 주소만 입력하면 화면을 이루는 HTML·CSS·JS·이미지를 복사해 오며, 로그인·게시판·신청·결제 같은 기능(서버 프로그램)은 복사되지 않습니다. 복사한 뒤에는 새로 만든 사이트처럼 수정·발행합니다.">?</button></h2>
|
||
<div class="mode-grid">
|
||
<button type="button" class="mode-opt" data-mode="copy"><span class="mode-title">사이트 복사하기</span><span class="mode-desc">웹 주소만 입력 → 화면(HTML 페이지)만 복사해 새 사이트로</span></button>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card hidden" id="copyStartCard">
|
||
<h2>사이트 복사하기 <button type="button" class="ghost small-btn" id="btnBackMode4">← 방식 변경</button></h2>
|
||
<label>사이트 주소 <span class="req">*</span> <button type="button" class="help" data-tip="복사할 사이트의 첫 페이지 주소입니다. 같은 도메인 안의 페이지와 그 페이지가 쓰는 CSS·JS·이미지·글꼴을 따라가며 내려받고, 링크를 이 빌더 안의 경로로 바꿉니다. 다른 도메인(CDN 등)의 자원은 원래 주소를 그대로 씁니다. 사이트 크기가 서버 용량의 10% 를 넘으면 중지됩니다.">?</button><input id="cpUrl" placeholder="https://www.example.com" autocomplete="off"></label>
|
||
<label>사이트 이름 <span class="muted small">(비우면 페이지 제목)</span><input id="cpTitle" autocomplete="off"></label>
|
||
<label>문의 수신 이메일 <span class="muted small">(선택)</span><input id="cpEmail" type="email" autocomplete="off" placeholder="info@example.com"></label>
|
||
<!-- v1.3.4: 무엇이 복사되고 무엇이 안 되는지, 왜 있는 기능인지 상세 설명 -->
|
||
<div class="copy-explain">
|
||
<p><b>이 기능은 무엇인가요?</b> 기존 사이트의 <b>모양은 최대한 유지하면서 새로운 사이트를 만들 때</b> 쓰는 기능입니다. 원래 사이트를 옮기거나 그대로 운영하는 기능이 아닙니다.</p>
|
||
<ul>
|
||
<li><b>복사되는 것</b> — 웹 주소로 열리는 기본 HTML 페이지와, 그 페이지가 쓰는 CSS·JS·이미지·글꼴 (같은 도메인 안의 페이지를 따라가며 최대 300쪽)</li>
|
||
<li><b>복사되지 않는 것</b> — 로그인·회원, 게시판 글 저장, 문의·신청·예약 접수, 결제, 검색처럼 서버에서 동작하는 기능과 그 데이터(DB), 로그인해야 보이는 화면</li>
|
||
<li><b>복사한 뒤</b> — 새로 만든 사이트로 취급되어 수정 지시·소스 편집·발행을 그대로 쓸 수 있습니다. 필요한 기능은 수정 지시로 빌더의 공통 기능 모듈(회원·게시판·문의·예약 등)로 새로 붙입니다.</li>
|
||
</ul>
|
||
<p class="muted small">본인 또는 권한이 있는 사이트만 복사하세요.</p>
|
||
</div>
|
||
<!-- v1.3.5: 검색·AI 최적화 생성 옵션 — 생성이 끝나면 AI 초안 → 수정 탭에서 검토 후 반영 -->
|
||
<div class="seo-opts" data-seo-opts>
|
||
<div class="field-label">검색·AI 최적화 <button type="button" class="help" data-tip="SEO: 검색 결과에 보이는 페이지별 제목·설명·키워드, 공유 미리보기, 사이트맵. AEO: 질문형 검색(AI·음성 답변)에 맞춘 자주 묻는 질문과 짧은 답, 구조화 데이터. GEO: 생성형 AI 검색이 정확히 인용하도록 사업체 정보 구조화 데이터·핵심 사실·llms.txt. 생성이 끝나면 AI 가 초안을 만들고(기본 등급, 캐시 차감) 수정 탭에서 확인·수정한 뒤 반영합니다. 바로 사이트에 들어가지 않습니다.">?</button></div>
|
||
<label class="chk"><input type="checkbox" data-opt="seo"> SEO AI 생성 <span class="muted small">— 페이지별 검색 제목·설명·키워드, 공유 미리보기, 사이트맵</span></label>
|
||
<label class="chk"><input type="checkbox" data-opt="aeo"> AEO 생성 <span class="muted small">— 질문형 FAQ·핵심 답변 (AI·음성 답변용)</span></label>
|
||
<label class="chk"><input type="checkbox" data-opt="geo"> GEO 생성 <span class="muted small">— 사업체 정보·인용용 사실·llms.txt (생성형 AI 검색용)</span></label>
|
||
</div>
|
||
<button id="cpStart" class="primary">사이트 복사 시작</button>
|
||
</section>
|
||
|
||
<!-- v1.3.10: 템플릿에서 시작 — 관리자가 사용을 허용한 템플릿 (public/templates-ui.js) -->
|
||
<section class="card hidden" id="templateStartCard">
|
||
<h2>템플릿에서 시작 <button type="button" class="ghost small-btn" id="btnBackMode5">← 방식 변경</button> <button type="button" class="help" data-tip="운영팀이 만든 완성 사이트(템플릿)를 바탕으로 새 사이트를 만듭니다. 업종 디렉터리나 #해시태그로 찾고 미리보기로 확인한 뒤 고르세요. 시작하면 템플릿의 페이지·디자인이 그대로 복사되며, 그 뒤에는 수정 지시로 내용을 바꿉니다.">?</button></h2>
|
||
<input id="tplQ" placeholder="#카페 #미니멀 처럼 해시태그나 낱말로 찾기" autocomplete="off">
|
||
<div class="tpl-tags" id="tplTags"></div>
|
||
<div class="tpl-layout"><div class="tpl-tree" id="tplTree"></div><div class="tpl-list" id="tplList"></div></div>
|
||
<p class="small" id="tplChosen"></p>
|
||
<label>사이트 이름 <span class="muted small">(비우면 템플릿 이름)</span><input id="tplTitle" autocomplete="off"></label>
|
||
<label>문의 수신 이메일 <span class="muted small">(선택)</span><input id="tplEmail" type="email" autocomplete="off" placeholder="info@example.com"></label>
|
||
<div class="seo-opts" data-seo-opts>
|
||
<div class="field-label">검색·AI 최적화</div>
|
||
<label class="chk"><input type="checkbox" data-opt="seo" checked> SEO AI 생성</label>
|
||
<label class="chk"><input type="checkbox" data-opt="aeo"> AEO 생성</label>
|
||
<label class="chk"><input type="checkbox" data-opt="geo"> GEO 생성</label>
|
||
</div>
|
||
<button id="tplStart" class="primary" disabled>이 템플릿으로 시작</button>
|
||
</section>
|
||
|
||
<section class="card hidden" id="aiStartCard">
|
||
<h2>AI에게 맡기기 <button type="button" class="ghost small-btn" id="btnBackMode">← 방식 변경</button></h2>
|
||
<label class="ai-main-label">만들고 싶은 사이트 <span class="req">*</span> <button type="button" class="help" data-tip="업종, 위치, 주요 고객, 꼭 들어가야 할 내용(예: 예약, 가격표, 강사 소개)을 자유롭게 적습니다. 많이 적을수록 AI 가 정확히 이해합니다. 결과: AI 가 업종·목표·페이지 구성을 정리해 추가로 필요한 정보만 묻습니다.">?</button>
|
||
<textarea id="aiText" class="ai-main-input" rows="10" placeholder="예: 강남역 근처 필라테스 스튜디오. 1:1 수업 중심, 30대 직장인 여성 대상. 예약을 많이 받고 싶고, 강사 소개와 가격표가 들어갔으면 함."></textarea>
|
||
</label>
|
||
<div class="field-label">디자인 컨셉 (선택) <button type="button" class="help" data-tip="주 색상은 버튼·강조색에 쓰이고, 톤은 전체 분위기(여백·글꼴·이미지 스타일)를 정합니다. 방향에는 '사진 크게', '둥근 버튼' 같은 요구를 적습니다. 비우면 업종에 맞게 AI 가 추천합니다.">?</button></div>
|
||
<div class="two">
|
||
<label>주 색상<div class="color-row"><input id="aiColor" type="color" value="#2f6fed"><input id="aiColorText" placeholder="#2f6fed 또는 '네이비'" autocomplete="off"></div></label>
|
||
<label>분위기(톤)<select id="aiTone"><option value="">AI 추천</option></select></label>
|
||
</div>
|
||
<label>디자인 방향<input id="aiDesignDir" placeholder="예: 여백 많은 고급스러운 느낌, 사진 크게" autocomplete="off"></label>
|
||
<label>페이지 수 <button type="button" class="help" data-tip="홈을 포함한 페이지 개수입니다. '자동'은 AI 가 업종과 목표에 맞게 3~6개를 정합니다. 1개를 고르면 모든 내용을 한 페이지에 섹션으로 배치하는 원페이지 사이트가 됩니다. 페이지가 많을수록 생성 비용과 시간이 늘어납니다.">?</button><select id="aiPageCount"><option value="0">자동 (AI 가 결정, 보통 3~6개)</option><option value="1">1개 (원페이지)</option><option value="2">2개</option><option value="3">3개</option><option value="4">4개</option><option value="5">5개</option><option value="6">6개</option><option value="8">8개</option><option value="10">10개</option></select></label>
|
||
<label>기존 사이트 URL <button type="button" class="help" data-tip="이미 사이트가 있으면 주소를 적습니다. AI 가 본문을 읽어 사업 정보와 전화·주소 같은 사실정보를 출처와 함께 가져옵니다.">?</button><input id="aiExistingUrl" placeholder="https://"></label>
|
||
<div class="field-label">첨부 <button type="button" class="help" data-tip="소개서(PDF·문서)는 내용에, 로고·사진은 페이지 이미지에 쓰입니다. 첨부가 없는 자리는 AI 가 그라데이션·도형으로 채웁니다.">?</button></div>
|
||
<div class="dropzone" id="dzCreate" data-target="create">
|
||
<div class="dz-text">파일을 끌어다 놓거나 <label class="dz-pick" for="fFiles">클릭해서 선택</label></div>
|
||
<input id="fFiles" type="file" multiple class="visually-hidden">
|
||
<ul class="pending" id="pendingCreate"></ul>
|
||
</div>
|
||
<div class="field-label">참고 사이트 (최대 10개) <button type="button" class="help" data-tip="참고할 사이트 주소와 '어떤 점을 반영할지'(메뉴 구성, 색감, 가격표 형식 등)를 함께 적습니다. 디자인·구조 제안에 반영됩니다.">?</button></div>
|
||
<div id="refsAi" class="refs"></div>
|
||
<!-- v1.3.5: 검색·AI 최적화 생성 옵션 — 생성이 끝나면 AI 초안 → 수정 탭에서 검토 후 반영 -->
|
||
<div class="seo-opts" data-seo-opts>
|
||
<div class="field-label">검색·AI 최적화 <button type="button" class="help" data-tip="SEO: 검색 결과에 보이는 페이지별 제목·설명·키워드, 공유 미리보기, 사이트맵. AEO: 질문형 검색(AI·음성 답변)에 맞춘 자주 묻는 질문과 짧은 답, 구조화 데이터. GEO: 생성형 AI 검색이 정확히 인용하도록 사업체 정보 구조화 데이터·핵심 사실·llms.txt. 생성이 끝나면 AI 가 초안을 만들고(기본 등급, 캐시 차감) 수정 탭에서 확인·수정한 뒤 반영합니다. 바로 사이트에 들어가지 않습니다.">?</button></div>
|
||
<label class="chk"><input type="checkbox" data-opt="seo" checked> SEO AI 생성 <span class="muted small">— 페이지별 검색 제목·설명·키워드, 공유 미리보기, 사이트맵</span></label>
|
||
<label class="chk"><input type="checkbox" data-opt="aeo" checked> AEO 생성 <span class="muted small">— 질문형 FAQ·핵심 답변 (AI·음성 답변용)</span></label>
|
||
<label class="chk"><input type="checkbox" data-opt="geo" checked> GEO 생성 <span class="muted small">— 사업체 정보·인용용 사실·llms.txt (생성형 AI 검색용)</span></label>
|
||
</div>
|
||
<!-- v1.3.10: 다국어 생성 옵션 — 언어마다 /ko/ /en/ 폴더, 기본 언어 페이지와 같은 구조로 번역 (app.js fillLangOpts) -->
|
||
<div class="lang-opts" data-lang-opts>
|
||
<div class="field-label">사이트 언어 <button type="button" class="help" data-tip="추가 언어를 고르면 다국어 사이트로 만듭니다. 주소는 언어마다 /ko/, /en/ 처럼 나뉘고, 다른 언어 페이지는 기본 언어 페이지와 같은 구조(페이지·섹션·순서)로 번역됩니다. 날짜·숫자는 언어별 형식으로, 아랍어 등은 오른쪽→왼쪽으로 표시되며, 언어마다 검색·AI 최적화 값이 따로 만들어집니다. 번역은 기본 등급 모델로 캐시가 차감됩니다. 나중에 수정 탭에서 언어를 더할 수도 있습니다.">?</button></div>
|
||
<label class="lang-default">기본 언어<select data-lang-default></select></label>
|
||
<div class="lang-chips" data-lang-extra></div>
|
||
<!-- v1.3.16: x-default — 어떤 언어에도 맞지 않는 방문자에게 보일 언어 (추가 언어를 골랐을 때만 보임) -->
|
||
<label class="lang-default lang-xdef hidden">x-default (다른 언어 방문자에게 보일 언어) <button type="button" class="help" data-tip="검색엔진의 hreflang x-default 와 사이트 맨 위 주소(언어 선택 페이지)의 자동 이동에 쓰입니다. 브라우저 언어가 사이트 언어 중 어느 것과도 맞지 않는 방문자는 이 언어로 갑니다. '언어 선택 페이지' 를 고르면 자동 이동 없이 선택 페이지를 보여 줍니다.">?</button><select data-lang-xdefault></select></label>
|
||
</div>
|
||
<button id="btnAiStart" class="primary">AI 분석 시작</button>
|
||
</section>
|
||
|
||
<section class="card hidden" id="manualStartCard">
|
||
<h2>내가 고르기 <button type="button" class="ghost small-btn" id="btnBackMode2">← 방식 변경</button></h2>
|
||
<label>상호명 <span class="req">*</span><input id="mName" placeholder="예: 한강 카페 로스터스"></label>
|
||
<div class="two">
|
||
<label>업종 대분류 <button type="button" class="help" data-tip="업종을 고르면 목적·기능·페이지·디자인 기본값이 미리 선택됩니다. 각 단계에서 바꿀 수 있습니다.">?</button><select id="mMajor"></select></label>
|
||
<label>소분류<select id="mMinor"></select></label>
|
||
</div>
|
||
<div class="two">
|
||
<label>지역 시·도<select id="mSido"></select></label>
|
||
<label>시·군·구<select id="mSigungu"></select></label>
|
||
</div>
|
||
<div class="field-label">참고 사이트 (최대 10개) <button type="button" class="help" data-tip="참고할 사이트 주소와 반영할 점을 적습니다. 디자인·구조에 반영됩니다.">?</button></div>
|
||
<div id="refsManual" class="refs"></div>
|
||
<!-- v1.3.5: 검색·AI 최적화 생성 옵션 — 생성이 끝나면 AI 초안 → 수정 탭에서 검토 후 반영 -->
|
||
<div class="seo-opts" data-seo-opts>
|
||
<div class="field-label">검색·AI 최적화 <button type="button" class="help" data-tip="SEO: 검색 결과에 보이는 페이지별 제목·설명·키워드, 공유 미리보기, 사이트맵. AEO: 질문형 검색(AI·음성 답변)에 맞춘 자주 묻는 질문과 짧은 답, 구조화 데이터. GEO: 생성형 AI 검색이 정확히 인용하도록 사업체 정보 구조화 데이터·핵심 사실·llms.txt. 생성이 끝나면 AI 가 초안을 만들고(기본 등급, 캐시 차감) 수정 탭에서 확인·수정한 뒤 반영합니다. 바로 사이트에 들어가지 않습니다.">?</button></div>
|
||
<label class="chk"><input type="checkbox" data-opt="seo" checked> SEO AI 생성 <span class="muted small">— 페이지별 검색 제목·설명·키워드, 공유 미리보기, 사이트맵</span></label>
|
||
<label class="chk"><input type="checkbox" data-opt="aeo" checked> AEO 생성 <span class="muted small">— 질문형 FAQ·핵심 답변 (AI·음성 답변용)</span></label>
|
||
<label class="chk"><input type="checkbox" data-opt="geo" checked> GEO 생성 <span class="muted small">— 사업체 정보·인용용 사실·llms.txt (생성형 AI 검색용)</span></label>
|
||
</div>
|
||
<!-- v1.3.10: 다국어 생성 옵션 — 언어마다 /ko/ /en/ 폴더, 기본 언어 페이지와 같은 구조로 번역 (app.js fillLangOpts) -->
|
||
<div class="lang-opts" data-lang-opts>
|
||
<div class="field-label">사이트 언어 <button type="button" class="help" data-tip="추가 언어를 고르면 다국어 사이트로 만듭니다. 주소는 언어마다 /ko/, /en/ 처럼 나뉘고, 다른 언어 페이지는 기본 언어 페이지와 같은 구조(페이지·섹션·순서)로 번역됩니다. 날짜·숫자는 언어별 형식으로, 아랍어 등은 오른쪽→왼쪽으로 표시되며, 언어마다 검색·AI 최적화 값이 따로 만들어집니다. 번역은 기본 등급 모델로 캐시가 차감됩니다. 나중에 수정 탭에서 언어를 더할 수도 있습니다.">?</button></div>
|
||
<label class="lang-default">기본 언어<select data-lang-default></select></label>
|
||
<div class="lang-chips" data-lang-extra></div>
|
||
<!-- v1.3.16: x-default — 어떤 언어에도 맞지 않는 방문자에게 보일 언어 (추가 언어를 골랐을 때만 보임) -->
|
||
<label class="lang-default lang-xdef hidden">x-default (다른 언어 방문자에게 보일 언어) <button type="button" class="help" data-tip="검색엔진의 hreflang x-default 와 사이트 맨 위 주소(언어 선택 페이지)의 자동 이동에 쓰입니다. 브라우저 언어가 사이트 언어 중 어느 것과도 맞지 않는 방문자는 이 언어로 갑니다. '언어 선택 페이지' 를 고르면 자동 이동 없이 선택 페이지를 보여 줍니다.">?</button><select data-lang-xdefault></select></label>
|
||
</div>
|
||
<button id="btnManualStart" class="primary">기본값으로 시작하기</button>
|
||
</section>
|
||
|
||
<!-- v1.3.4: "사이트 관리하기(서버 접속으로 가져오기)" 시작 카드 삭제 -->
|
||
|
||
<!-- 기획 진행 카드 (AI / 내가 고르기) -->
|
||
<section class="card hidden" id="planCard">
|
||
<h2><span id="planTitle">기획</span> <span id="planStage" class="pill idle"></span> <span class="spacer"></span><button type="button" class="ghost small-btn" id="btnAbortCreate" title="진행 중인 생성 작업을 멈추고 새 사이트 만들기로 돌아갑니다">중단하고 새로 만들기</button></h2>
|
||
<div id="planBody"></div>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- ===== 수정(edit, v1.4.14 → 1.6.40): 수정 지시·기본 사항·다국어·검색 최적화·버전·첨부. 발행·배포는 "배포" 화면으로 ===== -->
|
||
<div class="tabpane hidden" id="pane-edit">
|
||
<p class="muted small" id="editHint"></p>
|
||
<!-- v1.6.40: 발행·배포 / 원본 서버 반영 / 검색사이트 등록 카드는 "배포" 화면(#pane-deploy)으로 옮겼다. 수정 화면은 사이트를 고치는 일에만 집중한다. -->
|
||
<!-- 수정 완료 안내 (v1.1.2): 마지막 수정 작업의 결과 요약 + 상세 보기 -->
|
||
<section class="card done-banner hidden" id="doneBanner">
|
||
<div class="db-head"><span class="db-icon">✓</span><div><b id="dbTitle">수정 완료</b><div class="muted small" id="dbMeta"></div></div><span class="spacer"></span><button type="button" class="ghost small-btn" id="dbDetail">상세 내역</button><button type="button" class="ghost small-btn" id="dbClose" title="닫기">×</button></div>
|
||
<div class="small hidden" id="dbSummary"></div>
|
||
</section>
|
||
<!-- 수정 지시: 수정 탭의 핵심 -->
|
||
<section class="card update-card hidden" id="updateCard">
|
||
<h2>수정 지시 <span class="muted small" id="editLimitNote"></span> <button type="button" class="help" data-tip="바꾸고 싶은 내용을 문장으로 적으면 AI 가 해당 부분만 고칩니다. 예: '첫 화면 배너 문구를 더 짧게', '문의 폼에 회사명 항목 추가', '게시판 페이지 추가'. 기본 사항·이전 지시·설정은 그대로 유지됩니다. 수정이 끝나면 미리보기에 바로 반영되고 버전이 남습니다.">?</button></h2>
|
||
<div id="editLockBox" class="progress-warn hidden"></div>
|
||
<textarea id="fInstruction" rows="7" placeholder="무엇을 어떻게 바꿀지 적어 주세요. 예) 첫 화면 배너 문구를 '당신의 하루를 바꾸는 한 시간'으로 바꾸고, 가격표에 10회권 35만원을 추가해 주세요."></textarea>
|
||
<div class="update-tools">
|
||
<div class="model-row inline-row"><span class="muted small">이번 수정 모델</span><select id="editTierSelect" title="이번 수정 지시에 사용할 모델 등급"></select><button type="button" class="help" data-tip="수정마다 등급을 다르게 고를 수 있습니다. 모델이 바뀌어도 사이트 기본 사항과 이전 지시 내용은 그대로 유지되어 이어서 작업합니다.">?</button></div>
|
||
<div class="muted small" id="editCostLine"></div>
|
||
</div>
|
||
<div class="dropzone slim" id="dzUpdate" data-target="update">
|
||
<div class="dz-text">함께 보낼 파일을 끌어다 놓거나 <label class="dz-pick" for="fUpdFiles">선택</label> <button type="button" class="help" data-tip="이 지시와 함께 쓸 사진·문서입니다. 이미지는 페이지에, 문서는 내용에 반영됩니다.">?</button></div>
|
||
<input id="fUpdFiles" type="file" multiple class="visually-hidden">
|
||
<ul class="pending" id="pendingUpdate"></ul>
|
||
</div>
|
||
<button id="btnUpdate" class="primary big">수정 요청</button>
|
||
<details id="basicsBox" class="basics">
|
||
<summary>홈페이지 기본 사항 보기 / 수정 <span id="basicsState" class="basics-state"></span> <button type="button" class="help" data-tip="제목·목적·내용·디자인 방향·기타 요구사항·문의 수신 이메일. 저장하면 다음 수정 지시 때 AI 에게 함께 전달되어 페이지 전반에 반영됩니다.">?</button></summary>
|
||
<label>페이지 제목 <span class="req">*</span><input id="bTitle"></label>
|
||
<label>목적<textarea id="bPurpose" rows="2"></textarea></label>
|
||
<label>주요 컨텐츠<textarea id="bContent" rows="3"></textarea></label>
|
||
<label>디자인 방향<textarea id="bDesign" rows="2"></textarea></label>
|
||
<label>기타 요구사항<textarea id="bExtra" rows="3"></textarea></label>
|
||
<label>문의 수신 이메일<input id="bEmail" type="email" placeholder="예: info@example.com"></label>
|
||
<div class="row">
|
||
<button id="btnSaveBasics" class="primary small-btn" disabled>기본 사항 저장</button>
|
||
<button id="btnRevertBasics" class="ghost small-btn" disabled>되돌리기</button>
|
||
</div>
|
||
</details>
|
||
</section>
|
||
<!-- v1.3.10: 다국어 — 언어 추가·빼기, 단일 언어 사이트를 다국어 구조로 옮기기 (public/optimize.js LangUI) -->
|
||
<section class="card hidden" id="langCard">
|
||
<h2>다국어 <span class="pill small" id="langState"></span> <button type="button" class="help" data-tip="사이트를 여러 언어로 제공합니다. 주소는 언어마다 /ko/, /en/ 처럼 나뉘고, 사이트 맨 위 주소는 방문자 브라우저 언어로 안내하는 언어 선택 페이지가 됩니다. 기본 언어 페이지를 수정하면 다른 언어 페이지도 같은 구조로 다시 번역됩니다(바뀐 문장만 번역, 기본 등급 모델로 캐시 차감). 한 언어 사이트를 다국어로 바꿀 때는 AI 가 페이지를 기본 언어 폴더로 옮기는 수정 작업을 먼저 합니다.">?</button></h2>
|
||
<div id="langBody"></div>
|
||
</section>
|
||
<!-- v1.3.5: 검색·AI 최적화 (SEO·AEO·GEO) — AI 초안을 검토·수정한 뒤 반영 (public/optimize.js) -->
|
||
<section class="card hidden" id="optimizeCard">
|
||
<h2>검색·AI 최적화 <span class="pill small" id="optState"></span> <button type="button" class="help" data-tip="SEO(검색 결과 제목·설명·키워드·공유 미리보기·사이트맵), AEO(질문형 FAQ·핵심 답변, AI·음성 답변용), GEO(사업체 정보 구조화 데이터·인용용 사실·llms.txt, 생성형 AI 검색용) 값을 AI 가 초안으로 만들면 여기서 확인·수정해 반영합니다. 반영하면 버전이 저장되고, 다음 배포 때 운영 주소 기준(canonical·사이트맵)으로 함께 올라갑니다.">?</button></h2>
|
||
<div id="optBody"></div>
|
||
</section>
|
||
<section class="card hidden" id="versionsCard">
|
||
<h2>이전 버전으로 되돌리기 <span class="muted small" id="versionsCount"></span> <button type="button" class="help" data-tip="생성·수정·저장마다 버전이 남습니다. 되돌리면 그 시점 파일로 복원되고 복원도 새 버전으로 기록됩니다. 배포가 완료되면 이전 버전은 정리되고 배포본 하나만 남습니다.">?</button></h2>
|
||
<ul id="versionsList" class="git-list"></ul>
|
||
</section>
|
||
<section class="card hidden" id="attachCard">
|
||
<h2>첨부 파일 <span class="muted small" id="attachCount"></span> <button type="button" class="help" data-tip="파일당 최대 25MB. 이미지는 uploads/파일명 경로로 페이지에 삽입되고, 문서는 AI 가 읽어 내용에 반영합니다. 허용 형식은 아래 드롭존에 표시됩니다.">?</button></h2>
|
||
<ul id="attachList" class="attach-list"></ul>
|
||
<div class="dropzone slim" id="dzNow" data-target="now">
|
||
<div class="dz-text">파일을 놓으면 바로 업로드 · <label class="dz-pick" for="fAttachNow">선택</label> <span class="muted small">(<span id="attachExts"></span>)</span></div>
|
||
<input id="fAttachNow" type="file" multiple class="visually-hidden">
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- ===== 배포(deploy, v1.6.40 신설): 이전 단계(사이트 완성·도메인·DNS)가 갖춰졌는지 점검표(#deployChecklist, flow-ui.js) + 발행·배포 · 원본 서버 반영 · 검색사이트 등록 =====
|
||
배포는 다른 작업이 모두 끝나야 하는 마지막 작업이지만, 한 번 배포된 뒤의 수정·관리는 도메인·DNS 와 직접 묶이지 않는다 — 그래서 수정 화면과 분리했다. -->
|
||
<div class="tabpane hidden" id="pane-deploy">
|
||
<div id="deployChecklist"></div>
|
||
<section class="card hidden" id="publishCard">
|
||
<h2>발행 · 배포 <span id="publishState" class="pill idle"></span> <button type="button" class="help" data-tip="발행은 점검(입력 필요 항목·누락 페이지·규제 표현) 후 운영자가 지정한 배포 서버로 사이트를 전송합니다. 배포가 끝나면 상단 주소가 운영 주소로 바뀝니다. 발행 취소를 하면 운영 주소에는 '사이트 수정 중' 안내만 보이고, 다시 발행하면 정상 내용이 올라갑니다.">?</button></h2>
|
||
<div id="publishBody"></div>
|
||
</section>
|
||
<section class="card hidden" id="importCard">
|
||
<h2>원본 서버에 반영 <span id="imState" class="pill idle"></span> <button type="button" class="help" data-tip="여기서 수정한 파일을 원본 서버의 같은 경로에 덮어씁니다. 가져온 뒤 삭제한 파일은 서버에서도 지워지고, 서버에만 있는 파일(업로드·캐시)은 건드리지 않습니다. SSH 방식은 반영 전에 서버에 백업을 만듭니다.">?</button></h2>
|
||
<div id="imInfo" class="small"></div>
|
||
<div class="row">
|
||
<button id="imBtnDeploy" class="primary small-btn">수정 내용을 원본 서버에 반영 (배포)</button>
|
||
<button id="imBtnCreds" class="ghost small-btn">접속 정보 변경</button>
|
||
</div>
|
||
<div id="imDeployMsg" class="small"></div>
|
||
<div id="imCredsBox" class="hidden">
|
||
<div class="two">
|
||
<label>접속 계정(ID)<input id="imcUser" autocomplete="off"></label>
|
||
<label>포트<input id="imcPort" inputmode="numeric" autocomplete="off"></label>
|
||
</div>
|
||
<label>새 비밀번호 <span class="muted small">(바꿀 때만)</span><input id="imcPw" type="password" autocomplete="new-password"></label>
|
||
<label>사이트 파일 경로<input id="imcDocroot" autocomplete="off"></label>
|
||
<label>사이트 주소<input id="imcUrl" autocomplete="off"></label>
|
||
<div class="row"><button type="button" id="imcSave" class="primary small-btn">확인 후 저장</button><span id="imcMsg" class="muted small"></span></div>
|
||
</div>
|
||
</section>
|
||
<!-- v1.3.5: 검색사이트 등록 (구글·네이버, IndexNow) — 배포가 끝난 사이트만 -->
|
||
<section class="card hidden" id="searchCard">
|
||
<h2>검색사이트 등록 <button type="button" class="help" data-tip="구글 Search Console 과 네이버 서치어드바이저에 사이트를 등록합니다. 검색사이트가 주는 확인 코드를 넣으면 첫 페이지에 확인 태그를 넣고 다시 배포하며, 검색사이트에서 '확인'·사이트맵 제출 같은 사람이 해야 하는 단계는 체크리스트로 보여 줍니다(관리자 콘솔에서도 진행 가능). IndexNow 로 빙·네이버 등에 새 페이지 색인을 바로 요청할 수 있습니다. 배포가 끝난 사이트만 쓸 수 있고, 생성·수정·배포 중에는 쓸 수 없습니다.">?</button></h2>
|
||
<div id="searchBody"></div>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- ===== 운영(manage, v1.4.14 "관리" → 1.6.40 "운영"): 기능 모듈·사이트 관리자 페이지·메일, 문의 접수, 사이트 현황, 현황 분석, 캐시 사용, 사이트 설정 =====
|
||
이 화면을 고르면 오른쪽 캔버스가 "사이트 관리 창"(사이트 관리자 페이지 + 현황 요약)으로 바뀐다 (public/manage-ui.js). -->
|
||
<div class="tabpane hidden" id="pane-manage">
|
||
<p class="muted small" id="manageHint"></p>
|
||
<section class="card hidden" id="moduleCard">
|
||
<h2>사이트 기능 모듈 <button type="button" class="ghost small-btn" id="btnModuleReload">새로고침</button> <button type="button" class="help" data-tip="게시판·문의폼·설문·예약·갤러리·지도·후기·FAQ·회원 기능입니다. 켜면 관리자 페이지가 생기고, 수정 지시에 '게시판을 추가해 주세요'처럼 적으면 표준 코드로 페이지에 들어갑니다. 글·예약·응답 같은 데이터는 사이트 관리자 페이지에서 관리합니다.">?</button></h2>
|
||
<div id="moduleList" class="module-list"></div>
|
||
<div class="row"><a id="btnSiteAdmin" class="btn ghost small-btn" target="_blank" rel="noopener">사이트 관리자 페이지 열기</a><span class="muted small">— 오른쪽 사이트 관리 창에서도 바로 관리할 수 있습니다</span></div>
|
||
<!-- v1.3.2: 이 사이트의 메일 시스템 상태 (운영자가 켜면 "메일시스템 설정중" → DNS 확인 후 "사용 가능") -->
|
||
<div class="mail-line hidden" id="mailLine"><span class="muted small">메일</span> <span class="pill small" id="mailLabel"></span> <span class="muted small" id="mailMsg"></span> <a id="mailOpen" class="btn ghost small-btn hidden" target="_blank" rel="noopener">웹메일 열기</a></div>
|
||
</section>
|
||
<section class="card hidden" id="inquiryCard">
|
||
<h2>문의 접수 내역 <span class="muted small" id="inquiryCount"></span> <button type="button" class="ghost small-btn" id="btnInquiryReload">새로고침</button> <button type="button" class="help" data-tip="사이트 문의 폼으로 들어온 내용입니다. 문의 수신 이메일이 설정되어 있으면 메일로도 발송되며, 미발송 건은 '재발송'으로 다시 보낼 수 있습니다.">?</button></h2>
|
||
<p class="muted small" id="inquiryNote"></p>
|
||
<ul id="inquiryList" class="git-list"></ul>
|
||
</section>
|
||
<!-- v1.7.2 (요구 2): 사이트 정보는 오른쪽 캔버스의 "사이트 정보" 페이지(public/site-info.js)로 옮겼다. 여기에는 요약 세 줄과 "자세히 보기" 만 남는다 (app.js renderStats) -->
|
||
<section class="card hidden" id="siteInfoCard">
|
||
<h2>사이트 정보 <span class="muted small" id="statsUpdated"></span> <button type="button" class="ghost small-btn" id="btnStatsReload">새로고침</button> <button type="button" class="help" data-tip="접속 통계·네트워크 사용량(송신/수신)·디스크 사용량(웹·DB·메일)을 그래프로 보는 사이트 정보 페이지는 오른쪽 창에 열립니다. 방문자·페이지뷰·네트워크는 사이트가 올라간 서버의 접속 로그(5분 주기, 봇 제외)로 집계하고, 로그를 읽을 수 없는 서버는 통계 스크립트의 보고(추정)를 씁니다.">?</button></h2>
|
||
<div class="totals stat-grid" id="statVisits"></div>
|
||
<div class="row"><button type="button" class="primary small-btn" id="btnSiteInfoOpen">오른쪽 창에서 자세히 보기 (그래프)</button></div>
|
||
</section>
|
||
<!-- 사이트 관리하기·복사하기: 현황 분석 (v1.2.0) -->
|
||
<section class="card hidden" id="analysisCard">
|
||
<h2>사이트 현황 분석 <span class="muted small" id="anAt"></span> <button type="button" class="ghost small-btn" id="btnReanalyze">다시 분석</button> <button type="button" class="help" data-tip="가져오거나 복사한 사이트의 파일 통계(종류별 개수·크기, 페이지, 사용 기술)와 웹서버 정보, AI 요약(구성·기술·수정 난이도·문제점·개선 제안)입니다. AI 요약은 '기본' 등급으로 실행되며 캐시가 차감됩니다.">?</button></h2>
|
||
<div id="anBody" class="small"></div>
|
||
</section>
|
||
<section class="card hidden" id="usageCard">
|
||
<h2>캐시 사용 내역 <span class="muted small" id="usageScope"></span> <button type="button" class="ghost small-btn" id="btnUsageDetail">상세 보기</button> <button type="button" class="help" data-tip="작업 단위(생성·수정·검증 등)별 사용 캐시입니다. 작업이 끝날 때 잔액에서 차감되며 중단된 회차(*)는 추정값입니다. 최근 5건이 보이고 표 안에서 스크롤하면 나머지가 보입니다. 상세 보기에서 전체 이용 내역과 일간·주간·월간 사용량을 볼 수 있습니다.">?</button></h2>
|
||
<div class="totals">
|
||
<div class="tot"><span class="k">이 사이트 사용 캐시</span><span class="v" id="tKrw">0원</span></div>
|
||
<div class="tot"><span class="k">잔여 캐시</span><span class="v" id="tBalance">-</span></div>
|
||
</div>
|
||
<div class="table-wrap usage-scroll">
|
||
<table id="usageTable"><thead><tr><th>#</th><th>종류</th><th>지시</th><th>캐시</th><th>시간</th></tr></thead><tbody></tbody></table>
|
||
</div>
|
||
<ul id="creditLedger" class="hidden"></ul>
|
||
</section>
|
||
<!-- v1.3.10: 관리자 빌더 전용 — 이 사이트를 템플릿으로 등록 -->
|
||
<section class="card hidden" id="tplRegisterCard">
|
||
<h2>템플릿으로 등록 <span class="pill small">관리자</span> <button type="button" class="help" data-tip="지금 사이트의 파일을 템플릿으로 담습니다(이후 사이트를 고쳐도 템플릿은 그대로이며, 관리자 콘솔 › 템플릿 에서 '다시 담기' 로 바꿉니다). 사용자에게 보이게 하려면 관리자 콘솔에서 '사용자 사용 허용' 을 켭니다.">?</button></h2>
|
||
<label>템플릿 이름<input id="tplRegTitle" autocomplete="off"></label>
|
||
<div class="two"><label>디렉터리<select id="tplRegDir"></select></label><label>해시태그<input id="tplRegTags" placeholder="#카페 #미니멀" autocomplete="off"></label></div>
|
||
<label>설명<textarea id="tplRegDesc" rows="2"></textarea></label>
|
||
<div class="row"><button type="button" id="tplRegGo" class="primary small-btn">템플릿으로 등록</button><span class="muted small" id="tplRegMsg"></span></div>
|
||
</section>
|
||
<section class="card hidden" id="siteDangerCard">
|
||
<h2>사이트 설정</h2>
|
||
<div class="small muted">사이트 ID <code id="siteId"></code></div>
|
||
<div class="row" style="margin-top:6px"><button type="button" class="ghost small-btn danger hidden" id="btnDeleteSite">사이트 폐기</button><button type="button" class="help" data-tip="사이트 폐기는 배포된 파일·도메인 설정·버전·통계·문의 데이터를 모두 지우며 되돌릴 수 없습니다. 가져온 사이트의 원본 서버 파일은 지우지 않습니다.">?</button></div>
|
||
</section>
|
||
</div>
|
||
|
||
<!-- ===== 도메인(domains, v1.4.0 → 1.6.40 분리): 서브 도메인 등록 / 도메인 검색·구매(장바구니) / 이미 가진 도메인 등록 / 사이트에 연결 — public/domains-ui.js ===== -->
|
||
<div class="tabpane hidden" id="pane-domains"><div id="domainsBody"></div></div>
|
||
<!-- ===== DNS(dns, v1.6.40 신설): 도메인별 DNS 레코드·전파·직접 관리 도메인의 필요한 설정 확인 — 배포·메일과 연결되는 중간 단계. public/domains-ui.js (view=dns) ===== -->
|
||
<div class="tabpane hidden" id="pane-dns"><div id="dnsBody"></div></div>
|
||
<!-- ===== 메일(mail, v1.6.40 신설): 도메인별 메일(MX) 자동 설정·상태, 사이트 메일 시스템·웹메일 — public/domains-ui.js (view=mail) ===== -->
|
||
<div class="tabpane hidden" id="pane-mail"><div id="mailBody"></div></div>
|
||
<!-- ===== 캐시·충전(credits, v1.6.40 신설): 잔액·사용 요약, 선불 충전 상품 선택 → 결제 진행(PG 연동 전: 주문 접수만), 내 주문 — public/credits-ui.js ===== -->
|
||
<div class="tabpane hidden" id="pane-credits"><div id="creditsBody"></div></div>
|
||
|
||
<!-- ===== 설정(settings): 계정 ===== -->
|
||
<div class="tabpane hidden" id="pane-settings">
|
||
<section class="card" id="profileCard">
|
||
<h2>계정 정보</h2>
|
||
<label>아이디<input id="pfId" readonly></label>
|
||
<label>이름 (회사명)<input id="pfName" autocomplete="organization"></label>
|
||
<div class="row"><button type="button" id="pfSave" class="primary small-btn">저장</button><span id="pfMsg" class="muted small"></span></div>
|
||
<p class="muted small" id="pfCreditLine"></p>
|
||
</section>
|
||
<section class="card" id="myFeedbackCard">
|
||
<h2>내 문의 내역 <button type="button" class="ghost small-btn" id="btnFeedback2">새 글</button> <button type="button" class="help" data-tip="사용 방법 문의, 불편한 점이나 오류, 바라는 기능을 운영팀에 보냅니다. 올리면 AI 가 내용을 분석해 운영팀에 전달하고, 운영팀 답변이 오면 여기에 표시됩니다.">?</button></h2>
|
||
<ul id="myFeedbackList" class="git-list stat-list"></ul>
|
||
</section>
|
||
<section class="card" id="pwCard">
|
||
<h2>비밀번호 변경</h2>
|
||
<label>현재 비밀번호<input id="pwCur" type="password" autocomplete="current-password"></label>
|
||
<label data-pw-rule="label">새 비밀번호 (6자 이상)<input id="pwNew" type="password" autocomplete="new-password"></label>
|
||
<label>새 비밀번호 확인<input id="pwNew2" type="password" autocomplete="new-password"></label>
|
||
<div class="row"><button type="button" id="pwSave" class="primary small-btn">변경</button><span id="pwMsg" class="muted small"></span></div>
|
||
</section>
|
||
</div>
|
||
|
||
</div>
|
||
</aside>
|
||
|
||
<main class="right">
|
||
<div class="toolbar">
|
||
<span class="url" id="siteUrl">아직 생성된 페이지가 없습니다</span>
|
||
<select id="fileSelect" class="hidden" title="페이지 선택"></select>
|
||
<button id="btnMobile" class="ghost" disabled title="모바일 화면 크기로 미리보기">모바일 미리보기</button>
|
||
<button id="btnReload" class="ghost" disabled>새로고침</button>
|
||
<a id="btnOpen" class="btn ghost disabled" target="_blank" rel="noopener">새 탭에서 열기</a>
|
||
<button id="btnCopy" class="ghost" disabled>URL 복사</button>
|
||
<button id="btnToggleSource" class="ghost" disabled title="우측 화면을 위(미리보기)/아래(소스) 로 분할">소스 보기</button>
|
||
<!-- v1.8.0 직접 편집(시각 편집기): 미리보기 화면에서 글을 바로 고치고 블록을 끌어 옮기고 구성 요소를 놓는다. 사이트와 HTML 페이지가 골라져 있을 때만 켜진다 (public/visual-editor-ui.js) -->
|
||
<button id="btnVisual" class="ghost" disabled aria-pressed="false" title="미리보기 화면에서 글을 바로 고치고 블록을 끌어 옮기는 직접 편집 모드 (AI 캐시를 쓰지 않습니다)">직접 편집</button>
|
||
</div>
|
||
<div class="preview" id="previewArea">
|
||
<!-- v1.8.0 직접 편집 도구 줄: 저장 상태(aria-live) · 실행 취소 · 다시 실행 · 버리고 다시 불러오기 · 저장(Ctrl+S) · 편집 끝내기 -->
|
||
<div id="veBar" class="ve-bar hidden" role="toolbar" aria-label="직접 편집 도구">
|
||
<span class="ve-title">직접 편집</span>
|
||
<span id="veState" class="ve-state clean" aria-live="polite">변경 없음</span>
|
||
<span class="spacer"></span>
|
||
<button type="button" id="veUndo" class="ghost small-btn" disabled title="실행 취소 (Ctrl+Z)" aria-keyshortcuts="Control+Z">실행 취소</button>
|
||
<button type="button" id="veRedo" class="ghost small-btn" disabled title="다시 실행 (Ctrl+Shift+Z)" aria-keyshortcuts="Control+Shift+Z">다시 실행</button>
|
||
<button type="button" id="veDiscard" class="ghost small-btn" disabled title="저장하지 않은 변경을 버리고 저장된 페이지를 다시 불러옵니다">버리고 다시 불러오기</button>
|
||
<button type="button" id="veSave" class="primary small-btn" disabled title="선택한 HTML 파일에 저장하고 버전으로 남깁니다 (Ctrl+S)" aria-keyshortcuts="Control+S">저장 (Ctrl+S)</button>
|
||
<button type="button" id="veClose" class="ghost small-btn" title="직접 편집을 끝내고 미리보기로 돌아갑니다">편집 끝내기</button>
|
||
</div>
|
||
<div id="emptyState" class="empty">
|
||
<div class="empty-inner">
|
||
<h3>미리보기</h3>
|
||
<p>왼쪽 <b>만들기</b>에서 사이트를 만들면 이 영역에 결과가 표시됩니다. 만들어 둔 사이트는 왼쪽 레일의 사이트 선택 상자에서 고르고 <b>수정</b>에서 고칩니다.</p>
|
||
</div>
|
||
</div>
|
||
<!-- v1.4.15 사용자 첫 화면 페이지: 사이트를 고르기 전 오른쪽 창에만 보이는 관리자 지정 페이지 (app.js showWelcome) -->
|
||
<div id="welcomeBox" class="welcome-box hidden"><iframe id="welcomeFrame" class="welcome-frame" title="첫 화면" sandbox="allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox"></iframe></div>
|
||
<!-- v1.8.0 직접 편집 무대: 왼쪽 구성 요소 팔레트 · 가운데 미리보기(캔버스) · 오른쪽 속성 창. 팔레트·속성 창은 캔버스를 가리지 않고 옆(좁은 화면에서는 아래)에 놓이며 접을 수 있다 -->
|
||
<div class="ve-stage" id="veStage">
|
||
<aside id="vePalette" class="ve-side ve-palette hidden" role="region" aria-label="구성 요소 팔레트">
|
||
<div class="ve-side-head"><button type="button" id="vePaletteToggle" class="ve-toggle" aria-expanded="true" aria-controls="vePaletteList" title="팔레트 접기/펼치기">▾</button><b>구성 요소</b> <button type="button" class="help" data-tip="항목을 미리보기로 끌어다 놓으면 그 자리에 들어갑니다. 마우스를 쓰기 어려우면 '추가' 버튼으로 선택한 요소 뒤(선택이 없으면 페이지 끝)에 넣을 수 있습니다.">?</button></div>
|
||
<ul id="vePaletteList" class="ve-palette-list" aria-label="구성 요소 목록"></ul>
|
||
</aside>
|
||
<div class="frame-wrap" id="frameWrap"><iframe id="frame" class="hidden" title="생성된 페이지 미리보기" sandbox="allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-modals allow-downloads"></iframe><!-- v1.3.17 (S02): 미리보기는 별도 출처(sandbox, allow-same-origin 없음) — 사이트 스크립트가 빌더 세션·저장소를 쓰지 못한다. v1.8.0 직접 편집 캔버스도 같은 iframe(srcdoc)을 쓴다 --></div>
|
||
<aside id="veInspector" class="ve-side ve-inspector hidden" role="region" aria-label="선택한 요소 속성">
|
||
<div class="ve-side-head"><button type="button" id="veInspectorToggle" class="ve-toggle" aria-expanded="true" aria-controls="veInspectorBody" title="속성 창 접기/펼치기">▾</button><b>선택한 요소</b></div>
|
||
<div id="veInspectorBody" class="ve-inspector-body"></div>
|
||
</aside>
|
||
</div>
|
||
<div id="splitter" class="splitter hidden" title="드래그하여 크기 조절"></div>
|
||
<div id="editorPane" class="editor hidden">
|
||
<div class="editor-bar">
|
||
<select id="editFile" title="편집할 파일"></select>
|
||
<span id="editState" class="edit-state">저장됨</span>
|
||
<span class="spacer"></span>
|
||
<label class="inline"><input type="checkbox" id="liveApply" checked> 편집 즉시 미리보기 반영</label>
|
||
<button id="btnRevert" class="ghost small-btn">되돌리기</button>
|
||
<button id="btnSave" class="primary small-btn">파일에 저장 (Ctrl+S)</button>
|
||
</div>
|
||
<div class="editor-body">
|
||
<pre id="lineNos" class="line-nos" aria-hidden="true"></pre>
|
||
<textarea id="editor" spellcheck="false" wrap="off"></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- ===== v1.4.14 (요구 2) 관리 탭의 오른쪽 창: 미리보기 대신 "사이트 관리 창" =====
|
||
위: 사이트 관리자 페이지(회원·게시판·문의·예약 등 모듈 데이터 관리, /site-admin/<ID>/?embed=1) 와 현황 보기 전환
|
||
아래: 관리자 페이지 iframe 또는 현황 대시보드(접속·저장 공간·문의·모듈·메일·배포 상태). 그리기는 public/manage-ui.js -->
|
||
<div class="manage-view hidden" id="manageView">
|
||
<div class="toolbar mv-bar">
|
||
<span class="url" id="mvTitle">사이트 관리</span>
|
||
<button type="button" id="mvTabAdmin" class="ghost active" title="회원·게시판·문의·예약 등 모듈 데이터를 관리하는 사이트 관리자 페이지">사이트 관리자</button>
|
||
<button type="button" id="mvTabStatus" class="ghost" title="사이트 상태·접속 통계 그래프·네트워크 송수신 그래프·디스크 사용량 (v1.7.2)">사이트 정보</button>
|
||
<button type="button" id="mvReload" class="ghost" disabled>새로고침</button>
|
||
<a id="mvOpen" class="btn ghost disabled" target="_blank" rel="noopener">새 탭에서 열기</a>
|
||
</div>
|
||
<div class="mv-body">
|
||
<div id="mvEmpty" class="empty"><div class="empty-inner"><h3>사이트 관리</h3><p>왼쪽 레일의 사이트 선택 상자에서 사이트를 고르면 여기에 <b>사이트 관리자 페이지</b>와 <b>사이트 정보</b>(통계·네트워크·디스크 그래프)가 표시됩니다.</p></div></div>
|
||
<iframe id="mvAdminFrame" class="hidden" title="사이트 관리자 페이지"></iframe>
|
||
<div id="mvStatus" class="mv-status hidden"></div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
</div>
|
||
<div id="dropOverlay" class="drop-overlay hidden"><div class="drop-overlay-box" id="dropOverlayText">여기에 파일을 놓으세요</div></div>
|
||
<dialog id="fbDialog" class="wm-dialog"><form method="dialog"><h2>문의 · 제안 · 오류</h2>
|
||
<label>종류<select id="fbType"><option value="inquiry">사용 문의</option><option value="suggestion">개선 제안</option><option value="bug">오류 보고</option><option value="request">요구 사항</option></select></label>
|
||
<label>제목<input id="fbTitle" maxlength="120" placeholder="한 줄 요약"></label>
|
||
<label>내용 <span class="muted small">(무엇을 하려 했고, 무엇이 기대와 달랐는지)</span><textarea id="fbBody" rows="6" maxlength="5000"></textarea></label>
|
||
<p class="muted small" id="fbContext"></p>
|
||
<div class="fb-env-note small">보낼 때 문제 해결을 위해 <b>사용 환경 정보</b>가 함께 전송됩니다: 브라우저·운영체제, 화면 해상도와 창 크기, 화면 배율, 언어, 시간대, 서비스 버전, 현재 탭과 사이트 상태. 비밀번호나 입력 내용은 보내지 않습니다. <button type="button" class="ghost small-btn" id="fbEnvToggle">보낼 정보 보기</button><pre class="hidden" id="fbEnvPreview"></pre></div>
|
||
<div class="row"><button type="button" class="primary small-btn" id="fbSend">보내기</button><button type="button" class="ghost small-btn" id="fbCancel">취소</button><span class="muted small" id="fbMsg"></span></div>
|
||
</form></dialog>
|
||
<dialog id="usageDialog" class="wm-dialog wide"><form method="dialog"><h2>캐시 상세 내역</h2><div id="usageDialogBody"></div><div class="row"><button type="button" class="ghost small-btn" id="usageDialogClose">닫기</button></div></form></dialog>
|
||
<dialog id="domDialog" class="wm-dialog"><form method="dialog"><h2 id="domDialogTitle">도메인</h2><div id="domDialogBody"></div></form></dialog>
|
||
<div id="helpTip" class="help-tip hidden" role="tooltip"></div>
|
||
<dialog id="detailDialog" class="wm-dialog wide"><form method="dialog"><h2 id="ddTitle2">작업 상세 내역</h2><div id="ddBody2"></div><div class="row"><button type="button" class="ghost small-btn" id="ddClose2">닫기</button></div></form></dialog>
|
||
<script src="/numfmt.js"></script><!-- v1.4.5 숫자 칸 천 단위 쉼표 -->
|
||
<script src="/i18n.js"></script>
|
||
<script src="/pwrule.js"></script>
|
||
<script src="/app.js"></script>
|
||
<script src="/wizard.js"></script>
|
||
<script src="/import.js"></script>
|
||
<script src="/modules-ui.js"></script>
|
||
<script src="/optimize.js"></script>
|
||
<script src="/templates-ui.js"></script>
|
||
<script src="/domains-ui.js"></script>
|
||
<script src="/manage-ui.js"></script><!-- v1.4.14 관리 탭 오른쪽 사이트 관리 창 -->
|
||
<script src="/flow-ui.js"></script><!-- v1.6.40 홈(작업 흐름 지도)·레일 상태 배지·배포 점검표 -->
|
||
<script src="/credits-ui.js"></script><!-- v1.6.40 캐시·충전 화면(선불 충전 상품·주문) -->
|
||
<script src="/site-info.js"></script><!-- v1.7.2 오른쪽 캔버스 사이트 정보 페이지(그래프) -->
|
||
<script src="/visual-editor-core.js"></script><!-- v1.8.0 직접 편집 공용 핵심(실행 취소·저장 상태·메시지 규약·구성 요소) -->
|
||
<script src="/visual-editor-ui.js"></script><!-- v1.8.0 직접 편집 빌더 쪽 제어(팔레트·속성 창·저장) -->
|
||
</body>
|
||
</html>
|