Files
exAichatbot_agent/chatbotApp-chatbot2.0-agent/sample/index.html
T
Macbook 4b86b2a660 Agent 2.0 exdev 서버 배포 스택
- server-dev start/stop/deploy 및 Gitea push 자동 배포
- local-dev 로컬 개발 환경

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-21 22:57:30 +09:00

245 lines
9.3 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>국민참여로 - 국민과 함께, 열린 도로, 열린 소통</title>
<meta name="description" content="한국도로공사 국민참여로 샘플 — AI 검색 배너 iframe 연동" />
<link rel="stylesheet" href="/chatbot/sample/css/partcptn-sample.css" />
</head>
<body>
<div class="partcptn-page">
<header class="partcptn-header">
<div class="partcptn-logo" aria-label="ex 국민참여로">
<span class="partcptn-logo-ex">ex</span>
<span class="partcptn-logo-text">국민참여로</span>
</div>
<button type="button" class="partcptn-menu-btn" aria-label="전체메뉴">
<span class="partcptn-menu-icon" aria-hidden="true">
<span></span><span></span><span></span>
</span>
전체메뉴
</button>
</header>
<main class="partcptn-hero">
<div class="partcptn-hero-bg" aria-hidden="true"></div>
<div class="partcptn-hero-content">
<h1 class="partcptn-hero-title">국민과 함께, 열린 도로, 열린 소통</h1>
<p class="partcptn-hero-sub">
국민의 작은 목소리도 정책의 시작이 됩니다.<br />
소통하고, 함께 만들어가는 스마트 국민 소통 플랫폼
</p>
<div class="partcptn-search-slot" id="partcptn-search-slot">
<iframe
id="chatbot-banner-frame"
src="/chatbot/banner/?embed=1&theme=partcptn&minwonUrl=%2Fchatbot%2Fsample%2Fminwon%2F&placeholder=%EA%B2%80%EC%83%89%EC%96%B4%EB%A5%BC%20%EC%9E%85%EB%A0%A5%ED%95%B4%20%EC%A3%BC%EC%84%B8%EC%9A%94"
title="AI 검색"
loading="lazy"
allowtransparency="true"
style="height: 48px"
></iframe>
</div>
</div>
</main>
<nav class="partcptn-bottom-dock" aria-label="챗봇 바로가기">
<button
type="button"
class="partcptn-dock-item"
data-chatbot-url="/chatbot/app/"
data-chatbot-title="카톡챗봇"
>
<span class="partcptn-dock-icon" aria-hidden="true">
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M14 10h20a4 4 0 0 1 4 4v10a4 4 0 0 1-4 4H20l-6 4v-4h-4a4 4 0 0 1-4-4V14a4 4 0 0 1 4-4z"
stroke="currentColor"
stroke-width="1.6"
stroke-linejoin="round"
/>
<circle cx="18" cy="19" r="1.2" fill="currentColor" />
<circle cx="24" cy="19" r="1.2" fill="currentColor" />
<circle cx="30" cy="19" r="1.2" fill="currentColor" />
</svg>
</span>
<span class="partcptn-dock-label">카톡챗봇</span>
</button>
<button
type="button"
class="partcptn-dock-item"
data-chatbot-url="/chatbot/ai/"
data-chatbot-title="AI챗봇"
>
<span class="partcptn-dock-icon" aria-hidden="true">
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="12" y="14" width="24" height="20" rx="3" stroke="currentColor" stroke-width="1.6" />
<path d="M20 22h8M20 26h5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
<path d="M18 10h12" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
<circle cx="18" cy="10" r="1.5" fill="currentColor" />
<circle cx="30" cy="10" r="1.5" fill="currentColor" />
<path d="M16 38h16" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
</svg>
</span>
<span class="partcptn-dock-label">AI챗봇</span>
</button>
<button
type="button"
class="partcptn-dock-item"
data-chatbot-url="/chatbot/voicebot/"
data-chatbot-title="음성챗봇"
>
<span class="partcptn-dock-icon" aria-hidden="true">
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="20" y="12" width="8" height="14" rx="4" stroke="currentColor" stroke-width="1.6" />
<path
d="M16 24a8 8 0 0 0 16 0"
stroke="currentColor"
stroke-width="1.6"
stroke-linecap="round"
/>
<path d="M24 32v4" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
<path d="M20 36h8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" />
</svg>
</span>
<span class="partcptn-dock-label">음성챗봇</span>
</button>
</nav>
</div>
<div
id="sample-chat-overlay"
class="sample-chat-overlay"
role="dialog"
aria-modal="true"
aria-hidden="true"
aria-label="챗봇"
>
<div class="sample-chat-panel">
<iframe
id="sample-chat-frame"
title="챗봇"
src="about:blank"
allow="microphone *; autoplay *"
></iframe>
</div>
</div>
<script>
(function () {
var iframe = document.getElementById("chatbot-banner-frame");
var searchSlot = document.getElementById("partcptn-search-slot");
var page = document.querySelector(".partcptn-page");
if (iframe) {
var minH = 48;
function maxH() {
return Math.min(Math.round(window.innerHeight * 0.72), 640);
}
window.addEventListener("message", function (ev) {
if (!ev.data || ev.data.type !== "ex-chatbot-banner-resize") return;
if (ev.source !== iframe.contentWindow) return;
var h = Number(ev.data.height);
if (h > 0) {
var next = Math.min(Math.max(h, minH), maxH());
iframe.style.height = next + "px";
var expanded = next > minH + 8;
if (searchSlot) {
searchSlot.classList.toggle("is-expanded", expanded);
}
if (page) {
page.classList.toggle("partcptn-page--search-open", expanded);
}
}
});
}
var overlay = document.getElementById("sample-chat-overlay");
var chatFrame = document.getElementById("sample-chat-frame");
function withEmbed(url) {
if (!url) return url;
return url + (url.indexOf("?") >= 0 ? "&" : "?") + "embed=1";
}
function openChatbot(url, title) {
if (!overlay || !chatFrame) return;
var isVoicebot = url.indexOf("/voicebot") !== -1;
var frameUrl = withEmbed(url);
function showFrame() {
chatFrame.src = frameUrl;
chatFrame.title = title || "챗봇";
overlay.classList.add("is-open");
overlay.setAttribute("aria-hidden", "false");
document.body.style.overflow = "hidden";
if (isVoicebot) {
chatFrame.onload = function () {
try {
chatFrame.contentWindow.postMessage(
{ type: "ex-voicebot-autostart" },
window.location.origin
);
} catch (_) {}
};
} else {
chatFrame.onload = null;
}
}
if (isVoicebot && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices
.getUserMedia({ audio: true, video: false })
.then(function (stream) {
stream.getTracks().forEach(function (track) {
track.stop();
});
showFrame();
})
.catch(function () {
showFrame();
});
return;
}
showFrame();
}
function closeChatbot() {
if (!overlay || !chatFrame) return;
overlay.classList.remove("is-open");
overlay.setAttribute("aria-hidden", "true");
chatFrame.src = "about:blank";
document.body.style.overflow = "";
}
document.querySelectorAll("[data-chatbot-url]").forEach(function (btn) {
btn.addEventListener("click", function () {
openChatbot(btn.getAttribute("data-chatbot-url"), btn.getAttribute("data-chatbot-title"));
});
});
window.addEventListener("message", function (ev) {
if (!ev.data || ev.data.type !== "ex-chatbot-close") return;
if (chatFrame && ev.source === chatFrame.contentWindow) {
closeChatbot();
}
});
if (overlay) {
overlay.addEventListener("click", function (e) {
if (e.target === overlay) closeChatbot();
});
}
document.addEventListener("keydown", function (e) {
if (e.key === "Escape" && overlay && overlay.classList.contains("is-open")) {
closeChatbot();
}
});
})();
</script>
</body>
</html>