Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions public/ai_rag.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<!doctype html><!-- RAG기능때문에 신규로 추가한 AI검색 창 파일 -->
<head>
<meta http-equiv="Content-Type" content="text/html" charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>스프링 부트 웹 서버</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/app/bgimg.css">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
</head>
<body>
<div class="container">

<style>
.d-none{display:inline-block!important}
.d-none{display:none!important}
.spin-svg {
animation: rotateAnimation 2s linear infinite;
transform-origin: center; /* 회전 기준점을 SVG의 정중앙으로 설정 */
}
@keyframes rotateAnimation {
0% {
transform: rotate(360deg);
}
100% {
transform: rotate(0deg);
}
}
</style>
<div class="px-2 py-2">
<h4 class="font-bold text-center">Egov심플홈페이지 프런트엔드/서버엔드<br>무엇이든 물어보세요(RAG-검색증강생성AI)</h4>
<!-- 입력 폼 -->
<form id="chat-form" class="d-flex">
<input type="text" id="chat-input" class="flex-grow-1 border rounded p-2" placeholder="질문 입력..." required>
<button type="submit" class="px-2 py-2 rounded">보내기</button>
<svg id="loading-image" class="spin-svg d-none" width="40px" height="40px" style="vertical-align: middle;" enable-background="new 0 0 561 561" version="1.1" viewBox="0 0 561 561" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<path d="m280.5 76.5v-76.5l-102 102 102 102v-76.5c84.15 0 153 68.85 153 153 0 25.5-7.65 51-17.85 71.4l38.25 38.25c17.85-33.15 30.6-68.85 30.6-109.65 0-112.2-91.8-204-204-204zm0 357c-84.15 0-153-68.85-153-153 0-25.5 7.65-51 17.85-71.4l-38.25-38.25c-17.85 33.15-30.6 68.85-30.6 109.65 0 112.2 91.8 204 204 204v76.5l102-102-102-102v76.5z" fill="#006DF0"/>
</svg>
</form>
<!-- 채팅 박스 -->
<div id="chat-box" class="bg-light border rounded p-3" style="height:70vh;overflow:auto;">
<!-- 메시지 출력됨 -->
<span class="text-muted" style="font-size:small;">
질문을 입력하면 검색증강생성-AI가 아래 문서들을 참고하여 답변을 생성합니다.<br>
"https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-react/refs/heads/main/README.md"; // 프런트엔드소개<br>
"https://raw.githubusercontent.com/eGovFramework/egovframe-template-simple-backend/refs/heads/main/README.md"; // 백엔드소개<br>
AI 답변에 오류가 있을 수 있습니다. 중요한 문제는 답변이 정확한지 유선으로 확인하시기 바랍니다.
</span>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
const form = document.getElementById("chat-form");
const input = document.getElementById("chat-input");
const chatBox = document.getElementById("chat-box");
form.addEventListener("submit", async (e) => {
e.preventDefault();
const userMsg = input.value.trim();
if (!userMsg) return;
appendMessage("나", userMsg);
input.value = "";
const loading = document.querySelector("#loading-image");
loading.classList.remove("d-none");
try {
const res = await fetch("http://localhost:8080/api/gemini/rag_chat?prompt=" + encodeURIComponent(userMsg), {
method: "GET",
headers: {
"Content-Type": "application/json"
}
});
const data = await res.text();
if(data.length > 0){
loading.classList.add("d-none");
}
appendMessage("Gemini", marked.parse(data));
} catch (err) {
loading.classList.add("d-none");
console.error("Error:", err);
appendMessage("Gemini", "죄송합니다. 답변을 가져오는 중 오류가 발생했습니다.");
}
});
function appendMessage(sender, message) {
const div = document.createElement("div");
div.innerHTML = `<strong>${sender}:</strong> <div class="whitespace-pre-line">${message}</div>`;
chatBox.prepend(div);//chatBox.appendChild(div);
chatBox.scrollTop = chatBox.scrollHeight;
}
</script>

</div>
</body>
</html>
29 changes: 29 additions & 0 deletions src/components/EgovFloatingButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import "../css/floatingButton.css";

function EgovFloatingButton() {
let aiWindow;
const openAiWindow = () => {
if (!aiWindow || aiWindow.closed) {
let url = "/ai_rag.html";
// 모니터 가로 해상도 - 팝업창 가로 크기 = 오른쪽에 붙는 X 좌표
var leftPos = window.screen.width - 600;
leftPos += window.screenLeft; // 듀얼 모니터일 때
var topPos = 0; // 화면 상단에 붙임
const options = "width=600,height=700,left="+leftPos+",top="+topPos+",scrollbars=yes,resizable=yes";
// 새 창 열기
aiWindow = window.open(url, "aiWindow", options);
}else{
// 이미 열려있다면 기존 창을 활성화(포커스)
aiWindow.focus();
}
};

return (
<div className="floating-container">
<div className="floating-button" onClick={openAiWindow}>
AI
</div>
</div>
);
}
export default EgovFloatingButton;
24 changes: 24 additions & 0 deletions src/css/floatingButton.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@charset "UTF-8";
/* 플로딩 메뉴 디자인 과 소스 */
.floating-container {
position: fixed;
bottom: 30px;
right: 30px;
z-index: 9999;
display: flex;
flex-direction: column;
align-items: center;
}
.floating-button {
width: 60px;
height: 60px;
background-color: #007bff;
color: white;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
cursor: pointer;
box-shadow: 0 4px 6px rgba(0,0,0,0.2);
}
3 changes: 3 additions & 0 deletions src/routes/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { useAuth } from "@/contexts/AuthContext";
import EgovHeader from "@/components/EgovHeader";
import EgovFooter from "@/components/EgovFooter";
import EgovInfoPopup from "@/components/EgovInfoPopup";
//AI-RAG 페이지 호출 버튼 추가 2026.06.18(목) 김일국 추가
import EgovFloatingButton from "@/components/EgovFloatingButton";
import EgovError from "@/components/EgovError";

import EgovMain from "@/pages/main/EgovMain";
Expand Down Expand Up @@ -378,6 +380,7 @@ const SecondRoutes = () => {

<EgovFooter />
<EgovInfoPopup />
<EgovFloatingButton /> {/* AI-RAG 페이지 호출 버튼 추가 2026.06.18(목) 김일국 추가 */}
</>
);
};
Expand Down
Loading