let reader;
let currentStreamId;
function execDocReady() {
const pluginGroups = [
[
"../reference/lightblue4/docs/lib/widgster/widgster.js",
"../reference/lightblue4/docs/lib/slimScroll/jquery.slimscroll.min.js",
"./js/common/showdown/showdown.js",
"../reference/jquery-plugins/timerStyles.js"
]
];
loadPluginGroupsParallelAndSequential(pluginGroups)
.then(function () {
console.log("모든 플러그인 로드 완료");
//coming soon
$("#count-down").TimeCircles({
circle_bg_color: "#f8f8f8",
use_background: true,
bg_width: 0.2,
fg_width: 0.013,
time: {
Days: { color: "#f8f8f8" },
Hours: { color: "#f8f8f8" },
Minutes: { color: "#f8f8f8" },
Seconds: { color: "#f8f8f8" }
}
});
$("#chat").slimScroll({
height: "574px",
railVisible: true,
railColor: "#222",
railOpacity: 0.3,
wheelStep: 10,
allowPageScroll: false,
disableFadeOut: false
});
$(".widget").widgster();
setSideMenu("sidebar_large_menu_ai", "sidebar_medium_menu_ai_adms", "sidebar_small_menu_ai_ai_chat");
setSideMenu("toggle_large_menu_ai", "toggle_medium_menu_ai_dashboard");
initSendMessageEvent();
})
.catch(function () {
console.error("플러그인 로드 중 오류 발생");
});
$("#message-stop-btn").click(function () {
cancel();
});
}
function cancel() {
if (reader && currentStreamId) {
fetch(`/ai-api/ai/stopStream?streamId=${currentStreamId}`)
.then((response) => {
if (!response.ok) {
console.error("스트림 중단 요청 실패:", response.status);
} else {
console.log("스트림 중단 요청 성공:", currentStreamId);
}
})
.catch((error) => {
console.error("스트림 중단 요청 중 오류:", error);
});
reader.cancel();
currentStreamId = null; // 중단 후 ID 초기화
}
}
function initSendMessageEvent() {
// 전송 버튼 클릭 시
$("#message-send-btn").on("click", function () {
sendMessage();
});
// 엔터 키 눌렀을 때도 전송
$("#new_message").on("keyup", function (e) {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault(); // 줄바꿈 방지
sendMessage();
}
});
}
// 사용자 메시지 처리 함수 따로 빼기
function sendMessage() {
const messageText = $("#new_message").val().trim();
if (messageText === "") return;
// 사용자 메시지 UI 추가
const userMessage = $(`
${$("
").text(messageText).html()}
`);
$("#chat").append(userMessage);
// 입력창 초기화 + 스크롤 하단 이동
$("#new_message").val("");
$("#chat").scrollTop($("#chat")[0].scrollHeight);
sendChat(messageText); // AI 응답
}
// showdown.js 인스턴스 생성
const converter = new showdown.Converter();
function sendChat(userInput) {
cancel(); // 이전 요청 중단
const sendBtn = $("#message-send-btn");
const stopBtn = $("#message-stop-btn");
// 버튼 상태: 전송 숨기고, 멈춤 보이기
sendBtn.hide();
stopBtn.show();
const aiMessage = $(`
`);
$("#chat").append(aiMessage);
$("#chat").scrollTop($("#chat")[0].scrollHeight);
// 새로운 streamId 생성
currentStreamId = generateStreamId();
const params = new URLSearchParams({ message: userInput, streamId: currentStreamId }).toString();
const converter = new showdown.Converter();
fetch(`/ai-api/ai/generateStream?${params}`).then((res) => {
console.log(res);
aiMessage.find(".loading-gif").remove();
let accumulatedText = "";
if (res.status != 200) {
aiMessage.find(".text").append("지금은 답변을 드릴 수가 없습니다.");
stopBtn.hide();
sendBtn.show();
return;
}
reader = res.body.pipeThrough(new TextDecoderStream()).getReader();
// 멈춤 버튼 클릭 시: cancel() + 버튼 상태 복구
stopBtn.off("click").on("click", () => {
cancel();
stopBtn.hide();
sendBtn.show();
});
// 스트리밍 읽기
function processStream({ done, value }) {
if (done) {
console.log("done");
stopBtn.hide(); // 멈춤 버튼 숨김
sendBtn.show(); // 전송 버튼 다시 보이기
currentStreamId = null; // 스트림 종료 시 ID 초기화
return;
}
// 누적된 텍스트에 스트리밍된 데이터 추가
accumulatedText += value;
// 줄 단위로 Markdown 변환
const lines = accumulatedText.split("\n");
let formattedText = lines;
if (lines.length > 1) {
formattedText = lines
.map((line) => {
let index = line.indexOf(" ");
if (index > -1) {
return " " + converter.makeHtml(line.substring(index));
}
return converter.makeHtml(line);
})
.join("
");
}
aiMessage.find(".text").html(formattedText);
$("#chat").scrollTop($("#chat")[0].scrollHeight);
// 다음 스트리밍 데이터를 계속 처리
reader.read().then(processStream);
}
// 스트리밍 시작
reader.read().then(processStream);
});
}
function generateStreamId() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
var r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}