Files
hsa/Html/apps/static/js/chatbox.js
2025-09-14 15:30:05 +08:00

270 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var socket;
let system_message_idx=0
document.addEventListener('DOMContentLoaded', function() {
data = window.appData;
console.log(data);
socket = io('wss://hsamooc.cn/agent',{
query:{
user_uuid:data.user_uuid,
folder:data.folder
}
});
socket.on('connect', function() {
console.log('Connected to server');
socket.emit('login',JSON.stringify(data));
});
// 监听来自服务器的消息
socket.on('message', function(data) {
// 显示服务器的回复消息
const serverMessage = document.createElement('div');
serverMessage.innerHTML = `<div class="chat-message server-message"><b>华实君:</b> ${marked.parse(data)}</div>`;
document.getElementById('chatbox').appendChild(serverMessage);
// 滚动到最新消息
document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
});
socket.on('request_function', function(data){
try {
console.log("request_function", data);
if (typeof data === 'string') {
data = JSON.parse(data);
}
if (typeof data === 'object') {
data = [data];
}
for (let i = 0; i < data.length; i++) {
const element = data[i];
// 外层消息气泡
const requestMessage = document.createElement('div');
requestMessage.className = 'chat-message server-message';
// 左边描述部分
const description = document.createElement('div');
description.innerHTML = `<b>Function:</b> ${element.name}(${JSON.stringify(element.arguments)})`;
// 右边批准按钮
const approveButton = document.createElement('button');
approveButton.innerHTML = '√'; // 使用勾选符号
approveButton.data = element;
approveButton.className = 'approve-button';
approveButton.onclick = function(event) {
console.log(element);
socket.emit('message', JSON.stringify({ type: 'function', data: element }));
event.currentTarget.disabled = true;
event.currentTarget.classList.add('disabled');
};
// 把描述和按钮加到 requestMessage
requestMessage.appendChild(description);
requestMessage.appendChild(approveButton);
document.getElementById('chatbox').appendChild(requestMessage);
document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
}
} catch (error) {
console.log(error)
}
});
socket.on('next_chapter', function(data){
next_chapter(data);
});
socket.on('chapter_score',function(data){
if (typeof data === 'string'){
data = JSON.parse(data);
}
console.log(data)
const scoreMessage = document.createElement('div');
scoreMessage.className = 'chat-message server-message';
scoreMessage.innerHTML = `<b>Chapter ${data.chapter_id} Score:</b> ${JSON.stringify(data.data.content.speak)}`;
document.getElementById('chatbox').appendChild(scoreMessage);
document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
})
socket.on('system_message',function(data){
console.log(data)
let systemMessage = document.createElement('div');
systemMessage.className = 'chat-message server-message';
let closeButton = document.createElement('button');
closeButton.className = 'close-button'; // 可以根据需要添加样式类
closeButton.innerHTML = '×'; // 关闭按钮的文本内容
closeButton.style.marginRight = '10px'; // 可选:设置关闭按钮的右边距
systemMessage.appendChild(closeButton);
systemMessage.innerHTML += `<b>系统提示: </b> ${data}`;
systemMessage.id = 'system_message_'+system_message_idx;
system_message_idx+=1
document.getElementById('chatbox').appendChild(systemMessage);
document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
$('.close-button').on('click', function(event) {
$(this).css({
'background-color': 'gray',
'color': 'white', // 可选:设置文字颜色为白色,以便更清晰地显示
'border': 'none' // 可选:去掉边框
});
$(this).parent().remove();
});
setTimeout(function() {
$(systemMessage.id).remove();
}, 5000); // 5000 毫秒 = 5 秒
})
});
// 控制文字大小的滑块
const fontSizeSlider = document.getElementById('fontSizeSlider');
const chatbox = document.getElementById('chatbox');
fontSizeSlider.addEventListener('input', function() {
console.log(fontSizeSlider.value);
chatbox.style.fontSize = fontSizeSlider.value + 'px';
});
// 语言切换按钮
const englishRadio = document.getElementById('english');
const chineseRadio = document.getElementById('chinese');
const englishLabel = document.getElementById('label_for_en');
const chineseLabel = document.getElementById('label_for_zh');
let language = 'zh'; // 默认语言
// 切换语言事件
englishRadio.addEventListener('change', function() {
if (englishRadio.checked) {
language = 'en';
englishLabel.classList.add('active');
chineseLabel.classList.remove('active');
}
socket.emit('language',language);
});
chineseRadio.addEventListener('change', function() {
if (chineseRadio.checked) {
language = 'zh';
chineseLabel.classList.add('active');
englishLabel.classList.remove('active');
}
socket.emit('language',language);
});
function sendInitiativeFunctionCall(function_name){
socket.emit('initiative', {'name': function_name});
}
// 发送消息
function sendMessage() {
const input = document.getElementById('messageInput').value;
if (input.trim() === '') return;
// 使用 marked.js 解析 markdown
const markdownHtml = marked.parse(input);
// 显示用户发送的消息
const userMessage = document.createElement('div');
userMessage.innerHTML = `<div class="chat-message user-message"><b>你:</b> ${markdownHtml}</div>`;
document.getElementById('chatbox').appendChild(userMessage);
// 发送消息到服务器
socket.emit('message', JSON.stringify({data: input, type:'text'}));
// 清空输入框
document.getElementById('messageInput').value = '';
// 滚动到最新消息
document.getElementById('chatbox').scrollTop = document.getElementById('chatbox').scrollHeight;
}
let currentChapterIndex = -1;
function next_chapter(data) {
// 获取所有的 h3 元素
var iframe = document.getElementById('markdown-content-iframe');
// 访问 iframe 的文档对象
var iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
var titles = []
var h3Elements = iframeDocument.querySelectorAll('h3');
console.log("h3Elements next")
if (currentChapterIndex >= h3Elements.length) {
return; // 如果已经到了最后一个章节,则不进行任何操作
}
// 隐藏当前章节及其后的内容
for (let i = 0; i < h3Elements.length; i++) {
h3Elements[i].style.display = 'none';
titles.push(h3Elements[i].innerText)
let nextSibling = h3Elements[i].nextElementSibling;
while (nextSibling && nextSibling.tagName !== 'H3') {
nextSibling.style.display = 'none';
nextSibling = nextSibling.nextElementSibling;
}
}
// 显示下一个章节及其后的内容直到再下一个h3元素或结束
if (currentChapterIndex + 1 < h3Elements.length) {
h3Elements[currentChapterIndex + 1].style.display = 'block';
let nextSibling = h3Elements[currentChapterIndex + 1].nextElementSibling;
while (nextSibling && nextSibling.tagName !== 'H3') {
nextSibling.style.display = 'block';
nextSibling = nextSibling.nextElementSibling;
}
}
currentChapterIndex++;
generateProgressBar(h3Elements.length, currentChapterIndex, titles);
}
function generateProgressBar(N, idx, titles) {
const container = document.getElementById('markdown-content-process');
container.innerHTML = ''; // 清空内容
// 创建进度条的外框
const progressBox = document.createElement('div');
progressBox.className = 'progress-box';
// 获取详细信息容器
const detailBox = document.getElementById('progress-detail');
// 根据N值动态调整每个进度节点的宽度
const nodeWidth = 100 / N; // 每个节点的宽度为 100% / N
// 根据N值生成子框并设置颜色
for (let i = 0; i < N; i++) {
const titleBox = document.createElement('div');
titleBox.className = 'progress-title';
// 设置进度条的颜色
if (i < idx) {
titleBox.classList.add('green'); // 已完成部分
} else {
titleBox.classList.add('white'); // 未完成部分
}
// 设置每个子框的标题
titleBox.innerHTML = titles[i] || `Step ${i + 1}`;
// 设置每个进度节点的宽度
titleBox.style.width = `${nodeWidth}%`;
// 监听鼠标移入事件来显示详情
titleBox.addEventListener('mouseenter', function() {
detailBox.innerHTML = `Step ${i + 1}: ${titles[i] || "No title"}`;// - Additional details here...`;
detailBox.style.display = 'block';
// 根据进度条位置显示详情
const rect = titleBox.getBoundingClientRect();
detailBox.style.top = `${rect.top + window.scrollY - 100}px`; // 微调位置
detailBox.style.left = `${rect.left + window.scrollX + rect.width / 2 - detailBox.offsetWidth / 2}px`;
});
// 监听鼠标移出事件来隐藏详情
titleBox.addEventListener('mouseleave', function() {
detailBox.style.display = 'none';
});
progressBox.appendChild(titleBox);
}
// 将生成的进度条添加到容器中
container.appendChild(progressBox);
}